X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_IShapesOperations.cxx;h=199f2c0c569191aa0b8b2afd31a26333d5a36d99;hb=aa13d2abfd59ac43b3529ab5aefdd8018eb4f55e;hp=6db0d877682c98834e49c54f6896bec4c76e6d35;hpb=61b4585452cdc8fd050303862ef74fe02ab0cbbe;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx index 6db0d8776..199f2c0c5 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx @@ -1,4 +1,23 @@ -using namespace std; +// Copyright (C) 2005 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 +// +#include #include "GEOMImpl_IShapesOperations.hxx" @@ -16,8 +35,13 @@ using namespace std; #include "GEOMImpl_Block6Explorer.hxx" #include "GEOM_Function.hxx" +#include "GEOM_PythonDump.hxx" -#include "GEOMAlgo_FinderShapeOn.hxx" +#include "GEOMAlgo_FinderShapeOn1.hxx" +#include "GEOMAlgo_FinderShapeOnQuad.hxx" +#include "GEOMAlgo_FinderShapeOn2.hxx" +#include "GEOMAlgo_ClsfBox.hxx" +//#include "GEOMAlgo_ClsfSurf.hxx" #include "utilities.h" #include "OpUtil.hxx" @@ -27,19 +51,25 @@ using namespace std; #include #include #include +#include #include #include #include +#include #include #include +#include +#include #include +#include #include #include #include #include +#include #include #include #include @@ -47,6 +77,7 @@ using namespace std; #include #include #include +#include #include #include #include @@ -57,16 +88,21 @@ using namespace std; #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 //============================================================================= @@ -124,6 +160,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge //Compute the Edge value try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Vector driver failed"); return NULL; @@ -136,15 +175,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge } //Make a Python command - TCollection_AsciiString anEntry, aDescr; - TDF_Tool::Entry(anEdge->GetEntry(), anEntry); - aDescr += (anEntry+" = IShapesOperations.MakeEdge("); - TDF_Tool::Entry(thePnt1->GetEntry(), anEntry); - aDescr += (anEntry+", "); - TDF_Tool::Entry(thePnt2->GetEntry(), anEntry); - aDescr += (anEntry+")"); - - aFunction->SetDescription(aDescr); + GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge(" + << thePnt1 << ", " << thePnt2 << ")"; SetErrorCode(OK); return anEdge; @@ -195,6 +227,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) th //Compute the Face value try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to compute a face"); return NULL; @@ -207,19 +242,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) th } //Make a Python command - TCollection_AsciiString anEntry, aDescr; - TDF_Tool::Entry(aFace->GetEntry(), anEntry); - aDescr += anEntry; - aDescr += " = IShapesOperations.MakeFace("; - TDF_Tool::Entry(theWire->GetEntry(), anEntry); - aDescr += anEntry; - if (isPlanarWanted) - aDescr += ", 1)"; - - else - aDescr += ", 0)"; - - aFunction->SetDescription(aDescr); + GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace(" + << theWire << ", " << (int)isPlanarWanted << ")"; SetErrorCode(OK); return aFace; @@ -267,6 +291,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires //Compute the shape try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; @@ -279,28 +306,18 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires } //Make a Python command - TCollection_AsciiString anEntry, aDescr; - TDF_Tool::Entry(aShape->GetEntry(), anEntry); - aDescr += (anEntry + " = IShapesOperations.MakeFaceWires(["); + GEOM::TPythonDump pd (aFunction); + pd << aShape << " = geompy.MakeFaceWires(["; + // Shapes it = theShapes.begin(); if (it != theShapes.end()) { - TDF_Tool::Entry((*it)->GetEntry(), anEntry); - it++; - aDescr += (anEntry+", "); - for (; it != theShapes.end(); it++) { - aDescr += ", "; - TDF_Tool::Entry((*it)->GetEntry(), anEntry); - aDescr += anEntry; + pd << (*it++); + while (it != theShapes.end()) { + pd << ", " << (*it++); } } - if (isPlanarWanted) - aDescr += "], 1)"; - - else - aDescr += "], 0)"; - - aFunction->SetDescription(aDescr); + pd << "], " << (int)isPlanarWanted << ")"; SetErrorCode(OK); return aShape; @@ -325,7 +342,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells (list theShapes) { - return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolidShells"); + return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid"); } //============================================================================= @@ -360,6 +377,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Obje //Compute the Solid value try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Solid driver failed"); return NULL; @@ -372,14 +392,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Obje } //Make a Python command - TCollection_AsciiString anEntry, aDescr(""); - TDF_Tool::Entry(aSolid->GetEntry(), anEntry); - aDescr += anEntry; - aDescr += " = IShapesOperations.MakeSolidShell("; - TDF_Tool::Entry(theShell->GetEntry(), anEntry); - aDescr += (anEntry+")"); - - aFunction->SetDescription(aDescr); + GEOM::TPythonDump(aFunction) << aSolid + << " = geompy.MakeSolid(" << theShell << ")"; SetErrorCode(OK); return aSolid; @@ -402,10 +416,10 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape - (list theShapes, - const Standard_Integer theObjectType, - const Standard_Integer theFunctionType, - const TCollection_AsciiString theMethodName) + (list theShapes, + const Standard_Integer theObjectType, + const Standard_Integer theFunctionType, + const TCollection_AsciiString& theMethodName) { SetErrorCode(KO); @@ -438,6 +452,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape //Compute the shape try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; @@ -450,25 +467,18 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape } //Make a Python command - TCollection_AsciiString anEntry, aDescr(""); - TDF_Tool::Entry(aShape->GetEntry(), anEntry); - aDescr += (anEntry + " = IShapesOperations."); - aDescr += (theMethodName + "(["); + GEOM::TPythonDump pd (aFunction); + pd << aShape << " = geompy." << theMethodName.ToCString() << "(["; + // Shapes it = theShapes.begin(); if (it != theShapes.end()) { - TDF_Tool::Entry((*it)->GetEntry(), anEntry); - it++; - aDescr += (anEntry+", "); - for (; it != theShapes.end(); it++) { - aDescr += ", "; - TDF_Tool::Entry((*it)->GetEntry(), anEntry); - aDescr += anEntry; + pd << (*it++); + while (it != theShapes.end()) { + pd << ", " << (*it++); } } - aDescr += "])"; - - aFunction->SetDescription(aDescr); + pd << "])"; SetErrorCode(OK); return aShape; @@ -509,6 +519,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to glue faces"); return NULL; @@ -526,15 +539,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces } //Make a Python command - TCollection_AsciiString anEntry, aDescr; - TDF_Tool::Entry(aGlued->GetEntry(), anEntry); - aDescr += anEntry; - aDescr += " = IShapesOperations.MakeGlueFaces("; - TDF_Tool::Entry(theShape->GetEntry(), anEntry); - aDescr += anEntry + ", "; - aDescr += TCollection_AsciiString(theTolerance) + ")"; - - aFunction->SetDescription(aDescr); + GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces(" + << theShape << ", " << theTolerance << ")"; // to provide warning if (!isWarning) SetErrorCode(OK); @@ -551,9 +557,6 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode const Standard_Integer theShapeType, const Standard_Boolean isSorted) { -// OSD_Timer timer1, timer2, timer3, timer4; -// timer1.Start(); - SetErrorCode(KO); if (theShape.IsNull()) return NULL; @@ -591,21 +594,15 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode return aSeq; } -// timer1.Stop(); -// timer2.Start(); - if (isSorted) SortShapes(listShape); -// timer2.Stop(); -// timer3.Start(); - TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); Handle(TColStd_HArray1OfInteger) anArray; TopTools_ListIteratorOfListOfShape itSub (listShape); - TCollection_AsciiString anAsciiList = "[", anEntry; + TCollection_AsciiString anAsciiList, anEntry; for (int index = 1; itSub.More(); itSub.Next(), ++index) { TopoDS_Shape aValue = itSub.Value(); anArray = new TColStd_HArray1OfInteger(1,1); @@ -613,49 +610,24 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode anObj = GetEngine()->AddSubShape(theShape, anArray); aSeq->Append(anObj); + // for python command TDF_Tool::Entry(anObj->GetEntry(), anEntry); anAsciiList += anEntry; anAsciiList += ","; } -// timer3.Stop(); -// timer4.Start(); - + //Make a Python command anAsciiList.Trunc(anAsciiList.Length() - 1); - anAsciiList += "]"; - anAsciiList = TCollection_AsciiString("\n") + anAsciiList; - - //The explode doesn't change object so no new function is requiered. aFunction = theShape->GetLastFunction(); - //Make a Python command - TCollection_AsciiString aDescr(anAsciiList); - TDF_Tool::Entry(theShape->GetEntry(), anEntry); - aDescr += " = IShapesOperations.MakeExplode("; - aDescr += (anEntry + ","); - if (isSorted) - aDescr += (TCollection_AsciiString(theShapeType) + ", 1)"); - else - aDescr += (TCollection_AsciiString(theShapeType) + ", 0)"); - - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - anOldDescr = anOldDescr + aDescr; - aFunction->SetDescription(anOldDescr); + GEOM::TPythonDump pd (aFunction, /*append=*/true); + pd << "[" << anAsciiList.ToCString(); + pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "("); + pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; SetErrorCode(OK); -// timer4.Stop(); - -// cout << "Explosure takes:" << endl; -// timer1.Show(); -// cout << "Sorting takes:" << endl; -// timer2.Show(); -// cout << "Sub-shapes addition takes:" << endl; -// timer3.Show(); -// cout << "Update Description takes:" << endl; -// timer4.Show(); - return aSeq; } @@ -717,23 +689,13 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs aSeq->Append(anIndices.FindIndex(aValue)); } - //The explode doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command - TCollection_AsciiString aDescr - ("\nlistSubShapeAllIDs = IShapesOperations.SubShapeAllIDs("); - TCollection_AsciiString anEntry; - TDF_Tool::Entry(theShape->GetEntry(), anEntry); - aDescr += (anEntry + ","); - if (isSorted) - aDescr += (TCollection_AsciiString(theShapeType) + ", 1)"); - else - aDescr += (TCollection_AsciiString(theShapeType) + ", 0)"); - - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - anOldDescr = anOldDescr + aDescr; - aFunction->SetDescription(anOldDescr); + GEOM::TPythonDump pd (aFunction, /*append=*/true); + pd << "listSubShapeIDs = geompy.SubShapeAll"; + pd << (isSorted ? "SortedIDs(" : "IDs("); + pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; SetErrorCode(OK); return aSeq; @@ -754,32 +716,179 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, theID); - Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray); + 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; } - //The GetSubShape() doesn't change object so no new function is requiered. - Handle(GEOM_Function) aFunction = theMainShape->GetLastFunction(); + Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); //Make a Python command - TCollection_AsciiString aDescr ("\n"); - TCollection_AsciiString anEntry; - TDF_Tool::Entry(anObj->GetEntry(), anEntry); - aDescr += anEntry + " = IShapesOperations.GetSubShape("; - TDF_Tool::Entry(theMainShape->GetEntry(), anEntry); - aDescr += anEntry + ", "; - aDescr += TCollection_AsciiString(theID) + ")"; - - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - anOldDescr = anOldDescr + aDescr; - aFunction->SetDescription(anOldDescr); + GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape(" + << theMainShape << ", [" << theID << "])"; SetErrorCode(OK); return anObj; } +//============================================================================= +/*! + * 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; +} + //============================================================================= /*! @@ -864,6 +973,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) //Compute the sub-shape value try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to reverse shape"); return NULL; @@ -876,14 +988,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) } //Make a Python command - TCollection_AsciiString anEntry, aDescr; - TDF_Tool::Entry(aReversed->GetEntry(), anEntry); - aDescr += anEntry; - aDescr += " = IShapesOperations.ReverseShape("; - TDF_Tool::Entry(theShape->GetEntry(), anEntry); - aDescr += anEntry + ")"; - - aFunction->SetDescription(aDescr); + GEOM::TPythonDump(aFunction) << aReversed + << " = geompy.ChangeOrientation(" << theShape << ")"; SetErrorCode(OK); return aReversed; @@ -931,24 +1037,18 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command - TCollection_AsciiString aDescr ("\nlistFreeFacesIDs = IShapesOperations.GetFreeFacesIDs("); - TCollection_AsciiString anEntry; - TDF_Tool::Entry(theShape->GetEntry(), anEntry); - aDescr += (anEntry + ")"); - - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - anOldDescr = anOldDescr + aDescr; - aFunction->SetDescription(anOldDescr); + GEOM::TPythonDump(aFunction, /*append=*/true) + << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")"; SetErrorCode(OK); return aSeq; } -//============================================================================= -/*! - * GetSharedShapes - */ -//============================================================================= +//======================================================================= +//function : GetSharedShapes +//purpose : +//======================================================================= + Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2, @@ -972,6 +1072,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes 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)); @@ -982,6 +1083,11 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes 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 += ","; } } @@ -990,22 +1096,14 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes return aSeq; } - //The explode doesn't change object so no new function is required. - Handle(GEOM_Function) aFunction = theShape1->GetLastFunction(); - //Make a Python command - TCollection_AsciiString aDescr - ("\nlistSharedShapes = IShapesOperations.GetSharedShapes("); - TCollection_AsciiString anEntry; - TDF_Tool::Entry(theShape1->GetEntry(), anEntry); - aDescr += (anEntry + ","); - TDF_Tool::Entry(theShape2->GetEntry(), anEntry); - aDescr += (anEntry + ","); - aDescr += TCollection_AsciiString(theShapeType) + ")"; - - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - anOldDescr = anOldDescr + aDescr; - aFunction->SetDescription(anOldDescr); + 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; @@ -1013,33 +1111,67 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes //============================================================================= /*! - * 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) +static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump, + const GEOMAlgo_State theState) { - SetErrorCode(KO); - - if (theShape.IsNull() || theAx1.IsNull()) return NULL; - - TopoDS_Shape aShape = theShape->GetValue(); - TopoDS_Shape anAx1 = theAx1->GetValue(); + 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; +} - if (aShape.IsNull() || anAx1.IsNull()) return NULL; +//======================================================================= +//function : checkTypeShapesOn +/*! + * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK + * \param theShapeType - the shape type to check + * \retval bool - result of the check + */ +//======================================================================= - TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); - if (aShapeType != TopAbs_VERTEX && - aShapeType != TopAbs_EDGE && - aShapeType != TopAbs_FACE) { - SetErrorCode("Only vertices, edges or faces can be found by this method"); - return NULL; +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; +} - // Create plane +//======================================================================= +//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; @@ -1054,33 +1186,95 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlan 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; - Handle(Geom_Plane) aPlane = new Geom_Plane(aLoc, aVec); + TopoDS_Shape aBox = theBox->GetValue(); + TopoDS_Shape aShape = theShape->GetValue(); // Call algo - GEOMAlgo_FinderShapeOn aFinder; + 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.SetSurface(aPlane); - aFinder.SetShapeType(aShapeType); + 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_FinderShapeOn.cxx + // 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 NULL; + return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx + // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx if (iWrn) { MESSAGE(" *** iWrn : " << iWrn); } @@ -1088,123 +1282,171 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlan 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 plane"); - return NULL; + SetErrorCode("Not a single sub-shape of the requested type found on the given surface"); + return aSeqOfIDs; } - // Fill sequence of objects + // Fill sequence of object IDs + aSeqOfIDs = new TColStd_HSequenceOfInteger; + TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); - Handle(GEOM_Object) anObj; - Handle(TColStd_HArray1OfInteger) anArray; - Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; - TopTools_ListIteratorOfListOfShape itSub (listSS); for (int index = 1; itSub.More(); itSub.Next(), ++index) { int id = anIndices.FindIndex(itSub.Value()); - anArray = new TColStd_HArray1OfInteger(1,1); - anArray->SetValue(1, id); - anObj = GetEngine()->AddSubShape(theShape, anArray); - aSeq->Append(anObj); + aSeqOfIDs->Append(id); } - - // The GetShapesOnPlane() doesn't change object so no new function is required. - Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); + + 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 - TCollection_AsciiString anEntry, aDescr - ("\nlistShapesOnPlane = IShapesOperations.GetShapesOnPlane("); - TDF_Tool::Entry(theShape->GetEntry(), anEntry); - aDescr += anEntry + TCollection_AsciiString(theShapeType) + ","; - TDF_Tool::Entry(theAx1->GetEntry(), anEntry); - aDescr += anEntry + ","; - aDescr += TCollection_AsciiString(theState) + ")"; - - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - anOldDescr += aDescr; - aFunction->SetDescription(anOldDescr); + GEOM::TPythonDump(aFunction) + << "listShapesOnBoxIDs = geompy.GetShapesOnQuadrangleIDs(" + << theBox << ", " + << theShape << ", " + << TopAbs_ShapeEnum(theShapeType) << ", " + << theState << ")"; SetErrorCode(OK); - return aSeq; + return aSeqOfIDs; } -//============================================================================= +//======================================================================= +//function : GetShapesOnBox /*! - * GetShapesOnCylinder + * \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::GetShapesOnCylinder - (const Handle(GEOM_Object)& theShape, - const Standard_Integer theShapeType, - const Handle(GEOM_Object)& theAxis, - const Standard_Real theRadius, - const GEOMAlgo_State theState) +//======================================================================= + +Handle(TColStd_HSequenceOfTransient) + GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox, + const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + GEOMAlgo_State theState) { - SetErrorCode(KO); + // Find subshapes ids + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = + getShapesOnBoxIDs (theBox, theShape, theShapeType, theState); + if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) + return NULL; - if (theShape.IsNull() || theAxis.IsNull()) 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_Shape aShape = theShape->GetValue(); - TopoDS_Shape anAxis = theAxis->GetValue(); + // Make a Python command - if (aShape.IsNull() || anAxis.IsNull()) return NULL; + Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); + Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); - TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); - if (aShapeType != TopAbs_VERTEX && - aShapeType != TopAbs_EDGE && - aShapeType != TopAbs_FACE) { - SetErrorCode("Only vertices, edges or faces can be found by this method"); - return NULL; - } + GEOM::TPythonDump(aFunction) + << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox(" + << theBox << ", " + << theShape << ", " + << TopAbs_ShapeEnum(theShapeType) << ", " + << theState << ")"; - //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; - } + SetErrorCode(OK); + return aSeq; +} - gp_Ax3 anAx3 (aLoc, aVec); - Handle(Geom_CylindricalSurface) aCylinder = - new Geom_CylindricalSurface(anAx3, theRadius); + +//======================================================================= +//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)) + return aSeqOfIDs; // Call algo - GEOMAlgo_FinderShapeOn aFinder; + GEOMAlgo_FinderShapeOn1 aFinder; Standard_Real aTol = 0.0001; // default value - aFinder.SetShape(aShape); + aFinder.SetShape(theShape); aFinder.SetTolerance(aTol); - aFinder.SetSurface(aCylinder); - aFinder.SetShapeType(aShapeType); + 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_FinderShapeOn.cxx + // 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 NULL; + return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx + // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx if (iWrn) { MESSAGE(" *** iWrn : " << iWrn); } @@ -1212,43 +1454,258 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCyli 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 cylinder"); - return NULL; + SetErrorCode("Not a single sub-shape of the requested type found on the given surface"); + return aSeqOfIDs; } - // Fill sequence of objects - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aShape, anIndices); + // Fill sequence of object IDs + aSeqOfIDs = new TColStd_HSequenceOfInteger; - Handle(GEOM_Object) anObj; - Handle(TColStd_HArray1OfInteger) anArray; - Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; + 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()); - anArray = new TColStd_HArray1OfInteger(1,1); - anArray->SetValue(1, id); - anObj = GetEngine()->AddSubShape(theShape, anArray); - aSeq->Append(anObj); + aSeqOfIDs->Append(id); } - - // The GetShapesOnCylinder() doesn't change object so no new function is required. - Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); + + 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 - TCollection_AsciiString anEntry, aDescr - ("\nlistShapesOnCylinder = IShapesOperations.GetShapesOnCylinder("); - TDF_Tool::Entry(theShape->GetEntry(), anEntry); - aDescr += anEntry + TCollection_AsciiString(theShapeType) + ","; - TDF_Tool::Entry(theAxis->GetEntry(), anEntry); - aDescr += anEntry + ","; - aDescr += TCollection_AsciiString(theRadius) + ","; - aDescr += TCollection_AsciiString(theState) + ")"; - - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - anOldDescr += aDescr; - aFunction->SetDescription(anOldDescr); + + 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; @@ -1276,12 +1733,220 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphe if (aShape.IsNull() || aCenter.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); - if (aShapeType != TopAbs_VERTEX && - aShapeType != TopAbs_EDGE && - aShapeType != TopAbs_FACE) { - SetErrorCode("Only vertices, edges or faces can be found by this method"); + 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; +} + +//============================================================================= +/*! + * 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; @@ -1291,30 +1956,122 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphe 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)) + return aSeqOfIDs; + // Call algo - GEOMAlgo_FinderShapeOn aFinder; + 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(aSphere); + //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_FinderShapeOn.cxx + // 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 NULL; + return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx + // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx if (iWrn) { MESSAGE(" *** iWrn : " << iWrn); } @@ -1322,53 +2079,232 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphe 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 sphere"); - return NULL; + SetErrorCode("Not a single sub-shape of the requested type found on the given surface"); + return aSeqOfIDs; } - // Fill sequence of objects + // Fill sequence of object IDs + aSeqOfIDs = new TColStd_HSequenceOfInteger; + TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); - Handle(GEOM_Object) anObj; - Handle(TColStd_HArray1OfInteger) anArray; - Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; - TopTools_ListIteratorOfListOfShape itSub (listSS); for (int index = 1; itSub.More(); itSub.Next(), ++index) { int id = anIndices.FindIndex(itSub.Value()); - anArray = new TColStd_HArray1OfInteger(1,1); - anArray->SetValue(1, id); - anObj = GetEngine()->AddSubShape(theShape, anArray); - aSeq->Append(anObj); + aSeqOfIDs->Append(id); } - - // The GetShapesOnSphere() doesn't change object so no new function is required. - Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); + 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 - TCollection_AsciiString anEntry, aDescr - ("\nlistShapesOnSphere = IShapesOperations.GetShapesOnSphere("); - TDF_Tool::Entry(theShape->GetEntry(), anEntry); - aDescr += anEntry + TCollection_AsciiString(theShapeType) + ","; - TDF_Tool::Entry(theCenter->GetEntry(), anEntry); - aDescr += anEntry + ","; - aDescr += TCollection_AsciiString(theRadius) + ","; - aDescr += TCollection_AsciiString(theState) + ")"; - - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - anOldDescr += aDescr; - aFunction->SetDescription(anOldDescr); + + 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; +} + + //============================================================================= /*! * GetInPlace */ //============================================================================= +static void SimplifyWhat (TopoDS_Shape& theWhat, + TopTools_IndexedMapOfShape& theArgumentIndices, + TColStd_ListOfInteger& theSimpleSubWhat) +{ + TopTools_MapOfShape mapShape; + TopoDS_Iterator It (theWhat, Standard_True, Standard_True); + for (; It.More(); It.Next()) { + if (mapShape.Add(It.Value())) { + TopoDS_Shape curSh = It.Value(); + if (curSh.ShapeType() == TopAbs_COMPOUND || + curSh.ShapeType() == TopAbs_COMPSOLID) { + SimplifyWhat(curSh, theArgumentIndices, theSimpleSubWhat); + } else { + theSimpleSubWhat.Append(theArgumentIndices.FindIndex(curSh)); + } + } + } +} + +static bool GetInPlaceOfCompound (Handle(GEOM_Function)& theWhereFunction, + TopoDS_Shape& theWhat, + TColStd_ListOfInteger& theModifiedArray) +{ + bool isFoundAny = false; + TopTools_MapOfShape mapShape; + TopoDS_Iterator It (theWhat, Standard_True, Standard_True); + for (; It.More(); It.Next()) { + if (mapShape.Add(It.Value())) { + TopoDS_Shape curWhat = It.Value(); + if (curWhat.ShapeType() == TopAbs_COMPOUND || + curWhat.ShapeType() == TopAbs_COMPSOLID) { + // Recursive call for compound or compsolid + if (GetInPlaceOfCompound(theWhereFunction, curWhat, theModifiedArray)) + isFoundAny = true; + } else { + // Try to find for "simple" shape + bool isFound = 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(curWhat)) { + isFound = Standard_True; + Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(curWhat); + + // Find corresponding label in history + TDF_Label anArgumentHistoryLabel = + theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False); + if (!anArgumentHistoryLabel.IsNull()) { + TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False); + if (!aWhatHistoryLabel.IsNull()) { + Handle(TDataStd_IntegerArray) anIntegerArray; + if (aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) { + Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length(); + for (imod = 1; imod <= aModifLen; imod++) { + theModifiedArray.Append(anIntegerArray->Array()->Value(imod)); + } + } + } + } + } + } + if (isFound) + isFoundAny = true; + } + } + } + return isFoundAny; +} + Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere, Handle(GEOM_Object) theShapeWhat) @@ -1383,46 +2319,165 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace if (aWhere.IsNull() || aWhat.IsNull()) return NULL; //Fill array of indices - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aWhere, anIndices); - -// Handle(TColStd_HArray1OfInteger) anArray = -// new TColStd_HArray1OfInteger (1, listSS.Extent()); -// TopTools_ListIteratorOfListOfShape itSub (listSS); -// for (int index = 1; itSub.More(); itSub.Next(), ++index) { -// int id = anIndices.FindIndex(itSub.Value()); -// anArray->SetValue(index, id); -// } -// -// //Add a new group object -// Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(theShape, anArray); -// -// //Set a GROUP type -// aGroup->SetType(GEOM_GROUP); -// -// //Set a sub shape type -// TDF_Label aFreeLabel = aGroup->GetFreeLabel(); -// TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)theShapeType); -// -// //Make a Python command -// TCollection_AsciiString anEntry, aDescr; -// TDF_Tool::Entry(aGroup->GetEntry(), anEntry); -// aDescr += anEntry; -// aDescr += " = IShapesOperations.GetInPlace("; -// TDF_Tool::Entry(theShapeWhere->GetEntry(), anEntry); -// aDescr += anEntry + ","; -// TDF_Tool::Entry(theShapeWhat->GetEntry(), anEntry); -// aDescr += anEntry + ")"; -// -// Handle(GEOM_Function) aFunction = aGroup->GetFunction(1); -// aFunction->SetDescription(aDescr); + Handle(TColStd_HArray1OfInteger) aModifiedArray; -// SetErrorCode(OK); -// return aGroup; - SetErrorCode("Not yet implemented"); - return NULL; -} + Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction(); + + TopTools_IndexedMapOfShape aWhereIndices; + TopExp::MapShapes(aWhere, aWhereIndices); + + if (aWhereIndices.Contains(aWhat)) { + + // entity was not changed by the operation + Standard_Integer aWhatIndex = aWhereIndices.FindIndex(aWhat); + aModifiedArray = new TColStd_HArray1OfInteger(1,1); + aModifiedArray->SetValue(1, aWhatIndex); + + } else { + + TDF_Label aHistoryLabel = aWhereFunction->GetHistoryEntry(Standard_False); + if (aHistoryLabel.IsNull()) { + SetErrorCode("Modifications history does not exist for the shape under consideration."); + return NULL; + } + // search in history for all argument shapes + Standard_Boolean isFound = Standard_False; + + TDF_LabelSequence aLabelSeq; + aWhereFunction->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(aWhat)) { + isFound = Standard_True; + Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(aWhat); + + // Find corresponding label in history + TDF_Label anArgumentHistoryLabel = + aWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False); + if (anArgumentHistoryLabel.IsNull()) { + // Lost History of operation argument. Possibly, all its entities was removed. + SetErrorCode(OK); + return NULL; + } + + TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False); + if (aWhatHistoryLabel.IsNull()) { + // Check, if the sought shape is Compound or Compsolid. + // In that case we will try to find history for its sub-shapes + if (aWhat.ShapeType() == TopAbs_COMPOUND || + aWhat.ShapeType() == TopAbs_COMPSOLID) { + TColStd_ListOfInteger aSimpleSubWhat, aModifiedList; + SimplifyWhat(aWhat, anArgumentIndices, aSimpleSubWhat); + TColStd_ListIteratorOfListOfInteger anIterSub (aSimpleSubWhat); + for (; anIterSub.More(); anIterSub.Next()) { + Standard_Integer aSubWhatIndex = anIterSub.Value(); + TDF_Label aSubWhatHistoryLabel = + anArgumentHistoryLabel.FindChild(aSubWhatIndex, Standard_False); + if (!aSubWhatHistoryLabel.IsNull()) { + Handle(TDataStd_IntegerArray) anIntegerArray; + if (aSubWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) { + for (Standard_Integer isub = 1; isub <= anIntegerArray->Length(); isub++) { + aModifiedList.Append(anIntegerArray->Value(isub)); + } + } + } + } + if (aModifiedList.Extent() > 0) { + Handle(TColStd_HArray1OfInteger) aModifiedArraySub = + new TColStd_HArray1OfInteger (1, aModifiedList.Extent()); + TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList); + for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) { + aModifiedArraySub->SetValue(imod, anIterModif.Value()); + } + aModifiedArray = aModifiedArraySub; + } else { + // Removed entity + SetErrorCode(OK); + return NULL; + } + } else { + // Removed entity + SetErrorCode(OK); + return NULL; + } + } else { + Handle(TDataStd_IntegerArray) anIntegerArray; + if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) { + SetErrorCode("Error: Empty modifications history for the sought shape."); + return NULL; + } + + aModifiedArray = anIntegerArray->Array(); + if (aModifiedArray->Length() == 0) { + SetErrorCode("Error: Empty modifications history for the sought shape."); + return NULL; + } + } + } + } + + if (!isFound) { + // try compound element by element + if (aWhat.ShapeType() == TopAbs_COMPOUND || + aWhat.ShapeType() == TopAbs_COMPSOLID) { + TColStd_ListOfInteger aModifiedList; + isFound = GetInPlaceOfCompound(aWhereFunction, aWhat, aModifiedList); + if (isFound) { + if (aModifiedList.Extent() < 1) { + SetErrorCode("Error: Empty modifications history for all sub-shapes of the sought shape."); + 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()); + } + } + } + if (!isFound) { + SetErrorCode("The sought shape does not belong to any operation argument."); + 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 + TDF_Label aFreeLabel = aResult->GetFreeLabel(); + TopAbs_ShapeEnum aShapeType = aWhat.ShapeType(); + 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 << ")"; + + SetErrorCode(OK); + return aResult; +} //======================================================================= //function : SortShapes @@ -1461,6 +2516,7 @@ void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL) MidXYZ.SetValue(Index, GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9); } + // Sorting Standard_Integer aTemp; Standard_Boolean exchange, Sort = Standard_True; @@ -1488,3 +2544,358 @@ void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL) for (Index=1; Index <= MaxShapes; Index++) SL.Append( aShapes( OrderInd(Index) )); } + +//======================================================================= +//function : CheckTriangulation +//purpose : +//======================================================================= +bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape) +{ + TopExp_Explorer exp (aShape, TopAbs_FACE); + if (!exp.More()) { + SetErrorCode("Shape without faces given"); + return false; + } + + TopLoc_Location aTopLoc; + Handle(Poly_Triangulation) aTRF; + aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc); + if (aTRF.IsNull()) { + // calculate deflection + Standard_Real aDeviationCoefficient = 0.001; + + Bnd_Box B; + BRepBndLib::Add(aShape, B); + Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; + B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); + + Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin; + Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4; + Standard_Real aHLRAngle = 0.349066; + + BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle); + } + + return true; +} + +#define MAX_TOLERANCE 1.e-7 + + +//======================================================================= +//function : isSameEdge +//purpose : Returns True if two edges coincide +//======================================================================= +static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2) +{ + TopoDS_Vertex V11, V12, V21, V22; + TopExp::Vertices(theEdge1, V11, V12); + TopExp::Vertices(theEdge2, V21, V22); + gp_Pnt P11 = BRep_Tool::Pnt(V11); + gp_Pnt P12 = BRep_Tool::Pnt(V12); + gp_Pnt P21 = BRep_Tool::Pnt(V21); + gp_Pnt P22 = BRep_Tool::Pnt(V22); + bool coincide = false; + + //Check that ends of edges coincide + if(P11.Distance(P21) <= MAX_TOLERANCE) { + if(P12.Distance(P22) <= MAX_TOLERANCE) coincide = true; + } + else if(P11.Distance(P22) <= MAX_TOLERANCE) { + if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true; + } + + if(!coincide) return false; + + double U11, U12, U21, U22; + Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12); + Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22); + if(C1->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; + + //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; + } + + Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1); + Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2); + if(S1->DynamicType() == S2->DynamicType()) { + return true; + } + else { //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; + } + + 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; + + 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_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_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_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; +}