// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // File : GEOMImpl_IShapesOperations.cxx // Created : // Author : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007 // Project : SALOME #include #include "GEOMImpl_IShapesOperations.hxx" #include "GEOMImpl_Types.hxx" #include "GEOMImpl_VectorDriver.hxx" #include "GEOMImpl_ShapeDriver.hxx" #include "GEOMImpl_CopyDriver.hxx" #include "GEOMImpl_GlueDriver.hxx" #include "GEOMImpl_IVector.hxx" #include "GEOMImpl_IShapes.hxx" #include "GEOMImpl_IGlue.hxx" #include "GEOMImpl_Block6Explorer.hxx" #include "GEOMImpl_IHealingOperations.hxx" #include #include "GEOM_Function.hxx" #include "GEOM_ISubShape.hxx" #include "GEOM_PythonDump.hxx" #include "GEOMAlgo_ClsfBox.hxx" #include "GEOMAlgo_ClsfSolid.hxx" #include "GEOMAlgo_CoupleOfShapes.hxx" #include "GEOMAlgo_FinderShapeOn1.hxx" #include "GEOMAlgo_FinderShapeOnQuad.hxx" #include "GEOMAlgo_FinderShapeOn2.hxx" #include "GEOMAlgo_GetInPlace.hxx" #include "GEOMAlgo_GlueDetector.hxx" #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx" #include "GEOMAlgo_ListOfCoupleOfShapes.hxx" #include #include "utilities.h" #include "OpUtil.hxx" #include "Utils_ExceptHandlers.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC // Includes added for GetInPlace algorithm improvement #include #include #include #include #include #include #define STD_SORT_ALGO 1 //============================================================================= /*! * constructor: */ //============================================================================= GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID) : GEOM_IOperations(theEngine, theDocID) { MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations"); } //============================================================================= /*! * destructor */ //============================================================================= GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations() { MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations"); } //============================================================================= /*! * MakeEdge */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2) { SetErrorCode(KO); if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL; //Add a new Edge object Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE); //Add a new Vector function Handle(GEOM_Function) aFunction = anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT); //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL; GEOMImpl_IVector aPI (aFunction); Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction(); Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction(); if (aRef1.IsNull() || aRef2.IsNull()) return NULL; aPI.SetPoint1(aRef1); aPI.SetPoint2(aRef2); //Compute the Edge value try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Vector driver failed"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge(" << thePnt1 << ", " << thePnt2 << ")"; SetErrorCode(OK); return anEdge; } //============================================================================= /*! * MakeEdgeOnCurveByLength */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeOnCurveByLength (Handle(GEOM_Object) theRefCurve, const Standard_Real theLength, Handle(GEOM_Object) theStartPoint) { SetErrorCode(KO); if (theRefCurve.IsNull()) return NULL; //Add a new Edge object Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE); //Add a new Vector function Handle(GEOM_Function) aFunction = anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_CURVE_LENGTH); //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; GEOMImpl_IVector aPI (aFunction); Handle(GEOM_Function) aRef1 = theRefCurve->GetLastFunction(); if (aRef1.IsNull()) return NULL; aPI.SetPoint1(aRef1); if (!theStartPoint.IsNull()) { Handle(GEOM_Function) aRef2 = theStartPoint->GetLastFunction(); aPI.SetPoint2(aRef2); } aPI.SetParameter(theLength); //Compute the Edge value try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Vector driver failed"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeOnCurveByLength(" << theRefCurve << ", " << theLength << ", " << theStartPoint << ")"; SetErrorCode(OK); return anEdge; } //============================================================================= /*! * MakeEdgeWire */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire (Handle(GEOM_Object) theWire, const Standard_Real theLinearTolerance, const Standard_Real theAngularTolerance) { SetErrorCode(KO); if (theWire.IsNull()) return NULL; //Add a new Edge object Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE); //Add a new Vector function Handle(GEOM_Function) aFunction = anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_WIRE); //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; GEOMImpl_IShapes aCI (aFunction); Handle(GEOM_Function) aWire = theWire->GetLastFunction(); if (aWire.IsNull()) return NULL; aCI.SetBase(aWire); aCI.SetTolerance(theLinearTolerance); aCI.SetAngularTolerance(theAngularTolerance); //Compute the Edge value try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } const double DEF_LIN_TOL = Precision::Confusion(); const double DEF_ANG_TOL = Precision::Angular(); //Make a Python command if ( theAngularTolerance == DEF_ANG_TOL ) { if ( theLinearTolerance == DEF_LIN_TOL ) GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire(" << theWire << ")"; else GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire(" << theWire << ", " << theLinearTolerance << ")"; } else { GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire(" << theWire << ", " << theLinearTolerance << ", " << theAngularTolerance << ")"; } SetErrorCode(OK); return anEdge; } //============================================================================= /*! * MakeWire */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire (std::list theShapes, const Standard_Real theTolerance) { SetErrorCode(KO); //Add a new object Handle(GEOM_Object) aWire = GetEngine()->AddObject(GetDocID(), GEOM_WIRE); //Add a new function Handle(GEOM_Function) aFunction = aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES); if (aFunction.IsNull()) return NULL; //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; GEOMImpl_IShapes aCI (aFunction); aCI.SetTolerance(theTolerance); Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; // Shapes std::list::iterator it = theShapes.begin(); for (; it != theShapes.end(); it++) { Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction(); if (aRefSh.IsNull()) { SetErrorCode("NULL argument shape for the shape construction"); return NULL; } aShapesSeq->Append(aRefSh); } aCI.SetShapes(aShapesSeq); //Compute the shape try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command GEOM::TPythonDump pd (aFunction); pd << aWire << " = geompy.MakeWire(["; // Shapes it = theShapes.begin(); if (it != theShapes.end()) { pd << (*it++); while (it != theShapes.end()) { pd << ", " << (*it++); } } pd << "], " << theTolerance << ")"; SetErrorCode(OK); return aWire; } //============================================================================= /*! * MakeFace */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire, const bool isPlanarWanted) { SetErrorCode(KO); if (theWire.IsNull()) return NULL; //Add a new Face object Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE); //Add a new Shape function for creation of a face from a wire Handle(GEOM_Function) aFunction = aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE); if (aFunction.IsNull()) return NULL; //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; GEOMImpl_IShapes aCI (aFunction); Handle(GEOM_Function) aRefWire = theWire->GetLastFunction(); if (aRefWire.IsNull()) return NULL; aCI.SetBase(aRefWire); aCI.SetIsPlanar(isPlanarWanted); //Compute the Face value try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to compute a face"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace(" << theWire << ", " << (int)isPlanarWanted << ")"; SetErrorCode(OK); return aFace; } //============================================================================= /*! * MakeFaceWires */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires (std::list theShapes, const bool isPlanarWanted) { SetErrorCode(KO); //Add a new object Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE); //Add a new function Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES); if (aFunction.IsNull()) return NULL; //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; GEOMImpl_IShapes aCI (aFunction); Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; // Shapes std::list::iterator it = theShapes.begin(); for (; it != theShapes.end(); it++) { Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction(); if (aRefSh.IsNull()) { SetErrorCode("NULL argument shape for the face construction"); return NULL; } aShapesSeq->Append(aRefSh); } aCI.SetShapes(aShapesSeq); aCI.SetIsPlanar(isPlanarWanted); //Compute the shape try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command GEOM::TPythonDump pd (aFunction); pd << aShape << " = geompy.MakeFaceWires(["; // Shapes it = theShapes.begin(); if (it != theShapes.end()) { pd << (*it++); while (it != theShapes.end()) { pd << ", " << (*it++); } } pd << "], " << (int)isPlanarWanted << ")"; SetErrorCode(OK); return aShape; } //============================================================================= /*! * MakeShell */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell (std::list theShapes) { return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell"); } //============================================================================= /*! * MakeSolidShells */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells (std::list theShapes) { return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid"); } //============================================================================= /*! * MakeCompound */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound (std::list theShapes) { return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound"); } //============================================================================= /*! * MakeShape */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape (std::list theShapes, const Standard_Integer theObjectType, const Standard_Integer theFunctionType, const TCollection_AsciiString& theMethodName) { SetErrorCode(KO); //Add a new object Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType); //Add a new function Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType); if (aFunction.IsNull()) return NULL; //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; GEOMImpl_IShapes aCI (aFunction); Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; // Shapes std::list::iterator it = theShapes.begin(); for (; it != theShapes.end(); it++) { Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction(); if (aRefSh.IsNull()) { SetErrorCode("NULL argument shape for the shape construction"); return NULL; } aShapesSeq->Append(aRefSh); } aCI.SetShapes(aShapesSeq); //Compute the shape try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command GEOM::TPythonDump pd (aFunction); pd << aShape << " = geompy." << theMethodName.ToCString() << "(["; // Shapes it = theShapes.begin(); if (it != theShapes.end()) { pd << (*it++); while (it != theShapes.end()) { pd << ", " << (*it++); } } pd << "])"; SetErrorCode(OK); return aShape; } //============================================================================= /*! * MakeGlueFaces */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces (Handle(GEOM_Object) theShape, const Standard_Real theTolerance, const Standard_Boolean doKeepNonSolids) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; //Add a new Glued object Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED); //Add a new Glue function Handle(GEOM_Function) aFunction; aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES); if (aFunction.IsNull()) return NULL; //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL; GEOMImpl_IGlue aCI (aFunction); Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); if (aRefShape.IsNull()) return NULL; aCI.SetBase(aRefShape); aCI.SetTolerance(theTolerance); aCI.SetKeepNonSolids(doKeepNonSolids); //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to glue faces"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); // to provide warning if (!aFunction->GetValue().IsNull()) { isWarning = Standard_True; } else { return NULL; } } //Make a Python command GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces(" << theShape << ", " << theTolerance << ")"; // to provide warning if (!isWarning) SetErrorCode(OK); return aGlued; } //============================================================================= /*! * GetGlueFaces */ //============================================================================= /* Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces (Handle(GEOM_Object) theShape, const Standard_Real theTolerance) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); if (aShape.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; Standard_Integer iErr; TopoDS_Shape aS; GEOMAlgo_Gluer1 aGluer; GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS; GEOMAlgo_CoupleOfShapes aCS; GEOMAlgo_ListOfCoupleOfShapes aLCS; //aGluer = new GEOMAlgo_Gluer1; aGluer.SetShape(aShape); aGluer.SetTolerance(theTolerance); aGluer.Perform(); iErr = aGluer.ErrorStatus(); if (iErr) return NULL; TopTools_ListOfShape listShape; const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces(); // Access to faces aItCS.Initialize(aLCSG); for (; aItCS.More(); aItCS.Next()) { const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value(); listShape.Append(aCSG.Shape1()); } TopTools_ListIteratorOfListOfShape itSub (listShape); TCollection_AsciiString anAsciiList, anEntry; TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); Handle(TColStd_HArray1OfInteger) anArray; Handle(GEOM_Object) anObj; for (int index = 1; itSub.More(); itSub.Next(), ++index) { TopoDS_Shape aValue = itSub.Value(); anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aValue)); anObj = GetEngine()->AddSubShape(theShape, anArray); if (!anObj.IsNull()) { aSeq->Append(anObj); // for python command TDF_Tool::Entry(anObj->GetEntry(), anEntry); anAsciiList += anEntry; anAsciiList += ","; } } //Make a Python command if( anAsciiList.Length() > 0 ) { anAsciiList.Trunc(anAsciiList.Length() - 1); Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); GEOM::TPythonDump pd (aFunction, true); pd << "[" << anAsciiList.ToCString(); pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")"; } SetErrorCode(OK); return aSeq; } */ //============================================================================= /*! * MakeGlueFacesByList */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList (Handle(GEOM_Object) theShape, const Standard_Real theTolerance, std::list theFaces, const Standard_Boolean doKeepNonSolids, const Standard_Boolean doGlueAllEdges) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; //Add a new Glued object Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED); //Add a new Glue function Handle(GEOM_Function) aFunction; aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST); if (aFunction.IsNull()) return NULL; //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL; GEOMImpl_IGlue aCI (aFunction); Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); if (aRefShape.IsNull()) return NULL; aCI.SetBase(aRefShape); aCI.SetTolerance(theTolerance); aCI.SetKeepNonSolids(doKeepNonSolids); aCI.SetGlueAllEdges(doGlueAllEdges); Handle(TColStd_HSequenceOfTransient) aFaces = new TColStd_HSequenceOfTransient; std::list::iterator it = theFaces.begin(); for (; it != theFaces.end(); it++) { Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction(); if (aRefSh.IsNull()) { SetErrorCode("NULL argument shape for the shape construction"); return NULL; } aFaces->Append(aRefSh); } aCI.SetFaces(aFaces); //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to glue faces"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); // to provide warning if (!aFunction->GetValue().IsNull()) { isWarning = Standard_True; } else { return NULL; } } //Make a Python command GEOM::TPythonDump pd(aFunction); pd << aGlued << " = geompy.MakeGlueFacesByList(" << theShape << ", " << theTolerance << ", ["; // Faces it = theFaces.begin(); if (it != theFaces.end()) { pd << (*it++); while (it != theFaces.end()) { pd << ", " << (*it++); } } pd << "], " << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")"; // to provide warning if (!isWarning) SetErrorCode(OK); return aGlued; } //============================================================================= /*! * MakeGlueEdges */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdges (Handle(GEOM_Object) theShape, const Standard_Real theTolerance) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; //Add a new Glued object Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED); //Add a new Glue function Handle(GEOM_Function) aFunction; aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES); if (aFunction.IsNull()) return NULL; //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL; GEOMImpl_IGlue aCI (aFunction); Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); if (aRefShape.IsNull()) return NULL; aCI.SetBase(aRefShape); aCI.SetTolerance(theTolerance); aCI.SetKeepNonSolids(true); //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to glue edges"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); // to provide warning if (!aFunction->GetValue().IsNull()) { isWarning = Standard_True; } else { return NULL; } } //Make a Python command GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueEdges(" << theShape << ", " << theTolerance << ")"; // to provide warning if (!isWarning) SetErrorCode(OK); return aGlued; } //============================================================================= /*! * GetGlueShapes */ //============================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueShapes (Handle(GEOM_Object) theShape, const Standard_Real theTolerance, const TopAbs_ShapeEnum theType) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); if (aShape.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; GEOMAlgo_GlueDetector aGluer; aGluer.SetArgument(aShape); aGluer.SetTolerance(theTolerance); aGluer.Perform(); Standard_Integer iErr = aGluer.ErrorStatus(); if (iErr) return NULL; TCollection_AsciiString anAsciiList, anEntry; TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); Handle(TColStd_HArray1OfInteger) anArray; Handle(GEOM_Object) anObj; TopTools_ListOfShape listOnePerSet; const TopTools_DataMapOfShapeListOfShape& aImages = aGluer.Images(); TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS (aImages); for (int index = 1; aItDMSLS.More(); aItDMSLS.Next(), ++index) { // some key shape //const TopoDS_Shape& aSkey = aItDMSLS.Key(); // list of shapes of the argument that can be glued const TopTools_ListOfShape& aLSD = aItDMSLS.Value(); //listShape.Append(aLSD.First()); TopoDS_Shape aValue = aLSD.First(); if (aValue.ShapeType() == theType) { listOnePerSet.Append(aValue); } } // for stable order of returned entities GEOMImpl_IShapesOperations::SortShapes(listOnePerSet, Standard_False); TopTools_ListIteratorOfListOfShape aListIt (listOnePerSet); for (; aListIt.More(); aListIt.Next()) { TopoDS_Shape aValue = aListIt.Value(); anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aValue)); anObj = GetEngine()->AddSubShape(theShape, anArray); if (!anObj.IsNull()) { aSeq->Append(anObj); // for python command TDF_Tool::Entry(anObj->GetEntry(), anEntry); anAsciiList += anEntry; anAsciiList += ","; } } // Make a Python command if (anAsciiList.Length() > 0) { anAsciiList.Trunc(anAsciiList.Length() - 1); Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); GEOM::TPythonDump pd (aFunction, /*append=*/true); pd << "[" << anAsciiList.ToCString(); if (theType == TopAbs_FACE) pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")"; else if (theType == TopAbs_EDGE) pd << "] = geompy.GetGlueEdges(" << theShape << ", " << theTolerance << ")"; } SetErrorCode(OK); return aSeq; } //============================================================================= /*! * MakeGlueEdgesByList */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdgesByList (Handle(GEOM_Object) theShape, const Standard_Real theTolerance, std::list theEdges) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; //Add a new Glued object Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED); //Add a new Glue function Handle(GEOM_Function) aFunction; aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES_BY_LIST); if (aFunction.IsNull()) return NULL; //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL; GEOMImpl_IGlue aCI (aFunction); Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); if (aRefShape.IsNull()) return NULL; aCI.SetBase(aRefShape); aCI.SetTolerance(theTolerance); aCI.SetKeepNonSolids(true); Handle(TColStd_HSequenceOfTransient) anEdges = new TColStd_HSequenceOfTransient; std::list::iterator it = theEdges.begin(); for (; it != theEdges.end(); it++) { Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction(); if (aRefSh.IsNull()) { SetErrorCode("NULL argument shape for the shape construction"); return NULL; } anEdges->Append(aRefSh); } aCI.SetFaces(anEdges); //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to glue edges"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); // to provide warning if (!aFunction->GetValue().IsNull()) { isWarning = Standard_True; } else { return NULL; } } //Make a Python command GEOM::TPythonDump pd (aFunction); pd << aGlued << " = geompy.MakeGlueEdgesByList(" << theShape << ", " << theTolerance << ", ["; // Edges it = theEdges.begin(); if (it != theEdges.end()) { pd << (*it++); while (it != theEdges.end()) { pd << ", " << (*it++); } } pd << "])"; // to provide warning if (!isWarning) SetErrorCode(OK); return aGlued; } //============================================================================= /*! * GetExistingSubObjects */ //============================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetExistingSubObjects (Handle(GEOM_Object) theShape, const Standard_Boolean theGroupsOnly) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; Handle(GEOM_Function) aMainShape = theShape->GetLastFunction(); if (aMainShape.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; SetErrorCode(NOT_FOUND_ANY); if (!aMainShape->HasSubShapeReferences()) return aSeq; const TDataStd_ListOfExtendedString& aListEntries = aMainShape->GetSubShapeReferences(); if (aListEntries.IsEmpty()) return aSeq; SetErrorCode(KO); TCollection_AsciiString anAsciiList; TDataStd_ListIteratorOfListOfExtendedString anIt (aListEntries); for (; anIt.More(); anIt.Next()) { TCollection_ExtendedString anEntry = anIt.Value(); Standard_Integer aStrLen = anEntry.LengthOfCString(); char* anEntryStr = new char[aStrLen]; anEntry.ToUTF8CString(anEntryStr); Handle(GEOM_Object) anObj = GetEngine()->GetObject(GetDocID(), anEntryStr, false); if (!anObj.IsNull()) { if (!theGroupsOnly || anObj->GetType() == GEOM_GROUP) { aSeq->Append(anObj); // for python command anAsciiList += anEntryStr; anAsciiList += ","; } } delete [] anEntryStr; } if (aSeq->Length() == 0) { SetErrorCode(NOT_FOUND_ANY); return aSeq; } //Make a Python command anAsciiList.Trunc(anAsciiList.Length() - 1); GEOM::TPythonDump pd (aMainShape, /*append=*/true); pd << "[" << anAsciiList.ToCString(); pd << "] = geompy.GetExistingSubObjects("; pd << theShape << ", " << (bool)theGroupsOnly << ")"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * MakeExplode */ //============================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode (Handle(GEOM_Object) theShape, const Standard_Integer theShapeType, const Standard_Boolean isSorted, const ExplodeType theExplodeType) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); if (aShape.IsNull()) return NULL; Handle(GEOM_Function) aMainShape = theShape->GetLastFunction(); Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; Handle(GEOM_Object) anObj; TopTools_MapOfShape mapShape; TopTools_ListOfShape listShape; if (aShape.ShapeType() == TopAbs_COMPOUND && (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) { TopoDS_Iterator It (aShape, Standard_True, Standard_True); for (; It.More(); It.Next()) { if (mapShape.Add(It.Value())) { if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) { listShape.Append(It.Value()); } } } } else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079 { TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType)); for (; exp.More(); exp.Next()) if (mapShape.Add(exp.Current())) listShape.Append(exp.Current()); } if (listShape.IsEmpty()) { //SetErrorCode("The given shape has no sub-shapes of the requested type"); SetErrorCode(NOT_FOUND_ANY); // NPAL18017 return aSeq; } if (isSorted) { bool isOldSorting = false; if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN) isOldSorting = true; SortShapes(listShape, isOldSorting); } TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); Handle(TColStd_HArray1OfInteger) anArray; TopTools_ListIteratorOfListOfShape itSub (listShape); TCollection_AsciiString anAsciiList, anEntry; for (int index = 1; itSub.More(); itSub.Next(), ++index) { TopoDS_Shape aValue = itSub.Value(); anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aValue)); //anObj = GetEngine()->AddSubShape(theShape, anArray); { anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE); Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1); if (aFunction.IsNull()) return aSeq; GEOM_ISubShape aSSI (aFunction); aSSI.SetMainShape(aMainShape); aSSI.SetIndices(anArray); // Set function value directly, as we know it. // Usage of Solver here would lead to significant loss of time, // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape // on the main shape for each being calculated sub-shape separately. aFunction->SetValue(aValue); // Put this subshape in the list of subshapes of theMainShape aMainShape->AddSubShapeReference(aFunction); } if (!anObj.IsNull()) { aSeq->Append(anObj); // for python command TDF_Tool::Entry(anObj->GetEntry(), anEntry); anAsciiList += anEntry; anAsciiList += ","; } } //Make a Python command anAsciiList.Trunc(anAsciiList.Length() - 1); GEOM::TPythonDump pd (aMainShape, /*append=*/true); pd << "[" << anAsciiList.ToCString() << "] = geompy."; switch (theExplodeType) { case EXPLODE_NEW_EXCLUDE_MAIN: pd << "ExtractShapes(" << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")"; break; case EXPLODE_NEW_INCLUDE_MAIN: pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(") << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; break; case EXPLODE_OLD_INCLUDE_MAIN: pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(") << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; break; default: ; } SetErrorCode(OK); return aSeq; } //============================================================================= /*! * SubShapeAllIDs */ //============================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs (Handle(GEOM_Object) theShape, const Standard_Integer theShapeType, const Standard_Boolean isSorted, const ExplodeType theExplodeType) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); if (aShape.IsNull()) return NULL; Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger; TopTools_MapOfShape mapShape; TopTools_ListOfShape listShape; if (aShape.ShapeType() == TopAbs_COMPOUND && (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) { TopoDS_Iterator It (aShape, Standard_True, Standard_True); for (; It.More(); It.Next()) { if (mapShape.Add(It.Value())) { if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) { listShape.Append(It.Value()); } } } } else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079 { TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType)); for (; exp.More(); exp.Next()) if (mapShape.Add(exp.Current())) listShape.Append(exp.Current()); } if (listShape.IsEmpty()) { //SetErrorCode("The given shape has no sub-shapes of the requested type"); SetErrorCode(NOT_FOUND_ANY); // NPAL18017 return aSeq; } if (isSorted) { bool isOldSorting = false; if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN) isOldSorting = true; SortShapes(listShape, isOldSorting); } TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); Handle(TColStd_HArray1OfInteger) anArray; TopTools_ListIteratorOfListOfShape itSub (listShape); for (int index = 1; itSub.More(); itSub.Next(), ++index) { TopoDS_Shape aValue = itSub.Value(); aSeq->Append(anIndices.FindIndex(aValue)); } Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command GEOM::TPythonDump pd (aFunction, /*append=*/true); pd << "listSubShapeIDs = geompy.SubShapeAll"; switch (theExplodeType) { case EXPLODE_NEW_EXCLUDE_MAIN: break; case EXPLODE_NEW_INCLUDE_MAIN: pd << (isSorted ? "SortedCentresIDs(" : "IDs(") << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; break; case EXPLODE_OLD_INCLUDE_MAIN: pd << (isSorted ? "SortedIDs(" : "IDs(") << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; break; default: ; } SetErrorCode(OK); return aSeq; } //============================================================================= /*! * GetSubShape */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape (Handle(GEOM_Object) theMainShape, const Standard_Integer theID) { SetErrorCode(KO); if (theMainShape.IsNull()) return NULL; Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, theID); Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true); if (anObj.IsNull()) { SetErrorCode("Can not get a sub-shape with the given ID"); return NULL; } Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); //Make a Python command GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape(" << theMainShape << ", [" << theID << "])"; SetErrorCode(OK); return anObj; } //============================================================================= /*! * MakeSubShapes */ //============================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes (Handle(GEOM_Object) theMainShape, Handle(TColStd_HArray1OfInteger) theIndices) { SetErrorCode(KO); Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; if (!theIndices->Length()) { SetErrorCode(NOT_FOUND_ANY); return aSeq; } if (theMainShape.IsNull()) return NULL; TopoDS_Shape aShape = theMainShape->GetValue(); if (aShape.IsNull()) return NULL; Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction(); TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); Handle(TColStd_HArray1OfInteger) anArray; Handle(GEOM_Object) anObj; TCollection_AsciiString anAsciiList, anEntry; Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper(); for (i = low; i <= up; i++) { int id = theIndices->Value(i); if (1 <= id && id <= anIndices.Extent()) { TopoDS_Shape aValue = anIndices.FindKey(id); anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, id); anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE); if (!anObj.IsNull()) { Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1); if (aFunction.IsNull()) return aSeq; GEOM_ISubShape aSSI (aFunction); aSSI.SetMainShape(aMainShape); aSSI.SetIndices(anArray); // Set function value directly, as we know it. // Usage of Solver here would lead to significant loss of time, // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape // on the main shape for each being calculated sub-shape separately. aFunction->SetValue(aValue); // Put this subshape in the list of subshapes of theMainShape aMainShape->AddSubShapeReference(aFunction); aSeq->Append(anObj); // for python command TDF_Tool::Entry(anObj->GetEntry(), anEntry); anAsciiList += anEntry; anAsciiList += ","; } } } //Make a Python command anAsciiList.Trunc(anAsciiList.Length() - 1); GEOM::TPythonDump pd (aMainShape, /*append=*/true); pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes(" << theMainShape << ", [" ; for (i = low; i <= up - 1; i++) { pd << theIndices->Value(i) << ", "; } pd << theIndices->Value(up) << "])"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * GetSubShapeIndex */ //============================================================================= Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape, Handle(GEOM_Object) theSubShape) { SetErrorCode(KO); TopoDS_Shape aMainShape = theMainShape->GetValue(); TopoDS_Shape aSubShape = theSubShape->GetValue(); if (aMainShape.IsNull() || aSubShape.IsNull()) return -1; TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aMainShape, anIndices); if (anIndices.Contains(aSubShape)) { SetErrorCode(OK); return anIndices.FindIndex(aSubShape); } return -1; } //============================================================================= /*! * GetTopologyIndex */ //============================================================================= Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape, Handle(GEOM_Object) theSubShape) { SetErrorCode(OK); TopoDS_Shape aMainShape = theMainShape->GetValue(); TopoDS_Shape aSubShape = theSubShape->GetValue(); if (aMainShape.IsNull() || aSubShape.IsNull()) { SetErrorCode("Null argument shape given"); return -1; } int index = 1; if (aSubShape.ShapeType() == TopAbs_COMPOUND) { TopoDS_Iterator it; TopTools_ListOfShape CL; CL.Append(aMainShape); TopTools_ListIteratorOfListOfShape itC; for (itC.Initialize(CL); itC.More(); itC.Next()) { for (it.Initialize(itC.Value()); it.More(); it.Next()) { if (it.Value().ShapeType() == TopAbs_COMPOUND) { if (it.Value().IsSame(aSubShape)) return index; else index++; CL.Append(it.Value()); } } } } else { TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType()); TopTools_MapOfShape M; for (; anExp.More(); anExp.Next()) { if (M.Add(anExp.Current())) { if (anExp.Current().IsSame(aSubShape)) return index; index++; } } } SetErrorCode("The sub-shape does not belong to the main shape"); return -1; } //============================================================================= /*! * GetShapeTypeString */ //============================================================================= TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape) { SetErrorCode(KO); TCollection_AsciiString aTypeName ("Null Shape"); TopoDS_Shape aShape = theShape->GetValue(); if (aShape.IsNull()) return aTypeName; switch (aShape.ShapeType() ) { case TopAbs_COMPOUND: aTypeName = "Compound"; break; case TopAbs_COMPSOLID: aTypeName = "Compound Solid"; break; case TopAbs_SOLID: aTypeName = "Solid"; break; case TopAbs_SHELL: aTypeName = "Shell"; break; case TopAbs_FACE: { BRepAdaptor_Surface surf (TopoDS::Face(aShape)); if (surf.GetType() == GeomAbs_Plane) aTypeName = "Plane"; else if (surf.GetType() == GeomAbs_Cylinder) aTypeName = "Cylindrical Face"; else if (surf.GetType() == GeomAbs_Sphere) aTypeName = "Spherical Face"; else if (surf.GetType() == GeomAbs_Torus) aTypeName = "Toroidal Face"; else if (surf.GetType() == GeomAbs_Cone) aTypeName = "Conical Face"; else aTypeName = "GEOM::FACE"; } break; case TopAbs_WIRE: aTypeName = "Wire"; break; case TopAbs_EDGE: { BRepAdaptor_Curve curv (TopoDS::Edge(aShape)); if (curv.GetType() == GeomAbs_Line) { if ((Abs(curv.FirstParameter()) >= 1E6) || (Abs(curv.LastParameter()) >= 1E6)) aTypeName = "Line"; else aTypeName = "Edge"; } else if (curv.GetType() == GeomAbs_Circle) { if (curv.IsClosed()) aTypeName = "Circle"; else aTypeName = "Arc"; } else { aTypeName = "Edge"; } } break; case TopAbs_VERTEX: aTypeName = "Vertex"; break; case TopAbs_SHAPE: aTypeName = "Shape"; break; default: aTypeName = "Shape of unknown type"; } return aTypeName; } //============================================================================= /*! * NumberOfSubShapes */ //============================================================================= Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes (Handle(GEOM_Object) theShape, const Standard_Integer theShapeType) { SetErrorCode(KO); Standard_Integer nbShapes = 0; if (theShape.IsNull()) return -1; TopoDS_Shape aShape = theShape->GetValue(); if (aShape.IsNull()) return -1; /* TopTools_MapOfShape mapShape; if (aShape.ShapeType() == TopAbs_COMPOUND && (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) { TopoDS_Iterator It (aShape, Standard_True, Standard_True); for (; It.More(); It.Next()) { if (mapShape.Add(It.Value())) { if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) { nbShapes++; } } } } else { TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType)); for (; exp.More(); exp.Next()) if (mapShape.Add(exp.Current())) nbShapes++; } */ try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif int iType, nbTypes [TopAbs_SHAPE]; for (iType = 0; iType < TopAbs_SHAPE; ++iType) nbTypes[iType] = 0; nbTypes[aShape.ShapeType()]++; TopTools_MapOfShape aMapOfShape; aMapOfShape.Add(aShape); TopTools_ListOfShape aListOfShape; aListOfShape.Append(aShape); TopTools_ListIteratorOfListOfShape itL (aListOfShape); for (; itL.More(); itL.Next()) { TopoDS_Iterator it (itL.Value()); for (; it.More(); it.Next()) { TopoDS_Shape s = it.Value(); if (aMapOfShape.Add(s)) { aListOfShape.Append(s); nbTypes[s.ShapeType()]++; } } } if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE) nbShapes = aMapOfShape.Extent(); else nbShapes = nbTypes[theShapeType]; } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return -1; } SetErrorCode(OK); return nbShapes; } //============================================================================= /*! * ReverseShape */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; /* //Add a new reversed object Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType()); //Add a new Revese function Handle(GEOM_Function) aFunction; aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION); if (aFunction.IsNull()) return NULL; //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; GEOMImpl_IShapes aSI (aFunction); Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); if (aRefShape.IsNull()) return NULL; aSI.SetBase(aRefShape); //Compute the sub-shape value try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to reverse shape"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command GEOM::TPythonDump(aFunction) << aReversed << " = geompy.ChangeOrientation(" << theShape << ")"; SetErrorCode(OK); */ Handle(GEOM_Object) aReversed; GEOM_Engine* anEngine = GetEngine(); //GEOMImpl_Gen* aGen = dynamic_cast(anEngine); GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine; if (aGen) { GEOMImpl_IHealingOperations* anIHealingOperations = aGen->GetIHealingOperations(GetDocID()); aReversed = anIHealingOperations->ChangeOrientation(theShape); SetErrorCode(anIHealingOperations->GetErrorCode()); } return aReversed; } //============================================================================= /*! * GetFreeFacesIDs */ //============================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs (Handle(GEOM_Object) theShape) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); if (aShape.IsNull()) return NULL; Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger; TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks; GEOMImpl_Block6Explorer::MapShapesAndAncestors (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks); Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent(); if (nbFaces == 0) { SetErrorCode("The given shape has no faces"); return aSeq; } TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); Standard_Integer id; for (; ind <= nbFaces; ind++) { if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) { id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind)); aSeq->Append(id); } } //The explode doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")"; SetErrorCode(OK); return aSeq; } //======================================================================= //function : GetSharedShapes //purpose : //======================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2, const Standard_Integer theShapeType) { SetErrorCode(KO); if (theShape1.IsNull() || theShape2.IsNull()) return NULL; TopoDS_Shape aShape1 = theShape1->GetValue(); TopoDS_Shape aShape2 = theShape2->GetValue(); if (aShape1.IsNull() || aShape2.IsNull()) return NULL; TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape1, anIndices); Handle(TColStd_HArray1OfInteger) anArray; TopTools_IndexedMapOfShape mapShape1; TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1); Handle(GEOM_Object) anObj; Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; TCollection_AsciiString anAsciiList, anEntry; TopTools_MapOfShape mapShape2; TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType)); for (; exp.More(); exp.Next()) { TopoDS_Shape aSS = exp.Current(); if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) { anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aSS)); anObj = GetEngine()->AddSubShape(theShape1, anArray); aSeq->Append(anObj); // for python command TDF_Tool::Entry(anObj->GetEntry(), anEntry); anAsciiList += anEntry; anAsciiList += ","; } } if (aSeq->IsEmpty()) { SetErrorCode("The given shapes have no shared sub-shapes of the requested type"); return aSeq; } //Make a Python command anAsciiList.Trunc(anAsciiList.Length() - 1); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() << "] = geompy.GetSharedShapes(" << theShape1 << ", " << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; SetErrorCode(OK); return aSeq; } //======================================================================= //function : GetSharedShapes //purpose : //======================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes (std::list theShapes, const Standard_Integer theShapeType) { SetErrorCode(KO); int aLen = theShapes.size(); if (aLen < 1) return NULL; int ind = 1; std::list::iterator it = theShapes.begin(); Handle(GEOM_Object) aMainObj = (*it++); Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction(); if (aMainShape.IsNull()) { SetErrorCode("NULL shape for GetSharedShapes"); return NULL; } TopoDS_Shape aShape1 = aMainShape->GetValue(); if (aShape1.IsNull()) return NULL; TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape1, anIndices); TopTools_IndexedMapOfShape mapSelected; TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected); // Find shared shapes BRep_Builder B; TopoDS_Compound aCurrSelection; for (; it != theShapes.end(); it++, ind++) { Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction(); if (aRefShape.IsNull()) { SetErrorCode("NULL shape for GetSharedShapes"); return NULL; } TopoDS_Compound aCompound; B.MakeCompound(aCompound); TopoDS_Shape aShape2 = aRefShape->GetValue(); if (aShape2.IsNull()) return NULL; TopTools_MapOfShape mapShape2; TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType)); for (; exp.More(); exp.Next()) { TopoDS_Shape aSS = exp.Current(); if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) { B.Add(aCompound, aSS); } } mapSelected.Clear(); TopExp::MapShapes(aCompound, TopAbs_ShapeEnum(theShapeType), mapSelected); aCurrSelection = aCompound; } // Create GEOM_Object for each found shared shape (collected in aCurrSelection) Handle(GEOM_Object) anObj; Handle(TColStd_HArray1OfInteger) anArray; Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; TCollection_AsciiString anAsciiList, anEntry; TopoDS_Iterator itSel (aCurrSelection, Standard_True, Standard_True); for (; itSel.More(); itSel.Next()) { anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(itSel.Value())); anObj = GetEngine()->AddSubShape(aMainObj, anArray); aSeq->Append(anObj); // for python command TDF_Tool::Entry(anObj->GetEntry(), anEntry); anAsciiList += anEntry; anAsciiList += ","; } if (aSeq->IsEmpty()) { SetErrorCode("The given shapes have no shared sub-shapes of the requested type"); return aSeq; } // Make a Python command anAsciiList.Trunc(anAsciiList.Length() - 1); GEOM::TPythonDump pd (aMainShape, /*append=*/true); pd << "[" << anAsciiList.ToCString() << "] = geompy.GetSharedShapesMulti(["; it = theShapes.begin(); pd << (*it++); while (it != theShapes.end()) { pd << ", " << (*it++); } pd << "], " << TopAbs_ShapeEnum(theShapeType) << ")"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * */ //============================================================================= static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump, const GEOMAlgo_State theState) { switch (theState) { case GEOMAlgo_ST_IN: theDump << "geompy.GEOM.ST_IN"; break; case GEOMAlgo_ST_OUT: theDump << "geompy.GEOM.ST_OUT"; break; case GEOMAlgo_ST_ON: theDump << "geompy.GEOM.ST_ON"; break; case GEOMAlgo_ST_ONIN: theDump << "geompy.GEOM.ST_ONIN"; break; case GEOMAlgo_ST_ONOUT: theDump << "geompy.GEOM.ST_ONOUT"; break; default: theDump << "geompy.GEOM.ST_UNKNOWN"; break; } return theDump; } //======================================================================= //function : checkTypeShapesOn /*! * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK * \param theShapeType - the shape type to check * \retval bool - result of the check */ //======================================================================= bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType) { if (theShapeType != TopAbs_VERTEX && theShapeType != TopAbs_EDGE && theShapeType != TopAbs_FACE && theShapeType != TopAbs_SOLID) { SetErrorCode("Only solids, vertices, edges or faces can be found by this method"); return false; } return true; } //======================================================================= //function : makePlane /*! * \brief Creates Geom_Plane * \param theAx1 - shape object defining plane parameters * \retval Handle(Geom_Surface) - resulting surface */ //======================================================================= Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1) { if (anAx1.ShapeType() != TopAbs_EDGE) return NULL; TopoDS_Edge anEdge = TopoDS::Edge(anAx1); TopoDS_Vertex V1, V2; TopExp::Vertices(anEdge, V1, V2, Standard_True); if (V1.IsNull() || V2.IsNull()) { SetErrorCode("Bad edge given for the plane normal vector"); return NULL; } gp_Pnt aLoc = BRep_Tool::Pnt(V1); gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2)); if (aVec.Magnitude() < Precision::Confusion()) { SetErrorCode("Vector with null magnitude given"); return NULL; } return new Geom_Plane(aLoc, aVec); } //======================================================================= //function : makeCylinder /*! * \brief Creates Geom_CylindricalSurface * \param theAx1 - edge defining cylinder axis * \param theRadius - cylinder radius * \retval Handle(Geom_Surface) - resulting surface */ //======================================================================= Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis, const Standard_Real theRadius) { //Axis of the cylinder if (anAxis.ShapeType() != TopAbs_EDGE) { SetErrorCode("Not an edge given for the axis"); return NULL; } TopoDS_Edge anEdge = TopoDS::Edge(anAxis); TopoDS_Vertex V1, V2; TopExp::Vertices(anEdge, V1, V2, Standard_True); if (V1.IsNull() || V2.IsNull()) { SetErrorCode("Bad edge given for the axis"); return NULL; } gp_Pnt aLoc = BRep_Tool::Pnt(V1); gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2)); if (aVec.Magnitude() < Precision::Confusion()) { SetErrorCode("Vector with null magnitude given"); return NULL; } gp_Ax3 anAx3 (aLoc, aVec); return new Geom_CylindricalSurface(anAx3, theRadius); } //======================================================================= //function : getShapesOnBoxIDs /*! * \brief Find IDs of subshapes complying with given status about surface * \param theBox - the box to check state of subshapes against * \param theShape - the shape to explore * \param theShapeType - type of subshape of theShape * \param theState - required state * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes */ //======================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox, const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, GEOMAlgo_State theState) { Handle(TColStd_HSequenceOfInteger) aSeqOfIDs; TopoDS_Shape aBox = theBox->GetValue(); TopoDS_Shape aShape = theShape->GetValue(); // Check presence of triangulation, build if need if (!CheckTriangulation(aShape)) { SetErrorCode("Cannot build triangulation on the shape"); return aSeqOfIDs; } // Call algo GEOMAlgo_FinderShapeOn2 aFinder; Standard_Real aTol = 0.0001; // default value Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox; aClsfBox->SetBox(aBox); aFinder.SetShape(aShape); aFinder.SetTolerance(aTol); aFinder.SetClsf(aClsfBox); aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType ); aFinder.SetState(theState); aFinder.Perform(); // Interprete results Standard_Integer iErr = aFinder.ErrorStatus(); // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx if (iErr) { MESSAGE(" iErr : " << iErr); TCollection_AsciiString aMsg (" iErr : "); aMsg += TCollection_AsciiString(iErr); SetErrorCode(aMsg); return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx if (iWrn) { MESSAGE(" *** iWrn : " << iWrn); } const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result if (listSS.Extent() < 1) { //SetErrorCode("Not a single sub-shape of the requested type found on the given surface"); SetErrorCode(NOT_FOUND_ANY); // NPAL18017 return aSeqOfIDs; } // Fill sequence of object IDs aSeqOfIDs = new TColStd_HSequenceOfInteger; TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); TopTools_ListIteratorOfListOfShape itSub (listSS); for (int index = 1; itSub.More(); itSub.Next(), ++index) { int id = anIndices.FindIndex(itSub.Value()); aSeqOfIDs->Append(id); } return aSeqOfIDs; } //======================================================================= //function : GetShapesOnBoxIDs /*! * \brief Find subshapes complying with given status about surface * \param theBox - the box to check state of subshapes against * \param theShape - the shape to explore * \param theShapeType - type of subshape of theShape * \param theState - required state * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes */ //======================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox, const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, GEOMAlgo_State theState) { // Find subshapes ids Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = getShapesOnBoxIDs (theBox, theShape, theShapeType, theState); if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) return NULL; // The GetShapesOnBox() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction(); // Make a Python command GEOM::TPythonDump(aFunction) << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs(" << theBox << ", " << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theState << ")"; SetErrorCode(OK); return aSeqOfIDs; } //======================================================================= //function : GetShapesOnBox /*! * \brief Find subshapes complying with given status about surface * \param theBox - the box to check state of subshapes against * \param theShape - the shape to explore * \param theShapeType - type of subshape of theShape * \param theState - required state * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes */ //======================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox, const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, GEOMAlgo_State theState) { // Find subshapes ids Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = getShapesOnBoxIDs (theBox, theShape, theShapeType, theState); if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) return NULL; // Find objects by indices TCollection_AsciiString anAsciiList; Handle(TColStd_HSequenceOfTransient) aSeq; aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList ); if ( aSeq.IsNull() || aSeq->IsEmpty() ) return NULL; // Make a Python command Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox(" << theBox << ", " << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } //======================================================================= //function : getShapesOnShapeIDs /*! * \brief Find IDs of subshapes complying with given status about surface * \param theCheckShape - the shape to check state of subshapes against * \param theShape - the shape to explore * \param theShapeType - type of subshape of theShape * \param theState - required state * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes */ //======================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::getShapesOnShapeIDs (const Handle(GEOM_Object)& theCheckShape, const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, GEOMAlgo_State theState) { Handle(TColStd_HSequenceOfInteger) aSeqOfIDs; TopoDS_Shape aCheckShape = theCheckShape->GetValue(); TopoDS_Shape aShape = theShape->GetValue(); TopTools_ListOfShape res; // Check presence of triangulation, build if need if (!CheckTriangulation(aShape)) { SetErrorCode("Cannot build triangulation on the shape"); return aSeqOfIDs; } // Call algo GEOMAlgo_FinderShapeOn2 aFinder; Standard_Real aTol = 0.0001; // default value Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid; aClsfSolid->SetShape(aCheckShape); aFinder.SetShape(aShape); aFinder.SetTolerance(aTol); aFinder.SetClsf(aClsfSolid); aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType ); aFinder.SetState(theState); aFinder.Perform(); // Interprete results Standard_Integer iErr = aFinder.ErrorStatus(); // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx if (iErr) { if (iErr == 41) { SetErrorCode("theCheckShape must be a solid"); } else { MESSAGE(" iErr : " << iErr); TCollection_AsciiString aMsg (" iErr : "); aMsg += TCollection_AsciiString(iErr); SetErrorCode(aMsg); } return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx if (iWrn) { MESSAGE(" *** iWrn : " << iWrn); } const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result if (listSS.Extent() < 1) { //SetErrorCode("Not a single sub-shape of the requested type found on the given surface"); SetErrorCode(NOT_FOUND_ANY); // NPAL18017 } // Fill sequence of object IDs aSeqOfIDs = new TColStd_HSequenceOfInteger; TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); TopTools_ListIteratorOfListOfShape itSub (listSS); for (int index = 1; itSub.More(); itSub.Next(), ++index) { int id = anIndices.FindIndex(itSub.Value()); aSeqOfIDs->Append(id); } return aSeqOfIDs; } //======================================================================= //function : GetShapesOnShapeIDs /*! * \brief Find subshapes complying with given status about surface * \param theCheckShape - the shape to check state of subshapes against * \param theShape - the shape to explore * \param theShapeType - type of subshape of theShape * \param theState - required state * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes */ //======================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnShapeIDs (const Handle(GEOM_Object)& theCheckShape, const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, GEOMAlgo_State theState) { Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState); if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) return NULL; // The GetShapesOnShape() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction(); // Make a Python command GEOM::TPythonDump(aFunction) << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs(" << theCheckShape << ", " << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theState << ")"; SetErrorCode(OK); return aSeqOfIDs; } //======================================================================= //function : GetShapesOnShape /*! * \brief Find subshapes complying with given status about surface * \param theCheckShape - the shape to check state of subshapes against * \param theShape - the shape to explore * \param theShapeType - type of subshape of theShape * \param theState - required state * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes */ //======================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnShape (const Handle(GEOM_Object)& theCheckShape, const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, GEOMAlgo_State theState) { Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState); if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) return NULL; // Find objects by indices TCollection_AsciiString anAsciiList; Handle(TColStd_HSequenceOfTransient) aSeq; aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList ); if ( aSeq.IsNull() || aSeq->IsEmpty() ) return NULL; // Make a Python command Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape(" << theCheckShape << ", " << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } //======================================================================= //function : GetShapesOnShapeAsCompound //======================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound (const Handle(GEOM_Object)& theCheckShape, const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, GEOMAlgo_State theState) { Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState); if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) return NULL; // Find objects by indices TCollection_AsciiString anAsciiList; Handle(TColStd_HSequenceOfTransient) aSeq; aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList ); if ( aSeq.IsNull() || aSeq->IsEmpty() ) return NULL; TopoDS_Compound aCompound; BRep_Builder B; B.MakeCompound(aCompound); int i = 1; for(; i<=aSeq->Length(); i++) { Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i)); TopoDS_Shape aShape_i = anObj->GetValue(); B.Add(aCompound,aShape_i); } //Add a new result object Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE); Handle(GEOM_Function) aFunction = aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE); aFunction->SetValue(aCompound); GEOM::TPythonDump(aFunction) << aRes << " = geompy.GetShapesOnShapeAsCompound(" << theCheckShape << ", " << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theState << ")"; SetErrorCode(OK); return aRes; } //======================================================================= //function : getShapesOnSurfaceIDs /*! * \brief Find IDs of subshapes complying with given status about surface * \param theSurface - the surface to check state of subshapes against * \param theShape - the shape to explore * \param theShapeType - type of subshape of theShape * \param theState - required state * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes */ //======================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface, const TopoDS_Shape& theShape, TopAbs_ShapeEnum theShapeType, GEOMAlgo_State theState) { Handle(TColStd_HSequenceOfInteger) aSeqOfIDs; // Check presence of triangulation, build if need if (!CheckTriangulation(theShape)) { SetErrorCode("Cannot build triangulation on the shape"); return aSeqOfIDs; } // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape // Compute tolerance Standard_Real T, VertMax = -RealLast(); try { #if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) { TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current()); T = BRep_Tool::Tolerance(Vertex); if (T > VertMax) VertMax = T; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return aSeqOfIDs; } // END: Mantis issue 0020961 // Call algo GEOMAlgo_FinderShapeOn1 aFinder; //Standard_Real aTol = 0.0001; // default value Standard_Real aTol = VertMax; // Mantis issue 0020961 aFinder.SetShape(theShape); aFinder.SetTolerance(aTol); aFinder.SetSurface(theSurface); aFinder.SetShapeType(theShapeType); aFinder.SetState(theState); // Sets the minimal number of inner points for the faces that do not have own // inner points at all (for e.g. rectangular planar faces have just 2 triangles). // Default value=3 aFinder.SetNbPntsMin(3); // Sets the maximal number of inner points for edges or faces. // It is usefull for the cases when this number is very big (e.g =2000) to improve // the performance. If this value =0, all inner points will be taken into account. // Default value=0 aFinder.SetNbPntsMax(100); aFinder.Perform(); // Interprete results Standard_Integer iErr = aFinder.ErrorStatus(); // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx if (iErr) { MESSAGE(" iErr : " << iErr); TCollection_AsciiString aMsg (" iErr : "); aMsg += TCollection_AsciiString(iErr); SetErrorCode(aMsg); return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx if (iWrn) { MESSAGE(" *** iWrn : " << iWrn); } const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result if (listSS.Extent() < 1) { //SetErrorCode("Not a single sub-shape of the requested type found on the given surface"); SetErrorCode(NOT_FOUND_ANY); // NPAL18017 return aSeqOfIDs; } // Fill sequence of object IDs aSeqOfIDs = new TColStd_HSequenceOfInteger; TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(theShape, anIndices); TopTools_ListIteratorOfListOfShape itSub (listSS); for (int index = 1; itSub.More(); itSub.Next(), ++index) { int id = anIndices.FindIndex(itSub.Value()); aSeqOfIDs->Append(id); } return aSeqOfIDs; } //======================================================================= //function : getObjectsShapesOn /*! * \brief Find shape objects and their entries by their ids * \param theShapeIDs - incoming shape ids * \param theShapeEntries - outgoing entries like "entry1, entry2, ..." * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects */ //======================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations:: getObjectsShapesOn(const Handle(GEOM_Object)& theShape, const Handle(TColStd_HSequenceOfInteger)& theShapeIDs, TCollection_AsciiString & theShapeEntries) { Handle(TColStd_HSequenceOfTransient) aSeq; if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 ) { aSeq = new TColStd_HSequenceOfTransient; Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); TCollection_AsciiString anEntry; for ( int i = 1; i <= theShapeIDs->Length(); ++i ) { anArray->SetValue(1, theShapeIDs->Value( i )); Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray); aSeq->Append( anObj ); TDF_Tool::Entry(anObj->GetEntry(), anEntry); if ( i != 1 ) theShapeEntries += ","; theShapeEntries += anEntry; } } return aSeq; } //======================================================================= //function : getShapesOnSurface /*! * \brief Find subshapes complying with given status about surface * \param theSurface - the surface to check state of subshapes against * \param theShape - the shape to explore * \param theShapeType - type of subshape of theShape * \param theState - required state * \param theShapeEntries - outgoing entries like "entry1, entry2, ..." * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes */ //======================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface, const Handle(GEOM_Object)& theShape, TopAbs_ShapeEnum theShapeType, GEOMAlgo_State theState, TCollection_AsciiString & theShapeEntries) { // Find subshapes ids Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState); if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) return NULL; return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries ); } //============================================================================= /*! * GetShapesOnPlane */ //============================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theAx1, const GEOMAlgo_State theState) { SetErrorCode(KO); if (theShape.IsNull() || theAx1.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape anAx1 = theAx1->GetValue(); if (aShape.IsNull() || anAx1.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); if ( !checkTypeShapesOn( theShapeType )) return NULL; // Create plane Handle(Geom_Surface) aPlane = makePlane( anAx1 ); if ( aPlane.IsNull() ) return NULL; // Find objects TCollection_AsciiString anAsciiList; Handle(TColStd_HSequenceOfTransient) aSeq; aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList ); if ( aSeq.IsNull() || aSeq->Length() == 0 ) return NULL; // Make a Python command Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnPlane(" << theShape << ", " << aShapeType << ", " << theAx1 << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * GetShapesOnPlaneWithLocation */ //============================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theAx1, const Handle(GEOM_Object)& thePnt, const GEOMAlgo_State theState) { SetErrorCode(KO); if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape anAx1 = theAx1->GetValue(); TopoDS_Shape anPnt = thePnt->GetValue(); if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); if ( !checkTypeShapesOn( theShapeType )) return NULL; // Create plane if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL; TopoDS_Vertex V1, V2, V3; TopoDS_Edge anEdge = TopoDS::Edge(anAx1); TopExp::Vertices(anEdge, V1, V2, Standard_True); if (V1.IsNull() || V2.IsNull()) { SetErrorCode("Bad edge given for the plane normal vector"); return NULL; } V3 = TopoDS::Vertex(anPnt); if(V3.IsNull()) { SetErrorCode("Bad vertex given for the plane location"); return NULL; } gp_Pnt aLoc = BRep_Tool::Pnt(V3); gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2)); if (aVec.Magnitude() < Precision::Confusion()) { SetErrorCode("Vector with null magnitude given"); return NULL; } Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec); if ( aPlane.IsNull() ) return NULL; // Find objects TCollection_AsciiString anAsciiList; Handle(TColStd_HSequenceOfTransient) aSeq; aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList ); if ( aSeq.IsNull() || aSeq->Length() == 0 ) return NULL; // Make a Python command Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * GetShapesOnCylinder */ //============================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theAxis, const Standard_Real theRadius, const GEOMAlgo_State theState) { SetErrorCode(KO); if (theShape.IsNull() || theAxis.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape anAxis = theAxis->GetValue(); if (aShape.IsNull() || anAxis.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); if ( !checkTypeShapesOn( aShapeType )) return NULL; // Create a cylinder surface Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius ); if ( aCylinder.IsNull() ) return NULL; // Find objects TCollection_AsciiString anAsciiList; Handle(TColStd_HSequenceOfTransient) aSeq; aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList ); if ( aSeq.IsNull() || aSeq->Length() == 0 ) return NULL; // Make a Python command Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType << ", " << theAxis << ", " << theRadius << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * GetShapesOnCylinderWithLocation */ //============================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theAxis, const Handle(GEOM_Object)& thePnt, const Standard_Real theRadius, const GEOMAlgo_State theState) { SetErrorCode(KO); if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape anAxis = theAxis->GetValue(); TopoDS_Shape aPnt = thePnt->GetValue(); if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL; if (aPnt.ShapeType() != TopAbs_VERTEX ) { SetErrorCode("Bottom location point must be vertex"); return NULL; } TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); if ( !checkTypeShapesOn( aShapeType )) return NULL; // Create a cylinder surface Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius ); if ( aCylinder.IsNull() ) return NULL; // translate the surface Handle(Geom_CylindricalSurface) aCylSurface = Handle(Geom_CylindricalSurface)::DownCast( aCylinder ); if ( aCylSurface.IsNull() ) { SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface"); return NULL; } gp_Pnt fromLoc = aCylSurface->Cylinder().Location(); gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt )); aCylinder->Translate( fromLoc, toLoc ); // Find objects TCollection_AsciiString anAsciiList; Handle(TColStd_HSequenceOfTransient) aSeq; aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList ); if ( aSeq.IsNull() || aSeq->Length() == 0 ) return NULL; // Make a Python command Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", " << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * GetShapesOnSphere */ //============================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theCenter, const Standard_Real theRadius, const GEOMAlgo_State theState) { SetErrorCode(KO); if (theShape.IsNull() || theCenter.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape aCenter = theCenter->GetValue(); if (aShape.IsNull() || aCenter.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); if ( !checkTypeShapesOn( aShapeType )) return NULL; // Center of the sphere if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL; gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter)); gp_Ax3 anAx3 (aLoc, gp::DZ()); Handle(Geom_SphericalSurface) aSphere = new Geom_SphericalSurface(anAx3, theRadius); // Find objects TCollection_AsciiString anAsciiList; Handle(TColStd_HSequenceOfTransient) aSeq; aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList ); if ( aSeq.IsNull() || aSeq->Length() == 0 ) return NULL; // Make a Python command Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType << ", " << theCenter << ", " << theRadius << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * GetShapesOnPlaneIDs */ //============================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theAx1, const GEOMAlgo_State theState) { SetErrorCode(KO); if (theShape.IsNull() || theAx1.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape anAx1 = theAx1->GetValue(); if (aShape.IsNull() || anAx1.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); if ( !checkTypeShapesOn( aShapeType )) return NULL; // Create plane Handle(Geom_Surface) aPlane = makePlane( anAx1 ); if ( aPlane.IsNull() ) return NULL; // Find object IDs Handle(TColStd_HSequenceOfInteger) aSeq; aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState ); // The GetShapesOnPlaneIDs() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction(); // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs" << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * GetShapesOnPlaneWithLocationIDs */ //============================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theAx1, const Handle(GEOM_Object)& thePnt, const GEOMAlgo_State theState) { SetErrorCode(KO); if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape anAx1 = theAx1->GetValue(); TopoDS_Shape anPnt = thePnt->GetValue(); if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); if ( !checkTypeShapesOn( aShapeType )) return NULL; // Create plane if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL; TopoDS_Edge anEdge = TopoDS::Edge(anAx1); TopoDS_Vertex V1, V2, V3; TopExp::Vertices(anEdge, V1, V2, Standard_True); if (V1.IsNull() || V2.IsNull()) { SetErrorCode("Bad edge given for the plane normal vector"); return NULL; } V3 = TopoDS::Vertex(anPnt); if(V3.IsNull()) { SetErrorCode("Bad vertex given for the plane location"); return NULL; } gp_Pnt aLoc = BRep_Tool::Pnt(V3); gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2)); if (aVec.Magnitude() < Precision::Confusion()) { SetErrorCode("Vector with null magnitude given"); return NULL; } Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec); if ( aPlane.IsNull() ) return NULL; // Find object IDs Handle(TColStd_HSequenceOfInteger) aSeq; aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState ); // The GetShapesOnPlaneIDs() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction(); // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs" << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * GetShapesOnCylinderIDs */ //============================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theAxis, const Standard_Real theRadius, const GEOMAlgo_State theState) { SetErrorCode(KO); if (theShape.IsNull() || theAxis.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape anAxis = theAxis->GetValue(); if (aShape.IsNull() || anAxis.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); if ( !checkTypeShapesOn( aShapeType )) return NULL; // Create a cylinder surface Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius ); if ( aCylinder.IsNull() ) return NULL; // Find object IDs Handle(TColStd_HSequenceOfInteger) aSeq; aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState ); // The GetShapesOnCylinder() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction(); // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs" << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", " << theRadius << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * GetShapesOnCylinderWithLocationIDs */ //============================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theAxis, const Handle(GEOM_Object)& thePnt, const Standard_Real theRadius, const GEOMAlgo_State theState) { SetErrorCode(KO); if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape anAxis = theAxis->GetValue(); TopoDS_Shape aPnt = thePnt->GetValue(); if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL; if (aPnt.ShapeType() != TopAbs_VERTEX ) { SetErrorCode("Bottom location point must be vertex"); return NULL; } TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); if ( !checkTypeShapesOn( aShapeType )) return NULL; // Create a cylinder surface Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius ); if ( aCylinder.IsNull() ) return NULL; // translate the surface Handle(Geom_CylindricalSurface) aCylSurface = Handle(Geom_CylindricalSurface)::DownCast( aCylinder ); if ( aCylSurface.IsNull() ) { SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface"); return NULL; } gp_Pnt fromLoc = aCylSurface->Cylinder().Location(); gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt )); aCylinder->Translate( fromLoc, toLoc ); // Find object IDs Handle(TColStd_HSequenceOfInteger) aSeq; aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState ); // The GetShapesOnCylinder() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction(); // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs" << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } //============================================================================= /*! * GetShapesOnSphereIDs */ //============================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theCenter, const Standard_Real theRadius, const GEOMAlgo_State theState) { SetErrorCode(KO); if (theShape.IsNull() || theCenter.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape aCenter = theCenter->GetValue(); if (aShape.IsNull() || aCenter.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); if ( !checkTypeShapesOn( aShapeType )) return NULL; // Center of the sphere if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL; gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter)); gp_Ax3 anAx3 (aLoc, gp::DZ()); Handle(Geom_SphericalSurface) aSphere = new Geom_SphericalSurface(anAx3, theRadius); // Find object IDs Handle(TColStd_HSequenceOfInteger) aSeq; aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState ); // The GetShapesOnSphere() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction(); // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs" << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", " << theRadius << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } //======================================================================= //function : getShapesOnQuadrangleIDs /*! * \brief Find IDs of subshapes complying with given status about quadrangle * \param theShape - the shape to explore * \param theShapeType - type of subshape of theShape * \param theTopLeftPoint - top left quadrangle corner * \param theTopRigthPoint - top right quadrangle corner * \param theBottomLeftPoint - bottom left quadrangle corner * \param theBottomRigthPoint - bottom right quadrangle corner * \param theState - required state * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes */ //======================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theTopLeftPoint, const Handle(GEOM_Object)& theTopRigthPoint, const Handle(GEOM_Object)& theBottomLeftPoint, const Handle(GEOM_Object)& theBottomRigthPoint, const GEOMAlgo_State theState) { SetErrorCode(KO); if ( theShape.IsNull() || theTopLeftPoint.IsNull() || theTopRigthPoint.IsNull() || theBottomLeftPoint.IsNull() || theBottomRigthPoint.IsNull() ) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape aTL = theTopLeftPoint->GetValue(); TopoDS_Shape aTR = theTopRigthPoint->GetValue(); TopoDS_Shape aBL = theBottomLeftPoint->GetValue(); TopoDS_Shape aBR = theBottomRigthPoint->GetValue(); if (aShape.IsNull() || aTL.IsNull() || aTR.IsNull() || aBL.IsNull() || aBR.IsNull() || aTL.ShapeType() != TopAbs_VERTEX || aTR.ShapeType() != TopAbs_VERTEX || aBL.ShapeType() != TopAbs_VERTEX || aBR.ShapeType() != TopAbs_VERTEX ) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); if ( !checkTypeShapesOn( aShapeType )) return NULL; Handle(TColStd_HSequenceOfInteger) aSeqOfIDs; // Check presence of triangulation, build if need if (!CheckTriangulation(aShape)) { SetErrorCode("Cannot build triangulation on the shape"); return aSeqOfIDs; } // Call algo gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL)); gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR)); gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL)); gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR)); GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR ); Standard_Real aTol = 0.0001; // default value aFinder.SetShape(aShape); aFinder.SetTolerance(aTol); //aFinder.SetSurface(theSurface); aFinder.SetShapeType(aShapeType); aFinder.SetState(theState); // Sets the minimal number of inner points for the faces that do not have own // inner points at all (for e.g. rectangular planar faces have just 2 triangles). // Default value=3 aFinder.SetNbPntsMin(3); // Sets the maximal number of inner points for edges or faces. // It is usefull for the cases when this number is very big (e.g =2000) to improve // the performance. If this value =0, all inner points will be taken into account. // Default value=0 aFinder.SetNbPntsMax(100); aFinder.Perform(); // Interprete results Standard_Integer iErr = aFinder.ErrorStatus(); // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx if (iErr) { MESSAGE(" iErr : " << iErr); TCollection_AsciiString aMsg (" iErr : "); aMsg += TCollection_AsciiString(iErr); SetErrorCode(aMsg); return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx if (iWrn) { MESSAGE(" *** iWrn : " << iWrn); } const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result if (listSS.Extent() < 1) { //SetErrorCode("Not a single sub-shape of the requested type found on the given surface"); SetErrorCode(NOT_FOUND_ANY); // NPAL18017 return aSeqOfIDs; } // Fill sequence of object IDs aSeqOfIDs = new TColStd_HSequenceOfInteger; TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); TopTools_ListIteratorOfListOfShape itSub (listSS); for (int index = 1; itSub.More(); itSub.Next(), ++index) { int id = anIndices.FindIndex(itSub.Value()); aSeqOfIDs->Append(id); } return aSeqOfIDs; } //======================================================================= //function : GetShapesOnQuadrangle /*! * \brief Find subshapes complying with given status about quadrangle * \param theShape - the shape to explore * \param theShapeType - type of subshape of theShape * \param theTopLeftPoint - top left quadrangle corner * \param theTopRigthPoint - top right quadrangle corner * \param theBottomLeftPoint - bottom left quadrangle corner * \param theBottomRigthPoint - bottom right quadrangle corner * \param theState - required state * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes */ //======================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theTopLeftPoint, const Handle(GEOM_Object)& theTopRigthPoint, const Handle(GEOM_Object)& theBottomLeftPoint, const Handle(GEOM_Object)& theBottomRigthPoint, const GEOMAlgo_State theState) { // Find indices Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = getShapesOnQuadrangleIDs( theShape, theShapeType, theTopLeftPoint, theTopRigthPoint, theBottomLeftPoint, theBottomRigthPoint, theState); if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() ) return NULL; // Find objects by indices TCollection_AsciiString anAsciiList; Handle(TColStd_HSequenceOfTransient) aSeq; aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList ); if ( aSeq.IsNull() || aSeq->IsEmpty() ) return NULL; // Make a Python command Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle(" << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTopLeftPoint << ", " << theTopRigthPoint << ", " << theBottomLeftPoint << ", " << theBottomRigthPoint << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } //======================================================================= //function : GetShapesOnQuadrangleIDs /*! * \brief Find IDs of subshapes complying with given status about quadrangle * \param theShape - the shape to explore * \param theShapeType - type of subshape of theShape * \param theTopLeftPoint - top left quadrangle corner * \param theTopRigthPoint - top right quadrangle corner * \param theBottomLeftPoint - bottom left quadrangle corner * \param theBottomRigthPoint - bottom right quadrangle corner * \param theState - required state * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes */ //======================================================================= Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theTopLeftPoint, const Handle(GEOM_Object)& theTopRigthPoint, const Handle(GEOM_Object)& theBottomLeftPoint, const Handle(GEOM_Object)& theBottomRigthPoint, const GEOMAlgo_State theState) { // Find indices Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = getShapesOnQuadrangleIDs( theShape, theShapeType, theTopLeftPoint, theTopRigthPoint, theBottomLeftPoint, theBottomRigthPoint, theState); if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() ) return NULL; // Make a Python command // The GetShapesOnCylinder() doesn't change object so no new function is required. Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint); lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint); lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint); lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint); Handle(GEOM_Function) aFunction = lastObj->GetLastFunction(); GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs(" << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTopLeftPoint << ", " << theTopRigthPoint << ", " << theBottomLeftPoint << ", " << theBottomRigthPoint << ", " << theState << ")"; SetErrorCode(OK); return aSeqOfIDs; } //============================================================================= /*! * GetInPlaceOfShape */ //============================================================================= static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction, const TopTools_IndexedMapOfShape& theWhereIndices, const TopoDS_Shape& theWhat, TColStd_ListOfInteger& theModifiedList) { if (theWhereFunction.IsNull() || theWhat.IsNull()) return false; if (theWhereIndices.Contains(theWhat)) { // entity was not changed by the operation Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat); theModifiedList.Append(aWhatIndex); return true; } // try to find in history TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False); // search in history for all argument shapes Standard_Boolean isFound = Standard_False; Standard_Boolean isGood = Standard_False; TDF_LabelSequence aLabelSeq; theWhereFunction->GetDependency(aLabelSeq); Standard_Integer nbArg = aLabelSeq.Length(); for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) { TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg); Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel); TopoDS_Shape anArgumentShape = anArgumentObject->GetValue(); TopTools_IndexedMapOfShape anArgumentIndices; TopExp::MapShapes(anArgumentShape, anArgumentIndices); if (anArgumentIndices.Contains(theWhat)) { isFound = Standard_True; Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat); // Find corresponding label in history TDF_Label anArgumentHistoryLabel = theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False); if (anArgumentHistoryLabel.IsNull()) { // Lost History of operation argument. Possibly, all its entities was removed. isGood = Standard_True; } else { TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False); if (aWhatHistoryLabel.IsNull()) { // Removed entity ? Compound ? Compsolid ? Shell ? Wire isGood = Standard_False; } else { Handle(TDataStd_IntegerArray) anIntegerArray; if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) { //Error: Empty modifications history for the sought shape. isGood = Standard_False; } else { isGood = Standard_True; Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length(); for (imod = 1; imod <= aModifLen; imod++) { theModifiedList.Append(anIntegerArray->Array()->Value(imod)); } } } } } } isFound = isGood; if (!isFound) { // try compound/compsolid/shell/wire element by element bool isFoundAny = false; TopTools_MapOfShape mapShape; if (theWhat.ShapeType() == TopAbs_COMPOUND || theWhat.ShapeType() == TopAbs_COMPSOLID) { // recursive processing of compound/compsolid TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True); for (; anIt.More(); anIt.Next()) { if (mapShape.Add(anIt.Value())) { TopoDS_Shape curWhat = anIt.Value(); isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList); if (isFoundAny) isFound = Standard_True; } } } else if (theWhat.ShapeType() == TopAbs_SHELL) { // try to replace a shell by its faces images TopExp_Explorer anExp (theWhat, TopAbs_FACE); for (; anExp.More(); anExp.Next()) { if (mapShape.Add(anExp.Current())) { TopoDS_Shape curWhat = anExp.Current(); isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList); if (isFoundAny) isFound = Standard_True; } } } else if (theWhat.ShapeType() == TopAbs_WIRE) { // try to replace a wire by its edges images TopExp_Explorer anExp (theWhat, TopAbs_EDGE); for (; anExp.More(); anExp.Next()) { if (mapShape.Add(anExp.Current())) { TopoDS_Shape curWhat = anExp.Current(); isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList); if (isFoundAny) isFound = Standard_True; } } } else { // Removed entity } } return isFound; } //============================================================================= /*! * GetShapeProperties */ //============================================================================= void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[], gp_Pnt & aVertex ) { GProp_GProps theProps; gp_Pnt aCenterMass; //TopoDS_Shape aPntShape; Standard_Real aShapeSize; if (aShape.ShapeType() == TopAbs_VERTEX) aCenterMass = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) ); else if (aShape.ShapeType() == TopAbs_EDGE) BRepGProp::LinearProperties(aShape, theProps); else if (aShape.ShapeType() == TopAbs_FACE) BRepGProp::SurfaceProperties(aShape, theProps); else BRepGProp::VolumeProperties(aShape, theProps); if (aShape.ShapeType() == TopAbs_VERTEX) aShapeSize = 1; else { aCenterMass = theProps.CentreOfMass(); aShapeSize = theProps.Mass(); } // aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape(); // aVertex = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) ); aVertex = aCenterMass; tab[0] = aVertex.X(); tab[1] = aVertex.Y(); tab[2] = aVertex.Z(); tab[3] = aShapeSize; return; } namespace { //================================================================================ /*! * \brief Return normal to face at extrema point */ //================================================================================ gp_Vec GetNormal (const TopoDS_Face& face, const BRepExtrema_DistShapeShape& extrema) { gp_Vec defaultNorm(1,0,0); // to have same normals on different faces try { // get UV at extrema point Standard_Real u,v, f,l; switch ( extrema.SupportTypeShape2(1) ) { case BRepExtrema_IsInFace: { extrema.ParOnFaceS2(1, u, v ); break; } case BRepExtrema_IsOnEdge: { TopoDS_Edge edge = TopoDS::Edge( extrema.SupportOnShape2(1)); Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f,l ); extrema.ParOnEdgeS2( 1, u ); gp_Pnt2d uv = pcurve->Value( u ); u = uv.Coord(1); v = uv.Coord(2); break; } case BRepExtrema_IsVertex: return defaultNorm; } // get derivatives BRepAdaptor_Surface surface( face, false ); gp_Vec du, dv; gp_Pnt p; surface.D1( u, v, p, du, dv ); return du ^ dv; } catch (Standard_Failure ) { } return defaultNorm; } } //================================================================================ /*! * \brief Return type of shape for explode. In case of compound it will be a type of sub shape. */ //================================================================================ TopAbs_ShapeEnum GEOMImpl_IShapesOperations::GetTypeOfSimplePart (const TopoDS_Shape& theShape) { TopAbs_ShapeEnum aType = theShape.ShapeType(); if (aType == TopAbs_VERTEX) return TopAbs_VERTEX; else if (aType == TopAbs_EDGE || aType == TopAbs_WIRE) return TopAbs_EDGE; else if (aType == TopAbs_FACE || aType == TopAbs_SHELL) return TopAbs_FACE; else if (aType == TopAbs_SOLID || aType == TopAbs_COMPSOLID) return TopAbs_SOLID; else if (aType == TopAbs_COMPOUND) { // Only the iType of the first shape in the compound is taken into account TopoDS_Iterator It (theShape, Standard_False, Standard_False); if (It.More()) { return GetTypeOfSimplePart(It.Value()); } } return TopAbs_SHAPE; } //============================================================================= /*! * case GetInPlace: * default: */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere, Handle(GEOM_Object) theShapeWhat) { SetErrorCode(KO); if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL; TopoDS_Shape aWhere = theShapeWhere->GetValue(); TopoDS_Shape aWhat = theShapeWhat->GetValue(); TopoDS_Shape aPntShape; TopoDS_Vertex aVertex; if (aWhere.IsNull() || aWhat.IsNull()) { SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null."); return NULL; } Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction(); if (aWhereFunction.IsNull()) { SetErrorCode("Error: aWhereFunction is Null."); return NULL; } TopTools_IndexedMapOfShape aWhereIndices; TopExp::MapShapes(aWhere, aWhereIndices); TopAbs_ShapeEnum iType = TopAbs_SOLID; Standard_Real dl_l = 1e-3; Standard_Real min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass; Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; Bnd_Box BoundingBox; gp_Pnt aPnt, aPnt_aWhat, tab_Pnt[2]; GProp_GProps aProps; // Find the iType of the aWhat shape iType = GetTypeOfSimplePart(aWhat); if (iType == TopAbs_SHAPE) { SetErrorCode("Error: An attempt to extract a shape of not supported type."); return NULL; } TopExp_Explorer Exp_aWhat ( aWhat, iType ); TopExp_Explorer Exp_aWhere ( aWhere, iType ); TopExp_Explorer Exp_Edge ( aWhere, TopAbs_EDGE ); // Find the shortest edge in theShapeWhere shape BRepBndLib::Add(aWhere, BoundingBox); BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); min_l = fabs(aXmax - aXmin); if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin); if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin); min_l /= dl_l; // Mantis issue 0020908 BEGIN if (!Exp_Edge.More()) { min_l = Precision::Confusion(); } // Mantis issue 0020908 END for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) { TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX); for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) { aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) ); tab_Pnt[nbVertex] = aPnt; } if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) { BRepGProp::LinearProperties(Exp_Edge.Current(), aProps); if ( aProps.Mass() < min_l ) min_l = aProps.Mass(); } } // Compute tolerances Tol_0D = dl_l; Tol_1D = dl_l * min_l; Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l); Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) ); if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion(); if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion(); if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion(); if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion(); Tol_Mass = Tol_3D; if ( iType == TopAbs_VERTEX ) Tol_Mass = Tol_0D; else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D; else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D; // Searching for the sub-shapes inside the ShapeWhere shape GEOMAlgo_GetInPlace aGIP; aGIP.SetTolerance(Tol_1D); aGIP.SetTolMass(Tol_Mass); aGIP.SetTolCG(Tol_1D); aGIP.SetArgument(aWhat); aGIP.SetShapeWhere(aWhere); aGIP.Perform(); int iErr = aGIP.ErrorStatus(); if (iErr) { SetErrorCode("Error in GEOMAlgo_GetInPlace"); return NULL; } // aGIP.IsFound() returns true only when the whole theShapeWhat // is found (as one shape or several parts). But we are also interested // in the partial result, that is why this check is commented. //if (!aGIP.IsFound()) { // SetErrorCode(NOT_FOUND_ANY); // return NULL; //} const TopTools_DataMapOfShapeListOfShape& aDMSLS = aGIP.Images(); if (!aDMSLS.IsBound(aWhat)) { SetErrorCode(NOT_FOUND_ANY); return NULL; } // the list of shapes aLSA contains the shapes // of the Shape For Search that corresponds // to the Argument aWhat const TopTools_ListOfShape& aLSA = aDMSLS.Find(aWhat); if (aLSA.Extent() == 0) { SetErrorCode(NOT_FOUND_ANY); // Not found any Results return NULL; } Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent()); TopTools_ListIteratorOfListOfShape anIterModif (aLSA); for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) { if (aWhereIndices.Contains(anIterModif.Value())) { aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value())); } else { SetErrorCode("Error: wrong sub shape returned"); return NULL; } } //Add a new object Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray); if (aResult.IsNull()) { SetErrorCode("Error in algorithm: result found, but cannot be returned."); return NULL; } if (aModifiedArray->Length() > 1) { //Set a GROUP type aResult->SetType(GEOM_GROUP); //Set a sub shape type TopoDS_Shape aFirstFound = aLSA.First(); TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType(); TDF_Label aFreeLabel = aResult->GetFreeLabel(); TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType); } //Make a Python command Handle(GEOM_Function) aFunction = aResult->GetFunction(1); GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace(" << theShapeWhere << ", " << theShapeWhat << ", True)"; SetErrorCode(OK); return aResult; } //============================================================================= /*! * case GetInPlaceOld: * default: */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld (Handle(GEOM_Object) theShapeWhere, Handle(GEOM_Object) theShapeWhat) { SetErrorCode(KO); if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL; TopoDS_Shape aWhere = theShapeWhere->GetValue(); TopoDS_Shape aWhat = theShapeWhat->GetValue(); TopoDS_Shape aPntShape; TopoDS_Vertex aVertex; if (aWhere.IsNull() || aWhat.IsNull()) { SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null."); return NULL; } Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction(); if (aWhereFunction.IsNull()) { SetErrorCode("Error: aWhereFunction is Null."); return NULL; } TopTools_IndexedMapOfShape aWhereIndices; TopExp::MapShapes(aWhere, aWhereIndices); TColStd_ListOfInteger aModifiedList; Standard_Integer aWhereIndex; Handle(TColStd_HArray1OfInteger) aModifiedArray; Handle(GEOM_Object) aResult; bool isFound = false; TopAbs_ShapeEnum iType = TopAbs_SOLID; //Standard_Real aWhat_Mass = 0., aWhere_Mass = 0.; Standard_Real tab_aWhat[4], tab_aWhere[4]; Standard_Real dl_l = 1e-3; Standard_Real min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass; Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; Bnd_Box BoundingBox; gp_Pnt aPnt, aPnt_aWhat, tab_Pnt[2]; GProp_GProps aProps; // Find the iType of the aWhat shape /* if ( aWhat.ShapeType() == TopAbs_VERTEX ) iType = TopAbs_VERTEX; else if ( aWhat.ShapeType() == TopAbs_EDGE || aWhat.ShapeType() == TopAbs_WIRE ) iType = TopAbs_EDGE; else if ( aWhat.ShapeType() == TopAbs_FACE || aWhat.ShapeType() == TopAbs_SHELL ) iType = TopAbs_FACE; else if ( aWhat.ShapeType() == TopAbs_SOLID || aWhat.ShapeType() == TopAbs_COMPSOLID ) iType = TopAbs_SOLID; else if ( aWhat.ShapeType() == TopAbs_COMPOUND ) { // Only the iType of the first shape in the compound is taken into account TopoDS_Iterator It (aWhat, Standard_False, Standard_False); if ( !It.More() ) { SetErrorCode("Error: theShapeWhat is an empty COMPOUND."); return NULL; } TopAbs_ShapeEnum compType = It.Value().ShapeType(); if ( compType == TopAbs_VERTEX ) iType = TopAbs_VERTEX; else if ( compType == TopAbs_EDGE || compType == TopAbs_WIRE ) iType = TopAbs_EDGE; else if ( compType == TopAbs_FACE || compType == TopAbs_SHELL) iType = TopAbs_FACE; else if ( compType == TopAbs_SOLID || compType == TopAbs_COMPSOLID) iType = TopAbs_SOLID; } else { SetErrorCode("Error: An attempt to extract a shape of not supported type."); return NULL; } */ iType = GetTypeOfSimplePart(aWhat); if (iType == TopAbs_SHAPE) { SetErrorCode("Error: An attempt to extract a shape of not supported type."); return NULL; } TopExp_Explorer Exp_aWhat ( aWhat, iType ); TopExp_Explorer Exp_aWhere ( aWhere, iType ); TopExp_Explorer Exp_Edge ( aWhere, TopAbs_EDGE ); // Find the shortest edge in theShapeWhere shape BRepBndLib::Add(aWhere, BoundingBox); BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); min_l = fabs(aXmax - aXmin); if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin); if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin); min_l /= dl_l; // Mantis issue 0020908 BEGIN if (!Exp_Edge.More()) { min_l = Precision::Confusion(); } // Mantis issue 0020908 END for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) { TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX); for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) { aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) ); tab_Pnt[nbVertex] = aPnt; } if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) { BRepGProp::LinearProperties(Exp_Edge.Current(), aProps); if ( aProps.Mass() < min_l ) min_l = aProps.Mass(); } } // Compute tolerances Tol_0D = dl_l; Tol_1D = dl_l * min_l; Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l); Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) ); if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion(); if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion(); if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion(); if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion(); //if (Tol_1D > 1.0) Tol_1D = 1.0; //if (Tol_2D > 1.0) Tol_2D = 1.0; //if (Tol_3D > 1.0) Tol_3D = 1.0; Tol_Mass = Tol_3D; if ( iType == TopAbs_VERTEX ) Tol_Mass = Tol_0D; else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D; else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D; // Compute the ShapeWhat Mass /* for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) { if ( iType == TopAbs_VERTEX ) { aWhat_Mass += 1; continue; } else if ( iType == TopAbs_EDGE ) BRepGProp::LinearProperties(Exp_aWhat.Current(), aProps); else if ( iType == TopAbs_FACE ) BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps); else BRepGProp::VolumeProperties(Exp_aWhat.Current(), aProps); aWhat_Mass += aProps.Mass(); } */ // Searching for the sub-shapes inside the ShapeWhere shape TopTools_MapOfShape map_aWhere; for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) { if (!map_aWhere.Add(Exp_aWhere.Current())) continue; // skip repeated shape to avoid mass addition GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt ); for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) { GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat ); if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D ) isFound = true; else { if ( (tab_aWhat[3] - tab_aWhere[3]) > Tol_Mass ) { aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape(); aVertex = TopoDS::Vertex( aPntShape ); BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() ); BRepExtrema_DistShapeShape aWhatDistance ( aVertex, Exp_aWhat.Current() ); if ( aWhereDistance.IsDone() && aWhatDistance.IsDone() && fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= Tol_1D ) { // 0020162: "EDF 961 GEOM : Getinplace is getting additionnal orthogonal faces" // aVertex must be projected to the same point on Where and on What gp_Pnt pOnWhat = aWhatDistance.PointOnShape2(1); gp_Pnt pOnWhere = aWhereDistance.PointOnShape2(1); isFound = ( pOnWhat.Distance(pOnWhere) <= Tol_1D ); if ( isFound && iType == TopAbs_FACE ) { // check normals at pOnWhat and pOnWhere const double angleTol = PI/180.; gp_Vec normToWhat = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance); gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance); if ( normToWhat * normToWhere < 0 ) normToWhat.Reverse(); isFound = ( normToWhat.Angle( normToWhere ) < angleTol ); } } } } if ( isFound ) { aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current()); aModifiedList.Append(aWhereIndex); //aWhere_Mass += tab_aWhere[3]; isFound = false; break; } } //if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass ) //break; } if (aModifiedList.Extent() == 0) { // Not found any Results SetErrorCode(NOT_FOUND_ANY); return NULL; } aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent()); TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList); for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) aModifiedArray->SetValue(imod, anIterModif.Value()); //Add a new object aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray); if (aResult.IsNull()) { SetErrorCode("Error in algorithm: result found, but cannot be returned."); return NULL; } if (aModifiedArray->Length() > 1) { //Set a GROUP type aResult->SetType(GEOM_GROUP); //Set a sub shape type TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1)); TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType(); TDF_Label aFreeLabel = aResult->GetFreeLabel(); TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType); } //Make a Python command Handle(GEOM_Function) aFunction = aResult->GetFunction(1); GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace(" << theShapeWhere << ", " << theShapeWhat << ", False)"; SetErrorCode(OK); return aResult; } //======================================================================= //function : GetInPlaceByHistory //purpose : //======================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory (Handle(GEOM_Object) theShapeWhere, Handle(GEOM_Object) theShapeWhat) { SetErrorCode(KO); if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL; TopoDS_Shape aWhere = theShapeWhere->GetValue(); TopoDS_Shape aWhat = theShapeWhat->GetValue(); if (aWhere.IsNull() || aWhat.IsNull()) return NULL; Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction(); if (aWhereFunction.IsNull()) return NULL; //Fill array of indices TopTools_IndexedMapOfShape aWhereIndices; TopExp::MapShapes(aWhere, aWhereIndices); // process shape TColStd_ListOfInteger aModifiedList; bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList); if (!isFound || aModifiedList.Extent() < 1) { SetErrorCode("Error: No history found for the sought shape or its sub-shapes."); return NULL; } Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent()); TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList); for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) { aModifiedArray->SetValue(imod, anIterModif.Value()); } //Add a new object Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray); if (aResult.IsNull()) { SetErrorCode("Error in algorithm: result found, but cannot be returned."); return NULL; } if (aModifiedArray->Length() > 1) { //Set a GROUP type aResult->SetType(GEOM_GROUP); //Set a sub shape type TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1)); TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType(); TDF_Label aFreeLabel = aResult->GetFreeLabel(); TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType); } //Make a Python command Handle(GEOM_Function) aFunction = aResult->GetFunction(1); GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory(" << theShapeWhere << ", " << theShapeWhat << ")"; SetErrorCode(OK); return aResult; } //======================================================================= //function : ShapeToDouble //purpose : used by CompareShapes::operator() //======================================================================= std::pair ShapeToDouble (const TopoDS_Shape& S, bool isOldSorting) { // Computing of CentreOfMass gp_Pnt GPoint; double Len; if (S.ShapeType() == TopAbs_VERTEX) { GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S)); Len = (double)S.Orientation(); } else { GProp_GProps GPr; // BEGIN: fix for Mantis issue 0020842 if (isOldSorting) { BRepGProp::LinearProperties(S, GPr); } else { if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) { BRepGProp::LinearProperties(S, GPr); } else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) { BRepGProp::SurfaceProperties(S, GPr); } else { BRepGProp::VolumeProperties(S, GPr); } } // END: fix for Mantis issue 0020842 GPoint = GPr.CentreOfMass(); Len = GPr.Mass(); } double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9; return std::make_pair(dMidXYZ, Len); } //======================================================================= //function : CompareShapes::operator() //purpose : used by std::sort(), called from SortShapes() //======================================================================= bool GEOMImpl_IShapesOperations::CompareShapes::operator()(const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2) { if (!myMap.IsBound(theShape1)) { myMap.Bind(theShape1, ShapeToDouble(theShape1, myIsOldSorting)); } if (!myMap.IsBound(theShape2)) { myMap.Bind(theShape2, ShapeToDouble(theShape2, myIsOldSorting)); } std::pair val1 = myMap.Find(theShape1); std::pair val2 = myMap.Find(theShape2); double tol = Precision::Confusion(); bool exchange = Standard_False; double dMidXYZ = val1.first - val2.first; if (dMidXYZ >= tol) { exchange = Standard_True; } else if (Abs(dMidXYZ) < tol) { double dLength = val1.second - val2.second; if (dLength >= tol) { exchange = Standard_True; } else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) { // PAL17233 // equal values possible on shapes such as two halves of a sphere and // a membrane inside the sphere Bnd_Box box1,box2; BRepBndLib::Add(theShape1, box1); if (!box1.IsVoid()) { BRepBndLib::Add(theShape2, box2); Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent(); if (dSquareExtent >= tol) { exchange = Standard_True; } else if (Abs(dSquareExtent) < tol) { Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2; box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9; box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9; if ((val1 - val2) >= tol) { exchange = Standard_True; } } } } } //return val1 < val2; return !exchange; } //======================================================================= //function : SortShapes //purpose : //======================================================================= void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL, const Standard_Boolean isOldSorting) { #ifdef STD_SORT_ALGO std::vector aShapesVec; aShapesVec.reserve(SL.Extent()); TopTools_ListIteratorOfListOfShape it (SL); for (; it.More(); it.Next()) { aShapesVec.push_back(it.Value()); } SL.Clear(); CompareShapes shComp (isOldSorting); std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp); //std::sort(aShapesVec.begin(), aShapesVec.end(), shComp); std::vector::const_iterator anIter = aShapesVec.begin(); for (; anIter != aShapesVec.end(); ++anIter) { SL.Append(*anIter); } #else // old implementation Standard_Integer MaxShapes = SL.Extent(); TopTools_Array1OfShape aShapes (1,MaxShapes); TColStd_Array1OfInteger OrderInd(1,MaxShapes); TColStd_Array1OfReal MidXYZ (1,MaxShapes); //X,Y,Z; TColStd_Array1OfReal Length (1,MaxShapes); //X,Y,Z; // Computing of CentreOfMass Standard_Integer Index; GProp_GProps GPr; gp_Pnt GPoint; TopTools_ListIteratorOfListOfShape it(SL); for (Index=1; it.More(); Index++) { TopoDS_Shape S = it.Value(); SL.Remove( it ); // == it.Next() aShapes(Index) = S; OrderInd.SetValue (Index, Index); if (S.ShapeType() == TopAbs_VERTEX) { GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S )); Length.SetValue( Index, (Standard_Real) S.Orientation()); } else { // BEGIN: fix for Mantis issue 0020842 if (isOldSorting) { BRepGProp::LinearProperties (S, GPr); } else { if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) { BRepGProp::LinearProperties (S, GPr); } else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) { BRepGProp::SurfaceProperties(S, GPr); } else { BRepGProp::VolumeProperties(S, GPr); } } // END: fix for Mantis issue 0020842 GPoint = GPr.CentreOfMass(); Length.SetValue(Index, GPr.Mass()); } MidXYZ.SetValue(Index, GPoint.X()*999.0 + GPoint.Y()*99.0 + GPoint.Z()*0.9); //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl; } // Sorting Standard_Integer aTemp; Standard_Boolean exchange, Sort = Standard_True; Standard_Real tol = Precision::Confusion(); while (Sort) { Sort = Standard_False; for (Index=1; Index < MaxShapes; Index++) { exchange = Standard_False; Standard_Real dMidXYZ = MidXYZ(OrderInd(Index)) - MidXYZ(OrderInd(Index+1)); Standard_Real dLength = Length(OrderInd(Index)) - Length(OrderInd(Index+1)); if ( dMidXYZ >= tol ) { // cout << "MidXYZ: " << MidXYZ(OrderInd(Index))<< " > " <= tol ) { // cout << "Length: " << Length(OrderInd(Index))<< " > " <= tol ) { // cout << "SquareExtent: " << box1.SquareExtent()<<" > "< val2; if ((val1 - val2) >= tol) { exchange = Standard_True; } //cout << "box: " << val1<<" > "<DynamicType() == C2->DynamicType()) return true; //Check that both edges has the same geometry double range = U12-U11; double U = U11+ range/3.0; gp_Pnt P1 = C1->Value(U); //Compute a point on one third of the edge's length U = U11+range*2.0/3.0; gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22) return false; if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false; if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22) return false; if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false; return true; } #include //======================================================================= //function : isSameFace //purpose : Returns True if two faces coincide //======================================================================= static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2) { TopExp_Explorer E(theFace1, TopAbs_EDGE); TopTools_ListOfShape LS1, LS2; for(; E.More(); E.Next()) LS1.Append(E.Current()); E.Init(theFace2, TopAbs_EDGE); for(; E.More(); E.Next()) LS2.Append(E.Current()); //Compare the number of edges in the faces if(LS1.Extent() != LS2.Extent()) return false; double aMin = RealFirst(), aMax = RealLast(); double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax; double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin; for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) { gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current())); if(P.X() < xminB1) xminB1 = P.X(); if(P.Y() < yminB1) yminB1 = P.Y(); if(P.Z() < zminB1) zminB1 = P.Z(); if(P.X() > xmaxB1) xmaxB1 = P.X(); if(P.Y() > ymaxB1) ymaxB1 = P.Y(); if(P.Z() > zmaxB1) zmaxB1 = P.Z(); } for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) { gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current())); if(P.X() < xminB2) xminB2 = P.X(); if(P.Y() < yminB2) yminB2 = P.Y(); if(P.Z() < zminB2) zminB2 = P.Z(); if(P.X() > xmaxB2) xmaxB2 = P.X(); if(P.Y() > ymaxB2) ymaxB2 = P.Y(); if(P.Z() > zmaxB2) zmaxB2 = P.Z(); } //Compare the bounding boxes of both faces if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE) return false; if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE) return false; Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1); Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2); //Check if there a coincidence of two surfaces at least in two points double U11, U12, V11, V12, U21, U22, V21, V22; BRepTools::UVBounds(theFace1, U11, U12, V11, V12); BRepTools::UVBounds(theFace2, U21, U22, V21, V22); double rangeU = U12-U11; double rangeV = V12-V11; double U = U11 + rangeU/3.0; double V = V11 + rangeV/3.0; gp_Pnt P1 = S1->Value(U, V); U = U11+rangeU*2.0/3.0; V = V11+rangeV*2.0/3.0; gp_Pnt P2 = S1->Value(U, V); if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22) return false; if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false; if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22) return false; if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false; //Check that each edge of the Face1 has a counterpart in the Face2 TopTools_MapOfOrientedShape aMap; TopTools_ListIteratorOfListOfShape LSI1(LS1); for(; LSI1.More(); LSI1.Next()) { TopoDS_Edge E = TopoDS::Edge(LSI1.Value()); bool isFound = false; TopTools_ListIteratorOfListOfShape LSI2(LS2); for(; LSI2.More(); LSI2.Next()) { TopoDS_Shape aValue = LSI2.Value(); if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times if(isSameEdge(E, TopoDS::Edge(aValue))) { aMap.Add(aValue); isFound = true; break; } } if(!isFound) return false; } return true; } //======================================================================= //function : isSameSolid //purpose : Returns True if two solids coincide //======================================================================= bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2) { TopExp_Explorer E(theSolid1, TopAbs_FACE); TopTools_ListOfShape LS1, LS2; for(; E.More(); E.Next()) LS1.Append(E.Current()); E.Init(theSolid2, TopAbs_FACE); for(; E.More(); E.Next()) LS2.Append(E.Current()); if(LS1.Extent() != LS2.Extent()) return false; double aMin = RealFirst(), aMax = RealLast(); double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax; double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin; for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) { gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current())); if(P.X() < xminB1) xminB1 = P.X(); if(P.Y() < yminB1) yminB1 = P.Y(); if(P.Z() < zminB1) zminB1 = P.Z(); if(P.X() > xmaxB1) xmaxB1 = P.X(); if(P.Y() > ymaxB1) ymaxB1 = P.Y(); if(P.Z() > zmaxB1) zmaxB1 = P.Z(); } for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) { gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current())); if(P.X() < xminB2) xminB2 = P.X(); if(P.Y() < yminB2) yminB2 = P.Y(); if(P.Z() < zminB2) zminB2 = P.Z(); if(P.X() > xmaxB2) xmaxB2 = P.X(); if(P.Y() > ymaxB2) ymaxB2 = P.Y(); if(P.Z() > zmaxB2) zmaxB2 = P.Z(); } //Compare the bounding boxes of both solids if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE) return false; if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE) return false; //Check that each face of the Solid1 has a counterpart in the Solid2 TopTools_MapOfOrientedShape aMap; TopTools_ListIteratorOfListOfShape LSI1(LS1); for(; LSI1.More(); LSI1.Next()) { TopoDS_Face F = TopoDS::Face(LSI1.Value()); bool isFound = false; TopTools_ListIteratorOfListOfShape LSI2(LS2); for(; LSI2.More(); LSI2.Next()) { if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times if(isSameFace(F, TopoDS::Face(LSI2.Value()))) { aMap.Add(LSI2.Value()); isFound = true; break; } } if(!isFound) return false; } return true; } //======================================================================= //function : GetSame //purpose : //======================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere, const Handle(GEOM_Object)& theShapeWhat) { SetErrorCode(KO); if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL; TopoDS_Shape aWhere = theShapeWhere->GetValue(); TopoDS_Shape aWhat = theShapeWhat->GetValue(); if (aWhere.IsNull() || aWhat.IsNull()) return NULL; int anIndex = -1; bool isFound = false; TopoDS_Shape aSubShape; TopTools_MapOfShape aMap; if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) { TopoDS_Iterator It (aWhat, Standard_True, Standard_True); if (It.More()) aWhat = It.Value(); It.Next(); if (It.More()) { SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument"); return NULL; } } switch (aWhat.ShapeType()) { case TopAbs_VERTEX: { gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat)); TopExp_Explorer E(aWhere, TopAbs_VERTEX); for(; E.More(); E.Next()) { if(!aMap.Add(E.Current())) continue; gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current())); if(P.Distance(P2) <= MAX_TOLERANCE) { isFound = true; aSubShape = E.Current(); break; } } break; } case TopAbs_EDGE: { TopoDS_Edge anEdge = TopoDS::Edge(aWhat); TopExp_Explorer E(aWhere, TopAbs_EDGE); for(; E.More(); E.Next()) { if(!aMap.Add(E.Current())) continue; if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) { aSubShape = E.Current(); isFound = true; break; } } break; } case TopAbs_FACE: { TopoDS_Face aFace = TopoDS::Face(aWhat); TopExp_Explorer E(aWhere, TopAbs_FACE); for(; E.More(); E.Next()) { if(!aMap.Add(E.Current())) continue; if(isSameFace(aFace, TopoDS::Face(E.Current()))) { aSubShape = E.Current(); isFound = true; break; } } break; } case TopAbs_SOLID: { TopoDS_Solid aSolid = TopoDS::Solid(aWhat); TopExp_Explorer E(aWhere, TopAbs_SOLID); for(; E.More(); E.Next()) { if(!aMap.Add(E.Current())) continue; if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) { aSubShape = E.Current(); isFound = true; break; } } break; } default: return NULL; } if (isFound) { TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aWhere, anIndices); if (anIndices.Contains(aSubShape)) anIndex = anIndices.FindIndex(aSubShape); } if (anIndex < 0) return NULL; Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndex); Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray); Handle(GEOM_Function) aFunction = aResult->GetLastFunction(); GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame(" << theShapeWhere << ", " << theShapeWhat << ")"; SetErrorCode(OK); return aResult; }