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);
1459 delete [] anEntryStr;
1462 if (aSeq->Length() == 0) {
1463 SetErrorCode(NOT_FOUND_ANY);
1472 //=============================================================================
1476 //=============================================================================
1477 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
1478 (Handle(GEOM_Object) theShape,
1479 const Standard_Integer theShapeType,
1480 const Standard_Boolean isSorted,
1481 const ExplodeType theExplodeType)
1485 if (theShape.IsNull()) return NULL;
1486 TopoDS_Shape aShape = theShape->GetValue();
1487 if (aShape.IsNull()) return NULL;
1489 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1491 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1492 Handle(GEOM_Object) anObj;
1493 TopTools_MapOfShape mapShape;
1494 TopTools_ListOfShape listShape;
1496 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1497 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1499 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1500 for (; It.More(); It.Next()) {
1501 TopoDS_Shape SS = It.Value();
1502 if (mapShape.Add(SS)) {
1503 if (theShapeType == TopAbs_FLAT) {
1504 AddFlatSubShapes(SS, listShape, mapShape);
1506 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1507 listShape.Append(SS);
1509 // VSR: for EXPLODE_NEW_INCLUDE_MAIN and EXPLODE_OLD_INCLUDE_MAIN:
1510 // it seems it is necessary to add top-level shape if theShapeType == TopAbs_COMPOUND
1514 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1516 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1517 for (; exp.More(); exp.Next())
1518 if (mapShape.Add(exp.Current()))
1519 listShape.Append(exp.Current());
1522 if (listShape.IsEmpty()){
1523 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1524 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1529 bool isOldSorting = false;
1530 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1531 isOldSorting = true;
1532 GEOMUtils::SortShapes(listShape, isOldSorting);
1535 TopTools_IndexedMapOfShape anIndices;
1536 TopExp::MapShapes(aShape, anIndices);
1537 Handle(TColStd_HArray1OfInteger) anArray;
1539 TopTools_ListIteratorOfListOfShape itSub (listShape);
1540 TCollection_AsciiString anAsciiList, anEntry;
1541 for (int index = 1; itSub.More(); itSub.Next(), ++index)
1543 TopoDS_Shape aValue = itSub.Value();
1544 anArray = new TColStd_HArray1OfInteger(1,1);
1545 anArray->SetValue(1, anIndices.FindIndex(aValue));
1547 //anObj = GetEngine()->AddSubShape(theShape, anArray);
1549 anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1550 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1551 if (aFunction.IsNull()) return aSeq;
1553 GEOM_ISubShape aSSI (aFunction);
1554 aSSI.SetMainShape(aMainShape);
1555 aSSI.SetIndices(anArray);
1557 // Set function value directly, as we know it.
1558 // Usage of Solver here would lead to significant loss of time,
1559 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1560 // on the main shape for each being calculated sub-shape separately.
1561 aFunction->SetValue(aValue);
1563 // Put this subshape in the list of sub-shapes of theMainShape
1564 aMainShape->AddSubShapeReference(aFunction);
1566 if (!anObj.IsNull()) {
1567 aSeq->Append(anObj);
1569 // for python command
1570 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1571 anAsciiList += anEntry;
1576 //Make a Python command
1577 anAsciiList.Trunc(anAsciiList.Length() - 1);
1579 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1580 pd << "[" << anAsciiList.ToCString() << "] = geompy.";
1581 switch (theExplodeType) {
1582 case EXPLODE_NEW_EXCLUDE_MAIN:
1583 pd << "ExtractShapes(" << theShape << ", "
1584 << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")";
1586 case EXPLODE_NEW_INCLUDE_MAIN:
1587 pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(")
1588 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1590 case EXPLODE_OLD_INCLUDE_MAIN:
1591 pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(")
1592 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1601 //=============================================================================
1605 //=============================================================================
1606 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
1607 (Handle(GEOM_Object) theShape,
1608 const Standard_Integer theShapeType,
1609 const Standard_Boolean isSorted,
1610 const ExplodeType theExplodeType)
1614 if (theShape.IsNull()) return NULL;
1615 TopoDS_Shape aShape = theShape->GetValue();
1616 if (aShape.IsNull()) return NULL;
1618 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1619 TopTools_MapOfShape mapShape;
1620 TopTools_ListOfShape listShape;
1622 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1623 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1625 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1626 for (; It.More(); It.Next()) {
1627 TopoDS_Shape SS = It.Value();
1628 if (mapShape.Add(SS)) {
1629 if (theShapeType == TopAbs_FLAT) {
1630 AddFlatSubShapes(SS, listShape, mapShape);
1632 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1633 listShape.Append(SS);
1638 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1640 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1641 for (; exp.More(); exp.Next())
1642 if (mapShape.Add(exp.Current()))
1643 listShape.Append(exp.Current());
1646 if (listShape.IsEmpty()) {
1647 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1648 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1653 bool isOldSorting = false;
1654 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1655 isOldSorting = true;
1656 GEOMUtils::SortShapes(listShape, isOldSorting);
1659 TopTools_IndexedMapOfShape anIndices;
1660 TopExp::MapShapes(aShape, anIndices);
1661 Handle(TColStd_HArray1OfInteger) anArray;
1663 TopTools_ListIteratorOfListOfShape itSub (listShape);
1664 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1665 TopoDS_Shape aValue = itSub.Value();
1666 aSeq->Append(anIndices.FindIndex(aValue));
1669 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1671 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
1672 #ifdef DUMP_SUBSHAPE_IDS
1673 //Make a Python command
1674 GEOM::TPythonDump pd (aFunction, /*append=*/true);
1675 pd << "listSubShapeIDs = geompy.SubShapeAll";
1676 switch (theExplodeType) {
1677 case EXPLODE_NEW_EXCLUDE_MAIN:
1679 case EXPLODE_NEW_INCLUDE_MAIN:
1680 pd << (isSorted ? "SortedCentresIDs(" : "IDs(")
1681 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1683 case EXPLODE_OLD_INCLUDE_MAIN:
1684 pd << (isSorted ? "SortedIDs(" : "IDs(")
1685 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1689 #endif // DUMP_SUBSHAPE_IDS
1695 //=============================================================================
1699 //=============================================================================
1700 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
1701 (Handle(GEOM_Object) theMainShape,
1702 const Standard_Integer theID)
1706 if (theMainShape.IsNull()) return NULL;
1708 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1709 anArray->SetValue(1, theID);
1710 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
1711 if (anObj.IsNull()) {
1712 SetErrorCode("Can not get a sub-shape with the given ID");
1716 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1718 //Make a Python command
1719 GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1720 << theMainShape << ", [" << theID << "])";
1726 //=============================================================================
1730 //=============================================================================
1731 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes
1732 (Handle(GEOM_Object) theMainShape,
1733 Handle(TColStd_HArray1OfInteger) theIndices)
1737 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1739 if (!theIndices->Length()) {
1740 SetErrorCode(NOT_FOUND_ANY);
1744 if (theMainShape.IsNull()) return NULL;
1745 TopoDS_Shape aShape = theMainShape->GetValue();
1746 if (aShape.IsNull()) return NULL;
1748 Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
1750 TopTools_IndexedMapOfShape anIndices;
1751 TopExp::MapShapes(aShape, anIndices);
1753 Handle(TColStd_HArray1OfInteger) anArray;
1754 Handle(GEOM_Object) anObj;
1756 TCollection_AsciiString anAsciiList, anEntry;
1757 Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper();
1758 for (i = low; i <= up; i++) {
1759 int id = theIndices->Value(i);
1760 if (1 <= id && id <= anIndices.Extent()) {
1761 TopoDS_Shape aValue = anIndices.FindKey(id);
1762 anArray = new TColStd_HArray1OfInteger(1,1);
1763 anArray->SetValue(1, id);
1765 anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1766 if (!anObj.IsNull()) {
1767 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1768 if (aFunction.IsNull()) return aSeq;
1770 GEOM_ISubShape aSSI (aFunction);
1771 aSSI.SetMainShape(aMainShape);
1772 aSSI.SetIndices(anArray);
1774 // Set function value directly, as we know it.
1775 // Usage of Solver here would lead to significant loss of time,
1776 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1777 // on the main shape for each being calculated sub-shape separately.
1778 aFunction->SetValue(aValue);
1780 // Put this sub-shape in the list of sub-shapes of theMainShape
1781 aMainShape->AddSubShapeReference(aFunction);
1783 aSeq->Append(anObj);
1785 // for python command
1786 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1787 anAsciiList += anEntry;
1793 //Make a Python command
1794 anAsciiList.Trunc(anAsciiList.Length() - 1);
1796 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1797 pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes("
1798 << theMainShape << ", [" ;
1799 for (i = low; i <= up - 1; i++) {
1800 pd << theIndices->Value(i) << ", ";
1802 pd << theIndices->Value(up) << "])";
1809 //=============================================================================
1813 //=============================================================================
1814 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1815 Handle(GEOM_Object) theSubShape)
1819 TopoDS_Shape aMainShape = theMainShape->GetValue();
1820 TopoDS_Shape aSubShape = theSubShape->GetValue();
1822 if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1824 TopTools_IndexedMapOfShape anIndices;
1825 TopExp::MapShapes(aMainShape, anIndices);
1826 // if (anIndices.Contains(aSubShape)) {
1827 // SetErrorCode(OK);
1828 // return anIndices.FindIndex(aSubShape);
1830 int id = anIndices.FindIndex(aSubShape);
1841 //=============================================================================
1843 * GetSubShapeIndices
1845 //=============================================================================
1846 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSubShapesIndices (Handle(GEOM_Object) theMainShape,
1847 std::list<Handle(GEOM_Object)> theSubShapes)
1849 MESSAGE("GEOMImpl_IShapesOperations::GetSubShapesIndices")
1852 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1854 TopoDS_Shape aMainShape = theMainShape->GetValue();
1855 if (aMainShape.IsNull())
1857 MESSAGE("NULL main shape")
1861 TopTools_IndexedMapOfShape anIndices;
1862 TopExp::MapShapes(aMainShape, anIndices);
1864 std::list<Handle(GEOM_Object)>::iterator it;
1865 for (it=theSubShapes.begin(); it != theSubShapes.end(); ++it)
1867 TopoDS_Shape aSubShape = (*it)->GetValue();
1868 if (aSubShape.IsNull())
1870 MESSAGE("NULL subshape")
1873 int id = anIndices.FindIndex(aSubShape);
1882 //=============================================================================
1886 //=============================================================================
1887 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1888 Handle(GEOM_Object) theSubShape)
1892 TopoDS_Shape aMainShape = theMainShape->GetValue();
1893 TopoDS_Shape aSubShape = theSubShape->GetValue();
1895 if (aMainShape.IsNull() || aSubShape.IsNull()) {
1896 SetErrorCode("Null argument shape given");
1901 if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1903 TopTools_ListOfShape CL;
1904 CL.Append(aMainShape);
1905 TopTools_ListIteratorOfListOfShape itC;
1906 for (itC.Initialize(CL); itC.More(); itC.Next()) {
1907 for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1908 if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1909 if (it.Value().IsSame(aSubShape))
1913 CL.Append(it.Value());
1918 TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1919 TopTools_MapOfShape M;
1920 for (; anExp.More(); anExp.Next()) {
1921 if (M.Add(anExp.Current())) {
1922 if (anExp.Current().IsSame(aSubShape))
1929 SetErrorCode("The sub-shape does not belong to the main shape");
1933 //=============================================================================
1935 * GetShapeTypeString
1937 //=============================================================================
1938 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1942 TCollection_AsciiString aTypeName ("Null Shape");
1944 TopoDS_Shape aShape = theShape->GetValue();
1945 if (aShape.IsNull())
1948 switch (aShape.ShapeType() )
1950 case TopAbs_COMPOUND:
1951 aTypeName = "Compound";
1953 case TopAbs_COMPSOLID:
1954 aTypeName = "Compound Solid";
1957 aTypeName = "Solid";
1960 aTypeName = "Shell";
1964 BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1965 if (surf.GetType() == GeomAbs_Plane)
1966 aTypeName = "Plane";
1967 else if (surf.GetType() == GeomAbs_Cylinder)
1968 aTypeName = "Cylindrical Face";
1969 else if (surf.GetType() == GeomAbs_Sphere)
1970 aTypeName = "Spherical Face";
1971 else if (surf.GetType() == GeomAbs_Torus)
1972 aTypeName = "Toroidal Face";
1973 else if (surf.GetType() == GeomAbs_Cone)
1974 aTypeName = "Conical Face";
1976 aTypeName = "GEOM::FACE";
1984 BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1985 if (curv.GetType() == GeomAbs_Line) {
1986 if ((Abs(curv.FirstParameter()) >= 1E6) ||
1987 (Abs(curv.LastParameter()) >= 1E6))
1991 } else if (curv.GetType() == GeomAbs_Circle) {
1992 if (curv.IsClosed())
1993 aTypeName = "Circle";
2002 aTypeName = "Vertex";
2005 aTypeName = "Shape";
2008 aTypeName = "Shape of unknown type";
2014 //=============================================================================
2016 * IsSubShapeBelongsTo
2018 //=============================================================================
2019 Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject,
2020 const Standard_Integer theSubObjectIndex,
2021 Handle(GEOM_Object) theObject,
2022 const Standard_Integer theObjectIndex)
2026 if ( theObject.IsNull() || theSubObject.IsNull() )
2029 TopoDS_Shape shape = theObject->GetValue();
2030 TopoDS_Shape subShape = theSubObject->GetValue();
2032 if ( shape.IsNull() || subShape.IsNull() )
2035 TopTools_IndexedMapOfShape anIndices;
2036 if ( theObjectIndex > 0 ) {
2037 TopExp::MapShapes( shape, anIndices );
2038 shape = anIndices.FindKey(theObjectIndex);
2040 if ( theSubObjectIndex > 0 ) {
2041 TopExp::MapShapes( subShape, anIndices );
2042 subShape = anIndices.FindKey(theSubObjectIndex);
2045 TopExp::MapShapes( shape, anIndices );
2047 const Standard_Boolean isBelongTo = anIndices.Contains(subShape);
2054 //=============================================================================
2058 //=============================================================================
2059 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
2060 (Handle(GEOM_Object) theShape,
2061 const Standard_Integer theShapeType)
2064 Standard_Integer nbShapes = 0;
2066 if (theShape.IsNull()) return -1;
2067 TopoDS_Shape aShape = theShape->GetValue();
2068 if (aShape.IsNull()) return -1;
2071 TopTools_MapOfShape mapShape;
2073 if (aShape.ShapeType() == TopAbs_COMPOUND &&
2074 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2075 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
2076 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
2077 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
2078 for (; It.More(); It.Next()) {
2079 if (mapShape.Add(It.Value())) {
2080 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2081 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
2087 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
2088 for (; exp.More(); exp.Next())
2089 if (mapShape.Add(exp.Current()))
2095 if (theShapeType == TopAbs_FLAT) {
2096 TopTools_MapOfShape aMapOfShape;
2097 TopTools_ListOfShape aListOfShape;
2098 AddFlatSubShapes(aShape, aListOfShape, aMapOfShape);
2099 nbShapes = aListOfShape.Extent();
2103 int iType, nbTypes [TopAbs_SHAPE];
2104 for (iType = 0; iType < TopAbs_SHAPE; ++iType)
2106 nbTypes[aShape.ShapeType()]++;
2108 TopTools_MapOfShape aMapOfShape;
2109 aMapOfShape.Add(aShape);
2110 TopTools_ListOfShape aListOfShape;
2111 aListOfShape.Append(aShape);
2113 TopTools_ListIteratorOfListOfShape itL (aListOfShape);
2114 for (; itL.More(); itL.Next()) {
2115 TopoDS_Iterator it (itL.Value());
2116 for (; it.More(); it.Next()) {
2117 TopoDS_Shape s = it.Value();
2118 if (aMapOfShape.Add(s)) {
2119 aListOfShape.Append(s);
2120 nbTypes[s.ShapeType()]++;
2125 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
2126 nbShapes = aMapOfShape.Extent();
2128 nbShapes = nbTypes[theShapeType];
2131 catch (Standard_Failure& aFail) {
2132 SetErrorCode(aFail.GetMessageString());
2140 //=============================================================================
2144 //=============================================================================
2145 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
2149 if (theShape.IsNull()) return NULL;
2152 //Add a new reversed object
2153 Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
2155 //Add a new Revese function
2156 Handle(GEOM_Function) aFunction;
2157 aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
2158 if (aFunction.IsNull()) return NULL;
2160 //Check if the function is set correctly
2161 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
2163 GEOMImpl_IShapes aSI (aFunction);
2165 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2166 if (aRefShape.IsNull()) return NULL;
2168 aSI.SetBase(aRefShape);
2170 //Compute the sub-shape value
2173 if (!GetSolver()->ComputeFunction(aFunction)) {
2174 SetErrorCode("Shape driver failed to reverse shape");
2178 catch (Standard_Failure& aFail) {
2179 SetErrorCode(aFail.GetMessageString());
2183 //Make a Python command
2184 GEOM::TPythonDump(aFunction) << aReversed
2185 << " = geompy.ChangeOrientation(" << theShape << ")";
2190 Handle(GEOM_Object) aReversed;
2192 GEOM_Engine* anEngine = GetEngine();
2193 //GEOMImpl_Gen* aGen = dynamic_cast<GEOMImpl_Gen*>(anEngine);
2194 GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine;
2197 GEOMImpl_IHealingOperations* anIHealingOperations =
2198 aGen->GetIHealingOperations(GetDocID());
2199 aReversed = anIHealingOperations->ChangeOrientationCopy(theShape);
2200 SetErrorCode(anIHealingOperations->GetErrorCode());
2206 //=============================================================================
2210 //=============================================================================
2211 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
2212 (Handle(GEOM_Object) theShape)
2216 if (theShape.IsNull()) return NULL;
2217 TopoDS_Shape aShape = theShape->GetValue();
2218 if (aShape.IsNull()) return NULL;
2220 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
2222 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2223 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2224 (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2226 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2229 SetErrorCode("The given shape has no faces");
2233 TopTools_IndexedMapOfShape anIndices;
2234 TopExp::MapShapes(aShape, anIndices);
2236 Standard_Integer id;
2237 for (; ind <= nbFaces; ind++) {
2238 if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
2239 id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
2244 //The explode doesn't change object so no new function is required.
2245 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
2247 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2248 #ifdef DUMP_SUBSHAPE_IDS
2249 //Make a Python command
2250 GEOM::TPythonDump(aFunction, /*append=*/true)
2251 << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
2252 #endif // DUMP_SUBSHAPE_IDS
2258 //=======================================================================
2259 //function : GetSharedShapes
2261 //=======================================================================
2262 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2263 (Handle(GEOM_Object) theShape1,
2264 Handle(GEOM_Object) theShape2,
2265 const Standard_Integer theShapeType)
2269 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
2271 TopoDS_Shape aShape1 = theShape1->GetValue();
2272 TopoDS_Shape aShape2 = theShape2->GetValue();
2274 if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
2276 TopTools_IndexedMapOfShape anIndices;
2277 TopExp::MapShapes(aShape1, anIndices);
2278 Handle(TColStd_HArray1OfInteger) anArray;
2280 TopTools_IndexedMapOfShape mapShape1;
2281 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
2283 Handle(GEOM_Object) anObj;
2284 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2285 TCollection_AsciiString anAsciiList, anEntry;
2287 TopTools_MapOfShape mapShape2;
2288 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2289 for (; exp.More(); exp.Next()) {
2290 TopoDS_Shape aSS = exp.Current();
2291 if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
2292 anArray = new TColStd_HArray1OfInteger(1,1);
2293 anArray->SetValue(1, anIndices.FindIndex(aSS));
2294 anObj = GetEngine()->AddSubShape(theShape1, anArray);
2295 aSeq->Append(anObj);
2297 // for python command
2298 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2299 anAsciiList += anEntry;
2304 if (aSeq->IsEmpty()) {
2305 SetErrorCode(NOT_FOUND_ANY);
2309 //Make a Python command
2310 anAsciiList.Trunc(anAsciiList.Length() - 1);
2312 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2314 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2315 << "] = geompy.GetSharedShapes(" << theShape1 << ", "
2316 << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
2322 //=======================================================================
2323 //function : GetSharedShapes
2326 // NOTE on the implementation
2328 // 1) Resulting sub-shapes are published as a children of the 1st input shape
2329 // from theShapes list. Due to this reason only direct sub-shapes of the 1st
2330 // shape can be contained in the result of the operation (i.e. shares between
2331 // 2nd/3rd, etc couples cannot be retrieved.
2332 // 2) An exception from above case is when a single compound is specified as an
2333 // input. In this case we search shares between its top-level content, so we
2334 // are able to search shares between all possible couples of shapes.
2335 // 3) Parameter theMultiShare controls what types of shares to search:
2336 // - True: get sub-shapes that are shared between ALL input shapes;
2337 // - False: get shares between couples of input sub-shapes (see points 1 and 2).
2339 // Thus, we have the following cases:
2340 // [1] theShapes = N shapes (N>1), theMultiShare = True
2341 // Result: sub-shapes that are shared by all theShapes
2342 // [2] theShapes = N shapes (N>1), theMultiShare = False
2343 // Result: sub-shapes of 1st shape from theShapes that are shared with any shape
2345 // [3] theShapes = 1 shape, theMultiShare = True
2346 // Result: sub-shapes that are shared by all top-level sub-objects of theShapes[0]
2347 // [4] theShapes = 1 shape, theMultiShare = False
2348 // Result: sub-shapes of all possible couples of all top-level sub-objects of
2350 //=======================================================================
2351 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2352 (std::list<Handle(GEOM_Object)> & theShapes,
2353 const Standard_Integer theShapeType,
2354 const bool theMultiShare)
2358 int aLen = theShapes.size();
2359 if (aLen < 1) return NULL;
2361 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
2363 // main object is always first in the input list
2364 // it is the object from which sub-shapes indices are taken
2365 // and where results are published
2366 Handle(GEOM_Object) aMainObj = *it;
2367 Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
2369 // collect all shapes from the input list (including first one) for processing
2370 TopTools_SequenceOfShape shapeSeq;
2371 for (; it != theShapes.end(); it++) {
2372 Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
2373 if (aRefShape.IsNull()) {
2374 SetErrorCode("NULL shape for GetSharedShapes");
2377 TopoDS_Shape aShape = aRefShape->GetValue();
2378 if (aShape.IsNull()) {
2379 SetErrorCode("NULL shape for GetSharedShapes");
2382 shapeSeq.Append( aShape );
2385 // if only single shape is specified as input
2386 // collect all ites top-level sub-shapes for processing
2387 if ( shapeSeq.Length() == 1 )
2389 TopoDS_Shape aShape = shapeSeq.First();
2391 for ( TopoDS_Iterator it( aShape ); it.More(); it.Next() )
2392 shapeSeq.Append( it.Value() );
2395 // map all sub-shapes in a main shape to their indices
2396 TopTools_IndexedMapOfShape anIndices;
2397 TopExp::MapShapes(aMainShape->GetValue(), anIndices);
2398 TopTools_MapOfShape mapShape;
2400 // find shared shapes
2402 // here we will collect all shares
2403 TopTools_ListOfShape aShared;
2405 // number of iterations
2406 int nbIters = theMultiShare || theShapes.size() > 1 ? 1 : shapeSeq.Length()-1;
2407 // numShares factor to search (i.e. by what nb of shapes each found sub-shape should be shared)
2408 int nbShares = theMultiShare ? shapeSeq.Length()-1 : 1;
2410 for ( int iter = 1; iter <= nbIters; iter++) {
2411 for ( int ind = iter+1; ind <= shapeSeq.Length(); ind++) {
2412 if ( ind-1+nbShares > shapeSeq.Length() ) break;
2413 TopoDS_Compound aCurrSelection;
2414 TopoDS_Shape aShape1 = shapeSeq.Value( iter );
2415 TopTools_IndexedMapOfShape mapSelected;
2416 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
2417 for ( int s = 0; s < nbShares; s++ ) {
2419 TopoDS_Compound aCompound;
2420 B.MakeCompound(aCompound);
2421 const TopoDS_Shape& aShape2 = shapeSeq.Value( ind+s );
2422 TopTools_MapOfShape mapShape2;
2423 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2424 for (; exp.More(); exp.Next()) {
2425 const TopoDS_Shape& aSS = exp.Current();
2426 if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
2427 B.Add(aCompound, aSS);
2430 mapSelected.Clear();
2431 aCurrSelection = aCompound;
2432 TopExp::MapShapes(aCurrSelection, TopAbs_ShapeEnum(theShapeType), mapSelected);
2434 TopoDS_Iterator itSel(aCurrSelection, Standard_True, Standard_True);
2435 for (; itSel.More(); itSel.Next()) {
2436 const TopoDS_Shape& aSS = itSel.Value();
2437 if (mapShape.Add(aSS) )
2438 aShared.Append(aSS);
2443 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2445 if (aShared.IsEmpty()){
2446 SetErrorCode(NOT_FOUND_ANY);
2450 // create GEOM_Object for each found shared shape (collected in aShared)
2451 TCollection_AsciiString anAsciiList;
2452 Handle(GEOM_Object) anObj;
2453 TopTools_ListIteratorOfListOfShape itSub (aShared);
2454 for (; itSub.More(); itSub.Next()) {
2455 TopoDS_Shape aValue = itSub.Value();
2456 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2457 anArray->SetValue(1, anIndices.FindIndex(aValue));
2458 anObj = GetEngine()->AddSubShape(aMainObj, anArray);
2459 aSeq->Append(anObj);
2461 // for python command
2462 TCollection_AsciiString anEntry;
2463 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2464 anAsciiList += anEntry;
2468 // make a Python command
2469 anAsciiList.Trunc(anAsciiList.Length() - 1);
2471 GEOM::TPythonDump pd (anObj->GetLastFunction());
2472 pd << "[" << anAsciiList.ToCString()
2473 << "] = geompy.GetSharedShapesMulti(";
2478 it = theShapes.begin();
2480 while (it != theShapes.end()) {
2481 pd << ", " << (*it++);
2486 pd << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theMultiShare << ")";
2492 //=============================================================================
2496 //=============================================================================
2497 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump,
2498 const GEOMAlgo_State theState)
2501 case GEOMAlgo_ST_IN:
2502 theDump << "GEOM.ST_IN";
2504 case GEOMAlgo_ST_OUT:
2505 theDump << "GEOM.ST_OUT";
2507 case GEOMAlgo_ST_ON:
2508 theDump << "GEOM.ST_ON";
2510 case GEOMAlgo_ST_ONIN:
2511 theDump << "GEOM.ST_ONIN";
2513 case GEOMAlgo_ST_ONOUT:
2514 theDump << "GEOM.ST_ONOUT";
2517 theDump << "GEOM.ST_UNKNOWN";
2523 //=======================================================================
2524 //function : checkTypeShapesOn
2526 * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
2527 * \param theShapeType - the shape type to check
2528 * \retval bool - result of the check
2530 //=======================================================================
2531 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
2533 if (theShapeType != TopAbs_VERTEX &&
2534 theShapeType != TopAbs_EDGE &&
2535 theShapeType != TopAbs_FACE &&
2536 theShapeType != TopAbs_SOLID) {
2537 SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
2543 //=======================================================================
2544 //function : makePlane
2546 * \brief Creates Geom_Plane
2547 * \param theAx1 - shape object defining plane parameters
2548 * \retval Handle(Geom_Surface) - resulting surface
2550 //=======================================================================
2551 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
2553 if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
2554 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2555 TopoDS_Vertex V1, V2;
2556 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2557 if (V1.IsNull() || V2.IsNull()) {
2558 SetErrorCode("Bad edge given for the plane normal vector");
2561 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2562 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2563 if (aVec.Magnitude() < Precision::Confusion()) {
2564 SetErrorCode("Vector with null magnitude given");
2567 return new Geom_Plane(aLoc, aVec);
2570 //=======================================================================
2571 //function : makeCylinder
2573 * \brief Creates Geom_CylindricalSurface
2574 * \param theAx1 - edge defining cylinder axis
2575 * \param theRadius - cylinder radius
2576 * \retval Handle(Geom_Surface) - resulting surface
2578 //=======================================================================
2579 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
2580 const Standard_Real theRadius)
2582 //Axis of the cylinder
2583 if (anAxis.ShapeType() != TopAbs_EDGE) {
2584 SetErrorCode("Not an edge given for the axis");
2587 TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
2588 TopoDS_Vertex V1, V2;
2589 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2590 if (V1.IsNull() || V2.IsNull()) {
2591 SetErrorCode("Bad edge given for the axis");
2594 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2595 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2596 if (aVec.Magnitude() < Precision::Confusion()) {
2597 SetErrorCode("Vector with null magnitude given");
2601 gp_Ax3 anAx3 (aLoc, aVec);
2602 return new Geom_CylindricalSurface(anAx3, theRadius);
2605 //=======================================================================
2606 //function : getShapesOnBoxIDs
2608 * \brief Find IDs of sub-shapes complying with given status about surface
2609 * \param theBox - the box to check state of sub-shapes against
2610 * \param theShape - the shape to explore
2611 * \param theShapeType - type of sub-shape of theShape
2612 * \param theState - required state
2613 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2615 //=======================================================================
2616 Handle(TColStd_HSequenceOfInteger)
2617 GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2618 const Handle(GEOM_Object)& theShape,
2619 const Standard_Integer theShapeType,
2620 GEOMAlgo_State theState)
2622 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2624 TopoDS_Shape aBox = theBox->GetValue();
2625 TopoDS_Shape aShape = theShape->GetValue();
2627 // Check presence of triangulation, build if need
2628 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2629 SetErrorCode("Cannot build triangulation on the shape");
2634 GEOMAlgo_FinderShapeOn2 aFinder;
2635 Standard_Real aTol = 0.0001; // default value
2637 Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
2638 aClsfBox->SetBox(aBox);
2640 aFinder.SetShape(aShape);
2641 aFinder.SetTolerance(aTol);
2642 aFinder.SetClsf(aClsfBox);
2643 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2644 aFinder.SetState(theState);
2647 // Interprete results
2648 Standard_Integer iErr = aFinder.ErrorStatus();
2649 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2651 MESSAGE(" iErr : " << iErr);
2652 TCollection_AsciiString aMsg (" iErr : ");
2653 aMsg += TCollection_AsciiString(iErr);
2657 Standard_Integer iWrn = aFinder.WarningStatus();
2658 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2660 MESSAGE(" *** iWrn : " << iWrn);
2663 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2665 if (listSS.Extent() < 1) {
2666 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2667 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2671 // Fill sequence of object IDs
2672 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2674 TopTools_IndexedMapOfShape anIndices;
2675 TopExp::MapShapes(aShape, anIndices);
2677 TopTools_ListIteratorOfListOfShape itSub (listSS);
2678 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2679 int id = anIndices.FindIndex(itSub.Value());
2680 aSeqOfIDs->Append(id);
2686 //=======================================================================
2687 //function : GetShapesOnBoxIDs
2689 * \brief Find sub-shapes complying with given status about surface
2690 * \param theBox - the box to check state of sub-shapes against
2691 * \param theShape - the shape to explore
2692 * \param theShapeType - type of sub-shape of theShape
2693 * \param theState - required state
2694 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2696 //=======================================================================
2697 Handle(TColStd_HSequenceOfInteger)
2698 GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2699 const Handle(GEOM_Object)& theShape,
2700 const Standard_Integer theShapeType,
2701 GEOMAlgo_State theState)
2703 // Find sub-shapes ids
2704 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2705 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2706 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2709 // The GetShapesOnBox() doesn't change object so no new function is required.
2710 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
2712 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2713 #ifdef DUMP_SUBSHAPE_IDS
2714 // Make a Python command
2715 GEOM::TPythonDump(aFunction, /*append=*/true)
2716 << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
2719 << TopAbs_ShapeEnum(theShapeType) << ", "
2721 #endif // DUMP_SUBSHAPE_IDS
2727 //=======================================================================
2728 //function : GetShapesOnBox
2730 * \brief Find sub-shapes complying with given status about surface
2731 * \param theBox - the box to check state of sub-shapes against
2732 * \param theShape - the shape to explore
2733 * \param theShapeType - type of sub-shape of theShape
2734 * \param theState - required state
2735 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2737 //=======================================================================
2738 Handle(TColStd_HSequenceOfTransient)
2739 GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
2740 const Handle(GEOM_Object)& theShape,
2741 const Standard_Integer theShapeType,
2742 GEOMAlgo_State theState)
2744 // Find sub-shapes ids
2745 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2746 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2747 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2750 // Find objects by indices
2751 TCollection_AsciiString anAsciiList;
2752 Handle(TColStd_HSequenceOfTransient) aSeq;
2753 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2754 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2757 // Make a Python command
2759 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2760 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2762 GEOM::TPythonDump(aFunction)
2763 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
2766 << TopAbs_ShapeEnum(theShapeType) << ", "
2773 //=======================================================================
2774 //function : getShapesOnShapeIDs
2776 * \brief Find IDs of sub-shapes complying with given status about surface
2777 * \param theCheckShape - the shape to check state of sub-shapes against
2778 * \param theShape - the shape to explore
2779 * \param theShapeType - type of sub-shape of theShape
2780 * \param theState - required state
2781 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2783 //=======================================================================
2784 Handle(TColStd_HSequenceOfInteger)
2785 GEOMImpl_IShapesOperations::getShapesOnShapeIDs
2786 (const Handle(GEOM_Object)& theCheckShape,
2787 const Handle(GEOM_Object)& theShape,
2788 const Standard_Integer theShapeType,
2789 GEOMAlgo_State theState)
2791 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2793 TopoDS_Shape aCheckShape = theCheckShape->GetValue();
2794 TopoDS_Shape aShape = theShape->GetValue();
2795 TopTools_ListOfShape res;
2797 // Check presence of triangulation, build if need
2798 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2799 SetErrorCode("Cannot build triangulation on the shape");
2803 // Compute classification tolerance.
2804 TopTools_IndexedMapOfShape aMapVtx;
2805 Standard_Real aTol = Precision::Confusion();
2807 TopExp::MapShapes(aShape, TopAbs_VERTEX, aMapVtx);
2810 Standard_Integer aNbVtx = aMapVtx.Extent();
2812 for (i = 1; i <= aNbVtx; ++i) {
2813 const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(i));
2814 const Standard_Real aVtxTol = BRep_Tool::Tolerance(aVtx);
2816 if (aTol < aVtxTol) {
2821 // Bound the tolerance value.
2822 if (aTol > 0.0001) {
2827 GEOMAlgo_FinderShapeOn2 aFinder;
2829 Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
2830 aClsfSolid->SetShape(aCheckShape);
2832 aFinder.SetShape(aShape);
2833 aFinder.SetTolerance(aTol);
2834 aFinder.SetClsf(aClsfSolid);
2835 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2836 aFinder.SetState(theState);
2839 // Interprete results
2840 Standard_Integer iErr = aFinder.ErrorStatus();
2841 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2844 SetErrorCode("theCheckShape must be a solid");
2847 MESSAGE(" iErr : " << iErr);
2848 TCollection_AsciiString aMsg (" iErr : ");
2849 aMsg += TCollection_AsciiString(iErr);
2854 Standard_Integer iWrn = aFinder.WarningStatus();
2855 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2857 MESSAGE(" *** iWrn : " << iWrn);
2860 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2862 if (listSS.Extent() < 1) {
2863 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2864 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2867 // Fill sequence of object IDs
2868 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2870 TopTools_IndexedMapOfShape anIndices;
2871 TopExp::MapShapes(aShape, anIndices);
2873 TopTools_ListIteratorOfListOfShape itSub (listSS);
2874 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2875 int id = anIndices.FindIndex(itSub.Value());
2876 aSeqOfIDs->Append(id);
2882 //=======================================================================
2883 //function : GetShapesOnShapeIDs
2885 * \brief Find sub-shapes complying with given status about surface
2886 * \param theCheckShape - the shape to check state of sub-shapes against
2887 * \param theShape - the shape to explore
2888 * \param theShapeType - type of sub-shape of theShape
2889 * \param theState - required state
2890 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2892 //=======================================================================
2893 Handle(TColStd_HSequenceOfInteger)
2894 GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
2895 (const Handle(GEOM_Object)& theCheckShape,
2896 const Handle(GEOM_Object)& theShape,
2897 const Standard_Integer theShapeType,
2898 GEOMAlgo_State theState)
2900 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2901 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2903 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2906 // The GetShapesOnShape() doesn't change object so no new function is required.
2907 Handle(GEOM_Function) aFunction =
2908 GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
2910 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2911 #ifdef DUMP_SUBSHAPE_IDS
2912 // Make a Python command
2913 GEOM::TPythonDump(aFunction, /*append=*/true)
2914 << "listShapesOnShapeIDs = geompy.GetShapesOnShapeIDs("
2915 << theCheckShape << ", "
2917 << TopAbs_ShapeEnum(theShapeType) << ", "
2919 #endif // DUMP_SUBSHAPE_IDS
2925 //=======================================================================
2926 //function : GetShapesOnShape
2928 * \brief Find sub-shapes complying with given status about surface
2929 * \param theCheckShape - the shape to check state of sub-shapes against
2930 * \param theShape - the shape to explore
2931 * \param theShapeType - type of sub-shape of theShape
2932 * \param theState - required state
2933 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2935 //=======================================================================
2936 Handle(TColStd_HSequenceOfTransient)
2937 GEOMImpl_IShapesOperations::GetShapesOnShape
2938 (const Handle(GEOM_Object)& theCheckShape,
2939 const Handle(GEOM_Object)& theShape,
2940 const Standard_Integer theShapeType,
2941 GEOMAlgo_State theState)
2943 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2944 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2945 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2948 // Find objects by indices
2949 TCollection_AsciiString anAsciiList;
2950 Handle(TColStd_HSequenceOfTransient) aSeq;
2951 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2953 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2956 // Make a Python command
2958 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2959 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2961 GEOM::TPythonDump(aFunction)
2962 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
2963 << theCheckShape << ", "
2965 << TopAbs_ShapeEnum(theShapeType) << ", "
2972 //=======================================================================
2973 //function : GetShapesOnShapeAsCompound
2974 //=======================================================================
2975 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
2976 (const Handle(GEOM_Object)& theCheckShape,
2977 const Handle(GEOM_Object)& theShape,
2978 const Standard_Integer theShapeType,
2979 GEOMAlgo_State theState)
2981 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2982 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2984 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2987 // Find objects by indices
2988 TCollection_AsciiString anAsciiList;
2989 Handle(TColStd_HSequenceOfTransient) aSeq;
2990 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2992 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2995 TopoDS_Compound aCompound;
2997 B.MakeCompound(aCompound);
2999 for(; i<=aSeq->Length(); i++) {
3000 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
3001 TopoDS_Shape aShape_i = anObj->GetValue();
3002 B.Add(aCompound,aShape_i);
3005 //Add a new result object
3006 Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
3007 Handle(GEOM_Function) aFunction =
3008 aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
3009 aFunction->SetValue(aCompound);
3012 aSeq->Append( theCheckShape->GetLastFunction() );
3013 aSeq->Append( theShape->GetLastFunction() );
3015 GEOMImpl_IShapes aCI( aFunction );
3016 aCI.SetShapes( aSeq );
3017 aCI.SetSubShapeType( theShapeType );
3018 aCI.SetTolerance( theState );
3020 GEOM::TPythonDump(aFunction)
3021 << aRes << " = geompy.GetShapesOnShapeAsCompound("
3022 << theCheckShape << ", "
3024 << TopAbs_ShapeEnum(theShapeType) << ", "
3032 //=============================================================================
3034 * GetSubShapeEdgeSorted
3036 //=============================================================================
3037 Handle(TColStd_HSequenceOfTransient)
3038 GEOMImpl_IShapesOperations::GetSubShapeEdgeSorted
3039 (const Handle(GEOM_Object) &theShape,
3040 const Handle(GEOM_Object) &theStartPoint)
3042 // Get the sorted edges indices.
3043 Handle(TColStd_HSequenceOfInteger) aSortedIDs =
3044 getSubShapeEdgeSortedIDs(theShape, theStartPoint);
3046 // Get object by indices.
3047 TCollection_AsciiString anAsciiList;
3048 Handle(TColStd_HSequenceOfTransient) aSeq =
3049 getObjectsShapesOn(theShape, aSortedIDs, anAsciiList);
3051 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3052 SetErrorCode("Empty sequence of edges");
3056 // Make a Python command
3057 Handle(GEOM_Object) anObj =
3058 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3059 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3061 GEOM::TPythonDump(aFunction)
3062 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapeEdgeSorted("
3063 << theShape << ", " << theStartPoint << ")";
3070 //=============================================================================
3072 * GetSubShapesWithTolerance
3074 //=============================================================================
3075 Handle(TColStd_HSequenceOfTransient)
3076 GEOMImpl_IShapesOperations::GetSubShapesWithTolerance
3077 (const Handle(GEOM_Object) &theShape,
3078 const Standard_Integer theShapeType,
3079 const GEOMUtils::ComparisonCondition theCondition,
3080 const Standard_Real theTolerance)
3082 if (theShape.IsNull()) {
3083 SetErrorCode("NULL GEOM object");
3087 TopoDS_Shape aShape = theShape->GetValue();
3089 if (aShape.IsNull()) {
3090 SetErrorCode("NULL Shape");
3094 if (theShapeType != TopAbs_FACE && theShapeType != TopAbs_EDGE &&
3095 theShapeType != TopAbs_VERTEX && aShape.ShapeType() >= theShapeType) {
3096 SetErrorCode("Invalid shape type");
3100 TopTools_IndexedMapOfShape anIndices;
3101 TopTools_MapOfShape aMapFence;
3102 TopExp_Explorer anExp(aShape,
3103 (TopAbs_ShapeEnum) theShapeType);
3104 Handle(TColStd_HSequenceOfInteger) anIDs = new TColStd_HSequenceOfInteger;
3106 TopExp::MapShapes(aShape, anIndices);
3108 for (; anExp.More(); anExp.Next()) {
3109 const TopoDS_Shape &aSubShape = anExp.Current();
3111 if (aMapFence.Add(aSubShape)) {
3112 // Compute tolerance
3113 Standard_Real aTolerance = -1.;
3115 switch (aSubShape.ShapeType()) {
3117 aTolerance = BRep_Tool::Tolerance(TopoDS::Face(aSubShape));
3120 aTolerance = BRep_Tool::Tolerance(TopoDS::Edge(aSubShape));
3123 aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aSubShape));
3129 if (aTolerance < 0.) {
3133 // Compare the tolerance with reference value.
3134 if (GEOMUtils::IsFitCondition (theCondition, aTolerance, theTolerance)) {
3135 anIDs->Append(anIndices.FindIndex(aSubShape));
3140 if (anIDs->IsEmpty()) {
3141 SetErrorCode("Empty sequence of sub-shapes");
3145 // Get objects by indices.
3146 TCollection_AsciiString anAsciiList;
3147 Handle(TColStd_HSequenceOfTransient) aSeq =
3148 getObjectsShapesOn(theShape, anIDs, anAsciiList);
3150 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3151 SetErrorCode("Empty sequence of edges");
3155 // Make a Python command
3156 Handle(GEOM_Object) anObj =
3157 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3158 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3160 GEOM::TPythonDump(aFunction)
3161 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapesWithTolerance("
3162 << theShape << ", " << theShapeType << ", " << theCondition << ", "
3163 << theTolerance << ")";
3170 //=============================================================================
3174 //=============================================================================
3175 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeExtraction
3176 (const Handle(GEOM_Object) &theShape,
3177 const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs,
3178 std::list<ExtractionStat> &theStats)
3182 if (theShape.IsNull()) {
3186 //Add a new Result object
3187 Handle(GEOM_Object) aResult =
3188 GetEngine()->AddObject(GetDocID(), GEOM_EXTRACTION);
3190 //Add a new Extraction function
3191 Handle(GEOM_Function) aFunction =
3192 aResult->AddFunction(GEOMImpl_ShapeDriver::GetID(), EXTRACTION);
3194 //Check if the function is set correctly
3195 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
3199 Handle(GEOM_Function) aShape = theShape->GetLastFunction();
3201 if (aShape.IsNull()) {
3205 GEOMImpl_IExtract aCI (aFunction);
3207 aCI.SetShape(aShape);
3208 aCI.SetSubShapeIDs(theSubShapeIDs);
3210 //Compute the Edge value
3213 if (!GetSolver()->ComputeFunction(aFunction)) {
3214 SetErrorCode("Shape driver failed");
3219 catch (Standard_Failure& aFail) {
3220 SetErrorCode(aFail.GetMessageString());
3225 // Fill in statistics.
3228 Handle(TColStd_HArray1OfInteger) aStatIDsArray[3] =
3229 { aCI.GetRemovedIDs(), aCI.GetModifiedIDs(), aCI.GetAddedIDs() };
3233 for (j = 0; j < 3; ++j) {
3234 if (!aStatIDsArray[j].IsNull()) {
3235 const int anUpperID = aStatIDsArray[j]->Upper();
3236 ExtractionStat aStat;
3238 for (i = aStatIDsArray[j]->Lower(); i <= anUpperID; ++i) {
3239 aStat.indices.push_back(aStatIDsArray[j]->Value(i));
3242 aStat.type = (ExtractionStatType) j;
3243 theStats.push_back(aStat);
3247 //Make a Python command
3248 GEOM::TPythonDump pd(aFunction);
3250 pd << aResult << " = geompy.MakeExtraction(" << theShape << ", [";
3252 if (!theSubShapeIDs.IsNull()) {
3253 const int aNbIDs = theSubShapeIDs->Upper();
3255 for (i = theSubShapeIDs->Lower(); i < aNbIDs; ++i) {
3256 pd << theSubShapeIDs->Value(i) << ", ";
3259 // Dump the last value without a comma.
3260 pd << theSubShapeIDs->Value(i);
3270 //=======================================================================
3271 //function : getShapesOnSurfaceIDs
3273 * \brief Find IDs of sub-shapes complying with given status about surface
3274 * \param theSurface - the surface to check state of sub-shapes against
3275 * \param theShape - the shape to explore
3276 * \param theShapeType - type of sub-shape of theShape
3277 * \param theState - required state
3278 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3280 //=======================================================================
3281 Handle(TColStd_HSequenceOfInteger)
3282 GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
3283 const TopoDS_Shape& theShape,
3284 TopAbs_ShapeEnum theShapeType,
3285 GEOMAlgo_State theState)
3287 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3289 // Check presence of triangulation, build if need
3290 if (theShapeType != TopAbs_VERTEX &&
3291 !GEOMUtils::CheckTriangulation(theShape)) {
3292 SetErrorCode("Cannot build triangulation on the shape");
3296 // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
3297 // Compute tolerance
3298 Standard_Real T, VertMax = -RealLast();
3301 for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
3302 TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
3303 T = BRep_Tool::Tolerance(Vertex);
3308 catch (Standard_Failure& aFail) {
3309 SetErrorCode(aFail.GetMessageString());
3312 // END: Mantis issue 0020961
3315 GEOMAlgo_FinderShapeOn2 aFinder;
3316 Handle(GEOMAlgo_ClsfSurf) aClsfSurf = new GEOMAlgo_ClsfSurf;
3317 Standard_Real aTol = VertMax; // Mantis issue 0020961
3319 aClsfSurf->SetSurface(theSurface);
3320 aFinder.SetShape(theShape);
3321 aFinder.SetTolerance(aTol);
3322 aFinder.SetClsf(aClsfSurf);
3323 aFinder.SetShapeType(theShapeType);
3324 aFinder.SetState(theState);
3326 // Sets the minimal number of inner points for the faces that do not have own
3327 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
3329 aFinder.SetNbPntsMin(3);
3330 // Sets the maximal number of inner points for edges or faces.
3331 // It is useful for the cases when this number is very big (e.g =2000) to improve
3332 // the performance. If this value =0, all inner points will be taken into account.
3334 aFinder.SetNbPntsMax(100);
3338 // Interprete results
3339 Standard_Integer iErr = aFinder.ErrorStatus();
3340 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
3342 MESSAGE(" iErr : " << iErr);
3343 TCollection_AsciiString aMsg (" iErr : ");
3344 aMsg += TCollection_AsciiString(iErr);
3348 Standard_Integer iWrn = aFinder.WarningStatus();
3349 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
3351 MESSAGE(" *** iWrn : " << iWrn);
3354 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
3356 if (listSS.Extent() < 1) {
3357 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
3358 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
3362 // Fill sequence of object IDs
3363 aSeqOfIDs = new TColStd_HSequenceOfInteger;
3365 TopTools_IndexedMapOfShape anIndices;
3366 TopExp::MapShapes(theShape, anIndices);
3368 TopTools_ListIteratorOfListOfShape itSub (listSS);
3369 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3370 int id = anIndices.FindIndex(itSub.Value());
3371 aSeqOfIDs->Append(id);
3377 //=======================================================================
3378 //function : getObjectsShapesOn
3380 * \brief Find shape objects and their entries by their ids
3381 * \param theShapeIDs - incoming shape ids
3382 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3383 * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
3385 //=======================================================================
3386 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
3387 getObjectsShapesOn(const Handle(GEOM_Object)& theShape,
3388 const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
3389 TCollection_AsciiString & theShapeEntries)
3391 Handle(TColStd_HSequenceOfTransient) aSeq;
3393 if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
3395 aSeq = new TColStd_HSequenceOfTransient;
3396 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3397 TCollection_AsciiString anEntry;
3398 for ( int i = 1; i <= theShapeIDs->Length(); ++i )
3400 anArray->SetValue(1, theShapeIDs->Value( i ));
3401 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3402 aSeq->Append( anObj );
3404 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3405 if ( i != 1 ) theShapeEntries += ",";
3406 theShapeEntries += anEntry;
3412 //=============================================================================
3414 * getSubShapeEdgeSortedIDs
3416 //=============================================================================
3417 Handle(TColStd_HSequenceOfInteger)
3418 GEOMImpl_IShapesOperations::getSubShapeEdgeSortedIDs
3419 (const Handle(GEOM_Object) &theShape,
3420 const Handle(GEOM_Object) &theStartPoint)
3422 Handle(TColStd_HSequenceOfInteger) aResult;
3424 if (theShape.IsNull() || theStartPoint.IsNull()) {
3425 SetErrorCode("NULL GEOM object");
3429 const TopoDS_Shape aShape = theShape->GetValue();
3430 const TopoDS_Shape aStartPoint = theStartPoint->GetValue();
3432 if (aShape.IsNull() || aStartPoint.IsNull()) {
3433 SetErrorCode("NULL Shape");
3437 if (aStartPoint.ShapeType() != TopAbs_VERTEX) {
3438 SetErrorCode("Starting point is not a vertex");
3442 TopExp_Explorer anExp(aShape, TopAbs_EDGE);
3443 TopTools_MapOfShape aMapFence;
3444 TopTools_ListOfShape anEdges;
3446 for (; anExp.More(); anExp.Next()) {
3447 const TopoDS_Shape &anEdge = anExp.Current();
3449 if (aMapFence.Add(anEdge)) {
3450 anEdges.Append(anEdge);
3454 if (anEdges.IsEmpty()) {
3455 SetErrorCode("Shape doesn't contain edges");
3459 // Step 1: Sort edges
3460 GEOMUtils::SortShapes(anEdges, Standard_False);
3462 TopTools_ListIteratorOfListOfShape anIter(anEdges);
3463 TopoDS_Vertex aV[2];
3464 TopTools_DataMapOfShapeListOfShape aMapVE;
3466 // Step 2: Fill the map vertex - list of edges.
3467 for (; anIter.More(); anIter.Next()) {
3468 TopoDS_Edge anEdge = TopoDS::Edge(anIter.Value());
3470 TopExp::Vertices(anEdge, aV[0], aV[1]);
3472 const Standard_Integer aNbV = aV[0].IsSame(aV[1]) ? 1 : 2;
3475 for (i = 0; i < aNbV; ++i) {
3476 if (aV[i].IsNull() == Standard_False) {
3477 if (!aMapVE.IsBound(aV[i])) {
3478 // There is no this vertex in the map.
3479 aMapVE.Bind(aV[i], TopTools_ListOfShape());
3482 // Add the edge to the list bound with the vertex aV[i].
3483 TopTools_ListOfShape &aLEdges = aMapVE.ChangeFind(aV[i]);
3485 aLEdges.Append(anEdge);
3490 // Step 3: Find starting point in aMapVE.
3491 TopoDS_Vertex aStartVtx = TopoDS::Vertex(aStartPoint);
3493 if (!aMapVE.IsBound(aStartVtx)) {
3494 aStartVtx = getSameVertex(aShape, aStartVtx);
3496 if (aStartVtx.IsNull()) {
3497 SetErrorCode("Invalid Starting point");
3502 TopTools_IndexedMapOfShape anIndices;
3503 TopTools_MapOfShape aMapVFence;
3504 TopoDS_Shape aCurVtx = aStartVtx;
3505 TopoDS_Edge aCurEdge =
3506 TopoDS::Edge(aMapVE.Find(aCurVtx).First());
3508 aResult = new TColStd_HSequenceOfInteger;
3509 TopExp::MapShapes(aShape, anIndices);
3511 // Step 4: Fill the list of sorted edges.
3512 while (aMapVFence.Add(aCurVtx)) {
3513 // Append the ID of the current edge to the list of sorted.
3514 aResult->Append(anIndices.FindIndex(aCurEdge));
3515 TopExp::Vertices(aCurEdge, aV[0], aV[1]);
3517 // Get the next vertex.
3518 if (aCurVtx.IsSame(aV[0])) {
3519 if (aCurVtx.IsSame(aV[1])) {
3520 // There is no next vertex.
3529 if (aCurVtx.IsNull()) {
3530 // There is no next vertex.
3534 // Get the next edge.
3535 const TopTools_ListOfShape &aLEdges = aMapVE.Find(aCurVtx);
3536 TopTools_ListIteratorOfListOfShape anEIter(aLEdges);
3538 for (; anEIter.More(); anEIter.Next()) {
3539 const TopoDS_Shape &aLocalEdge = anEIter.Value();
3541 if (aLocalEdge.IsNull() == Standard_False) {
3542 if (!aCurEdge.IsSame(aLocalEdge)) {
3543 aCurEdge = TopoDS::Edge(aLocalEdge);
3549 if (!anEIter.More()) {
3550 // There is no next edge.
3558 //=======================================================================
3559 //function : getShapesOnSurface
3561 * \brief Find sub-shapes complying with given status about surface
3562 * \param theSurface - the surface to check state of sub-shapes against
3563 * \param theShape - the shape to explore
3564 * \param theShapeType - type of sub-shape of theShape
3565 * \param theState - required state
3566 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3567 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3569 //=======================================================================
3570 Handle(TColStd_HSequenceOfTransient)
3571 GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
3572 const Handle(GEOM_Object)& theShape,
3573 TopAbs_ShapeEnum theShapeType,
3574 GEOMAlgo_State theState,
3575 TCollection_AsciiString & theShapeEntries)
3577 // Find sub-shapes ids
3578 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3579 getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
3580 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3583 return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
3586 //=============================================================================
3590 //=============================================================================
3591 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
3592 (const Handle(GEOM_Object)& theShape,
3593 const Standard_Integer theShapeType,
3594 const Handle(GEOM_Object)& theAx1,
3595 const GEOMAlgo_State theState)
3599 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3601 TopoDS_Shape aShape = theShape->GetValue();
3602 TopoDS_Shape anAx1 = theAx1->GetValue();
3604 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3606 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3607 if ( !checkTypeShapesOn( theShapeType ))
3611 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3612 if ( aPlane.IsNull() )
3616 TCollection_AsciiString anAsciiList;
3617 Handle(TColStd_HSequenceOfTransient) aSeq;
3618 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3619 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3622 // Make a Python command
3624 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3625 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3627 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3628 << "] = geompy.GetShapesOnPlane(" << theShape << ", "
3629 << aShapeType << ", " << theAx1 << ", " << theState << ")";
3635 //=============================================================================
3637 * GetShapesOnPlaneWithLocation
3639 //=============================================================================
3640 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
3641 (const Handle(GEOM_Object)& theShape,
3642 const Standard_Integer theShapeType,
3643 const Handle(GEOM_Object)& theAx1,
3644 const Handle(GEOM_Object)& thePnt,
3645 const GEOMAlgo_State theState)
3649 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3651 TopoDS_Shape aShape = theShape->GetValue();
3652 TopoDS_Shape anAx1 = theAx1->GetValue();
3653 TopoDS_Shape anPnt = thePnt->GetValue();
3655 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3657 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3658 if ( !checkTypeShapesOn( theShapeType ))
3662 if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
3663 TopoDS_Vertex V1, V2, V3;
3664 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3665 TopExp::Vertices(anEdge, V1, V2, Standard_True);
3667 if (V1.IsNull() || V2.IsNull()) {
3668 SetErrorCode("Bad edge given for the plane normal vector");
3671 V3 = TopoDS::Vertex(anPnt);
3674 SetErrorCode("Bad vertex given for the plane location");
3677 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3678 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3680 if (aVec.Magnitude() < Precision::Confusion()) {
3681 SetErrorCode("Vector with null magnitude given");
3684 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3686 if ( aPlane.IsNull() )
3690 TCollection_AsciiString anAsciiList;
3691 Handle(TColStd_HSequenceOfTransient) aSeq;
3692 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3693 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3696 // Make a Python command
3698 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3699 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3701 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3702 << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
3703 << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
3709 //=============================================================================
3711 * GetShapesOnCylinder
3713 //=============================================================================
3714 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
3715 (const Handle(GEOM_Object)& theShape,
3716 const Standard_Integer theShapeType,
3717 const Handle(GEOM_Object)& theAxis,
3718 const Standard_Real theRadius,
3719 const GEOMAlgo_State theState)
3723 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3725 TopoDS_Shape aShape = theShape->GetValue();
3726 TopoDS_Shape anAxis = theAxis->GetValue();
3728 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3730 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3731 if ( !checkTypeShapesOn( aShapeType ))
3734 // Create a cylinder surface
3735 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3736 if ( aCylinder.IsNull() )
3740 TCollection_AsciiString anAsciiList;
3741 Handle(TColStd_HSequenceOfTransient) aSeq;
3742 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3743 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3746 // Make a Python command
3748 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3749 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3751 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3752 << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
3753 << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
3759 //=============================================================================
3761 * GetShapesOnCylinderWithLocation
3763 //=============================================================================
3764 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
3765 (const Handle(GEOM_Object)& theShape,
3766 const Standard_Integer theShapeType,
3767 const Handle(GEOM_Object)& theAxis,
3768 const Handle(GEOM_Object)& thePnt,
3769 const Standard_Real theRadius,
3770 const GEOMAlgo_State theState)
3774 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3776 TopoDS_Shape aShape = theShape->GetValue();
3777 TopoDS_Shape anAxis = theAxis->GetValue();
3778 TopoDS_Shape aPnt = thePnt->GetValue();
3780 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3782 if (aPnt.ShapeType() != TopAbs_VERTEX )
3784 SetErrorCode("Bottom location point must be vertex");
3788 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3789 if ( !checkTypeShapesOn( aShapeType ))
3792 // Create a cylinder surface
3793 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3794 if ( aCylinder.IsNull() )
3797 // translate the surface
3798 Handle(Geom_CylindricalSurface) aCylSurface =
3799 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3800 if ( aCylSurface.IsNull() )
3802 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3805 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3806 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3807 aCylinder->Translate( fromLoc, toLoc );
3810 TCollection_AsciiString anAsciiList;
3811 Handle(TColStd_HSequenceOfTransient) aSeq;
3812 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3813 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3816 // Make a Python command
3818 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3819 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3821 GEOM::TPythonDump(aFunction)
3822 << "[" << anAsciiList.ToCString()
3823 << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
3824 << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
3830 //=============================================================================
3834 //=============================================================================
3835 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
3836 (const Handle(GEOM_Object)& theShape,
3837 const Standard_Integer theShapeType,
3838 const Handle(GEOM_Object)& theCenter,
3839 const Standard_Real theRadius,
3840 const GEOMAlgo_State theState)
3844 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3846 TopoDS_Shape aShape = theShape->GetValue();
3847 TopoDS_Shape aCenter = theCenter->GetValue();
3849 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3851 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3852 if ( !checkTypeShapesOn( aShapeType ))
3855 // Center of the sphere
3856 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3857 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3859 gp_Ax3 anAx3 (aLoc, gp::DZ());
3860 Handle(Geom_SphericalSurface) aSphere =
3861 new Geom_SphericalSurface(anAx3, theRadius);
3864 TCollection_AsciiString anAsciiList;
3865 Handle(TColStd_HSequenceOfTransient) aSeq;
3866 aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
3867 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3870 // Make a Python command
3872 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3873 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3875 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3876 << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
3877 << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
3883 //=============================================================================
3885 * GetShapesOnPlaneIDs
3887 //=============================================================================
3888 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
3889 (const Handle(GEOM_Object)& theShape,
3890 const Standard_Integer theShapeType,
3891 const Handle(GEOM_Object)& theAx1,
3892 const GEOMAlgo_State theState)
3896 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3898 TopoDS_Shape aShape = theShape->GetValue();
3899 TopoDS_Shape anAx1 = theAx1->GetValue();
3901 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3903 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3904 if ( !checkTypeShapesOn( aShapeType ))
3908 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3909 if ( aPlane.IsNull() )
3913 Handle(TColStd_HSequenceOfInteger) aSeq;
3914 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3916 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3917 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3919 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
3920 #ifdef DUMP_SUBSHAPE_IDS
3921 // Make a Python command
3922 GEOM::TPythonDump(aFunction, /*append=*/true)
3923 << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
3924 << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
3925 #endif // DUMP_SUBSHAPE_IDS
3931 //=============================================================================
3933 * GetShapesOnPlaneWithLocationIDs
3935 //=============================================================================
3936 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
3937 (const Handle(GEOM_Object)& theShape,
3938 const Standard_Integer theShapeType,
3939 const Handle(GEOM_Object)& theAx1,
3940 const Handle(GEOM_Object)& thePnt,
3941 const GEOMAlgo_State theState)
3945 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3947 TopoDS_Shape aShape = theShape->GetValue();
3948 TopoDS_Shape anAx1 = theAx1->GetValue();
3949 TopoDS_Shape anPnt = thePnt->GetValue();
3951 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3953 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3954 if ( !checkTypeShapesOn( aShapeType ))
3958 if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
3959 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3960 TopoDS_Vertex V1, V2, V3;
3961 TopExp::Vertices(anEdge, V1, V2, Standard_True);
3962 if (V1.IsNull() || V2.IsNull()) {
3963 SetErrorCode("Bad edge given for the plane normal vector");
3966 V3 = TopoDS::Vertex(anPnt);
3968 SetErrorCode("Bad vertex given for the plane location");
3971 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3972 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3973 if (aVec.Magnitude() < Precision::Confusion()) {
3974 SetErrorCode("Vector with null magnitude given");
3978 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3979 if ( aPlane.IsNull() )
3983 Handle(TColStd_HSequenceOfInteger) aSeq;
3984 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3986 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3987 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3989 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
3990 #ifdef DUMP_SUBSHAPE_IDS
3991 // Make a Python command
3992 GEOM::TPythonDump(aFunction, /*append=*/true)
3993 << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
3994 << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")";
3995 #endif // DUMP_SUBSHAPE_IDS
4001 //=============================================================================
4003 * GetShapesOnCylinderIDs
4005 //=============================================================================
4006 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
4007 (const Handle(GEOM_Object)& theShape,
4008 const Standard_Integer theShapeType,
4009 const Handle(GEOM_Object)& theAxis,
4010 const Standard_Real theRadius,
4011 const GEOMAlgo_State theState)
4015 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
4017 TopoDS_Shape aShape = theShape->GetValue();
4018 TopoDS_Shape anAxis = theAxis->GetValue();
4020 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
4022 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4023 if ( !checkTypeShapesOn( aShapeType ))
4026 // Create a cylinder surface
4027 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4028 if ( aCylinder.IsNull() )
4032 Handle(TColStd_HSequenceOfInteger) aSeq;
4033 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4035 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4036 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
4038 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4039 #ifdef DUMP_SUBSHAPE_IDS
4040 // Make a Python command
4041 GEOM::TPythonDump(aFunction, /*append=*/true)
4042 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
4043 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4044 << theRadius << ", " << theState << ")";
4045 #endif // DUMP_SUBSHAPE_IDS
4051 //=============================================================================
4053 * GetShapesOnCylinderWithLocationIDs
4055 //=============================================================================
4056 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
4057 (const Handle(GEOM_Object)& theShape,
4058 const Standard_Integer theShapeType,
4059 const Handle(GEOM_Object)& theAxis,
4060 const Handle(GEOM_Object)& thePnt,
4061 const Standard_Real theRadius,
4062 const GEOMAlgo_State theState)
4066 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
4068 TopoDS_Shape aShape = theShape->GetValue();
4069 TopoDS_Shape anAxis = theAxis->GetValue();
4070 TopoDS_Shape aPnt = thePnt->GetValue();
4072 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
4074 if (aPnt.ShapeType() != TopAbs_VERTEX )
4076 SetErrorCode("Bottom location point must be vertex");
4080 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4081 if ( !checkTypeShapesOn( aShapeType ))
4084 // Create a cylinder surface
4085 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4086 if ( aCylinder.IsNull() )
4089 // translate the surface
4090 Handle(Geom_CylindricalSurface) aCylSurface =
4091 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
4092 if ( aCylSurface.IsNull() )
4094 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
4097 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
4098 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
4099 aCylinder->Translate( fromLoc, toLoc );
4102 Handle(TColStd_HSequenceOfInteger) aSeq;
4103 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4105 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4106 Handle(GEOM_Function) aFunction =
4107 GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
4109 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4110 #ifdef DUMP_SUBSHAPE_IDS
4111 // Make a Python command
4112 GEOM::TPythonDump(aFunction, /*append=*/true)
4113 << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
4114 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4115 << thePnt << ", " << theRadius << ", " << theState << ")";
4116 #endif // DUMP_SUBSHAPE_IDS
4122 //=============================================================================
4124 * GetShapesOnSphereIDs
4126 //=============================================================================
4127 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
4128 (const Handle(GEOM_Object)& theShape,
4129 const Standard_Integer theShapeType,
4130 const Handle(GEOM_Object)& theCenter,
4131 const Standard_Real theRadius,
4132 const GEOMAlgo_State theState)
4136 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
4138 TopoDS_Shape aShape = theShape->GetValue();
4139 TopoDS_Shape aCenter = theCenter->GetValue();
4141 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
4143 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4144 if ( !checkTypeShapesOn( aShapeType ))
4147 // Center of the sphere
4148 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
4149 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
4151 gp_Ax3 anAx3 (aLoc, gp::DZ());
4152 Handle(Geom_SphericalSurface) aSphere =
4153 new Geom_SphericalSurface(anAx3, theRadius);
4156 Handle(TColStd_HSequenceOfInteger) aSeq;
4157 aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
4159 // The GetShapesOnSphere() doesn't change object so no new function is required.
4160 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
4162 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4163 #ifdef DUMP_SUBSHAPE_IDS
4164 // Make a Python command
4165 GEOM::TPythonDump(aFunction, /*append=*/true)
4166 << "listShapesOnSphere = geompy.GetShapesOnSphereIDs"
4167 << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
4168 << theRadius << ", " << theState << ")";
4169 #endif // DUMP_SUBSHAPE_IDS
4175 //=======================================================================
4176 //function : getShapesOnQuadrangleIDs
4178 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4179 * \param theShape - the shape to explore
4180 * \param theShapeType - type of sub-shape of theShape
4181 * \param theTopLeftPoint - top left quadrangle corner
4182 * \param theTopRightPoint - top right quadrangle corner
4183 * \param theBottomLeftPoint - bottom left quadrangle corner
4184 * \param theBottomRightPoint - bottom right quadrangle corner
4185 * \param theState - required state
4186 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4188 //=======================================================================
4189 Handle(TColStd_HSequenceOfInteger)
4190 GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4191 const Standard_Integer theShapeType,
4192 const Handle(GEOM_Object)& theTopLeftPoint,
4193 const Handle(GEOM_Object)& theTopRightPoint,
4194 const Handle(GEOM_Object)& theBottomLeftPoint,
4195 const Handle(GEOM_Object)& theBottomRightPoint,
4196 const GEOMAlgo_State theState)
4200 if ( theShape.IsNull() ||
4201 theTopLeftPoint.IsNull() ||
4202 theTopRightPoint.IsNull() ||
4203 theBottomLeftPoint.IsNull() ||
4204 theBottomRightPoint.IsNull() )
4207 TopoDS_Shape aShape = theShape->GetValue();
4208 TopoDS_Shape aTL = theTopLeftPoint->GetValue();
4209 TopoDS_Shape aTR = theTopRightPoint->GetValue();
4210 TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
4211 TopoDS_Shape aBR = theBottomRightPoint->GetValue();
4213 if (aShape.IsNull() ||
4218 aTL.ShapeType() != TopAbs_VERTEX ||
4219 aTR.ShapeType() != TopAbs_VERTEX ||
4220 aBL.ShapeType() != TopAbs_VERTEX ||
4221 aBR.ShapeType() != TopAbs_VERTEX )
4224 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4225 if ( !checkTypeShapesOn( aShapeType ))
4228 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
4230 // Check presence of triangulation, build if need
4231 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
4232 SetErrorCode("Cannot build triangulation on the shape");
4237 gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
4238 gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
4239 gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
4240 gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
4242 GEOMAlgo_FinderShapeOn2 aFinder;
4243 Handle(GEOMAlgo_ClsfQuad) aClsfQuad = new GEOMAlgo_ClsfQuad;
4245 Standard_Real aTol = 0.0001; // default value
4247 aClsfQuad->SetCorners(aPntTL, aPntTR, aPntBL, aPntBR);
4248 aFinder.SetShape(aShape);
4249 aFinder.SetTolerance(aTol);
4250 aFinder.SetClsf(aClsfQuad);
4251 aFinder.SetShapeType(aShapeType);
4252 aFinder.SetState(theState);
4254 // Sets the minimal number of inner points for the faces that do not have own
4255 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
4257 aFinder.SetNbPntsMin(3);
4258 // Sets the maximal number of inner points for edges or faces.
4259 // It is useful for the cases when this number is very big (e.g =2000) to improve
4260 // the performance. If this value =0, all inner points will be taken into account.
4262 aFinder.SetNbPntsMax(100);
4266 // Interprete results
4267 Standard_Integer iErr = aFinder.ErrorStatus();
4268 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
4270 MESSAGE(" iErr : " << iErr);
4271 TCollection_AsciiString aMsg (" iErr : ");
4272 aMsg += TCollection_AsciiString(iErr);
4276 Standard_Integer iWrn = aFinder.WarningStatus();
4277 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
4279 MESSAGE(" *** iWrn : " << iWrn);
4282 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
4284 if (listSS.Extent() < 1) {
4285 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
4286 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
4290 // Fill sequence of object IDs
4291 aSeqOfIDs = new TColStd_HSequenceOfInteger;
4293 TopTools_IndexedMapOfShape anIndices;
4294 TopExp::MapShapes(aShape, anIndices);
4296 TopTools_ListIteratorOfListOfShape itSub (listSS);
4297 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
4298 int id = anIndices.FindIndex(itSub.Value());
4299 aSeqOfIDs->Append(id);
4304 //=======================================================================
4305 //function : GetShapesOnQuadrangle
4307 * \brief Find sub-shapes complying with given status about quadrangle
4308 * \param theShape - the shape to explore
4309 * \param theShapeType - type of sub-shape of theShape
4310 * \param theTopLeftPoint - top left quadrangle corner
4311 * \param theTopRightPoint - top right quadrangle corner
4312 * \param theBottomLeftPoint - bottom left quadrangle corner
4313 * \param theBottomRightPoint - bottom right quadrangle corner
4314 * \param theState - required state
4315 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4317 //=======================================================================
4318 Handle(TColStd_HSequenceOfTransient)
4319 GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
4320 const Standard_Integer theShapeType,
4321 const Handle(GEOM_Object)& theTopLeftPoint,
4322 const Handle(GEOM_Object)& theTopRightPoint,
4323 const Handle(GEOM_Object)& theBottomLeftPoint,
4324 const Handle(GEOM_Object)& theBottomRightPoint,
4325 const GEOMAlgo_State theState)
4328 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4329 getShapesOnQuadrangleIDs( theShape,
4334 theBottomRightPoint,
4336 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4339 // Find objects by indices
4340 TCollection_AsciiString anAsciiList;
4341 Handle(TColStd_HSequenceOfTransient) aSeq;
4342 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
4343 if ( aSeq.IsNull() || aSeq->IsEmpty() )
4346 // Make a Python command
4348 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
4349 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
4351 GEOM::TPythonDump(aFunction)
4352 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
4354 << TopAbs_ShapeEnum(theShapeType) << ", "
4355 << theTopLeftPoint << ", "
4356 << theTopRightPoint << ", "
4357 << theBottomLeftPoint << ", "
4358 << theBottomRightPoint << ", "
4365 //=======================================================================
4366 //function : GetShapesOnQuadrangleIDs
4368 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4369 * \param theShape - the shape to explore
4370 * \param theShapeType - type of sub-shape of theShape
4371 * \param theTopLeftPoint - top left quadrangle corner
4372 * \param theTopRightPoint - top right quadrangle corner
4373 * \param theBottomLeftPoint - bottom left quadrangle corner
4374 * \param theBottomRightPoint - bottom right quadrangle corner
4375 * \param theState - required state
4376 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4378 //=======================================================================
4379 Handle(TColStd_HSequenceOfInteger)
4380 GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4381 const Standard_Integer theShapeType,
4382 const Handle(GEOM_Object)& theTopLeftPoint,
4383 const Handle(GEOM_Object)& theTopRightPoint,
4384 const Handle(GEOM_Object)& theBottomLeftPoint,
4385 const Handle(GEOM_Object)& theBottomRightPoint,
4386 const GEOMAlgo_State theState)
4389 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4390 getShapesOnQuadrangleIDs( theShape,
4395 theBottomRightPoint,
4397 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4400 // Make a Python command
4402 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4403 Handle(GEOM_BaseObject) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
4404 lastObj = GEOM::GetCreatedLast(lastObj,theTopRightPoint);
4405 lastObj = GEOM::GetCreatedLast(lastObj,theBottomRightPoint);
4406 lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
4407 Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
4409 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4410 #ifdef DUMP_SUBSHAPE_IDS
4411 GEOM::TPythonDump(aFunction, /*append=*/true)
4412 << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
4414 << TopAbs_ShapeEnum(theShapeType) << ", "
4415 << theTopLeftPoint << ", "
4416 << theTopRightPoint << ", "
4417 << theBottomLeftPoint << ", "
4418 << theBottomRightPoint << ", "
4420 #endif // DUMP_SUBSHAPE_IDS
4426 //=============================================================================
4431 //=============================================================================
4432 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
4433 Handle(GEOM_Object) theShapeWhat)
4437 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4439 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4440 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4442 if (aWhere.IsNull() || aWhat.IsNull()) {
4443 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4447 // Searching for the sub-shapes inside the ShapeWhere shape
4448 GEOMAlgo_GetInPlace aGIP;
4450 if (!GEOMAlgo_GetInPlaceAPI::GetInPlace(aWhere, aWhat, aGIP)) {
4451 SetErrorCode("Error in GEOMAlgo_GetInPlace");
4455 // Add direct result.
4456 TopTools_ListOfShape aLSA;
4457 const TopoDS_Shape &aShapeResult = aGIP.Result();
4458 TopTools_MapOfShape aMFence;
4459 TopTools_IndexedMapOfShape aWhereIndices;
4460 Standard_Integer aShapeType = -1;
4462 TopExp::MapShapes(aWhere, aWhereIndices);
4464 if (aShapeResult.IsNull() == Standard_False) {
4465 TopoDS_Iterator anIt(aShapeResult);
4467 for (; anIt.More(); anIt.Next()) {
4468 const TopoDS_Shape &aPart = anIt.Value();
4470 if(aWhereIndices.Contains(aPart) && aMFence.Add(aPart)) {
4471 const TopAbs_ShapeEnum aType = aPart.ShapeType();
4473 if (aShapeType == -1) {
4476 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4478 aShapeType = TopAbs_SHAPE;
4486 if (aLSA.Extent() == 0) {
4487 SetErrorCode(NOT_FOUND_ANY); // Not found any Results
4491 Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent());
4492 TopTools_ListIteratorOfListOfShape anIterModif (aLSA);
4493 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4494 aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value()));
4498 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4499 if (aResult.IsNull()) {
4500 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4504 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4506 if ((aModifiedArray->Length() > 1 && isSameType) ||
4507 theShapeWhat->GetType() == GEOM_GROUP) {
4509 aResult->SetType(GEOM_GROUP);
4511 //Set a sub-shape type
4512 TopoDS_Shape aFirstFound = aLSA.First();
4513 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4515 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4516 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4519 //Make a Python command
4520 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4522 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4523 << theShapeWhere << ", " << theShapeWhat << ", True)";
4529 //=============================================================================
4531 * case GetInPlaceOld:
4534 //=============================================================================
4535 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld
4536 (Handle(GEOM_Object) theShapeWhere,
4537 Handle(GEOM_Object) theShapeWhat)
4541 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4543 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4544 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4545 TopTools_ListOfShape aModifiedList;
4546 const Standard_Integer iErr =
4547 GEOMAlgo_GetInPlaceAPI::GetInPlaceOld(aWhere, aWhat, aModifiedList);
4552 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4556 ("Error: An attempt to extract a shape of not supported type.");
4559 SetErrorCode(NOT_FOUND_ANY);
4562 SetErrorCode("Shape driver failed");
4569 TopTools_IndexedMapOfShape aWhereIndices;
4570 TopExp::MapShapes(aWhere, aWhereIndices);
4572 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4573 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4574 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4575 Standard_Integer imod;
4576 Standard_Integer aShapeType = -1;
4578 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4579 const Standard_Integer anIndex =
4580 aWhereIndices.FindIndex(anIterModif.Value());
4581 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4583 if (aShapeType == -1) {
4586 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4588 aShapeType = TopAbs_SHAPE;
4591 aModifiedArray->SetValue(imod, anIndex);
4595 Handle(GEOM_Object) aResult =
4596 GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4598 if (aResult.IsNull()) {
4599 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4603 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4605 if ((aModifiedArray->Length() > 1 && isSameType) ||
4606 theShapeWhat->GetType() == GEOM_GROUP) {
4608 aResult->SetType(GEOM_GROUP);
4610 //Set a sub-shape type
4611 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4612 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4614 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4615 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4618 //Make a Python command
4619 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4621 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4622 << theShapeWhere << ", " << theShapeWhat << ", False)";
4629 //=======================================================================
4630 //function : GetInPlaceByHistory
4632 //=======================================================================
4633 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
4634 (Handle(GEOM_Object) theShapeWhere,
4635 Handle(GEOM_Object) theShapeWhat)
4639 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4641 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4642 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4644 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4646 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4647 if (aWhereFunction.IsNull()) return NULL;
4649 //Fill array of indices
4650 TopTools_IndexedMapOfShape aWhereIndices;
4652 TopExp::MapShapes(aWhere, aWhereIndices);
4655 TopTools_ListOfShape aModifiedList;
4656 bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceByHistory
4657 (aWhereFunction, aWhereIndices, aWhat, aModifiedList);
4659 if (!isFound || aModifiedList.Extent() < 1) {
4660 SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
4664 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4665 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4666 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4667 Standard_Integer imod;
4668 Standard_Integer aShapeType = -1;
4670 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4671 const Standard_Integer anIndex =
4672 aWhereIndices.FindIndex(anIterModif.Value());
4673 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4675 if (aShapeType == -1) {
4678 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4680 aShapeType = TopAbs_SHAPE;
4683 aModifiedArray->SetValue(imod, anIndex);
4687 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4688 if (aResult.IsNull()) {
4689 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4693 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4695 if ((aModifiedArray->Length() > 1 && isSameType) ||
4696 theShapeWhat->GetType() == GEOM_GROUP) {
4698 aResult->SetType(GEOM_GROUP);
4700 //Set a sub-shape type
4701 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4702 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4704 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4705 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4708 //Make a Python command
4709 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4711 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
4712 << theShapeWhere << ", " << theShapeWhat << ")";
4718 //=======================================================================
4719 //function : isSameEdge
4720 //purpose : Returns True if two edges coincide
4721 //=======================================================================
4722 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4724 TopoDS_Vertex V11, V12, V21, V22;
4725 TopExp::Vertices(theEdge1, V11, V12);
4726 TopExp::Vertices(theEdge2, V21, V22);
4727 gp_Pnt P11 = BRep_Tool::Pnt(V11);
4728 gp_Pnt P12 = BRep_Tool::Pnt(V12);
4729 gp_Pnt P21 = BRep_Tool::Pnt(V21);
4730 gp_Pnt P22 = BRep_Tool::Pnt(V22);
4731 bool coincide = false;
4733 //Check that ends of edges coincide
4734 if(P11.Distance(P21) <= MAX_TOLERANCE) {
4735 if(P12.Distance(P22) <= MAX_TOLERANCE) coincide = true;
4737 else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4738 if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4741 if(!coincide) return false;
4743 if (BRep_Tool::Degenerated(theEdge1))
4744 if (BRep_Tool::Degenerated(theEdge2)) return true;
4747 if (BRep_Tool::Degenerated(theEdge2)) return false;
4749 double U11, U12, U21, U22;
4750 Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4751 Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4753 //Check that both edges has the same geometry
4754 double range = U12-U11;
4755 double U = U11+ range/3.0;
4756 gp_Pnt P1 = C1->Value(U); //Compute a point on one third of the edge's length
4757 U = U11+range*2.0/3.0;
4758 gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length
4760 C2 = new Geom_TrimmedCurve(C2, U21, U22);
4762 if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22)
4765 if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4767 if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4770 if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4775 //=======================================================================
4776 //function : isSameFace
4777 //purpose : Returns True if two faces coincide
4778 //=======================================================================
4779 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4781 TopExp_Explorer E(theFace1, TopAbs_EDGE);
4782 TopTools_ListOfShape LS1, LS2;
4783 for(; E.More(); E.Next()) LS1.Append(E.Current());
4785 E.Init(theFace2, TopAbs_EDGE);
4786 for(; E.More(); E.Next()) LS2.Append(E.Current());
4788 //Compare the number of edges in the faces
4789 if(LS1.Extent() != LS2.Extent()) return false;
4791 double aMin = RealFirst(), aMax = RealLast();
4792 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4793 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4795 for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4796 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4797 if(P.X() < xminB1) xminB1 = P.X();
4798 if(P.Y() < yminB1) yminB1 = P.Y();
4799 if(P.Z() < zminB1) zminB1 = P.Z();
4800 if(P.X() > xmaxB1) xmaxB1 = P.X();
4801 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4802 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4805 for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4806 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4807 if(P.X() < xminB2) xminB2 = P.X();
4808 if(P.Y() < yminB2) yminB2 = P.Y();
4809 if(P.Z() < zminB2) zminB2 = P.Z();
4810 if(P.X() > xmaxB2) xmaxB2 = P.X();
4811 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4812 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4815 //Compare the bounding boxes of both faces
4816 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4819 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4822 Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4823 Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4825 //Check if there a coincidence of two surfaces at least in two points
4826 double U11, U12, V11, V12, U21, U22, V21, V22;
4827 BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4828 BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4830 double rangeU = U12-U11;
4831 double rangeV = V12-V11;
4832 double U = U11 + rangeU/3.0;
4833 double V = V11 + rangeV/3.0;
4834 gp_Pnt P1 = S1->Value(U, V);
4835 U = U11+rangeU*2.0/3.0;
4836 V = V11+rangeV*2.0/3.0;
4837 gp_Pnt P2 = S1->Value(U, V);
4839 if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4842 if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4844 if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4847 if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
4849 //Check that each edge of the Face1 has a counterpart in the Face2
4850 TopTools_MapOfOrientedShape aMap;
4851 TopTools_ListIteratorOfListOfShape LSI1(LS1);
4852 for(; LSI1.More(); LSI1.Next()) {
4853 TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
4854 bool isFound = false;
4855 TopTools_ListIteratorOfListOfShape LSI2(LS2);
4856 for(; LSI2.More(); LSI2.Next()) {
4857 TopoDS_Shape aValue = LSI2.Value();
4858 if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
4859 if(isSameEdge(E, TopoDS::Edge(aValue))) {
4865 if(!isFound) return false;
4871 //=======================================================================
4872 //function : isSameSolid
4873 //purpose : Returns True if two solids coincide
4874 //=======================================================================
4875 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
4877 TopExp_Explorer E(theSolid1, TopAbs_FACE);
4878 TopTools_ListOfShape LS1, LS2;
4879 for(; E.More(); E.Next()) LS1.Append(E.Current());
4880 E.Init(theSolid2, TopAbs_FACE);
4881 for(; E.More(); E.Next()) LS2.Append(E.Current());
4883 if(LS1.Extent() != LS2.Extent()) return false;
4885 double aMin = RealFirst(), aMax = RealLast();
4886 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4887 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4889 for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
4890 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4891 if(P.X() < xminB1) xminB1 = P.X();
4892 if(P.Y() < yminB1) yminB1 = P.Y();
4893 if(P.Z() < zminB1) zminB1 = P.Z();
4894 if(P.X() > xmaxB1) xmaxB1 = P.X();
4895 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4896 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4899 for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
4900 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4901 if(P.X() < xminB2) xminB2 = P.X();
4902 if(P.Y() < yminB2) yminB2 = P.Y();
4903 if(P.Z() < zminB2) zminB2 = P.Z();
4904 if(P.X() > xmaxB2) xmaxB2 = P.X();
4905 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4906 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4909 //Compare the bounding boxes of both solids
4910 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4913 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4916 //Check that each face of the Solid1 has a counterpart in the Solid2
4917 TopTools_MapOfOrientedShape aMap;
4918 TopTools_ListIteratorOfListOfShape LSI1(LS1);
4919 for(; LSI1.More(); LSI1.Next()) {
4920 TopoDS_Face F = TopoDS::Face(LSI1.Value());
4921 bool isFound = false;
4922 TopTools_ListIteratorOfListOfShape LSI2(LS2);
4923 for(; LSI2.More(); LSI2.Next()) {
4924 if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
4925 if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
4926 aMap.Add(LSI2.Value());
4931 if(!isFound) return false;
4937 //=======================================================================
4938 //function : GetSame
4940 //=======================================================================
4941 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
4942 const Handle(GEOM_Object)& theShapeWhat)
4945 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4947 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4948 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4950 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4953 bool isFound = false;
4954 TopoDS_Shape aSubShape;
4955 TopTools_MapOfShape aMap;
4957 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4958 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4959 if (It.More()) aWhat = It.Value();
4962 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4967 switch (aWhat.ShapeType()) {
4968 case TopAbs_VERTEX: {
4969 aSubShape = getSameVertex(aWhere, TopoDS::Vertex(aWhat));
4970 isFound = !aSubShape.IsNull();
4974 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4975 TopExp_Explorer E(aWhere, TopAbs_EDGE);
4976 for(; E.More(); E.Next()) {
4977 if(!aMap.Add(E.Current())) continue;
4978 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4979 aSubShape = E.Current();
4987 TopoDS_Face aFace = TopoDS::Face(aWhat);
4988 TopExp_Explorer E(aWhere, TopAbs_FACE);
4989 for(; E.More(); E.Next()) {
4990 if(!aMap.Add(E.Current())) continue;
4991 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
4992 aSubShape = E.Current();
4999 case TopAbs_SOLID: {
5000 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5001 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5002 for(; E.More(); E.Next()) {
5003 if(!aMap.Add(E.Current())) continue;
5004 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5005 aSubShape = E.Current();
5017 TopTools_IndexedMapOfShape anIndices;
5018 TopExp::MapShapes(aWhere, anIndices);
5019 if (anIndices.Contains(aSubShape))
5020 anIndex = anIndices.FindIndex(aSubShape);
5023 if (anIndex < 0) return NULL;
5025 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
5027 anArray->SetValue(1, anIndex);
5029 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
5030 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
5032 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
5033 << theShapeWhere << ", " << theShapeWhat << ")";
5041 //=======================================================================
5042 //function : GetSameIDs
5044 //=======================================================================
5045 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
5046 (const Handle(GEOM_Object)& theShapeWhere,
5047 const Handle(GEOM_Object)& theShapeWhat)
5050 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
5052 TopoDS_Shape aWhere = theShapeWhere->GetValue();
5053 TopoDS_Shape aWhat = theShapeWhat->GetValue();
5055 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
5057 TopTools_ListOfShape listShape;
5058 TopTools_MapOfShape aMap;
5060 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
5061 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
5062 if (It.More()) aWhat = It.Value();
5065 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
5070 switch (aWhat.ShapeType()) {
5071 case TopAbs_VERTEX: {
5072 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
5073 TopExp_Explorer E(aWhere, TopAbs_VERTEX);
5074 for(; E.More(); E.Next()) {
5075 if(!aMap.Add(E.Current())) continue;
5076 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
5077 if(P.Distance(P2) <= MAX_TOLERANCE) {
5078 listShape.Append(E.Current());
5084 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
5085 TopExp_Explorer E(aWhere, TopAbs_EDGE);
5086 for(; E.More(); E.Next()) {
5087 if(!aMap.Add(E.Current())) continue;
5088 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
5089 listShape.Append(E.Current());
5095 TopoDS_Face aFace = TopoDS::Face(aWhat);
5096 TopExp_Explorer E(aWhere, TopAbs_FACE);
5097 for(; E.More(); E.Next()) {
5098 if(!aMap.Add(E.Current())) continue;
5099 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5100 listShape.Append(E.Current());
5105 case TopAbs_SOLID: {
5106 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5107 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5108 for(; E.More(); E.Next()) {
5109 if(!aMap.Add(E.Current())) continue;
5110 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5111 listShape.Append(E.Current());
5120 if ( !listShape.IsEmpty() ) {
5121 TopTools_IndexedMapOfShape anIndices;
5122 TopExp::MapShapes(aWhere, anIndices);
5123 TopTools_ListIteratorOfListOfShape itSub (listShape);
5124 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
5125 for (; itSub.More(); itSub.Next()) {
5126 if (anIndices.Contains(itSub.Value()))
5127 aSeq->Append(anIndices.FindIndex(itSub.Value()));
5130 // The GetSameIDs() doesn't change object so no new function is required.
5131 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
5133 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
5134 #ifdef DUMP_SUBSHAPE_IDS
5135 // Make a Python command
5136 GEOM::TPythonDump(aFunction, /*append=*/true)
5137 << "listSameIDs = geompy.GetSameIDs("
5138 << theShapeWhere << ", "
5139 << theShapeWhat << ")";
5140 #endif // DUMP_SUBSHAPE_IDS
5143 SetErrorCode(NOT_FOUND_ANY);
5148 //=======================================================================
5149 //function : ExtendEdge
5151 //=======================================================================
5152 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendEdge
5153 (const Handle(GEOM_Object) &theEdge,
5154 const Standard_Real theMin,
5155 const Standard_Real theMax)
5159 if (theEdge.IsNull()) {
5163 //Add a new Edge object
5164 Handle(GEOM_Object) aResEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
5166 //Add a new Vector function
5167 Handle(GEOM_Function) aFunction =
5168 aResEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_UV);
5170 //Check if the function is set correctly
5171 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5175 GEOMImpl_IShapeExtend aCI (aFunction);
5177 Handle(GEOM_Function) anEdge = theEdge->GetLastFunction();
5179 if (anEdge.IsNull()) {
5183 aCI.SetShape(anEdge);
5184 aCI.SetUMin(theMin);
5185 aCI.SetUMax(theMax);
5187 //Compute the Edge value
5190 if (!GetSolver()->ComputeFunction(aFunction)) {
5191 SetErrorCode("Shape driver failed");
5196 catch (Standard_Failure& aFail) {
5197 SetErrorCode(aFail.GetMessageString());
5202 //Make a Python command
5203 GEOM::TPythonDump(aFunction)
5204 << aResEdge << " = geompy.ExtendEdge("
5205 << theEdge << ", " << theMin << ", " << theMax << ")";
5212 //=======================================================================
5213 //function : ExtendFace
5215 //=======================================================================
5216 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendFace
5217 (const Handle(GEOM_Object) &theFace,
5218 const Standard_Real theUMin,
5219 const Standard_Real theUMax,
5220 const Standard_Real theVMin,
5221 const Standard_Real theVMax)
5225 if (theFace.IsNull()) {
5229 //Add a new Face object
5230 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
5232 //Add a new Vector function
5233 Handle(GEOM_Function) aFunction =
5234 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_UV);
5236 //Check if the function is set correctly
5237 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5241 GEOMImpl_IShapeExtend aCI (aFunction);
5243 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5245 if (aFace.IsNull()) {
5249 aCI.SetShape(aFace);
5250 aCI.SetUMin(theUMin);
5251 aCI.SetUMax(theUMax);
5252 aCI.SetVMin(theVMin);
5253 aCI.SetVMax(theVMax);
5255 //Compute the Face value
5258 if (!GetSolver()->ComputeFunction(aFunction)) {
5259 SetErrorCode("Shape driver failed");
5264 catch (Standard_Failure& aFail) {
5265 SetErrorCode(aFail.GetMessageString());
5270 //Make a Python command
5271 GEOM::TPythonDump(aFunction)
5272 << aResFace << " = geompy.ExtendFace("
5273 << theFace << ", " << theUMin << ", " << theUMax << ", "
5274 << theVMin << ", " << theVMax << ")";
5281 //=======================================================================
5282 //function : MakeSurfaceFromFace
5284 //=======================================================================
5285 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSurfaceFromFace
5286 (const Handle(GEOM_Object) &theFace)
5290 if (theFace.IsNull()) {
5294 //Add a new Face object
5295 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
5297 //Add a new Vector function
5298 Handle(GEOM_Function) aFunction =
5299 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), SURFACE_FROM_FACE);
5301 //Check if the function is set correctly
5302 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5306 GEOMImpl_IShapeExtend aCI (aFunction);
5308 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5310 if (aFace.IsNull()) {
5314 aCI.SetShape(aFace);
5316 //Compute the Face value
5319 if (!GetSolver()->ComputeFunction(aFunction)) {
5320 SetErrorCode("Shape driver failed");
5325 catch (Standard_Failure& aFail) {
5326 SetErrorCode(aFail.GetMessageString());
5331 //Make a Python command
5332 GEOM::TPythonDump(aFunction)
5333 << aResFace << " = geompy.MakeSurfaceFromFace("