1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : GEOMImpl_IShapesOperations.cxx
25 // Author : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
28 //#include <Standard_Stream.hxx>
30 #include "GEOMImpl_IShapesOperations.hxx"
32 #include "GEOMImpl_Types.hxx"
34 #include "GEOMImpl_VectorDriver.hxx"
35 #include "GEOMImpl_ShapeDriver.hxx"
36 #include "GEOMImpl_GlueDriver.hxx"
37 #include "GEOMImpl_FillingDriver.hxx"
39 #include "GEOMImpl_IExtract.hxx"
40 #include "GEOMImpl_IVector.hxx"
41 #include "GEOMImpl_IShapes.hxx"
42 #include "GEOMImpl_IShapeExtend.hxx"
43 #include "GEOMImpl_IGlue.hxx"
44 #include "GEOMImpl_IFilling.hxx"
46 #include "GEOMImpl_Block6Explorer.hxx"
47 #include "GEOMImpl_IHealingOperations.hxx"
49 #include "GEOMImpl_Gen.hxx"
51 #include "GEOM_Function.hxx"
52 #include "GEOM_ISubShape.hxx"
53 #include "GEOM_PythonDump.hxx"
55 #include "GEOMUtils.hxx"
57 #include "GEOMAlgo_ClsfBox.hxx"
58 #include "GEOMAlgo_ClsfQuad.hxx"
59 #include "GEOMAlgo_ClsfSolid.hxx"
60 #include "GEOMAlgo_ClsfSurf.hxx"
61 #include "GEOMAlgo_FinderShapeOn2.hxx"
62 #include "GEOMAlgo_GetInPlace.hxx"
63 #include "GEOMAlgo_GetInPlaceAPI.hxx"
64 #include "GEOMAlgo_GlueDetector.hxx"
66 #include <utilities.h>
68 #include <BRepAdaptor_Curve.hxx>
69 #include <BRepAdaptor_Surface.hxx>
70 #include <BRepTools.hxx>
71 #include <BRep_Builder.hxx>
72 #include <BRep_Tool.hxx>
73 #include <GeomLib_Tool.hxx>
74 #include <Geom_CylindricalSurface.hxx>
75 #include <Geom_Plane.hxx>
76 #include <Geom_SphericalSurface.hxx>
77 #include <Geom_Surface.hxx>
78 #include <Geom_TrimmedCurve.hxx>
79 #include <Precision.hxx>
80 #include <TDF_Tool.hxx>
81 #include <TDataStd_Integer.hxx>
82 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
84 #include <TopExp_Explorer.hxx>
85 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
86 #include <TopTools_IndexedMapOfShape.hxx>
87 #include <TopTools_ListIteratorOfListOfShape.hxx>
88 #include <TopTools_MapOfOrientedShape.hxx>
89 #include <TopTools_MapOfShape.hxx>
90 #include <TopTools_SequenceOfShape.hxx>
92 #include <TopoDS_TShape.hxx>
93 #include <TopoDS_Compound.hxx>
94 #include <TopoDS_Edge.hxx>
95 #include <TopoDS_Face.hxx>
96 #include <TopoDS_Iterator.hxx>
97 #include <TopoDS_Shape.hxx>
98 #include <TopoDS_Solid.hxx>
99 #include <TopoDS_Vertex.hxx>
100 #include <gp_Cylinder.hxx>
101 #include <gp_Pnt.hxx>
105 #include <Standard_Failure.hxx>
106 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
108 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
109 // Next macro, when defined, causes appearing of SubShapeAllIDs(), SubShapeAllSortedIDs(), GetSameIDs()
110 // and other such commands in Python dump.
111 // See also GEOM_Engine.cxx.
112 // ---------------------------------------
113 // #define DUMP_SUBSHAPE_IDS
114 // ---------------------------------------
118 void AddFlatSubShapes(const TopoDS_Shape& S, TopTools_ListOfShape& L, TopTools_MapOfShape& M)
120 if (S.ShapeType() != TopAbs_COMPOUND) {
124 TopoDS_Iterator It(S, Standard_True, Standard_True);
125 for (; It.More(); It.Next()) {
126 TopoDS_Shape SS = It.Value();
128 AddFlatSubShapes(SS, L, M);
136 const double MAX_TOLERANCE = 1.e-7;
139 * \brief Returns the vertex from theWhere shape that is coincident with
142 * \param theWhere the shape where the coinsident vertex is searched.
143 * \param theVertex the vertex to be searched.
144 * \return the coincident vertex if it is found. Otherwise null object.
146 static TopoDS_Vertex getSameVertex(const TopoDS_Shape &theWhere,
147 const TopoDS_Vertex &theVertex)
149 TopoDS_Vertex aResult;
150 gp_Pnt aPoint = BRep_Tool::Pnt(theVertex);
151 TopExp_Explorer anExp(theWhere, TopAbs_VERTEX);
152 TopTools_MapOfShape aMap;
154 for(; anExp.More(); anExp.Next()) {
155 const TopoDS_Shape &aLocalShape = anExp.Current();
157 if(!aMap.Add(aLocalShape)) {
161 TopoDS_Vertex aVertex = TopoDS::Vertex(aLocalShape);
162 gp_Pnt aPoint2 = BRep_Tool::Pnt(aVertex);
164 if(aPoint.Distance(aPoint2) <= MAX_TOLERANCE) {
172 } // end of namespace
174 //=============================================================================
178 //=============================================================================
179 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
180 : GEOM_IOperations(theEngine, theDocID)
182 MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
185 //=============================================================================
189 //=============================================================================
190 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
192 MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
195 //=============================================================================
199 //=============================================================================
200 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
201 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
205 if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
207 //Add a new Edge object
208 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
210 //Add a new Vector function
211 Handle(GEOM_Function) aFunction =
212 anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
214 //Check if the function is set correctly
215 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
217 GEOMImpl_IVector aPI (aFunction);
219 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
220 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
221 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
223 aPI.SetPoint1(aRef1);
224 aPI.SetPoint2(aRef2);
226 //Compute the Edge value
229 if (!GetSolver()->ComputeFunction(aFunction)) {
230 SetErrorCode("Vector driver failed");
234 catch (Standard_Failure& aFail) {
235 SetErrorCode(aFail.GetMessageString());
239 //Make a Python command
240 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
241 << thePnt1 << ", " << thePnt2 << ")";
247 //=============================================================================
249 * MakeEdgeOnCurveByLength
251 //=============================================================================
252 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeOnCurveByLength
253 (Handle(GEOM_Object) theRefCurve,
254 const Standard_Real theLength,
255 Handle(GEOM_Object) theStartPoint)
259 if (theRefCurve.IsNull()) return NULL;
261 //Add a new Edge object
262 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
264 //Add a new Vector function
265 Handle(GEOM_Function) aFunction =
266 anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_CURVE_LENGTH);
268 //Check if the function is set correctly
269 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
271 GEOMImpl_IVector aPI (aFunction);
273 Handle(GEOM_Function) aRef1 = theRefCurve->GetLastFunction();
274 if (aRef1.IsNull()) return NULL;
275 aPI.SetPoint1(aRef1);
277 if (!theStartPoint.IsNull()) {
278 Handle(GEOM_Function) aRef2 = theStartPoint->GetLastFunction();
279 aPI.SetPoint2(aRef2);
282 aPI.SetParameter(theLength);
284 //Compute the Edge value
287 if (!GetSolver()->ComputeFunction(aFunction)) {
288 SetErrorCode("Vector driver failed");
292 catch (Standard_Failure& aFail) {
293 SetErrorCode(aFail.GetMessageString());
297 //Make a Python command
298 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeOnCurveByLength("
299 << theRefCurve << ", " << theLength << ", " << theStartPoint << ")";
305 //=============================================================================
309 //=============================================================================
310 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire
311 (Handle(GEOM_Object) theWire,
312 const Standard_Real theLinearTolerance,
313 const Standard_Real theAngularTolerance)
317 if (theWire.IsNull()) return NULL;
319 //Add a new Edge object
320 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
322 //Add a new Vector function
323 Handle(GEOM_Function) aFunction =
324 anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_WIRE);
326 //Check if the function is set correctly
327 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
329 GEOMImpl_IShapes aCI (aFunction);
331 Handle(GEOM_Function) aWire = theWire->GetLastFunction();
333 if (aWire.IsNull()) return NULL;
336 aCI.SetTolerance(theLinearTolerance);
337 aCI.SetAngularTolerance(theAngularTolerance);
339 //Compute the Edge value
342 if (!GetSolver()->ComputeFunction(aFunction)) {
343 SetErrorCode("Shape driver failed");
347 catch (Standard_Failure& aFail) {
348 SetErrorCode(aFail.GetMessageString());
352 const double DEF_LIN_TOL = Precision::Confusion();
353 const double DEF_ANG_TOL = Precision::Angular();
354 //Make a Python command
355 if ( theAngularTolerance == DEF_ANG_TOL ) {
356 if ( theLinearTolerance == DEF_LIN_TOL )
357 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
360 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
361 << theWire << ", " << theLinearTolerance << ")";
364 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
365 << theWire << ", " << theLinearTolerance << ", "
366 << theAngularTolerance << ")";
373 //=============================================================================
377 //=============================================================================
378 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
379 (std::list<Handle(GEOM_Object)> theShapes,
380 const Standard_Real theTolerance)
385 Handle(GEOM_Object) aWire = GetEngine()->AddObject(GetDocID(), GEOM_WIRE);
388 Handle(GEOM_Function) aFunction =
389 aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES);
390 if (aFunction.IsNull()) return NULL;
392 //Check if the function is set correctly
393 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
395 GEOMImpl_IShapes aCI (aFunction);
396 aCI.SetTolerance(theTolerance);
398 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
401 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
402 for (; it != theShapes.end(); it++) {
403 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
404 if (aRefSh.IsNull()) {
405 SetErrorCode("NULL argument shape for the shape construction");
408 aShapesSeq->Append(aRefSh);
410 aCI.SetShapes(aShapesSeq);
415 if (!GetSolver()->ComputeFunction(aFunction)) {
416 SetErrorCode("Shape driver failed");
420 catch (Standard_Failure& aFail) {
421 SetErrorCode(aFail.GetMessageString());
425 //Make a Python command
426 GEOM::TPythonDump pd (aFunction);
427 pd << aWire << " = geompy.MakeWire([";
430 it = theShapes.begin();
431 if (it != theShapes.end()) {
433 while (it != theShapes.end()) {
434 pd << ", " << (*it++);
437 pd << "], " << theTolerance << ")";
443 //=============================================================================
447 //=============================================================================
448 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
449 const bool isPlanarWanted)
453 if (theWire.IsNull()) return NULL;
455 //Add a new Face object
456 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
458 //Add a new Shape function for creation of a face from a wire
459 Handle(GEOM_Function) aFunction =
460 aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
461 if (aFunction.IsNull()) return NULL;
463 //Check if the function is set correctly
464 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
466 GEOMImpl_IShapes aCI (aFunction);
468 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
470 if (aRefWire.IsNull()) return NULL;
472 aCI.SetBase(aRefWire);
473 aCI.SetIsPlanar(isPlanarWanted);
475 //Compute the Face value
476 Standard_Boolean isWarning = Standard_False;
479 if (!GetSolver()->ComputeFunction(aFunction)) {
480 SetErrorCode("Shape driver failed to compute a face");
484 catch (Standard_Failure& aFail) {
485 SetErrorCode(aFail.GetMessageString());
486 // to provide warning
487 if (!aFunction->GetValue().IsNull()) {
488 isWarning = Standard_True;
494 //Make a Python command
495 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
496 << theWire << ", " << (int)isPlanarWanted << ")";
498 // to provide warning
499 if (!isWarning) SetErrorCode(OK);
503 //=============================================================================
507 //=============================================================================
508 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
509 (std::list<Handle(GEOM_Object)> theShapes,
510 const bool isPlanarWanted)
515 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
518 Handle(GEOM_Function) aFunction =
519 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
520 if (aFunction.IsNull()) return NULL;
522 //Check if the function is set correctly
523 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
525 GEOMImpl_IShapes aCI (aFunction);
527 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
530 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
531 for (; it != theShapes.end(); it++) {
532 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
533 if (aRefSh.IsNull()) {
534 SetErrorCode("NULL argument shape for the face construction");
537 aShapesSeq->Append(aRefSh);
539 aCI.SetShapes(aShapesSeq);
541 aCI.SetIsPlanar(isPlanarWanted);
544 Standard_Boolean isWarning = Standard_False;
547 if (!GetSolver()->ComputeFunction(aFunction)) {
548 SetErrorCode("Shape driver failed");
552 catch (Standard_Failure& aFail) {
553 SetErrorCode(aFail.GetMessageString());
554 // to provide warning
555 if (!aFunction->GetValue().IsNull()) {
556 isWarning = Standard_True;
562 //Make a Python command
563 GEOM::TPythonDump pd (aFunction);
564 pd << aShape << " = geompy.MakeFaceWires([";
567 it = theShapes.begin();
568 if (it != theShapes.end()) {
570 while (it != theShapes.end()) {
571 pd << ", " << (*it++);
574 pd << "], " << (int)isPlanarWanted << ")";
576 // to provide warning
577 if (!isWarning) SetErrorCode(OK);
581 //=============================================================================
583 * MakeFaceFromSurface
585 //=============================================================================
586 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface
587 (Handle(GEOM_Object) theFace,
588 Handle(GEOM_Object) theWire)
593 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
596 Handle(GEOM_Function) aFunction =
597 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_FROM_SURFACE);
599 if (aFunction.IsNull()) {
603 //Check if the function is set correctly
604 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
608 GEOMImpl_IShapes aCI (aFunction);
609 Handle(TColStd_HSequenceOfTransient) aShapesSeq =
610 new TColStd_HSequenceOfTransient;
611 Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
612 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
614 if (aRefFace.IsNull()) {
615 SetErrorCode("NULL argument face for the face construction");
619 if (aRefWire.IsNull()) {
620 SetErrorCode("NULL argument wire for the face construction");
624 aShapesSeq->Append(aRefFace);
625 aShapesSeq->Append(aRefWire);
627 aCI.SetShapes(aShapesSeq);
632 if (!GetSolver()->ComputeFunction(aFunction)) {
633 SetErrorCode("Shape driver failed");
637 catch (Standard_Failure& aFail) {
638 SetErrorCode(aFail.GetMessageString());
642 //Make a Python command
643 GEOM::TPythonDump (aFunction) << aShape
644 << " = geompy.MakeFaceFromSurface(" << theFace << ", " << theWire << ")";
651 //=============================================================================
653 * MakeFaceWithConstraints
655 //=============================================================================
656 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWithConstraints
657 (std::list<Handle(GEOM_Object)> theConstraints)
662 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FILLING);
665 Handle(GEOM_Function) aFunction =
666 aShape->AddFunction(GEOMImpl_FillingDriver::GetID(), FILLING_ON_CONSTRAINTS);
667 if (aFunction.IsNull()) return NULL;
669 //Check if the function is set correctly
670 if (aFunction->GetDriverGUID() != GEOMImpl_FillingDriver::GetID()) return NULL;
672 GEOMImpl_IFilling aCI (aFunction);
673 Handle(TColStd_HSequenceOfTransient) aConstraints = new TColStd_HSequenceOfTransient;
676 std::list<Handle(GEOM_Object)>::iterator it = theConstraints.begin();
677 while (it != theConstraints.end()) {
678 Handle(GEOM_Object) anObject = (*it);
679 if ( anObject.IsNull() || anObject->GetValue().ShapeType() != TopAbs_EDGE ) {
680 SetErrorCode("NULL argument edge for the face construction");
683 Handle(GEOM_Function) aRefSh = anObject->GetLastFunction();
684 aConstraints->Append(aRefSh);
686 if ( it != theConstraints.end() ) {
687 Handle(GEOM_Object) aFace = (*it);
688 if ( aFace.IsNull() ) {
689 // null constraint face - it is a valid case
693 if ( aFace->GetValue().ShapeType() != TopAbs_FACE )
694 // constraint face can be omitted - it is a valid case
696 // Keep the old error code as IsSubShapeBelongsTo changes it.
697 TCollection_AsciiString anOldCode = GetErrorCode();
699 if ( IsSubShapeBelongsTo( anObject, 0, aFace, 0 ) ) {
701 SetErrorCode(anOldCode);
702 aRefSh = aFace->GetLastFunction();
703 aConstraints->Append(aRefSh);
708 SetErrorCode("Face is NULL or not connected to the Edge");
713 aCI.SetShapes( aConstraints );
716 Standard_Boolean isWarning = Standard_False;
719 if (!GetSolver()->ComputeFunction(aFunction)) {
720 SetErrorCode("Shape driver failed");
724 catch (Standard_Failure& aFail) {
725 SetErrorCode(aFail.GetMessageString());
726 // to provide warning
727 if (!aFunction->GetValue().IsNull()) {
728 isWarning = Standard_True;
734 //Make a Python command
735 GEOM::TPythonDump pd (aFunction);
736 pd << aShape << " = geompy.MakeFaceWithConstraints([";
739 it = theConstraints.begin();
740 if (it != theConstraints.end() ) {
742 while (it != theConstraints.end()) {
743 Handle(GEOM_Object) anObject = (*it++);
744 if( !anObject.IsNull() )
745 pd << ", " << anObject;
750 // to provide warning
751 if (!isWarning) SetErrorCode(OK);
755 //=============================================================================
759 //=============================================================================
760 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
761 (std::list<Handle(GEOM_Object)> theShapes)
763 return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
766 //=============================================================================
770 //=============================================================================
771 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
772 (std::list<Handle(GEOM_Object)> theShapes)
774 return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
777 //=============================================================================
781 //=============================================================================
782 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
783 (std::list<Handle(GEOM_Object)> theShapes)
785 return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
788 //=============================================================================
792 //=============================================================================
793 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
794 (std::list<Handle(GEOM_Object)> theShapes,
795 const Standard_Integer theObjectType,
796 const Standard_Integer theFunctionType,
797 const TCollection_AsciiString& theMethodName)
802 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
805 Handle(GEOM_Function) aFunction =
806 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
807 if (aFunction.IsNull()) return NULL;
809 //Check if the function is set correctly
810 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
812 GEOMImpl_IShapes aCI (aFunction);
814 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
817 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
818 for (; it != theShapes.end(); it++) {
819 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
820 if (aRefSh.IsNull()) {
821 SetErrorCode("NULL argument shape for the shape construction");
824 aShapesSeq->Append(aRefSh);
826 aCI.SetShapes(aShapesSeq);
831 if (!GetSolver()->ComputeFunction(aFunction)) {
832 SetErrorCode("Shape driver failed");
836 catch (Standard_Failure& aFail) {
837 SetErrorCode(aFail.GetMessageString());
841 //Make a Python command
842 GEOM::TPythonDump pd (aFunction);
843 pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
846 it = theShapes.begin();
847 if (it != theShapes.end()) {
849 while (it != theShapes.end()) {
850 pd << ", " << (*it++);
859 //=============================================================================
861 * MakeSolidFromConnectedFaces
863 //=============================================================================
864 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidFromConnectedFaces
865 (std::list<Handle(GEOM_Object)> theFacesOrShells,
866 const Standard_Boolean isIntersect)
871 Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
874 Handle(GEOM_Function) aFunction =
875 aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_FACES);
876 if (aFunction.IsNull()) return NULL;
878 //Check if the function is set correctly
879 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
881 GEOMImpl_IShapes aCI (aFunction);
883 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
886 std::list<Handle(GEOM_Object)>::iterator it = theFacesOrShells.begin();
887 for (; it != theFacesOrShells.end(); it++) {
888 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
889 if (aRefSh.IsNull()) {
890 SetErrorCode("NULL argument shape for the shape construction");
893 aShapesSeq->Append(aRefSh);
895 aCI.SetShapes(aShapesSeq);
896 aCI.SetIsIntersect(isIntersect);
901 if (!GetSolver()->ComputeFunction(aFunction)) {
902 SetErrorCode("Shape driver failed");
906 catch (Standard_Failure& aFail) {
907 SetErrorCode(aFail.GetMessageString());
911 //Make a Python command
912 GEOM::TPythonDump pd (aFunction);
913 pd << aSolid << " = geompy.MakeSolidFromConnectedFaces([";
916 it = theFacesOrShells.begin();
917 if (it != theFacesOrShells.end()) {
919 while (it != theFacesOrShells.end()) {
920 pd << ", " << (*it++);
923 pd << "]," << (isIntersect ? "True" : "False") << ")";
929 //=============================================================================
933 //=============================================================================
935 GEOMImpl_IShapesOperations::MakeGlueFaces (std::list< Handle(GEOM_Object) >& theShapes,
936 const Standard_Real theTolerance,
937 const Standard_Boolean doKeepNonSolids)
941 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
942 if ( objects.IsNull() || objects->IsEmpty() ) {
943 SetErrorCode("NULL argument shape");
947 //Add a new Glued object
948 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
950 //Add a new Glue function
951 Handle(GEOM_Function) aFunction;
952 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
953 if (aFunction.IsNull()) return NULL;
955 //Check if the function is set correctly
956 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
958 GEOMImpl_IGlue aCI (aFunction);
960 aCI.SetBase( objects );
961 aCI.SetTolerance(theTolerance);
962 aCI.SetKeepNonSolids(doKeepNonSolids);
964 //Compute the sub-shape value
965 Standard_Boolean isWarning = Standard_False;
968 if (!GetSolver()->ComputeFunction(aFunction)) {
969 SetErrorCode("Shape driver failed to glue faces");
973 catch (Standard_Failure& aFail) {
974 SetErrorCode(aFail.GetMessageString());
975 // to provide warning
976 if (!aFunction->GetValue().IsNull()) {
977 isWarning = Standard_True;
983 //Make a Python command
984 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
985 << theShapes << ", " << theTolerance << ")";
987 // to provide warning
988 if (!isWarning) SetErrorCode(OK);
992 //=============================================================================
996 //=============================================================================
998 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
999 (Handle(GEOM_Object) theShape,
1000 const Standard_Real theTolerance)
1004 if (theShape.IsNull()) return NULL;
1005 TopoDS_Shape aShape = theShape->GetValue();
1006 if (aShape.IsNull()) return NULL;
1008 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1010 Standard_Integer iErr;
1012 GEOMAlgo_Gluer1 aGluer;
1013 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
1014 GEOMAlgo_CoupleOfShapes aCS;
1015 GEOMAlgo_ListOfCoupleOfShapes aLCS;
1017 //aGluer = new GEOMAlgo_Gluer1;
1018 aGluer.SetShape(aShape);
1019 aGluer.SetTolerance(theTolerance);
1021 iErr = aGluer.ErrorStatus();
1022 if (iErr) return NULL;
1024 TopTools_ListOfShape listShape;
1025 const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
1027 aItCS.Initialize(aLCSG);
1028 for (; aItCS.More(); aItCS.Next()) {
1029 const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
1030 listShape.Append(aCSG.Shape1());
1033 TopTools_ListIteratorOfListOfShape itSub (listShape);
1034 TCollection_AsciiString anAsciiList, anEntry;
1035 TopTools_IndexedMapOfShape anIndices;
1036 TopExp::MapShapes(aShape, anIndices);
1037 Handle(TColStd_HArray1OfInteger) anArray;
1038 Handle(GEOM_Object) anObj;
1039 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1040 TopoDS_Shape aValue = itSub.Value();
1041 anArray = new TColStd_HArray1OfInteger(1,1);
1042 anArray->SetValue(1, anIndices.FindIndex(aValue));
1043 anObj = GetEngine()->AddSubShape(theShape, anArray);
1044 if (!anObj.IsNull()) {
1045 aSeq->Append(anObj);
1047 // for python command
1048 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1049 anAsciiList += anEntry;
1054 //Make a Python command
1055 if( anAsciiList.Length() > 0 ) {
1056 anAsciiList.Trunc(anAsciiList.Length() - 1);
1057 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1058 GEOM::TPythonDump pd (aFunction, true);
1059 pd << "[" << anAsciiList.ToCString();
1060 pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
1069 //=============================================================================
1071 * MakeGlueFacesByList
1073 //=============================================================================
1075 GEOMImpl_IShapesOperations::MakeGlueFacesByList(std::list< Handle(GEOM_Object) >& theShapes,
1076 const Standard_Real theTolerance,
1077 std::list<Handle(GEOM_Object)> & theFaces,
1078 const Standard_Boolean doKeepNonSolids,
1079 const Standard_Boolean doGlueAllEdges)
1083 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1084 if ( objects.IsNull() || objects->IsEmpty() ) {
1085 SetErrorCode("NULL argument shape");
1088 Handle(TColStd_HSequenceOfTransient) aFaces = GEOM_Object::GetLastFunctions( theFaces );
1089 if ( aFaces.IsNull() ) {
1090 SetErrorCode("NULL argument shape for the shape construction");
1094 //Add a new Glued object
1095 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
1097 //Add a new Glue function
1098 Handle(GEOM_Function) aFunction;
1099 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
1100 if (aFunction.IsNull()) return NULL;
1102 //Check if the function is set correctly
1103 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1105 GEOMImpl_IGlue aCI (aFunction);
1107 aCI.SetBase( objects );
1108 aCI.SetTolerance(theTolerance);
1109 aCI.SetKeepNonSolids(doKeepNonSolids);
1110 aCI.SetGlueAllEdges(doGlueAllEdges);
1111 aCI.SetFaces(aFaces);
1113 //Compute the sub-shape value
1114 Standard_Boolean isWarning = Standard_False;
1117 if (!GetSolver()->ComputeFunction(aFunction)) {
1118 SetErrorCode("Shape driver failed to glue faces");
1122 catch (Standard_Failure& aFail) {
1123 SetErrorCode(aFail.GetMessageString());
1124 // to provide warning
1125 if (!aFunction->GetValue().IsNull()) {
1126 isWarning = Standard_True;
1132 //Make a Python command
1134 GEOM::TPythonDump pd(aFunction);
1135 pd << aGlued << " = geompy.MakeGlueFacesByList("
1136 << theShapes << ", " << theTolerance << ", " << theFaces << ", "
1137 << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")";
1139 // to provide warning
1140 if (!isWarning) SetErrorCode(OK);
1144 //=============================================================================
1148 //=============================================================================
1150 GEOMImpl_IShapesOperations::MakeGlueEdges (std::list< Handle(GEOM_Object) >& theShapes,
1151 const Standard_Real theTolerance)
1155 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1156 if ( objects.IsNull() || objects->IsEmpty() ) {
1157 SetErrorCode("NULL argument shape");
1161 //Add a new Glued object
1162 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
1164 //Add a new Glue function
1165 Handle(GEOM_Function) aFunction;
1166 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES);
1167 if (aFunction.IsNull()) return NULL;
1169 //Check if the function is set correctly
1170 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1172 GEOMImpl_IGlue aCI (aFunction);
1174 aCI.SetBase( objects );
1175 aCI.SetTolerance(theTolerance);
1176 aCI.SetKeepNonSolids(true);
1178 //Compute the sub-shape value
1179 Standard_Boolean isWarning = Standard_False;
1182 if (!GetSolver()->ComputeFunction(aFunction)) {
1183 SetErrorCode("Shape driver failed to glue edges");
1187 catch (Standard_Failure& aFail) {
1188 SetErrorCode(aFail.GetMessageString());
1189 // to provide warning
1190 if (!aFunction->GetValue().IsNull()) {
1191 isWarning = Standard_True;
1197 //Make a Python command
1198 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueEdges("
1199 << theShapes << ", " << theTolerance << ")";
1201 // to provide warning
1202 if (!isWarning) SetErrorCode(OK);
1206 //=============================================================================
1210 //=============================================================================
1211 Handle(TColStd_HSequenceOfTransient)
1212 GEOMImpl_IShapesOperations::GetGlueShapes (std::list< Handle(GEOM_Object) >& theShapes,
1213 const Standard_Real theTolerance,
1214 const TopAbs_ShapeEnum theType)
1218 TopoDS_Shape aShape;
1219 TopTools_SequenceOfShape shapes;
1220 std::list< Handle(GEOM_Object) >::iterator s = theShapes.begin();
1221 Handle(GEOM_BaseObject) lastCreatedGO;
1222 for ( ; s != theShapes.end(); ++s )
1224 Handle(GEOM_Object) go = *s;
1225 if ( go.IsNull() ) return NULL;
1226 aShape = go->GetValue();
1227 if ( aShape.IsNull() ) return NULL;
1228 shapes.Append( aShape );
1229 lastCreatedGO = GEOM::GetCreatedLast( lastCreatedGO, go );
1231 if ( shapes.Length() > 1 )
1233 TopoDS_Compound compound;
1234 BRep_Builder builder;
1235 builder.MakeCompound( compound );
1236 for ( int i = 1; i <= shapes.Length(); ++i )
1237 builder.Add( compound, shapes( i ) );
1242 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1244 GEOMAlgo_GlueDetector aGluer;
1245 aGluer.SetArgument(aShape);
1246 aGluer.SetTolerance(theTolerance);
1248 Standard_Integer iErr = aGluer.ErrorStatus();
1249 if (iErr) return NULL;
1251 std::vector< TopTools_IndexedMapOfShape* > anIndices( shapes.Length(), NULL );
1252 Handle(TColStd_HArray1OfInteger) anArray;
1253 Handle(GEOM_Object) anObj;
1255 TopTools_ListOfShape listOnePerSet;
1257 const TopTools_DataMapOfShapeListOfShape& aImages = aGluer.Images();
1258 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS (aImages);
1259 for (int index = 1; aItDMSLS.More(); aItDMSLS.Next(), ++index) {
1261 //const TopoDS_Shape& aSkey = aItDMSLS.Key();
1263 // list of shapes of the argument that can be glued
1264 const TopTools_ListOfShape& aLSD = aItDMSLS.Value();
1266 //listShape.Append(aLSD.First());
1267 TopoDS_Shape aValue = aLSD.First();
1269 if (aValue.ShapeType() == theType) {
1270 listOnePerSet.Append(aValue);
1274 // for stable order of returned entities
1275 GEOMUtils::SortShapes(listOnePerSet, Standard_False);
1277 TopTools_ListIteratorOfListOfShape aListIt (listOnePerSet);
1278 for (; aListIt.More(); aListIt.Next())
1280 TopoDS_Shape aValue = aListIt.Value();
1281 // find a shape to add aValue as a sub-shape
1283 s = theShapes.begin();
1284 for ( int i = 0; i < shapes.Length(); ++i, ++s )
1286 Handle(GEOM_Object) object = *s;
1287 if ( !anIndices[i] ) {
1288 anIndices[i] = new TopTools_IndexedMapOfShape;
1289 TopExp::MapShapes( object->GetValue(), *anIndices[i]);
1291 if (int index = anIndices[i]->FindIndex( aValue )) {
1292 anArray = new TColStd_HArray1OfInteger(1,1);
1293 anArray->SetValue(1, index);
1294 anObj = GetEngine()->AddSubShape( object, anArray);
1298 if (!anObj.IsNull())
1299 aSeq->Append(anObj);
1301 for ( size_t i = 0 ; i < anIndices.size(); ++i )
1302 delete anIndices[i];
1304 // Make a Python command
1305 if ( aSeq->Length() > 0)
1307 Handle(GEOM_Function) aFunction = lastCreatedGO->GetLastFunction();
1308 GEOM::TPythonDump pd (aFunction, /*append=*/true);
1310 << " = geompy." << (theType == TopAbs_FACE ? "GetGlueFaces" : "GetGlueEdges" )
1311 << "( " << theShapes << ", " << theTolerance << ")";
1319 //=============================================================================
1321 * MakeGlueEdgesByList
1323 //=============================================================================
1325 GEOMImpl_IShapesOperations::MakeGlueEdgesByList (std::list< Handle(GEOM_Object) >& theShapes,
1326 const Standard_Real theTolerance,
1327 std::list<Handle(GEOM_Object)>& theEdges)
1331 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1332 if ( objects.IsNull() || objects->IsEmpty() ) {
1333 SetErrorCode("NULL argument shape");
1336 Handle(TColStd_HSequenceOfTransient) anEdges = GEOM_Object::GetLastFunctions( theEdges );
1337 if ( anEdges.IsNull() ) {
1338 SetErrorCode("NULL argument shape for the shape construction");
1341 //Add a new Glued object
1342 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
1344 //Add a new Glue function
1345 Handle(GEOM_Function) aFunction;
1346 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES_BY_LIST);
1347 if (aFunction.IsNull()) return NULL;
1349 //Check if the function is set correctly
1350 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1352 GEOMImpl_IGlue aCI (aFunction);
1354 aCI.SetBase( objects );
1355 aCI.SetTolerance(theTolerance);
1356 aCI.SetKeepNonSolids(true);
1357 aCI.SetFaces(anEdges);
1359 //Compute the sub-shape value
1360 Standard_Boolean isWarning = Standard_False;
1363 if (!GetSolver()->ComputeFunction(aFunction)) {
1364 SetErrorCode("Shape driver failed to glue edges");
1368 catch (Standard_Failure& aFail) {
1369 SetErrorCode(aFail.GetMessageString());
1370 // to provide warning
1371 if (!aFunction->GetValue().IsNull()) {
1372 isWarning = Standard_True;
1378 //Make a Python command
1380 GEOM::TPythonDump pd (aFunction);
1381 pd << aGlued << " = geompy.MakeGlueEdgesByList("
1382 << theShapes << ", " << theTolerance << ", " << theEdges << " )";
1384 // to provide warning
1385 if (!isWarning) SetErrorCode(OK);
1389 //=============================================================================
1391 * GetExistingSubObjects
1393 //=============================================================================
1394 Handle(TColStd_HSequenceOfTransient)
1395 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape,
1396 const Standard_Boolean theGroupsOnly)
1398 // note: this method does not return fields
1400 Standard_Integer types = theGroupsOnly ? Groups : Groups|SubShapes;
1401 Handle(TColStd_HSequenceOfTransient) results = GetExistingSubObjects(theShape, types);
1403 Handle(GEOM_BaseObject) lastCreatedGO = GEOM::GetCreatedLast(results);
1404 lastCreatedGO = GEOM::GetCreatedLast(lastCreatedGO, theShape);
1406 if (results->Length() > 0) {
1407 // Make a Python command
1408 GEOM::TPythonDump pd (lastCreatedGO->GetLastFunction(), /*append=*/true);
1410 Standard_Integer i, aLen = results->Length();
1411 for (i = 1; i <= aLen; i++)
1413 Handle(GEOM_BaseObject) obj = Handle(GEOM_BaseObject)::DownCast(results->Value(i));
1414 pd << obj << ((i < aLen) ? ", " : "");
1416 pd << "] = geompy.GetExistingSubObjects(";
1417 pd << theShape << ", " << (bool)theGroupsOnly << ")";
1423 Handle(TColStd_HSequenceOfTransient)
1424 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape,
1425 const Standard_Integer theTypes)
1429 if (theShape.IsNull()) return NULL;
1431 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1432 if (aMainShape.IsNull()) return NULL;
1434 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1435 SetErrorCode(NOT_FOUND_ANY);
1437 if (!aMainShape->HasSubShapeReferences()) return aSeq;
1438 const TDataStd_ListOfExtendedString& aListEntries = aMainShape->GetSubShapeReferences();
1439 if (aListEntries.IsEmpty()) return aSeq;
1443 TDataStd_ListIteratorOfListOfExtendedString anIt (aListEntries);
1444 for (; anIt.More(); anIt.Next()) {
1445 TCollection_ExtendedString anEntry = anIt.Value();
1446 Standard_Integer aStrLen = anEntry.LengthOfCString();
1447 char* anEntryStr = new char[aStrLen+1];
1448 anEntry.ToUTF8CString(anEntryStr);
1449 Handle(GEOM_BaseObject) anObj = GetEngine()->GetObject(GetDocID(), anEntryStr, false);
1450 if (!anObj.IsNull() ) {
1451 bool isGroup = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() == GEOM_GROUP;
1452 bool isSubShape = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() != GEOM_GROUP;
1453 bool isField = anObj->IsKind(STANDARD_TYPE(GEOM_Field));
1454 if (theTypes & Groups && isGroup ||
1455 theTypes & SubShapes && isSubShape ||
1456 theTypes & Fields && isField) {
1457 aSeq->Append(anObj);
1460 delete [] anEntryStr;
1463 if (aSeq->Length() == 0) {
1464 SetErrorCode(NOT_FOUND_ANY);
1473 //=============================================================================
1477 //=============================================================================
1478 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
1479 (Handle(GEOM_Object) theShape,
1480 const Standard_Integer theShapeType,
1481 const Standard_Boolean isSorted,
1482 const ExplodeType theExplodeType)
1486 if (theShape.IsNull()) return NULL;
1487 TopoDS_Shape aShape = theShape->GetValue();
1488 if (aShape.IsNull()) return NULL;
1490 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1492 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1493 Handle(GEOM_Object) anObj;
1494 TopTools_MapOfShape mapShape;
1495 TopTools_ListOfShape listShape;
1497 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1498 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1500 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1501 for (; It.More(); It.Next()) {
1502 TopoDS_Shape SS = It.Value();
1503 if (mapShape.Add(SS)) {
1504 if (theShapeType == TopAbs_FLAT) {
1505 AddFlatSubShapes(SS, listShape, mapShape);
1507 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1508 listShape.Append(SS);
1510 // VSR: for EXPLODE_NEW_INCLUDE_MAIN and EXPLODE_OLD_INCLUDE_MAIN:
1511 // it seems it is necessary to add top-level shape if theShapeType == TopAbs_COMPOUND
1515 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1517 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1518 for (; exp.More(); exp.Next())
1519 if (mapShape.Add(exp.Current()))
1520 listShape.Append(exp.Current());
1523 if (listShape.IsEmpty()){
1524 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1525 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1530 bool isOldSorting = false;
1531 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1532 isOldSorting = true;
1533 GEOMUtils::SortShapes(listShape, isOldSorting);
1536 TopTools_IndexedMapOfShape anIndices;
1537 TopExp::MapShapes(aShape, anIndices);
1538 Handle(TColStd_HArray1OfInteger) anArray;
1540 TopTools_ListIteratorOfListOfShape itSub (listShape);
1541 TCollection_AsciiString anAsciiList, anEntry;
1542 for (int index = 1; itSub.More(); itSub.Next(), ++index)
1544 TopoDS_Shape aValue = itSub.Value();
1545 anArray = new TColStd_HArray1OfInteger(1,1);
1546 anArray->SetValue(1, anIndices.FindIndex(aValue));
1548 //anObj = GetEngine()->AddSubShape(theShape, anArray);
1550 anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1551 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1552 if (aFunction.IsNull()) return aSeq;
1554 GEOM_ISubShape aSSI (aFunction);
1555 aSSI.SetMainShape(aMainShape);
1556 aSSI.SetIndices(anArray);
1558 // Set function value directly, as we know it.
1559 // Usage of Solver here would lead to significant loss of time,
1560 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1561 // on the main shape for each being calculated sub-shape separately.
1562 aFunction->SetValue(aValue);
1564 // Put this subshape in the list of sub-shapes of theMainShape
1565 aMainShape->AddSubShapeReference(aFunction);
1567 if (!anObj.IsNull()) {
1568 aSeq->Append(anObj);
1570 // for python command
1571 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1572 anAsciiList += anEntry;
1577 //Make a Python command
1578 anAsciiList.Trunc(anAsciiList.Length() - 1);
1580 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1581 pd << "[" << anAsciiList.ToCString() << "] = geompy.";
1582 switch (theExplodeType) {
1583 case EXPLODE_NEW_EXCLUDE_MAIN:
1584 pd << "ExtractShapes(" << theShape << ", "
1585 << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")";
1587 case EXPLODE_NEW_INCLUDE_MAIN:
1588 pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(")
1589 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1591 case EXPLODE_OLD_INCLUDE_MAIN:
1592 pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(")
1593 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1602 //=============================================================================
1606 //=============================================================================
1607 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
1608 (Handle(GEOM_Object) theShape,
1609 const Standard_Integer theShapeType,
1610 const Standard_Boolean isSorted,
1611 const ExplodeType theExplodeType)
1615 if (theShape.IsNull()) return NULL;
1616 TopoDS_Shape aShape = theShape->GetValue();
1617 if (aShape.IsNull()) return NULL;
1619 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1620 TopTools_MapOfShape mapShape;
1621 TopTools_ListOfShape listShape;
1623 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1624 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1626 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1627 for (; It.More(); It.Next()) {
1628 TopoDS_Shape SS = It.Value();
1629 if (mapShape.Add(SS)) {
1630 if (theShapeType == TopAbs_FLAT) {
1631 AddFlatSubShapes(SS, listShape, mapShape);
1633 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1634 listShape.Append(SS);
1639 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1641 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1642 for (; exp.More(); exp.Next())
1643 if (mapShape.Add(exp.Current()))
1644 listShape.Append(exp.Current());
1647 if (listShape.IsEmpty()) {
1648 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1649 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1654 bool isOldSorting = false;
1655 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1656 isOldSorting = true;
1657 GEOMUtils::SortShapes(listShape, isOldSorting);
1660 TopTools_IndexedMapOfShape anIndices;
1661 TopExp::MapShapes(aShape, anIndices);
1662 Handle(TColStd_HArray1OfInteger) anArray;
1664 TopTools_ListIteratorOfListOfShape itSub (listShape);
1665 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1666 TopoDS_Shape aValue = itSub.Value();
1667 aSeq->Append(anIndices.FindIndex(aValue));
1670 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1672 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
1673 #ifdef DUMP_SUBSHAPE_IDS
1674 //Make a Python command
1675 GEOM::TPythonDump pd (aFunction, /*append=*/true);
1676 pd << "listSubShapeIDs = geompy.SubShapeAll";
1677 switch (theExplodeType) {
1678 case EXPLODE_NEW_EXCLUDE_MAIN:
1680 case EXPLODE_NEW_INCLUDE_MAIN:
1681 pd << (isSorted ? "SortedCentresIDs(" : "IDs(")
1682 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1684 case EXPLODE_OLD_INCLUDE_MAIN:
1685 pd << (isSorted ? "SortedIDs(" : "IDs(")
1686 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1690 #endif // DUMP_SUBSHAPE_IDS
1696 //=============================================================================
1700 //=============================================================================
1701 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
1702 (Handle(GEOM_Object) theMainShape,
1703 const Standard_Integer theID)
1707 if (theMainShape.IsNull()) return NULL;
1709 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1710 anArray->SetValue(1, theID);
1711 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
1712 if (anObj.IsNull()) {
1713 SetErrorCode("Can not get a sub-shape with the given ID");
1717 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1719 //Make a Python command
1720 GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1721 << theMainShape << ", [" << theID << "])";
1727 //=============================================================================
1731 //=============================================================================
1732 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes
1733 (Handle(GEOM_Object) theMainShape,
1734 Handle(TColStd_HArray1OfInteger) theIndices)
1738 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1740 if (!theIndices->Length()) {
1741 SetErrorCode(NOT_FOUND_ANY);
1745 if (theMainShape.IsNull()) return NULL;
1746 TopoDS_Shape aShape = theMainShape->GetValue();
1747 if (aShape.IsNull()) return NULL;
1749 Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
1751 TopTools_IndexedMapOfShape anIndices;
1752 TopExp::MapShapes(aShape, anIndices);
1754 Handle(TColStd_HArray1OfInteger) anArray;
1755 Handle(GEOM_Object) anObj;
1757 TCollection_AsciiString anAsciiList, anEntry;
1758 Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper();
1759 for (i = low; i <= up; i++) {
1760 int id = theIndices->Value(i);
1761 if (1 <= id && id <= anIndices.Extent()) {
1762 TopoDS_Shape aValue = anIndices.FindKey(id);
1763 anArray = new TColStd_HArray1OfInteger(1,1);
1764 anArray->SetValue(1, id);
1766 anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1767 if (!anObj.IsNull()) {
1768 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1769 if (aFunction.IsNull()) return aSeq;
1771 GEOM_ISubShape aSSI (aFunction);
1772 aSSI.SetMainShape(aMainShape);
1773 aSSI.SetIndices(anArray);
1775 // Set function value directly, as we know it.
1776 // Usage of Solver here would lead to significant loss of time,
1777 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1778 // on the main shape for each being calculated sub-shape separately.
1779 aFunction->SetValue(aValue);
1781 // Put this sub-shape in the list of sub-shapes of theMainShape
1782 aMainShape->AddSubShapeReference(aFunction);
1784 aSeq->Append(anObj);
1786 // for python command
1787 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1788 anAsciiList += anEntry;
1794 //Make a Python command
1795 anAsciiList.Trunc(anAsciiList.Length() - 1);
1797 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1798 pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes("
1799 << theMainShape << ", [" ;
1800 for (i = low; i <= up - 1; i++) {
1801 pd << theIndices->Value(i) << ", ";
1803 pd << theIndices->Value(up) << "])";
1810 //=============================================================================
1814 //=============================================================================
1815 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1816 Handle(GEOM_Object) theSubShape)
1820 TopoDS_Shape aMainShape = theMainShape->GetValue();
1821 TopoDS_Shape aSubShape = theSubShape->GetValue();
1823 if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1825 TopTools_IndexedMapOfShape anIndices;
1826 TopExp::MapShapes(aMainShape, anIndices);
1827 // if (anIndices.Contains(aSubShape)) {
1828 // SetErrorCode(OK);
1829 // return anIndices.FindIndex(aSubShape);
1831 int id = anIndices.FindIndex(aSubShape);
1842 //=============================================================================
1844 * GetSubShapeIndices
1846 //=============================================================================
1847 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSubShapesIndices (Handle(GEOM_Object) theMainShape,
1848 std::list<Handle(GEOM_Object)> theSubShapes)
1850 MESSAGE("GEOMImpl_IShapesOperations::GetSubShapesIndices")
1853 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1855 TopoDS_Shape aMainShape = theMainShape->GetValue();
1856 if (aMainShape.IsNull())
1858 MESSAGE("NULL main shape")
1862 TopTools_IndexedMapOfShape anIndices;
1863 TopExp::MapShapes(aMainShape, anIndices);
1865 std::list<Handle(GEOM_Object)>::iterator it;
1866 for (it=theSubShapes.begin(); it != theSubShapes.end(); ++it)
1868 TopoDS_Shape aSubShape = (*it)->GetValue();
1869 if (aSubShape.IsNull())
1871 MESSAGE("NULL subshape")
1874 int id = anIndices.FindIndex(aSubShape);
1883 //=============================================================================
1887 //=============================================================================
1888 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1889 Handle(GEOM_Object) theSubShape)
1893 TopoDS_Shape aMainShape = theMainShape->GetValue();
1894 TopoDS_Shape aSubShape = theSubShape->GetValue();
1896 if (aMainShape.IsNull() || aSubShape.IsNull()) {
1897 SetErrorCode("Null argument shape given");
1902 if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1904 TopTools_ListOfShape CL;
1905 CL.Append(aMainShape);
1906 TopTools_ListIteratorOfListOfShape itC;
1907 for (itC.Initialize(CL); itC.More(); itC.Next()) {
1908 for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1909 if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1910 if (it.Value().IsSame(aSubShape))
1914 CL.Append(it.Value());
1919 TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1920 TopTools_MapOfShape M;
1921 for (; anExp.More(); anExp.Next()) {
1922 if (M.Add(anExp.Current())) {
1923 if (anExp.Current().IsSame(aSubShape))
1930 SetErrorCode("The sub-shape does not belong to the main shape");
1934 //=============================================================================
1936 * GetShapeTypeString
1938 //=============================================================================
1939 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1943 TCollection_AsciiString aTypeName ("Null Shape");
1945 TopoDS_Shape aShape = theShape->GetValue();
1946 if (aShape.IsNull())
1949 switch (aShape.ShapeType() )
1951 case TopAbs_COMPOUND:
1952 aTypeName = "Compound";
1954 case TopAbs_COMPSOLID:
1955 aTypeName = "Compound Solid";
1958 aTypeName = "Solid";
1961 aTypeName = "Shell";
1965 BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1966 if (surf.GetType() == GeomAbs_Plane)
1967 aTypeName = "Plane";
1968 else if (surf.GetType() == GeomAbs_Cylinder)
1969 aTypeName = "Cylindrical Face";
1970 else if (surf.GetType() == GeomAbs_Sphere)
1971 aTypeName = "Spherical Face";
1972 else if (surf.GetType() == GeomAbs_Torus)
1973 aTypeName = "Toroidal Face";
1974 else if (surf.GetType() == GeomAbs_Cone)
1975 aTypeName = "Conical Face";
1977 aTypeName = "GEOM::FACE";
1985 BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1986 if (curv.GetType() == GeomAbs_Line) {
1987 if ((Abs(curv.FirstParameter()) >= 1E6) ||
1988 (Abs(curv.LastParameter()) >= 1E6))
1992 } else if (curv.GetType() == GeomAbs_Circle) {
1993 if (curv.IsClosed())
1994 aTypeName = "Circle";
2003 aTypeName = "Vertex";
2006 aTypeName = "Shape";
2009 aTypeName = "Shape of unknown type";
2015 //=============================================================================
2017 * IsSubShapeBelongsTo
2019 //=============================================================================
2020 Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject,
2021 const Standard_Integer theSubObjectIndex,
2022 Handle(GEOM_Object) theObject,
2023 const Standard_Integer theObjectIndex)
2027 if ( theObject.IsNull() || theSubObject.IsNull() )
2030 TopoDS_Shape shape = theObject->GetValue();
2031 TopoDS_Shape subShape = theSubObject->GetValue();
2033 if ( shape.IsNull() || subShape.IsNull() )
2036 TopTools_IndexedMapOfShape anIndices;
2037 if ( theObjectIndex > 0 ) {
2038 TopExp::MapShapes( shape, anIndices );
2039 shape = anIndices.FindKey(theObjectIndex);
2041 if ( theSubObjectIndex > 0 ) {
2042 TopExp::MapShapes( subShape, anIndices );
2043 subShape = anIndices.FindKey(theSubObjectIndex);
2046 TopExp::MapShapes( shape, anIndices );
2048 const Standard_Boolean isBelongTo = anIndices.Contains(subShape);
2055 //=============================================================================
2059 //=============================================================================
2060 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
2061 (Handle(GEOM_Object) theShape,
2062 const Standard_Integer theShapeType)
2065 Standard_Integer nbShapes = 0;
2067 if (theShape.IsNull()) return -1;
2068 TopoDS_Shape aShape = theShape->GetValue();
2069 if (aShape.IsNull()) return -1;
2072 TopTools_MapOfShape mapShape;
2074 if (aShape.ShapeType() == TopAbs_COMPOUND &&
2075 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2076 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
2077 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
2078 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
2079 for (; It.More(); It.Next()) {
2080 if (mapShape.Add(It.Value())) {
2081 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2082 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
2088 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
2089 for (; exp.More(); exp.Next())
2090 if (mapShape.Add(exp.Current()))
2096 if (theShapeType == TopAbs_FLAT) {
2097 TopTools_MapOfShape aMapOfShape;
2098 TopTools_ListOfShape aListOfShape;
2099 AddFlatSubShapes(aShape, aListOfShape, aMapOfShape);
2100 nbShapes = aListOfShape.Extent();
2104 int iType, nbTypes [TopAbs_SHAPE];
2105 for (iType = 0; iType < TopAbs_SHAPE; ++iType)
2107 nbTypes[aShape.ShapeType()]++;
2109 TopTools_MapOfShape aMapOfShape;
2110 aMapOfShape.Add(aShape);
2111 TopTools_ListOfShape aListOfShape;
2112 aListOfShape.Append(aShape);
2114 TopTools_ListIteratorOfListOfShape itL (aListOfShape);
2115 for (; itL.More(); itL.Next()) {
2116 TopoDS_Iterator it (itL.Value());
2117 for (; it.More(); it.Next()) {
2118 TopoDS_Shape s = it.Value();
2119 if (aMapOfShape.Add(s)) {
2120 aListOfShape.Append(s);
2121 nbTypes[s.ShapeType()]++;
2126 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
2127 nbShapes = aMapOfShape.Extent();
2129 nbShapes = nbTypes[theShapeType];
2132 catch (Standard_Failure& aFail) {
2133 SetErrorCode(aFail.GetMessageString());
2141 //=============================================================================
2145 //=============================================================================
2146 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
2150 if (theShape.IsNull()) return NULL;
2153 //Add a new reversed object
2154 Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
2156 //Add a new Revese function
2157 Handle(GEOM_Function) aFunction;
2158 aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
2159 if (aFunction.IsNull()) return NULL;
2161 //Check if the function is set correctly
2162 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
2164 GEOMImpl_IShapes aSI (aFunction);
2166 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2167 if (aRefShape.IsNull()) return NULL;
2169 aSI.SetBase(aRefShape);
2171 //Compute the sub-shape value
2174 if (!GetSolver()->ComputeFunction(aFunction)) {
2175 SetErrorCode("Shape driver failed to reverse shape");
2179 catch (Standard_Failure& aFail) {
2180 SetErrorCode(aFail.GetMessageString());
2184 //Make a Python command
2185 GEOM::TPythonDump(aFunction) << aReversed
2186 << " = geompy.ChangeOrientation(" << theShape << ")";
2191 Handle(GEOM_Object) aReversed;
2193 GEOM_Engine* anEngine = GetEngine();
2194 //GEOMImpl_Gen* aGen = dynamic_cast<GEOMImpl_Gen*>(anEngine);
2195 GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine;
2198 GEOMImpl_IHealingOperations* anIHealingOperations =
2199 aGen->GetIHealingOperations(GetDocID());
2200 aReversed = anIHealingOperations->ChangeOrientationCopy(theShape);
2201 SetErrorCode(anIHealingOperations->GetErrorCode());
2207 //=============================================================================
2211 //=============================================================================
2212 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
2213 (Handle(GEOM_Object) theShape)
2217 if (theShape.IsNull()) return NULL;
2218 TopoDS_Shape aShape = theShape->GetValue();
2219 if (aShape.IsNull()) return NULL;
2221 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
2223 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2224 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2225 (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2227 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2230 SetErrorCode("The given shape has no faces");
2234 TopTools_IndexedMapOfShape anIndices;
2235 TopExp::MapShapes(aShape, anIndices);
2237 Standard_Integer id;
2238 for (; ind <= nbFaces; ind++) {
2239 if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
2240 id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
2245 //The explode doesn't change object so no new function is required.
2246 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
2248 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2249 #ifdef DUMP_SUBSHAPE_IDS
2250 //Make a Python command
2251 GEOM::TPythonDump(aFunction, /*append=*/true)
2252 << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
2253 #endif // DUMP_SUBSHAPE_IDS
2259 //=======================================================================
2260 //function : GetSharedShapes
2262 //=======================================================================
2263 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2264 (Handle(GEOM_Object) theShape1,
2265 Handle(GEOM_Object) theShape2,
2266 const Standard_Integer theShapeType)
2270 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
2272 TopoDS_Shape aShape1 = theShape1->GetValue();
2273 TopoDS_Shape aShape2 = theShape2->GetValue();
2275 if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
2277 TopTools_IndexedMapOfShape anIndices;
2278 TopExp::MapShapes(aShape1, anIndices);
2279 Handle(TColStd_HArray1OfInteger) anArray;
2281 TopTools_IndexedMapOfShape mapShape1;
2282 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
2284 Handle(GEOM_Object) anObj;
2285 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2286 TCollection_AsciiString anAsciiList, anEntry;
2288 TopTools_MapOfShape mapShape2;
2289 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2290 for (; exp.More(); exp.Next()) {
2291 TopoDS_Shape aSS = exp.Current();
2292 if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
2293 anArray = new TColStd_HArray1OfInteger(1,1);
2294 anArray->SetValue(1, anIndices.FindIndex(aSS));
2295 anObj = GetEngine()->AddSubShape(theShape1, anArray);
2296 aSeq->Append(anObj);
2298 // for python command
2299 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2300 anAsciiList += anEntry;
2305 if (aSeq->IsEmpty()) {
2306 SetErrorCode(NOT_FOUND_ANY);
2310 //Make a Python command
2311 anAsciiList.Trunc(anAsciiList.Length() - 1);
2313 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2315 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2316 << "] = geompy.GetSharedShapes(" << theShape1 << ", "
2317 << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
2323 //=======================================================================
2324 //function : GetSharedShapes
2327 // NOTE on the implementation
2329 // 1) Resulting sub-shapes are published as a children of the 1st input shape
2330 // from theShapes list. Due to this reason only direct sub-shapes of the 1st
2331 // shape can be contained in the result of the operation (i.e. shares between
2332 // 2nd/3rd, etc couples cannot be retrieved.
2333 // 2) An exception from above case is when a single compound is specified as an
2334 // input. In this case we search shares between its top-level content, so we
2335 // are able to search shares between all possible couples of shapes.
2336 // 3) Parameter theMultiShare controls what types of shares to search:
2337 // - True: get sub-shapes that are shared between ALL input shapes;
2338 // - False: get shares between couples of input sub-shapes (see points 1 and 2).
2340 // Thus, we have the following cases:
2341 // [1] theShapes = N shapes (N>1), theMultiShare = True
2342 // Result: sub-shapes that are shared by all theShapes
2343 // [2] theShapes = N shapes (N>1), theMultiShare = False
2344 // Result: sub-shapes of 1st shape from theShapes that are shared with any shape
2346 // [3] theShapes = 1 shape, theMultiShare = True
2347 // Result: sub-shapes that are shared by all top-level sub-objects of theShapes[0]
2348 // [4] theShapes = 1 shape, theMultiShare = False
2349 // Result: sub-shapes of all possible couples of all top-level sub-objects of
2351 //=======================================================================
2352 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2353 (std::list<Handle(GEOM_Object)> & theShapes,
2354 const Standard_Integer theShapeType,
2355 const bool theMultiShare)
2359 int aLen = theShapes.size();
2360 if (aLen < 1) return NULL;
2362 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
2364 // main object is always first in the input list
2365 // it is the object from which sub-shapes indices are taken
2366 // and where results are published
2367 Handle(GEOM_Object) aMainObj = *it;
2368 Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
2370 // collect all shapes from the input list (including first one) for processing
2371 TopTools_SequenceOfShape shapeSeq;
2372 for (; it != theShapes.end(); it++) {
2373 Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
2374 if (aRefShape.IsNull()) {
2375 SetErrorCode("NULL shape for GetSharedShapes");
2378 TopoDS_Shape aShape = aRefShape->GetValue();
2379 if (aShape.IsNull()) {
2380 SetErrorCode("NULL shape for GetSharedShapes");
2383 shapeSeq.Append( aShape );
2386 // if only single shape is specified as input
2387 // collect all ites top-level sub-shapes for processing
2388 if ( shapeSeq.Length() == 1 )
2390 TopoDS_Shape aShape = shapeSeq.First();
2392 for ( TopoDS_Iterator it( aShape ); it.More(); it.Next() )
2393 shapeSeq.Append( it.Value() );
2396 // map all sub-shapes in a main shape to their indices
2397 TopTools_IndexedMapOfShape anIndices;
2398 TopExp::MapShapes(aMainShape->GetValue(), anIndices);
2399 TopTools_MapOfShape mapShape;
2401 // find shared shapes
2403 // here we will collect all shares
2404 TopTools_ListOfShape aShared;
2406 // number of iterations
2407 int nbIters = theMultiShare || theShapes.size() > 1 ? 1 : shapeSeq.Length()-1;
2408 // numShares factor to search (i.e. by what nb of shapes each found sub-shape should be shared)
2409 int nbShares = theMultiShare ? shapeSeq.Length()-1 : 1;
2411 for ( int iter = 1; iter <= nbIters; iter++) {
2412 for ( int ind = iter+1; ind <= shapeSeq.Length(); ind++) {
2413 if ( ind-1+nbShares > shapeSeq.Length() ) break;
2414 TopoDS_Compound aCurrSelection;
2415 TopoDS_Shape aShape1 = shapeSeq.Value( iter );
2416 TopTools_IndexedMapOfShape mapSelected;
2417 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
2418 for ( int s = 0; s < nbShares; s++ ) {
2420 TopoDS_Compound aCompound;
2421 B.MakeCompound(aCompound);
2422 const TopoDS_Shape& aShape2 = shapeSeq.Value( ind+s );
2423 TopTools_MapOfShape mapShape2;
2424 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2425 for (; exp.More(); exp.Next()) {
2426 const TopoDS_Shape& aSS = exp.Current();
2427 if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
2428 B.Add(aCompound, aSS);
2431 mapSelected.Clear();
2432 aCurrSelection = aCompound;
2433 TopExp::MapShapes(aCurrSelection, TopAbs_ShapeEnum(theShapeType), mapSelected);
2435 TopoDS_Iterator itSel(aCurrSelection, Standard_True, Standard_True);
2436 for (; itSel.More(); itSel.Next()) {
2437 const TopoDS_Shape& aSS = itSel.Value();
2438 if (mapShape.Add(aSS) )
2439 aShared.Append(aSS);
2444 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2446 if (aShared.IsEmpty()){
2447 SetErrorCode(NOT_FOUND_ANY);
2451 // create GEOM_Object for each found shared shape (collected in aShared)
2452 TCollection_AsciiString anAsciiList;
2453 Handle(GEOM_Object) anObj;
2454 TopTools_ListIteratorOfListOfShape itSub (aShared);
2455 for (; itSub.More(); itSub.Next()) {
2456 TopoDS_Shape aValue = itSub.Value();
2457 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2458 anArray->SetValue(1, anIndices.FindIndex(aValue));
2459 anObj = GetEngine()->AddSubShape(aMainObj, anArray);
2460 aSeq->Append(anObj);
2462 // for python command
2463 TCollection_AsciiString anEntry;
2464 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2465 anAsciiList += anEntry;
2469 // make a Python command
2470 anAsciiList.Trunc(anAsciiList.Length() - 1);
2472 GEOM::TPythonDump pd (anObj->GetLastFunction());
2473 pd << "[" << anAsciiList.ToCString()
2474 << "] = geompy.GetSharedShapesMulti(";
2479 it = theShapes.begin();
2481 while (it != theShapes.end()) {
2482 pd << ", " << (*it++);
2487 pd << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theMultiShare << ")";
2493 //=============================================================================
2497 //=============================================================================
2498 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump,
2499 const GEOMAlgo_State theState)
2502 case GEOMAlgo_ST_IN:
2503 theDump << "GEOM.ST_IN";
2505 case GEOMAlgo_ST_OUT:
2506 theDump << "GEOM.ST_OUT";
2508 case GEOMAlgo_ST_ON:
2509 theDump << "GEOM.ST_ON";
2511 case GEOMAlgo_ST_ONIN:
2512 theDump << "GEOM.ST_ONIN";
2514 case GEOMAlgo_ST_ONOUT:
2515 theDump << "GEOM.ST_ONOUT";
2518 theDump << "GEOM.ST_UNKNOWN";
2524 //=======================================================================
2525 //function : checkTypeShapesOn
2527 * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
2528 * \param theShapeType - the shape type to check
2529 * \retval bool - result of the check
2531 //=======================================================================
2532 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
2534 if (theShapeType != TopAbs_VERTEX &&
2535 theShapeType != TopAbs_EDGE &&
2536 theShapeType != TopAbs_FACE &&
2537 theShapeType != TopAbs_SOLID) {
2538 SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
2544 //=======================================================================
2545 //function : makePlane
2547 * \brief Creates Geom_Plane
2548 * \param theAx1 - shape object defining plane parameters
2549 * \retval Handle(Geom_Surface) - resulting surface
2551 //=======================================================================
2552 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
2554 if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
2555 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2556 TopoDS_Vertex V1, V2;
2557 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2558 if (V1.IsNull() || V2.IsNull()) {
2559 SetErrorCode("Bad edge given for the plane normal vector");
2562 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2563 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2564 if (aVec.Magnitude() < Precision::Confusion()) {
2565 SetErrorCode("Vector with null magnitude given");
2568 return new Geom_Plane(aLoc, aVec);
2571 //=======================================================================
2572 //function : makeCylinder
2574 * \brief Creates Geom_CylindricalSurface
2575 * \param theAx1 - edge defining cylinder axis
2576 * \param theRadius - cylinder radius
2577 * \retval Handle(Geom_Surface) - resulting surface
2579 //=======================================================================
2580 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
2581 const Standard_Real theRadius)
2583 //Axis of the cylinder
2584 if (anAxis.ShapeType() != TopAbs_EDGE) {
2585 SetErrorCode("Not an edge given for the axis");
2588 TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
2589 TopoDS_Vertex V1, V2;
2590 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2591 if (V1.IsNull() || V2.IsNull()) {
2592 SetErrorCode("Bad edge given for the axis");
2595 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2596 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2597 if (aVec.Magnitude() < Precision::Confusion()) {
2598 SetErrorCode("Vector with null magnitude given");
2602 gp_Ax3 anAx3 (aLoc, aVec);
2603 return new Geom_CylindricalSurface(anAx3, theRadius);
2606 //=======================================================================
2607 //function : getShapesOnBoxIDs
2609 * \brief Find IDs of sub-shapes complying with given status about surface
2610 * \param theBox - the box to check state of sub-shapes against
2611 * \param theShape - the shape to explore
2612 * \param theShapeType - type of sub-shape of theShape
2613 * \param theState - required state
2614 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2616 //=======================================================================
2617 Handle(TColStd_HSequenceOfInteger)
2618 GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2619 const Handle(GEOM_Object)& theShape,
2620 const Standard_Integer theShapeType,
2621 GEOMAlgo_State theState)
2623 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2625 TopoDS_Shape aBox = theBox->GetValue();
2626 TopoDS_Shape aShape = theShape->GetValue();
2628 // Check presence of triangulation, build if need
2629 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2630 SetErrorCode("Cannot build triangulation on the shape");
2635 GEOMAlgo_FinderShapeOn2 aFinder;
2636 Standard_Real aTol = 0.0001; // default value
2638 Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
2639 aClsfBox->SetBox(aBox);
2641 aFinder.SetShape(aShape);
2642 aFinder.SetTolerance(aTol);
2643 aFinder.SetClsf(aClsfBox);
2644 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2645 aFinder.SetState(theState);
2648 // Interprete results
2649 Standard_Integer iErr = aFinder.ErrorStatus();
2650 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2652 MESSAGE(" iErr : " << iErr);
2653 TCollection_AsciiString aMsg (" iErr : ");
2654 aMsg += TCollection_AsciiString(iErr);
2658 Standard_Integer iWrn = aFinder.WarningStatus();
2659 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2661 MESSAGE(" *** iWrn : " << iWrn);
2664 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2666 if (listSS.Extent() < 1) {
2667 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2668 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2672 // Fill sequence of object IDs
2673 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2675 TopTools_IndexedMapOfShape anIndices;
2676 TopExp::MapShapes(aShape, anIndices);
2678 TopTools_ListIteratorOfListOfShape itSub (listSS);
2679 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2680 int id = anIndices.FindIndex(itSub.Value());
2681 aSeqOfIDs->Append(id);
2687 //=======================================================================
2688 //function : GetShapesOnBoxIDs
2690 * \brief Find sub-shapes complying with given status about surface
2691 * \param theBox - the box to check state of sub-shapes against
2692 * \param theShape - the shape to explore
2693 * \param theShapeType - type of sub-shape of theShape
2694 * \param theState - required state
2695 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2697 //=======================================================================
2698 Handle(TColStd_HSequenceOfInteger)
2699 GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2700 const Handle(GEOM_Object)& theShape,
2701 const Standard_Integer theShapeType,
2702 GEOMAlgo_State theState)
2704 // Find sub-shapes ids
2705 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2706 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2707 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2710 // The GetShapesOnBox() doesn't change object so no new function is required.
2711 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
2713 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2714 #ifdef DUMP_SUBSHAPE_IDS
2715 // Make a Python command
2716 GEOM::TPythonDump(aFunction, /*append=*/true)
2717 << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
2720 << TopAbs_ShapeEnum(theShapeType) << ", "
2722 #endif // DUMP_SUBSHAPE_IDS
2728 //=======================================================================
2729 //function : GetShapesOnBox
2731 * \brief Find sub-shapes complying with given status about surface
2732 * \param theBox - the box to check state of sub-shapes against
2733 * \param theShape - the shape to explore
2734 * \param theShapeType - type of sub-shape of theShape
2735 * \param theState - required state
2736 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2738 //=======================================================================
2739 Handle(TColStd_HSequenceOfTransient)
2740 GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
2741 const Handle(GEOM_Object)& theShape,
2742 const Standard_Integer theShapeType,
2743 GEOMAlgo_State theState)
2745 // Find sub-shapes ids
2746 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2747 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2748 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2751 // Find objects by indices
2752 TCollection_AsciiString anAsciiList;
2753 Handle(TColStd_HSequenceOfTransient) aSeq;
2754 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2755 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2758 // Make a Python command
2760 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2761 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2763 GEOM::TPythonDump(aFunction)
2764 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
2767 << TopAbs_ShapeEnum(theShapeType) << ", "
2774 //=======================================================================
2775 //function : getShapesOnShapeIDs
2777 * \brief Find IDs of sub-shapes complying with given status about surface
2778 * \param theCheckShape - the shape to check state of sub-shapes against
2779 * \param theShape - the shape to explore
2780 * \param theShapeType - type of sub-shape of theShape
2781 * \param theState - required state
2782 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2784 //=======================================================================
2785 Handle(TColStd_HSequenceOfInteger)
2786 GEOMImpl_IShapesOperations::getShapesOnShapeIDs
2787 (const Handle(GEOM_Object)& theCheckShape,
2788 const Handle(GEOM_Object)& theShape,
2789 const Standard_Integer theShapeType,
2790 GEOMAlgo_State theState)
2792 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2794 TopoDS_Shape aCheckShape = theCheckShape->GetValue();
2795 TopoDS_Shape aShape = theShape->GetValue();
2796 TopTools_ListOfShape res;
2798 // Check presence of triangulation, build if need
2799 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2800 SetErrorCode("Cannot build triangulation on the shape");
2804 // Compute classification tolerance.
2805 TopTools_IndexedMapOfShape aMapVtx;
2806 Standard_Real aTol = Precision::Confusion();
2808 TopExp::MapShapes(aShape, TopAbs_VERTEX, aMapVtx);
2811 Standard_Integer aNbVtx = aMapVtx.Extent();
2813 for (i = 1; i <= aNbVtx; ++i) {
2814 const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(i));
2815 const Standard_Real aVtxTol = BRep_Tool::Tolerance(aVtx);
2817 if (aTol < aVtxTol) {
2822 // Bound the tolerance value.
2823 if (aTol > 0.0001) {
2828 GEOMAlgo_FinderShapeOn2 aFinder;
2830 Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
2831 aClsfSolid->SetShape(aCheckShape);
2833 aFinder.SetShape(aShape);
2834 aFinder.SetTolerance(aTol);
2835 aFinder.SetClsf(aClsfSolid);
2836 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2837 aFinder.SetState(theState);
2840 // Interprete results
2841 Standard_Integer iErr = aFinder.ErrorStatus();
2842 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2845 SetErrorCode("theCheckShape must be a solid");
2848 MESSAGE(" iErr : " << iErr);
2849 TCollection_AsciiString aMsg (" iErr : ");
2850 aMsg += TCollection_AsciiString(iErr);
2855 Standard_Integer iWrn = aFinder.WarningStatus();
2856 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2858 MESSAGE(" *** iWrn : " << iWrn);
2861 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2863 if (listSS.Extent() < 1) {
2864 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2865 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2868 // Fill sequence of object IDs
2869 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2871 TopTools_IndexedMapOfShape anIndices;
2872 TopExp::MapShapes(aShape, anIndices);
2874 TopTools_ListIteratorOfListOfShape itSub (listSS);
2875 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2876 int id = anIndices.FindIndex(itSub.Value());
2877 aSeqOfIDs->Append(id);
2883 //=======================================================================
2884 //function : GetShapesOnShapeIDs
2886 * \brief Find sub-shapes complying with given status about surface
2887 * \param theCheckShape - the shape to check state of sub-shapes against
2888 * \param theShape - the shape to explore
2889 * \param theShapeType - type of sub-shape of theShape
2890 * \param theState - required state
2891 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2893 //=======================================================================
2894 Handle(TColStd_HSequenceOfInteger)
2895 GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
2896 (const Handle(GEOM_Object)& theCheckShape,
2897 const Handle(GEOM_Object)& theShape,
2898 const Standard_Integer theShapeType,
2899 GEOMAlgo_State theState)
2901 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2902 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2904 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2907 // The GetShapesOnShape() doesn't change object so no new function is required.
2908 Handle(GEOM_Function) aFunction =
2909 GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
2911 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2912 #ifdef DUMP_SUBSHAPE_IDS
2913 // Make a Python command
2914 GEOM::TPythonDump(aFunction, /*append=*/true)
2915 << "listShapesOnShapeIDs = geompy.GetShapesOnShapeIDs("
2916 << theCheckShape << ", "
2918 << TopAbs_ShapeEnum(theShapeType) << ", "
2920 #endif // DUMP_SUBSHAPE_IDS
2926 //=======================================================================
2927 //function : GetShapesOnShape
2929 * \brief Find sub-shapes complying with given status about surface
2930 * \param theCheckShape - the shape to check state of sub-shapes against
2931 * \param theShape - the shape to explore
2932 * \param theShapeType - type of sub-shape of theShape
2933 * \param theState - required state
2934 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2936 //=======================================================================
2937 Handle(TColStd_HSequenceOfTransient)
2938 GEOMImpl_IShapesOperations::GetShapesOnShape
2939 (const Handle(GEOM_Object)& theCheckShape,
2940 const Handle(GEOM_Object)& theShape,
2941 const Standard_Integer theShapeType,
2942 GEOMAlgo_State theState)
2944 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2945 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2946 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2949 // Find objects by indices
2950 TCollection_AsciiString anAsciiList;
2951 Handle(TColStd_HSequenceOfTransient) aSeq;
2952 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2954 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2957 // Make a Python command
2959 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2960 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2962 GEOM::TPythonDump(aFunction)
2963 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
2964 << theCheckShape << ", "
2966 << TopAbs_ShapeEnum(theShapeType) << ", "
2973 //=======================================================================
2974 //function : GetShapesOnShapeAsCompound
2975 //=======================================================================
2976 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
2977 (const Handle(GEOM_Object)& theCheckShape,
2978 const Handle(GEOM_Object)& theShape,
2979 const Standard_Integer theShapeType,
2980 GEOMAlgo_State theState)
2982 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2983 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2985 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2988 // Find objects by indices
2989 TCollection_AsciiString anAsciiList;
2990 Handle(TColStd_HSequenceOfTransient) aSeq;
2991 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2993 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2996 TopoDS_Compound aCompound;
2998 B.MakeCompound(aCompound);
3000 for(; i<=aSeq->Length(); i++) {
3001 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
3002 TopoDS_Shape aShape_i = anObj->GetValue();
3003 B.Add(aCompound,aShape_i);
3006 //Add a new result object
3007 Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
3008 Handle(GEOM_Function) aFunction =
3009 aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
3010 aFunction->SetValue(aCompound);
3013 aSeq->Append( theCheckShape->GetLastFunction() );
3014 aSeq->Append( theShape->GetLastFunction() );
3016 GEOMImpl_IShapes aCI( aFunction );
3017 aCI.SetShapes( aSeq );
3018 aCI.SetSubShapeType( theShapeType );
3019 aCI.SetTolerance( theState );
3021 GEOM::TPythonDump(aFunction)
3022 << aRes << " = geompy.GetShapesOnShapeAsCompound("
3023 << theCheckShape << ", "
3025 << TopAbs_ShapeEnum(theShapeType) << ", "
3033 //=============================================================================
3035 * GetSubShapeEdgeSorted
3037 //=============================================================================
3038 Handle(TColStd_HSequenceOfTransient)
3039 GEOMImpl_IShapesOperations::GetSubShapeEdgeSorted
3040 (const Handle(GEOM_Object) &theShape,
3041 const Handle(GEOM_Object) &theStartPoint)
3043 // Get the sorted edges indices.
3044 Handle(TColStd_HSequenceOfInteger) aSortedIDs =
3045 getSubShapeEdgeSortedIDs(theShape, theStartPoint);
3047 // Get object by indices.
3048 TCollection_AsciiString anAsciiList;
3049 Handle(TColStd_HSequenceOfTransient) aSeq =
3050 getObjectsShapesOn(theShape, aSortedIDs, anAsciiList);
3052 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3053 SetErrorCode("Empty sequence of edges");
3057 // Make a Python command
3058 Handle(GEOM_Object) anObj =
3059 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3060 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3062 GEOM::TPythonDump(aFunction)
3063 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapeEdgeSorted("
3064 << theShape << ", " << theStartPoint << ")";
3071 //=============================================================================
3073 * GetSubShapesWithTolerance
3075 //=============================================================================
3076 Handle(TColStd_HSequenceOfTransient)
3077 GEOMImpl_IShapesOperations::GetSubShapesWithTolerance
3078 (const Handle(GEOM_Object) &theShape,
3079 const Standard_Integer theShapeType,
3080 const GEOMUtils::ComparisonCondition theCondition,
3081 const Standard_Real theTolerance)
3083 if (theShape.IsNull()) {
3084 SetErrorCode("NULL GEOM object");
3088 TopoDS_Shape aShape = theShape->GetValue();
3090 if (aShape.IsNull()) {
3091 SetErrorCode("NULL Shape");
3095 if (theShapeType != TopAbs_FACE && theShapeType != TopAbs_EDGE &&
3096 theShapeType != TopAbs_VERTEX && aShape.ShapeType() >= theShapeType) {
3097 SetErrorCode("Invalid shape type");
3101 TopTools_IndexedMapOfShape anIndices;
3102 TopTools_MapOfShape aMapFence;
3103 TopExp_Explorer anExp(aShape,
3104 (TopAbs_ShapeEnum) theShapeType);
3105 Handle(TColStd_HSequenceOfInteger) anIDs = new TColStd_HSequenceOfInteger;
3107 TopExp::MapShapes(aShape, anIndices);
3109 for (; anExp.More(); anExp.Next()) {
3110 const TopoDS_Shape &aSubShape = anExp.Current();
3112 if (aMapFence.Add(aSubShape)) {
3113 // Compute tolerance
3114 Standard_Real aTolerance = -1.;
3116 switch (aSubShape.ShapeType()) {
3118 aTolerance = BRep_Tool::Tolerance(TopoDS::Face(aSubShape));
3121 aTolerance = BRep_Tool::Tolerance(TopoDS::Edge(aSubShape));
3124 aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aSubShape));
3130 if (aTolerance < 0.) {
3134 // Compare the tolerance with reference value.
3135 if (GEOMUtils::IsFitCondition (theCondition, aTolerance, theTolerance)) {
3136 anIDs->Append(anIndices.FindIndex(aSubShape));
3141 if (anIDs->IsEmpty()) {
3142 SetErrorCode("Empty sequence of sub-shapes");
3146 // Get objects by indices.
3147 TCollection_AsciiString anAsciiList;
3148 Handle(TColStd_HSequenceOfTransient) aSeq =
3149 getObjectsShapesOn(theShape, anIDs, anAsciiList);
3151 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3152 SetErrorCode("Empty sequence of edges");
3156 // Make a Python command
3157 Handle(GEOM_Object) anObj =
3158 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3159 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3161 GEOM::TPythonDump(aFunction)
3162 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapesWithTolerance("
3163 << theShape << ", " << theShapeType << ", " << theCondition << ", "
3164 << theTolerance << ")";
3171 //=============================================================================
3175 //=============================================================================
3176 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeExtraction
3177 (const Handle(GEOM_Object) &theShape,
3178 const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs,
3179 std::list<ExtractionStat> &theStats)
3183 if (theShape.IsNull()) {
3187 //Add a new Result object
3188 Handle(GEOM_Object) aResult =
3189 GetEngine()->AddObject(GetDocID(), GEOM_EXTRACTION);
3191 //Add a new Extraction function
3192 Handle(GEOM_Function) aFunction =
3193 aResult->AddFunction(GEOMImpl_ShapeDriver::GetID(), EXTRACTION);
3195 //Check if the function is set correctly
3196 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
3200 Handle(GEOM_Function) aShape = theShape->GetLastFunction();
3202 if (aShape.IsNull()) {
3206 GEOMImpl_IExtract aCI (aFunction);
3208 aCI.SetShape(aShape);
3209 aCI.SetSubShapeIDs(theSubShapeIDs);
3211 //Compute the Edge value
3214 if (!GetSolver()->ComputeFunction(aFunction)) {
3215 SetErrorCode("Shape driver failed");
3220 catch (Standard_Failure& aFail) {
3221 SetErrorCode(aFail.GetMessageString());
3226 // Fill in statistics.
3229 Handle(TColStd_HArray1OfInteger) aStatIDsArray[3] =
3230 { aCI.GetRemovedIDs(), aCI.GetModifiedIDs(), aCI.GetAddedIDs() };
3234 for (j = 0; j < 3; ++j) {
3235 if (!aStatIDsArray[j].IsNull()) {
3236 const int anUpperID = aStatIDsArray[j]->Upper();
3237 ExtractionStat aStat;
3239 for (i = aStatIDsArray[j]->Lower(); i <= anUpperID; ++i) {
3240 aStat.indices.push_back(aStatIDsArray[j]->Value(i));
3243 aStat.type = (ExtractionStatType) j;
3244 theStats.push_back(aStat);
3248 //Make a Python command
3249 GEOM::TPythonDump pd(aFunction);
3251 pd << aResult << " = geompy.MakeExtraction(" << theShape << ", [";
3253 if (!theSubShapeIDs.IsNull()) {
3254 const int aNbIDs = theSubShapeIDs->Upper();
3256 for (i = theSubShapeIDs->Lower(); i < aNbIDs; ++i) {
3257 pd << theSubShapeIDs->Value(i) << ", ";
3260 // Dump the last value without a comma.
3261 pd << theSubShapeIDs->Value(i);
3271 //=======================================================================
3272 //function : getShapesOnSurfaceIDs
3274 * \brief Find IDs of sub-shapes complying with given status about surface
3275 * \param theSurface - the surface to check state of sub-shapes against
3276 * \param theShape - the shape to explore
3277 * \param theShapeType - type of sub-shape of theShape
3278 * \param theState - required state
3279 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3281 //=======================================================================
3282 Handle(TColStd_HSequenceOfInteger)
3283 GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
3284 const TopoDS_Shape& theShape,
3285 TopAbs_ShapeEnum theShapeType,
3286 GEOMAlgo_State theState)
3288 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3290 // Check presence of triangulation, build if need
3291 if (theShapeType != TopAbs_VERTEX &&
3292 !GEOMUtils::CheckTriangulation(theShape)) {
3293 SetErrorCode("Cannot build triangulation on the shape");
3297 // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
3298 // Compute tolerance
3299 Standard_Real T, VertMax = -RealLast();
3302 for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
3303 TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
3304 T = BRep_Tool::Tolerance(Vertex);
3309 catch (Standard_Failure& aFail) {
3310 SetErrorCode(aFail.GetMessageString());
3313 // END: Mantis issue 0020961
3316 GEOMAlgo_FinderShapeOn2 aFinder;
3317 Handle(GEOMAlgo_ClsfSurf) aClsfSurf = new GEOMAlgo_ClsfSurf;
3318 Standard_Real aTol = VertMax; // Mantis issue 0020961
3320 aClsfSurf->SetSurface(theSurface);
3321 aFinder.SetShape(theShape);
3322 aFinder.SetTolerance(aTol);
3323 aFinder.SetClsf(aClsfSurf);
3324 aFinder.SetShapeType(theShapeType);
3325 aFinder.SetState(theState);
3327 // Sets the minimal number of inner points for the faces that do not have own
3328 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
3330 aFinder.SetNbPntsMin(3);
3331 // Sets the maximal number of inner points for edges or faces.
3332 // It is usefull for the cases when this number is very big (e.g =2000) to improve
3333 // the performance. If this value =0, all inner points will be taken into account.
3335 aFinder.SetNbPntsMax(100);
3339 // Interprete results
3340 Standard_Integer iErr = aFinder.ErrorStatus();
3341 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
3343 MESSAGE(" iErr : " << iErr);
3344 TCollection_AsciiString aMsg (" iErr : ");
3345 aMsg += TCollection_AsciiString(iErr);
3349 Standard_Integer iWrn = aFinder.WarningStatus();
3350 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
3352 MESSAGE(" *** iWrn : " << iWrn);
3355 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
3357 if (listSS.Extent() < 1) {
3358 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
3359 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
3363 // Fill sequence of object IDs
3364 aSeqOfIDs = new TColStd_HSequenceOfInteger;
3366 TopTools_IndexedMapOfShape anIndices;
3367 TopExp::MapShapes(theShape, anIndices);
3369 TopTools_ListIteratorOfListOfShape itSub (listSS);
3370 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3371 int id = anIndices.FindIndex(itSub.Value());
3372 aSeqOfIDs->Append(id);
3378 //=======================================================================
3379 //function : getObjectsShapesOn
3381 * \brief Find shape objects and their entries by their ids
3382 * \param theShapeIDs - incoming shape ids
3383 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3384 * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
3386 //=======================================================================
3387 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
3388 getObjectsShapesOn(const Handle(GEOM_Object)& theShape,
3389 const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
3390 TCollection_AsciiString & theShapeEntries)
3392 Handle(TColStd_HSequenceOfTransient) aSeq;
3394 if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
3396 aSeq = new TColStd_HSequenceOfTransient;
3397 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3398 TCollection_AsciiString anEntry;
3399 for ( int i = 1; i <= theShapeIDs->Length(); ++i )
3401 anArray->SetValue(1, theShapeIDs->Value( i ));
3402 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3403 aSeq->Append( anObj );
3405 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3406 if ( i != 1 ) theShapeEntries += ",";
3407 theShapeEntries += anEntry;
3413 //=============================================================================
3415 * getSubShapeEdgeSortedIDs
3417 //=============================================================================
3418 Handle(TColStd_HSequenceOfInteger)
3419 GEOMImpl_IShapesOperations::getSubShapeEdgeSortedIDs
3420 (const Handle(GEOM_Object) &theShape,
3421 const Handle(GEOM_Object) &theStartPoint)
3423 Handle(TColStd_HSequenceOfInteger) aResult;
3425 if (theShape.IsNull() || theStartPoint.IsNull()) {
3426 SetErrorCode("NULL GEOM object");
3430 const TopoDS_Shape aShape = theShape->GetValue();
3431 const TopoDS_Shape aStartPoint = theStartPoint->GetValue();
3433 if (aShape.IsNull() || aStartPoint.IsNull()) {
3434 SetErrorCode("NULL Shape");
3438 if (aStartPoint.ShapeType() != TopAbs_VERTEX) {
3439 SetErrorCode("Starting point is not a vertex");
3443 TopExp_Explorer anExp(aShape, TopAbs_EDGE);
3444 TopTools_MapOfShape aMapFence;
3445 TopTools_ListOfShape anEdges;
3447 for (; anExp.More(); anExp.Next()) {
3448 const TopoDS_Shape &anEdge = anExp.Current();
3450 if (aMapFence.Add(anEdge)) {
3451 anEdges.Append(anEdge);
3455 if (anEdges.IsEmpty()) {
3456 SetErrorCode("Shape doesn't contain edges");
3460 // Step 1: Sort edges
3461 GEOMUtils::SortShapes(anEdges, Standard_False);
3463 TopTools_ListIteratorOfListOfShape anIter(anEdges);
3464 TopoDS_Vertex aV[2];
3465 TopTools_DataMapOfShapeListOfShape aMapVE;
3467 // Step 2: Fill the map vertex - list of edges.
3468 for (; anIter.More(); anIter.Next()) {
3469 TopoDS_Edge anEdge = TopoDS::Edge(anIter.Value());
3471 TopExp::Vertices(anEdge, aV[0], aV[1]);
3473 const Standard_Integer aNbV = aV[0].IsSame(aV[1]) ? 1 : 2;
3476 for (i = 0; i < aNbV; ++i) {
3477 if (aV[i].IsNull() == Standard_False) {
3478 if (!aMapVE.IsBound(aV[i])) {
3479 // There is no this vertex in the map.
3480 aMapVE.Bind(aV[i], TopTools_ListOfShape());
3483 // Add the edge to the list bound with the vertex aV[i].
3484 TopTools_ListOfShape &aLEdges = aMapVE.ChangeFind(aV[i]);
3486 aLEdges.Append(anEdge);
3491 // Step 3: Find starting point in aMapVE.
3492 TopoDS_Vertex aStartVtx = TopoDS::Vertex(aStartPoint);
3494 if (!aMapVE.IsBound(aStartVtx)) {
3495 aStartVtx = getSameVertex(aShape, aStartVtx);
3497 if (aStartVtx.IsNull()) {
3498 SetErrorCode("Invalid Starting point");
3503 TopTools_IndexedMapOfShape anIndices;
3504 TopTools_MapOfShape aMapVFence;
3505 TopoDS_Shape aCurVtx = aStartVtx;
3506 TopoDS_Edge aCurEdge =
3507 TopoDS::Edge(aMapVE.Find(aCurVtx).First());
3509 aResult = new TColStd_HSequenceOfInteger;
3510 TopExp::MapShapes(aShape, anIndices);
3512 // Step 4: Fill the list of sorted edges.
3513 while (aMapVFence.Add(aCurVtx)) {
3514 // Append the ID of the current edge to the list of sorted.
3515 aResult->Append(anIndices.FindIndex(aCurEdge));
3516 TopExp::Vertices(aCurEdge, aV[0], aV[1]);
3518 // Get the next vertex.
3519 if (aCurVtx.IsSame(aV[0])) {
3520 if (aCurVtx.IsSame(aV[1])) {
3521 // There is no next vertex.
3530 if (aCurVtx.IsNull()) {
3531 // There is no next vertex.
3535 // Get the next edge.
3536 const TopTools_ListOfShape &aLEdges = aMapVE.Find(aCurVtx);
3537 TopTools_ListIteratorOfListOfShape anEIter(aLEdges);
3539 for (; anEIter.More(); anEIter.Next()) {
3540 const TopoDS_Shape &aLocalEdge = anEIter.Value();
3542 if (aLocalEdge.IsNull() == Standard_False) {
3543 if (!aCurEdge.IsSame(aLocalEdge)) {
3544 aCurEdge = TopoDS::Edge(aLocalEdge);
3550 if (!anEIter.More()) {
3551 // There is no next edge.
3559 //=======================================================================
3560 //function : getShapesOnSurface
3562 * \brief Find sub-shapes complying with given status about surface
3563 * \param theSurface - the surface to check state of sub-shapes against
3564 * \param theShape - the shape to explore
3565 * \param theShapeType - type of sub-shape of theShape
3566 * \param theState - required state
3567 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3568 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3570 //=======================================================================
3571 Handle(TColStd_HSequenceOfTransient)
3572 GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
3573 const Handle(GEOM_Object)& theShape,
3574 TopAbs_ShapeEnum theShapeType,
3575 GEOMAlgo_State theState,
3576 TCollection_AsciiString & theShapeEntries)
3578 // Find sub-shapes ids
3579 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3580 getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
3581 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3584 return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
3587 //=============================================================================
3591 //=============================================================================
3592 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
3593 (const Handle(GEOM_Object)& theShape,
3594 const Standard_Integer theShapeType,
3595 const Handle(GEOM_Object)& theAx1,
3596 const GEOMAlgo_State theState)
3600 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3602 TopoDS_Shape aShape = theShape->GetValue();
3603 TopoDS_Shape anAx1 = theAx1->GetValue();
3605 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3607 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3608 if ( !checkTypeShapesOn( theShapeType ))
3612 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3613 if ( aPlane.IsNull() )
3617 TCollection_AsciiString anAsciiList;
3618 Handle(TColStd_HSequenceOfTransient) aSeq;
3619 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3620 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3623 // Make a Python command
3625 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3626 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3628 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3629 << "] = geompy.GetShapesOnPlane(" << theShape << ", "
3630 << aShapeType << ", " << theAx1 << ", " << theState << ")";
3636 //=============================================================================
3638 * GetShapesOnPlaneWithLocation
3640 //=============================================================================
3641 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
3642 (const Handle(GEOM_Object)& theShape,
3643 const Standard_Integer theShapeType,
3644 const Handle(GEOM_Object)& theAx1,
3645 const Handle(GEOM_Object)& thePnt,
3646 const GEOMAlgo_State theState)
3650 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3652 TopoDS_Shape aShape = theShape->GetValue();
3653 TopoDS_Shape anAx1 = theAx1->GetValue();
3654 TopoDS_Shape anPnt = thePnt->GetValue();
3656 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3658 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3659 if ( !checkTypeShapesOn( theShapeType ))
3663 if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
3664 TopoDS_Vertex V1, V2, V3;
3665 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3666 TopExp::Vertices(anEdge, V1, V2, Standard_True);
3668 if (V1.IsNull() || V2.IsNull()) {
3669 SetErrorCode("Bad edge given for the plane normal vector");
3672 V3 = TopoDS::Vertex(anPnt);
3675 SetErrorCode("Bad vertex given for the plane location");
3678 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3679 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3681 if (aVec.Magnitude() < Precision::Confusion()) {
3682 SetErrorCode("Vector with null magnitude given");
3685 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3687 if ( aPlane.IsNull() )
3691 TCollection_AsciiString anAsciiList;
3692 Handle(TColStd_HSequenceOfTransient) aSeq;
3693 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3694 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3697 // Make a Python command
3699 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3700 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3702 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3703 << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
3704 << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
3710 //=============================================================================
3712 * GetShapesOnCylinder
3714 //=============================================================================
3715 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
3716 (const Handle(GEOM_Object)& theShape,
3717 const Standard_Integer theShapeType,
3718 const Handle(GEOM_Object)& theAxis,
3719 const Standard_Real theRadius,
3720 const GEOMAlgo_State theState)
3724 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3726 TopoDS_Shape aShape = theShape->GetValue();
3727 TopoDS_Shape anAxis = theAxis->GetValue();
3729 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3731 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3732 if ( !checkTypeShapesOn( aShapeType ))
3735 // Create a cylinder surface
3736 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3737 if ( aCylinder.IsNull() )
3741 TCollection_AsciiString anAsciiList;
3742 Handle(TColStd_HSequenceOfTransient) aSeq;
3743 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3744 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3747 // Make a Python command
3749 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3750 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3752 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3753 << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
3754 << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
3760 //=============================================================================
3762 * GetShapesOnCylinderWithLocation
3764 //=============================================================================
3765 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
3766 (const Handle(GEOM_Object)& theShape,
3767 const Standard_Integer theShapeType,
3768 const Handle(GEOM_Object)& theAxis,
3769 const Handle(GEOM_Object)& thePnt,
3770 const Standard_Real theRadius,
3771 const GEOMAlgo_State theState)
3775 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3777 TopoDS_Shape aShape = theShape->GetValue();
3778 TopoDS_Shape anAxis = theAxis->GetValue();
3779 TopoDS_Shape aPnt = thePnt->GetValue();
3781 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3783 if (aPnt.ShapeType() != TopAbs_VERTEX )
3785 SetErrorCode("Bottom location point must be vertex");
3789 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3790 if ( !checkTypeShapesOn( aShapeType ))
3793 // Create a cylinder surface
3794 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3795 if ( aCylinder.IsNull() )
3798 // translate the surface
3799 Handle(Geom_CylindricalSurface) aCylSurface =
3800 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3801 if ( aCylSurface.IsNull() )
3803 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3806 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3807 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3808 aCylinder->Translate( fromLoc, toLoc );
3811 TCollection_AsciiString anAsciiList;
3812 Handle(TColStd_HSequenceOfTransient) aSeq;
3813 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3814 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3817 // Make a Python command
3819 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3820 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3822 GEOM::TPythonDump(aFunction)
3823 << "[" << anAsciiList.ToCString()
3824 << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
3825 << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
3831 //=============================================================================
3835 //=============================================================================
3836 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
3837 (const Handle(GEOM_Object)& theShape,
3838 const Standard_Integer theShapeType,
3839 const Handle(GEOM_Object)& theCenter,
3840 const Standard_Real theRadius,
3841 const GEOMAlgo_State theState)
3845 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3847 TopoDS_Shape aShape = theShape->GetValue();
3848 TopoDS_Shape aCenter = theCenter->GetValue();
3850 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3852 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3853 if ( !checkTypeShapesOn( aShapeType ))
3856 // Center of the sphere
3857 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3858 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3860 gp_Ax3 anAx3 (aLoc, gp::DZ());
3861 Handle(Geom_SphericalSurface) aSphere =
3862 new Geom_SphericalSurface(anAx3, theRadius);
3865 TCollection_AsciiString anAsciiList;
3866 Handle(TColStd_HSequenceOfTransient) aSeq;
3867 aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
3868 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3871 // Make a Python command
3873 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3874 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3876 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3877 << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
3878 << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
3884 //=============================================================================
3886 * GetShapesOnPlaneIDs
3888 //=============================================================================
3889 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
3890 (const Handle(GEOM_Object)& theShape,
3891 const Standard_Integer theShapeType,
3892 const Handle(GEOM_Object)& theAx1,
3893 const GEOMAlgo_State theState)
3897 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3899 TopoDS_Shape aShape = theShape->GetValue();
3900 TopoDS_Shape anAx1 = theAx1->GetValue();
3902 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3904 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3905 if ( !checkTypeShapesOn( aShapeType ))
3909 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3910 if ( aPlane.IsNull() )
3914 Handle(TColStd_HSequenceOfInteger) aSeq;
3915 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3917 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3918 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3920 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
3921 #ifdef DUMP_SUBSHAPE_IDS
3922 // Make a Python command
3923 GEOM::TPythonDump(aFunction, /*append=*/true)
3924 << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
3925 << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
3926 #endif // DUMP_SUBSHAPE_IDS
3932 //=============================================================================
3934 * GetShapesOnPlaneWithLocationIDs
3936 //=============================================================================
3937 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
3938 (const Handle(GEOM_Object)& theShape,
3939 const Standard_Integer theShapeType,
3940 const Handle(GEOM_Object)& theAx1,
3941 const Handle(GEOM_Object)& thePnt,
3942 const GEOMAlgo_State theState)
3946 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3948 TopoDS_Shape aShape = theShape->GetValue();
3949 TopoDS_Shape anAx1 = theAx1->GetValue();
3950 TopoDS_Shape anPnt = thePnt->GetValue();
3952 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3954 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3955 if ( !checkTypeShapesOn( aShapeType ))
3959 if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
3960 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3961 TopoDS_Vertex V1, V2, V3;
3962 TopExp::Vertices(anEdge, V1, V2, Standard_True);
3963 if (V1.IsNull() || V2.IsNull()) {
3964 SetErrorCode("Bad edge given for the plane normal vector");
3967 V3 = TopoDS::Vertex(anPnt);
3969 SetErrorCode("Bad vertex given for the plane location");
3972 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3973 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3974 if (aVec.Magnitude() < Precision::Confusion()) {
3975 SetErrorCode("Vector with null magnitude given");
3979 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3980 if ( aPlane.IsNull() )
3984 Handle(TColStd_HSequenceOfInteger) aSeq;
3985 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3987 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3988 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3990 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
3991 #ifdef DUMP_SUBSHAPE_IDS
3992 // Make a Python command
3993 GEOM::TPythonDump(aFunction, /*append=*/true)
3994 << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
3995 << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")";
3996 #endif // DUMP_SUBSHAPE_IDS
4002 //=============================================================================
4004 * GetShapesOnCylinderIDs
4006 //=============================================================================
4007 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
4008 (const Handle(GEOM_Object)& theShape,
4009 const Standard_Integer theShapeType,
4010 const Handle(GEOM_Object)& theAxis,
4011 const Standard_Real theRadius,
4012 const GEOMAlgo_State theState)
4016 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
4018 TopoDS_Shape aShape = theShape->GetValue();
4019 TopoDS_Shape anAxis = theAxis->GetValue();
4021 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
4023 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4024 if ( !checkTypeShapesOn( aShapeType ))
4027 // Create a cylinder surface
4028 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4029 if ( aCylinder.IsNull() )
4033 Handle(TColStd_HSequenceOfInteger) aSeq;
4034 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4036 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4037 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
4039 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4040 #ifdef DUMP_SUBSHAPE_IDS
4041 // Make a Python command
4042 GEOM::TPythonDump(aFunction, /*append=*/true)
4043 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
4044 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4045 << theRadius << ", " << theState << ")";
4046 #endif // DUMP_SUBSHAPE_IDS
4052 //=============================================================================
4054 * GetShapesOnCylinderWithLocationIDs
4056 //=============================================================================
4057 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
4058 (const Handle(GEOM_Object)& theShape,
4059 const Standard_Integer theShapeType,
4060 const Handle(GEOM_Object)& theAxis,
4061 const Handle(GEOM_Object)& thePnt,
4062 const Standard_Real theRadius,
4063 const GEOMAlgo_State theState)
4067 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
4069 TopoDS_Shape aShape = theShape->GetValue();
4070 TopoDS_Shape anAxis = theAxis->GetValue();
4071 TopoDS_Shape aPnt = thePnt->GetValue();
4073 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
4075 if (aPnt.ShapeType() != TopAbs_VERTEX )
4077 SetErrorCode("Bottom location point must be vertex");
4081 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4082 if ( !checkTypeShapesOn( aShapeType ))
4085 // Create a cylinder surface
4086 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4087 if ( aCylinder.IsNull() )
4090 // translate the surface
4091 Handle(Geom_CylindricalSurface) aCylSurface =
4092 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
4093 if ( aCylSurface.IsNull() )
4095 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
4098 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
4099 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
4100 aCylinder->Translate( fromLoc, toLoc );
4103 Handle(TColStd_HSequenceOfInteger) aSeq;
4104 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4106 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4107 Handle(GEOM_Function) aFunction =
4108 GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
4110 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4111 #ifdef DUMP_SUBSHAPE_IDS
4112 // Make a Python command
4113 GEOM::TPythonDump(aFunction, /*append=*/true)
4114 << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
4115 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4116 << thePnt << ", " << theRadius << ", " << theState << ")";
4117 #endif // DUMP_SUBSHAPE_IDS
4123 //=============================================================================
4125 * GetShapesOnSphereIDs
4127 //=============================================================================
4128 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
4129 (const Handle(GEOM_Object)& theShape,
4130 const Standard_Integer theShapeType,
4131 const Handle(GEOM_Object)& theCenter,
4132 const Standard_Real theRadius,
4133 const GEOMAlgo_State theState)
4137 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
4139 TopoDS_Shape aShape = theShape->GetValue();
4140 TopoDS_Shape aCenter = theCenter->GetValue();
4142 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
4144 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4145 if ( !checkTypeShapesOn( aShapeType ))
4148 // Center of the sphere
4149 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
4150 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
4152 gp_Ax3 anAx3 (aLoc, gp::DZ());
4153 Handle(Geom_SphericalSurface) aSphere =
4154 new Geom_SphericalSurface(anAx3, theRadius);
4157 Handle(TColStd_HSequenceOfInteger) aSeq;
4158 aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
4160 // The GetShapesOnSphere() doesn't change object so no new function is required.
4161 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
4163 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4164 #ifdef DUMP_SUBSHAPE_IDS
4165 // Make a Python command
4166 GEOM::TPythonDump(aFunction, /*append=*/true)
4167 << "listShapesOnSphere = geompy.GetShapesOnSphereIDs"
4168 << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
4169 << theRadius << ", " << theState << ")";
4170 #endif // DUMP_SUBSHAPE_IDS
4176 //=======================================================================
4177 //function : getShapesOnQuadrangleIDs
4179 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4180 * \param theShape - the shape to explore
4181 * \param theShapeType - type of sub-shape of theShape
4182 * \param theTopLeftPoint - top left quadrangle corner
4183 * \param theTopRigthPoint - top right quadrangle corner
4184 * \param theBottomLeftPoint - bottom left quadrangle corner
4185 * \param theBottomRigthPoint - bottom right quadrangle corner
4186 * \param theState - required state
4187 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4189 //=======================================================================
4190 Handle(TColStd_HSequenceOfInteger)
4191 GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4192 const Standard_Integer theShapeType,
4193 const Handle(GEOM_Object)& theTopLeftPoint,
4194 const Handle(GEOM_Object)& theTopRigthPoint,
4195 const Handle(GEOM_Object)& theBottomLeftPoint,
4196 const Handle(GEOM_Object)& theBottomRigthPoint,
4197 const GEOMAlgo_State theState)
4201 if ( theShape.IsNull() ||
4202 theTopLeftPoint.IsNull() ||
4203 theTopRigthPoint.IsNull() ||
4204 theBottomLeftPoint.IsNull() ||
4205 theBottomRigthPoint.IsNull() )
4208 TopoDS_Shape aShape = theShape->GetValue();
4209 TopoDS_Shape aTL = theTopLeftPoint->GetValue();
4210 TopoDS_Shape aTR = theTopRigthPoint->GetValue();
4211 TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
4212 TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
4214 if (aShape.IsNull() ||
4219 aTL.ShapeType() != TopAbs_VERTEX ||
4220 aTR.ShapeType() != TopAbs_VERTEX ||
4221 aBL.ShapeType() != TopAbs_VERTEX ||
4222 aBR.ShapeType() != TopAbs_VERTEX )
4225 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4226 if ( !checkTypeShapesOn( aShapeType ))
4229 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
4231 // Check presence of triangulation, build if need
4232 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
4233 SetErrorCode("Cannot build triangulation on the shape");
4238 gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
4239 gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
4240 gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
4241 gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
4243 GEOMAlgo_FinderShapeOn2 aFinder;
4244 Handle(GEOMAlgo_ClsfQuad) aClsfQuad = new GEOMAlgo_ClsfQuad;
4246 Standard_Real aTol = 0.0001; // default value
4248 aClsfQuad->SetCorners(aPntTL, aPntTR, aPntBL, aPntBR);
4249 aFinder.SetShape(aShape);
4250 aFinder.SetTolerance(aTol);
4251 aFinder.SetClsf(aClsfQuad);
4252 aFinder.SetShapeType(aShapeType);
4253 aFinder.SetState(theState);
4255 // Sets the minimal number of inner points for the faces that do not have own
4256 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
4258 aFinder.SetNbPntsMin(3);
4259 // Sets the maximal number of inner points for edges or faces.
4260 // It is usefull for the cases when this number is very big (e.g =2000) to improve
4261 // the performance. If this value =0, all inner points will be taken into account.
4263 aFinder.SetNbPntsMax(100);
4267 // Interprete results
4268 Standard_Integer iErr = aFinder.ErrorStatus();
4269 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
4271 MESSAGE(" iErr : " << iErr);
4272 TCollection_AsciiString aMsg (" iErr : ");
4273 aMsg += TCollection_AsciiString(iErr);
4277 Standard_Integer iWrn = aFinder.WarningStatus();
4278 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
4280 MESSAGE(" *** iWrn : " << iWrn);
4283 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
4285 if (listSS.Extent() < 1) {
4286 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
4287 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
4291 // Fill sequence of object IDs
4292 aSeqOfIDs = new TColStd_HSequenceOfInteger;
4294 TopTools_IndexedMapOfShape anIndices;
4295 TopExp::MapShapes(aShape, anIndices);
4297 TopTools_ListIteratorOfListOfShape itSub (listSS);
4298 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
4299 int id = anIndices.FindIndex(itSub.Value());
4300 aSeqOfIDs->Append(id);
4305 //=======================================================================
4306 //function : GetShapesOnQuadrangle
4308 * \brief Find sub-shapes complying with given status about quadrangle
4309 * \param theShape - the shape to explore
4310 * \param theShapeType - type of sub-shape of theShape
4311 * \param theTopLeftPoint - top left quadrangle corner
4312 * \param theTopRigthPoint - top right quadrangle corner
4313 * \param theBottomLeftPoint - bottom left quadrangle corner
4314 * \param theBottomRigthPoint - bottom right quadrangle corner
4315 * \param theState - required state
4316 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4318 //=======================================================================
4319 Handle(TColStd_HSequenceOfTransient)
4320 GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
4321 const Standard_Integer theShapeType,
4322 const Handle(GEOM_Object)& theTopLeftPoint,
4323 const Handle(GEOM_Object)& theTopRigthPoint,
4324 const Handle(GEOM_Object)& theBottomLeftPoint,
4325 const Handle(GEOM_Object)& theBottomRigthPoint,
4326 const GEOMAlgo_State theState)
4329 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4330 getShapesOnQuadrangleIDs( theShape,
4335 theBottomRigthPoint,
4337 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4340 // Find objects by indices
4341 TCollection_AsciiString anAsciiList;
4342 Handle(TColStd_HSequenceOfTransient) aSeq;
4343 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
4344 if ( aSeq.IsNull() || aSeq->IsEmpty() )
4347 // Make a Python command
4349 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
4350 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
4352 GEOM::TPythonDump(aFunction)
4353 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
4355 << TopAbs_ShapeEnum(theShapeType) << ", "
4356 << theTopLeftPoint << ", "
4357 << theTopRigthPoint << ", "
4358 << theBottomLeftPoint << ", "
4359 << theBottomRigthPoint << ", "
4366 //=======================================================================
4367 //function : GetShapesOnQuadrangleIDs
4369 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4370 * \param theShape - the shape to explore
4371 * \param theShapeType - type of sub-shape of theShape
4372 * \param theTopLeftPoint - top left quadrangle corner
4373 * \param theTopRigthPoint - top right quadrangle corner
4374 * \param theBottomLeftPoint - bottom left quadrangle corner
4375 * \param theBottomRigthPoint - bottom right quadrangle corner
4376 * \param theState - required state
4377 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4379 //=======================================================================
4380 Handle(TColStd_HSequenceOfInteger)
4381 GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4382 const Standard_Integer theShapeType,
4383 const Handle(GEOM_Object)& theTopLeftPoint,
4384 const Handle(GEOM_Object)& theTopRigthPoint,
4385 const Handle(GEOM_Object)& theBottomLeftPoint,
4386 const Handle(GEOM_Object)& theBottomRigthPoint,
4387 const GEOMAlgo_State theState)
4390 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4391 getShapesOnQuadrangleIDs( theShape,
4396 theBottomRigthPoint,
4398 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4401 // Make a Python command
4403 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4404 Handle(GEOM_BaseObject) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
4405 lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
4406 lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
4407 lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
4408 Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
4410 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4411 #ifdef DUMP_SUBSHAPE_IDS
4412 GEOM::TPythonDump(aFunction, /*append=*/true)
4413 << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
4415 << TopAbs_ShapeEnum(theShapeType) << ", "
4416 << theTopLeftPoint << ", "
4417 << theTopRigthPoint << ", "
4418 << theBottomLeftPoint << ", "
4419 << theBottomRigthPoint << ", "
4421 #endif // DUMP_SUBSHAPE_IDS
4427 //=============================================================================
4432 //=============================================================================
4433 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
4434 Handle(GEOM_Object) theShapeWhat)
4438 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4440 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4441 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4443 if (aWhere.IsNull() || aWhat.IsNull()) {
4444 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4448 // Searching for the sub-shapes inside the ShapeWhere shape
4449 GEOMAlgo_GetInPlace aGIP;
4451 if (!GEOMAlgo_GetInPlaceAPI::GetInPlace(aWhere, aWhat, aGIP)) {
4452 SetErrorCode("Error in GEOMAlgo_GetInPlace");
4456 // Add direct result.
4457 TopTools_ListOfShape aLSA;
4458 const TopoDS_Shape &aShapeResult = aGIP.Result();
4459 TopTools_MapOfShape aMFence;
4460 TopTools_IndexedMapOfShape aWhereIndices;
4461 Standard_Integer aShapeType = -1;
4463 TopExp::MapShapes(aWhere, aWhereIndices);
4465 if (aShapeResult.IsNull() == Standard_False) {
4466 TopoDS_Iterator anIt(aShapeResult);
4467 Standard_Boolean isFirst = Standard_True;
4469 for (; anIt.More(); anIt.Next()) {
4470 const TopoDS_Shape &aPart = anIt.Value();
4472 if(aWhereIndices.Contains(aPart) && aMFence.Add(aPart)) {
4473 const TopAbs_ShapeEnum aType = aPart.ShapeType();
4475 if (aShapeType == -1) {
4478 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4480 aShapeType = TopAbs_SHAPE;
4488 if (aLSA.Extent() == 0) {
4489 SetErrorCode(NOT_FOUND_ANY); // Not found any Results
4493 Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent());
4494 TopTools_ListIteratorOfListOfShape anIterModif (aLSA);
4495 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4496 aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value()));
4500 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4501 if (aResult.IsNull()) {
4502 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4506 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4508 if ((aModifiedArray->Length() > 1 && isSameType) ||
4509 theShapeWhat->GetType() == GEOM_GROUP) {
4511 aResult->SetType(GEOM_GROUP);
4513 //Set a sub-shape type
4514 TopoDS_Shape aFirstFound = aLSA.First();
4515 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4517 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4518 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4521 //Make a Python command
4522 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4524 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4525 << theShapeWhere << ", " << theShapeWhat << ", True)";
4531 //=============================================================================
4533 * case GetInPlaceOld:
4536 //=============================================================================
4537 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld
4538 (Handle(GEOM_Object) theShapeWhere,
4539 Handle(GEOM_Object) theShapeWhat)
4543 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4545 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4546 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4547 TopTools_ListOfShape aModifiedList;
4548 const Standard_Integer iErr =
4549 GEOMAlgo_GetInPlaceAPI::GetInPlaceOld(aWhere, aWhat, aModifiedList);
4554 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4558 ("Error: An attempt to extract a shape of not supported type.");
4561 SetErrorCode(NOT_FOUND_ANY);
4564 SetErrorCode("Shape driver failed");
4571 TopTools_IndexedMapOfShape aWhereIndices;
4572 TopExp::MapShapes(aWhere, aWhereIndices);
4574 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4575 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4576 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4577 Standard_Integer imod;
4578 Standard_Integer aShapeType = -1;
4580 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4581 const Standard_Integer anIndex =
4582 aWhereIndices.FindIndex(anIterModif.Value());
4583 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4585 if (aShapeType == -1) {
4588 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4590 aShapeType = TopAbs_SHAPE;
4593 aModifiedArray->SetValue(imod, anIndex);
4597 Handle(GEOM_Object) aResult =
4598 GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4600 if (aResult.IsNull()) {
4601 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4605 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4607 if ((aModifiedArray->Length() > 1 && isSameType) ||
4608 theShapeWhat->GetType() == GEOM_GROUP) {
4610 aResult->SetType(GEOM_GROUP);
4612 //Set a sub-shape type
4613 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4614 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4616 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4617 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4620 //Make a Python command
4621 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4623 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4624 << theShapeWhere << ", " << theShapeWhat << ", False)";
4631 //=======================================================================
4632 //function : GetInPlaceByHistory
4634 //=======================================================================
4635 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
4636 (Handle(GEOM_Object) theShapeWhere,
4637 Handle(GEOM_Object) theShapeWhat)
4641 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4643 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4644 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4646 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4648 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4649 if (aWhereFunction.IsNull()) return NULL;
4651 //Fill array of indices
4652 TopTools_IndexedMapOfShape aWhereIndices;
4654 TopExp::MapShapes(aWhere, aWhereIndices);
4657 TopTools_ListOfShape aModifiedList;
4658 bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceByHistory
4659 (aWhereFunction, aWhereIndices, aWhat, aModifiedList);
4661 if (!isFound || aModifiedList.Extent() < 1) {
4662 SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
4666 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4667 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4668 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4669 Standard_Integer imod;
4670 Standard_Integer aShapeType = -1;
4672 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4673 const Standard_Integer anIndex =
4674 aWhereIndices.FindIndex(anIterModif.Value());
4675 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4677 if (aShapeType == -1) {
4680 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4682 aShapeType = TopAbs_SHAPE;
4685 aModifiedArray->SetValue(imod, anIndex);
4689 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4690 if (aResult.IsNull()) {
4691 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4695 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4697 if ((aModifiedArray->Length() > 1 && isSameType) ||
4698 theShapeWhat->GetType() == GEOM_GROUP) {
4700 aResult->SetType(GEOM_GROUP);
4702 //Set a sub-shape type
4703 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4704 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4706 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4707 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4710 //Make a Python command
4711 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4713 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
4714 << theShapeWhere << ", " << theShapeWhat << ")";
4720 //=======================================================================
4721 //function : isSameEdge
4722 //purpose : Returns True if two edges coincide
4723 //=======================================================================
4724 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4726 TopoDS_Vertex V11, V12, V21, V22;
4727 TopExp::Vertices(theEdge1, V11, V12);
4728 TopExp::Vertices(theEdge2, V21, V22);
4729 gp_Pnt P11 = BRep_Tool::Pnt(V11);
4730 gp_Pnt P12 = BRep_Tool::Pnt(V12);
4731 gp_Pnt P21 = BRep_Tool::Pnt(V21);
4732 gp_Pnt P22 = BRep_Tool::Pnt(V22);
4733 bool coincide = false;
4735 //Check that ends of edges coincide
4736 if(P11.Distance(P21) <= MAX_TOLERANCE) {
4737 if(P12.Distance(P22) <= MAX_TOLERANCE) coincide = true;
4739 else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4740 if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4743 if(!coincide) return false;
4745 if (BRep_Tool::Degenerated(theEdge1))
4746 if (BRep_Tool::Degenerated(theEdge2)) return true;
4749 if (BRep_Tool::Degenerated(theEdge2)) return false;
4751 double U11, U12, U21, U22;
4752 Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4753 Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4755 //Check that both edges has the same geometry
4756 double range = U12-U11;
4757 double U = U11+ range/3.0;
4758 gp_Pnt P1 = C1->Value(U); //Compute a point on one third of the edge's length
4759 U = U11+range*2.0/3.0;
4760 gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length
4762 C2 = new Geom_TrimmedCurve(C2, U21, U22);
4764 if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22)
4767 if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4769 if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4772 if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4777 //=======================================================================
4778 //function : isSameFace
4779 //purpose : Returns True if two faces coincide
4780 //=======================================================================
4781 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4783 TopExp_Explorer E(theFace1, TopAbs_EDGE);
4784 TopTools_ListOfShape LS1, LS2;
4785 for(; E.More(); E.Next()) LS1.Append(E.Current());
4787 E.Init(theFace2, TopAbs_EDGE);
4788 for(; E.More(); E.Next()) LS2.Append(E.Current());
4790 //Compare the number of edges in the faces
4791 if(LS1.Extent() != LS2.Extent()) return false;
4793 double aMin = RealFirst(), aMax = RealLast();
4794 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4795 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4797 for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4798 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4799 if(P.X() < xminB1) xminB1 = P.X();
4800 if(P.Y() < yminB1) yminB1 = P.Y();
4801 if(P.Z() < zminB1) zminB1 = P.Z();
4802 if(P.X() > xmaxB1) xmaxB1 = P.X();
4803 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4804 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4807 for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4808 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4809 if(P.X() < xminB2) xminB2 = P.X();
4810 if(P.Y() < yminB2) yminB2 = P.Y();
4811 if(P.Z() < zminB2) zminB2 = P.Z();
4812 if(P.X() > xmaxB2) xmaxB2 = P.X();
4813 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4814 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4817 //Compare the bounding boxes of both faces
4818 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4821 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4824 Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4825 Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4827 //Check if there a coincidence of two surfaces at least in two points
4828 double U11, U12, V11, V12, U21, U22, V21, V22;
4829 BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4830 BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4832 double rangeU = U12-U11;
4833 double rangeV = V12-V11;
4834 double U = U11 + rangeU/3.0;
4835 double V = V11 + rangeV/3.0;
4836 gp_Pnt P1 = S1->Value(U, V);
4837 U = U11+rangeU*2.0/3.0;
4838 V = V11+rangeV*2.0/3.0;
4839 gp_Pnt P2 = S1->Value(U, V);
4841 if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4844 if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4846 if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4849 if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
4851 //Check that each edge of the Face1 has a counterpart in the Face2
4852 TopTools_MapOfOrientedShape aMap;
4853 TopTools_ListIteratorOfListOfShape LSI1(LS1);
4854 for(; LSI1.More(); LSI1.Next()) {
4855 TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
4856 bool isFound = false;
4857 TopTools_ListIteratorOfListOfShape LSI2(LS2);
4858 for(; LSI2.More(); LSI2.Next()) {
4859 TopoDS_Shape aValue = LSI2.Value();
4860 if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
4861 if(isSameEdge(E, TopoDS::Edge(aValue))) {
4867 if(!isFound) return false;
4873 //=======================================================================
4874 //function : isSameSolid
4875 //purpose : Returns True if two solids coincide
4876 //=======================================================================
4877 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
4879 TopExp_Explorer E(theSolid1, TopAbs_FACE);
4880 TopTools_ListOfShape LS1, LS2;
4881 for(; E.More(); E.Next()) LS1.Append(E.Current());
4882 E.Init(theSolid2, TopAbs_FACE);
4883 for(; E.More(); E.Next()) LS2.Append(E.Current());
4885 if(LS1.Extent() != LS2.Extent()) return false;
4887 double aMin = RealFirst(), aMax = RealLast();
4888 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4889 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4891 for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
4892 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4893 if(P.X() < xminB1) xminB1 = P.X();
4894 if(P.Y() < yminB1) yminB1 = P.Y();
4895 if(P.Z() < zminB1) zminB1 = P.Z();
4896 if(P.X() > xmaxB1) xmaxB1 = P.X();
4897 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4898 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4901 for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
4902 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4903 if(P.X() < xminB2) xminB2 = P.X();
4904 if(P.Y() < yminB2) yminB2 = P.Y();
4905 if(P.Z() < zminB2) zminB2 = P.Z();
4906 if(P.X() > xmaxB2) xmaxB2 = P.X();
4907 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4908 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4911 //Compare the bounding boxes of both solids
4912 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4915 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4918 //Check that each face of the Solid1 has a counterpart in the Solid2
4919 TopTools_MapOfOrientedShape aMap;
4920 TopTools_ListIteratorOfListOfShape LSI1(LS1);
4921 for(; LSI1.More(); LSI1.Next()) {
4922 TopoDS_Face F = TopoDS::Face(LSI1.Value());
4923 bool isFound = false;
4924 TopTools_ListIteratorOfListOfShape LSI2(LS2);
4925 for(; LSI2.More(); LSI2.Next()) {
4926 if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
4927 if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
4928 aMap.Add(LSI2.Value());
4933 if(!isFound) return false;
4939 //=======================================================================
4940 //function : GetSame
4942 //=======================================================================
4943 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
4944 const Handle(GEOM_Object)& theShapeWhat)
4947 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4949 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4950 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4952 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4955 bool isFound = false;
4956 TopoDS_Shape aSubShape;
4957 TopTools_MapOfShape aMap;
4959 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4960 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4961 if (It.More()) aWhat = It.Value();
4964 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4969 switch (aWhat.ShapeType()) {
4970 case TopAbs_VERTEX: {
4971 aSubShape = getSameVertex(aWhere, TopoDS::Vertex(aWhat));
4972 isFound = !aSubShape.IsNull();
4976 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4977 TopExp_Explorer E(aWhere, TopAbs_EDGE);
4978 for(; E.More(); E.Next()) {
4979 if(!aMap.Add(E.Current())) continue;
4980 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4981 aSubShape = E.Current();
4989 TopoDS_Face aFace = TopoDS::Face(aWhat);
4990 TopExp_Explorer E(aWhere, TopAbs_FACE);
4991 for(; E.More(); E.Next()) {
4992 if(!aMap.Add(E.Current())) continue;
4993 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
4994 aSubShape = E.Current();
5001 case TopAbs_SOLID: {
5002 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5003 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5004 for(; E.More(); E.Next()) {
5005 if(!aMap.Add(E.Current())) continue;
5006 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5007 aSubShape = E.Current();
5019 TopTools_IndexedMapOfShape anIndices;
5020 TopExp::MapShapes(aWhere, anIndices);
5021 if (anIndices.Contains(aSubShape))
5022 anIndex = anIndices.FindIndex(aSubShape);
5025 if (anIndex < 0) return NULL;
5027 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
5029 anArray->SetValue(1, anIndex);
5031 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
5032 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
5034 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
5035 << theShapeWhere << ", " << theShapeWhat << ")";
5043 //=======================================================================
5044 //function : GetSameIDs
5046 //=======================================================================
5047 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
5048 (const Handle(GEOM_Object)& theShapeWhere,
5049 const Handle(GEOM_Object)& theShapeWhat)
5052 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
5054 TopoDS_Shape aWhere = theShapeWhere->GetValue();
5055 TopoDS_Shape aWhat = theShapeWhat->GetValue();
5057 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
5059 TopTools_ListOfShape listShape;
5060 TopTools_MapOfShape aMap;
5062 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
5063 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
5064 if (It.More()) aWhat = It.Value();
5067 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
5072 switch (aWhat.ShapeType()) {
5073 case TopAbs_VERTEX: {
5074 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
5075 TopExp_Explorer E(aWhere, TopAbs_VERTEX);
5076 for(; E.More(); E.Next()) {
5077 if(!aMap.Add(E.Current())) continue;
5078 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
5079 if(P.Distance(P2) <= MAX_TOLERANCE) {
5080 listShape.Append(E.Current());
5086 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
5087 TopExp_Explorer E(aWhere, TopAbs_EDGE);
5088 for(; E.More(); E.Next()) {
5089 if(!aMap.Add(E.Current())) continue;
5090 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
5091 listShape.Append(E.Current());
5097 TopoDS_Face aFace = TopoDS::Face(aWhat);
5098 TopExp_Explorer E(aWhere, TopAbs_FACE);
5099 for(; E.More(); E.Next()) {
5100 if(!aMap.Add(E.Current())) continue;
5101 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5102 listShape.Append(E.Current());
5107 case TopAbs_SOLID: {
5108 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5109 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5110 for(; E.More(); E.Next()) {
5111 if(!aMap.Add(E.Current())) continue;
5112 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5113 listShape.Append(E.Current());
5122 if ( !listShape.IsEmpty() ) {
5123 TopTools_IndexedMapOfShape anIndices;
5124 TopExp::MapShapes(aWhere, anIndices);
5125 TopTools_ListIteratorOfListOfShape itSub (listShape);
5126 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
5127 for (; itSub.More(); itSub.Next()) {
5128 if (anIndices.Contains(itSub.Value()))
5129 aSeq->Append(anIndices.FindIndex(itSub.Value()));
5132 // The GetSameIDs() doesn't change object so no new function is required.
5133 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
5135 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
5136 #ifdef DUMP_SUBSHAPE_IDS
5137 // Make a Python command
5138 GEOM::TPythonDump(aFunction, /*append=*/true)
5139 << "listSameIDs = geompy.GetSameIDs("
5140 << theShapeWhere << ", "
5141 << theShapeWhat << ")";
5142 #endif // DUMP_SUBSHAPE_IDS
5145 SetErrorCode(NOT_FOUND_ANY);
5150 //=======================================================================
5151 //function : ExtendEdge
5153 //=======================================================================
5154 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendEdge
5155 (const Handle(GEOM_Object) &theEdge,
5156 const Standard_Real theMin,
5157 const Standard_Real theMax)
5161 if (theEdge.IsNull()) {
5165 //Add a new Edge object
5166 Handle(GEOM_Object) aResEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
5168 //Add a new Vector function
5169 Handle(GEOM_Function) aFunction =
5170 aResEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_UV);
5172 //Check if the function is set correctly
5173 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5177 GEOMImpl_IShapeExtend aCI (aFunction);
5179 Handle(GEOM_Function) anEdge = theEdge->GetLastFunction();
5181 if (anEdge.IsNull()) {
5185 aCI.SetShape(anEdge);
5186 aCI.SetUMin(theMin);
5187 aCI.SetUMax(theMax);
5189 //Compute the Edge value
5192 if (!GetSolver()->ComputeFunction(aFunction)) {
5193 SetErrorCode("Shape driver failed");
5198 catch (Standard_Failure& aFail) {
5199 SetErrorCode(aFail.GetMessageString());
5204 //Make a Python command
5205 GEOM::TPythonDump(aFunction)
5206 << aResEdge << " = geompy.ExtendEdge("
5207 << theEdge << ", " << theMin << ", " << theMax << ")";
5214 //=======================================================================
5215 //function : ExtendFace
5217 //=======================================================================
5218 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendFace
5219 (const Handle(GEOM_Object) &theFace,
5220 const Standard_Real theUMin,
5221 const Standard_Real theUMax,
5222 const Standard_Real theVMin,
5223 const Standard_Real theVMax)
5227 if (theFace.IsNull()) {
5231 //Add a new Face object
5232 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
5234 //Add a new Vector function
5235 Handle(GEOM_Function) aFunction =
5236 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_UV);
5238 //Check if the function is set correctly
5239 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5243 GEOMImpl_IShapeExtend aCI (aFunction);
5245 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5247 if (aFace.IsNull()) {
5251 aCI.SetShape(aFace);
5252 aCI.SetUMin(theUMin);
5253 aCI.SetUMax(theUMax);
5254 aCI.SetVMin(theVMin);
5255 aCI.SetVMax(theVMax);
5257 //Compute the Face value
5260 if (!GetSolver()->ComputeFunction(aFunction)) {
5261 SetErrorCode("Shape driver failed");
5266 catch (Standard_Failure& aFail) {
5267 SetErrorCode(aFail.GetMessageString());
5272 //Make a Python command
5273 GEOM::TPythonDump(aFunction)
5274 << aResFace << " = geompy.ExtendFace("
5275 << theFace << ", " << theUMin << ", " << theUMax << ", "
5276 << theVMin << ", " << theVMax << ")";
5283 //=======================================================================
5284 //function : MakeSurfaceFromFace
5286 //=======================================================================
5287 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSurfaceFromFace
5288 (const Handle(GEOM_Object) &theFace)
5292 if (theFace.IsNull()) {
5296 //Add a new Face object
5297 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
5299 //Add a new Vector function
5300 Handle(GEOM_Function) aFunction =
5301 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), SURFACE_FROM_FACE);
5303 //Check if the function is set correctly
5304 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5308 GEOMImpl_IShapeExtend aCI (aFunction);
5310 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5312 if (aFace.IsNull()) {
5316 aCI.SetShape(aFace);
5318 //Compute the Face value
5321 if (!GetSolver()->ComputeFunction(aFunction)) {
5322 SetErrorCode("Shape driver failed");
5327 catch (Standard_Failure& aFail) {
5328 SetErrorCode(aFail.GetMessageString());
5333 //Make a Python command
5334 GEOM::TPythonDump(aFunction)
5335 << aResFace << " = geompy.MakeSurfaceFromFace("