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
21 #include <Standard_Stream.hxx>
23 #include "GEOMImpl_IShapesOperations.hxx"
25 #include "GEOMImpl_Types.hxx"
27 #include "GEOMImpl_VectorDriver.hxx"
28 #include "GEOMImpl_ShapeDriver.hxx"
29 #include "GEOMImpl_CopyDriver.hxx"
30 #include "GEOMImpl_GlueDriver.hxx"
32 #include "GEOMImpl_IVector.hxx"
33 #include "GEOMImpl_IShapes.hxx"
34 #include "GEOMImpl_IGlue.hxx"
36 #include "GEOMImpl_Block6Explorer.hxx"
38 #include "GEOM_Function.hxx"
39 #include "GEOM_PythonDump.hxx"
41 #include "GEOMAlgo_FinderShapeOn1.hxx"
42 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
43 #include "GEOMAlgo_FinderShapeOn2.hxx"
44 #include "GEOMAlgo_ClsfBox.hxx"
45 #include "GEOMAlgo_Gluer1.hxx"
46 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
47 #include "GEOMAlgo_CoupleOfShapes.hxx"
48 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
50 #include "utilities.h"
52 #include "Utils_ExceptHandlers.hxx"
54 #include <TFunction_DriverTable.hxx>
55 #include <TFunction_Driver.hxx>
56 #include <TFunction_Logbook.hxx>
57 #include <TDataStd_Integer.hxx>
58 #include <TDataStd_IntegerArray.hxx>
59 #include <TDF_Tool.hxx>
61 #include <BRepExtrema_ExtCF.hxx>
63 #include <BRep_Tool.hxx>
64 #include <BRep_Builder.hxx>
65 #include <BRepTools.hxx>
66 #include <BRepGProp.hxx>
67 #include <BRepAdaptor_Curve.hxx>
68 #include <BRepAdaptor_Surface.hxx>
69 #include <BRepBndLib.hxx>
70 #include <BRepBuilderAPI_MakeFace.hxx>
71 #include <BRepMesh_IncrementalMesh.hxx>
76 #include <TopoDS_Shape.hxx>
77 #include <TopoDS_Solid.hxx>
78 #include <TopoDS_Face.hxx>
79 #include <TopoDS_Edge.hxx>
80 #include <TopoDS_Vertex.hxx>
81 #include <TopoDS_Compound.hxx>
82 #include <TopoDS_Iterator.hxx>
83 #include <TopExp_Explorer.hxx>
84 #include <TopLoc_Location.hxx>
85 #include <TopTools_MapOfShape.hxx>
86 #include <TopTools_MapOfOrientedShape.hxx>
87 #include <TopTools_Array1OfShape.hxx>
88 #include <TopTools_ListIteratorOfListOfShape.hxx>
89 #include <TopTools_IndexedMapOfShape.hxx>
91 #include <Geom_Surface.hxx>
92 #include <Geom_Plane.hxx>
93 #include <Geom_SphericalSurface.hxx>
94 #include <Geom_CylindricalSurface.hxx>
95 #include <GeomAdaptor_Surface.hxx>
97 #include <GeomLib_Tool.hxx>
98 #include <Geom2d_Curve.hxx>
100 #include <Bnd_Box.hxx>
101 #include <GProp_GProps.hxx>
102 #include <gp_Pnt.hxx>
103 #include <gp_Lin.hxx>
104 #include <TColStd_ListOfInteger.hxx>
105 #include <TColStd_ListIteratorOfListOfInteger.hxx>
106 #include <TColStd_Array1OfReal.hxx>
107 #include <TColStd_HArray1OfInteger.hxx>
111 #include <Standard_Failure.hxx>
112 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
114 //=============================================================================
118 //=============================================================================
119 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
120 : GEOM_IOperations(theEngine, theDocID)
122 MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
125 //=============================================================================
129 //=============================================================================
130 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
132 MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
136 //=============================================================================
140 //=============================================================================
141 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
142 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
146 if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
148 //Add a new Edge object
149 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
151 //Add a new Vector function
152 Handle(GEOM_Function) aFunction =
153 anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
155 //Check if the function is set correctly
156 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
158 GEOMImpl_IVector aPI (aFunction);
160 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
161 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
162 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
164 aPI.SetPoint1(aRef1);
165 aPI.SetPoint2(aRef2);
167 //Compute the Edge value
169 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
172 if (!GetSolver()->ComputeFunction(aFunction)) {
173 SetErrorCode("Vector driver failed");
177 catch (Standard_Failure) {
178 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
179 SetErrorCode(aFail->GetMessageString());
183 //Make a Python command
184 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
185 << thePnt1 << ", " << thePnt2 << ")";
191 //=============================================================================
195 //=============================================================================
196 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
197 (list<Handle(GEOM_Object)> theShapes)
199 return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
202 //=============================================================================
206 //=============================================================================
207 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
208 const bool isPlanarWanted)
212 if (theWire.IsNull()) return NULL;
214 //Add a new Face object
215 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
217 //Add a new Shape function for creation of a face from a wire
218 Handle(GEOM_Function) aFunction =
219 aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
220 if (aFunction.IsNull()) return NULL;
222 //Check if the function is set correctly
223 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
225 GEOMImpl_IShapes aCI (aFunction);
227 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
229 if (aRefWire.IsNull()) return NULL;
231 aCI.SetBase(aRefWire);
232 aCI.SetIsPlanar(isPlanarWanted);
234 //Compute the Face value
236 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
239 if (!GetSolver()->ComputeFunction(aFunction)) {
240 SetErrorCode("Shape driver failed to compute a face");
244 catch (Standard_Failure) {
245 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
246 SetErrorCode(aFail->GetMessageString());
250 //Make a Python command
251 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
252 << theWire << ", " << (int)isPlanarWanted << ")";
258 //=============================================================================
262 //=============================================================================
263 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
264 (list<Handle(GEOM_Object)> theShapes,
265 const bool isPlanarWanted)
270 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
273 Handle(GEOM_Function) aFunction =
274 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
275 if (aFunction.IsNull()) return NULL;
277 //Check if the function is set correctly
278 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
280 GEOMImpl_IShapes aCI (aFunction);
282 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
285 list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
286 for (; it != theShapes.end(); it++) {
287 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
288 if (aRefSh.IsNull()) {
289 SetErrorCode("NULL argument shape for the face construction");
292 aShapesSeq->Append(aRefSh);
294 aCI.SetShapes(aShapesSeq);
296 aCI.SetIsPlanar(isPlanarWanted);
300 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
303 if (!GetSolver()->ComputeFunction(aFunction)) {
304 SetErrorCode("Shape driver failed");
308 catch (Standard_Failure) {
309 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
310 SetErrorCode(aFail->GetMessageString());
314 //Make a Python command
315 GEOM::TPythonDump pd (aFunction);
316 pd << aShape << " = geompy.MakeFaceWires([";
319 it = theShapes.begin();
320 if (it != theShapes.end()) {
322 while (it != theShapes.end()) {
323 pd << ", " << (*it++);
326 pd << "], " << (int)isPlanarWanted << ")";
332 //=============================================================================
336 //=============================================================================
337 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
338 (list<Handle(GEOM_Object)> theShapes)
340 return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
343 //=============================================================================
347 //=============================================================================
348 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
349 (list<Handle(GEOM_Object)> theShapes)
351 return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
354 //=============================================================================
358 //=============================================================================
359 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
363 if (theShell.IsNull()) return NULL;
365 //Add a new Solid object
366 Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
368 //Add a new Solid function for creation of a solid from a shell
369 Handle(GEOM_Function) aFunction =
370 aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
371 if (aFunction.IsNull()) return NULL;
373 //Check if the function is set correctly
374 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
376 GEOMImpl_IShapes aCI (aFunction);
378 Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
380 if (aRefShell.IsNull()) return NULL;
382 aCI.SetBase(aRefShell);
384 //Compute the Solid value
386 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
389 if (!GetSolver()->ComputeFunction(aFunction)) {
390 SetErrorCode("Solid driver failed");
394 catch (Standard_Failure) {
395 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
396 SetErrorCode(aFail->GetMessageString());
400 //Make a Python command
401 GEOM::TPythonDump(aFunction) << aSolid
402 << " = geompy.MakeSolid(" << theShell << ")";
408 //=============================================================================
412 //=============================================================================
413 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
414 (list<Handle(GEOM_Object)> theShapes)
416 return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
419 //=============================================================================
423 //=============================================================================
424 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
425 (list<Handle(GEOM_Object)> theShapes,
426 const Standard_Integer theObjectType,
427 const Standard_Integer theFunctionType,
428 const TCollection_AsciiString& theMethodName)
433 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
436 Handle(GEOM_Function) aFunction =
437 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
438 if (aFunction.IsNull()) return NULL;
440 //Check if the function is set correctly
441 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
443 GEOMImpl_IShapes aCI (aFunction);
445 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
448 list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
449 for (; it != theShapes.end(); it++) {
450 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
451 if (aRefSh.IsNull()) {
452 SetErrorCode("NULL argument shape for the shape construction");
455 aShapesSeq->Append(aRefSh);
457 aCI.SetShapes(aShapesSeq);
461 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
464 if (!GetSolver()->ComputeFunction(aFunction)) {
465 SetErrorCode("Shape driver failed");
469 catch (Standard_Failure) {
470 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
471 SetErrorCode(aFail->GetMessageString());
475 //Make a Python command
476 GEOM::TPythonDump pd (aFunction);
477 pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
480 it = theShapes.begin();
481 if (it != theShapes.end()) {
483 while (it != theShapes.end()) {
484 pd << ", " << (*it++);
493 //=============================================================================
497 //=============================================================================
498 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
499 (Handle(GEOM_Object) theShape,
500 const Standard_Real theTolerance)
504 if (theShape.IsNull()) return NULL;
506 //Add a new Glued object
507 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
509 //Add a new Glue function
510 Handle(GEOM_Function) aFunction;
511 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
512 if (aFunction.IsNull()) return NULL;
514 //Check if the function is set correctly
515 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
517 GEOMImpl_IGlue aCI (aFunction);
519 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
520 if (aRefShape.IsNull()) return NULL;
522 aCI.SetBase(aRefShape);
523 aCI.SetTolerance(theTolerance);
525 //Compute the sub-shape value
526 Standard_Boolean isWarning = Standard_False;
528 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
531 if (!GetSolver()->ComputeFunction(aFunction)) {
532 SetErrorCode("Shape driver failed to glue faces");
536 catch (Standard_Failure) {
537 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
538 SetErrorCode(aFail->GetMessageString());
539 // to provide warning
540 if (!aFunction->GetValue().IsNull()) {
541 isWarning = Standard_True;
547 //Make a Python command
548 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
549 << theShape << ", " << theTolerance << ")";
551 // to provide warning
552 if (!isWarning) SetErrorCode(OK);
556 //=============================================================================
560 //=============================================================================
561 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
562 (Handle(GEOM_Object) theShape,
563 const Standard_Real theTolerance)
567 if (theShape.IsNull()) return NULL;
568 TopoDS_Shape aShape = theShape->GetValue();
569 if (aShape.IsNull()) return NULL;
571 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
573 Standard_Integer iErr;
575 GEOMAlgo_Gluer1 aGluer;
576 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
577 GEOMAlgo_CoupleOfShapes aCS;
578 GEOMAlgo_ListOfCoupleOfShapes aLCS;
580 //aGluer = new GEOMAlgo_Gluer1;
581 aGluer.SetShape(aShape);
582 aGluer.SetTolerance(theTolerance);
584 iErr = aGluer.ErrorStatus();
585 if (iErr) return NULL;
587 TopTools_ListOfShape listShape;
588 const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
590 aItCS.Initialize(aLCSG);
591 for (; aItCS.More(); aItCS.Next()) {
592 const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
593 listShape.Append(aCSG.Shape1());
596 TopTools_ListIteratorOfListOfShape itSub (listShape);
597 TCollection_AsciiString anAsciiList, anEntry;
598 TopTools_IndexedMapOfShape anIndices;
599 TopExp::MapShapes(aShape, anIndices);
600 Handle(TColStd_HArray1OfInteger) anArray;
601 Handle(GEOM_Object) anObj;
602 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
603 TopoDS_Shape aValue = itSub.Value();
604 anArray = new TColStd_HArray1OfInteger(1,1);
605 anArray->SetValue(1, anIndices.FindIndex(aValue));
606 anObj = GetEngine()->AddSubShape(theShape, anArray);
607 if (!anObj.IsNull()) {
610 // for python command
611 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
612 anAsciiList += anEntry;
617 //Make a Python command
618 if(anAsciiList.Length()>0)
619 anAsciiList.Trunc(anAsciiList.Length() - 1);
620 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
621 GEOM::TPythonDump pd (aFunction, /*append=*/true);
622 pd << "[" << anAsciiList.ToCString();
623 pd << "] = geompy.GetGlueFaces" << theShape << ", " << theTolerance << ")";
631 //=============================================================================
633 * MakeGlueFacesByList
635 //=============================================================================
636 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList
637 (Handle(GEOM_Object) theShape,
638 const Standard_Real theTolerance,
639 list<Handle(GEOM_Object)> theFaces)
643 if (theShape.IsNull()) return NULL;
645 //Add a new Glued object
646 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
648 //Add a new Glue function
649 Handle(GEOM_Function) aFunction;
650 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
651 if (aFunction.IsNull()) return NULL;
653 //Check if the function is set correctly
654 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
656 GEOMImpl_IGlue aCI (aFunction);
658 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
659 if (aRefShape.IsNull()) return NULL;
661 aCI.SetBase(aRefShape);
662 aCI.SetTolerance(theTolerance);
663 Handle(TColStd_HSequenceOfTransient) aFaces = new TColStd_HSequenceOfTransient;
664 list<Handle(GEOM_Object)>::iterator it = theFaces.begin();
665 for (; it != theFaces.end(); it++) {
666 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
667 if (aRefSh.IsNull()) {
668 SetErrorCode("NULL argument shape for the shape construction");
671 aFaces->Append(aRefSh);
673 aCI.SetFaces(aFaces);
675 //Compute the sub-shape value
676 Standard_Boolean isWarning = Standard_False;
678 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
681 if (!GetSolver()->ComputeFunction(aFunction)) {
682 SetErrorCode("Shape driver failed to glue faces");
686 catch (Standard_Failure) {
687 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
688 SetErrorCode(aFail->GetMessageString());
689 // to provide warning
690 if (!aFunction->GetValue().IsNull()) {
691 isWarning = Standard_True;
697 //Make a Python command
699 GEOM::TPythonDump pd(aFunction);
700 pd << aGlued << " = geompy.MakeGlueFacesByList("
701 << theShape << ", " << theTolerance << ", [";
703 it = theFaces.begin();
704 if (it != theFaces.end()) {
706 while (it != theFaces.end()) {
707 pd << ", " << (*it++);
713 // to provide warning
714 if (!isWarning) SetErrorCode(OK);
720 //=============================================================================
724 //=============================================================================
725 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
726 (Handle(GEOM_Object) theShape,
727 const Standard_Integer theShapeType,
728 const Standard_Boolean isSorted)
732 if (theShape.IsNull()) return NULL;
733 TopoDS_Shape aShape = theShape->GetValue();
734 if (aShape.IsNull()) return NULL;
736 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
737 Handle(GEOM_Object) anObj;
738 Handle(GEOM_Function) aFunction;
739 TopTools_MapOfShape mapShape;
740 TopTools_ListOfShape listShape;
742 if (aShape.ShapeType() == TopAbs_COMPOUND &&
743 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
744 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
745 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
746 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
747 for (; It.More(); It.Next()) {
748 if (mapShape.Add(It.Value())) {
749 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
750 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
751 listShape.Append(It.Value());
756 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
757 for (; exp.More(); exp.Next())
758 if (mapShape.Add(exp.Current()))
759 listShape.Append(exp.Current());
762 if (listShape.IsEmpty()) {
763 SetErrorCode("The given shape has no sub-shapes of the requested type");
768 SortShapes(listShape);
770 TopTools_IndexedMapOfShape anIndices;
771 TopExp::MapShapes(aShape, anIndices);
772 Handle(TColStd_HArray1OfInteger) anArray;
774 TopTools_ListIteratorOfListOfShape itSub (listShape);
775 TCollection_AsciiString anAsciiList, anEntry;
776 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
777 TopoDS_Shape aValue = itSub.Value();
778 anArray = new TColStd_HArray1OfInteger(1,1);
779 anArray->SetValue(1, anIndices.FindIndex(aValue));
780 anObj = GetEngine()->AddSubShape(theShape, anArray);
781 if (!anObj.IsNull()) {
784 // for python command
785 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
786 anAsciiList += anEntry;
791 //Make a Python command
792 anAsciiList.Trunc(anAsciiList.Length() - 1);
794 aFunction = theShape->GetLastFunction();
796 GEOM::TPythonDump pd (aFunction, /*append=*/true);
797 pd << "[" << anAsciiList.ToCString();
798 pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
799 pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
806 //=============================================================================
810 //=============================================================================
811 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
812 (Handle(GEOM_Object) theShape,
813 const Standard_Integer theShapeType,
814 const Standard_Boolean isSorted)
818 if (theShape.IsNull()) return NULL;
819 TopoDS_Shape aShape = theShape->GetValue();
820 if (aShape.IsNull()) return NULL;
822 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
823 TopTools_MapOfShape mapShape;
824 TopTools_ListOfShape listShape;
826 if (aShape.ShapeType() == TopAbs_COMPOUND &&
827 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
828 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
829 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
830 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
831 for (; It.More(); It.Next()) {
832 if (mapShape.Add(It.Value())) {
833 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
834 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
835 listShape.Append(It.Value());
840 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
841 for (; exp.More(); exp.Next())
842 if (mapShape.Add(exp.Current()))
843 listShape.Append(exp.Current());
846 if (listShape.IsEmpty()) {
847 SetErrorCode("The given shape has no sub-shapes of the requested type");
852 SortShapes(listShape);
854 TopTools_IndexedMapOfShape anIndices;
855 TopExp::MapShapes(aShape, anIndices);
856 Handle(TColStd_HArray1OfInteger) anArray;
858 TopTools_ListIteratorOfListOfShape itSub (listShape);
859 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
860 TopoDS_Shape aValue = itSub.Value();
861 aSeq->Append(anIndices.FindIndex(aValue));
864 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
866 //Make a Python command
867 GEOM::TPythonDump pd (aFunction, /*append=*/true);
868 pd << "listSubShapeIDs = geompy.SubShapeAll";
869 pd << (isSorted ? "SortedIDs(" : "IDs(");
870 pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
876 //=============================================================================
880 //=============================================================================
881 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
882 (Handle(GEOM_Object) theMainShape,
883 const Standard_Integer theID)
887 if (theMainShape.IsNull()) return NULL;
889 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
890 anArray->SetValue(1, theID);
891 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
892 if (anObj.IsNull()) {
893 SetErrorCode("Can not get a sub-shape with the given ID");
897 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
899 //Make a Python command
900 GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
901 << theMainShape << ", [" << theID << "])";
907 //=============================================================================
911 //=============================================================================
912 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
913 Handle(GEOM_Object) theSubShape)
917 TopoDS_Shape aMainShape = theMainShape->GetValue();
918 TopoDS_Shape aSubShape = theSubShape->GetValue();
920 if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
922 TopTools_IndexedMapOfShape anIndices;
923 TopExp::MapShapes(aMainShape, anIndices);
924 if (anIndices.Contains(aSubShape)) {
926 return anIndices.FindIndex(aSubShape);
932 //=============================================================================
936 //=============================================================================
937 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
938 Handle(GEOM_Object) theSubShape)
942 TopoDS_Shape aMainShape = theMainShape->GetValue();
943 TopoDS_Shape aSubShape = theSubShape->GetValue();
945 if (aMainShape.IsNull() || aSubShape.IsNull()) {
946 SetErrorCode("Null argument shape given");
951 if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
953 TopTools_ListOfShape CL;
954 CL.Append(aMainShape);
955 TopTools_ListIteratorOfListOfShape itC;
956 for (itC.Initialize(CL); itC.More(); itC.Next()) {
957 for (it.Initialize(itC.Value()); it.More(); it.Next()) {
958 if (it.Value().ShapeType() == TopAbs_COMPOUND) {
959 if (it.Value().IsSame(aSubShape))
963 CL.Append(it.Value());
968 TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
969 TopTools_MapOfShape M;
970 for (; anExp.More(); anExp.Next()) {
971 if (M.Add(anExp.Current())) {
972 if (anExp.Current().IsSame(aSubShape))
979 SetErrorCode("The sub-shape does not belong to the main shape");
983 //=============================================================================
987 //=============================================================================
988 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
992 TCollection_AsciiString aTypeName ("Null Shape");
994 TopoDS_Shape aShape = theShape->GetValue();
998 switch (aShape.ShapeType() )
1000 case TopAbs_COMPOUND:
1001 aTypeName = "Compound";
1003 case TopAbs_COMPSOLID:
1004 aTypeName = "Compound Solid";
1007 aTypeName = "Solid";
1010 aTypeName = "Shell";
1014 BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1015 if (surf.GetType() == GeomAbs_Plane)
1016 aTypeName = "Plane";
1017 else if (surf.GetType() == GeomAbs_Cylinder)
1018 aTypeName = "Cylindrical Face";
1019 else if (surf.GetType() == GeomAbs_Sphere)
1020 aTypeName = "Spherical Face";
1021 else if (surf.GetType() == GeomAbs_Torus)
1022 aTypeName = "Toroidal Face";
1023 else if (surf.GetType() == GeomAbs_Cone)
1024 aTypeName = "Conical Face";
1026 aTypeName = "GEOM::FACE";
1034 BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1035 if (curv.GetType() == GeomAbs_Line) {
1036 if ((Abs(curv.FirstParameter()) >= 1E6) ||
1037 (Abs(curv.LastParameter()) >= 1E6))
1040 aTypeName = "Edge" ;
1041 } else if (curv.GetType() == GeomAbs_Circle) {
1042 if (curv.IsClosed())
1043 aTypeName = "Circle";
1052 aTypeName = "Vertex";
1055 aTypeName = "Shape";
1058 aTypeName = "Shape of unknown type";
1065 //=============================================================================
1069 //=============================================================================
1070 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
1074 Standard_Integer nb = 0;
1076 if (theShape.IsNull()) return -1;
1077 TopoDS_Shape aShape = theShape->GetValue();
1078 if (aShape.IsNull()) return -1;
1080 TopTools_MapOfShape mapShape;
1082 TopExp_Explorer exp (aShape, TopAbs_FACE);
1083 for (; exp.More(); exp.Next())
1084 if (mapShape.Add(exp.Current()))
1091 //=============================================================================
1095 //=============================================================================
1096 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
1100 Standard_Integer nb = 0;
1102 if (theShape.IsNull()) return -1;
1103 TopoDS_Shape aShape = theShape->GetValue();
1104 if (aShape.IsNull()) return -1;
1106 TopTools_MapOfShape mapShape;
1108 TopExp_Explorer exp (aShape, TopAbs_EDGE);
1109 for (; exp.More(); exp.Next())
1110 if (mapShape.Add(exp.Current()))
1117 //=============================================================================
1121 //=============================================================================
1122 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
1126 if (theShape.IsNull()) return NULL;
1128 //Add a new reversed object
1129 Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
1131 //Add a new Revese function
1132 Handle(GEOM_Function) aFunction;
1133 aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
1134 if (aFunction.IsNull()) return NULL;
1136 //Check if the function is set correctly
1137 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
1139 GEOMImpl_IShapes aSI (aFunction);
1141 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1142 if (aRefShape.IsNull()) return NULL;
1144 aSI.SetBase(aRefShape);
1146 //Compute the sub-shape value
1148 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1151 if (!GetSolver()->ComputeFunction(aFunction)) {
1152 SetErrorCode("Shape driver failed to reverse shape");
1156 catch (Standard_Failure) {
1157 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1158 SetErrorCode(aFail->GetMessageString());
1162 //Make a Python command
1163 GEOM::TPythonDump(aFunction) << aReversed
1164 << " = geompy.ChangeOrientation(" << theShape << ")";
1170 //=============================================================================
1174 //=============================================================================
1175 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
1176 (Handle(GEOM_Object) theShape)
1180 if (theShape.IsNull()) return NULL;
1181 TopoDS_Shape aShape = theShape->GetValue();
1182 if (aShape.IsNull()) return NULL;
1184 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1186 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1187 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1188 (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1190 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1193 SetErrorCode("The given shape has no faces");
1197 TopTools_IndexedMapOfShape anIndices;
1198 TopExp::MapShapes(aShape, anIndices);
1200 Standard_Integer id;
1201 for (; ind <= nbFaces; ind++) {
1202 if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1203 id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1208 //The explode doesn't change object so no new function is required.
1209 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1211 //Make a Python command
1212 GEOM::TPythonDump(aFunction, /*append=*/true)
1213 << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
1219 //=======================================================================
1220 //function : GetSharedShapes
1222 //=======================================================================
1224 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1225 (Handle(GEOM_Object) theShape1,
1226 Handle(GEOM_Object) theShape2,
1227 const Standard_Integer theShapeType)
1231 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
1233 TopoDS_Shape aShape1 = theShape1->GetValue();
1234 TopoDS_Shape aShape2 = theShape2->GetValue();
1236 if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
1238 TopTools_IndexedMapOfShape anIndices;
1239 TopExp::MapShapes(aShape1, anIndices);
1240 Handle(TColStd_HArray1OfInteger) anArray;
1242 TopTools_IndexedMapOfShape mapShape1;
1243 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
1245 Handle(GEOM_Object) anObj;
1246 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1247 TCollection_AsciiString anAsciiList, anEntry;
1249 TopTools_MapOfShape mapShape2;
1250 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
1251 for (; exp.More(); exp.Next()) {
1252 TopoDS_Shape aSS = exp.Current();
1253 if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
1254 anArray = new TColStd_HArray1OfInteger(1,1);
1255 anArray->SetValue(1, anIndices.FindIndex(aSS));
1256 anObj = GetEngine()->AddSubShape(theShape1, anArray);
1257 aSeq->Append(anObj);
1259 // for python command
1260 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1261 anAsciiList += anEntry;
1266 if (aSeq->IsEmpty()) {
1267 SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
1271 //Make a Python command
1272 anAsciiList.Trunc(anAsciiList.Length() - 1);
1274 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1276 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1277 << "] = geompy.GetSharedShapes(" << theShape1 << ", "
1278 << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1284 //=============================================================================
1288 //=============================================================================
1289 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump,
1290 const GEOMAlgo_State theState)
1293 case GEOMAlgo_ST_IN:
1294 theDump << "geompy.GEOM.ST_IN";
1296 case GEOMAlgo_ST_OUT:
1297 theDump << "geompy.GEOM.ST_OUT";
1299 case GEOMAlgo_ST_ON:
1300 theDump << "geompy.GEOM.ST_ON";
1302 case GEOMAlgo_ST_ONIN:
1303 theDump << "geompy.GEOM.ST_ONIN";
1305 case GEOMAlgo_ST_ONOUT:
1306 theDump << "geompy.GEOM.ST_ONOUT";
1309 theDump << "geompy.GEOM.ST_UNKNOWN";
1315 //=======================================================================
1316 //function : checkTypeShapesOn
1318 * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
1319 * \param theShapeType - the shape type to check
1320 * \retval bool - result of the check
1322 //=======================================================================
1324 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
1326 if (theShapeType != TopAbs_VERTEX &&
1327 theShapeType != TopAbs_EDGE &&
1328 theShapeType != TopAbs_FACE &&
1329 theShapeType != TopAbs_SOLID) {
1330 SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1336 //=======================================================================
1337 //function : makePlane
1339 * \brief Creates Geom_Plane
1340 * \param theAx1 - shape object defining plane parameters
1341 * \retval Handle(Geom_Surface) - resulting surface
1343 //=======================================================================
1345 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
1347 if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1348 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1349 TopoDS_Vertex V1, V2;
1350 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1351 if (V1.IsNull() || V2.IsNull()) {
1352 SetErrorCode("Bad edge given for the plane normal vector");
1355 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1356 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1357 if (aVec.Magnitude() < Precision::Confusion()) {
1358 SetErrorCode("Vector with null magnitude given");
1361 return new Geom_Plane(aLoc, aVec);
1364 //=======================================================================
1365 //function : makeCylinder
1367 * \brief Creates Geom_CylindricalSurface
1368 * \param theAx1 - edge defining cylinder axis
1369 * \param theRadius - cylinder radius
1370 * \retval Handle(Geom_Surface) - resulting surface
1372 //=======================================================================
1374 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
1375 const Standard_Real theRadius)
1377 //Axis of the cylinder
1378 if (anAxis.ShapeType() != TopAbs_EDGE) {
1379 SetErrorCode("Not an edge given for the axis");
1382 TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1383 TopoDS_Vertex V1, V2;
1384 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1385 if (V1.IsNull() || V2.IsNull()) {
1386 SetErrorCode("Bad edge given for the axis");
1389 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1390 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1391 if (aVec.Magnitude() < Precision::Confusion()) {
1392 SetErrorCode("Vector with null magnitude given");
1396 gp_Ax3 anAx3 (aLoc, aVec);
1397 return new Geom_CylindricalSurface(anAx3, theRadius);
1401 //=======================================================================
1402 //function : getShapesOnBoxIDs
1404 * \brief Find IDs of subshapes complying with given status about surface
1405 * \param theBox - the box to check state of subshapes against
1406 * \param theShape - the shape to explore
1407 * \param theShapeType - type of subshape of theShape
1408 * \param theState - required state
1409 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1411 //=======================================================================
1413 Handle(TColStd_HSequenceOfInteger)
1414 GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1415 const Handle(GEOM_Object)& theShape,
1416 const Standard_Integer theShapeType,
1417 GEOMAlgo_State theState)
1419 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1421 TopoDS_Shape aBox = theBox->GetValue();
1422 TopoDS_Shape aShape = theShape->GetValue();
1424 // Check presence of triangulation, build if need
1425 if (!CheckTriangulation(aShape)) {
1426 SetErrorCode("Cannot build triangulation on the shape");
1431 GEOMAlgo_FinderShapeOn2 aFinder;
1432 Standard_Real aTol = 0.0001; // default value
1434 Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
1435 aClsfBox->SetBox(aBox);
1437 aFinder.SetShape(aShape);
1438 aFinder.SetTolerance(aTol);
1439 aFinder.SetClsf(aClsfBox);
1440 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1441 aFinder.SetState(theState);
1444 // Interprete results
1445 Standard_Integer iErr = aFinder.ErrorStatus();
1446 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1448 MESSAGE(" iErr : " << iErr);
1449 TCollection_AsciiString aMsg (" iErr : ");
1450 aMsg += TCollection_AsciiString(iErr);
1454 Standard_Integer iWrn = aFinder.WarningStatus();
1455 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1457 MESSAGE(" *** iWrn : " << iWrn);
1460 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1462 if (listSS.Extent() < 1) {
1463 SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1467 // Fill sequence of object IDs
1468 aSeqOfIDs = new TColStd_HSequenceOfInteger;
1470 TopTools_IndexedMapOfShape anIndices;
1471 TopExp::MapShapes(aShape, anIndices);
1473 TopTools_ListIteratorOfListOfShape itSub (listSS);
1474 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1475 int id = anIndices.FindIndex(itSub.Value());
1476 aSeqOfIDs->Append(id);
1483 //=======================================================================
1484 //function : GetShapesOnBoxIDs
1486 * \brief Find subshapes complying with given status about surface
1487 * \param theBox - the box to check state of subshapes against
1488 * \param theShape - the shape to explore
1489 * \param theShapeType - type of subshape of theShape
1490 * \param theState - required state
1491 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1493 //=======================================================================
1495 Handle(TColStd_HSequenceOfInteger)
1496 GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1497 const Handle(GEOM_Object)& theShape,
1498 const Standard_Integer theShapeType,
1499 GEOMAlgo_State theState)
1501 // Find subshapes ids
1502 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1503 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1504 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1507 // The GetShapesOnBox() doesn't change object so no new function is required.
1508 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
1510 // Make a Python command
1511 GEOM::TPythonDump(aFunction)
1512 << "listShapesOnBoxIDs = geompy.GetShapesOnQuadrangleIDs("
1515 << TopAbs_ShapeEnum(theShapeType) << ", "
1522 //=======================================================================
1523 //function : GetShapesOnBox
1525 * \brief Find subshapes complying with given status about surface
1526 * \param theBox - the box to check state of subshapes against
1527 * \param theShape - the shape to explore
1528 * \param theShapeType - type of subshape of theShape
1529 * \param theState - required state
1530 * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1532 //=======================================================================
1534 Handle(TColStd_HSequenceOfTransient)
1535 GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
1536 const Handle(GEOM_Object)& theShape,
1537 const Standard_Integer theShapeType,
1538 GEOMAlgo_State theState)
1540 // Find subshapes ids
1541 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1542 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1543 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1546 // Find objects by indices
1547 TCollection_AsciiString anAsciiList;
1548 Handle(TColStd_HSequenceOfTransient) aSeq;
1549 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1550 if ( aSeq.IsNull() || aSeq->IsEmpty() )
1553 // Make a Python command
1555 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1556 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1558 GEOM::TPythonDump(aFunction)
1559 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
1562 << TopAbs_ShapeEnum(theShapeType) << ", "
1570 //=======================================================================
1571 //function : getShapesOnSurfaceIDs
1573 * \brief Find IDs of subshapes complying with given status about surface
1574 * \param theSurface - the surface to check state of subshapes against
1575 * \param theShape - the shape to explore
1576 * \param theShapeType - type of subshape of theShape
1577 * \param theState - required state
1578 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1580 //=======================================================================
1582 Handle(TColStd_HSequenceOfInteger)
1583 GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
1584 const TopoDS_Shape& theShape,
1585 TopAbs_ShapeEnum theShapeType,
1586 GEOMAlgo_State theState)
1588 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1590 // Check presence of triangulation, build if need
1591 if (!CheckTriangulation(theShape)) {
1592 SetErrorCode("Cannot build triangulation on the shape");
1597 GEOMAlgo_FinderShapeOn1 aFinder;
1598 Standard_Real aTol = 0.0001; // default value
1600 aFinder.SetShape(theShape);
1601 aFinder.SetTolerance(aTol);
1602 aFinder.SetSurface(theSurface);
1603 aFinder.SetShapeType(theShapeType);
1604 aFinder.SetState(theState);
1606 // Sets the minimal number of inner points for the faces that do not have own
1607 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1609 aFinder.SetNbPntsMin(3);
1610 // Sets the maximal number of inner points for edges or faces.
1611 // It is usefull for the cases when this number is very big (e.g =2000) to improve
1612 // the performance. If this value =0, all inner points will be taken into account.
1614 aFinder.SetNbPntsMax(100);
1618 // Interprete results
1619 Standard_Integer iErr = aFinder.ErrorStatus();
1620 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1622 MESSAGE(" iErr : " << iErr);
1623 TCollection_AsciiString aMsg (" iErr : ");
1624 aMsg += TCollection_AsciiString(iErr);
1628 Standard_Integer iWrn = aFinder.WarningStatus();
1629 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1631 MESSAGE(" *** iWrn : " << iWrn);
1634 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1636 if (listSS.Extent() < 1) {
1637 SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1641 // Fill sequence of object IDs
1642 aSeqOfIDs = new TColStd_HSequenceOfInteger;
1644 TopTools_IndexedMapOfShape anIndices;
1645 TopExp::MapShapes(theShape, anIndices);
1647 TopTools_ListIteratorOfListOfShape itSub (listSS);
1648 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1649 int id = anIndices.FindIndex(itSub.Value());
1650 aSeqOfIDs->Append(id);
1656 //=======================================================================
1657 //function : getObjectsShapesOn
1659 * \brief Find shape objects and their entries by their ids
1660 * \param theShapeIDs - incoming shape ids
1661 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1662 * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
1664 //=======================================================================
1666 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
1667 getObjectsShapesOn(const Handle(GEOM_Object)& theShape,
1668 const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
1669 TCollection_AsciiString & theShapeEntries)
1671 Handle(TColStd_HSequenceOfTransient) aSeq;
1673 if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
1675 aSeq = new TColStd_HSequenceOfTransient;
1676 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1677 TCollection_AsciiString anEntry;
1678 for ( int i = 1; i <= theShapeIDs->Length(); ++i )
1680 anArray->SetValue(1, theShapeIDs->Value( i ));
1681 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
1682 aSeq->Append( anObj );
1684 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1685 if ( i != 1 ) theShapeEntries += ",";
1686 theShapeEntries += anEntry;
1692 //=======================================================================
1693 //function : getShapesOnSurface
1695 * \brief Find subshapes complying with given status about surface
1696 * \param theSurface - the surface to check state of subshapes against
1697 * \param theShape - the shape to explore
1698 * \param theShapeType - type of subshape of theShape
1699 * \param theState - required state
1700 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1701 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1703 //=======================================================================
1705 Handle(TColStd_HSequenceOfTransient)
1706 GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
1707 const Handle(GEOM_Object)& theShape,
1708 TopAbs_ShapeEnum theShapeType,
1709 GEOMAlgo_State theState,
1710 TCollection_AsciiString & theShapeEntries)
1712 // Find subshapes ids
1713 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1714 getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
1715 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1718 return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
1721 //=============================================================================
1725 //=============================================================================
1726 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
1727 (const Handle(GEOM_Object)& theShape,
1728 const Standard_Integer theShapeType,
1729 const Handle(GEOM_Object)& theAx1,
1730 const GEOMAlgo_State theState)
1734 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1736 TopoDS_Shape aShape = theShape->GetValue();
1737 TopoDS_Shape anAx1 = theAx1->GetValue();
1739 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1741 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1742 if ( !checkTypeShapesOn( theShapeType ))
1746 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1747 if ( aPlane.IsNull() )
1751 TCollection_AsciiString anAsciiList;
1752 Handle(TColStd_HSequenceOfTransient) aSeq;
1753 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1754 if ( aSeq.IsNull() || aSeq->Length() == 0 )
1757 // Make a Python command
1759 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1760 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1762 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1763 << "] = geompy.GetShapesOnPlane(" << theShape << ", "
1764 << aShapeType << ", " << theAx1 << ", " << theState << ")";
1770 //=============================================================================
1772 * GetShapesOnPlaneWithLocation
1774 //=============================================================================
1775 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
1776 (const Handle(GEOM_Object)& theShape,
1777 const Standard_Integer theShapeType,
1778 const Handle(GEOM_Object)& theAx1,
1779 const Handle(GEOM_Object)& thePnt,
1780 const GEOMAlgo_State theState)
1784 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
1786 TopoDS_Shape aShape = theShape->GetValue();
1787 TopoDS_Shape anAx1 = theAx1->GetValue();
1788 TopoDS_Shape anPnt = thePnt->GetValue();
1790 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
1792 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1793 if ( !checkTypeShapesOn( theShapeType ))
1797 if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
1798 TopoDS_Vertex V1, V2, V3;
1799 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1800 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1802 if (V1.IsNull() || V2.IsNull()) {
1803 SetErrorCode("Bad edge given for the plane normal vector");
1806 V3 = TopoDS::Vertex(anPnt);
1809 SetErrorCode("Bad vertex given for the plane location");
1812 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
1813 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
1815 if (aVec.Magnitude() < Precision::Confusion()) {
1816 SetErrorCode("Vector with null magnitude given");
1819 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
1821 if ( aPlane.IsNull() )
1825 TCollection_AsciiString anAsciiList;
1826 Handle(TColStd_HSequenceOfTransient) aSeq;
1827 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1828 if ( aSeq.IsNull() || aSeq->Length() == 0 )
1831 // Make a Python command
1833 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1834 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1836 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1837 << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
1838 << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
1844 //=============================================================================
1846 * GetShapesOnCylinder
1848 //=============================================================================
1849 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
1850 (const Handle(GEOM_Object)& theShape,
1851 const Standard_Integer theShapeType,
1852 const Handle(GEOM_Object)& theAxis,
1853 const Standard_Real theRadius,
1854 const GEOMAlgo_State theState)
1858 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1860 TopoDS_Shape aShape = theShape->GetValue();
1861 TopoDS_Shape anAxis = theAxis->GetValue();
1863 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1865 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1866 if ( !checkTypeShapesOn( aShapeType ))
1869 // Create a cylinder surface
1870 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1871 if ( aCylinder.IsNull() )
1875 TCollection_AsciiString anAsciiList;
1876 Handle(TColStd_HSequenceOfTransient) aSeq;
1877 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
1878 if ( aSeq.IsNull() || aSeq->Length() == 0 )
1881 // Make a Python command
1883 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1884 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1886 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1887 << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
1888 << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
1894 //=============================================================================
1898 //=============================================================================
1899 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
1900 (const Handle(GEOM_Object)& theShape,
1901 const Standard_Integer theShapeType,
1902 const Handle(GEOM_Object)& theCenter,
1903 const Standard_Real theRadius,
1904 const GEOMAlgo_State theState)
1908 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1910 TopoDS_Shape aShape = theShape->GetValue();
1911 TopoDS_Shape aCenter = theCenter->GetValue();
1913 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1915 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1916 if ( !checkTypeShapesOn( aShapeType ))
1919 // Center of the sphere
1920 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1921 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1923 gp_Ax3 anAx3 (aLoc, gp::DZ());
1924 Handle(Geom_SphericalSurface) aSphere =
1925 new Geom_SphericalSurface(anAx3, theRadius);
1928 TCollection_AsciiString anAsciiList;
1929 Handle(TColStd_HSequenceOfTransient) aSeq;
1930 aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
1931 if ( aSeq.IsNull() || aSeq->Length() == 0 )
1934 // Make a Python command
1936 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1937 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1939 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1940 << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
1941 << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
1947 //=============================================================================
1949 * GetShapesOnPlaneIDs
1951 //=============================================================================
1952 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
1953 (const Handle(GEOM_Object)& theShape,
1954 const Standard_Integer theShapeType,
1955 const Handle(GEOM_Object)& theAx1,
1956 const GEOMAlgo_State theState)
1960 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1962 TopoDS_Shape aShape = theShape->GetValue();
1963 TopoDS_Shape anAx1 = theAx1->GetValue();
1965 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1967 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1968 if ( !checkTypeShapesOn( aShapeType ))
1972 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1973 if ( aPlane.IsNull() )
1977 Handle(TColStd_HSequenceOfInteger) aSeq;
1978 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
1980 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
1981 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
1983 // Make a Python command
1984 GEOM::TPythonDump(aFunction, /*append=*/true)
1985 << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
1986 << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
1992 //=============================================================================
1994 * GetShapesOnPlaneWithLocationIDs
1996 //=============================================================================
1997 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
1998 (const Handle(GEOM_Object)& theShape,
1999 const Standard_Integer theShapeType,
2000 const Handle(GEOM_Object)& theAx1,
2001 const Handle(GEOM_Object)& thePnt,
2002 const GEOMAlgo_State theState)
2006 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2008 TopoDS_Shape aShape = theShape->GetValue();
2009 TopoDS_Shape anAx1 = theAx1->GetValue();
2010 TopoDS_Shape anPnt = thePnt->GetValue();
2012 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2014 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2015 if ( !checkTypeShapesOn( aShapeType ))
2019 if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
2020 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2021 TopoDS_Vertex V1, V2, V3;
2022 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2023 if (V1.IsNull() || V2.IsNull()) {
2024 SetErrorCode("Bad edge given for the plane normal vector");
2027 V3 = TopoDS::Vertex(anPnt);
2029 SetErrorCode("Bad vertex given for the plane location");
2032 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2033 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2034 if (aVec.Magnitude() < Precision::Confusion()) {
2035 SetErrorCode("Vector with null magnitude given");
2039 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2040 if ( aPlane.IsNull() )
2044 Handle(TColStd_HSequenceOfInteger) aSeq;
2045 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
2047 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
2048 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
2050 // Make a Python command
2051 GEOM::TPythonDump(aFunction, /*append=*/true)
2052 << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
2053 << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")";
2059 //=============================================================================
2061 * GetShapesOnCylinderIDs
2063 //=============================================================================
2064 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
2065 (const Handle(GEOM_Object)& theShape,
2066 const Standard_Integer theShapeType,
2067 const Handle(GEOM_Object)& theAxis,
2068 const Standard_Real theRadius,
2069 const GEOMAlgo_State theState)
2073 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2075 TopoDS_Shape aShape = theShape->GetValue();
2076 TopoDS_Shape anAxis = theAxis->GetValue();
2078 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2080 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2081 if ( !checkTypeShapesOn( aShapeType ))
2084 // Create a cylinder surface
2085 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2086 if ( aCylinder.IsNull() )
2090 Handle(TColStd_HSequenceOfInteger) aSeq;
2091 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
2093 // The GetShapesOnCylinder() doesn't change object so no new function is required.
2094 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
2096 // Make a Python command
2097 GEOM::TPythonDump(aFunction, /*append=*/true)
2098 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2099 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
2100 << theRadius << ", " << theState << ")";
2106 //=============================================================================
2108 * GetShapesOnSphereIDs
2110 //=============================================================================
2111 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
2112 (const Handle(GEOM_Object)& theShape,
2113 const Standard_Integer theShapeType,
2114 const Handle(GEOM_Object)& theCenter,
2115 const Standard_Real theRadius,
2116 const GEOMAlgo_State theState)
2120 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
2122 TopoDS_Shape aShape = theShape->GetValue();
2123 TopoDS_Shape aCenter = theCenter->GetValue();
2125 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
2127 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2128 if ( !checkTypeShapesOn( aShapeType ))
2131 // Center of the sphere
2132 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
2133 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
2135 gp_Ax3 anAx3 (aLoc, gp::DZ());
2136 Handle(Geom_SphericalSurface) aSphere =
2137 new Geom_SphericalSurface(anAx3, theRadius);
2140 Handle(TColStd_HSequenceOfInteger) aSeq;
2141 aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
2143 // The GetShapesOnSphere() doesn't change object so no new function is required.
2144 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
2146 // Make a Python command
2147 GEOM::TPythonDump(aFunction, /*append=*/true)
2148 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2149 << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
2150 << theRadius << ", " << theState << ")";
2156 //=======================================================================
2157 //function : getShapesOnQuadrangleIDs
2159 * \brief Find IDs of subshapes complying with given status about quadrangle
2160 * \param theShape - the shape to explore
2161 * \param theShapeType - type of subshape of theShape
2162 * \param theTopLeftPoint - top left quadrangle corner
2163 * \param theTopRigthPoint - top right quadrangle corner
2164 * \param theBottomLeftPoint - bottom left quadrangle corner
2165 * \param theBottomRigthPoint - bottom right quadrangle corner
2166 * \param theState - required state
2167 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2169 //=======================================================================
2171 Handle(TColStd_HSequenceOfInteger)
2172 GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2173 const Standard_Integer theShapeType,
2174 const Handle(GEOM_Object)& theTopLeftPoint,
2175 const Handle(GEOM_Object)& theTopRigthPoint,
2176 const Handle(GEOM_Object)& theBottomLeftPoint,
2177 const Handle(GEOM_Object)& theBottomRigthPoint,
2178 const GEOMAlgo_State theState)
2182 if ( theShape.IsNull() ||
2183 theTopLeftPoint.IsNull() ||
2184 theTopRigthPoint.IsNull() ||
2185 theBottomLeftPoint.IsNull() ||
2186 theBottomRigthPoint.IsNull() )
2189 TopoDS_Shape aShape = theShape->GetValue();
2190 TopoDS_Shape aTL = theTopLeftPoint->GetValue();
2191 TopoDS_Shape aTR = theTopRigthPoint->GetValue();
2192 TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
2193 TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
2195 if (aShape.IsNull() ||
2200 aTL.ShapeType() != TopAbs_VERTEX ||
2201 aTR.ShapeType() != TopAbs_VERTEX ||
2202 aBL.ShapeType() != TopAbs_VERTEX ||
2203 aBR.ShapeType() != TopAbs_VERTEX )
2206 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2207 if ( !checkTypeShapesOn( aShapeType ))
2210 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2212 // Check presence of triangulation, build if need
2213 if (!CheckTriangulation(aShape)) {
2214 SetErrorCode("Cannot build triangulation on the shape");
2219 gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
2220 gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
2221 gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
2222 gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
2224 GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
2225 Standard_Real aTol = 0.0001; // default value
2227 aFinder.SetShape(aShape);
2228 aFinder.SetTolerance(aTol);
2229 //aFinder.SetSurface(theSurface);
2230 aFinder.SetShapeType(aShapeType);
2231 aFinder.SetState(theState);
2233 // Sets the minimal number of inner points for the faces that do not have own
2234 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
2236 aFinder.SetNbPntsMin(3);
2237 // Sets the maximal number of inner points for edges or faces.
2238 // It is usefull for the cases when this number is very big (e.g =2000) to improve
2239 // the performance. If this value =0, all inner points will be taken into account.
2241 aFinder.SetNbPntsMax(100);
2245 // Interprete results
2246 Standard_Integer iErr = aFinder.ErrorStatus();
2247 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2249 MESSAGE(" iErr : " << iErr);
2250 TCollection_AsciiString aMsg (" iErr : ");
2251 aMsg += TCollection_AsciiString(iErr);
2255 Standard_Integer iWrn = aFinder.WarningStatus();
2256 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2258 MESSAGE(" *** iWrn : " << iWrn);
2261 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2263 if (listSS.Extent() < 1) {
2264 SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2268 // Fill sequence of object IDs
2269 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2271 TopTools_IndexedMapOfShape anIndices;
2272 TopExp::MapShapes(aShape, anIndices);
2274 TopTools_ListIteratorOfListOfShape itSub (listSS);
2275 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2276 int id = anIndices.FindIndex(itSub.Value());
2277 aSeqOfIDs->Append(id);
2282 //=======================================================================
2283 //function : GetShapesOnQuadrangle
2285 * \brief Find subshapes complying with given status about quadrangle
2286 * \param theShape - the shape to explore
2287 * \param theShapeType - type of subshape of theShape
2288 * \param theTopLeftPoint - top left quadrangle corner
2289 * \param theTopRigthPoint - top right quadrangle corner
2290 * \param theBottomLeftPoint - bottom left quadrangle corner
2291 * \param theBottomRigthPoint - bottom right quadrangle corner
2292 * \param theState - required state
2293 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2295 //=======================================================================
2297 Handle(TColStd_HSequenceOfTransient)
2298 GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
2299 const Standard_Integer theShapeType,
2300 const Handle(GEOM_Object)& theTopLeftPoint,
2301 const Handle(GEOM_Object)& theTopRigthPoint,
2302 const Handle(GEOM_Object)& theBottomLeftPoint,
2303 const Handle(GEOM_Object)& theBottomRigthPoint,
2304 const GEOMAlgo_State theState)
2307 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2308 getShapesOnQuadrangleIDs( theShape,
2313 theBottomRigthPoint,
2315 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2318 // Find objects by indices
2319 TCollection_AsciiString anAsciiList;
2320 Handle(TColStd_HSequenceOfTransient) aSeq;
2321 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2322 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2325 // Make a Python command
2327 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2328 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2330 GEOM::TPythonDump(aFunction)
2331 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
2333 << TopAbs_ShapeEnum(theShapeType) << ", "
2334 << theTopLeftPoint << ", "
2335 << theTopRigthPoint << ", "
2336 << theBottomLeftPoint << ", "
2337 << theBottomRigthPoint << ", "
2344 //=======================================================================
2345 //function : GetShapesOnQuadrangleIDs
2347 * \brief Find IDs of subshapes complying with given status about quadrangle
2348 * \param theShape - the shape to explore
2349 * \param theShapeType - type of subshape of theShape
2350 * \param theTopLeftPoint - top left quadrangle corner
2351 * \param theTopRigthPoint - top right quadrangle corner
2352 * \param theBottomLeftPoint - bottom left quadrangle corner
2353 * \param theBottomRigthPoint - bottom right quadrangle corner
2354 * \param theState - required state
2355 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2357 //=======================================================================
2359 Handle(TColStd_HSequenceOfInteger)
2360 GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2361 const Standard_Integer theShapeType,
2362 const Handle(GEOM_Object)& theTopLeftPoint,
2363 const Handle(GEOM_Object)& theTopRigthPoint,
2364 const Handle(GEOM_Object)& theBottomLeftPoint,
2365 const Handle(GEOM_Object)& theBottomRigthPoint,
2366 const GEOMAlgo_State theState)
2369 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2370 getShapesOnQuadrangleIDs( theShape,
2375 theBottomRigthPoint,
2377 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2380 // Make a Python command
2382 // The GetShapesOnCylinder() doesn't change object so no new function is required.
2383 Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
2384 lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
2385 lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
2386 lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
2387 Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
2389 GEOM::TPythonDump(aFunction, /*append=*/true)
2390 << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
2392 << TopAbs_ShapeEnum(theShapeType) << ", "
2393 << theTopLeftPoint << ", "
2394 << theTopRigthPoint << ", "
2395 << theBottomLeftPoint << ", "
2396 << theBottomRigthPoint << ", "
2404 //=============================================================================
2408 //=============================================================================
2409 static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
2410 const TopTools_IndexedMapOfShape& theWhereIndices,
2411 const TopoDS_Shape& theWhat,
2412 TColStd_ListOfInteger& theModifiedList)
2414 if (theWhereFunction.IsNull() || theWhat.IsNull()) return false;
2416 if (theWhereIndices.Contains(theWhat)) {
2417 // entity was not changed by the operation
2418 Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
2419 theModifiedList.Append(aWhatIndex);
2423 // try to find in history
2424 TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
2426 // search in history for all argument shapes
2427 Standard_Boolean isFound = Standard_False;
2428 Standard_Boolean isGood = Standard_False;
2430 TDF_LabelSequence aLabelSeq;
2431 theWhereFunction->GetDependency(aLabelSeq);
2432 Standard_Integer nbArg = aLabelSeq.Length();
2434 for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
2436 TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
2438 Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
2439 TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
2441 TopTools_IndexedMapOfShape anArgumentIndices;
2442 TopExp::MapShapes(anArgumentShape, anArgumentIndices);
2444 if (anArgumentIndices.Contains(theWhat)) {
2445 isFound = Standard_True;
2446 Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
2448 // Find corresponding label in history
2449 TDF_Label anArgumentHistoryLabel =
2450 theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
2451 if (anArgumentHistoryLabel.IsNull()) {
2452 // Lost History of operation argument. Possibly, all its entities was removed.
2453 isGood = Standard_True;
2456 TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
2458 if (aWhatHistoryLabel.IsNull()) {
2459 // Removed entity ? Compound ? Compsolid ? Shell ? Wire
2460 isGood = Standard_False;
2462 Handle(TDataStd_IntegerArray) anIntegerArray;
2463 if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2464 //Error: Empty modifications history for the sought shape.
2465 isGood = Standard_False;
2468 isGood = Standard_True;
2469 Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
2470 for (imod = 1; imod <= aModifLen; imod++) {
2471 theModifiedList.Append(anIntegerArray->Array()->Value(imod));
2482 // try compound/compsolid/shell/wire element by element
2483 bool isFoundAny = false;
2484 TopTools_MapOfShape mapShape;
2486 if (theWhat.ShapeType() == TopAbs_COMPOUND ||
2487 theWhat.ShapeType() == TopAbs_COMPSOLID) {
2488 // recursive processing of compound/compsolid
2489 TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
2490 for (; anIt.More(); anIt.Next()) {
2491 if (mapShape.Add(anIt.Value())) {
2492 TopoDS_Shape curWhat = anIt.Value();
2493 isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2494 if (isFoundAny) isFound = Standard_True;
2498 else if (theWhat.ShapeType() == TopAbs_SHELL) {
2499 // try to replace a shell by its faces images
2500 TopExp_Explorer anExp (theWhat, TopAbs_FACE);
2501 for (; anExp.More(); anExp.Next()) {
2502 if (mapShape.Add(anExp.Current())) {
2503 TopoDS_Shape curWhat = anExp.Current();
2504 isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2505 if (isFoundAny) isFound = Standard_True;
2509 else if (theWhat.ShapeType() == TopAbs_WIRE) {
2510 // try to replace a wire by its edges images
2511 TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
2512 for (; anExp.More(); anExp.Next()) {
2513 if (mapShape.Add(anExp.Current())) {
2514 TopoDS_Shape curWhat = anExp.Current();
2515 isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2516 if (isFoundAny) isFound = Standard_True;
2528 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
2529 (Handle(GEOM_Object) theShapeWhere,
2530 Handle(GEOM_Object) theShapeWhat)
2534 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2536 TopoDS_Shape aWhere = theShapeWhere->GetValue();
2537 TopoDS_Shape aWhat = theShapeWhat->GetValue();
2539 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
2541 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
2542 if (aWhereFunction.IsNull()) return NULL;
2544 //Fill array of indices
2545 TopTools_IndexedMapOfShape aWhereIndices;
2546 TopExp::MapShapes(aWhere, aWhereIndices);
2549 TColStd_ListOfInteger aModifiedList;
2550 bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
2552 if (!isFound || aModifiedList.Extent() < 1) {
2553 SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
2557 Handle(TColStd_HArray1OfInteger) aModifiedArray =
2558 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
2559 TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
2560 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
2561 aModifiedArray->SetValue(imod, anIterModif.Value());
2565 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
2566 if (aResult.IsNull()) {
2567 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2571 if (aModifiedArray->Length() > 1) {
2573 aResult->SetType(GEOM_GROUP);
2575 //Set a sub shape type
2576 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
2577 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
2579 TDF_Label aFreeLabel = aResult->GetFreeLabel();
2580 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
2583 //Make a Python command
2584 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
2586 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
2587 << theShapeWhere << ", " << theShapeWhat << ")";
2593 //=======================================================================
2594 //function : SortShapes
2596 //=======================================================================
2597 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
2599 Standard_Integer MaxShapes = SL.Extent();
2600 TopTools_Array1OfShape aShapes (1,MaxShapes);
2601 TColStd_Array1OfInteger OrderInd(1,MaxShapes);
2602 TColStd_Array1OfReal MidXYZ (1,MaxShapes); //X,Y,Z;
2603 TColStd_Array1OfReal Length (1,MaxShapes); //X,Y,Z;
2605 // Computing of CentreOfMass
2606 Standard_Integer Index;
2609 TopTools_ListIteratorOfListOfShape it(SL);
2610 for (Index=1; it.More(); Index++)
2612 TopoDS_Shape S = it.Value();
2613 SL.Remove( it ); // == it.Next()
2615 OrderInd.SetValue (Index, Index);
2616 if (S.ShapeType() == TopAbs_VERTEX)
2618 GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
2619 Length.SetValue( Index, (Standard_Real) S.Orientation());
2623 BRepGProp::LinearProperties (S, GPr);
2624 GPoint = GPr.CentreOfMass();
2625 Length.SetValue( Index, GPr.Mass() );
2627 MidXYZ.SetValue(Index,
2628 GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
2632 Standard_Integer aTemp;
2633 Standard_Boolean exchange, Sort = Standard_True;
2636 Sort = Standard_False;
2637 for (Index=1; Index < MaxShapes; Index++)
2639 if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
2640 exchange = Standard_True;
2641 else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
2642 Length(OrderInd(Index)) > Length(OrderInd(Index+1)) )
2643 exchange = Standard_True;
2645 exchange = Standard_False;
2648 aTemp = OrderInd(Index);
2649 OrderInd(Index) = OrderInd(Index+1);
2650 OrderInd(Index+1) = aTemp;
2651 Sort = Standard_True;
2655 for (Index=1; Index <= MaxShapes; Index++)
2656 SL.Append( aShapes( OrderInd(Index) ));
2659 //=======================================================================
2660 //function : CompsolidToCompound
2662 //=======================================================================
2663 TopoDS_Shape GEOMImpl_IShapesOperations::CompsolidToCompound (const TopoDS_Shape& theCompsolid)
2665 if (theCompsolid.ShapeType() != TopAbs_COMPSOLID) {
2666 return theCompsolid;
2669 TopoDS_Compound aCompound;
2671 B.MakeCompound(aCompound);
2673 TopTools_MapOfShape mapShape;
2674 TopoDS_Iterator It (theCompsolid, Standard_True, Standard_True);
2676 for (; It.More(); It.Next()) {
2677 TopoDS_Shape aShape_i = It.Value();
2678 if (mapShape.Add(aShape_i)) {
2679 B.Add(aCompound, aShape_i);
2686 //=======================================================================
2687 //function : CheckTriangulation
2689 //=======================================================================
2690 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
2692 TopExp_Explorer exp (aShape, TopAbs_FACE);
2697 TopLoc_Location aTopLoc;
2698 Handle(Poly_Triangulation) aTRF;
2699 aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
2700 if (aTRF.IsNull()) {
2701 // calculate deflection
2702 Standard_Real aDeviationCoefficient = 0.001;
2705 BRepBndLib::Add(aShape, B);
2706 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
2707 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
2709 Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
2710 Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
2711 Standard_Real aHLRAngle = 0.349066;
2713 BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
2719 #define MAX_TOLERANCE 1.e-7
2722 //=======================================================================
2723 //function : isSameEdge
2724 //purpose : Returns True if two edges coincide
2725 //=======================================================================
2726 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
2728 TopoDS_Vertex V11, V12, V21, V22;
2729 TopExp::Vertices(theEdge1, V11, V12);
2730 TopExp::Vertices(theEdge2, V21, V22);
2731 gp_Pnt P11 = BRep_Tool::Pnt(V11);
2732 gp_Pnt P12 = BRep_Tool::Pnt(V12);
2733 gp_Pnt P21 = BRep_Tool::Pnt(V21);
2734 gp_Pnt P22 = BRep_Tool::Pnt(V22);
2735 bool coincide = false;
2737 //Check that ends of edges coincide
2738 if(P11.Distance(P21) <= MAX_TOLERANCE) {
2739 if(P12.Distance(P22) <= MAX_TOLERANCE) coincide = true;
2741 else if(P11.Distance(P22) <= MAX_TOLERANCE) {
2742 if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
2745 if(!coincide) return false;
2747 double U11, U12, U21, U22;
2748 Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
2749 Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
2750 if(C1->DynamicType() == C2->DynamicType()) return true;
2752 //Check that both edges has the same geometry
2753 double range = U12-U11;
2754 double U = U11+ range/3.0;
2755 gp_Pnt P1 = C1->Value(U); //Compute a point on one third of the edge's length
2756 U = U11+range*2.0/3.0;
2757 gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length
2759 if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22)
2762 if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
2764 if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
2767 if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
2772 #include <TopoDS_TShape.hxx>
2773 //=======================================================================
2774 //function : isSameFace
2775 //purpose : Returns True if two faces coincide
2776 //=======================================================================
2777 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
2779 TopExp_Explorer E(theFace1, TopAbs_EDGE);
2780 TopTools_ListOfShape LS1, LS2;
2781 for(; E.More(); E.Next()) LS1.Append(E.Current());
2783 E.Init(theFace2, TopAbs_EDGE);
2784 for(; E.More(); E.Next()) LS2.Append(E.Current());
2786 //Compare the number of edges in the faces
2787 if(LS1.Extent() != LS2.Extent()) return false;
2789 double aMin = RealFirst(), aMax = RealLast();
2790 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
2791 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
2793 for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
2794 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2795 if(P.X() < xminB1) xminB1 = P.X();
2796 if(P.Y() < yminB1) yminB1 = P.Y();
2797 if(P.Z() < zminB1) zminB1 = P.Z();
2798 if(P.X() > xmaxB1) xmaxB1 = P.X();
2799 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
2800 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
2803 for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
2804 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2805 if(P.X() < xminB2) xminB2 = P.X();
2806 if(P.Y() < yminB2) yminB2 = P.Y();
2807 if(P.Z() < zminB2) zminB2 = P.Z();
2808 if(P.X() > xmaxB2) xmaxB2 = P.X();
2809 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
2810 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
2813 //Compare the bounding boxes of both faces
2814 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
2817 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
2820 //Check that each edge of the Face1 has a counterpart in the Face2
2821 TopTools_MapOfOrientedShape aMap;
2822 TopTools_ListIteratorOfListOfShape LSI1(LS1);
2823 for(; LSI1.More(); LSI1.Next()) {
2824 TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
2825 bool isFound = false;
2826 TopTools_ListIteratorOfListOfShape LSI2(LS2);
2827 for(; LSI2.More(); LSI2.Next()) {
2828 TopoDS_Shape aValue = LSI2.Value();
2829 if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
2830 if(isSameEdge(E, TopoDS::Edge(aValue))) {
2836 if(!isFound) return false;
2839 Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
2840 Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
2841 if(S1->DynamicType() == S2->DynamicType()) {
2844 else { //Check if there a coincidence of two surfaces at least in two points
2845 double U11, U12, V11, V12, U21, U22, V21, V22;
2846 BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
2847 BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
2849 double rangeU = U12-U11;
2850 double rangeV = V12-V11;
2851 double U = U11 + rangeU/3.0;
2852 double V = V11 + rangeV/3.0;
2853 gp_Pnt P1 = S1->Value(U, V);
2854 U = U11+rangeU*2.0/3.0;
2855 V = V11+rangeV*2.0/3.0;
2856 gp_Pnt P2 = S1->Value(U, V);
2858 if(!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
2861 if(P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
2863 if(!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
2866 if(P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
2872 //=======================================================================
2873 //function : isSameSolid
2874 //purpose : Returns True if two solids coincide
2875 //=======================================================================
2876 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
2878 TopExp_Explorer E(theSolid1, TopAbs_FACE);
2879 TopTools_ListOfShape LS1, LS2;
2880 for(; E.More(); E.Next()) LS1.Append(E.Current());
2881 E.Init(theSolid2, TopAbs_FACE);
2882 for(; E.More(); E.Next()) LS2.Append(E.Current());
2884 if(LS1.Extent() != LS2.Extent()) return false;
2886 double aMin = RealFirst(), aMax = RealLast();
2887 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
2888 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
2890 for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
2891 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2892 if(P.X() < xminB1) xminB1 = P.X();
2893 if(P.Y() < yminB1) yminB1 = P.Y();
2894 if(P.Z() < zminB1) zminB1 = P.Z();
2895 if(P.X() > xmaxB1) xmaxB1 = P.X();
2896 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
2897 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
2900 for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
2901 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2902 if(P.X() < xminB2) xminB2 = P.X();
2903 if(P.Y() < yminB2) yminB2 = P.Y();
2904 if(P.Z() < zminB2) zminB2 = P.Z();
2905 if(P.X() > xmaxB2) xmaxB2 = P.X();
2906 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
2907 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
2910 //Compare the bounding boxes of both solids
2911 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
2914 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
2917 //Check that each face of the Solid1 has a counterpart in the Solid2
2918 TopTools_MapOfOrientedShape aMap;
2919 TopTools_ListIteratorOfListOfShape LSI1(LS1);
2920 for(; LSI1.More(); LSI1.Next()) {
2921 TopoDS_Face F = TopoDS::Face(LSI1.Value());
2922 bool isFound = false;
2923 TopTools_ListIteratorOfListOfShape LSI2(LS2);
2924 for(; LSI2.More(); LSI2.Next()) {
2925 if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
2926 if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
2927 aMap.Add(LSI2.Value());
2932 if(!isFound) return false;
2938 //=======================================================================
2939 //function : GetSame
2941 //=======================================================================
2942 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
2943 const Handle(GEOM_Object)& theShapeWhat)
2946 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2948 TopoDS_Shape aWhere = theShapeWhere->GetValue();
2949 TopoDS_Shape aWhat = theShapeWhat->GetValue();
2951 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
2954 bool isFound = false;
2955 TopoDS_Shape aSubShape;
2956 TopTools_MapOfShape aMap;
2958 switch(aWhat.ShapeType()) {
2959 case TopAbs_VERTEX: {
2960 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
2961 TopExp_Explorer E(aWhere, TopAbs_VERTEX);
2962 for(; E.More(); E.Next()) {
2963 if(!aMap.Add(E.Current())) continue;
2964 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2965 if(P.Distance(P2) <= MAX_TOLERANCE) {
2967 aSubShape = E.Current();
2974 TopoDS_Face aFace = TopoDS::Face(aWhat);
2975 TopExp_Explorer E(aWhere, TopAbs_FACE);
2976 for(; E.More(); E.Next()) {
2977 if(!aMap.Add(E.Current())) continue;
2978 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
2979 aSubShape = E.Current();
2987 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
2988 TopExp_Explorer E(aWhere, TopAbs_EDGE);
2989 for(; E.More(); E.Next()) {
2990 if(!aMap.Add(E.Current())) continue;
2991 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
2992 aSubShape = E.Current();
2999 case TopAbs_SOLID: {
3000 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
3001 TopExp_Explorer E(aWhere, TopAbs_SOLID);
3002 for(; E.More(); E.Next()) {
3003 if(!aMap.Add(E.Current())) continue;
3004 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
3005 aSubShape = E.Current();
3017 TopTools_IndexedMapOfShape anIndices;
3018 TopExp::MapShapes(aWhere, anIndices);
3019 if (anIndices.Contains(aSubShape))
3020 anIndex = anIndices.FindIndex(aSubShape);
3023 if(anIndex < 0) return NULL;
3025 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3027 anArray->SetValue(1, anIndex);
3029 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
3030 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
3032 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
3033 << theShapeWhere << ", " << theShapeWhat << ")";