1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include <Standard_Stream.hxx>
22 #include "GEOMImpl_IShapesOperations.hxx"
24 #include "GEOMImpl_Types.hxx"
26 #include "GEOMImpl_VectorDriver.hxx"
27 #include "GEOMImpl_ShapeDriver.hxx"
28 #include "GEOMImpl_CopyDriver.hxx"
29 #include "GEOMImpl_GlueDriver.hxx"
31 #include "GEOMImpl_IVector.hxx"
32 #include "GEOMImpl_IShapes.hxx"
33 #include "GEOMImpl_IGlue.hxx"
35 #include "GEOMImpl_Block6Explorer.hxx"
37 #include "GEOM_Function.hxx"
38 #include "GEOM_PythonDump.hxx"
40 #include "GEOMAlgo_FinderShapeOn1.hxx"
41 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
42 #include "GEOMAlgo_FinderShapeOn2.hxx"
43 #include "GEOMAlgo_ClsfBox.hxx"
44 //#include "GEOMAlgo_ClsfSurf.hxx"
46 #include "utilities.h"
48 #include "Utils_ExceptHandlers.hxx"
50 #include <TFunction_DriverTable.hxx>
51 #include <TFunction_Driver.hxx>
52 #include <TFunction_Logbook.hxx>
53 #include <TDataStd_Integer.hxx>
54 #include <TDataStd_IntegerArray.hxx>
55 #include <TDF_Tool.hxx>
57 #include <BRepExtrema_ExtCF.hxx>
59 #include <BRep_Tool.hxx>
60 #include <BRepTools.hxx>
61 #include <BRepGProp.hxx>
62 #include <BRepAdaptor_Curve.hxx>
63 #include <BRepAdaptor_Surface.hxx>
64 #include <BRepBndLib.hxx>
65 #include <BRepBuilderAPI_MakeFace.hxx>
66 #include <BRepMesh_IncrementalMesh.hxx>
71 #include <TopoDS_Shape.hxx>
72 #include <TopoDS_Solid.hxx>
73 #include <TopoDS_Face.hxx>
74 #include <TopoDS_Edge.hxx>
75 #include <TopoDS_Vertex.hxx>
76 #include <TopoDS_Iterator.hxx>
77 #include <TopExp_Explorer.hxx>
78 #include <TopLoc_Location.hxx>
79 #include <TopTools_MapOfShape.hxx>
80 #include <TopTools_MapOfOrientedShape.hxx>
81 #include <TopTools_Array1OfShape.hxx>
82 #include <TopTools_ListIteratorOfListOfShape.hxx>
83 #include <TopTools_IndexedMapOfShape.hxx>
85 #include <Geom_Surface.hxx>
86 #include <Geom_Plane.hxx>
87 #include <Geom_SphericalSurface.hxx>
88 #include <Geom_CylindricalSurface.hxx>
89 #include <GeomAdaptor_Surface.hxx>
91 #include <GeomLib_Tool.hxx>
92 #include <Geom2d_Curve.hxx>
94 #include <Bnd_Box.hxx>
95 #include <GProp_GProps.hxx>
98 #include <TColStd_ListOfInteger.hxx>
99 #include <TColStd_ListIteratorOfListOfInteger.hxx>
100 #include <TColStd_Array1OfReal.hxx>
101 #include <TColStd_HArray1OfInteger.hxx>
105 #include <Standard_Failure.hxx>
106 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
108 //=============================================================================
112 //=============================================================================
113 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
114 : GEOM_IOperations(theEngine, theDocID)
116 MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
119 //=============================================================================
123 //=============================================================================
124 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
126 MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
130 //=============================================================================
134 //=============================================================================
135 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
136 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
140 if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
142 //Add a new Edge object
143 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
145 //Add a new Vector function
146 Handle(GEOM_Function) aFunction =
147 anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
149 //Check if the function is set correctly
150 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
152 GEOMImpl_IVector aPI (aFunction);
154 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
155 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
156 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
158 aPI.SetPoint1(aRef1);
159 aPI.SetPoint2(aRef2);
161 //Compute the Edge value
163 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
166 if (!GetSolver()->ComputeFunction(aFunction)) {
167 SetErrorCode("Vector driver failed");
171 catch (Standard_Failure) {
172 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
173 SetErrorCode(aFail->GetMessageString());
177 //Make a Python command
178 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
179 << thePnt1 << ", " << thePnt2 << ")";
185 //=============================================================================
189 //=============================================================================
190 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
191 (list<Handle(GEOM_Object)> theShapes)
193 return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
196 //=============================================================================
200 //=============================================================================
201 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
202 const bool isPlanarWanted)
206 if (theWire.IsNull()) return NULL;
208 //Add a new Face object
209 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
211 //Add a new Shape function for creation of a face from a wire
212 Handle(GEOM_Function) aFunction =
213 aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
214 if (aFunction.IsNull()) return NULL;
216 //Check if the function is set correctly
217 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
219 GEOMImpl_IShapes aCI (aFunction);
221 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
223 if (aRefWire.IsNull()) return NULL;
225 aCI.SetBase(aRefWire);
226 aCI.SetIsPlanar(isPlanarWanted);
228 //Compute the Face value
230 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
233 if (!GetSolver()->ComputeFunction(aFunction)) {
234 SetErrorCode("Shape driver failed to compute a face");
238 catch (Standard_Failure) {
239 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
240 SetErrorCode(aFail->GetMessageString());
244 //Make a Python command
245 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
246 << theWire << ", " << (int)isPlanarWanted << ")";
252 //=============================================================================
256 //=============================================================================
257 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
258 (list<Handle(GEOM_Object)> theShapes,
259 const bool isPlanarWanted)
264 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
267 Handle(GEOM_Function) aFunction =
268 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
269 if (aFunction.IsNull()) return NULL;
271 //Check if the function is set correctly
272 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
274 GEOMImpl_IShapes aCI (aFunction);
276 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
279 list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
280 for (; it != theShapes.end(); it++) {
281 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
282 if (aRefSh.IsNull()) {
283 SetErrorCode("NULL argument shape for the face construction");
286 aShapesSeq->Append(aRefSh);
288 aCI.SetShapes(aShapesSeq);
290 aCI.SetIsPlanar(isPlanarWanted);
294 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
297 if (!GetSolver()->ComputeFunction(aFunction)) {
298 SetErrorCode("Shape driver failed");
302 catch (Standard_Failure) {
303 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
304 SetErrorCode(aFail->GetMessageString());
308 //Make a Python command
309 GEOM::TPythonDump pd (aFunction);
310 pd << aShape << " = geompy.MakeFaceWires([";
313 it = theShapes.begin();
314 if (it != theShapes.end()) {
316 while (it != theShapes.end()) {
317 pd << ", " << (*it++);
320 pd << "], " << (int)isPlanarWanted << ")";
326 //=============================================================================
330 //=============================================================================
331 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
332 (list<Handle(GEOM_Object)> theShapes)
334 return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
337 //=============================================================================
341 //=============================================================================
342 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
343 (list<Handle(GEOM_Object)> theShapes)
345 return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
348 //=============================================================================
352 //=============================================================================
353 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
357 if (theShell.IsNull()) return NULL;
359 //Add a new Solid object
360 Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
362 //Add a new Solid function for creation of a solid from a shell
363 Handle(GEOM_Function) aFunction =
364 aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
365 if (aFunction.IsNull()) return NULL;
367 //Check if the function is set correctly
368 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
370 GEOMImpl_IShapes aCI (aFunction);
372 Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
374 if (aRefShell.IsNull()) return NULL;
376 aCI.SetBase(aRefShell);
378 //Compute the Solid value
380 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
383 if (!GetSolver()->ComputeFunction(aFunction)) {
384 SetErrorCode("Solid driver failed");
388 catch (Standard_Failure) {
389 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
390 SetErrorCode(aFail->GetMessageString());
394 //Make a Python command
395 GEOM::TPythonDump(aFunction) << aSolid
396 << " = geompy.MakeSolid(" << theShell << ")";
402 //=============================================================================
406 //=============================================================================
407 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
408 (list<Handle(GEOM_Object)> theShapes)
410 return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
413 //=============================================================================
417 //=============================================================================
418 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
419 (list<Handle(GEOM_Object)> theShapes,
420 const Standard_Integer theObjectType,
421 const Standard_Integer theFunctionType,
422 const TCollection_AsciiString& theMethodName)
427 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
430 Handle(GEOM_Function) aFunction =
431 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
432 if (aFunction.IsNull()) return NULL;
434 //Check if the function is set correctly
435 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
437 GEOMImpl_IShapes aCI (aFunction);
439 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
442 list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
443 for (; it != theShapes.end(); it++) {
444 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
445 if (aRefSh.IsNull()) {
446 SetErrorCode("NULL argument shape for the shape construction");
449 aShapesSeq->Append(aRefSh);
451 aCI.SetShapes(aShapesSeq);
455 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
458 if (!GetSolver()->ComputeFunction(aFunction)) {
459 SetErrorCode("Shape driver failed");
463 catch (Standard_Failure) {
464 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
465 SetErrorCode(aFail->GetMessageString());
469 //Make a Python command
470 GEOM::TPythonDump pd (aFunction);
471 pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
474 it = theShapes.begin();
475 if (it != theShapes.end()) {
477 while (it != theShapes.end()) {
478 pd << ", " << (*it++);
487 //=============================================================================
491 //=============================================================================
492 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
493 (Handle(GEOM_Object) theShape,
494 const Standard_Real theTolerance)
498 if (theShape.IsNull()) return NULL;
500 //Add a new Glued object
501 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
503 //Add a new Glue function
504 Handle(GEOM_Function) aFunction;
505 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
506 if (aFunction.IsNull()) return NULL;
508 //Check if the function is set correctly
509 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
511 GEOMImpl_IGlue aCI (aFunction);
513 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
514 if (aRefShape.IsNull()) return NULL;
516 aCI.SetBase(aRefShape);
517 aCI.SetTolerance(theTolerance);
519 //Compute the sub-shape value
520 Standard_Boolean isWarning = Standard_False;
522 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
525 if (!GetSolver()->ComputeFunction(aFunction)) {
526 SetErrorCode("Shape driver failed to glue faces");
530 catch (Standard_Failure) {
531 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
532 SetErrorCode(aFail->GetMessageString());
533 // to provide warning
534 if (!aFunction->GetValue().IsNull()) {
535 isWarning = Standard_True;
541 //Make a Python command
542 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
543 << theShape << ", " << theTolerance << ")";
545 // to provide warning
546 if (!isWarning) SetErrorCode(OK);
550 //=============================================================================
554 //=============================================================================
555 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
556 (Handle(GEOM_Object) theShape,
557 const Standard_Integer theShapeType,
558 const Standard_Boolean isSorted)
562 if (theShape.IsNull()) return NULL;
563 TopoDS_Shape aShape = theShape->GetValue();
564 if (aShape.IsNull()) return NULL;
566 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
567 Handle(GEOM_Object) anObj;
568 Handle(GEOM_Function) aFunction;
569 TopTools_MapOfShape mapShape;
570 TopTools_ListOfShape listShape;
572 if (aShape.ShapeType() == TopAbs_COMPOUND &&
573 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
574 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
575 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
576 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
577 for (; It.More(); It.Next()) {
578 if (mapShape.Add(It.Value())) {
579 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
580 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
581 listShape.Append(It.Value());
586 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
587 for (; exp.More(); exp.Next())
588 if (mapShape.Add(exp.Current()))
589 listShape.Append(exp.Current());
592 if (listShape.IsEmpty()) {
593 SetErrorCode("The given shape has no sub-shapes of the requested type");
598 SortShapes(listShape);
600 TopTools_IndexedMapOfShape anIndices;
601 TopExp::MapShapes(aShape, anIndices);
602 Handle(TColStd_HArray1OfInteger) anArray;
604 TopTools_ListIteratorOfListOfShape itSub (listShape);
605 TCollection_AsciiString anAsciiList, anEntry;
606 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
607 TopoDS_Shape aValue = itSub.Value();
608 anArray = new TColStd_HArray1OfInteger(1,1);
609 anArray->SetValue(1, anIndices.FindIndex(aValue));
610 anObj = GetEngine()->AddSubShape(theShape, anArray);
613 // for python command
614 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
615 anAsciiList += anEntry;
619 //Make a Python command
620 anAsciiList.Trunc(anAsciiList.Length() - 1);
622 aFunction = theShape->GetLastFunction();
624 GEOM::TPythonDump pd (aFunction, /*append=*/true);
625 pd << "[" << anAsciiList.ToCString();
626 pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
627 pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
634 //=============================================================================
638 //=============================================================================
639 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
640 (Handle(GEOM_Object) theShape,
641 const Standard_Integer theShapeType,
642 const Standard_Boolean isSorted)
646 if (theShape.IsNull()) return NULL;
647 TopoDS_Shape aShape = theShape->GetValue();
648 if (aShape.IsNull()) return NULL;
650 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
651 TopTools_MapOfShape mapShape;
652 TopTools_ListOfShape listShape;
654 if (aShape.ShapeType() == TopAbs_COMPOUND &&
655 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
656 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
657 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
658 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
659 for (; It.More(); It.Next()) {
660 if (mapShape.Add(It.Value())) {
661 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
662 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
663 listShape.Append(It.Value());
668 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
669 for (; exp.More(); exp.Next())
670 if (mapShape.Add(exp.Current()))
671 listShape.Append(exp.Current());
674 if (listShape.IsEmpty()) {
675 SetErrorCode("The given shape has no sub-shapes of the requested type");
680 SortShapes(listShape);
682 TopTools_IndexedMapOfShape anIndices;
683 TopExp::MapShapes(aShape, anIndices);
684 Handle(TColStd_HArray1OfInteger) anArray;
686 TopTools_ListIteratorOfListOfShape itSub (listShape);
687 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
688 TopoDS_Shape aValue = itSub.Value();
689 aSeq->Append(anIndices.FindIndex(aValue));
692 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
694 //Make a Python command
695 GEOM::TPythonDump pd (aFunction, /*append=*/true);
696 pd << "listSubShapeIDs = geompy.SubShapeAll";
697 pd << (isSorted ? "SortedIDs(" : "IDs(");
698 pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
704 //=============================================================================
708 //=============================================================================
709 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
710 (Handle(GEOM_Object) theMainShape,
711 const Standard_Integer theID)
715 if (theMainShape.IsNull()) return NULL;
717 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
718 anArray->SetValue(1, theID);
719 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
720 if (anObj.IsNull()) {
721 SetErrorCode("Can not get a sub-shape with the given ID");
725 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
727 //Make a Python command
728 GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
729 << theMainShape << ", [" << theID << "])";
735 //=============================================================================
739 //=============================================================================
740 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
741 Handle(GEOM_Object) theSubShape)
745 TopoDS_Shape aMainShape = theMainShape->GetValue();
746 TopoDS_Shape aSubShape = theSubShape->GetValue();
748 if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
750 TopTools_IndexedMapOfShape anIndices;
751 TopExp::MapShapes(aMainShape, anIndices);
752 if (anIndices.Contains(aSubShape)) {
754 return anIndices.FindIndex(aSubShape);
760 //=============================================================================
764 //=============================================================================
765 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
766 Handle(GEOM_Object) theSubShape)
770 TopoDS_Shape aMainShape = theMainShape->GetValue();
771 TopoDS_Shape aSubShape = theSubShape->GetValue();
773 if (aMainShape.IsNull() || aSubShape.IsNull()) {
774 SetErrorCode("Null argument shape given");
779 if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
781 TopTools_ListOfShape CL;
782 CL.Append(aMainShape);
783 TopTools_ListIteratorOfListOfShape itC;
784 for (itC.Initialize(CL); itC.More(); itC.Next()) {
785 for (it.Initialize(itC.Value()); it.More(); it.Next()) {
786 if (it.Value().ShapeType() == TopAbs_COMPOUND) {
787 if (it.Value().IsSame(aSubShape))
791 CL.Append(it.Value());
796 TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
797 TopTools_MapOfShape M;
798 for (; anExp.More(); anExp.Next()) {
799 if (M.Add(anExp.Current())) {
800 if (anExp.Current().IsSame(aSubShape))
807 SetErrorCode("The sub-shape does not belong to the main shape");
811 //=============================================================================
815 //=============================================================================
816 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
820 TCollection_AsciiString aTypeName ("Null Shape");
822 TopoDS_Shape aShape = theShape->GetValue();
826 switch (aShape.ShapeType() )
828 case TopAbs_COMPOUND:
829 aTypeName = "Compound";
831 case TopAbs_COMPSOLID:
832 aTypeName = "Compound Solid";
842 BRepAdaptor_Surface surf (TopoDS::Face(aShape));
843 if (surf.GetType() == GeomAbs_Plane)
845 else if (surf.GetType() == GeomAbs_Cylinder)
846 aTypeName = "Cylindrical Face";
847 else if (surf.GetType() == GeomAbs_Sphere)
848 aTypeName = "Spherical Face";
849 else if (surf.GetType() == GeomAbs_Torus)
850 aTypeName = "Toroidal Face";
851 else if (surf.GetType() == GeomAbs_Cone)
852 aTypeName = "Conical Face";
854 aTypeName = "GEOM::FACE";
862 BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
863 if (curv.GetType() == GeomAbs_Line) {
864 if ((Abs(curv.FirstParameter()) >= 1E6) ||
865 (Abs(curv.LastParameter()) >= 1E6))
869 } else if (curv.GetType() == GeomAbs_Circle) {
871 aTypeName = "Circle";
880 aTypeName = "Vertex";
886 aTypeName = "Shape of unknown type";
893 //=============================================================================
897 //=============================================================================
898 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
902 Standard_Integer nb = 0;
904 if (theShape.IsNull()) return -1;
905 TopoDS_Shape aShape = theShape->GetValue();
906 if (aShape.IsNull()) return -1;
908 TopTools_MapOfShape mapShape;
910 TopExp_Explorer exp (aShape, TopAbs_FACE);
911 for (; exp.More(); exp.Next())
912 if (mapShape.Add(exp.Current()))
919 //=============================================================================
923 //=============================================================================
924 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
928 Standard_Integer nb = 0;
930 if (theShape.IsNull()) return -1;
931 TopoDS_Shape aShape = theShape->GetValue();
932 if (aShape.IsNull()) return -1;
934 TopTools_MapOfShape mapShape;
936 TopExp_Explorer exp (aShape, TopAbs_EDGE);
937 for (; exp.More(); exp.Next())
938 if (mapShape.Add(exp.Current()))
945 //=============================================================================
949 //=============================================================================
950 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
954 if (theShape.IsNull()) return NULL;
956 //Add a new reversed object
957 Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
959 //Add a new Revese function
960 Handle(GEOM_Function) aFunction;
961 aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
962 if (aFunction.IsNull()) return NULL;
964 //Check if the function is set correctly
965 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
967 GEOMImpl_IShapes aSI (aFunction);
969 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
970 if (aRefShape.IsNull()) return NULL;
972 aSI.SetBase(aRefShape);
974 //Compute the sub-shape value
976 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
979 if (!GetSolver()->ComputeFunction(aFunction)) {
980 SetErrorCode("Shape driver failed to reverse shape");
984 catch (Standard_Failure) {
985 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
986 SetErrorCode(aFail->GetMessageString());
990 //Make a Python command
991 GEOM::TPythonDump(aFunction) << aReversed
992 << " = geompy.ChangeOrientation(" << theShape << ")";
998 //=============================================================================
1002 //=============================================================================
1003 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
1004 (Handle(GEOM_Object) theShape)
1008 if (theShape.IsNull()) return NULL;
1009 TopoDS_Shape aShape = theShape->GetValue();
1010 if (aShape.IsNull()) return NULL;
1012 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1014 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1015 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1016 (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1018 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1021 SetErrorCode("The given shape has no faces");
1025 TopTools_IndexedMapOfShape anIndices;
1026 TopExp::MapShapes(aShape, anIndices);
1028 Standard_Integer id;
1029 for (; ind <= nbFaces; ind++) {
1030 if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1031 id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1036 //The explode doesn't change object so no new function is required.
1037 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1039 //Make a Python command
1040 GEOM::TPythonDump(aFunction, /*append=*/true)
1041 << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
1047 //=======================================================================
1048 //function : GetSharedShapes
1050 //=======================================================================
1052 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1053 (Handle(GEOM_Object) theShape1,
1054 Handle(GEOM_Object) theShape2,
1055 const Standard_Integer theShapeType)
1059 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
1061 TopoDS_Shape aShape1 = theShape1->GetValue();
1062 TopoDS_Shape aShape2 = theShape2->GetValue();
1064 if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
1066 TopTools_IndexedMapOfShape anIndices;
1067 TopExp::MapShapes(aShape1, anIndices);
1068 Handle(TColStd_HArray1OfInteger) anArray;
1070 TopTools_IndexedMapOfShape mapShape1;
1071 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
1073 Handle(GEOM_Object) anObj;
1074 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1075 TCollection_AsciiString anAsciiList, anEntry;
1077 TopTools_MapOfShape mapShape2;
1078 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
1079 for (; exp.More(); exp.Next()) {
1080 TopoDS_Shape aSS = exp.Current();
1081 if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
1082 anArray = new TColStd_HArray1OfInteger(1,1);
1083 anArray->SetValue(1, anIndices.FindIndex(aSS));
1084 anObj = GetEngine()->AddSubShape(theShape1, anArray);
1085 aSeq->Append(anObj);
1087 // for python command
1088 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1089 anAsciiList += anEntry;
1094 if (aSeq->IsEmpty()) {
1095 SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
1099 //Make a Python command
1100 anAsciiList.Trunc(anAsciiList.Length() - 1);
1102 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1104 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1105 << "] = geompy.GetSharedShapes(" << theShape1 << ", "
1106 << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1112 //=============================================================================
1116 //=============================================================================
1117 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump,
1118 const GEOMAlgo_State theState)
1121 case GEOMAlgo_ST_IN:
1122 theDump << "geompy.GEOM.ST_IN";
1124 case GEOMAlgo_ST_OUT:
1125 theDump << "geompy.GEOM.ST_OUT";
1127 case GEOMAlgo_ST_ON:
1128 theDump << "geompy.GEOM.ST_ON";
1130 case GEOMAlgo_ST_ONIN:
1131 theDump << "geompy.GEOM.ST_ONIN";
1133 case GEOMAlgo_ST_ONOUT:
1134 theDump << "geompy.GEOM.ST_ONOUT";
1137 theDump << "geompy.GEOM.ST_UNKNOWN";
1143 //=======================================================================
1144 //function : checkTypeShapesOn
1146 * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
1147 * \param theShapeType - the shape type to check
1148 * \retval bool - result of the check
1150 //=======================================================================
1152 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
1154 if (theShapeType != TopAbs_VERTEX &&
1155 theShapeType != TopAbs_EDGE &&
1156 theShapeType != TopAbs_FACE &&
1157 theShapeType != TopAbs_SOLID) {
1158 SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1164 //=======================================================================
1165 //function : makePlane
1167 * \brief Creates Geom_Plane
1168 * \param theAx1 - shape object defining plane parameters
1169 * \retval Handle(Geom_Surface) - resulting surface
1171 //=======================================================================
1173 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
1175 if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1176 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1177 TopoDS_Vertex V1, V2;
1178 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1179 if (V1.IsNull() || V2.IsNull()) {
1180 SetErrorCode("Bad edge given for the plane normal vector");
1183 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1184 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1185 if (aVec.Magnitude() < Precision::Confusion()) {
1186 SetErrorCode("Vector with null magnitude given");
1189 return new Geom_Plane(aLoc, aVec);
1192 //=======================================================================
1193 //function : makeCylinder
1195 * \brief Creates Geom_CylindricalSurface
1196 * \param theAx1 - edge defining cylinder axis
1197 * \param theRadius - cylinder radius
1198 * \retval Handle(Geom_Surface) - resulting surface
1200 //=======================================================================
1202 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
1203 const Standard_Real theRadius)
1205 //Axis of the cylinder
1206 if (anAxis.ShapeType() != TopAbs_EDGE) {
1207 SetErrorCode("Not an edge given for the axis");
1210 TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1211 TopoDS_Vertex V1, V2;
1212 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1213 if (V1.IsNull() || V2.IsNull()) {
1214 SetErrorCode("Bad edge given for the axis");
1217 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1218 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1219 if (aVec.Magnitude() < Precision::Confusion()) {
1220 SetErrorCode("Vector with null magnitude given");
1224 gp_Ax3 anAx3 (aLoc, aVec);
1225 return new Geom_CylindricalSurface(anAx3, theRadius);
1229 //=======================================================================
1230 //function : getShapesOnBoxIDs
1232 * \brief Find IDs of subshapes complying with given status about surface
1233 * \param theBox - the box to check state of subshapes against
1234 * \param theShape - the shape to explore
1235 * \param theShapeType - type of subshape of theShape
1236 * \param theState - required state
1237 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1239 //=======================================================================
1241 Handle(TColStd_HSequenceOfInteger)
1242 GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1243 const Handle(GEOM_Object)& theShape,
1244 const Standard_Integer theShapeType,
1245 GEOMAlgo_State theState)
1247 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1249 TopoDS_Shape aBox = theBox->GetValue();
1250 TopoDS_Shape aShape = theShape->GetValue();
1253 GEOMAlgo_FinderShapeOn2 aFinder;
1254 Standard_Real aTol = 0.0001; // default value
1256 Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
1257 aClsfBox->SetBox(aBox);
1259 aFinder.SetShape(aShape);
1260 aFinder.SetTolerance(aTol);
1261 aFinder.SetClsf(aClsfBox);
1262 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1263 aFinder.SetState(theState);
1266 // Interprete results
1267 Standard_Integer iErr = aFinder.ErrorStatus();
1268 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1270 MESSAGE(" iErr : " << iErr);
1271 TCollection_AsciiString aMsg (" iErr : ");
1272 aMsg += TCollection_AsciiString(iErr);
1276 Standard_Integer iWrn = aFinder.WarningStatus();
1277 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1279 MESSAGE(" *** iWrn : " << iWrn);
1282 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1284 if (listSS.Extent() < 1) {
1285 SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1289 // Fill sequence of object IDs
1290 aSeqOfIDs = new TColStd_HSequenceOfInteger;
1292 TopTools_IndexedMapOfShape anIndices;
1293 TopExp::MapShapes(aShape, anIndices);
1295 TopTools_ListIteratorOfListOfShape itSub (listSS);
1296 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1297 int id = anIndices.FindIndex(itSub.Value());
1298 aSeqOfIDs->Append(id);
1305 //=======================================================================
1306 //function : GetShapesOnBoxIDs
1308 * \brief Find subshapes complying with given status about surface
1309 * \param theBox - the box to check state of subshapes against
1310 * \param theShape - the shape to explore
1311 * \param theShapeType - type of subshape of theShape
1312 * \param theState - required state
1313 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1315 //=======================================================================
1317 Handle(TColStd_HSequenceOfInteger)
1318 GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1319 const Handle(GEOM_Object)& theShape,
1320 const Standard_Integer theShapeType,
1321 GEOMAlgo_State theState)
1323 // Find subshapes ids
1324 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1325 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1326 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1329 // The GetShapesOnBox() doesn't change object so no new function is required.
1330 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
1332 // Make a Python command
1333 GEOM::TPythonDump(aFunction)
1334 << "listShapesOnBoxIDs = geompy.GetShapesOnQuadrangleIDs("
1337 << TopAbs_ShapeEnum(theShapeType) << ", "
1344 //=======================================================================
1345 //function : GetShapesOnBox
1347 * \brief Find subshapes complying with given status about surface
1348 * \param theBox - the box to check state of subshapes against
1349 * \param theShape - the shape to explore
1350 * \param theShapeType - type of subshape of theShape
1351 * \param theState - required state
1352 * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1354 //=======================================================================
1356 Handle(TColStd_HSequenceOfTransient)
1357 GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
1358 const Handle(GEOM_Object)& theShape,
1359 const Standard_Integer theShapeType,
1360 GEOMAlgo_State theState)
1362 // Find subshapes ids
1363 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1364 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1365 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1368 // Find objects by indices
1369 TCollection_AsciiString anAsciiList;
1370 Handle(TColStd_HSequenceOfTransient) aSeq;
1371 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1372 if ( aSeq.IsNull() || aSeq->IsEmpty() )
1375 // Make a Python command
1377 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1378 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1380 GEOM::TPythonDump(aFunction)
1381 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
1384 << TopAbs_ShapeEnum(theShapeType) << ", "
1392 //=======================================================================
1393 //function : getShapesOnSurfaceIDs
1395 * \brief Find IDs of subshapes complying with given status about surface
1396 * \param theSurface - the surface to check state of subshapes against
1397 * \param theShape - the shape to explore
1398 * \param theShapeType - type of subshape of theShape
1399 * \param theState - required state
1400 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1402 //=======================================================================
1404 Handle(TColStd_HSequenceOfInteger)
1405 GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
1406 const TopoDS_Shape& theShape,
1407 TopAbs_ShapeEnum theShapeType,
1408 GEOMAlgo_State theState)
1410 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1412 // Check presence of triangulation, build if need
1413 if (!CheckTriangulation(theShape))
1417 GEOMAlgo_FinderShapeOn1 aFinder;
1418 Standard_Real aTol = 0.0001; // default value
1420 aFinder.SetShape(theShape);
1421 aFinder.SetTolerance(aTol);
1422 aFinder.SetSurface(theSurface);
1423 aFinder.SetShapeType(theShapeType);
1424 aFinder.SetState(theState);
1426 // Sets the minimal number of inner points for the faces that do not have own
1427 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1429 aFinder.SetNbPntsMin(3);
1430 // Sets the maximal number of inner points for edges or faces.
1431 // It is usefull for the cases when this number is very big (e.g =2000) to improve
1432 // the performance. If this value =0, all inner points will be taken into account.
1434 aFinder.SetNbPntsMax(100);
1438 // Interprete results
1439 Standard_Integer iErr = aFinder.ErrorStatus();
1440 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1442 MESSAGE(" iErr : " << iErr);
1443 TCollection_AsciiString aMsg (" iErr : ");
1444 aMsg += TCollection_AsciiString(iErr);
1448 Standard_Integer iWrn = aFinder.WarningStatus();
1449 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1451 MESSAGE(" *** iWrn : " << iWrn);
1454 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1456 if (listSS.Extent() < 1) {
1457 SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1461 // Fill sequence of object IDs
1462 aSeqOfIDs = new TColStd_HSequenceOfInteger;
1464 TopTools_IndexedMapOfShape anIndices;
1465 TopExp::MapShapes(theShape, anIndices);
1467 TopTools_ListIteratorOfListOfShape itSub (listSS);
1468 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1469 int id = anIndices.FindIndex(itSub.Value());
1470 aSeqOfIDs->Append(id);
1476 //=======================================================================
1477 //function : getObjectsShapesOn
1479 * \brief Find shape objects and their entries by their ids
1480 * \param theShapeIDs - incoming shape ids
1481 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1482 * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
1484 //=======================================================================
1486 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
1487 getObjectsShapesOn(const Handle(GEOM_Object)& theShape,
1488 const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
1489 TCollection_AsciiString & theShapeEntries)
1491 Handle(TColStd_HSequenceOfTransient) aSeq;
1493 if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
1495 aSeq = new TColStd_HSequenceOfTransient;
1496 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1497 TCollection_AsciiString anEntry;
1498 for ( int i = 1; i <= theShapeIDs->Length(); ++i )
1500 anArray->SetValue(1, theShapeIDs->Value( i ));
1501 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
1502 aSeq->Append( anObj );
1504 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1505 if ( i != 1 ) theShapeEntries += ",";
1506 theShapeEntries += anEntry;
1512 //=======================================================================
1513 //function : getShapesOnSurface
1515 * \brief Find subshapes complying with given status about surface
1516 * \param theSurface - the surface to check state of subshapes against
1517 * \param theShape - the shape to explore
1518 * \param theShapeType - type of subshape of theShape
1519 * \param theState - required state
1520 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1521 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1523 //=======================================================================
1525 Handle(TColStd_HSequenceOfTransient)
1526 GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
1527 const Handle(GEOM_Object)& theShape,
1528 TopAbs_ShapeEnum theShapeType,
1529 GEOMAlgo_State theState,
1530 TCollection_AsciiString & theShapeEntries)
1532 // Find subshapes ids
1533 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1534 getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
1535 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1538 return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
1541 //=============================================================================
1545 //=============================================================================
1546 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
1547 (const Handle(GEOM_Object)& theShape,
1548 const Standard_Integer theShapeType,
1549 const Handle(GEOM_Object)& theAx1,
1550 const GEOMAlgo_State theState)
1554 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1556 TopoDS_Shape aShape = theShape->GetValue();
1557 TopoDS_Shape anAx1 = theAx1->GetValue();
1559 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1561 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1562 if ( !checkTypeShapesOn( theShapeType ))
1566 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1567 if ( aPlane.IsNull() )
1571 TCollection_AsciiString anAsciiList;
1572 Handle(TColStd_HSequenceOfTransient) aSeq;
1573 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1574 if ( aSeq.IsNull() || aSeq->Length() == 0 )
1577 // Make a Python command
1579 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1580 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1582 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1583 << "] = geompy.GetShapesOnPlane(" << theShape << ", "
1584 << aShapeType << ", " << theAx1 << ", " << theState << ")";
1590 //=============================================================================
1592 * GetShapesOnPlaneWithLocation
1594 //=============================================================================
1595 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
1596 (const Handle(GEOM_Object)& theShape,
1597 const Standard_Integer theShapeType,
1598 const Handle(GEOM_Object)& theAx1,
1599 const Handle(GEOM_Object)& thePnt,
1600 const GEOMAlgo_State theState)
1604 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
1606 TopoDS_Shape aShape = theShape->GetValue();
1607 TopoDS_Shape anAx1 = theAx1->GetValue();
1608 TopoDS_Shape anPnt = thePnt->GetValue();
1610 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
1612 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1613 if ( !checkTypeShapesOn( theShapeType ))
1617 if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
1618 TopoDS_Vertex V1, V2, V3;
1619 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1620 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1622 if (V1.IsNull() || V2.IsNull()) {
1623 SetErrorCode("Bad edge given for the plane normal vector");
1626 V3 = TopoDS::Vertex(anPnt);
1629 SetErrorCode("Bad vertex given for the plane location");
1632 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
1633 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
1635 if (aVec.Magnitude() < Precision::Confusion()) {
1636 SetErrorCode("Vector with null magnitude given");
1639 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
1641 if ( aPlane.IsNull() )
1645 TCollection_AsciiString anAsciiList;
1646 Handle(TColStd_HSequenceOfTransient) aSeq;
1647 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1648 if ( aSeq.IsNull() || aSeq->Length() == 0 )
1651 // Make a Python command
1653 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1654 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1656 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1657 << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
1658 << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
1664 //=============================================================================
1666 * GetShapesOnCylinder
1668 //=============================================================================
1669 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
1670 (const Handle(GEOM_Object)& theShape,
1671 const Standard_Integer theShapeType,
1672 const Handle(GEOM_Object)& theAxis,
1673 const Standard_Real theRadius,
1674 const GEOMAlgo_State theState)
1678 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1680 TopoDS_Shape aShape = theShape->GetValue();
1681 TopoDS_Shape anAxis = theAxis->GetValue();
1683 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1685 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1686 if ( !checkTypeShapesOn( aShapeType ))
1689 // Create a cylinder surface
1690 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1691 if ( aCylinder.IsNull() )
1695 TCollection_AsciiString anAsciiList;
1696 Handle(TColStd_HSequenceOfTransient) aSeq;
1697 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
1698 if ( aSeq.IsNull() || aSeq->Length() == 0 )
1701 // Make a Python command
1703 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1704 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1706 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1707 << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
1708 << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
1714 //=============================================================================
1718 //=============================================================================
1719 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
1720 (const Handle(GEOM_Object)& theShape,
1721 const Standard_Integer theShapeType,
1722 const Handle(GEOM_Object)& theCenter,
1723 const Standard_Real theRadius,
1724 const GEOMAlgo_State theState)
1728 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1730 TopoDS_Shape aShape = theShape->GetValue();
1731 TopoDS_Shape aCenter = theCenter->GetValue();
1733 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1735 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1736 if ( !checkTypeShapesOn( aShapeType ))
1739 // Center of the sphere
1740 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1741 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1743 gp_Ax3 anAx3 (aLoc, gp::DZ());
1744 Handle(Geom_SphericalSurface) aSphere =
1745 new Geom_SphericalSurface(anAx3, theRadius);
1748 TCollection_AsciiString anAsciiList;
1749 Handle(TColStd_HSequenceOfTransient) aSeq;
1750 aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
1751 if ( aSeq.IsNull() || aSeq->Length() == 0 )
1754 // Make a Python command
1756 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1757 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1759 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1760 << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
1761 << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
1767 //=============================================================================
1769 * GetShapesOnPlaneIDs
1771 //=============================================================================
1772 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
1773 (const Handle(GEOM_Object)& theShape,
1774 const Standard_Integer theShapeType,
1775 const Handle(GEOM_Object)& theAx1,
1776 const GEOMAlgo_State theState)
1780 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1782 TopoDS_Shape aShape = theShape->GetValue();
1783 TopoDS_Shape anAx1 = theAx1->GetValue();
1785 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1787 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1788 if ( !checkTypeShapesOn( aShapeType ))
1792 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1793 if ( aPlane.IsNull() )
1797 Handle(TColStd_HSequenceOfInteger) aSeq;
1798 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
1800 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
1801 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
1803 // Make a Python command
1804 GEOM::TPythonDump(aFunction, /*append=*/true)
1805 << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
1806 << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
1812 //=============================================================================
1814 * GetShapesOnPlaneWithLocationIDs
1816 //=============================================================================
1817 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
1818 (const Handle(GEOM_Object)& theShape,
1819 const Standard_Integer theShapeType,
1820 const Handle(GEOM_Object)& theAx1,
1821 const Handle(GEOM_Object)& thePnt,
1822 const GEOMAlgo_State theState)
1826 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
1828 TopoDS_Shape aShape = theShape->GetValue();
1829 TopoDS_Shape anAx1 = theAx1->GetValue();
1830 TopoDS_Shape anPnt = thePnt->GetValue();
1832 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
1834 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1835 if ( !checkTypeShapesOn( aShapeType ))
1839 if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
1840 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1841 TopoDS_Vertex V1, V2, V3;
1842 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1843 if (V1.IsNull() || V2.IsNull()) {
1844 SetErrorCode("Bad edge given for the plane normal vector");
1847 V3 = TopoDS::Vertex(anPnt);
1849 SetErrorCode("Bad vertex given for the plane location");
1852 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
1853 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
1854 if (aVec.Magnitude() < Precision::Confusion()) {
1855 SetErrorCode("Vector with null magnitude given");
1859 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
1860 if ( aPlane.IsNull() )
1864 Handle(TColStd_HSequenceOfInteger) aSeq;
1865 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
1867 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
1868 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
1870 // Make a Python command
1871 GEOM::TPythonDump(aFunction, /*append=*/true)
1872 << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
1873 << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")";
1879 //=============================================================================
1881 * GetShapesOnCylinderIDs
1883 //=============================================================================
1884 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
1885 (const Handle(GEOM_Object)& theShape,
1886 const Standard_Integer theShapeType,
1887 const Handle(GEOM_Object)& theAxis,
1888 const Standard_Real theRadius,
1889 const GEOMAlgo_State theState)
1893 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1895 TopoDS_Shape aShape = theShape->GetValue();
1896 TopoDS_Shape anAxis = theAxis->GetValue();
1898 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1900 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1901 if ( !checkTypeShapesOn( aShapeType ))
1904 // Create a cylinder surface
1905 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1906 if ( aCylinder.IsNull() )
1910 Handle(TColStd_HSequenceOfInteger) aSeq;
1911 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
1913 // The GetShapesOnCylinder() doesn't change object so no new function is required.
1914 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
1916 // Make a Python command
1917 GEOM::TPythonDump(aFunction, /*append=*/true)
1918 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
1919 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
1920 << theRadius << ", " << theState << ")";
1926 //=============================================================================
1928 * GetShapesOnSphereIDs
1930 //=============================================================================
1931 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
1932 (const Handle(GEOM_Object)& theShape,
1933 const Standard_Integer theShapeType,
1934 const Handle(GEOM_Object)& theCenter,
1935 const Standard_Real theRadius,
1936 const GEOMAlgo_State theState)
1940 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1942 TopoDS_Shape aShape = theShape->GetValue();
1943 TopoDS_Shape aCenter = theCenter->GetValue();
1945 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1947 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1948 if ( !checkTypeShapesOn( aShapeType ))
1951 // Center of the sphere
1952 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1953 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1955 gp_Ax3 anAx3 (aLoc, gp::DZ());
1956 Handle(Geom_SphericalSurface) aSphere =
1957 new Geom_SphericalSurface(anAx3, theRadius);
1960 Handle(TColStd_HSequenceOfInteger) aSeq;
1961 aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
1963 // The GetShapesOnSphere() doesn't change object so no new function is required.
1964 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
1966 // Make a Python command
1967 GEOM::TPythonDump(aFunction, /*append=*/true)
1968 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
1969 << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
1970 << theRadius << ", " << theState << ")";
1976 //=======================================================================
1977 //function : getShapesOnQuadrangleIDs
1979 * \brief Find IDs of subshapes complying with given status about quadrangle
1980 * \param theShape - the shape to explore
1981 * \param theShapeType - type of subshape of theShape
1982 * \param theTopLeftPoint - top left quadrangle corner
1983 * \param theTopRigthPoint - top right quadrangle corner
1984 * \param theBottomLeftPoint - bottom left quadrangle corner
1985 * \param theBottomRigthPoint - bottom right quadrangle corner
1986 * \param theState - required state
1987 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1989 //=======================================================================
1991 Handle(TColStd_HSequenceOfInteger)
1992 GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
1993 const Standard_Integer theShapeType,
1994 const Handle(GEOM_Object)& theTopLeftPoint,
1995 const Handle(GEOM_Object)& theTopRigthPoint,
1996 const Handle(GEOM_Object)& theBottomLeftPoint,
1997 const Handle(GEOM_Object)& theBottomRigthPoint,
1998 const GEOMAlgo_State theState)
2002 if ( theShape.IsNull() ||
2003 theTopLeftPoint.IsNull() ||
2004 theTopRigthPoint.IsNull() ||
2005 theBottomLeftPoint.IsNull() ||
2006 theBottomRigthPoint.IsNull() )
2009 TopoDS_Shape aShape = theShape->GetValue();
2010 TopoDS_Shape aTL = theTopLeftPoint->GetValue();
2011 TopoDS_Shape aTR = theTopRigthPoint->GetValue();
2012 TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
2013 TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
2015 if (aShape.IsNull() ||
2020 aTL.ShapeType() != TopAbs_VERTEX ||
2021 aTR.ShapeType() != TopAbs_VERTEX ||
2022 aBL.ShapeType() != TopAbs_VERTEX ||
2023 aBR.ShapeType() != TopAbs_VERTEX )
2026 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2027 if ( !checkTypeShapesOn( aShapeType ))
2030 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2032 // Check presence of triangulation, build if need
2033 if (!CheckTriangulation(aShape))
2037 gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
2038 gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
2039 gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
2040 gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
2042 GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
2043 Standard_Real aTol = 0.0001; // default value
2045 aFinder.SetShape(aShape);
2046 aFinder.SetTolerance(aTol);
2047 //aFinder.SetSurface(theSurface);
2048 aFinder.SetShapeType(aShapeType);
2049 aFinder.SetState(theState);
2051 // Sets the minimal number of inner points for the faces that do not have own
2052 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
2054 aFinder.SetNbPntsMin(3);
2055 // Sets the maximal number of inner points for edges or faces.
2056 // It is usefull for the cases when this number is very big (e.g =2000) to improve
2057 // the performance. If this value =0, all inner points will be taken into account.
2059 aFinder.SetNbPntsMax(100);
2063 // Interprete results
2064 Standard_Integer iErr = aFinder.ErrorStatus();
2065 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2067 MESSAGE(" iErr : " << iErr);
2068 TCollection_AsciiString aMsg (" iErr : ");
2069 aMsg += TCollection_AsciiString(iErr);
2073 Standard_Integer iWrn = aFinder.WarningStatus();
2074 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2076 MESSAGE(" *** iWrn : " << iWrn);
2079 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2081 if (listSS.Extent() < 1) {
2082 SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2086 // Fill sequence of object IDs
2087 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2089 TopTools_IndexedMapOfShape anIndices;
2090 TopExp::MapShapes(aShape, anIndices);
2092 TopTools_ListIteratorOfListOfShape itSub (listSS);
2093 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2094 int id = anIndices.FindIndex(itSub.Value());
2095 aSeqOfIDs->Append(id);
2100 //=======================================================================
2101 //function : GetShapesOnQuadrangle
2103 * \brief Find subshapes complying with given status about quadrangle
2104 * \param theShape - the shape to explore
2105 * \param theShapeType - type of subshape of theShape
2106 * \param theTopLeftPoint - top left quadrangle corner
2107 * \param theTopRigthPoint - top right quadrangle corner
2108 * \param theBottomLeftPoint - bottom left quadrangle corner
2109 * \param theBottomRigthPoint - bottom right quadrangle corner
2110 * \param theState - required state
2111 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2113 //=======================================================================
2115 Handle(TColStd_HSequenceOfTransient)
2116 GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
2117 const Standard_Integer theShapeType,
2118 const Handle(GEOM_Object)& theTopLeftPoint,
2119 const Handle(GEOM_Object)& theTopRigthPoint,
2120 const Handle(GEOM_Object)& theBottomLeftPoint,
2121 const Handle(GEOM_Object)& theBottomRigthPoint,
2122 const GEOMAlgo_State theState)
2125 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2126 getShapesOnQuadrangleIDs( theShape,
2131 theBottomRigthPoint,
2133 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2136 // Find objects by indices
2137 TCollection_AsciiString anAsciiList;
2138 Handle(TColStd_HSequenceOfTransient) aSeq;
2139 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2140 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2143 // Make a Python command
2145 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2146 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2148 GEOM::TPythonDump(aFunction)
2149 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
2151 << TopAbs_ShapeEnum(theShapeType) << ", "
2152 << theTopLeftPoint << ", "
2153 << theTopRigthPoint << ", "
2154 << theBottomLeftPoint << ", "
2155 << theBottomRigthPoint << ", "
2162 //=======================================================================
2163 //function : GetShapesOnQuadrangleIDs
2165 * \brief Find IDs of subshapes complying with given status about quadrangle
2166 * \param theShape - the shape to explore
2167 * \param theShapeType - type of subshape of theShape
2168 * \param theTopLeftPoint - top left quadrangle corner
2169 * \param theTopRigthPoint - top right quadrangle corner
2170 * \param theBottomLeftPoint - bottom left quadrangle corner
2171 * \param theBottomRigthPoint - bottom right quadrangle corner
2172 * \param theState - required state
2173 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2175 //=======================================================================
2177 Handle(TColStd_HSequenceOfInteger)
2178 GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2179 const Standard_Integer theShapeType,
2180 const Handle(GEOM_Object)& theTopLeftPoint,
2181 const Handle(GEOM_Object)& theTopRigthPoint,
2182 const Handle(GEOM_Object)& theBottomLeftPoint,
2183 const Handle(GEOM_Object)& theBottomRigthPoint,
2184 const GEOMAlgo_State theState)
2187 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2188 getShapesOnQuadrangleIDs( theShape,
2193 theBottomRigthPoint,
2195 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2198 // Make a Python command
2200 // The GetShapesOnCylinder() doesn't change object so no new function is required.
2201 Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
2202 lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
2203 lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
2204 lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
2205 Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
2207 GEOM::TPythonDump(aFunction, /*append=*/true)
2208 << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
2210 << TopAbs_ShapeEnum(theShapeType) << ", "
2211 << theTopLeftPoint << ", "
2212 << theTopRigthPoint << ", "
2213 << theBottomLeftPoint << ", "
2214 << theBottomRigthPoint << ", "
2222 //=============================================================================
2226 //=============================================================================
2227 static void SimplifyWhat (TopoDS_Shape& theWhat,
2228 TopTools_IndexedMapOfShape& theArgumentIndices,
2229 TColStd_ListOfInteger& theSimpleSubWhat)
2231 TopTools_MapOfShape mapShape;
2232 TopoDS_Iterator It (theWhat, Standard_True, Standard_True);
2233 for (; It.More(); It.Next()) {
2234 if (mapShape.Add(It.Value())) {
2235 TopoDS_Shape curSh = It.Value();
2236 if (curSh.ShapeType() == TopAbs_COMPOUND ||
2237 curSh.ShapeType() == TopAbs_COMPSOLID) {
2238 SimplifyWhat(curSh, theArgumentIndices, theSimpleSubWhat);
2240 theSimpleSubWhat.Append(theArgumentIndices.FindIndex(curSh));
2246 static bool GetInPlaceOfCompound (Handle(GEOM_Function)& theWhereFunction,
2247 TopoDS_Shape& theWhat,
2248 TColStd_ListOfInteger& theModifiedArray)
2250 bool isFoundAny = false;
2251 TopTools_MapOfShape mapShape;
2252 TopoDS_Iterator It (theWhat, Standard_True, Standard_True);
2253 for (; It.More(); It.Next()) {
2254 if (mapShape.Add(It.Value())) {
2255 TopoDS_Shape curWhat = It.Value();
2256 if (curWhat.ShapeType() == TopAbs_COMPOUND ||
2257 curWhat.ShapeType() == TopAbs_COMPSOLID) {
2258 // Recursive call for compound or compsolid
2259 if (GetInPlaceOfCompound(theWhereFunction, curWhat, theModifiedArray))
2262 // Try to find for "simple" shape
2263 bool isFound = false;
2265 TDF_LabelSequence aLabelSeq;
2266 theWhereFunction->GetDependency(aLabelSeq);
2267 Standard_Integer nbArg = aLabelSeq.Length();
2269 for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
2271 TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
2273 Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
2274 TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
2276 TopTools_IndexedMapOfShape anArgumentIndices;
2277 TopExp::MapShapes(anArgumentShape, anArgumentIndices);
2279 if (anArgumentIndices.Contains(curWhat)) {
2280 isFound = Standard_True;
2281 Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(curWhat);
2283 // Find corresponding label in history
2284 TDF_Label anArgumentHistoryLabel =
2285 theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
2286 if (!anArgumentHistoryLabel.IsNull()) {
2287 TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
2288 if (!aWhatHistoryLabel.IsNull()) {
2289 Handle(TDataStd_IntegerArray) anIntegerArray;
2290 if (aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2291 Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
2292 for (imod = 1; imod <= aModifLen; imod++) {
2293 theModifiedArray.Append(anIntegerArray->Array()->Value(imod));
2308 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
2309 (Handle(GEOM_Object) theShapeWhere,
2310 Handle(GEOM_Object) theShapeWhat)
2314 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2316 TopoDS_Shape aWhere = theShapeWhere->GetValue();
2317 TopoDS_Shape aWhat = theShapeWhat->GetValue();
2319 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
2321 //Fill array of indices
2322 Handle(TColStd_HArray1OfInteger) aModifiedArray;
2324 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
2326 TopTools_IndexedMapOfShape aWhereIndices;
2327 TopExp::MapShapes(aWhere, aWhereIndices);
2329 if (aWhereIndices.Contains(aWhat)) {
2331 // entity was not changed by the operation
2332 Standard_Integer aWhatIndex = aWhereIndices.FindIndex(aWhat);
2333 aModifiedArray = new TColStd_HArray1OfInteger(1,1);
2334 aModifiedArray->SetValue(1, aWhatIndex);
2338 TDF_Label aHistoryLabel = aWhereFunction->GetHistoryEntry(Standard_False);
2339 if (aHistoryLabel.IsNull()) {
2340 SetErrorCode("Modifications history does not exist for the shape under consideration.");
2344 // search in history for all argument shapes
2345 Standard_Boolean isFound = Standard_False;
2347 TDF_LabelSequence aLabelSeq;
2348 aWhereFunction->GetDependency(aLabelSeq);
2349 Standard_Integer nbArg = aLabelSeq.Length();
2351 for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
2353 TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
2355 Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
2356 TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
2358 TopTools_IndexedMapOfShape anArgumentIndices;
2359 TopExp::MapShapes(anArgumentShape, anArgumentIndices);
2361 if (anArgumentIndices.Contains(aWhat)) {
2362 isFound = Standard_True;
2363 Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(aWhat);
2365 // Find corresponding label in history
2366 TDF_Label anArgumentHistoryLabel =
2367 aWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
2368 if (anArgumentHistoryLabel.IsNull()) {
2369 // Lost History of operation argument. Possibly, all its entities was removed.
2374 TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
2375 if (aWhatHistoryLabel.IsNull()) {
2376 // Check, if the sought shape is Compound or Compsolid.
2377 // In that case we will try to find history for its sub-shapes
2378 if (aWhat.ShapeType() == TopAbs_COMPOUND ||
2379 aWhat.ShapeType() == TopAbs_COMPSOLID) {
2380 TColStd_ListOfInteger aSimpleSubWhat, aModifiedList;
2381 SimplifyWhat(aWhat, anArgumentIndices, aSimpleSubWhat);
2382 TColStd_ListIteratorOfListOfInteger anIterSub (aSimpleSubWhat);
2383 for (; anIterSub.More(); anIterSub.Next()) {
2384 Standard_Integer aSubWhatIndex = anIterSub.Value();
2385 TDF_Label aSubWhatHistoryLabel =
2386 anArgumentHistoryLabel.FindChild(aSubWhatIndex, Standard_False);
2387 if (!aSubWhatHistoryLabel.IsNull()) {
2388 Handle(TDataStd_IntegerArray) anIntegerArray;
2389 if (aSubWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2390 for (Standard_Integer isub = 1; isub <= anIntegerArray->Length(); isub++) {
2391 aModifiedList.Append(anIntegerArray->Value(isub));
2396 if (aModifiedList.Extent() > 0) {
2397 Handle(TColStd_HArray1OfInteger) aModifiedArraySub =
2398 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
2399 TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
2400 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
2401 aModifiedArraySub->SetValue(imod, anIterModif.Value());
2403 aModifiedArray = aModifiedArraySub;
2415 Handle(TDataStd_IntegerArray) anIntegerArray;
2416 if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2417 SetErrorCode("Error: Empty modifications history for the sought shape.");
2421 aModifiedArray = anIntegerArray->Array();
2422 if (aModifiedArray->Length() == 0) {
2423 SetErrorCode("Error: Empty modifications history for the sought shape.");
2431 // try compound element by element
2432 if (aWhat.ShapeType() == TopAbs_COMPOUND ||
2433 aWhat.ShapeType() == TopAbs_COMPSOLID) {
2434 TColStd_ListOfInteger aModifiedList;
2435 isFound = GetInPlaceOfCompound(aWhereFunction, aWhat, aModifiedList);
2437 if (aModifiedList.Extent() < 1) {
2438 SetErrorCode("Error: Empty modifications history for all sub-shapes of the sought shape.");
2441 aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
2442 TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
2443 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
2444 aModifiedArray->SetValue(imod, anIterModif.Value());
2449 SetErrorCode("The sought shape does not belong to any operation argument.");
2456 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
2457 if (aResult.IsNull()) {
2458 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2462 if (aModifiedArray->Length() > 1) {
2464 aResult->SetType(GEOM_GROUP);
2466 //Set a sub shape type
2467 TDF_Label aFreeLabel = aResult->GetFreeLabel();
2468 TopAbs_ShapeEnum aShapeType = aWhat.ShapeType();
2469 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
2472 //Make a Python command
2473 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
2475 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
2476 << theShapeWhere << ", " << theShapeWhat << ")";
2482 //=======================================================================
2483 //function : SortShapes
2485 //=======================================================================
2486 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
2488 Standard_Integer MaxShapes = SL.Extent();
2489 TopTools_Array1OfShape aShapes (1,MaxShapes);
2490 TColStd_Array1OfInteger OrderInd(1,MaxShapes);
2491 TColStd_Array1OfReal MidXYZ (1,MaxShapes); //X,Y,Z;
2492 TColStd_Array1OfReal Length (1,MaxShapes); //X,Y,Z;
2494 // Computing of CentreOfMass
2495 Standard_Integer Index;
2498 TopTools_ListIteratorOfListOfShape it(SL);
2499 for (Index=1; it.More(); Index++)
2501 TopoDS_Shape S = it.Value();
2502 SL.Remove( it ); // == it.Next()
2504 OrderInd.SetValue (Index, Index);
2505 if (S.ShapeType() == TopAbs_VERTEX)
2507 GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
2508 Length.SetValue( Index, (Standard_Real) S.Orientation());
2512 BRepGProp::LinearProperties (S, GPr);
2513 GPoint = GPr.CentreOfMass();
2514 Length.SetValue( Index, GPr.Mass() );
2516 MidXYZ.SetValue(Index,
2517 GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
2521 Standard_Integer aTemp;
2522 Standard_Boolean exchange, Sort = Standard_True;
2525 Sort = Standard_False;
2526 for (Index=1; Index < MaxShapes; Index++)
2528 if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
2529 exchange = Standard_True;
2530 else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
2531 Length(OrderInd(Index)) > Length(OrderInd(Index+1)) )
2532 exchange = Standard_True;
2534 exchange = Standard_False;
2537 aTemp = OrderInd(Index);
2538 OrderInd(Index) = OrderInd(Index+1);
2539 OrderInd(Index+1) = aTemp;
2540 Sort = Standard_True;
2544 for (Index=1; Index <= MaxShapes; Index++)
2545 SL.Append( aShapes( OrderInd(Index) ));
2548 //=======================================================================
2549 //function : CheckTriangulation
2551 //=======================================================================
2552 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
2554 TopExp_Explorer exp (aShape, TopAbs_FACE);
2556 SetErrorCode("Shape without faces given");
2560 TopLoc_Location aTopLoc;
2561 Handle(Poly_Triangulation) aTRF;
2562 aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
2563 if (aTRF.IsNull()) {
2564 // calculate deflection
2565 Standard_Real aDeviationCoefficient = 0.001;
2568 BRepBndLib::Add(aShape, B);
2569 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
2570 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
2572 Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
2573 Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
2574 Standard_Real aHLRAngle = 0.349066;
2576 BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
2582 #define MAX_TOLERANCE 1.e-7
2585 //=======================================================================
2586 //function : isSameEdge
2587 //purpose : Returns True if two edges coincide
2588 //=======================================================================
2589 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
2591 TopoDS_Vertex V11, V12, V21, V22;
2592 TopExp::Vertices(theEdge1, V11, V12);
2593 TopExp::Vertices(theEdge2, V21, V22);
2594 gp_Pnt P11 = BRep_Tool::Pnt(V11);
2595 gp_Pnt P12 = BRep_Tool::Pnt(V12);
2596 gp_Pnt P21 = BRep_Tool::Pnt(V21);
2597 gp_Pnt P22 = BRep_Tool::Pnt(V22);
2598 bool coincide = false;
2600 //Check that ends of edges coincide
2601 if(P11.Distance(P21) <= MAX_TOLERANCE) {
2602 if(P12.Distance(P22) <= MAX_TOLERANCE) coincide = true;
2604 else if(P11.Distance(P22) <= MAX_TOLERANCE) {
2605 if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
2608 if(!coincide) return false;
2610 double U11, U12, U21, U22;
2611 Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
2612 Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
2613 if(C1->DynamicType() == C2->DynamicType()) return true;
2615 //Check that both edges has the same geometry
2616 double range = U12-U11;
2617 double U = U11+ range/3.0;
2618 gp_Pnt P1 = C1->Value(U); //Compute a point on one third of the edge's length
2619 U = U11+range*2.0/3.0;
2620 gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length
2622 if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22)
2625 if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
2627 if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
2630 if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
2635 #include <TopoDS_TShape.hxx>
2636 //=======================================================================
2637 //function : isSameFace
2638 //purpose : Returns True if two faces coincide
2639 //=======================================================================
2640 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
2642 TopExp_Explorer E(theFace1, TopAbs_EDGE);
2643 TopTools_ListOfShape LS1, LS2;
2644 for(; E.More(); E.Next()) LS1.Append(E.Current());
2646 E.Init(theFace2, TopAbs_EDGE);
2647 for(; E.More(); E.Next()) LS2.Append(E.Current());
2649 //Compare the number of edges in the faces
2650 if(LS1.Extent() != LS2.Extent()) return false;
2652 double aMin = RealFirst(), aMax = RealLast();
2653 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
2654 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
2656 for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
2657 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2658 if(P.X() < xminB1) xminB1 = P.X();
2659 if(P.Y() < yminB1) yminB1 = P.Y();
2660 if(P.Z() < zminB1) zminB1 = P.Z();
2661 if(P.X() > xmaxB1) xmaxB1 = P.X();
2662 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
2663 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
2666 for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
2667 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2668 if(P.X() < xminB2) xminB2 = P.X();
2669 if(P.Y() < yminB2) yminB2 = P.Y();
2670 if(P.Z() < zminB2) zminB2 = P.Z();
2671 if(P.X() > xmaxB2) xmaxB2 = P.X();
2672 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
2673 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
2676 //Compare the bounding boxes of both faces
2677 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
2680 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
2683 //Check that each edge of the Face1 has a counterpart in the Face2
2684 TopTools_MapOfOrientedShape aMap;
2685 TopTools_ListIteratorOfListOfShape LSI1(LS1);
2686 for(; LSI1.More(); LSI1.Next()) {
2687 TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
2688 bool isFound = false;
2689 TopTools_ListIteratorOfListOfShape LSI2(LS2);
2690 for(; LSI2.More(); LSI2.Next()) {
2691 TopoDS_Shape aValue = LSI2.Value();
2692 if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
2693 if(isSameEdge(E, TopoDS::Edge(aValue))) {
2699 if(!isFound) return false;
2702 Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
2703 Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
2704 if(S1->DynamicType() == S2->DynamicType()) {
2707 else { //Check if there a coincidence of two surfaces at least in two points
2708 double U11, U12, V11, V12, U21, U22, V21, V22;
2709 BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
2710 BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
2712 double rangeU = U12-U11;
2713 double rangeV = V12-V11;
2714 double U = U11 + rangeU/3.0;
2715 double V = V11 + rangeV/3.0;
2716 gp_Pnt P1 = S1->Value(U, V);
2717 U = U11+rangeU*2.0/3.0;
2718 V = V11+rangeV*2.0/3.0;
2719 gp_Pnt P2 = S1->Value(U, V);
2721 if(!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
2724 if(P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
2726 if(!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
2729 if(P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
2735 //=======================================================================
2736 //function : isSameSolid
2737 //purpose : Returns True if two solids coincide
2738 //=======================================================================
2739 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
2741 TopExp_Explorer E(theSolid1, TopAbs_FACE);
2742 TopTools_ListOfShape LS1, LS2;
2743 for(; E.More(); E.Next()) LS1.Append(E.Current());
2744 E.Init(theSolid2, TopAbs_FACE);
2745 for(; E.More(); E.Next()) LS2.Append(E.Current());
2747 if(LS1.Extent() != LS2.Extent()) return false;
2749 double aMin = RealFirst(), aMax = RealLast();
2750 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
2751 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
2753 for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
2754 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2755 if(P.X() < xminB1) xminB1 = P.X();
2756 if(P.Y() < yminB1) yminB1 = P.Y();
2757 if(P.Z() < zminB1) zminB1 = P.Z();
2758 if(P.X() > xmaxB1) xmaxB1 = P.X();
2759 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
2760 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
2763 for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
2764 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2765 if(P.X() < xminB2) xminB2 = P.X();
2766 if(P.Y() < yminB2) yminB2 = P.Y();
2767 if(P.Z() < zminB2) zminB2 = P.Z();
2768 if(P.X() > xmaxB2) xmaxB2 = P.X();
2769 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
2770 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
2773 //Compare the bounding boxes of both solids
2774 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
2777 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
2780 //Check that each face of the Solid1 has a counterpart in the Solid2
2781 TopTools_MapOfOrientedShape aMap;
2782 TopTools_ListIteratorOfListOfShape LSI1(LS1);
2783 for(; LSI1.More(); LSI1.Next()) {
2784 TopoDS_Face F = TopoDS::Face(LSI1.Value());
2785 bool isFound = false;
2786 TopTools_ListIteratorOfListOfShape LSI2(LS2);
2787 for(; LSI2.More(); LSI2.Next()) {
2788 if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
2789 if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
2790 aMap.Add(LSI2.Value());
2795 if(!isFound) return false;
2801 //=======================================================================
2802 //function : GetSame
2804 //=======================================================================
2805 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
2806 const Handle(GEOM_Object)& theShapeWhat)
2809 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2811 TopoDS_Shape aWhere = theShapeWhere->GetValue();
2812 TopoDS_Shape aWhat = theShapeWhat->GetValue();
2814 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
2817 bool isFound = false;
2818 TopoDS_Shape aSubShape;
2819 TopTools_MapOfShape aMap;
2821 switch(aWhat.ShapeType()) {
2822 case TopAbs_VERTEX: {
2823 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
2824 TopExp_Explorer E(aWhere, TopAbs_VERTEX);
2825 for(; E.More(); E.Next()) {
2826 if(!aMap.Add(E.Current())) continue;
2827 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2828 if(P.Distance(P2) <= MAX_TOLERANCE) {
2830 aSubShape = E.Current();
2837 TopoDS_Face aFace = TopoDS::Face(aWhat);
2838 TopExp_Explorer E(aWhere, TopAbs_FACE);
2839 for(; E.More(); E.Next()) {
2840 if(!aMap.Add(E.Current())) continue;
2841 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
2842 aSubShape = E.Current();
2850 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
2851 TopExp_Explorer E(aWhere, TopAbs_EDGE);
2852 for(; E.More(); E.Next()) {
2853 if(!aMap.Add(E.Current())) continue;
2854 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
2855 aSubShape = E.Current();
2862 case TopAbs_SOLID: {
2863 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
2864 TopExp_Explorer E(aWhere, TopAbs_SOLID);
2865 for(; E.More(); E.Next()) {
2866 if(!aMap.Add(E.Current())) continue;
2867 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
2868 aSubShape = E.Current();
2880 TopTools_IndexedMapOfShape anIndices;
2881 TopExp::MapShapes(aWhere, anIndices);
2882 if (anIndices.Contains(aSubShape))
2883 anIndex = anIndices.FindIndex(aSubShape);
2886 if(anIndex < 0) return NULL;
2888 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2890 anArray->SetValue(1, anIndex);
2892 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
2893 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2895 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
2896 << theShapeWhere << ", " << theShapeWhat << ")";