1 // Copyright (C) 2007-2024 CEA, EDF, 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"
38 #include "GEOMImpl_WrappingDriver.hxx"
40 #include "GEOMImpl_IExtract.hxx"
41 #include "GEOMImpl_IVector.hxx"
42 #include "GEOMImpl_IShapes.hxx"
43 #include "GEOMImpl_IShapeExtend.hxx"
44 #include "GEOMImpl_IGlue.hxx"
45 #include "GEOMImpl_IFilling.hxx"
46 #include "GEOMImpl_IWrap.hxx"
48 #include "GEOMImpl_Block6Explorer.hxx"
49 #include "GEOMImpl_IHealingOperations.hxx"
51 #include "GEOMImpl_Gen.hxx"
53 #include "GEOM_Function.hxx"
54 #include "GEOM_ISubShape.hxx"
55 #include "GEOM_PythonDump.hxx"
57 #include "GEOMUtils.hxx"
59 #include "GEOMAlgo_ClsfBox.hxx"
60 #include "GEOMAlgo_ClsfQuad.hxx"
61 #include "GEOMAlgo_ClsfSolid.hxx"
62 #include "GEOMAlgo_ClsfSurf.hxx"
63 #include "GEOMAlgo_FinderShapeOn2.hxx"
64 #include "GEOMAlgo_GetInPlace.hxx"
65 #include "GEOMAlgo_GetInPlaceAPI.hxx"
66 #include "GEOMAlgo_GlueDetector.hxx"
68 #include <utilities.h>
70 #include <BRepAdaptor_Curve.hxx>
71 #include <BRepAdaptor_Surface.hxx>
72 #include <BRepTools.hxx>
73 #include <BRep_Builder.hxx>
74 #include <BRep_Tool.hxx>
75 #include <GeomLib_Tool.hxx>
76 #include <Geom_CylindricalSurface.hxx>
77 #include <Geom_Plane.hxx>
78 #include <Geom_SphericalSurface.hxx>
79 #include <Geom_Surface.hxx>
80 #include <Geom_TrimmedCurve.hxx>
81 #include <Precision.hxx>
82 #include <TDF_Tool.hxx>
83 #include <TDataStd_Integer.hxx>
84 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
86 #include <TopExp_Explorer.hxx>
87 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
88 #include <TopTools_IndexedMapOfShape.hxx>
89 #include <TopTools_ListIteratorOfListOfShape.hxx>
90 #include <TopTools_MapOfOrientedShape.hxx>
91 #include <TopTools_MapOfShape.hxx>
92 #include <TopTools_SequenceOfShape.hxx>
94 #include <TopoDS_TShape.hxx>
95 #include <TopoDS_Compound.hxx>
96 #include <TopoDS_Edge.hxx>
97 #include <TopoDS_Face.hxx>
98 #include <TopoDS_Iterator.hxx>
99 #include <TopoDS_Shape.hxx>
100 #include <TopoDS_Solid.hxx>
101 #include <TopoDS_Vertex.hxx>
102 #include <gp_Cylinder.hxx>
103 #include <gp_Pnt.hxx>
107 #include <Standard_Failure.hxx>
108 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
110 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
111 // Next macro, when defined, causes appearing of SubShapeAllIDs(), SubShapeAllSortedIDs(), GetSameIDs()
112 // and other such commands in Python dump.
113 // See also GEOM_Engine.cxx.
114 // ---------------------------------------
115 // #define DUMP_SUBSHAPE_IDS
116 // ---------------------------------------
120 void AddFlatSubShapes(const TopoDS_Shape& S, TopTools_ListOfShape& L, TopTools_MapOfShape& M)
122 if (S.ShapeType() != TopAbs_COMPOUND) {
126 TopoDS_Iterator It(S, Standard_True, Standard_True);
127 for (; It.More(); It.Next()) {
128 TopoDS_Shape SS = It.Value();
130 AddFlatSubShapes(SS, L, M);
138 const double MAX_TOLERANCE = 1.e-7;
141 * \brief Returns the vertex from theWhere shape that is coincident with
144 * \param theWhere the shape where the coincident vertex is searched.
145 * \param theVertex the vertex to be searched.
146 * \return the coincident vertex if it is found. Otherwise null object.
148 static TopoDS_Vertex getSameVertex(const TopoDS_Shape &theWhere,
149 const TopoDS_Vertex &theVertex)
151 TopoDS_Vertex aResult;
152 gp_Pnt aPoint = BRep_Tool::Pnt(theVertex);
153 TopExp_Explorer anExp(theWhere, TopAbs_VERTEX);
154 TopTools_MapOfShape aMap;
156 for(; anExp.More(); anExp.Next()) {
157 const TopoDS_Shape &aLocalShape = anExp.Current();
159 if(!aMap.Add(aLocalShape)) {
163 TopoDS_Vertex aVertex = TopoDS::Vertex(aLocalShape);
164 gp_Pnt aPoint2 = BRep_Tool::Pnt(aVertex);
166 if(aPoint.Distance(aPoint2) <= MAX_TOLERANCE) {
174 } // end of namespace
176 //=============================================================================
180 //=============================================================================
181 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine)
182 : GEOM_IOperations(theEngine)
184 MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
187 //=============================================================================
191 //=============================================================================
192 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
194 MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
197 //=============================================================================
201 //=============================================================================
202 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
203 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
207 if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
209 //Add a new Edge object
210 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GEOM_EDGE);
212 //Add a new Vector function
213 Handle(GEOM_Function) aFunction =
214 anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
216 //Check if the function is set correctly
217 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
219 GEOMImpl_IVector aPI (aFunction);
221 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
222 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
223 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
225 aPI.SetPoint1(aRef1);
226 aPI.SetPoint2(aRef2);
228 //Compute the Edge value
231 if (!GetSolver()->ComputeFunction(aFunction)) {
232 SetErrorCode("Vector driver failed");
236 catch (Standard_Failure& aFail) {
237 SetErrorCode(aFail.GetMessageString());
241 //Make a Python command
242 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
243 << thePnt1 << ", " << thePnt2 << ")";
249 //=============================================================================
251 * MakeEdgeOnCurveByLength
253 //=============================================================================
254 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeOnCurveByLength
255 (Handle(GEOM_Object) theRefCurve,
256 const Standard_Real theLength,
257 Handle(GEOM_Object) theStartPoint)
261 if (theRefCurve.IsNull()) return NULL;
263 //Add a new Edge object
264 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GEOM_EDGE);
266 //Add a new Vector function
267 Handle(GEOM_Function) aFunction =
268 anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_CURVE_LENGTH);
270 //Check if the function is set correctly
271 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
273 GEOMImpl_IVector aPI (aFunction);
275 Handle(GEOM_Function) aRef1 = theRefCurve->GetLastFunction();
276 if (aRef1.IsNull()) return NULL;
277 aPI.SetPoint1(aRef1);
279 if (!theStartPoint.IsNull()) {
280 Handle(GEOM_Function) aRef2 = theStartPoint->GetLastFunction();
281 aPI.SetPoint2(aRef2);
284 aPI.SetParameter(theLength);
286 //Compute the Edge value
289 if (!GetSolver()->ComputeFunction(aFunction)) {
290 SetErrorCode("Vector driver failed");
294 catch (Standard_Failure& aFail) {
295 SetErrorCode(aFail.GetMessageString());
299 //Make a Python command
300 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeOnCurveByLength("
301 << theRefCurve << ", " << theLength << ", " << theStartPoint << ")";
307 //=============================================================================
311 //=============================================================================
312 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire
313 (Handle(GEOM_Object) theWire,
314 const Standard_Real theLinearTolerance,
315 const Standard_Real theAngularTolerance)
319 if (theWire.IsNull()) return NULL;
321 //Add a new Edge object
322 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GEOM_EDGE);
324 //Add a new Vector function
325 Handle(GEOM_Function) aFunction =
326 anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_WIRE);
328 //Check if the function is set correctly
329 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
331 GEOMImpl_IShapes aCI (aFunction);
333 Handle(GEOM_Function) aWire = theWire->GetLastFunction();
335 if (aWire.IsNull()) return NULL;
338 aCI.SetTolerance(theLinearTolerance);
339 aCI.SetAngularTolerance(theAngularTolerance);
341 //Compute the Edge value
344 if (!GetSolver()->ComputeFunction(aFunction)) {
345 SetErrorCode("Shape driver failed");
349 catch (Standard_Failure& aFail) {
350 SetErrorCode(aFail.GetMessageString());
354 const double DEF_LIN_TOL = Precision::Confusion();
355 const double DEF_ANG_TOL = Precision::Angular();
356 //Make a Python command
357 if ( theAngularTolerance == DEF_ANG_TOL ) {
358 if ( theLinearTolerance == DEF_LIN_TOL )
359 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
362 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
363 << theWire << ", " << theLinearTolerance << ")";
366 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
367 << theWire << ", " << theLinearTolerance << ", "
368 << theAngularTolerance << ")";
375 //=============================================================================
379 //=============================================================================
380 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
381 (std::list<Handle(GEOM_Object)> theShapes,
382 const Standard_Real theTolerance,
383 const GEOMImpl_WireBuildMode theMode)
388 Handle(GEOM_Object) aWire = GetEngine()->AddObject(GEOM_WIRE);
391 Handle(GEOM_Function) aFunction =
392 aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES);
393 if (aFunction.IsNull()) return NULL;
395 //Check if the function is set correctly
396 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
398 GEOMImpl_IShapes aCI (aFunction);
399 aCI.SetTolerance(theTolerance);
400 aCI.SetWireMode(theMode);
402 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
405 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
406 for (; it != theShapes.end(); it++) {
407 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
408 if (aRefSh.IsNull()) {
409 SetErrorCode("NULL argument shape for the shape construction");
412 aShapesSeq->Append(aRefSh);
414 aCI.SetShapes(aShapesSeq);
419 if (!GetSolver()->ComputeFunction(aFunction)) {
420 SetErrorCode("Shape driver failed");
424 catch (Standard_Failure& aFail) {
425 SetErrorCode(aFail.GetMessageString());
429 //Make a Python command
430 GEOM::TPythonDump pd (aFunction);
433 case GEOMImpl_WBM_FixTolerance:
434 pd << " = geompy.MakeWire([";
436 case GEOMImpl_WBM_Approximation:
437 pd << " = geompy.MakeWireWithMode([";
439 case GEOMImpl_WBM_KeepCurveType:
440 pd << " = geompy.MakeWireConstCurveType([";
446 it = theShapes.begin();
447 if (it != theShapes.end()) {
449 while (it != theShapes.end()) {
450 pd << ", " << (*it++);
453 pd << "], " << theTolerance;
454 if (theMode == GEOMImpl_WBM_Approximation) {
455 pd << ", GEOM.WBM_Approximation";
463 //=============================================================================
467 //=============================================================================
468 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
469 const bool isPlanarWanted)
473 if (theWire.IsNull()) return NULL;
475 //Add a new Face object
476 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GEOM_FACE);
478 //Add a new Shape function for creation of a face from a wire
479 Handle(GEOM_Function) aFunction =
480 aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
481 if (aFunction.IsNull()) return NULL;
483 //Check if the function is set correctly
484 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
486 GEOMImpl_IShapes aCI (aFunction);
488 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
490 if (aRefWire.IsNull()) return NULL;
492 aCI.SetBase(aRefWire);
493 aCI.SetIsPlanar(isPlanarWanted);
495 //Compute the Face value
496 Standard_Boolean isWarning = Standard_False;
499 if (!GetSolver()->ComputeFunction(aFunction)) {
500 SetErrorCode("Shape driver failed to compute a face");
504 catch (Standard_Failure& aFail) {
505 SetErrorCode(aFail.GetMessageString());
506 // to provide warning
507 if (!aFunction->GetValue().IsNull()) {
508 isWarning = Standard_True;
514 //Make a Python command
515 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
516 << theWire << ", " << (int)isPlanarWanted << ")";
518 // to provide warning
519 if (!isWarning) SetErrorCode(OK);
523 //=============================================================================
527 //=============================================================================
528 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
529 (std::list<Handle(GEOM_Object)> theShapes,
530 const bool isPlanarWanted)
535 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FACE);
538 Handle(GEOM_Function) aFunction =
539 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
540 if (aFunction.IsNull()) return NULL;
542 //Check if the function is set correctly
543 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
545 GEOMImpl_IShapes aCI (aFunction);
547 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
550 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
551 for (; it != theShapes.end(); it++) {
552 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
553 if (aRefSh.IsNull()) {
554 SetErrorCode("NULL argument shape for the face construction");
557 aShapesSeq->Append(aRefSh);
559 aCI.SetShapes(aShapesSeq);
561 aCI.SetIsPlanar(isPlanarWanted);
564 Standard_Boolean isWarning = Standard_False;
567 if (!GetSolver()->ComputeFunction(aFunction)) {
568 SetErrorCode("Shape driver failed");
572 catch (Standard_Failure& aFail) {
573 SetErrorCode(aFail.GetMessageString());
574 // to provide warning
575 if (!aFunction->GetValue().IsNull()) {
576 isWarning = Standard_True;
582 //Make a Python command
583 GEOM::TPythonDump pd (aFunction);
584 pd << aShape << " = geompy.MakeFaceWires([";
587 it = theShapes.begin();
588 if (it != theShapes.end()) {
590 while (it != theShapes.end()) {
591 pd << ", " << (*it++);
594 pd << "], " << (int)isPlanarWanted << ")";
596 // to provide warning
597 if (!isWarning) SetErrorCode(OK);
601 //=============================================================================
603 * MakeFaceFromSurface
605 //=============================================================================
606 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface
607 (Handle(GEOM_Object) theFace,
608 Handle(GEOM_Object) theWire)
613 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FACE);
616 Handle(GEOM_Function) aFunction =
617 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_FROM_SURFACE);
619 if (aFunction.IsNull()) {
623 //Check if the function is set correctly
624 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
628 GEOMImpl_IShapes aCI (aFunction);
629 Handle(TColStd_HSequenceOfTransient) aShapesSeq =
630 new TColStd_HSequenceOfTransient;
631 Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
632 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
634 if (aRefFace.IsNull()) {
635 SetErrorCode("NULL argument face for the face construction");
639 if (aRefWire.IsNull()) {
640 SetErrorCode("NULL argument wire for the face construction");
644 aShapesSeq->Append(aRefFace);
645 aShapesSeq->Append(aRefWire);
647 aCI.SetShapes(aShapesSeq);
652 if (!GetSolver()->ComputeFunction(aFunction)) {
653 SetErrorCode("Shape driver failed");
657 catch (Standard_Failure& aFail) {
658 SetErrorCode(aFail.GetMessageString());
662 //Make a Python command
663 GEOM::TPythonDump (aFunction) << aShape
664 << " = geompy.MakeFaceFromSurface(" << theFace << ", " << theWire << ")";
671 //=============================================================================
675 //=============================================================================
676 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWrappedFace
677 (std::list<Handle(GEOM_Object)> theEdges,
678 std::list<Handle(GEOM_Object)> theVertices,
679 const Standard_Real theTolerance)
683 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FACE);
686 Handle(GEOM_Function) aFunction =
687 aShape->AddFunction(GEOMImpl_WrappingDriver::GetID(), WRAPPING_FACE);
688 if (aFunction.IsNull()) return NULL;
690 //Check if the function is set correctly
691 if (aFunction->GetDriverGUID() != GEOMImpl_WrappingDriver::GetID()) return NULL;
693 GEOMImpl_IWrap aCI (aFunction);
694 aCI.SetTolerance(theTolerance);
697 Handle(TColStd_HSequenceOfTransient) anEdgesSeq = new TColStd_HSequenceOfTransient;
698 std::list<Handle(GEOM_Object)>::iterator it = theEdges.begin();
699 for (; it != theEdges.end(); it++) {
700 Handle(GEOM_Object) anEdge = (*it);
701 if ( anEdge.IsNull() || anEdge->GetValue().ShapeType() != TopAbs_EDGE ) {
702 SetErrorCode("NULL argument edge for the face construction");
705 Handle(GEOM_Function) aRefSh = anEdge->GetLastFunction();
706 anEdgesSeq->Append(aRefSh);
708 aCI.SetEdges(anEdgesSeq);
711 Handle(TColStd_HSequenceOfTransient) aVerticesSeq = new TColStd_HSequenceOfTransient;
712 it = theVertices.begin();
713 for (; it != theVertices.end(); it++) {
714 Handle(GEOM_Object) aVertex = (*it);
715 if ( aVertex.IsNull() || aVertex->GetValue().ShapeType() != TopAbs_VERTEX ) {
716 SetErrorCode("NULL argument vertex for the face construction");
719 Handle(GEOM_Function) aRefSh = aVertex->GetLastFunction();
720 aVerticesSeq->Append(aRefSh);
722 aCI.SetVertices(aVerticesSeq);
727 if (!GetSolver()->ComputeFunction(aFunction)) {
728 SetErrorCode("Wrap driver failed");
732 catch (Standard_Failure& aFail) {
733 SetErrorCode(aFail.GetMessageString());
737 //Make a Python command
738 GEOM::TPythonDump pd (aFunction);
739 pd << aShape << " = geompy.MakeWrappedFace([";
742 it = theEdges.begin();
743 if (it != theEdges.end()) {
745 while (it != theEdges.end()) {
746 pd << ", " << (*it++);
751 it = theVertices.begin();
752 if (it != theVertices.end()) {
754 while (it != theVertices.end()) {
755 pd << ", " << (*it++);
758 pd << "], " << theTolerance << ")";
764 //=============================================================================
766 * MakeFaceWithConstraints
768 //=============================================================================
769 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWithConstraints
770 (std::list<Handle(GEOM_Object)> theConstraints)
775 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FILLING);
778 Handle(GEOM_Function) aFunction =
779 aShape->AddFunction(GEOMImpl_FillingDriver::GetID(), FILLING_ON_CONSTRAINTS);
780 if (aFunction.IsNull()) return NULL;
782 //Check if the function is set correctly
783 if (aFunction->GetDriverGUID() != GEOMImpl_FillingDriver::GetID()) return NULL;
785 GEOMImpl_IFilling aCI (aFunction);
786 Handle(TColStd_HSequenceOfTransient) aConstraints = new TColStd_HSequenceOfTransient;
789 std::list<Handle(GEOM_Object)>::iterator it = theConstraints.begin();
790 while (it != theConstraints.end()) {
791 Handle(GEOM_Object) anObject = (*it);
792 if ( anObject.IsNull() || anObject->GetValue().ShapeType() != TopAbs_EDGE ) {
793 SetErrorCode("NULL argument edge for the face construction");
796 Handle(GEOM_Function) aRefSh = anObject->GetLastFunction();
797 aConstraints->Append(aRefSh);
799 if ( it != theConstraints.end() ) {
800 Handle(GEOM_Object) aFace = (*it);
801 if ( aFace.IsNull() ) {
802 // null constraint face - it is a valid case
806 if ( aFace->GetValue().ShapeType() != TopAbs_FACE )
807 // constraint face can be omitted - it is a valid case
809 // Keep the old error code as IsSubShapeBelongsTo changes it.
810 TCollection_AsciiString anOldCode = GetErrorCode();
812 if ( IsSubShapeBelongsTo( anObject, 0, aFace, 0 ) ) {
814 SetErrorCode(anOldCode);
815 aRefSh = aFace->GetLastFunction();
816 aConstraints->Append(aRefSh);
821 SetErrorCode("Face is NULL or not connected to the Edge");
826 aCI.SetShapes( aConstraints );
829 Standard_Boolean isWarning = Standard_False;
832 if (!GetSolver()->ComputeFunction(aFunction)) {
833 SetErrorCode("Shape driver failed");
837 catch (Standard_Failure& aFail) {
838 SetErrorCode(aFail.GetMessageString());
839 // to provide warning
840 if (!aFunction->GetValue().IsNull()) {
841 isWarning = Standard_True;
847 //Make a Python command
848 GEOM::TPythonDump pd (aFunction);
849 pd << aShape << " = geompy.MakeFaceWithConstraints([";
852 it = theConstraints.begin();
853 if (it != theConstraints.end() ) {
855 while (it != theConstraints.end()) {
856 Handle(GEOM_Object) anObject = (*it++);
857 if( !anObject.IsNull() )
858 pd << ", " << anObject;
863 // to provide warning
864 if (!isWarning) SetErrorCode(OK);
868 //=============================================================================
872 //=============================================================================
873 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
874 (std::list<Handle(GEOM_Object)> theShapes)
876 return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
879 //=============================================================================
883 //=============================================================================
884 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
885 (std::list<Handle(GEOM_Object)> theShapes)
887 return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
890 //=============================================================================
894 //=============================================================================
895 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
896 (std::list<Handle(GEOM_Object)> theShapes)
898 return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
901 //=============================================================================
905 //=============================================================================
906 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
907 (std::list<Handle(GEOM_Object)> theShapes,
908 const Standard_Integer theObjectType,
909 const Standard_Integer theFunctionType,
910 const TCollection_AsciiString& theMethodName)
915 Handle(GEOM_Object) aShape = GetEngine()->AddObject(theObjectType);
918 Handle(GEOM_Function) aFunction =
919 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
920 if (aFunction.IsNull()) return NULL;
922 //Check if the function is set correctly
923 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
925 GEOMImpl_IShapes aCI (aFunction);
927 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
930 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
931 for (; it != theShapes.end(); it++) {
932 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
933 if (aRefSh.IsNull()) {
934 SetErrorCode("NULL argument shape for the shape construction");
937 aShapesSeq->Append(aRefSh);
939 aCI.SetShapes(aShapesSeq);
944 if (!GetSolver()->ComputeFunction(aFunction)) {
945 SetErrorCode("Shape driver failed");
949 catch (Standard_Failure& aFail) {
950 SetErrorCode(aFail.GetMessageString());
954 //Make a Python command
955 GEOM::TPythonDump pd (aFunction);
956 pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
959 it = theShapes.begin();
960 if (it != theShapes.end()) {
962 while (it != theShapes.end()) {
963 pd << ", " << (*it++);
972 //=============================================================================
974 * MakeSolidFromConnectedFaces
976 //=============================================================================
977 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidFromConnectedFaces
978 (std::list<Handle(GEOM_Object)> theFacesOrShells,
979 const Standard_Boolean isIntersect)
984 Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GEOM_SOLID);
987 Handle(GEOM_Function) aFunction =
988 aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_FACES);
989 if (aFunction.IsNull()) return NULL;
991 //Check if the function is set correctly
992 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
994 GEOMImpl_IShapes aCI (aFunction);
996 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
999 std::list<Handle(GEOM_Object)>::iterator it = theFacesOrShells.begin();
1000 for (; it != theFacesOrShells.end(); it++) {
1001 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
1002 if (aRefSh.IsNull()) {
1003 SetErrorCode("NULL argument shape for the shape construction");
1006 aShapesSeq->Append(aRefSh);
1008 aCI.SetShapes(aShapesSeq);
1009 aCI.SetIsIntersect(isIntersect);
1014 if (!GetSolver()->ComputeFunction(aFunction)) {
1015 SetErrorCode("Shape driver failed");
1019 catch (Standard_Failure& aFail) {
1020 SetErrorCode(aFail.GetMessageString());
1024 //Make a Python command
1025 GEOM::TPythonDump pd (aFunction);
1026 pd << aSolid << " = geompy.MakeSolidFromConnectedFaces([";
1029 it = theFacesOrShells.begin();
1030 if (it != theFacesOrShells.end()) {
1032 while (it != theFacesOrShells.end()) {
1033 pd << ", " << (*it++);
1036 pd << "]," << (isIntersect ? "True" : "False") << ")";
1042 //=============================================================================
1046 //=============================================================================
1048 GEOMImpl_IShapesOperations::MakeGlueFaces (std::list< Handle(GEOM_Object) >& theShapes,
1049 const Standard_Real theTolerance,
1050 const Standard_Boolean doKeepNonSolids)
1054 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1055 if ( objects.IsNull() || objects->IsEmpty() ) {
1056 SetErrorCode("NULL argument shape");
1060 //Add a new Glued object
1061 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
1063 //Add a new Glue function
1064 Handle(GEOM_Function) aFunction;
1065 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
1066 if (aFunction.IsNull()) return NULL;
1068 //Check if the function is set correctly
1069 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1071 GEOMImpl_IGlue aCI (aFunction);
1073 aCI.SetBase( objects );
1074 aCI.SetTolerance(theTolerance);
1075 aCI.SetKeepNonSolids(doKeepNonSolids);
1077 //Compute the sub-shape value
1078 Standard_Boolean isWarning = Standard_False;
1081 if (!GetSolver()->ComputeFunction(aFunction)) {
1082 SetErrorCode("Shape driver failed to glue faces");
1086 catch (Standard_Failure& aFail) {
1087 SetErrorCode(aFail.GetMessageString());
1088 // to provide warning
1089 if (!aFunction->GetValue().IsNull()) {
1090 isWarning = Standard_True;
1096 //Make a Python command
1097 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
1098 << theShapes << ", " << theTolerance << ")";
1100 // to provide warning
1101 if (!isWarning) SetErrorCode(OK);
1105 //=============================================================================
1109 //=============================================================================
1111 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
1112 (Handle(GEOM_Object) theShape,
1113 const Standard_Real theTolerance)
1117 if (theShape.IsNull()) return NULL;
1118 TopoDS_Shape aShape = theShape->GetValue();
1119 if (aShape.IsNull()) return NULL;
1121 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1123 Standard_Integer iErr;
1125 GEOMAlgo_Gluer1 aGluer;
1126 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
1127 GEOMAlgo_CoupleOfShapes aCS;
1128 GEOMAlgo_ListOfCoupleOfShapes aLCS;
1130 //aGluer = new GEOMAlgo_Gluer1;
1131 aGluer.SetShape(aShape);
1132 aGluer.SetTolerance(theTolerance);
1134 iErr = aGluer.ErrorStatus();
1135 if (iErr) return NULL;
1137 TopTools_ListOfShape listShape;
1138 const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
1140 aItCS.Initialize(aLCSG);
1141 for (; aItCS.More(); aItCS.Next()) {
1142 const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
1143 listShape.Append(aCSG.Shape1());
1146 TopTools_ListIteratorOfListOfShape itSub (listShape);
1147 TCollection_AsciiString anAsciiList, anEntry;
1148 TopTools_IndexedMapOfShape anIndices;
1149 TopExp::MapShapes(aShape, anIndices);
1150 Handle(TColStd_HArray1OfInteger) anArray;
1151 Handle(GEOM_Object) anObj;
1152 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1153 TopoDS_Shape aValue = itSub.Value();
1154 anArray = new TColStd_HArray1OfInteger(1,1);
1155 anArray->SetValue(1, anIndices.FindIndex(aValue));
1156 anObj = GetEngine()->AddSubShape(theShape, anArray);
1157 if (!anObj.IsNull()) {
1158 aSeq->Append(anObj);
1160 // for python command
1161 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1162 anAsciiList += anEntry;
1167 //Make a Python command
1168 if( anAsciiList.Length() > 0 ) {
1169 anAsciiList.Trunc(anAsciiList.Length() - 1);
1170 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1171 GEOM::TPythonDump pd (aFunction, true);
1172 pd << "[" << anAsciiList.ToCString();
1173 pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
1182 //=============================================================================
1184 * MakeGlueFacesByList
1186 //=============================================================================
1188 GEOMImpl_IShapesOperations::MakeGlueFacesByList(std::list< Handle(GEOM_Object) >& theShapes,
1189 const Standard_Real theTolerance,
1190 std::list<Handle(GEOM_Object)> & theFaces,
1191 const Standard_Boolean doKeepNonSolids,
1192 const Standard_Boolean doGlueAllEdges)
1196 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1197 if ( objects.IsNull() || objects->IsEmpty() ) {
1198 SetErrorCode("NULL argument shape");
1201 Handle(TColStd_HSequenceOfTransient) aFaces = GEOM_Object::GetLastFunctions( theFaces );
1202 if ( aFaces.IsNull() ) {
1203 SetErrorCode("NULL argument shape for the shape construction");
1207 //Add a new Glued object
1208 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
1210 //Add a new Glue function
1211 Handle(GEOM_Function) aFunction;
1212 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
1213 if (aFunction.IsNull()) return NULL;
1215 //Check if the function is set correctly
1216 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1218 GEOMImpl_IGlue aCI (aFunction);
1220 aCI.SetBase( objects );
1221 aCI.SetTolerance(theTolerance);
1222 aCI.SetKeepNonSolids(doKeepNonSolids);
1223 aCI.SetGlueAllEdges(doGlueAllEdges);
1224 aCI.SetFaces(aFaces);
1226 //Compute the sub-shape value
1227 Standard_Boolean isWarning = Standard_False;
1230 if (!GetSolver()->ComputeFunction(aFunction)) {
1231 SetErrorCode("Shape driver failed to glue faces");
1235 catch (Standard_Failure& aFail) {
1236 SetErrorCode(aFail.GetMessageString());
1237 // to provide warning
1238 if (!aFunction->GetValue().IsNull()) {
1239 isWarning = Standard_True;
1245 //Make a Python command
1247 GEOM::TPythonDump pd(aFunction);
1248 pd << aGlued << " = geompy.MakeGlueFacesByList("
1249 << theShapes << ", " << theTolerance << ", " << theFaces << ", "
1250 << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")";
1252 // to provide warning
1253 if (!isWarning) SetErrorCode(OK);
1257 //=============================================================================
1261 //=============================================================================
1263 GEOMImpl_IShapesOperations::MakeGlueEdges (std::list< Handle(GEOM_Object) >& theShapes,
1264 const Standard_Real theTolerance)
1268 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1269 if ( objects.IsNull() || objects->IsEmpty() ) {
1270 SetErrorCode("NULL argument shape");
1274 //Add a new Glued object
1275 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
1277 //Add a new Glue function
1278 Handle(GEOM_Function) aFunction;
1279 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES);
1280 if (aFunction.IsNull()) return NULL;
1282 //Check if the function is set correctly
1283 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1285 GEOMImpl_IGlue aCI (aFunction);
1287 aCI.SetBase( objects );
1288 aCI.SetTolerance(theTolerance);
1289 aCI.SetKeepNonSolids(true);
1291 //Compute the sub-shape value
1292 Standard_Boolean isWarning = Standard_False;
1295 if (!GetSolver()->ComputeFunction(aFunction)) {
1296 SetErrorCode("Shape driver failed to glue edges");
1300 catch (Standard_Failure& aFail) {
1301 SetErrorCode(aFail.GetMessageString());
1302 // to provide warning
1303 if (!aFunction->GetValue().IsNull()) {
1304 isWarning = Standard_True;
1310 //Make a Python command
1311 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueEdges("
1312 << theShapes << ", " << theTolerance << ")";
1314 // to provide warning
1315 if (!isWarning) SetErrorCode(OK);
1319 //=============================================================================
1323 //=============================================================================
1324 Handle(TColStd_HSequenceOfTransient)
1325 GEOMImpl_IShapesOperations::GetGlueShapes (std::list< Handle(GEOM_Object) >& theShapes,
1326 const Standard_Real theTolerance,
1327 const TopAbs_ShapeEnum theType)
1331 TopoDS_Shape aShape;
1332 TopTools_SequenceOfShape shapes;
1333 std::list< Handle(GEOM_Object) >::iterator s = theShapes.begin();
1334 Handle(GEOM_BaseObject) lastCreatedGO;
1335 for ( ; s != theShapes.end(); ++s )
1337 Handle(GEOM_Object) go = *s;
1338 if ( go.IsNull() ) return NULL;
1339 aShape = go->GetValue();
1340 if ( aShape.IsNull() ) return NULL;
1341 shapes.Append( aShape );
1342 lastCreatedGO = GEOM::GetCreatedLast( lastCreatedGO, go );
1344 if ( shapes.Length() > 1 )
1346 TopoDS_Compound compound;
1347 BRep_Builder builder;
1348 builder.MakeCompound( compound );
1349 for ( int i = 1; i <= shapes.Length(); ++i )
1350 builder.Add( compound, shapes( i ) );
1355 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1357 GEOMAlgo_GlueDetector aGluer;
1358 aGluer.SetArgument(aShape);
1359 aGluer.SetTolerance(theTolerance);
1361 Standard_Integer iErr = aGluer.ErrorStatus();
1362 if (iErr) return NULL;
1364 std::vector< TopTools_IndexedMapOfShape* > anIndices( shapes.Length(), NULL );
1365 Handle(TColStd_HArray1OfInteger) anArray;
1366 Handle(GEOM_Object) anObj;
1368 TopTools_ListOfShape listOnePerSet;
1370 const TopTools_DataMapOfShapeListOfShape& aImages = aGluer.Images();
1371 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS (aImages);
1372 for (int index = 1; aItDMSLS.More(); aItDMSLS.Next(), ++index) {
1374 //const TopoDS_Shape& aSkey = aItDMSLS.Key();
1376 // list of shapes of the argument that can be glued
1377 const TopTools_ListOfShape& aLSD = aItDMSLS.Value();
1379 //listShape.Append(aLSD.First());
1380 TopoDS_Shape aValue = aLSD.First();
1382 if (aValue.ShapeType() == theType) {
1383 listOnePerSet.Append(aValue);
1387 // for stable order of returned entities
1388 GEOMUtils::SortShapes(listOnePerSet, Standard_False);
1390 TopTools_ListIteratorOfListOfShape aListIt (listOnePerSet);
1391 for (; aListIt.More(); aListIt.Next())
1393 TopoDS_Shape aValue = aListIt.Value();
1394 // find a shape to add aValue as a sub-shape
1396 s = theShapes.begin();
1397 for ( int i = 0; i < shapes.Length(); ++i, ++s )
1399 Handle(GEOM_Object) object = *s;
1400 if ( !anIndices[i] ) {
1401 anIndices[i] = new TopTools_IndexedMapOfShape;
1402 TopExp::MapShapes( object->GetValue(), *anIndices[i]);
1404 if (int index = anIndices[i]->FindIndex( aValue )) {
1405 anArray = new TColStd_HArray1OfInteger(1,1);
1406 anArray->SetValue(1, index);
1407 anObj = GetEngine()->AddSubShape( object, anArray);
1411 if (!anObj.IsNull())
1412 aSeq->Append(anObj);
1414 for ( size_t i = 0 ; i < anIndices.size(); ++i )
1415 delete anIndices[i];
1417 // Make a Python command
1418 if ( aSeq->Length() > 0)
1420 Handle(GEOM_Function) aFunction = lastCreatedGO->GetLastFunction();
1421 GEOM::TPythonDump pd (aFunction, /*append=*/true);
1423 << " = geompy." << (theType == TopAbs_FACE ? "GetGlueFaces" : "GetGlueEdges" )
1424 << "( " << theShapes << ", " << theTolerance << ")";
1432 //=============================================================================
1434 * MakeGlueEdgesByList
1436 //=============================================================================
1438 GEOMImpl_IShapesOperations::MakeGlueEdgesByList (std::list< Handle(GEOM_Object) >& theShapes,
1439 const Standard_Real theTolerance,
1440 std::list<Handle(GEOM_Object)>& theEdges)
1444 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1445 if ( objects.IsNull() || objects->IsEmpty() ) {
1446 SetErrorCode("NULL argument shape");
1449 Handle(TColStd_HSequenceOfTransient) anEdges = GEOM_Object::GetLastFunctions( theEdges );
1450 if ( anEdges.IsNull() ) {
1451 SetErrorCode("NULL argument shape for the shape construction");
1454 //Add a new Glued object
1455 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
1457 //Add a new Glue function
1458 Handle(GEOM_Function) aFunction;
1459 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES_BY_LIST);
1460 if (aFunction.IsNull()) return NULL;
1462 //Check if the function is set correctly
1463 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1465 GEOMImpl_IGlue aCI (aFunction);
1467 aCI.SetBase( objects );
1468 aCI.SetTolerance(theTolerance);
1469 aCI.SetKeepNonSolids(true);
1470 aCI.SetFaces(anEdges);
1472 //Compute the sub-shape value
1473 Standard_Boolean isWarning = Standard_False;
1476 if (!GetSolver()->ComputeFunction(aFunction)) {
1477 SetErrorCode("Shape driver failed to glue edges");
1481 catch (Standard_Failure& aFail) {
1482 SetErrorCode(aFail.GetMessageString());
1483 // to provide warning
1484 if (!aFunction->GetValue().IsNull()) {
1485 isWarning = Standard_True;
1491 //Make a Python command
1493 GEOM::TPythonDump pd (aFunction);
1494 pd << aGlued << " = geompy.MakeGlueEdgesByList("
1495 << theShapes << ", " << theTolerance << ", " << theEdges << " )";
1497 // to provide warning
1498 if (!isWarning) SetErrorCode(OK);
1502 //=============================================================================
1504 * GetExistingSubObjects
1506 //=============================================================================
1507 Handle(TColStd_HSequenceOfTransient)
1508 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape,
1509 const Standard_Boolean theGroupsOnly)
1511 // note: this method does not return fields
1513 Standard_Integer types = theGroupsOnly ? Groups : Groups|SubShapes;
1514 Handle(TColStd_HSequenceOfTransient) results = GetExistingSubObjects(theShape, types);
1516 Handle(GEOM_BaseObject) lastCreatedGO = GEOM::GetCreatedLast(results);
1517 lastCreatedGO = GEOM::GetCreatedLast(lastCreatedGO, theShape);
1519 if (results->Length() > 0) {
1520 // Make a Python command
1521 GEOM::TPythonDump pd (lastCreatedGO->GetLastFunction(), /*append=*/true);
1523 Standard_Integer i, aLen = results->Length();
1524 for (i = 1; i <= aLen; i++)
1526 Handle(GEOM_BaseObject) obj = Handle(GEOM_BaseObject)::DownCast(results->Value(i));
1527 pd << obj << ((i < aLen) ? ", " : "");
1529 pd << "] = geompy.GetExistingSubObjects(";
1530 pd << theShape << ", " << (bool)theGroupsOnly << ")";
1536 Handle(TColStd_HSequenceOfTransient)
1537 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape,
1538 const Standard_Integer theTypes)
1542 if (theShape.IsNull()) return NULL;
1544 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1545 if (aMainShape.IsNull()) return NULL;
1547 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1548 SetErrorCode(NOT_FOUND_ANY);
1550 if (!aMainShape->HasSubShapeReferences()) return aSeq;
1551 const TDataStd_ListOfExtendedString& aListEntries = aMainShape->GetSubShapeReferences();
1552 if (aListEntries.IsEmpty()) return aSeq;
1556 TDataStd_ListIteratorOfListOfExtendedString anIt (aListEntries);
1557 for (; anIt.More(); anIt.Next()) {
1558 TCollection_ExtendedString anEntry = anIt.Value();
1559 Standard_Integer aStrLen = anEntry.LengthOfCString();
1560 char* anEntryStr = new char[aStrLen+1];
1561 anEntry.ToUTF8CString(anEntryStr);
1562 Handle(GEOM_BaseObject) anObj = GetEngine()->GetObject(anEntryStr, false);
1563 if (!anObj.IsNull() ) {
1564 bool isGroup = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() == GEOM_GROUP;
1565 bool isSubShape = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() != GEOM_GROUP;
1566 bool isField = anObj->IsKind(STANDARD_TYPE(GEOM_Field));
1567 if ((theTypes & Groups && isGroup ) ||
1568 (theTypes & SubShapes && isSubShape ) ||
1569 (theTypes & Fields && isField ))
1570 aSeq->Append(anObj);
1572 delete [] anEntryStr;
1575 if (aSeq->Length() == 0) {
1576 SetErrorCode(NOT_FOUND_ANY);
1585 //=============================================================================
1589 //=============================================================================
1590 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
1591 (Handle(GEOM_Object) theShape,
1592 const Standard_Integer theShapeType,
1593 const Standard_Boolean isSorted,
1594 const ExplodeType theExplodeType)
1598 if (theShape.IsNull()) return NULL;
1599 TopoDS_Shape aShape = theShape->GetValue();
1600 if (aShape.IsNull()) return NULL;
1602 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1604 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1605 Handle(GEOM_Object) anObj;
1606 TopTools_MapOfShape mapShape;
1607 TopTools_ListOfShape listShape;
1609 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1610 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1612 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1613 for (; It.More(); It.Next()) {
1614 TopoDS_Shape SS = It.Value();
1615 if (mapShape.Add(SS)) {
1616 if (theShapeType == TopAbs_FLAT) {
1617 AddFlatSubShapes(SS, listShape, mapShape);
1619 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1620 listShape.Append(SS);
1622 // VSR: for EXPLODE_NEW_INCLUDE_MAIN and EXPLODE_OLD_INCLUDE_MAIN:
1623 // it seems it is necessary to add top-level shape if theShapeType == TopAbs_COMPOUND
1627 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1629 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1630 for (; exp.More(); exp.Next())
1631 if (mapShape.Add(exp.Current()))
1632 listShape.Append(exp.Current());
1635 if (listShape.IsEmpty()){
1636 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1637 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1642 bool isOldSorting = false;
1643 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1644 isOldSorting = true;
1645 GEOMUtils::SortShapes(listShape, isOldSorting);
1648 TopTools_IndexedMapOfShape anIndices;
1649 TopExp::MapShapes(aShape, anIndices);
1650 Handle(TColStd_HArray1OfInteger) anArray;
1652 TopTools_ListIteratorOfListOfShape itSub (listShape);
1653 TCollection_AsciiString anAsciiList, anEntry;
1654 for (int index = 1; itSub.More(); itSub.Next(), ++index)
1656 TopoDS_Shape aValue = itSub.Value();
1657 anArray = new TColStd_HArray1OfInteger(1,1);
1658 anArray->SetValue(1, anIndices.FindIndex(aValue));
1660 //anObj = GetEngine()->AddSubShape(theShape, anArray);
1662 anObj = GetEngine()->AddObject(GEOM_SUBSHAPE);
1663 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1664 if (aFunction.IsNull()) return aSeq;
1666 GEOM_ISubShape aSSI (aFunction);
1667 aSSI.SetMainShape(aMainShape);
1668 aSSI.SetIndices(anArray);
1670 // Set function value directly, as we know it.
1671 // Usage of Solver here would lead to significant loss of time,
1672 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1673 // on the main shape for each being calculated sub-shape separately.
1674 aFunction->SetValue(aValue);
1676 // Put this subshape in the list of sub-shapes of theMainShape
1677 aMainShape->AddSubShapeReference(aFunction);
1679 if (!anObj.IsNull()) {
1680 aSeq->Append(anObj);
1682 // for python command
1683 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1684 anAsciiList += anEntry;
1689 //Make a Python command
1690 anAsciiList.Trunc(anAsciiList.Length() - 1);
1692 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1693 pd << "[" << anAsciiList.ToCString() << "] = geompy.";
1694 switch (theExplodeType) {
1695 case EXPLODE_NEW_EXCLUDE_MAIN:
1696 pd << "ExtractShapes(" << theShape << ", "
1697 << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")";
1699 case EXPLODE_NEW_INCLUDE_MAIN:
1700 pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(")
1701 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1703 case EXPLODE_OLD_INCLUDE_MAIN:
1704 pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(")
1705 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1714 //=============================================================================
1718 //=============================================================================
1719 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
1720 (Handle(GEOM_Object) theShape,
1721 const Standard_Integer theShapeType,
1722 const Standard_Boolean isSorted,
1723 const ExplodeType theExplodeType)
1727 if (theShape.IsNull()) return NULL;
1728 TopoDS_Shape aShape = theShape->GetValue();
1729 if (aShape.IsNull()) return NULL;
1731 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1732 TopTools_MapOfShape mapShape;
1733 TopTools_ListOfShape listShape;
1735 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1736 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1738 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1739 for (; It.More(); It.Next()) {
1740 TopoDS_Shape SS = It.Value();
1741 if (mapShape.Add(SS)) {
1742 if (theShapeType == TopAbs_FLAT) {
1743 AddFlatSubShapes(SS, listShape, mapShape);
1745 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1746 listShape.Append(SS);
1751 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1753 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1754 for (; exp.More(); exp.Next())
1755 if (mapShape.Add(exp.Current()))
1756 listShape.Append(exp.Current());
1759 if (listShape.IsEmpty()) {
1760 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1761 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1766 bool isOldSorting = false;
1767 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1768 isOldSorting = true;
1769 GEOMUtils::SortShapes(listShape, isOldSorting);
1772 TopTools_IndexedMapOfShape anIndices;
1773 TopExp::MapShapes(aShape, anIndices);
1774 Handle(TColStd_HArray1OfInteger) anArray;
1776 TopTools_ListIteratorOfListOfShape itSub (listShape);
1777 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1778 TopoDS_Shape aValue = itSub.Value();
1779 aSeq->Append(anIndices.FindIndex(aValue));
1782 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1784 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
1785 #ifdef DUMP_SUBSHAPE_IDS
1786 //Make a Python command
1787 GEOM::TPythonDump pd (aFunction, /*append=*/true);
1788 pd << "listSubShapeIDs = geompy.SubShapeAll";
1789 switch (theExplodeType) {
1790 case EXPLODE_NEW_EXCLUDE_MAIN:
1792 case EXPLODE_NEW_INCLUDE_MAIN:
1793 pd << (isSorted ? "SortedCentresIDs(" : "IDs(")
1794 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1796 case EXPLODE_OLD_INCLUDE_MAIN:
1797 pd << (isSorted ? "SortedIDs(" : "IDs(")
1798 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1802 #endif // DUMP_SUBSHAPE_IDS
1808 //=============================================================================
1812 //=============================================================================
1813 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
1814 (Handle(GEOM_Object) theMainShape,
1815 const Standard_Integer theID)
1819 if (theMainShape.IsNull()) return NULL;
1821 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1822 anArray->SetValue(1, theID);
1823 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
1824 if (anObj.IsNull()) {
1825 SetErrorCode("Can not get a sub-shape with the given ID");
1829 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1831 //Make a Python command
1832 GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1833 << theMainShape << ", [" << theID << "])";
1839 //=============================================================================
1843 //=============================================================================
1844 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes
1845 (Handle(GEOM_Object) theMainShape,
1846 Handle(TColStd_HArray1OfInteger) theIndices)
1850 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1852 if (!theIndices->Length()) {
1853 SetErrorCode(NOT_FOUND_ANY);
1857 if (theMainShape.IsNull()) return NULL;
1858 TopoDS_Shape aShape = theMainShape->GetValue();
1859 if (aShape.IsNull()) return NULL;
1861 Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
1863 TopTools_IndexedMapOfShape anIndices;
1864 TopExp::MapShapes(aShape, anIndices);
1866 Handle(TColStd_HArray1OfInteger) anArray;
1867 Handle(GEOM_Object) anObj;
1869 TCollection_AsciiString anAsciiList, anEntry;
1870 Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper();
1871 for (i = low; i <= up; i++) {
1872 int id = theIndices->Value(i);
1873 if (1 <= id && id <= anIndices.Extent()) {
1874 TopoDS_Shape aValue = anIndices.FindKey(id);
1875 anArray = new TColStd_HArray1OfInteger(1,1);
1876 anArray->SetValue(1, id);
1878 anObj = GetEngine()->AddObject(GEOM_SUBSHAPE);
1879 if (!anObj.IsNull()) {
1880 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1881 if (aFunction.IsNull()) return aSeq;
1883 GEOM_ISubShape aSSI (aFunction);
1884 aSSI.SetMainShape(aMainShape);
1885 aSSI.SetIndices(anArray);
1887 // Set function value directly, as we know it.
1888 // Usage of Solver here would lead to significant loss of time,
1889 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1890 // on the main shape for each being calculated sub-shape separately.
1891 aFunction->SetValue(aValue);
1893 // Put this sub-shape in the list of sub-shapes of theMainShape
1894 aMainShape->AddSubShapeReference(aFunction);
1896 aSeq->Append(anObj);
1898 // for python command
1899 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1900 anAsciiList += anEntry;
1906 //Make a Python command
1907 anAsciiList.Trunc(anAsciiList.Length() - 1);
1909 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1910 pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes("
1911 << theMainShape << ", [" ;
1912 for (i = low; i <= up - 1; i++) {
1913 pd << theIndices->Value(i) << ", ";
1915 pd << theIndices->Value(up) << "])";
1922 //=============================================================================
1926 //=============================================================================
1927 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1928 Handle(GEOM_Object) theSubShape)
1932 TopoDS_Shape aMainShape = theMainShape->GetValue();
1933 TopoDS_Shape aSubShape = theSubShape->GetValue();
1935 if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1937 TopTools_IndexedMapOfShape anIndices;
1938 TopExp::MapShapes(aMainShape, anIndices);
1939 // if (anIndices.Contains(aSubShape)) {
1940 // SetErrorCode(OK);
1941 // return anIndices.FindIndex(aSubShape);
1943 int id = anIndices.FindIndex(aSubShape);
1954 //=============================================================================
1956 * GetSubShapeIndices
1958 //=============================================================================
1959 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSubShapesIndices (Handle(GEOM_Object) theMainShape,
1960 std::list<Handle(GEOM_Object)> theSubShapes)
1962 MESSAGE("GEOMImpl_IShapesOperations::GetSubShapesIndices");
1965 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1967 TopoDS_Shape aMainShape = theMainShape->GetValue();
1968 if (aMainShape.IsNull())
1970 MESSAGE("NULL main shape");
1974 TopTools_IndexedMapOfShape anIndices;
1975 TopExp::MapShapes(aMainShape, anIndices);
1977 std::list<Handle(GEOM_Object)>::iterator it;
1978 for (it=theSubShapes.begin(); it != theSubShapes.end(); ++it)
1980 TopoDS_Shape aSubShape = (*it)->GetValue();
1981 if (aSubShape.IsNull())
1983 MESSAGE("NULL subshape");
1986 int id = anIndices.FindIndex(aSubShape);
1995 //=============================================================================
1999 //=============================================================================
2000 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
2001 Handle(GEOM_Object) theSubShape)
2005 TopoDS_Shape aMainShape = theMainShape->GetValue();
2006 TopoDS_Shape aSubShape = theSubShape->GetValue();
2008 if (aMainShape.IsNull() || aSubShape.IsNull()) {
2009 SetErrorCode("Null argument shape given");
2014 if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
2016 TopTools_ListOfShape CL;
2017 CL.Append(aMainShape);
2018 TopTools_ListIteratorOfListOfShape itC;
2019 for (itC.Initialize(CL); itC.More(); itC.Next()) {
2020 for (it.Initialize(itC.Value()); it.More(); it.Next()) {
2021 if (it.Value().ShapeType() == TopAbs_COMPOUND) {
2022 if (it.Value().IsSame(aSubShape))
2026 CL.Append(it.Value());
2031 TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
2032 TopTools_MapOfShape M;
2033 for (; anExp.More(); anExp.Next()) {
2034 if (M.Add(anExp.Current())) {
2035 if (anExp.Current().IsSame(aSubShape))
2042 SetErrorCode("The sub-shape does not belong to the main shape");
2046 //=============================================================================
2048 * GetShapeTypeString
2050 //=============================================================================
2051 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
2055 TCollection_AsciiString aTypeName ("Null Shape");
2057 TopoDS_Shape aShape = theShape->GetValue();
2058 if (aShape.IsNull())
2061 switch (aShape.ShapeType() )
2063 case TopAbs_COMPOUND:
2064 aTypeName = "Compound";
2066 case TopAbs_COMPSOLID:
2067 aTypeName = "Compound Solid";
2070 aTypeName = "Solid";
2073 aTypeName = "Shell";
2077 BRepAdaptor_Surface surf (TopoDS::Face(aShape));
2078 if (surf.GetType() == GeomAbs_Plane)
2079 aTypeName = "Plane";
2080 else if (surf.GetType() == GeomAbs_Cylinder)
2081 aTypeName = "Cylindrical Face";
2082 else if (surf.GetType() == GeomAbs_Sphere)
2083 aTypeName = "Spherical Face";
2084 else if (surf.GetType() == GeomAbs_Torus)
2085 aTypeName = "Toroidal Face";
2086 else if (surf.GetType() == GeomAbs_Cone)
2087 aTypeName = "Conical Face";
2089 aTypeName = "GEOM::FACE";
2097 BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
2098 if (curv.GetType() == GeomAbs_Line) {
2099 if ((Abs(curv.FirstParameter()) >= 1E6) ||
2100 (Abs(curv.LastParameter()) >= 1E6))
2104 } else if (curv.GetType() == GeomAbs_Circle) {
2105 if (curv.IsClosed())
2106 aTypeName = "Circle";
2115 aTypeName = "Vertex";
2118 aTypeName = "Shape";
2121 aTypeName = "Shape of unknown type";
2127 //=============================================================================
2129 * IsSubShapeBelongsTo
2131 //=============================================================================
2132 Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject,
2133 const Standard_Integer theSubObjectIndex,
2134 Handle(GEOM_Object) theObject,
2135 const Standard_Integer theObjectIndex)
2139 if ( theObject.IsNull() || theSubObject.IsNull() )
2142 TopoDS_Shape shape = theObject->GetValue();
2143 TopoDS_Shape subShape = theSubObject->GetValue();
2145 if ( shape.IsNull() || subShape.IsNull() )
2148 TopTools_IndexedMapOfShape anIndices;
2149 if ( theObjectIndex > 0 ) {
2150 TopExp::MapShapes( shape, anIndices );
2151 shape = anIndices.FindKey(theObjectIndex);
2154 if ( theSubObjectIndex > 0 ) {
2155 TopExp::MapShapes( subShape, anIndices );
2156 subShape = anIndices.FindKey(theSubObjectIndex);
2160 TopExp::MapShapes( shape, anIndices );
2162 const Standard_Boolean isBelongTo = anIndices.Contains(subShape);
2169 //=============================================================================
2173 //=============================================================================
2174 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
2175 (Handle(GEOM_Object) theShape,
2176 const Standard_Integer theShapeType)
2179 Standard_Integer nbShapes = 0;
2181 if (theShape.IsNull()) return -1;
2182 TopoDS_Shape aShape = theShape->GetValue();
2183 if (aShape.IsNull()) return -1;
2186 TopTools_MapOfShape mapShape;
2188 if (aShape.ShapeType() == TopAbs_COMPOUND &&
2189 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2190 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
2191 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
2192 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
2193 for (; It.More(); It.Next()) {
2194 if (mapShape.Add(It.Value())) {
2195 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2196 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
2202 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
2203 for (; exp.More(); exp.Next())
2204 if (mapShape.Add(exp.Current()))
2210 if (theShapeType == TopAbs_FLAT) {
2211 TopTools_MapOfShape aMapOfShape;
2212 TopTools_ListOfShape aListOfShape;
2213 AddFlatSubShapes(aShape, aListOfShape, aMapOfShape);
2214 nbShapes = aListOfShape.Extent();
2218 int iType, nbTypes [TopAbs_SHAPE];
2219 for (iType = 0; iType < TopAbs_SHAPE; ++iType)
2221 nbTypes[aShape.ShapeType()]++;
2223 TopTools_MapOfShape aMapOfShape;
2224 aMapOfShape.Add(aShape);
2225 TopTools_ListOfShape aListOfShape;
2226 aListOfShape.Append(aShape);
2228 TopTools_ListIteratorOfListOfShape itL (aListOfShape);
2229 for (; itL.More(); itL.Next()) {
2230 TopoDS_Iterator it (itL.Value());
2231 for (; it.More(); it.Next()) {
2232 TopoDS_Shape s = it.Value();
2233 if (aMapOfShape.Add(s)) {
2234 aListOfShape.Append(s);
2235 nbTypes[s.ShapeType()]++;
2240 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
2241 nbShapes = aMapOfShape.Extent();
2243 nbShapes = nbTypes[theShapeType];
2246 catch (Standard_Failure& aFail) {
2247 SetErrorCode(aFail.GetMessageString());
2255 //=============================================================================
2259 //=============================================================================
2260 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
2264 if (theShape.IsNull()) return NULL;
2267 //Add a new reversed object
2268 Handle(GEOM_Object) aReversed = GetEngine()->AddObject(theShape->GetType());
2270 //Add a new Revese function
2271 Handle(GEOM_Function) aFunction;
2272 aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
2273 if (aFunction.IsNull()) return NULL;
2275 //Check if the function is set correctly
2276 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
2278 GEOMImpl_IShapes aSI (aFunction);
2280 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2281 if (aRefShape.IsNull()) return NULL;
2283 aSI.SetBase(aRefShape);
2285 //Compute the sub-shape value
2288 if (!GetSolver()->ComputeFunction(aFunction)) {
2289 SetErrorCode("Shape driver failed to reverse shape");
2293 catch (Standard_Failure& aFail) {
2294 SetErrorCode(aFail.GetMessageString());
2298 //Make a Python command
2299 GEOM::TPythonDump(aFunction) << aReversed
2300 << " = geompy.ChangeOrientation(" << theShape << ")";
2305 Handle(GEOM_Object) aReversed;
2307 GEOM_Engine* anEngine = GetEngine();
2308 //GEOMImpl_Gen* aGen = dynamic_cast<GEOMImpl_Gen*>(anEngine);
2309 GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine;
2312 GEOMImpl_IHealingOperations* anIHealingOperations =
2313 aGen->GetIHealingOperations();
2314 aReversed = anIHealingOperations->ChangeOrientationCopy(theShape);
2315 SetErrorCode(anIHealingOperations->GetErrorCode());
2321 //=============================================================================
2325 //=============================================================================
2326 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
2327 (Handle(GEOM_Object) theShape)
2331 if (theShape.IsNull()) return NULL;
2332 TopoDS_Shape aShape = theShape->GetValue();
2333 if (aShape.IsNull()) return NULL;
2335 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
2337 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2338 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2339 (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2341 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2344 SetErrorCode("The given shape has no faces");
2348 TopTools_IndexedMapOfShape anIndices;
2349 TopExp::MapShapes(aShape, anIndices);
2351 Standard_Integer id;
2352 for (; ind <= nbFaces; ind++) {
2353 if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
2354 id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
2359 //The explode doesn't change object so no new function is required.
2360 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
2362 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2363 #ifdef DUMP_SUBSHAPE_IDS
2364 //Make a Python command
2365 GEOM::TPythonDump(aFunction, /*append=*/true)
2366 << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
2367 #endif // DUMP_SUBSHAPE_IDS
2373 //=======================================================================
2374 //function : GetSharedShapes
2376 //=======================================================================
2377 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2378 (Handle(GEOM_Object) theShape1,
2379 Handle(GEOM_Object) theShape2,
2380 const Standard_Integer theShapeType)
2384 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
2386 TopoDS_Shape aShape1 = theShape1->GetValue();
2387 TopoDS_Shape aShape2 = theShape2->GetValue();
2389 if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
2391 TopTools_IndexedMapOfShape anIndices;
2392 TopExp::MapShapes(aShape1, anIndices);
2393 Handle(TColStd_HArray1OfInteger) anArray;
2395 TopTools_IndexedMapOfShape mapShape1;
2396 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
2398 Handle(GEOM_Object) anObj;
2399 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2400 TCollection_AsciiString anAsciiList, anEntry;
2402 TopTools_MapOfShape mapShape2;
2403 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2404 for (; exp.More(); exp.Next()) {
2405 TopoDS_Shape aSS = exp.Current();
2406 if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
2407 anArray = new TColStd_HArray1OfInteger(1,1);
2408 anArray->SetValue(1, anIndices.FindIndex(aSS));
2409 anObj = GetEngine()->AddSubShape(theShape1, anArray);
2410 aSeq->Append(anObj);
2412 // for python command
2413 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2414 anAsciiList += anEntry;
2419 if (aSeq->IsEmpty()) {
2420 SetErrorCode(NOT_FOUND_ANY);
2424 //Make a Python command
2425 anAsciiList.Trunc(anAsciiList.Length() - 1);
2427 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2429 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2430 << "] = geompy.GetSharedShapes(" << theShape1 << ", "
2431 << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
2437 //=======================================================================
2438 //function : GetSharedShapes
2441 // NOTE on the implementation
2443 // 1) Resulting sub-shapes are published as a children of the 1st input shape
2444 // from theShapes list. Due to this reason only direct sub-shapes of the 1st
2445 // shape can be contained in the result of the operation (i.e. shares between
2446 // 2nd/3rd, etc couples cannot be retrieved.
2447 // 2) An exception from above case is when a single compound is specified as an
2448 // input. In this case we search shares between its top-level content, so we
2449 // are able to search shares between all possible couples of shapes.
2450 // 3) Parameter theMultiShare controls what types of shares to search:
2451 // - True: get sub-shapes that are shared between ALL input shapes;
2452 // - False: get shares between couples of input sub-shapes (see points 1 and 2).
2454 // Thus, we have the following cases:
2455 // [1] theShapes = N shapes (N>1), theMultiShare = True
2456 // Result: sub-shapes that are shared by all theShapes
2457 // [2] theShapes = N shapes (N>1), theMultiShare = False
2458 // Result: sub-shapes of 1st shape from theShapes that are shared with any shape
2460 // [3] theShapes = 1 shape, theMultiShare = True
2461 // Result: sub-shapes that are shared by all top-level sub-objects of theShapes[0]
2462 // [4] theShapes = 1 shape, theMultiShare = False
2463 // Result: sub-shapes of all possible couples of all top-level sub-objects of
2465 //=======================================================================
2466 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2467 (std::list<Handle(GEOM_Object)> & theShapes,
2468 const Standard_Integer theShapeType,
2469 const bool theMultiShare)
2473 int aLen = theShapes.size();
2474 if (aLen < 1) return NULL;
2476 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
2478 // main object is always first in the input list
2479 // it is the object from which sub-shapes indices are taken
2480 // and where results are published
2481 Handle(GEOM_Object) aMainObj = *it;
2482 Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
2484 // collect all shapes from the input list (including first one) for processing
2485 TopTools_SequenceOfShape shapeSeq;
2486 for (; it != theShapes.end(); it++) {
2487 Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
2488 if (aRefShape.IsNull()) {
2489 SetErrorCode("NULL shape for GetSharedShapes");
2492 TopoDS_Shape aShape = aRefShape->GetValue();
2493 if (aShape.IsNull()) {
2494 SetErrorCode("NULL shape for GetSharedShapes");
2497 shapeSeq.Append( aShape );
2500 // if only single shape is specified as input
2501 // collect all ites top-level sub-shapes for processing
2502 if ( shapeSeq.Length() == 1 )
2504 TopoDS_Shape aShape = shapeSeq.First();
2506 for ( TopoDS_Iterator it( aShape ); it.More(); it.Next() )
2507 shapeSeq.Append( it.Value() );
2510 // map all sub-shapes in a main shape to their indices
2511 TopTools_IndexedMapOfShape anIndices;
2512 TopExp::MapShapes(aMainShape->GetValue(), anIndices);
2513 TopTools_MapOfShape mapShape;
2515 // find shared shapes
2517 // here we will collect all shares
2518 TopTools_ListOfShape aShared;
2520 // number of iterations
2521 int nbIters = theMultiShare || theShapes.size() > 1 ? 1 : shapeSeq.Length()-1;
2522 // numShares factor to search (i.e. by what nb of shapes each found sub-shape should be shared)
2523 int nbShares = theMultiShare ? shapeSeq.Length()-1 : 1;
2525 for ( int iter = 1; iter <= nbIters; iter++) {
2526 for ( int ind = iter+1; ind <= shapeSeq.Length(); ind++) {
2527 if ( ind-1+nbShares > shapeSeq.Length() ) break;
2528 TopoDS_Compound aCurrSelection;
2529 TopoDS_Shape aShape1 = shapeSeq.Value( iter );
2530 TopTools_IndexedMapOfShape mapSelected;
2531 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
2532 for ( int s = 0; s < nbShares; s++ ) {
2534 TopoDS_Compound aCompound;
2535 B.MakeCompound(aCompound);
2536 const TopoDS_Shape& aShape2 = shapeSeq.Value( ind+s );
2537 TopTools_MapOfShape mapShape2;
2538 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2539 for (; exp.More(); exp.Next()) {
2540 const TopoDS_Shape& aSS = exp.Current();
2541 if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
2542 B.Add(aCompound, aSS);
2545 mapSelected.Clear();
2546 aCurrSelection = aCompound;
2547 TopExp::MapShapes(aCurrSelection, TopAbs_ShapeEnum(theShapeType), mapSelected);
2549 TopoDS_Iterator itSel(aCurrSelection, Standard_True, Standard_True);
2550 for (; itSel.More(); itSel.Next()) {
2551 const TopoDS_Shape& aSS = itSel.Value();
2552 if (mapShape.Add(aSS) )
2553 aShared.Append(aSS);
2558 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2560 if (aShared.IsEmpty()){
2561 SetErrorCode(NOT_FOUND_ANY);
2565 // create GEOM_Object for each found shared shape (collected in aShared)
2566 TCollection_AsciiString anAsciiList;
2567 Handle(GEOM_Object) anObj;
2568 TopTools_ListIteratorOfListOfShape itSub (aShared);
2569 for (; itSub.More(); itSub.Next()) {
2570 TopoDS_Shape aValue = itSub.Value();
2571 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2572 anArray->SetValue(1, anIndices.FindIndex(aValue));
2573 anObj = GetEngine()->AddSubShape(aMainObj, anArray);
2574 aSeq->Append(anObj);
2576 // for python command
2577 TCollection_AsciiString anEntry;
2578 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2579 anAsciiList += anEntry;
2583 // make a Python command
2584 anAsciiList.Trunc(anAsciiList.Length() - 1);
2586 GEOM::TPythonDump pd (anObj->GetLastFunction());
2587 pd << "[" << anAsciiList.ToCString()
2588 << "] = geompy.GetSharedShapesMulti(";
2593 it = theShapes.begin();
2595 while (it != theShapes.end()) {
2596 pd << ", " << (*it++);
2601 pd << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theMultiShare << ")";
2607 //=============================================================================
2611 //=============================================================================
2612 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump,
2613 const GEOMAlgo_State theState)
2616 case GEOMAlgo_ST_IN:
2617 theDump << "GEOM.ST_IN";
2619 case GEOMAlgo_ST_OUT:
2620 theDump << "GEOM.ST_OUT";
2622 case GEOMAlgo_ST_ON:
2623 theDump << "GEOM.ST_ON";
2625 case GEOMAlgo_ST_ONIN:
2626 theDump << "GEOM.ST_ONIN";
2628 case GEOMAlgo_ST_ONOUT:
2629 theDump << "GEOM.ST_ONOUT";
2632 theDump << "GEOM.ST_UNKNOWN";
2638 //=======================================================================
2639 //function : checkTypeShapesOn
2641 * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
2642 * \param theShapeType - the shape type to check
2643 * \retval bool - result of the check
2645 //=======================================================================
2646 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
2648 if (theShapeType != TopAbs_VERTEX &&
2649 theShapeType != TopAbs_EDGE &&
2650 theShapeType != TopAbs_FACE &&
2651 theShapeType != TopAbs_SOLID) {
2652 SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
2658 //=======================================================================
2659 //function : makePlane
2661 * \brief Creates Geom_Plane
2662 * \param theAx1 - shape object defining plane parameters
2663 * \retval Handle(Geom_Surface) - resulting surface
2665 //=======================================================================
2666 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
2668 if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
2669 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2670 TopoDS_Vertex V1, V2;
2671 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2672 if (V1.IsNull() || V2.IsNull()) {
2673 SetErrorCode("Bad edge given for the plane normal vector");
2676 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2677 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2678 if (aVec.Magnitude() < Precision::Confusion()) {
2679 SetErrorCode("Vector with null magnitude given");
2682 return new Geom_Plane(aLoc, aVec);
2685 //=======================================================================
2686 //function : makeCylinder
2688 * \brief Creates Geom_CylindricalSurface
2689 * \param theAx1 - edge defining cylinder axis
2690 * \param theRadius - cylinder radius
2691 * \retval Handle(Geom_Surface) - resulting surface
2693 //=======================================================================
2694 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
2695 const Standard_Real theRadius)
2697 //Axis of the cylinder
2698 if (anAxis.ShapeType() != TopAbs_EDGE) {
2699 SetErrorCode("Not an edge given for the axis");
2702 TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
2703 TopoDS_Vertex V1, V2;
2704 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2705 if (V1.IsNull() || V2.IsNull()) {
2706 SetErrorCode("Bad edge given for the axis");
2709 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2710 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2711 if (aVec.Magnitude() < Precision::Confusion()) {
2712 SetErrorCode("Vector with null magnitude given");
2716 gp_Ax3 anAx3 (aLoc, aVec);
2717 return new Geom_CylindricalSurface(anAx3, theRadius);
2720 //=======================================================================
2721 //function : getShapesOnBoxIDs
2723 * \brief Find IDs of sub-shapes complying with given status about surface
2724 * \param theBox - the box to check state of sub-shapes against
2725 * \param theShape - the shape to explore
2726 * \param theShapeType - type of sub-shape of theShape
2727 * \param theState - required state
2728 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2730 //=======================================================================
2731 Handle(TColStd_HSequenceOfInteger)
2732 GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2733 const Handle(GEOM_Object)& theShape,
2734 const Standard_Integer theShapeType,
2735 GEOMAlgo_State theState)
2737 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2739 TopoDS_Shape aBox = theBox->GetValue();
2740 TopoDS_Shape aShape = theShape->GetValue();
2742 // Check presence of triangulation, build if need
2743 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2744 SetErrorCode("Cannot build triangulation on the shape");
2749 GEOMAlgo_FinderShapeOn2 aFinder;
2750 Standard_Real aTol = 0.0001; // default value
2752 Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
2753 aClsfBox->SetBox(aBox);
2755 aFinder.SetShape(aShape);
2756 aFinder.SetTolerance(aTol);
2757 aFinder.SetClsf(aClsfBox);
2758 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2759 aFinder.SetState(theState);
2762 // Interpret results
2763 Standard_Integer iErr = aFinder.ErrorStatus();
2764 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2766 MESSAGE(" iErr : " << iErr);
2767 TCollection_AsciiString aMsg (" iErr : ");
2768 aMsg += TCollection_AsciiString(iErr);
2772 Standard_Integer iWrn = aFinder.WarningStatus();
2773 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2775 MESSAGE(" *** iWrn : " << iWrn);
2778 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2780 if (listSS.Extent() < 1) {
2781 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2782 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2786 // Fill sequence of object IDs
2787 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2789 TopTools_IndexedMapOfShape anIndices;
2790 TopExp::MapShapes(aShape, anIndices);
2792 TopTools_ListIteratorOfListOfShape itSub (listSS);
2793 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2794 int id = anIndices.FindIndex(itSub.Value());
2795 aSeqOfIDs->Append(id);
2801 //=======================================================================
2802 //function : GetShapesOnBoxIDs
2804 * \brief Find sub-shapes complying with given status about surface
2805 * \param theBox - the box to check state of sub-shapes against
2806 * \param theShape - the shape to explore
2807 * \param theShapeType - type of sub-shape of theShape
2808 * \param theState - required state
2809 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2811 //=======================================================================
2812 Handle(TColStd_HSequenceOfInteger)
2813 GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2814 const Handle(GEOM_Object)& theShape,
2815 const Standard_Integer theShapeType,
2816 GEOMAlgo_State theState)
2818 // Find sub-shapes ids
2819 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2820 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2821 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2824 // The GetShapesOnBox() doesn't change object so no new function is required.
2825 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
2827 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2828 #ifdef DUMP_SUBSHAPE_IDS
2829 // Make a Python command
2830 GEOM::TPythonDump(aFunction, /*append=*/true)
2831 << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
2834 << TopAbs_ShapeEnum(theShapeType) << ", "
2836 #endif // DUMP_SUBSHAPE_IDS
2842 //=======================================================================
2843 //function : GetShapesOnBox
2845 * \brief Find sub-shapes complying with given status about surface
2846 * \param theBox - the box to check state of sub-shapes against
2847 * \param theShape - the shape to explore
2848 * \param theShapeType - type of sub-shape of theShape
2849 * \param theState - required state
2850 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2852 //=======================================================================
2853 Handle(TColStd_HSequenceOfTransient)
2854 GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
2855 const Handle(GEOM_Object)& theShape,
2856 const Standard_Integer theShapeType,
2857 GEOMAlgo_State theState)
2859 // Find sub-shapes ids
2860 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2861 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2862 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2865 // Find objects by indices
2866 TCollection_AsciiString anAsciiList;
2867 Handle(TColStd_HSequenceOfTransient) aSeq;
2868 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2869 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2872 // Make a Python command
2874 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2875 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2877 GEOM::TPythonDump(aFunction)
2878 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
2881 << TopAbs_ShapeEnum(theShapeType) << ", "
2888 //=======================================================================
2889 //function : getShapesOnShapeIDs
2891 * \brief Find IDs of sub-shapes complying with given status about surface
2892 * \param theCheckShape - the shape to check state of sub-shapes against
2893 * \param theShape - the shape to explore
2894 * \param theShapeType - type of sub-shape of theShape
2895 * \param theState - required state
2896 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2898 //=======================================================================
2899 Handle(TColStd_HSequenceOfInteger)
2900 GEOMImpl_IShapesOperations::getShapesOnShapeIDs
2901 (const Handle(GEOM_Object)& theCheckShape,
2902 const Handle(GEOM_Object)& theShape,
2903 const Standard_Integer theShapeType,
2904 GEOMAlgo_State theState)
2906 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2908 TopoDS_Shape aCheckShape = theCheckShape->GetValue();
2909 TopoDS_Shape aShape = theShape->GetValue();
2910 TopTools_ListOfShape res;
2912 // Check presence of triangulation, build if need
2913 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2914 SetErrorCode("Cannot build triangulation on the shape");
2918 // Compute classification tolerance.
2919 TopTools_IndexedMapOfShape aMapVtx;
2920 Standard_Real aTol = Precision::Confusion();
2922 TopExp::MapShapes(aShape, TopAbs_VERTEX, aMapVtx);
2925 Standard_Integer aNbVtx = aMapVtx.Extent();
2927 for (i = 1; i <= aNbVtx; ++i) {
2928 const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(i));
2929 const Standard_Real aVtxTol = BRep_Tool::Tolerance(aVtx);
2931 if (aTol < aVtxTol) {
2936 // Bound the tolerance value.
2937 if (aTol > 0.0001) {
2942 GEOMAlgo_FinderShapeOn2 aFinder;
2944 Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
2945 aClsfSolid->SetShape(aCheckShape);
2947 aFinder.SetShape(aShape);
2948 aFinder.SetTolerance(aTol);
2949 aFinder.SetClsf(aClsfSolid);
2950 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2951 aFinder.SetState(theState);
2954 // Interpret results
2955 Standard_Integer iErr = aFinder.ErrorStatus();
2956 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2959 SetErrorCode("theCheckShape must be a solid");
2962 MESSAGE(" iErr : " << iErr);
2963 TCollection_AsciiString aMsg (" iErr : ");
2964 aMsg += TCollection_AsciiString(iErr);
2969 Standard_Integer iWrn = aFinder.WarningStatus();
2970 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2972 MESSAGE(" *** iWrn : " << iWrn);
2975 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2977 if (listSS.Extent() < 1) {
2978 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2979 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2982 // Fill sequence of object IDs
2983 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2985 TopTools_IndexedMapOfShape anIndices;
2986 TopExp::MapShapes(aShape, anIndices);
2988 TopTools_ListIteratorOfListOfShape itSub (listSS);
2989 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2990 int id = anIndices.FindIndex(itSub.Value());
2991 aSeqOfIDs->Append(id);
2997 //=======================================================================
2998 //function : GetShapesOnShapeIDs
3000 * \brief Find sub-shapes complying with given status about surface
3001 * \param theCheckShape - the shape to check state of sub-shapes against
3002 * \param theShape - the shape to explore
3003 * \param theShapeType - type of sub-shape of theShape
3004 * \param theState - required state
3005 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3007 //=======================================================================
3008 Handle(TColStd_HSequenceOfInteger)
3009 GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
3010 (const Handle(GEOM_Object)& theCheckShape,
3011 const Handle(GEOM_Object)& theShape,
3012 const Standard_Integer theShapeType,
3013 GEOMAlgo_State theState)
3015 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3016 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
3018 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3021 // The GetShapesOnShape() doesn't change object so no new function is required.
3022 Handle(GEOM_Function) aFunction =
3023 GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
3025 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
3026 #ifdef DUMP_SUBSHAPE_IDS
3027 // Make a Python command
3028 GEOM::TPythonDump(aFunction, /*append=*/true)
3029 << "listShapesOnShapeIDs = geompy.GetShapesOnShapeIDs("
3030 << theCheckShape << ", "
3032 << TopAbs_ShapeEnum(theShapeType) << ", "
3034 #endif // DUMP_SUBSHAPE_IDS
3040 //=======================================================================
3041 //function : GetShapesOnShape
3043 * \brief Find sub-shapes complying with given status about surface
3044 * \param theCheckShape - the shape to check state of sub-shapes against
3045 * \param theShape - the shape to explore
3046 * \param theShapeType - type of sub-shape of theShape
3047 * \param theState - required state
3048 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
3050 //=======================================================================
3051 Handle(TColStd_HSequenceOfTransient)
3052 GEOMImpl_IShapesOperations::GetShapesOnShape
3053 (const Handle(GEOM_Object)& theCheckShape,
3054 const Handle(GEOM_Object)& theShape,
3055 const Standard_Integer theShapeType,
3056 GEOMAlgo_State theState)
3058 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3059 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
3060 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3063 // Find objects by indices
3064 TCollection_AsciiString anAsciiList;
3065 Handle(TColStd_HSequenceOfTransient) aSeq;
3066 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
3068 if ( aSeq.IsNull() || aSeq->IsEmpty() )
3071 // Make a Python command
3073 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3074 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3076 GEOM::TPythonDump(aFunction)
3077 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
3078 << theCheckShape << ", "
3080 << TopAbs_ShapeEnum(theShapeType) << ", "
3087 //=======================================================================
3088 //function : GetShapesOnShapeAsCompound
3089 //=======================================================================
3090 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
3091 (const Handle(GEOM_Object)& theCheckShape,
3092 const Handle(GEOM_Object)& theShape,
3093 const Standard_Integer theShapeType,
3094 GEOMAlgo_State theState)
3096 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3097 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
3099 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3102 // Find objects by indices
3103 TCollection_AsciiString anAsciiList;
3104 Handle(TColStd_HSequenceOfTransient) aSeq;
3105 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
3107 if ( aSeq.IsNull() || aSeq->IsEmpty() )
3110 TopoDS_Compound aCompound;
3112 B.MakeCompound(aCompound);
3114 for(; i<=aSeq->Length(); i++) {
3115 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
3116 TopoDS_Shape aShape_i = anObj->GetValue();
3117 B.Add(aCompound,aShape_i);
3120 //Add a new result object
3121 Handle(GEOM_Object) aRes = GetEngine()->AddObject(GEOM_SHAPES_ON_SHAPE);
3122 Handle(GEOM_Function) aFunction =
3123 aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
3124 aFunction->SetValue(aCompound);
3127 aSeq->Append( theCheckShape->GetLastFunction() );
3128 aSeq->Append( theShape->GetLastFunction() );
3130 GEOMImpl_IShapes aCI( aFunction );
3131 aCI.SetShapes( aSeq );
3132 aCI.SetSubShapeType( theShapeType );
3133 aCI.SetTolerance( theState );
3135 GEOM::TPythonDump(aFunction)
3136 << aRes << " = geompy.GetShapesOnShapeAsCompound("
3137 << theCheckShape << ", "
3139 << TopAbs_ShapeEnum(theShapeType) << ", "
3147 //=============================================================================
3149 * GetSubShapeEdgeSorted
3151 //=============================================================================
3152 Handle(TColStd_HSequenceOfTransient)
3153 GEOMImpl_IShapesOperations::GetSubShapeEdgeSorted
3154 (const Handle(GEOM_Object) &theShape,
3155 const Handle(GEOM_Object) &theStartPoint)
3157 // Get the sorted edges indices.
3158 Handle(TColStd_HSequenceOfInteger) aSortedIDs =
3159 getSubShapeEdgeSortedIDs(theShape, theStartPoint);
3161 // Get object by indices.
3162 TCollection_AsciiString anAsciiList;
3163 Handle(TColStd_HSequenceOfTransient) aSeq =
3164 getObjectsShapesOn(theShape, aSortedIDs, anAsciiList);
3166 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3167 SetErrorCode("Empty sequence of edges");
3171 // Make a Python command
3172 Handle(GEOM_Object) anObj =
3173 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3174 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3176 GEOM::TPythonDump(aFunction)
3177 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapeEdgeSorted("
3178 << theShape << ", " << theStartPoint << ")";
3185 //=============================================================================
3187 * GetSubShapesWithTolerance
3189 //=============================================================================
3190 Handle(TColStd_HSequenceOfTransient)
3191 GEOMImpl_IShapesOperations::GetSubShapesWithTolerance
3192 (const Handle(GEOM_Object) &theShape,
3193 const Standard_Integer theShapeType,
3194 const GEOMUtils::ComparisonCondition theCondition,
3195 const Standard_Real theTolerance)
3197 if (theShape.IsNull()) {
3198 SetErrorCode("NULL GEOM object");
3202 TopoDS_Shape aShape = theShape->GetValue();
3204 if (aShape.IsNull()) {
3205 SetErrorCode("NULL Shape");
3209 if (theShapeType != TopAbs_FACE && theShapeType != TopAbs_EDGE &&
3210 theShapeType != TopAbs_VERTEX && aShape.ShapeType() >= theShapeType) {
3211 SetErrorCode("Invalid shape type");
3215 TopTools_IndexedMapOfShape anIndices;
3216 TopTools_MapOfShape aMapFence;
3217 TopExp_Explorer anExp(aShape,
3218 (TopAbs_ShapeEnum) theShapeType);
3219 Handle(TColStd_HSequenceOfInteger) anIDs = new TColStd_HSequenceOfInteger;
3221 TopExp::MapShapes(aShape, anIndices);
3223 for (; anExp.More(); anExp.Next()) {
3224 const TopoDS_Shape &aSubShape = anExp.Current();
3226 if (aMapFence.Add(aSubShape)) {
3227 // Compute tolerance
3228 Standard_Real aTolerance = -1.;
3230 switch (aSubShape.ShapeType()) {
3232 aTolerance = BRep_Tool::Tolerance(TopoDS::Face(aSubShape));
3235 aTolerance = BRep_Tool::Tolerance(TopoDS::Edge(aSubShape));
3238 aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aSubShape));
3244 if (aTolerance < 0.) {
3248 // Compare the tolerance with reference value.
3249 if (GEOMUtils::IsFitCondition (theCondition, aTolerance, theTolerance)) {
3250 anIDs->Append(anIndices.FindIndex(aSubShape));
3255 if (anIDs->IsEmpty()) {
3256 SetErrorCode("Empty sequence of sub-shapes");
3260 // Get objects by indices.
3261 TCollection_AsciiString anAsciiList;
3262 Handle(TColStd_HSequenceOfTransient) aSeq =
3263 getObjectsShapesOn(theShape, anIDs, anAsciiList);
3265 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3266 SetErrorCode("Empty sequence of edges");
3270 // Make a Python command
3271 Handle(GEOM_Object) anObj =
3272 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3273 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3275 GEOM::TPythonDump(aFunction)
3276 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapesWithTolerance("
3277 << theShape << ", " << theShapeType << ", " << theCondition << ", "
3278 << theTolerance << ")";
3285 //=============================================================================
3289 //=============================================================================
3290 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeExtraction
3291 (const Handle(GEOM_Object) &theShape,
3292 const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs,
3293 std::list<ExtractionStat> &theStats)
3297 if (theShape.IsNull()) {
3301 //Add a new Result object
3302 Handle(GEOM_Object) aResult =
3303 GetEngine()->AddObject(GEOM_EXTRACTION);
3305 //Add a new Extraction function
3306 Handle(GEOM_Function) aFunction =
3307 aResult->AddFunction(GEOMImpl_ShapeDriver::GetID(), EXTRACTION);
3309 //Check if the function is set correctly
3310 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
3314 Handle(GEOM_Function) aShape = theShape->GetLastFunction();
3316 if (aShape.IsNull()) {
3320 GEOMImpl_IExtract aCI (aFunction);
3322 aCI.SetShape(aShape);
3323 aCI.SetSubShapeIDs(theSubShapeIDs);
3325 //Compute the Edge value
3328 if (!GetSolver()->ComputeFunction(aFunction)) {
3329 SetErrorCode("Shape driver failed");
3334 catch (Standard_Failure& aFail) {
3335 SetErrorCode(aFail.GetMessageString());
3340 // Fill in statistics.
3343 Handle(TColStd_HArray1OfInteger) aStatIDsArray[3] =
3344 { aCI.GetRemovedIDs(), aCI.GetModifiedIDs(), aCI.GetAddedIDs() };
3348 for (j = 0; j < 3; ++j) {
3349 if (!aStatIDsArray[j].IsNull()) {
3350 const int anUpperID = aStatIDsArray[j]->Upper();
3351 ExtractionStat aStat;
3353 for (i = aStatIDsArray[j]->Lower(); i <= anUpperID; ++i) {
3354 aStat.indices.push_back(aStatIDsArray[j]->Value(i));
3357 aStat.type = (ExtractionStatType) j;
3358 theStats.push_back(aStat);
3362 //Make a Python command
3363 GEOM::TPythonDump pd(aFunction);
3365 pd << aResult << " = geompy.MakeExtraction(" << theShape << ", [";
3367 if (!theSubShapeIDs.IsNull()) {
3368 const int aNbIDs = theSubShapeIDs->Upper();
3370 for (i = theSubShapeIDs->Lower(); i < aNbIDs; ++i) {
3371 pd << theSubShapeIDs->Value(i) << ", ";
3374 // Dump the last value without a comma.
3375 pd << theSubShapeIDs->Value(i);
3385 //=======================================================================
3386 //function : getShapesOnSurfaceIDs
3388 * \brief Find IDs of sub-shapes complying with given status about surface
3389 * \param theSurface - the surface to check state of sub-shapes against
3390 * \param theShape - the shape to explore
3391 * \param theShapeType - type of sub-shape of theShape
3392 * \param theState - required state
3393 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3395 //=======================================================================
3396 Handle(TColStd_HSequenceOfInteger)
3397 GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
3398 const TopoDS_Shape& theShape,
3399 TopAbs_ShapeEnum theShapeType,
3400 GEOMAlgo_State theState)
3402 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3404 // Check presence of triangulation, build if need
3405 if (theShapeType != TopAbs_VERTEX &&
3406 !GEOMUtils::CheckTriangulation(theShape)) {
3407 SetErrorCode("Cannot build triangulation on the shape");
3411 // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
3412 // Compute tolerance
3413 Standard_Real T, VertMax = -RealLast();
3416 for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
3417 TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
3418 T = BRep_Tool::Tolerance(Vertex);
3423 catch (Standard_Failure& aFail) {
3424 SetErrorCode(aFail.GetMessageString());
3427 // END: Mantis issue 0020961
3430 GEOMAlgo_FinderShapeOn2 aFinder;
3431 Handle(GEOMAlgo_ClsfSurf) aClsfSurf = new GEOMAlgo_ClsfSurf;
3432 Standard_Real aTol = VertMax; // Mantis issue 0020961
3434 aClsfSurf->SetSurface(theSurface);
3435 aFinder.SetShape(theShape);
3436 aFinder.SetTolerance(aTol);
3437 aFinder.SetClsf(aClsfSurf);
3438 aFinder.SetShapeType(theShapeType);
3439 aFinder.SetState(theState);
3441 // Sets the minimal number of inner points for the faces that do not have own
3442 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
3444 aFinder.SetNbPntsMin(3);
3445 // Sets the maximal number of inner points for edges or faces.
3446 // It is useful for the cases when this number is very big (e.g =2000) to improve
3447 // the performance. If this value =0, all inner points will be taken into account.
3449 aFinder.SetNbPntsMax(100);
3453 // Interpret results
3454 Standard_Integer iErr = aFinder.ErrorStatus();
3455 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
3457 MESSAGE(" iErr : " << iErr);
3458 TCollection_AsciiString aMsg (" iErr : ");
3459 aMsg += TCollection_AsciiString(iErr);
3463 Standard_Integer iWrn = aFinder.WarningStatus();
3464 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
3466 MESSAGE(" *** iWrn : " << iWrn);
3469 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
3471 if (listSS.Extent() < 1) {
3472 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
3473 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
3477 // Fill sequence of object IDs
3478 aSeqOfIDs = new TColStd_HSequenceOfInteger;
3480 TopTools_IndexedMapOfShape anIndices;
3481 TopExp::MapShapes(theShape, anIndices);
3483 TopTools_ListIteratorOfListOfShape itSub (listSS);
3484 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3485 int id = anIndices.FindIndex(itSub.Value());
3486 aSeqOfIDs->Append(id);
3492 //=======================================================================
3493 //function : getObjectsShapesOn
3495 * \brief Find shape objects and their entries by their ids
3496 * \param theShapeIDs - incoming shape ids
3497 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3498 * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
3500 //=======================================================================
3501 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
3502 getObjectsShapesOn(const Handle(GEOM_Object)& theShape,
3503 const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
3504 TCollection_AsciiString & theShapeEntries)
3506 Handle(TColStd_HSequenceOfTransient) aSeq;
3508 if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
3510 aSeq = new TColStd_HSequenceOfTransient;
3511 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3512 TCollection_AsciiString anEntry;
3513 for ( int i = 1; i <= theShapeIDs->Length(); ++i )
3515 anArray->SetValue(1, theShapeIDs->Value( i ));
3516 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3517 aSeq->Append( anObj );
3519 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3520 if ( i != 1 ) theShapeEntries += ",";
3521 theShapeEntries += anEntry;
3527 //=============================================================================
3529 * getSubShapeEdgeSortedIDs
3531 //=============================================================================
3532 Handle(TColStd_HSequenceOfInteger)
3533 GEOMImpl_IShapesOperations::getSubShapeEdgeSortedIDs
3534 (const Handle(GEOM_Object) &theShape,
3535 const Handle(GEOM_Object) &theStartPoint)
3537 Handle(TColStd_HSequenceOfInteger) aResult;
3539 if (theShape.IsNull() || theStartPoint.IsNull()) {
3540 SetErrorCode("NULL GEOM object");
3544 const TopoDS_Shape aShape = theShape->GetValue();
3545 const TopoDS_Shape aStartPoint = theStartPoint->GetValue();
3547 if (aShape.IsNull() || aStartPoint.IsNull()) {
3548 SetErrorCode("NULL Shape");
3552 if (aStartPoint.ShapeType() != TopAbs_VERTEX) {
3553 SetErrorCode("Starting point is not a vertex");
3557 TopExp_Explorer anExp(aShape, TopAbs_EDGE);
3558 TopTools_MapOfShape aMapFence;
3559 TopTools_ListOfShape anEdges;
3561 for (; anExp.More(); anExp.Next()) {
3562 const TopoDS_Shape &anEdge = anExp.Current();
3564 if (aMapFence.Add(anEdge)) {
3565 anEdges.Append(anEdge);
3569 if (anEdges.IsEmpty()) {
3570 SetErrorCode("Shape doesn't contain edges");
3574 // Step 1: Sort edges
3575 GEOMUtils::SortShapes(anEdges, Standard_False);
3577 TopTools_ListIteratorOfListOfShape anIter(anEdges);
3578 TopoDS_Vertex aV[2];
3579 TopTools_DataMapOfShapeListOfShape aMapVE;
3581 // Step 2: Fill the map vertex - list of edges.
3582 for (; anIter.More(); anIter.Next()) {
3583 TopoDS_Edge anEdge = TopoDS::Edge(anIter.Value());
3585 TopExp::Vertices(anEdge, aV[0], aV[1]);
3587 const Standard_Integer aNbV = aV[0].IsSame(aV[1]) ? 1 : 2;
3590 for (i = 0; i < aNbV; ++i) {
3591 if (aV[i].IsNull() == Standard_False) {
3592 if (!aMapVE.IsBound(aV[i])) {
3593 // There is no this vertex in the map.
3594 aMapVE.Bind(aV[i], TopTools_ListOfShape());
3597 // Add the edge to the list bound with the vertex aV[i].
3598 TopTools_ListOfShape &aLEdges = aMapVE.ChangeFind(aV[i]);
3600 aLEdges.Append(anEdge);
3605 // Step 3: Find starting point in aMapVE.
3606 TopoDS_Vertex aStartVtx = TopoDS::Vertex(aStartPoint);
3608 if (!aMapVE.IsBound(aStartVtx)) {
3609 aStartVtx = getSameVertex(aShape, aStartVtx);
3611 if (aStartVtx.IsNull()) {
3612 SetErrorCode("Invalid Starting point");
3617 TopTools_IndexedMapOfShape anIndices;
3618 TopTools_MapOfShape aMapVFence;
3619 TopoDS_Shape aCurVtx = aStartVtx;
3620 TopoDS_Edge aCurEdge =
3621 TopoDS::Edge(aMapVE.Find(aCurVtx).First());
3623 aResult = new TColStd_HSequenceOfInteger;
3624 TopExp::MapShapes(aShape, anIndices);
3626 // Step 4: Fill the list of sorted edges.
3627 while (aMapVFence.Add(aCurVtx)) {
3628 // Append the ID of the current edge to the list of sorted.
3629 aResult->Append(anIndices.FindIndex(aCurEdge));
3630 TopExp::Vertices(aCurEdge, aV[0], aV[1]);
3632 // Get the next vertex.
3633 if (aCurVtx.IsSame(aV[0])) {
3634 if (aCurVtx.IsSame(aV[1])) {
3635 // There is no next vertex.
3644 if (aCurVtx.IsNull()) {
3645 // There is no next vertex.
3649 // Get the next edge.
3650 const TopTools_ListOfShape &aLEdges = aMapVE.Find(aCurVtx);
3651 TopTools_ListIteratorOfListOfShape anEIter(aLEdges);
3653 for (; anEIter.More(); anEIter.Next()) {
3654 const TopoDS_Shape &aLocalEdge = anEIter.Value();
3656 if (aLocalEdge.IsNull() == Standard_False) {
3657 if (!aCurEdge.IsSame(aLocalEdge)) {
3658 aCurEdge = TopoDS::Edge(aLocalEdge);
3664 if (!anEIter.More()) {
3665 // There is no next edge.
3673 //=======================================================================
3674 //function : getShapesOnSurface
3676 * \brief Find sub-shapes complying with given status about surface
3677 * \param theSurface - the surface to check state of sub-shapes against
3678 * \param theShape - the shape to explore
3679 * \param theShapeType - type of sub-shape of theShape
3680 * \param theState - required state
3681 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3682 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3684 //=======================================================================
3685 Handle(TColStd_HSequenceOfTransient)
3686 GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
3687 const Handle(GEOM_Object)& theShape,
3688 TopAbs_ShapeEnum theShapeType,
3689 GEOMAlgo_State theState,
3690 TCollection_AsciiString & theShapeEntries)
3692 // Find sub-shapes ids
3693 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3694 getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
3695 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3698 return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
3701 //=============================================================================
3705 //=============================================================================
3706 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
3707 (const Handle(GEOM_Object)& theShape,
3708 const Standard_Integer theShapeType,
3709 const Handle(GEOM_Object)& theAx1,
3710 const GEOMAlgo_State theState)
3714 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3716 TopoDS_Shape aShape = theShape->GetValue();
3717 TopoDS_Shape anAx1 = theAx1->GetValue();
3719 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3721 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3722 if ( !checkTypeShapesOn( theShapeType ))
3726 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3727 if ( aPlane.IsNull() )
3731 TCollection_AsciiString anAsciiList;
3732 Handle(TColStd_HSequenceOfTransient) aSeq;
3733 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3734 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3737 // Make a Python command
3739 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3740 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3742 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3743 << "] = geompy.GetShapesOnPlane(" << theShape << ", "
3744 << aShapeType << ", " << theAx1 << ", " << theState << ")";
3750 //=============================================================================
3752 * GetShapesOnPlaneWithLocation
3754 //=============================================================================
3755 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
3756 (const Handle(GEOM_Object)& theShape,
3757 const Standard_Integer theShapeType,
3758 const Handle(GEOM_Object)& theAx1,
3759 const Handle(GEOM_Object)& thePnt,
3760 const GEOMAlgo_State theState)
3764 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3766 TopoDS_Shape aShape = theShape->GetValue();
3767 TopoDS_Shape anAx1 = theAx1->GetValue();
3768 TopoDS_Shape anPnt = thePnt->GetValue();
3770 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3772 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3773 if ( !checkTypeShapesOn( theShapeType ))
3777 if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
3778 TopoDS_Vertex V1, V2, V3;
3779 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3780 TopExp::Vertices(anEdge, V1, V2, Standard_True);
3782 if (V1.IsNull() || V2.IsNull()) {
3783 SetErrorCode("Bad edge given for the plane normal vector");
3786 V3 = TopoDS::Vertex(anPnt);
3789 SetErrorCode("Bad vertex given for the plane location");
3792 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3793 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3795 if (aVec.Magnitude() < Precision::Confusion()) {
3796 SetErrorCode("Vector with null magnitude given");
3799 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3801 if ( aPlane.IsNull() )
3805 TCollection_AsciiString anAsciiList;
3806 Handle(TColStd_HSequenceOfTransient) aSeq;
3807 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3808 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3811 // Make a Python command
3813 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3814 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3816 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3817 << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
3818 << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
3824 //=============================================================================
3826 * GetShapesOnCylinder
3828 //=============================================================================
3829 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
3830 (const Handle(GEOM_Object)& theShape,
3831 const Standard_Integer theShapeType,
3832 const Handle(GEOM_Object)& theAxis,
3833 const Standard_Real theRadius,
3834 const GEOMAlgo_State theState)
3838 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3840 TopoDS_Shape aShape = theShape->GetValue();
3841 TopoDS_Shape anAxis = theAxis->GetValue();
3843 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3845 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3846 if ( !checkTypeShapesOn( aShapeType ))
3849 // Create a cylinder surface
3850 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3851 if ( aCylinder.IsNull() )
3855 TCollection_AsciiString anAsciiList;
3856 Handle(TColStd_HSequenceOfTransient) aSeq;
3857 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3858 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3861 // Make a Python command
3863 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3864 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3866 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3867 << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
3868 << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
3874 //=============================================================================
3876 * GetShapesOnCylinderWithLocation
3878 //=============================================================================
3879 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
3880 (const Handle(GEOM_Object)& theShape,
3881 const Standard_Integer theShapeType,
3882 const Handle(GEOM_Object)& theAxis,
3883 const Handle(GEOM_Object)& thePnt,
3884 const Standard_Real theRadius,
3885 const GEOMAlgo_State theState)
3889 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3891 TopoDS_Shape aShape = theShape->GetValue();
3892 TopoDS_Shape anAxis = theAxis->GetValue();
3893 TopoDS_Shape aPnt = thePnt->GetValue();
3895 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3897 if (aPnt.ShapeType() != TopAbs_VERTEX )
3899 SetErrorCode("Bottom location point must be vertex");
3903 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3904 if ( !checkTypeShapesOn( aShapeType ))
3907 // Create a cylinder surface
3908 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3909 if ( aCylinder.IsNull() )
3912 // translate the surface
3913 Handle(Geom_CylindricalSurface) aCylSurface =
3914 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3915 if ( aCylSurface.IsNull() )
3917 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3920 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3921 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3922 aCylinder->Translate( fromLoc, toLoc );
3925 TCollection_AsciiString anAsciiList;
3926 Handle(TColStd_HSequenceOfTransient) aSeq;
3927 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3928 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3931 // Make a Python command
3933 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3934 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3936 GEOM::TPythonDump(aFunction)
3937 << "[" << anAsciiList.ToCString()
3938 << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
3939 << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
3945 //=============================================================================
3949 //=============================================================================
3950 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
3951 (const Handle(GEOM_Object)& theShape,
3952 const Standard_Integer theShapeType,
3953 const Handle(GEOM_Object)& theCenter,
3954 const Standard_Real theRadius,
3955 const GEOMAlgo_State theState)
3959 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3961 TopoDS_Shape aShape = theShape->GetValue();
3962 TopoDS_Shape aCenter = theCenter->GetValue();
3964 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3966 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3967 if ( !checkTypeShapesOn( aShapeType ))
3970 // Center of the sphere
3971 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3972 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3974 gp_Ax3 anAx3 (aLoc, gp::DZ());
3975 Handle(Geom_SphericalSurface) aSphere =
3976 new Geom_SphericalSurface(anAx3, theRadius);
3979 TCollection_AsciiString anAsciiList;
3980 Handle(TColStd_HSequenceOfTransient) aSeq;
3981 aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
3982 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3985 // Make a Python command
3987 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3988 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3990 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3991 << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
3992 << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
3998 //=============================================================================
4000 * GetShapesOnPlaneIDs
4002 //=============================================================================
4003 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
4004 (const Handle(GEOM_Object)& theShape,
4005 const Standard_Integer theShapeType,
4006 const Handle(GEOM_Object)& theAx1,
4007 const GEOMAlgo_State theState)
4011 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
4013 TopoDS_Shape aShape = theShape->GetValue();
4014 TopoDS_Shape anAx1 = theAx1->GetValue();
4016 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
4018 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4019 if ( !checkTypeShapesOn( aShapeType ))
4023 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
4024 if ( aPlane.IsNull() )
4028 Handle(TColStd_HSequenceOfInteger) aSeq;
4029 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
4031 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
4032 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
4034 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4035 #ifdef DUMP_SUBSHAPE_IDS
4036 // Make a Python command
4037 GEOM::TPythonDump(aFunction, /*append=*/true)
4038 << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
4039 << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
4040 #endif // DUMP_SUBSHAPE_IDS
4046 //=============================================================================
4048 * GetShapesOnPlaneWithLocationIDs
4050 //=============================================================================
4051 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
4052 (const Handle(GEOM_Object)& theShape,
4053 const Standard_Integer theShapeType,
4054 const Handle(GEOM_Object)& theAx1,
4055 const Handle(GEOM_Object)& thePnt,
4056 const GEOMAlgo_State theState)
4060 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
4062 TopoDS_Shape aShape = theShape->GetValue();
4063 TopoDS_Shape anAx1 = theAx1->GetValue();
4064 TopoDS_Shape anPnt = thePnt->GetValue();
4066 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
4068 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4069 if ( !checkTypeShapesOn( aShapeType ))
4073 if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
4074 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
4075 TopoDS_Vertex V1, V2, V3;
4076 TopExp::Vertices(anEdge, V1, V2, Standard_True);
4077 if (V1.IsNull() || V2.IsNull()) {
4078 SetErrorCode("Bad edge given for the plane normal vector");
4081 V3 = TopoDS::Vertex(anPnt);
4083 SetErrorCode("Bad vertex given for the plane location");
4086 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
4087 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
4088 if (aVec.Magnitude() < Precision::Confusion()) {
4089 SetErrorCode("Vector with null magnitude given");
4093 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
4094 if ( aPlane.IsNull() )
4098 Handle(TColStd_HSequenceOfInteger) aSeq;
4099 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
4101 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
4102 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
4104 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4105 #ifdef DUMP_SUBSHAPE_IDS
4106 // Make a Python command
4107 GEOM::TPythonDump(aFunction, /*append=*/true)
4108 << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
4109 << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")";
4110 #endif // DUMP_SUBSHAPE_IDS
4116 //=============================================================================
4118 * GetShapesOnCylinderIDs
4120 //=============================================================================
4121 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
4122 (const Handle(GEOM_Object)& theShape,
4123 const Standard_Integer theShapeType,
4124 const Handle(GEOM_Object)& theAxis,
4125 const Standard_Real theRadius,
4126 const GEOMAlgo_State theState)
4130 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
4132 TopoDS_Shape aShape = theShape->GetValue();
4133 TopoDS_Shape anAxis = theAxis->GetValue();
4135 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
4137 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4138 if ( !checkTypeShapesOn( aShapeType ))
4141 // Create a cylinder surface
4142 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4143 if ( aCylinder.IsNull() )
4147 Handle(TColStd_HSequenceOfInteger) aSeq;
4148 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4150 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4151 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
4153 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4154 #ifdef DUMP_SUBSHAPE_IDS
4155 // Make a Python command
4156 GEOM::TPythonDump(aFunction, /*append=*/true)
4157 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
4158 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4159 << theRadius << ", " << theState << ")";
4160 #endif // DUMP_SUBSHAPE_IDS
4166 //=============================================================================
4168 * GetShapesOnCylinderWithLocationIDs
4170 //=============================================================================
4171 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
4172 (const Handle(GEOM_Object)& theShape,
4173 const Standard_Integer theShapeType,
4174 const Handle(GEOM_Object)& theAxis,
4175 const Handle(GEOM_Object)& thePnt,
4176 const Standard_Real theRadius,
4177 const GEOMAlgo_State theState)
4181 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
4183 TopoDS_Shape aShape = theShape->GetValue();
4184 TopoDS_Shape anAxis = theAxis->GetValue();
4185 TopoDS_Shape aPnt = thePnt->GetValue();
4187 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
4189 if (aPnt.ShapeType() != TopAbs_VERTEX )
4191 SetErrorCode("Bottom location point must be vertex");
4195 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4196 if ( !checkTypeShapesOn( aShapeType ))
4199 // Create a cylinder surface
4200 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4201 if ( aCylinder.IsNull() )
4204 // translate the surface
4205 Handle(Geom_CylindricalSurface) aCylSurface =
4206 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
4207 if ( aCylSurface.IsNull() )
4209 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
4212 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
4213 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
4214 aCylinder->Translate( fromLoc, toLoc );
4217 Handle(TColStd_HSequenceOfInteger) aSeq;
4218 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4220 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4221 Handle(GEOM_Function) aFunction =
4222 GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
4224 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4225 #ifdef DUMP_SUBSHAPE_IDS
4226 // Make a Python command
4227 GEOM::TPythonDump(aFunction, /*append=*/true)
4228 << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
4229 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4230 << thePnt << ", " << theRadius << ", " << theState << ")";
4231 #endif // DUMP_SUBSHAPE_IDS
4237 //=============================================================================
4239 * GetShapesOnSphereIDs
4241 //=============================================================================
4242 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
4243 (const Handle(GEOM_Object)& theShape,
4244 const Standard_Integer theShapeType,
4245 const Handle(GEOM_Object)& theCenter,
4246 const Standard_Real theRadius,
4247 const GEOMAlgo_State theState)
4251 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
4253 TopoDS_Shape aShape = theShape->GetValue();
4254 TopoDS_Shape aCenter = theCenter->GetValue();
4256 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
4258 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4259 if ( !checkTypeShapesOn( aShapeType ))
4262 // Center of the sphere
4263 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
4264 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
4266 gp_Ax3 anAx3 (aLoc, gp::DZ());
4267 Handle(Geom_SphericalSurface) aSphere =
4268 new Geom_SphericalSurface(anAx3, theRadius);
4271 Handle(TColStd_HSequenceOfInteger) aSeq;
4272 aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
4274 // The GetShapesOnSphere() doesn't change object so no new function is required.
4275 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
4277 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4278 #ifdef DUMP_SUBSHAPE_IDS
4279 // Make a Python command
4280 GEOM::TPythonDump(aFunction, /*append=*/true)
4281 << "listShapesOnSphere = geompy.GetShapesOnSphereIDs"
4282 << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
4283 << theRadius << ", " << theState << ")";
4284 #endif // DUMP_SUBSHAPE_IDS
4290 //=======================================================================
4291 //function : getShapesOnQuadrangleIDs
4293 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4294 * \param theShape - the shape to explore
4295 * \param theShapeType - type of sub-shape of theShape
4296 * \param theTopLeftPoint - top left quadrangle corner
4297 * \param theTopRightPoint - top right quadrangle corner
4298 * \param theBottomLeftPoint - bottom left quadrangle corner
4299 * \param theBottomRightPoint - bottom right quadrangle corner
4300 * \param theState - required state
4301 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4303 //=======================================================================
4304 Handle(TColStd_HSequenceOfInteger)
4305 GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4306 const Standard_Integer theShapeType,
4307 const Handle(GEOM_Object)& theTopLeftPoint,
4308 const Handle(GEOM_Object)& theTopRightPoint,
4309 const Handle(GEOM_Object)& theBottomLeftPoint,
4310 const Handle(GEOM_Object)& theBottomRightPoint,
4311 const GEOMAlgo_State theState)
4315 if ( theShape.IsNull() ||
4316 theTopLeftPoint.IsNull() ||
4317 theTopRightPoint.IsNull() ||
4318 theBottomLeftPoint.IsNull() ||
4319 theBottomRightPoint.IsNull() )
4322 TopoDS_Shape aShape = theShape->GetValue();
4323 TopoDS_Shape aTL = theTopLeftPoint->GetValue();
4324 TopoDS_Shape aTR = theTopRightPoint->GetValue();
4325 TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
4326 TopoDS_Shape aBR = theBottomRightPoint->GetValue();
4328 if (aShape.IsNull() ||
4333 aTL.ShapeType() != TopAbs_VERTEX ||
4334 aTR.ShapeType() != TopAbs_VERTEX ||
4335 aBL.ShapeType() != TopAbs_VERTEX ||
4336 aBR.ShapeType() != TopAbs_VERTEX )
4339 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4340 if ( !checkTypeShapesOn( aShapeType ))
4343 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
4345 // Check presence of triangulation, build if need
4346 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
4347 SetErrorCode("Cannot build triangulation on the shape");
4352 gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
4353 gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
4354 gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
4355 gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
4357 GEOMAlgo_FinderShapeOn2 aFinder;
4358 Handle(GEOMAlgo_ClsfQuad) aClsfQuad = new GEOMAlgo_ClsfQuad;
4360 Standard_Real aTol = 0.0001; // default value
4362 aClsfQuad->SetCorners(aPntTL, aPntTR, aPntBL, aPntBR);
4363 aFinder.SetShape(aShape);
4364 aFinder.SetTolerance(aTol);
4365 aFinder.SetClsf(aClsfQuad);
4366 aFinder.SetShapeType(aShapeType);
4367 aFinder.SetState(theState);
4369 // Sets the minimal number of inner points for the faces that do not have own
4370 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
4372 aFinder.SetNbPntsMin(3);
4373 // Sets the maximal number of inner points for edges or faces.
4374 // It is useful for the cases when this number is very big (e.g =2000) to improve
4375 // the performance. If this value =0, all inner points will be taken into account.
4377 aFinder.SetNbPntsMax(100);
4381 // Interpret results
4382 Standard_Integer iErr = aFinder.ErrorStatus();
4383 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
4385 MESSAGE(" iErr : " << iErr);
4386 TCollection_AsciiString aMsg (" iErr : ");
4387 aMsg += TCollection_AsciiString(iErr);
4391 Standard_Integer iWrn = aFinder.WarningStatus();
4392 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
4394 MESSAGE(" *** iWrn : " << iWrn);
4397 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
4399 if (listSS.Extent() < 1) {
4400 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
4401 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
4405 // Fill sequence of object IDs
4406 aSeqOfIDs = new TColStd_HSequenceOfInteger;
4408 TopTools_IndexedMapOfShape anIndices;
4409 TopExp::MapShapes(aShape, anIndices);
4411 TopTools_ListIteratorOfListOfShape itSub (listSS);
4412 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
4413 int id = anIndices.FindIndex(itSub.Value());
4414 aSeqOfIDs->Append(id);
4419 //=======================================================================
4420 //function : GetShapesOnQuadrangle
4422 * \brief Find sub-shapes complying with given status about quadrangle
4423 * \param theShape - the shape to explore
4424 * \param theShapeType - type of sub-shape of theShape
4425 * \param theTopLeftPoint - top left quadrangle corner
4426 * \param theTopRightPoint - top right quadrangle corner
4427 * \param theBottomLeftPoint - bottom left quadrangle corner
4428 * \param theBottomRightPoint - bottom right quadrangle corner
4429 * \param theState - required state
4430 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4432 //=======================================================================
4433 Handle(TColStd_HSequenceOfTransient)
4434 GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
4435 const Standard_Integer theShapeType,
4436 const Handle(GEOM_Object)& theTopLeftPoint,
4437 const Handle(GEOM_Object)& theTopRightPoint,
4438 const Handle(GEOM_Object)& theBottomLeftPoint,
4439 const Handle(GEOM_Object)& theBottomRightPoint,
4440 const GEOMAlgo_State theState)
4443 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4444 getShapesOnQuadrangleIDs( theShape,
4449 theBottomRightPoint,
4451 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4454 // Find objects by indices
4455 TCollection_AsciiString anAsciiList;
4456 Handle(TColStd_HSequenceOfTransient) aSeq;
4457 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
4458 if ( aSeq.IsNull() || aSeq->IsEmpty() )
4461 // Make a Python command
4463 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
4464 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
4466 GEOM::TPythonDump(aFunction)
4467 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
4469 << TopAbs_ShapeEnum(theShapeType) << ", "
4470 << theTopLeftPoint << ", "
4471 << theTopRightPoint << ", "
4472 << theBottomLeftPoint << ", "
4473 << theBottomRightPoint << ", "
4480 //=======================================================================
4481 //function : GetShapesOnQuadrangleIDs
4483 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4484 * \param theShape - the shape to explore
4485 * \param theShapeType - type of sub-shape of theShape
4486 * \param theTopLeftPoint - top left quadrangle corner
4487 * \param theTopRightPoint - top right quadrangle corner
4488 * \param theBottomLeftPoint - bottom left quadrangle corner
4489 * \param theBottomRightPoint - bottom right quadrangle corner
4490 * \param theState - required state
4491 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4493 //=======================================================================
4494 Handle(TColStd_HSequenceOfInteger)
4495 GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4496 const Standard_Integer theShapeType,
4497 const Handle(GEOM_Object)& theTopLeftPoint,
4498 const Handle(GEOM_Object)& theTopRightPoint,
4499 const Handle(GEOM_Object)& theBottomLeftPoint,
4500 const Handle(GEOM_Object)& theBottomRightPoint,
4501 const GEOMAlgo_State theState)
4504 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4505 getShapesOnQuadrangleIDs( theShape,
4510 theBottomRightPoint,
4512 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4515 // Make a Python command
4517 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4518 Handle(GEOM_BaseObject) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
4519 lastObj = GEOM::GetCreatedLast(lastObj,theTopRightPoint);
4520 lastObj = GEOM::GetCreatedLast(lastObj,theBottomRightPoint);
4521 lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
4522 Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
4524 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4525 #ifdef DUMP_SUBSHAPE_IDS
4526 GEOM::TPythonDump(aFunction, /*append=*/true)
4527 << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
4529 << TopAbs_ShapeEnum(theShapeType) << ", "
4530 << theTopLeftPoint << ", "
4531 << theTopRightPoint << ", "
4532 << theBottomLeftPoint << ", "
4533 << theBottomRightPoint << ", "
4535 #endif // DUMP_SUBSHAPE_IDS
4541 //=============================================================================
4546 //=============================================================================
4547 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
4548 Handle(GEOM_Object) theShapeWhat)
4552 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4554 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4555 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4557 if (aWhere.IsNull() || aWhat.IsNull()) {
4558 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4562 // Searching for the sub-shapes inside the ShapeWhere shape
4563 GEOMAlgo_GetInPlace aGIP;
4565 if (!GEOMAlgo_GetInPlaceAPI::GetInPlace(aWhere, aWhat, aGIP)) {
4566 SetErrorCode("Error in GEOMAlgo_GetInPlace");
4570 // Add direct result.
4571 TopTools_ListOfShape aLSA;
4572 const TopoDS_Shape &aShapeResult = aGIP.Result();
4573 TopTools_MapOfShape aMFence;
4574 TopTools_IndexedMapOfShape aWhereIndices;
4575 Standard_Integer aShapeType = -1;
4577 TopExp::MapShapes(aWhere, aWhereIndices);
4579 if (aShapeResult.IsNull() == Standard_False) {
4580 TopoDS_Iterator anIt(aShapeResult);
4582 for (; anIt.More(); anIt.Next()) {
4583 const TopoDS_Shape &aPart = anIt.Value();
4585 if(aWhereIndices.Contains(aPart) && aMFence.Add(aPart)) {
4586 const TopAbs_ShapeEnum aType = aPart.ShapeType();
4588 if (aShapeType == -1) {
4591 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4593 aShapeType = TopAbs_SHAPE;
4601 if (aLSA.Extent() == 0) {
4602 SetErrorCode(NOT_FOUND_ANY); // Not found any Results
4606 Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent());
4607 TopTools_ListIteratorOfListOfShape anIterModif (aLSA);
4608 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4609 aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value()));
4613 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4614 if (aResult.IsNull()) {
4615 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4619 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4621 if ((aModifiedArray->Length() > 1 && isSameType) ||
4622 theShapeWhat->GetType() == GEOM_GROUP) {
4624 aResult->SetType(GEOM_GROUP);
4626 //Set a sub-shape type
4627 TopoDS_Shape aFirstFound = aLSA.First();
4628 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4630 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4631 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4634 //Make a Python command
4635 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4637 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4638 << theShapeWhere << ", " << theShapeWhat << ", True)";
4644 //=============================================================================
4646 * case GetInPlaceOld:
4649 //=============================================================================
4650 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld
4651 (Handle(GEOM_Object) theShapeWhere,
4652 Handle(GEOM_Object) theShapeWhat)
4656 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4658 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4659 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4660 TopTools_ListOfShape aModifiedList;
4661 const Standard_Integer iErr =
4662 GEOMAlgo_GetInPlaceAPI::GetInPlaceOld(aWhere, aWhat, aModifiedList);
4667 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4671 ("Error: An attempt to extract a shape of not supported type.");
4674 SetErrorCode(NOT_FOUND_ANY);
4677 SetErrorCode("Shape driver failed");
4684 TopTools_IndexedMapOfShape aWhereIndices;
4685 TopExp::MapShapes(aWhere, aWhereIndices);
4687 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4688 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4689 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4690 Standard_Integer imod;
4691 Standard_Integer aShapeType = -1;
4693 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4694 const Standard_Integer anIndex =
4695 aWhereIndices.FindIndex(anIterModif.Value());
4696 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4698 if (aShapeType == -1) {
4701 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4703 aShapeType = TopAbs_SHAPE;
4706 aModifiedArray->SetValue(imod, anIndex);
4710 Handle(GEOM_Object) aResult =
4711 GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4713 if (aResult.IsNull()) {
4714 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4718 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4720 if ((aModifiedArray->Length() > 1 && isSameType) ||
4721 theShapeWhat->GetType() == GEOM_GROUP) {
4723 aResult->SetType(GEOM_GROUP);
4725 //Set a sub-shape type
4726 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4727 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4729 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4730 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4733 //Make a Python command
4734 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4736 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4737 << theShapeWhere << ", " << theShapeWhat << ", False)";
4744 //=======================================================================
4745 //function : GetInPlaceByHistory
4747 //=======================================================================
4748 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
4749 (Handle(GEOM_Object) theShapeWhere,
4750 Handle(GEOM_Object) theShapeWhat)
4754 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4756 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4757 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4759 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4761 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4762 if (aWhereFunction.IsNull()) return NULL;
4764 //Fill array of indices
4765 TopTools_IndexedMapOfShape aWhereIndices;
4767 TopExp::MapShapes(aWhere, aWhereIndices);
4770 TopTools_ListOfShape aModifiedList;
4771 bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceByHistory
4772 (aWhereFunction, aWhereIndices, aWhat, aModifiedList);
4774 if (!isFound || aModifiedList.Extent() < 1) {
4775 SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
4779 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4780 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4781 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4782 Standard_Integer imod;
4783 Standard_Integer aShapeType = -1;
4785 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4786 const Standard_Integer anIndex =
4787 aWhereIndices.FindIndex(anIterModif.Value());
4788 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4790 if (aShapeType == -1) {
4793 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4795 aShapeType = TopAbs_SHAPE;
4798 aModifiedArray->SetValue(imod, anIndex);
4802 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4803 if (aResult.IsNull()) {
4804 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4808 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4810 if ((aModifiedArray->Length() > 1 && isSameType) ||
4811 theShapeWhat->GetType() == GEOM_GROUP) {
4813 aResult->SetType(GEOM_GROUP);
4815 //Set a sub-shape type
4816 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4817 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4819 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4820 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4823 //Make a Python command
4824 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4826 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
4827 << theShapeWhere << ", " << theShapeWhat << ")";
4833 //=======================================================================
4834 //function : GetInPlaceMap
4836 //=======================================================================
4837 void GEOMImpl_IShapesOperations::GetInPlaceMap (Handle(GEOM_Object) theShapeWhere,
4838 Handle(GEOM_Object) theShapeWhat,
4839 std::vector< std::vector< int > > & theResVec)
4843 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return;
4845 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4846 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4848 if (aWhere.IsNull() || aWhat.IsNull()) return;
4850 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4851 if (aWhereFunction.IsNull()) return;
4853 bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceMap( aWhereFunction, aWhat, theResVec );
4858 Handle(GEOM_Function) aFunction =
4859 GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
4861 GEOM::TPythonDump(aFunction, /*append=*/true)
4862 << "resultList = geompy.GetInPlaceMap( "
4863 << theShapeWhere << ", "
4864 << theShapeWhat << ")";
4869 //=======================================================================
4870 //function : isSameEdge
4871 //purpose : Returns True if two edges coincide
4872 //=======================================================================
4873 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4875 TopoDS_Vertex V11, V12, V21, V22;
4876 TopExp::Vertices(theEdge1, V11, V12);
4877 TopExp::Vertices(theEdge2, V21, V22);
4878 gp_Pnt P11 = BRep_Tool::Pnt(V11);
4879 gp_Pnt P12 = BRep_Tool::Pnt(V12);
4880 gp_Pnt P21 = BRep_Tool::Pnt(V21);
4881 gp_Pnt P22 = BRep_Tool::Pnt(V22);
4882 bool coincide = false;
4884 //Check that ends of edges coincide
4885 if(P11.Distance(P21) <= MAX_TOLERANCE) {
4886 if(P12.Distance(P22) <= MAX_TOLERANCE) coincide = true;
4888 else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4889 if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4892 if(!coincide) return false;
4894 if (BRep_Tool::Degenerated(theEdge1))
4895 if (BRep_Tool::Degenerated(theEdge2)) return true;
4898 if (BRep_Tool::Degenerated(theEdge2)) return false;
4900 double U11, U12, U21, U22;
4901 Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4902 Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4904 //Check that both edges has the same geometry
4905 double range = U12-U11;
4906 double U = U11+ range/3.0;
4907 gp_Pnt P1 = C1->Value(U); //Compute a point on one third of the edge's length
4908 U = U11+range*2.0/3.0;
4909 gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length
4911 C2 = new Geom_TrimmedCurve(C2, U21, U22);
4912 // vsr 04/10/2018: 0023312 - As curve may be periodic, its parameters may be normalized
4913 // so, we re-take them from trimmed curve
4914 U21 = C2->FirstParameter();
4915 U22 = C2->LastParameter();
4917 if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22)
4920 if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4922 if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4925 if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4930 //=======================================================================
4931 //function : isSameFace
4932 //purpose : Returns True if two faces coincide
4933 //=======================================================================
4934 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4936 TopExp_Explorer E(theFace1, TopAbs_EDGE);
4937 TopTools_ListOfShape LS1, LS2;
4938 for(; E.More(); E.Next()) LS1.Append(E.Current());
4940 E.Init(theFace2, TopAbs_EDGE);
4941 for(; E.More(); E.Next()) LS2.Append(E.Current());
4943 //Compare the number of edges in the faces
4944 if(LS1.Extent() != LS2.Extent()) return false;
4946 double aMin = RealFirst(), aMax = RealLast();
4947 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4948 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4950 for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4951 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4952 if(P.X() < xminB1) xminB1 = P.X();
4953 if(P.Y() < yminB1) yminB1 = P.Y();
4954 if(P.Z() < zminB1) zminB1 = P.Z();
4955 if(P.X() > xmaxB1) xmaxB1 = P.X();
4956 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4957 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4960 for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4961 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4962 if(P.X() < xminB2) xminB2 = P.X();
4963 if(P.Y() < yminB2) yminB2 = P.Y();
4964 if(P.Z() < zminB2) zminB2 = P.Z();
4965 if(P.X() > xmaxB2) xmaxB2 = P.X();
4966 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4967 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4970 //Compare the bounding boxes of both faces
4971 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4974 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4977 Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4978 Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4980 //Check if there a coincidence of two surfaces at least in two points
4981 double U11, U12, V11, V12, U21, U22, V21, V22;
4982 BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4983 BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4985 double rangeU = U12-U11;
4986 double rangeV = V12-V11;
4987 double U = U11 + rangeU/3.0;
4988 double V = V11 + rangeV/3.0;
4989 gp_Pnt P1 = S1->Value(U, V);
4990 U = U11+rangeU*2.0/3.0;
4991 V = V11+rangeV*2.0/3.0;
4992 gp_Pnt P2 = S1->Value(U, V);
4994 if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4997 if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4999 if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
5002 if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
5004 //Check that each edge of the Face1 has a counterpart in the Face2
5005 TopTools_MapOfOrientedShape aMap;
5006 TopTools_ListIteratorOfListOfShape LSI1(LS1);
5007 for(; LSI1.More(); LSI1.Next()) {
5008 TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
5009 bool isFound = false;
5010 TopTools_ListIteratorOfListOfShape LSI2(LS2);
5011 for(; LSI2.More(); LSI2.Next()) {
5012 TopoDS_Shape aValue = LSI2.Value();
5013 if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
5014 if(isSameEdge(E, TopoDS::Edge(aValue))) {
5020 if(!isFound) return false;
5026 //=======================================================================
5027 //function : isSameSolid
5028 //purpose : Returns True if two solids coincide
5029 //=======================================================================
5030 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
5032 TopExp_Explorer E(theSolid1, TopAbs_FACE);
5033 TopTools_ListOfShape LS1, LS2;
5034 for(; E.More(); E.Next()) LS1.Append(E.Current());
5035 E.Init(theSolid2, TopAbs_FACE);
5036 for(; E.More(); E.Next()) LS2.Append(E.Current());
5038 if(LS1.Extent() != LS2.Extent()) return false;
5040 double aMin = RealFirst(), aMax = RealLast();
5041 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
5042 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
5044 for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
5045 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
5046 if(P.X() < xminB1) xminB1 = P.X();
5047 if(P.Y() < yminB1) yminB1 = P.Y();
5048 if(P.Z() < zminB1) zminB1 = P.Z();
5049 if(P.X() > xmaxB1) xmaxB1 = P.X();
5050 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
5051 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
5054 for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
5055 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
5056 if(P.X() < xminB2) xminB2 = P.X();
5057 if(P.Y() < yminB2) yminB2 = P.Y();
5058 if(P.Z() < zminB2) zminB2 = P.Z();
5059 if(P.X() > xmaxB2) xmaxB2 = P.X();
5060 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
5061 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
5064 //Compare the bounding boxes of both solids
5065 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
5068 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
5071 //Check that each face of the Solid1 has a counterpart in the Solid2
5072 TopTools_MapOfOrientedShape aMap;
5073 TopTools_ListIteratorOfListOfShape LSI1(LS1);
5074 for(; LSI1.More(); LSI1.Next()) {
5075 TopoDS_Face F = TopoDS::Face(LSI1.Value());
5076 bool isFound = false;
5077 TopTools_ListIteratorOfListOfShape LSI2(LS2);
5078 for(; LSI2.More(); LSI2.Next()) {
5079 if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
5080 if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
5081 aMap.Add(LSI2.Value());
5086 if(!isFound) return false;
5092 //=======================================================================
5093 //function : GetSame
5095 //=======================================================================
5096 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
5097 const Handle(GEOM_Object)& theShapeWhat)
5100 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
5102 TopoDS_Shape aWhere = theShapeWhere->GetValue();
5103 TopoDS_Shape aWhat = theShapeWhat->GetValue();
5105 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
5108 bool isFound = false;
5109 TopoDS_Shape aSubShape;
5110 TopTools_MapOfShape aMap;
5112 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
5113 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
5114 if (It.More()) aWhat = It.Value();
5117 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
5122 switch (aWhat.ShapeType()) {
5123 case TopAbs_VERTEX: {
5124 aSubShape = getSameVertex(aWhere, TopoDS::Vertex(aWhat));
5125 isFound = !aSubShape.IsNull();
5129 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
5130 TopExp_Explorer E(aWhere, TopAbs_EDGE);
5131 for(; E.More(); E.Next()) {
5132 if(!aMap.Add(E.Current())) continue;
5133 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
5134 aSubShape = E.Current();
5142 TopoDS_Face aFace = TopoDS::Face(aWhat);
5143 TopExp_Explorer E(aWhere, TopAbs_FACE);
5144 for(; E.More(); E.Next()) {
5145 if(!aMap.Add(E.Current())) continue;
5146 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5147 aSubShape = E.Current();
5154 case TopAbs_SOLID: {
5155 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5156 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5157 for(; E.More(); E.Next()) {
5158 if(!aMap.Add(E.Current())) continue;
5159 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5160 aSubShape = E.Current();
5172 TopTools_IndexedMapOfShape anIndices;
5173 TopExp::MapShapes(aWhere, anIndices);
5174 if (anIndices.Contains(aSubShape))
5175 anIndex = anIndices.FindIndex(aSubShape);
5178 if (anIndex < 0) return NULL;
5180 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
5182 anArray->SetValue(1, anIndex);
5184 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
5185 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
5187 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
5188 << theShapeWhere << ", " << theShapeWhat << ")";
5196 //=======================================================================
5197 //function : GetSameIDs
5199 //=======================================================================
5200 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
5201 (const Handle(GEOM_Object)& theShapeWhere,
5202 const Handle(GEOM_Object)& theShapeWhat)
5205 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
5207 TopoDS_Shape aWhere = theShapeWhere->GetValue();
5208 TopoDS_Shape aWhat = theShapeWhat->GetValue();
5210 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
5212 TopTools_ListOfShape listShape;
5213 TopTools_MapOfShape aMap;
5215 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
5216 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
5217 if (It.More()) aWhat = It.Value();
5220 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
5225 switch (aWhat.ShapeType()) {
5226 case TopAbs_VERTEX: {
5227 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
5228 TopExp_Explorer E(aWhere, TopAbs_VERTEX);
5229 for(; E.More(); E.Next()) {
5230 if(!aMap.Add(E.Current())) continue;
5231 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
5232 if(P.Distance(P2) <= MAX_TOLERANCE) {
5233 listShape.Append(E.Current());
5239 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
5240 TopExp_Explorer E(aWhere, TopAbs_EDGE);
5241 for(; E.More(); E.Next()) {
5242 if(!aMap.Add(E.Current())) continue;
5243 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
5244 listShape.Append(E.Current());
5250 TopoDS_Face aFace = TopoDS::Face(aWhat);
5251 TopExp_Explorer E(aWhere, TopAbs_FACE);
5252 for(; E.More(); E.Next()) {
5253 if(!aMap.Add(E.Current())) continue;
5254 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5255 listShape.Append(E.Current());
5260 case TopAbs_SOLID: {
5261 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5262 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5263 for(; E.More(); E.Next()) {
5264 if(!aMap.Add(E.Current())) continue;
5265 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5266 listShape.Append(E.Current());
5275 if ( !listShape.IsEmpty() ) {
5276 TopTools_IndexedMapOfShape anIndices;
5277 TopExp::MapShapes(aWhere, anIndices);
5278 TopTools_ListIteratorOfListOfShape itSub (listShape);
5279 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
5280 for (; itSub.More(); itSub.Next()) {
5281 if (anIndices.Contains(itSub.Value()))
5282 aSeq->Append(anIndices.FindIndex(itSub.Value()));
5285 // The GetSameIDs() doesn't change object so no new function is required.
5286 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
5288 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
5289 #ifdef DUMP_SUBSHAPE_IDS
5290 // Make a Python command
5291 GEOM::TPythonDump(aFunction, /*append=*/true)
5292 << "listSameIDs = geompy.GetSameIDs("
5293 << theShapeWhere << ", "
5294 << theShapeWhat << ")";
5295 #endif // DUMP_SUBSHAPE_IDS
5298 SetErrorCode(NOT_FOUND_ANY);
5303 //=======================================================================
5304 //function : ExtendEdge
5306 //=======================================================================
5307 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendEdge
5308 (const Handle(GEOM_Object) &theEdge,
5309 const Standard_Real theMin,
5310 const Standard_Real theMax)
5314 if (theEdge.IsNull()) {
5318 //Add a new Edge object
5319 Handle(GEOM_Object) aResEdge = GetEngine()->AddObject(GEOM_EDGE);
5321 //Add a new Vector function
5322 Handle(GEOM_Function) aFunction =
5323 aResEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_UV);
5325 //Check if the function is set correctly
5326 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5330 GEOMImpl_IShapeExtend aCI (aFunction);
5332 Handle(GEOM_Function) anEdge = theEdge->GetLastFunction();
5334 if (anEdge.IsNull()) {
5338 aCI.SetShape(anEdge);
5339 aCI.SetUMin(theMin);
5340 aCI.SetUMax(theMax);
5342 //Compute the Edge value
5345 if (!GetSolver()->ComputeFunction(aFunction)) {
5346 SetErrorCode("Shape driver failed");
5351 catch (Standard_Failure& aFail) {
5352 SetErrorCode(aFail.GetMessageString());
5357 //Make a Python command
5358 GEOM::TPythonDump(aFunction)
5359 << aResEdge << " = geompy.ExtendEdge("
5360 << theEdge << ", " << theMin << ", " << theMax << ")";
5367 //=======================================================================
5368 //function : ExtendFace
5370 //=======================================================================
5371 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendFace
5372 (const Handle(GEOM_Object) &theFace,
5373 const Standard_Real theUMin,
5374 const Standard_Real theUMax,
5375 const Standard_Real theVMin,
5376 const Standard_Real theVMax)
5380 if (theFace.IsNull()) {
5384 //Add a new Face object
5385 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GEOM_FACE);
5387 //Add a new Vector function
5388 Handle(GEOM_Function) aFunction =
5389 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_UV);
5391 //Check if the function is set correctly
5392 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5396 GEOMImpl_IShapeExtend aCI (aFunction);
5398 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5400 if (aFace.IsNull()) {
5404 aCI.SetShape(aFace);
5405 aCI.SetUMin(theUMin);
5406 aCI.SetUMax(theUMax);
5407 aCI.SetVMin(theVMin);
5408 aCI.SetVMax(theVMax);
5410 //Compute the Face value
5413 if (!GetSolver()->ComputeFunction(aFunction)) {
5414 SetErrorCode("Shape driver failed");
5419 catch (Standard_Failure& aFail) {
5420 SetErrorCode(aFail.GetMessageString());
5425 //Make a Python command
5426 GEOM::TPythonDump(aFunction)
5427 << aResFace << " = geompy.ExtendFace("
5428 << theFace << ", " << theUMin << ", " << theUMax << ", "
5429 << theVMin << ", " << theVMax << ")";
5436 //=======================================================================
5437 //function : MakeSurfaceFromFace
5439 //=======================================================================
5440 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSurfaceFromFace
5441 (const Handle(GEOM_Object) &theFace)
5445 if (theFace.IsNull()) {
5449 //Add a new Face object
5450 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GEOM_FACE);
5452 //Add a new Vector function
5453 Handle(GEOM_Function) aFunction =
5454 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), SURFACE_FROM_FACE);
5456 //Check if the function is set correctly
5457 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5461 GEOMImpl_IShapeExtend aCI (aFunction);
5463 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5465 if (aFace.IsNull()) {
5469 aCI.SetShape(aFace);
5471 //Compute the Face value
5474 if (!GetSolver()->ComputeFunction(aFunction)) {
5475 SetErrorCode("Shape driver failed");
5480 catch (Standard_Failure& aFail) {
5481 SetErrorCode(aFail.GetMessageString());
5486 //Make a Python command
5487 GEOM::TPythonDump(aFunction)
5488 << aResFace << " = geompy.MakeSurfaceFromFace("