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)
387 Handle(GEOM_Object) aWire = GetEngine()->AddObject(GEOM_WIRE);
390 Handle(GEOM_Function) aFunction =
391 aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES);
392 if (aFunction.IsNull()) return NULL;
394 //Check if the function is set correctly
395 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
397 GEOMImpl_IShapes aCI (aFunction);
398 aCI.SetTolerance(theTolerance);
400 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
403 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
404 for (; it != theShapes.end(); it++) {
405 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
406 if (aRefSh.IsNull()) {
407 SetErrorCode("NULL argument shape for the shape construction");
410 aShapesSeq->Append(aRefSh);
412 aCI.SetShapes(aShapesSeq);
417 if (!GetSolver()->ComputeFunction(aFunction)) {
418 SetErrorCode("Shape driver failed");
422 catch (Standard_Failure& aFail) {
423 SetErrorCode(aFail.GetMessageString());
427 //Make a Python command
428 GEOM::TPythonDump pd (aFunction);
429 pd << aWire << " = geompy.MakeWire([";
432 it = theShapes.begin();
433 if (it != theShapes.end()) {
435 while (it != theShapes.end()) {
436 pd << ", " << (*it++);
439 pd << "], " << theTolerance << ")";
445 //=============================================================================
449 //=============================================================================
450 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
451 const bool isPlanarWanted)
455 if (theWire.IsNull()) return NULL;
457 //Add a new Face object
458 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GEOM_FACE);
460 //Add a new Shape function for creation of a face from a wire
461 Handle(GEOM_Function) aFunction =
462 aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
463 if (aFunction.IsNull()) return NULL;
465 //Check if the function is set correctly
466 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
468 GEOMImpl_IShapes aCI (aFunction);
470 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
472 if (aRefWire.IsNull()) return NULL;
474 aCI.SetBase(aRefWire);
475 aCI.SetIsPlanar(isPlanarWanted);
477 //Compute the Face value
478 Standard_Boolean isWarning = Standard_False;
481 if (!GetSolver()->ComputeFunction(aFunction)) {
482 SetErrorCode("Shape driver failed to compute a face");
486 catch (Standard_Failure& aFail) {
487 SetErrorCode(aFail.GetMessageString());
488 // to provide warning
489 if (!aFunction->GetValue().IsNull()) {
490 isWarning = Standard_True;
496 //Make a Python command
497 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
498 << theWire << ", " << (int)isPlanarWanted << ")";
500 // to provide warning
501 if (!isWarning) SetErrorCode(OK);
505 //=============================================================================
509 //=============================================================================
510 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
511 (std::list<Handle(GEOM_Object)> theShapes,
512 const bool isPlanarWanted)
517 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FACE);
520 Handle(GEOM_Function) aFunction =
521 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
522 if (aFunction.IsNull()) return NULL;
524 //Check if the function is set correctly
525 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
527 GEOMImpl_IShapes aCI (aFunction);
529 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
532 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
533 for (; it != theShapes.end(); it++) {
534 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
535 if (aRefSh.IsNull()) {
536 SetErrorCode("NULL argument shape for the face construction");
539 aShapesSeq->Append(aRefSh);
541 aCI.SetShapes(aShapesSeq);
543 aCI.SetIsPlanar(isPlanarWanted);
546 Standard_Boolean isWarning = Standard_False;
549 if (!GetSolver()->ComputeFunction(aFunction)) {
550 SetErrorCode("Shape driver failed");
554 catch (Standard_Failure& aFail) {
555 SetErrorCode(aFail.GetMessageString());
556 // to provide warning
557 if (!aFunction->GetValue().IsNull()) {
558 isWarning = Standard_True;
564 //Make a Python command
565 GEOM::TPythonDump pd (aFunction);
566 pd << aShape << " = geompy.MakeFaceWires([";
569 it = theShapes.begin();
570 if (it != theShapes.end()) {
572 while (it != theShapes.end()) {
573 pd << ", " << (*it++);
576 pd << "], " << (int)isPlanarWanted << ")";
578 // to provide warning
579 if (!isWarning) SetErrorCode(OK);
583 //=============================================================================
585 * MakeFaceFromSurface
587 //=============================================================================
588 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface
589 (Handle(GEOM_Object) theFace,
590 Handle(GEOM_Object) theWire)
595 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FACE);
598 Handle(GEOM_Function) aFunction =
599 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_FROM_SURFACE);
601 if (aFunction.IsNull()) {
605 //Check if the function is set correctly
606 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
610 GEOMImpl_IShapes aCI (aFunction);
611 Handle(TColStd_HSequenceOfTransient) aShapesSeq =
612 new TColStd_HSequenceOfTransient;
613 Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
614 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
616 if (aRefFace.IsNull()) {
617 SetErrorCode("NULL argument face for the face construction");
621 if (aRefWire.IsNull()) {
622 SetErrorCode("NULL argument wire for the face construction");
626 aShapesSeq->Append(aRefFace);
627 aShapesSeq->Append(aRefWire);
629 aCI.SetShapes(aShapesSeq);
634 if (!GetSolver()->ComputeFunction(aFunction)) {
635 SetErrorCode("Shape driver failed");
639 catch (Standard_Failure& aFail) {
640 SetErrorCode(aFail.GetMessageString());
644 //Make a Python command
645 GEOM::TPythonDump (aFunction) << aShape
646 << " = geompy.MakeFaceFromSurface(" << theFace << ", " << theWire << ")";
653 //=============================================================================
657 //=============================================================================
658 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWrappedFace
659 (std::list<Handle(GEOM_Object)> theEdges,
660 std::list<Handle(GEOM_Object)> theVertices,
661 const Standard_Real theTolerance)
665 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FACE);
668 Handle(GEOM_Function) aFunction =
669 aShape->AddFunction(GEOMImpl_WrappingDriver::GetID(), WRAPPING_FACE);
670 if (aFunction.IsNull()) return NULL;
672 //Check if the function is set correctly
673 if (aFunction->GetDriverGUID() != GEOMImpl_WrappingDriver::GetID()) return NULL;
675 GEOMImpl_IWrap aCI (aFunction);
676 aCI.SetTolerance(theTolerance);
679 Handle(TColStd_HSequenceOfTransient) anEdgesSeq = new TColStd_HSequenceOfTransient;
680 std::list<Handle(GEOM_Object)>::iterator it = theEdges.begin();
681 for (; it != theEdges.end(); it++) {
682 Handle(GEOM_Object) anEdge = (*it);
683 if ( anEdge.IsNull() || anEdge->GetValue().ShapeType() != TopAbs_EDGE ) {
684 SetErrorCode("NULL argument edge for the face construction");
687 Handle(GEOM_Function) aRefSh = anEdge->GetLastFunction();
688 anEdgesSeq->Append(aRefSh);
690 aCI.SetEdges(anEdgesSeq);
693 Handle(TColStd_HSequenceOfTransient) aVerticesSeq = new TColStd_HSequenceOfTransient;
694 it = theVertices.begin();
695 for (; it != theVertices.end(); it++) {
696 Handle(GEOM_Object) aVertex = (*it);
697 if ( aVertex.IsNull() || aVertex->GetValue().ShapeType() != TopAbs_VERTEX ) {
698 SetErrorCode("NULL argument vertex for the face construction");
701 Handle(GEOM_Function) aRefSh = aVertex->GetLastFunction();
702 aVerticesSeq->Append(aRefSh);
704 aCI.SetVertices(aVerticesSeq);
709 if (!GetSolver()->ComputeFunction(aFunction)) {
710 SetErrorCode("Wrap driver failed");
714 catch (Standard_Failure& aFail) {
715 SetErrorCode(aFail.GetMessageString());
719 //Make a Python command
720 GEOM::TPythonDump pd (aFunction);
721 pd << aShape << " = geompy.MakeWrappedFace([";
724 it = theEdges.begin();
725 if (it != theEdges.end()) {
727 while (it != theEdges.end()) {
728 pd << ", " << (*it++);
733 it = theVertices.begin();
734 if (it != theVertices.end()) {
736 while (it != theVertices.end()) {
737 pd << ", " << (*it++);
740 pd << "], " << theTolerance << ")";
746 //=============================================================================
748 * MakeFaceWithConstraints
750 //=============================================================================
751 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWithConstraints
752 (std::list<Handle(GEOM_Object)> theConstraints)
757 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FILLING);
760 Handle(GEOM_Function) aFunction =
761 aShape->AddFunction(GEOMImpl_FillingDriver::GetID(), FILLING_ON_CONSTRAINTS);
762 if (aFunction.IsNull()) return NULL;
764 //Check if the function is set correctly
765 if (aFunction->GetDriverGUID() != GEOMImpl_FillingDriver::GetID()) return NULL;
767 GEOMImpl_IFilling aCI (aFunction);
768 Handle(TColStd_HSequenceOfTransient) aConstraints = new TColStd_HSequenceOfTransient;
771 std::list<Handle(GEOM_Object)>::iterator it = theConstraints.begin();
772 while (it != theConstraints.end()) {
773 Handle(GEOM_Object) anObject = (*it);
774 if ( anObject.IsNull() || anObject->GetValue().ShapeType() != TopAbs_EDGE ) {
775 SetErrorCode("NULL argument edge for the face construction");
778 Handle(GEOM_Function) aRefSh = anObject->GetLastFunction();
779 aConstraints->Append(aRefSh);
781 if ( it != theConstraints.end() ) {
782 Handle(GEOM_Object) aFace = (*it);
783 if ( aFace.IsNull() ) {
784 // null constraint face - it is a valid case
788 if ( aFace->GetValue().ShapeType() != TopAbs_FACE )
789 // constraint face can be omitted - it is a valid case
791 // Keep the old error code as IsSubShapeBelongsTo changes it.
792 TCollection_AsciiString anOldCode = GetErrorCode();
794 if ( IsSubShapeBelongsTo( anObject, 0, aFace, 0 ) ) {
796 SetErrorCode(anOldCode);
797 aRefSh = aFace->GetLastFunction();
798 aConstraints->Append(aRefSh);
803 SetErrorCode("Face is NULL or not connected to the Edge");
808 aCI.SetShapes( aConstraints );
811 Standard_Boolean isWarning = Standard_False;
814 if (!GetSolver()->ComputeFunction(aFunction)) {
815 SetErrorCode("Shape driver failed");
819 catch (Standard_Failure& aFail) {
820 SetErrorCode(aFail.GetMessageString());
821 // to provide warning
822 if (!aFunction->GetValue().IsNull()) {
823 isWarning = Standard_True;
829 //Make a Python command
830 GEOM::TPythonDump pd (aFunction);
831 pd << aShape << " = geompy.MakeFaceWithConstraints([";
834 it = theConstraints.begin();
835 if (it != theConstraints.end() ) {
837 while (it != theConstraints.end()) {
838 Handle(GEOM_Object) anObject = (*it++);
839 if( !anObject.IsNull() )
840 pd << ", " << anObject;
845 // to provide warning
846 if (!isWarning) SetErrorCode(OK);
850 //=============================================================================
854 //=============================================================================
855 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
856 (std::list<Handle(GEOM_Object)> theShapes)
858 return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
861 //=============================================================================
865 //=============================================================================
866 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
867 (std::list<Handle(GEOM_Object)> theShapes)
869 return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
872 //=============================================================================
876 //=============================================================================
877 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
878 (std::list<Handle(GEOM_Object)> theShapes)
880 return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
883 //=============================================================================
887 //=============================================================================
888 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
889 (std::list<Handle(GEOM_Object)> theShapes,
890 const Standard_Integer theObjectType,
891 const Standard_Integer theFunctionType,
892 const TCollection_AsciiString& theMethodName)
897 Handle(GEOM_Object) aShape = GetEngine()->AddObject(theObjectType);
900 Handle(GEOM_Function) aFunction =
901 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
902 if (aFunction.IsNull()) return NULL;
904 //Check if the function is set correctly
905 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
907 GEOMImpl_IShapes aCI (aFunction);
909 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
912 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
913 for (; it != theShapes.end(); it++) {
914 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
915 if (aRefSh.IsNull()) {
916 SetErrorCode("NULL argument shape for the shape construction");
919 aShapesSeq->Append(aRefSh);
921 aCI.SetShapes(aShapesSeq);
926 if (!GetSolver()->ComputeFunction(aFunction)) {
927 SetErrorCode("Shape driver failed");
931 catch (Standard_Failure& aFail) {
932 SetErrorCode(aFail.GetMessageString());
936 //Make a Python command
937 GEOM::TPythonDump pd (aFunction);
938 pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
941 it = theShapes.begin();
942 if (it != theShapes.end()) {
944 while (it != theShapes.end()) {
945 pd << ", " << (*it++);
954 //=============================================================================
956 * MakeSolidFromConnectedFaces
958 //=============================================================================
959 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidFromConnectedFaces
960 (std::list<Handle(GEOM_Object)> theFacesOrShells,
961 const Standard_Boolean isIntersect)
966 Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GEOM_SOLID);
969 Handle(GEOM_Function) aFunction =
970 aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_FACES);
971 if (aFunction.IsNull()) return NULL;
973 //Check if the function is set correctly
974 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
976 GEOMImpl_IShapes aCI (aFunction);
978 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
981 std::list<Handle(GEOM_Object)>::iterator it = theFacesOrShells.begin();
982 for (; it != theFacesOrShells.end(); it++) {
983 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
984 if (aRefSh.IsNull()) {
985 SetErrorCode("NULL argument shape for the shape construction");
988 aShapesSeq->Append(aRefSh);
990 aCI.SetShapes(aShapesSeq);
991 aCI.SetIsIntersect(isIntersect);
996 if (!GetSolver()->ComputeFunction(aFunction)) {
997 SetErrorCode("Shape driver failed");
1001 catch (Standard_Failure& aFail) {
1002 SetErrorCode(aFail.GetMessageString());
1006 //Make a Python command
1007 GEOM::TPythonDump pd (aFunction);
1008 pd << aSolid << " = geompy.MakeSolidFromConnectedFaces([";
1011 it = theFacesOrShells.begin();
1012 if (it != theFacesOrShells.end()) {
1014 while (it != theFacesOrShells.end()) {
1015 pd << ", " << (*it++);
1018 pd << "]," << (isIntersect ? "True" : "False") << ")";
1024 //=============================================================================
1028 //=============================================================================
1030 GEOMImpl_IShapesOperations::MakeGlueFaces (std::list< Handle(GEOM_Object) >& theShapes,
1031 const Standard_Real theTolerance,
1032 const Standard_Boolean doKeepNonSolids)
1036 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1037 if ( objects.IsNull() || objects->IsEmpty() ) {
1038 SetErrorCode("NULL argument shape");
1042 //Add a new Glued object
1043 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
1045 //Add a new Glue function
1046 Handle(GEOM_Function) aFunction;
1047 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
1048 if (aFunction.IsNull()) return NULL;
1050 //Check if the function is set correctly
1051 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1053 GEOMImpl_IGlue aCI (aFunction);
1055 aCI.SetBase( objects );
1056 aCI.SetTolerance(theTolerance);
1057 aCI.SetKeepNonSolids(doKeepNonSolids);
1059 //Compute the sub-shape value
1060 Standard_Boolean isWarning = Standard_False;
1063 if (!GetSolver()->ComputeFunction(aFunction)) {
1064 SetErrorCode("Shape driver failed to glue faces");
1068 catch (Standard_Failure& aFail) {
1069 SetErrorCode(aFail.GetMessageString());
1070 // to provide warning
1071 if (!aFunction->GetValue().IsNull()) {
1072 isWarning = Standard_True;
1078 //Make a Python command
1079 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
1080 << theShapes << ", " << theTolerance << ")";
1082 // to provide warning
1083 if (!isWarning) SetErrorCode(OK);
1087 //=============================================================================
1091 //=============================================================================
1093 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
1094 (Handle(GEOM_Object) theShape,
1095 const Standard_Real theTolerance)
1099 if (theShape.IsNull()) return NULL;
1100 TopoDS_Shape aShape = theShape->GetValue();
1101 if (aShape.IsNull()) return NULL;
1103 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1105 Standard_Integer iErr;
1107 GEOMAlgo_Gluer1 aGluer;
1108 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
1109 GEOMAlgo_CoupleOfShapes aCS;
1110 GEOMAlgo_ListOfCoupleOfShapes aLCS;
1112 //aGluer = new GEOMAlgo_Gluer1;
1113 aGluer.SetShape(aShape);
1114 aGluer.SetTolerance(theTolerance);
1116 iErr = aGluer.ErrorStatus();
1117 if (iErr) return NULL;
1119 TopTools_ListOfShape listShape;
1120 const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
1122 aItCS.Initialize(aLCSG);
1123 for (; aItCS.More(); aItCS.Next()) {
1124 const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
1125 listShape.Append(aCSG.Shape1());
1128 TopTools_ListIteratorOfListOfShape itSub (listShape);
1129 TCollection_AsciiString anAsciiList, anEntry;
1130 TopTools_IndexedMapOfShape anIndices;
1131 TopExp::MapShapes(aShape, anIndices);
1132 Handle(TColStd_HArray1OfInteger) anArray;
1133 Handle(GEOM_Object) anObj;
1134 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1135 TopoDS_Shape aValue = itSub.Value();
1136 anArray = new TColStd_HArray1OfInteger(1,1);
1137 anArray->SetValue(1, anIndices.FindIndex(aValue));
1138 anObj = GetEngine()->AddSubShape(theShape, anArray);
1139 if (!anObj.IsNull()) {
1140 aSeq->Append(anObj);
1142 // for python command
1143 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1144 anAsciiList += anEntry;
1149 //Make a Python command
1150 if( anAsciiList.Length() > 0 ) {
1151 anAsciiList.Trunc(anAsciiList.Length() - 1);
1152 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1153 GEOM::TPythonDump pd (aFunction, true);
1154 pd << "[" << anAsciiList.ToCString();
1155 pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
1164 //=============================================================================
1166 * MakeGlueFacesByList
1168 //=============================================================================
1170 GEOMImpl_IShapesOperations::MakeGlueFacesByList(std::list< Handle(GEOM_Object) >& theShapes,
1171 const Standard_Real theTolerance,
1172 std::list<Handle(GEOM_Object)> & theFaces,
1173 const Standard_Boolean doKeepNonSolids,
1174 const Standard_Boolean doGlueAllEdges)
1178 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1179 if ( objects.IsNull() || objects->IsEmpty() ) {
1180 SetErrorCode("NULL argument shape");
1183 Handle(TColStd_HSequenceOfTransient) aFaces = GEOM_Object::GetLastFunctions( theFaces );
1184 if ( aFaces.IsNull() ) {
1185 SetErrorCode("NULL argument shape for the shape construction");
1189 //Add a new Glued object
1190 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
1192 //Add a new Glue function
1193 Handle(GEOM_Function) aFunction;
1194 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
1195 if (aFunction.IsNull()) return NULL;
1197 //Check if the function is set correctly
1198 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1200 GEOMImpl_IGlue aCI (aFunction);
1202 aCI.SetBase( objects );
1203 aCI.SetTolerance(theTolerance);
1204 aCI.SetKeepNonSolids(doKeepNonSolids);
1205 aCI.SetGlueAllEdges(doGlueAllEdges);
1206 aCI.SetFaces(aFaces);
1208 //Compute the sub-shape value
1209 Standard_Boolean isWarning = Standard_False;
1212 if (!GetSolver()->ComputeFunction(aFunction)) {
1213 SetErrorCode("Shape driver failed to glue faces");
1217 catch (Standard_Failure& aFail) {
1218 SetErrorCode(aFail.GetMessageString());
1219 // to provide warning
1220 if (!aFunction->GetValue().IsNull()) {
1221 isWarning = Standard_True;
1227 //Make a Python command
1229 GEOM::TPythonDump pd(aFunction);
1230 pd << aGlued << " = geompy.MakeGlueFacesByList("
1231 << theShapes << ", " << theTolerance << ", " << theFaces << ", "
1232 << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")";
1234 // to provide warning
1235 if (!isWarning) SetErrorCode(OK);
1239 //=============================================================================
1243 //=============================================================================
1245 GEOMImpl_IShapesOperations::MakeGlueEdges (std::list< Handle(GEOM_Object) >& theShapes,
1246 const Standard_Real theTolerance)
1250 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1251 if ( objects.IsNull() || objects->IsEmpty() ) {
1252 SetErrorCode("NULL argument shape");
1256 //Add a new Glued object
1257 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
1259 //Add a new Glue function
1260 Handle(GEOM_Function) aFunction;
1261 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES);
1262 if (aFunction.IsNull()) return NULL;
1264 //Check if the function is set correctly
1265 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1267 GEOMImpl_IGlue aCI (aFunction);
1269 aCI.SetBase( objects );
1270 aCI.SetTolerance(theTolerance);
1271 aCI.SetKeepNonSolids(true);
1273 //Compute the sub-shape value
1274 Standard_Boolean isWarning = Standard_False;
1277 if (!GetSolver()->ComputeFunction(aFunction)) {
1278 SetErrorCode("Shape driver failed to glue edges");
1282 catch (Standard_Failure& aFail) {
1283 SetErrorCode(aFail.GetMessageString());
1284 // to provide warning
1285 if (!aFunction->GetValue().IsNull()) {
1286 isWarning = Standard_True;
1292 //Make a Python command
1293 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueEdges("
1294 << theShapes << ", " << theTolerance << ")";
1296 // to provide warning
1297 if (!isWarning) SetErrorCode(OK);
1301 //=============================================================================
1305 //=============================================================================
1306 Handle(TColStd_HSequenceOfTransient)
1307 GEOMImpl_IShapesOperations::GetGlueShapes (std::list< Handle(GEOM_Object) >& theShapes,
1308 const Standard_Real theTolerance,
1309 const TopAbs_ShapeEnum theType)
1313 TopoDS_Shape aShape;
1314 TopTools_SequenceOfShape shapes;
1315 std::list< Handle(GEOM_Object) >::iterator s = theShapes.begin();
1316 Handle(GEOM_BaseObject) lastCreatedGO;
1317 for ( ; s != theShapes.end(); ++s )
1319 Handle(GEOM_Object) go = *s;
1320 if ( go.IsNull() ) return NULL;
1321 aShape = go->GetValue();
1322 if ( aShape.IsNull() ) return NULL;
1323 shapes.Append( aShape );
1324 lastCreatedGO = GEOM::GetCreatedLast( lastCreatedGO, go );
1326 if ( shapes.Length() > 1 )
1328 TopoDS_Compound compound;
1329 BRep_Builder builder;
1330 builder.MakeCompound( compound );
1331 for ( int i = 1; i <= shapes.Length(); ++i )
1332 builder.Add( compound, shapes( i ) );
1337 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1339 GEOMAlgo_GlueDetector aGluer;
1340 aGluer.SetArgument(aShape);
1341 aGluer.SetTolerance(theTolerance);
1343 Standard_Integer iErr = aGluer.ErrorStatus();
1344 if (iErr) return NULL;
1346 std::vector< TopTools_IndexedMapOfShape* > anIndices( shapes.Length(), NULL );
1347 Handle(TColStd_HArray1OfInteger) anArray;
1348 Handle(GEOM_Object) anObj;
1350 TopTools_ListOfShape listOnePerSet;
1352 const TopTools_DataMapOfShapeListOfShape& aImages = aGluer.Images();
1353 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS (aImages);
1354 for (int index = 1; aItDMSLS.More(); aItDMSLS.Next(), ++index) {
1356 //const TopoDS_Shape& aSkey = aItDMSLS.Key();
1358 // list of shapes of the argument that can be glued
1359 const TopTools_ListOfShape& aLSD = aItDMSLS.Value();
1361 //listShape.Append(aLSD.First());
1362 TopoDS_Shape aValue = aLSD.First();
1364 if (aValue.ShapeType() == theType) {
1365 listOnePerSet.Append(aValue);
1369 // for stable order of returned entities
1370 GEOMUtils::SortShapes(listOnePerSet, Standard_False);
1372 TopTools_ListIteratorOfListOfShape aListIt (listOnePerSet);
1373 for (; aListIt.More(); aListIt.Next())
1375 TopoDS_Shape aValue = aListIt.Value();
1376 // find a shape to add aValue as a sub-shape
1378 s = theShapes.begin();
1379 for ( int i = 0; i < shapes.Length(); ++i, ++s )
1381 Handle(GEOM_Object) object = *s;
1382 if ( !anIndices[i] ) {
1383 anIndices[i] = new TopTools_IndexedMapOfShape;
1384 TopExp::MapShapes( object->GetValue(), *anIndices[i]);
1386 if (int index = anIndices[i]->FindIndex( aValue )) {
1387 anArray = new TColStd_HArray1OfInteger(1,1);
1388 anArray->SetValue(1, index);
1389 anObj = GetEngine()->AddSubShape( object, anArray);
1393 if (!anObj.IsNull())
1394 aSeq->Append(anObj);
1396 for ( size_t i = 0 ; i < anIndices.size(); ++i )
1397 delete anIndices[i];
1399 // Make a Python command
1400 if ( aSeq->Length() > 0)
1402 Handle(GEOM_Function) aFunction = lastCreatedGO->GetLastFunction();
1403 GEOM::TPythonDump pd (aFunction, /*append=*/true);
1405 << " = geompy." << (theType == TopAbs_FACE ? "GetGlueFaces" : "GetGlueEdges" )
1406 << "( " << theShapes << ", " << theTolerance << ")";
1414 //=============================================================================
1416 * MakeGlueEdgesByList
1418 //=============================================================================
1420 GEOMImpl_IShapesOperations::MakeGlueEdgesByList (std::list< Handle(GEOM_Object) >& theShapes,
1421 const Standard_Real theTolerance,
1422 std::list<Handle(GEOM_Object)>& theEdges)
1426 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1427 if ( objects.IsNull() || objects->IsEmpty() ) {
1428 SetErrorCode("NULL argument shape");
1431 Handle(TColStd_HSequenceOfTransient) anEdges = GEOM_Object::GetLastFunctions( theEdges );
1432 if ( anEdges.IsNull() ) {
1433 SetErrorCode("NULL argument shape for the shape construction");
1436 //Add a new Glued object
1437 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
1439 //Add a new Glue function
1440 Handle(GEOM_Function) aFunction;
1441 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES_BY_LIST);
1442 if (aFunction.IsNull()) return NULL;
1444 //Check if the function is set correctly
1445 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1447 GEOMImpl_IGlue aCI (aFunction);
1449 aCI.SetBase( objects );
1450 aCI.SetTolerance(theTolerance);
1451 aCI.SetKeepNonSolids(true);
1452 aCI.SetFaces(anEdges);
1454 //Compute the sub-shape value
1455 Standard_Boolean isWarning = Standard_False;
1458 if (!GetSolver()->ComputeFunction(aFunction)) {
1459 SetErrorCode("Shape driver failed to glue edges");
1463 catch (Standard_Failure& aFail) {
1464 SetErrorCode(aFail.GetMessageString());
1465 // to provide warning
1466 if (!aFunction->GetValue().IsNull()) {
1467 isWarning = Standard_True;
1473 //Make a Python command
1475 GEOM::TPythonDump pd (aFunction);
1476 pd << aGlued << " = geompy.MakeGlueEdgesByList("
1477 << theShapes << ", " << theTolerance << ", " << theEdges << " )";
1479 // to provide warning
1480 if (!isWarning) SetErrorCode(OK);
1484 //=============================================================================
1486 * GetExistingSubObjects
1488 //=============================================================================
1489 Handle(TColStd_HSequenceOfTransient)
1490 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape,
1491 const Standard_Boolean theGroupsOnly)
1493 // note: this method does not return fields
1495 Standard_Integer types = theGroupsOnly ? Groups : Groups|SubShapes;
1496 Handle(TColStd_HSequenceOfTransient) results = GetExistingSubObjects(theShape, types);
1498 Handle(GEOM_BaseObject) lastCreatedGO = GEOM::GetCreatedLast(results);
1499 lastCreatedGO = GEOM::GetCreatedLast(lastCreatedGO, theShape);
1501 if (results->Length() > 0) {
1502 // Make a Python command
1503 GEOM::TPythonDump pd (lastCreatedGO->GetLastFunction(), /*append=*/true);
1505 Standard_Integer i, aLen = results->Length();
1506 for (i = 1; i <= aLen; i++)
1508 Handle(GEOM_BaseObject) obj = Handle(GEOM_BaseObject)::DownCast(results->Value(i));
1509 pd << obj << ((i < aLen) ? ", " : "");
1511 pd << "] = geompy.GetExistingSubObjects(";
1512 pd << theShape << ", " << (bool)theGroupsOnly << ")";
1518 Handle(TColStd_HSequenceOfTransient)
1519 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape,
1520 const Standard_Integer theTypes)
1524 if (theShape.IsNull()) return NULL;
1526 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1527 if (aMainShape.IsNull()) return NULL;
1529 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1530 SetErrorCode(NOT_FOUND_ANY);
1532 if (!aMainShape->HasSubShapeReferences()) return aSeq;
1533 const TDataStd_ListOfExtendedString& aListEntries = aMainShape->GetSubShapeReferences();
1534 if (aListEntries.IsEmpty()) return aSeq;
1538 TDataStd_ListIteratorOfListOfExtendedString anIt (aListEntries);
1539 for (; anIt.More(); anIt.Next()) {
1540 TCollection_ExtendedString anEntry = anIt.Value();
1541 Standard_Integer aStrLen = anEntry.LengthOfCString();
1542 char* anEntryStr = new char[aStrLen+1];
1543 anEntry.ToUTF8CString(anEntryStr);
1544 Handle(GEOM_BaseObject) anObj = GetEngine()->GetObject(anEntryStr, false);
1545 if (!anObj.IsNull() ) {
1546 bool isGroup = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() == GEOM_GROUP;
1547 bool isSubShape = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() != GEOM_GROUP;
1548 bool isField = anObj->IsKind(STANDARD_TYPE(GEOM_Field));
1549 if ((theTypes & Groups && isGroup ) ||
1550 (theTypes & SubShapes && isSubShape ) ||
1551 (theTypes & Fields && isField ))
1552 aSeq->Append(anObj);
1554 delete [] anEntryStr;
1557 if (aSeq->Length() == 0) {
1558 SetErrorCode(NOT_FOUND_ANY);
1567 //=============================================================================
1571 //=============================================================================
1572 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
1573 (Handle(GEOM_Object) theShape,
1574 const Standard_Integer theShapeType,
1575 const Standard_Boolean isSorted,
1576 const ExplodeType theExplodeType)
1580 if (theShape.IsNull()) return NULL;
1581 TopoDS_Shape aShape = theShape->GetValue();
1582 if (aShape.IsNull()) return NULL;
1584 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1586 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1587 Handle(GEOM_Object) anObj;
1588 TopTools_MapOfShape mapShape;
1589 TopTools_ListOfShape listShape;
1591 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1592 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1594 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1595 for (; It.More(); It.Next()) {
1596 TopoDS_Shape SS = It.Value();
1597 if (mapShape.Add(SS)) {
1598 if (theShapeType == TopAbs_FLAT) {
1599 AddFlatSubShapes(SS, listShape, mapShape);
1601 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1602 listShape.Append(SS);
1604 // VSR: for EXPLODE_NEW_INCLUDE_MAIN and EXPLODE_OLD_INCLUDE_MAIN:
1605 // it seems it is necessary to add top-level shape if theShapeType == TopAbs_COMPOUND
1609 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1611 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1612 for (; exp.More(); exp.Next())
1613 if (mapShape.Add(exp.Current()))
1614 listShape.Append(exp.Current());
1617 if (listShape.IsEmpty()){
1618 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1619 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1624 bool isOldSorting = false;
1625 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1626 isOldSorting = true;
1627 GEOMUtils::SortShapes(listShape, isOldSorting);
1630 TopTools_IndexedMapOfShape anIndices;
1631 TopExp::MapShapes(aShape, anIndices);
1632 Handle(TColStd_HArray1OfInteger) anArray;
1634 TopTools_ListIteratorOfListOfShape itSub (listShape);
1635 TCollection_AsciiString anAsciiList, anEntry;
1636 for (int index = 1; itSub.More(); itSub.Next(), ++index)
1638 TopoDS_Shape aValue = itSub.Value();
1639 anArray = new TColStd_HArray1OfInteger(1,1);
1640 anArray->SetValue(1, anIndices.FindIndex(aValue));
1642 //anObj = GetEngine()->AddSubShape(theShape, anArray);
1644 anObj = GetEngine()->AddObject(GEOM_SUBSHAPE);
1645 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1646 if (aFunction.IsNull()) return aSeq;
1648 GEOM_ISubShape aSSI (aFunction);
1649 aSSI.SetMainShape(aMainShape);
1650 aSSI.SetIndices(anArray);
1652 // Set function value directly, as we know it.
1653 // Usage of Solver here would lead to significant loss of time,
1654 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1655 // on the main shape for each being calculated sub-shape separately.
1656 aFunction->SetValue(aValue);
1658 // Put this subshape in the list of sub-shapes of theMainShape
1659 aMainShape->AddSubShapeReference(aFunction);
1661 if (!anObj.IsNull()) {
1662 aSeq->Append(anObj);
1664 // for python command
1665 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1666 anAsciiList += anEntry;
1671 //Make a Python command
1672 anAsciiList.Trunc(anAsciiList.Length() - 1);
1674 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1675 pd << "[" << anAsciiList.ToCString() << "] = geompy.";
1676 switch (theExplodeType) {
1677 case EXPLODE_NEW_EXCLUDE_MAIN:
1678 pd << "ExtractShapes(" << theShape << ", "
1679 << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")";
1681 case EXPLODE_NEW_INCLUDE_MAIN:
1682 pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(")
1683 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1685 case EXPLODE_OLD_INCLUDE_MAIN:
1686 pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(")
1687 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1696 //=============================================================================
1700 //=============================================================================
1701 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
1702 (Handle(GEOM_Object) theShape,
1703 const Standard_Integer theShapeType,
1704 const Standard_Boolean isSorted,
1705 const ExplodeType theExplodeType)
1709 if (theShape.IsNull()) return NULL;
1710 TopoDS_Shape aShape = theShape->GetValue();
1711 if (aShape.IsNull()) return NULL;
1713 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1714 TopTools_MapOfShape mapShape;
1715 TopTools_ListOfShape listShape;
1717 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1718 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1720 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1721 for (; It.More(); It.Next()) {
1722 TopoDS_Shape SS = It.Value();
1723 if (mapShape.Add(SS)) {
1724 if (theShapeType == TopAbs_FLAT) {
1725 AddFlatSubShapes(SS, listShape, mapShape);
1727 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1728 listShape.Append(SS);
1733 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1735 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1736 for (; exp.More(); exp.Next())
1737 if (mapShape.Add(exp.Current()))
1738 listShape.Append(exp.Current());
1741 if (listShape.IsEmpty()) {
1742 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1743 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1748 bool isOldSorting = false;
1749 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1750 isOldSorting = true;
1751 GEOMUtils::SortShapes(listShape, isOldSorting);
1754 TopTools_IndexedMapOfShape anIndices;
1755 TopExp::MapShapes(aShape, anIndices);
1756 Handle(TColStd_HArray1OfInteger) anArray;
1758 TopTools_ListIteratorOfListOfShape itSub (listShape);
1759 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1760 TopoDS_Shape aValue = itSub.Value();
1761 aSeq->Append(anIndices.FindIndex(aValue));
1764 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1766 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
1767 #ifdef DUMP_SUBSHAPE_IDS
1768 //Make a Python command
1769 GEOM::TPythonDump pd (aFunction, /*append=*/true);
1770 pd << "listSubShapeIDs = geompy.SubShapeAll";
1771 switch (theExplodeType) {
1772 case EXPLODE_NEW_EXCLUDE_MAIN:
1774 case EXPLODE_NEW_INCLUDE_MAIN:
1775 pd << (isSorted ? "SortedCentresIDs(" : "IDs(")
1776 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1778 case EXPLODE_OLD_INCLUDE_MAIN:
1779 pd << (isSorted ? "SortedIDs(" : "IDs(")
1780 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1784 #endif // DUMP_SUBSHAPE_IDS
1790 //=============================================================================
1794 //=============================================================================
1795 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
1796 (Handle(GEOM_Object) theMainShape,
1797 const Standard_Integer theID)
1801 if (theMainShape.IsNull()) return NULL;
1803 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1804 anArray->SetValue(1, theID);
1805 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
1806 if (anObj.IsNull()) {
1807 SetErrorCode("Can not get a sub-shape with the given ID");
1811 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1813 //Make a Python command
1814 GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1815 << theMainShape << ", [" << theID << "])";
1821 //=============================================================================
1825 //=============================================================================
1826 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes
1827 (Handle(GEOM_Object) theMainShape,
1828 Handle(TColStd_HArray1OfInteger) theIndices)
1832 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1834 if (!theIndices->Length()) {
1835 SetErrorCode(NOT_FOUND_ANY);
1839 if (theMainShape.IsNull()) return NULL;
1840 TopoDS_Shape aShape = theMainShape->GetValue();
1841 if (aShape.IsNull()) return NULL;
1843 Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
1845 TopTools_IndexedMapOfShape anIndices;
1846 TopExp::MapShapes(aShape, anIndices);
1848 Handle(TColStd_HArray1OfInteger) anArray;
1849 Handle(GEOM_Object) anObj;
1851 TCollection_AsciiString anAsciiList, anEntry;
1852 Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper();
1853 for (i = low; i <= up; i++) {
1854 int id = theIndices->Value(i);
1855 if (1 <= id && id <= anIndices.Extent()) {
1856 TopoDS_Shape aValue = anIndices.FindKey(id);
1857 anArray = new TColStd_HArray1OfInteger(1,1);
1858 anArray->SetValue(1, id);
1860 anObj = GetEngine()->AddObject(GEOM_SUBSHAPE);
1861 if (!anObj.IsNull()) {
1862 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1863 if (aFunction.IsNull()) return aSeq;
1865 GEOM_ISubShape aSSI (aFunction);
1866 aSSI.SetMainShape(aMainShape);
1867 aSSI.SetIndices(anArray);
1869 // Set function value directly, as we know it.
1870 // Usage of Solver here would lead to significant loss of time,
1871 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1872 // on the main shape for each being calculated sub-shape separately.
1873 aFunction->SetValue(aValue);
1875 // Put this sub-shape in the list of sub-shapes of theMainShape
1876 aMainShape->AddSubShapeReference(aFunction);
1878 aSeq->Append(anObj);
1880 // for python command
1881 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1882 anAsciiList += anEntry;
1888 //Make a Python command
1889 anAsciiList.Trunc(anAsciiList.Length() - 1);
1891 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1892 pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes("
1893 << theMainShape << ", [" ;
1894 for (i = low; i <= up - 1; i++) {
1895 pd << theIndices->Value(i) << ", ";
1897 pd << theIndices->Value(up) << "])";
1904 //=============================================================================
1908 //=============================================================================
1909 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1910 Handle(GEOM_Object) theSubShape)
1914 TopoDS_Shape aMainShape = theMainShape->GetValue();
1915 TopoDS_Shape aSubShape = theSubShape->GetValue();
1917 if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1919 TopTools_IndexedMapOfShape anIndices;
1920 TopExp::MapShapes(aMainShape, anIndices);
1921 // if (anIndices.Contains(aSubShape)) {
1922 // SetErrorCode(OK);
1923 // return anIndices.FindIndex(aSubShape);
1925 int id = anIndices.FindIndex(aSubShape);
1936 //=============================================================================
1938 * GetSubShapeIndices
1940 //=============================================================================
1941 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSubShapesIndices (Handle(GEOM_Object) theMainShape,
1942 std::list<Handle(GEOM_Object)> theSubShapes)
1944 MESSAGE("GEOMImpl_IShapesOperations::GetSubShapesIndices");
1947 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1949 TopoDS_Shape aMainShape = theMainShape->GetValue();
1950 if (aMainShape.IsNull())
1952 MESSAGE("NULL main shape");
1956 TopTools_IndexedMapOfShape anIndices;
1957 TopExp::MapShapes(aMainShape, anIndices);
1959 std::list<Handle(GEOM_Object)>::iterator it;
1960 for (it=theSubShapes.begin(); it != theSubShapes.end(); ++it)
1962 TopoDS_Shape aSubShape = (*it)->GetValue();
1963 if (aSubShape.IsNull())
1965 MESSAGE("NULL subshape");
1968 int id = anIndices.FindIndex(aSubShape);
1977 //=============================================================================
1981 //=============================================================================
1982 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1983 Handle(GEOM_Object) theSubShape)
1987 TopoDS_Shape aMainShape = theMainShape->GetValue();
1988 TopoDS_Shape aSubShape = theSubShape->GetValue();
1990 if (aMainShape.IsNull() || aSubShape.IsNull()) {
1991 SetErrorCode("Null argument shape given");
1996 if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1998 TopTools_ListOfShape CL;
1999 CL.Append(aMainShape);
2000 TopTools_ListIteratorOfListOfShape itC;
2001 for (itC.Initialize(CL); itC.More(); itC.Next()) {
2002 for (it.Initialize(itC.Value()); it.More(); it.Next()) {
2003 if (it.Value().ShapeType() == TopAbs_COMPOUND) {
2004 if (it.Value().IsSame(aSubShape))
2008 CL.Append(it.Value());
2013 TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
2014 TopTools_MapOfShape M;
2015 for (; anExp.More(); anExp.Next()) {
2016 if (M.Add(anExp.Current())) {
2017 if (anExp.Current().IsSame(aSubShape))
2024 SetErrorCode("The sub-shape does not belong to the main shape");
2028 //=============================================================================
2030 * GetShapeTypeString
2032 //=============================================================================
2033 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
2037 TCollection_AsciiString aTypeName ("Null Shape");
2039 TopoDS_Shape aShape = theShape->GetValue();
2040 if (aShape.IsNull())
2043 switch (aShape.ShapeType() )
2045 case TopAbs_COMPOUND:
2046 aTypeName = "Compound";
2048 case TopAbs_COMPSOLID:
2049 aTypeName = "Compound Solid";
2052 aTypeName = "Solid";
2055 aTypeName = "Shell";
2059 BRepAdaptor_Surface surf (TopoDS::Face(aShape));
2060 if (surf.GetType() == GeomAbs_Plane)
2061 aTypeName = "Plane";
2062 else if (surf.GetType() == GeomAbs_Cylinder)
2063 aTypeName = "Cylindrical Face";
2064 else if (surf.GetType() == GeomAbs_Sphere)
2065 aTypeName = "Spherical Face";
2066 else if (surf.GetType() == GeomAbs_Torus)
2067 aTypeName = "Toroidal Face";
2068 else if (surf.GetType() == GeomAbs_Cone)
2069 aTypeName = "Conical Face";
2071 aTypeName = "GEOM::FACE";
2079 BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
2080 if (curv.GetType() == GeomAbs_Line) {
2081 if ((Abs(curv.FirstParameter()) >= 1E6) ||
2082 (Abs(curv.LastParameter()) >= 1E6))
2086 } else if (curv.GetType() == GeomAbs_Circle) {
2087 if (curv.IsClosed())
2088 aTypeName = "Circle";
2097 aTypeName = "Vertex";
2100 aTypeName = "Shape";
2103 aTypeName = "Shape of unknown type";
2109 //=============================================================================
2111 * IsSubShapeBelongsTo
2113 //=============================================================================
2114 Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject,
2115 const Standard_Integer theSubObjectIndex,
2116 Handle(GEOM_Object) theObject,
2117 const Standard_Integer theObjectIndex)
2121 if ( theObject.IsNull() || theSubObject.IsNull() )
2124 TopoDS_Shape shape = theObject->GetValue();
2125 TopoDS_Shape subShape = theSubObject->GetValue();
2127 if ( shape.IsNull() || subShape.IsNull() )
2130 TopTools_IndexedMapOfShape anIndices;
2131 if ( theObjectIndex > 0 ) {
2132 TopExp::MapShapes( shape, anIndices );
2133 shape = anIndices.FindKey(theObjectIndex);
2136 if ( theSubObjectIndex > 0 ) {
2137 TopExp::MapShapes( subShape, anIndices );
2138 subShape = anIndices.FindKey(theSubObjectIndex);
2142 TopExp::MapShapes( shape, anIndices );
2144 const Standard_Boolean isBelongTo = anIndices.Contains(subShape);
2151 //=============================================================================
2155 //=============================================================================
2156 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
2157 (Handle(GEOM_Object) theShape,
2158 const Standard_Integer theShapeType)
2161 Standard_Integer nbShapes = 0;
2163 if (theShape.IsNull()) return -1;
2164 TopoDS_Shape aShape = theShape->GetValue();
2165 if (aShape.IsNull()) return -1;
2168 TopTools_MapOfShape mapShape;
2170 if (aShape.ShapeType() == TopAbs_COMPOUND &&
2171 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2172 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
2173 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
2174 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
2175 for (; It.More(); It.Next()) {
2176 if (mapShape.Add(It.Value())) {
2177 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2178 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
2184 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
2185 for (; exp.More(); exp.Next())
2186 if (mapShape.Add(exp.Current()))
2192 if (theShapeType == TopAbs_FLAT) {
2193 TopTools_MapOfShape aMapOfShape;
2194 TopTools_ListOfShape aListOfShape;
2195 AddFlatSubShapes(aShape, aListOfShape, aMapOfShape);
2196 nbShapes = aListOfShape.Extent();
2200 int iType, nbTypes [TopAbs_SHAPE];
2201 for (iType = 0; iType < TopAbs_SHAPE; ++iType)
2203 nbTypes[aShape.ShapeType()]++;
2205 TopTools_MapOfShape aMapOfShape;
2206 aMapOfShape.Add(aShape);
2207 TopTools_ListOfShape aListOfShape;
2208 aListOfShape.Append(aShape);
2210 TopTools_ListIteratorOfListOfShape itL (aListOfShape);
2211 for (; itL.More(); itL.Next()) {
2212 TopoDS_Iterator it (itL.Value());
2213 for (; it.More(); it.Next()) {
2214 TopoDS_Shape s = it.Value();
2215 if (aMapOfShape.Add(s)) {
2216 aListOfShape.Append(s);
2217 nbTypes[s.ShapeType()]++;
2222 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
2223 nbShapes = aMapOfShape.Extent();
2225 nbShapes = nbTypes[theShapeType];
2228 catch (Standard_Failure& aFail) {
2229 SetErrorCode(aFail.GetMessageString());
2237 //=============================================================================
2241 //=============================================================================
2242 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
2246 if (theShape.IsNull()) return NULL;
2249 //Add a new reversed object
2250 Handle(GEOM_Object) aReversed = GetEngine()->AddObject(theShape->GetType());
2252 //Add a new Revese function
2253 Handle(GEOM_Function) aFunction;
2254 aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
2255 if (aFunction.IsNull()) return NULL;
2257 //Check if the function is set correctly
2258 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
2260 GEOMImpl_IShapes aSI (aFunction);
2262 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2263 if (aRefShape.IsNull()) return NULL;
2265 aSI.SetBase(aRefShape);
2267 //Compute the sub-shape value
2270 if (!GetSolver()->ComputeFunction(aFunction)) {
2271 SetErrorCode("Shape driver failed to reverse shape");
2275 catch (Standard_Failure& aFail) {
2276 SetErrorCode(aFail.GetMessageString());
2280 //Make a Python command
2281 GEOM::TPythonDump(aFunction) << aReversed
2282 << " = geompy.ChangeOrientation(" << theShape << ")";
2287 Handle(GEOM_Object) aReversed;
2289 GEOM_Engine* anEngine = GetEngine();
2290 //GEOMImpl_Gen* aGen = dynamic_cast<GEOMImpl_Gen*>(anEngine);
2291 GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine;
2294 GEOMImpl_IHealingOperations* anIHealingOperations =
2295 aGen->GetIHealingOperations();
2296 aReversed = anIHealingOperations->ChangeOrientationCopy(theShape);
2297 SetErrorCode(anIHealingOperations->GetErrorCode());
2303 //=============================================================================
2307 //=============================================================================
2308 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
2309 (Handle(GEOM_Object) theShape)
2313 if (theShape.IsNull()) return NULL;
2314 TopoDS_Shape aShape = theShape->GetValue();
2315 if (aShape.IsNull()) return NULL;
2317 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
2319 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2320 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2321 (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2323 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2326 SetErrorCode("The given shape has no faces");
2330 TopTools_IndexedMapOfShape anIndices;
2331 TopExp::MapShapes(aShape, anIndices);
2333 Standard_Integer id;
2334 for (; ind <= nbFaces; ind++) {
2335 if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
2336 id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
2341 //The explode doesn't change object so no new function is required.
2342 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
2344 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2345 #ifdef DUMP_SUBSHAPE_IDS
2346 //Make a Python command
2347 GEOM::TPythonDump(aFunction, /*append=*/true)
2348 << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
2349 #endif // DUMP_SUBSHAPE_IDS
2355 //=======================================================================
2356 //function : GetSharedShapes
2358 //=======================================================================
2359 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2360 (Handle(GEOM_Object) theShape1,
2361 Handle(GEOM_Object) theShape2,
2362 const Standard_Integer theShapeType)
2366 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
2368 TopoDS_Shape aShape1 = theShape1->GetValue();
2369 TopoDS_Shape aShape2 = theShape2->GetValue();
2371 if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
2373 TopTools_IndexedMapOfShape anIndices;
2374 TopExp::MapShapes(aShape1, anIndices);
2375 Handle(TColStd_HArray1OfInteger) anArray;
2377 TopTools_IndexedMapOfShape mapShape1;
2378 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
2380 Handle(GEOM_Object) anObj;
2381 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2382 TCollection_AsciiString anAsciiList, anEntry;
2384 TopTools_MapOfShape mapShape2;
2385 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2386 for (; exp.More(); exp.Next()) {
2387 TopoDS_Shape aSS = exp.Current();
2388 if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
2389 anArray = new TColStd_HArray1OfInteger(1,1);
2390 anArray->SetValue(1, anIndices.FindIndex(aSS));
2391 anObj = GetEngine()->AddSubShape(theShape1, anArray);
2392 aSeq->Append(anObj);
2394 // for python command
2395 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2396 anAsciiList += anEntry;
2401 if (aSeq->IsEmpty()) {
2402 SetErrorCode(NOT_FOUND_ANY);
2406 //Make a Python command
2407 anAsciiList.Trunc(anAsciiList.Length() - 1);
2409 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2411 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2412 << "] = geompy.GetSharedShapes(" << theShape1 << ", "
2413 << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
2419 //=======================================================================
2420 //function : GetSharedShapes
2423 // NOTE on the implementation
2425 // 1) Resulting sub-shapes are published as a children of the 1st input shape
2426 // from theShapes list. Due to this reason only direct sub-shapes of the 1st
2427 // shape can be contained in the result of the operation (i.e. shares between
2428 // 2nd/3rd, etc couples cannot be retrieved.
2429 // 2) An exception from above case is when a single compound is specified as an
2430 // input. In this case we search shares between its top-level content, so we
2431 // are able to search shares between all possible couples of shapes.
2432 // 3) Parameter theMultiShare controls what types of shares to search:
2433 // - True: get sub-shapes that are shared between ALL input shapes;
2434 // - False: get shares between couples of input sub-shapes (see points 1 and 2).
2436 // Thus, we have the following cases:
2437 // [1] theShapes = N shapes (N>1), theMultiShare = True
2438 // Result: sub-shapes that are shared by all theShapes
2439 // [2] theShapes = N shapes (N>1), theMultiShare = False
2440 // Result: sub-shapes of 1st shape from theShapes that are shared with any shape
2442 // [3] theShapes = 1 shape, theMultiShare = True
2443 // Result: sub-shapes that are shared by all top-level sub-objects of theShapes[0]
2444 // [4] theShapes = 1 shape, theMultiShare = False
2445 // Result: sub-shapes of all possible couples of all top-level sub-objects of
2447 //=======================================================================
2448 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2449 (std::list<Handle(GEOM_Object)> & theShapes,
2450 const Standard_Integer theShapeType,
2451 const bool theMultiShare)
2455 int aLen = theShapes.size();
2456 if (aLen < 1) return NULL;
2458 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
2460 // main object is always first in the input list
2461 // it is the object from which sub-shapes indices are taken
2462 // and where results are published
2463 Handle(GEOM_Object) aMainObj = *it;
2464 Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
2466 // collect all shapes from the input list (including first one) for processing
2467 TopTools_SequenceOfShape shapeSeq;
2468 for (; it != theShapes.end(); it++) {
2469 Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
2470 if (aRefShape.IsNull()) {
2471 SetErrorCode("NULL shape for GetSharedShapes");
2474 TopoDS_Shape aShape = aRefShape->GetValue();
2475 if (aShape.IsNull()) {
2476 SetErrorCode("NULL shape for GetSharedShapes");
2479 shapeSeq.Append( aShape );
2482 // if only single shape is specified as input
2483 // collect all ites top-level sub-shapes for processing
2484 if ( shapeSeq.Length() == 1 )
2486 TopoDS_Shape aShape = shapeSeq.First();
2488 for ( TopoDS_Iterator it( aShape ); it.More(); it.Next() )
2489 shapeSeq.Append( it.Value() );
2492 // map all sub-shapes in a main shape to their indices
2493 TopTools_IndexedMapOfShape anIndices;
2494 TopExp::MapShapes(aMainShape->GetValue(), anIndices);
2495 TopTools_MapOfShape mapShape;
2497 // find shared shapes
2499 // here we will collect all shares
2500 TopTools_ListOfShape aShared;
2502 // number of iterations
2503 int nbIters = theMultiShare || theShapes.size() > 1 ? 1 : shapeSeq.Length()-1;
2504 // numShares factor to search (i.e. by what nb of shapes each found sub-shape should be shared)
2505 int nbShares = theMultiShare ? shapeSeq.Length()-1 : 1;
2507 for ( int iter = 1; iter <= nbIters; iter++) {
2508 for ( int ind = iter+1; ind <= shapeSeq.Length(); ind++) {
2509 if ( ind-1+nbShares > shapeSeq.Length() ) break;
2510 TopoDS_Compound aCurrSelection;
2511 TopoDS_Shape aShape1 = shapeSeq.Value( iter );
2512 TopTools_IndexedMapOfShape mapSelected;
2513 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
2514 for ( int s = 0; s < nbShares; s++ ) {
2516 TopoDS_Compound aCompound;
2517 B.MakeCompound(aCompound);
2518 const TopoDS_Shape& aShape2 = shapeSeq.Value( ind+s );
2519 TopTools_MapOfShape mapShape2;
2520 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2521 for (; exp.More(); exp.Next()) {
2522 const TopoDS_Shape& aSS = exp.Current();
2523 if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
2524 B.Add(aCompound, aSS);
2527 mapSelected.Clear();
2528 aCurrSelection = aCompound;
2529 TopExp::MapShapes(aCurrSelection, TopAbs_ShapeEnum(theShapeType), mapSelected);
2531 TopoDS_Iterator itSel(aCurrSelection, Standard_True, Standard_True);
2532 for (; itSel.More(); itSel.Next()) {
2533 const TopoDS_Shape& aSS = itSel.Value();
2534 if (mapShape.Add(aSS) )
2535 aShared.Append(aSS);
2540 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2542 if (aShared.IsEmpty()){
2543 SetErrorCode(NOT_FOUND_ANY);
2547 // create GEOM_Object for each found shared shape (collected in aShared)
2548 TCollection_AsciiString anAsciiList;
2549 Handle(GEOM_Object) anObj;
2550 TopTools_ListIteratorOfListOfShape itSub (aShared);
2551 for (; itSub.More(); itSub.Next()) {
2552 TopoDS_Shape aValue = itSub.Value();
2553 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2554 anArray->SetValue(1, anIndices.FindIndex(aValue));
2555 anObj = GetEngine()->AddSubShape(aMainObj, anArray);
2556 aSeq->Append(anObj);
2558 // for python command
2559 TCollection_AsciiString anEntry;
2560 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2561 anAsciiList += anEntry;
2565 // make a Python command
2566 anAsciiList.Trunc(anAsciiList.Length() - 1);
2568 GEOM::TPythonDump pd (anObj->GetLastFunction());
2569 pd << "[" << anAsciiList.ToCString()
2570 << "] = geompy.GetSharedShapesMulti(";
2575 it = theShapes.begin();
2577 while (it != theShapes.end()) {
2578 pd << ", " << (*it++);
2583 pd << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theMultiShare << ")";
2589 //=============================================================================
2593 //=============================================================================
2594 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump,
2595 const GEOMAlgo_State theState)
2598 case GEOMAlgo_ST_IN:
2599 theDump << "GEOM.ST_IN";
2601 case GEOMAlgo_ST_OUT:
2602 theDump << "GEOM.ST_OUT";
2604 case GEOMAlgo_ST_ON:
2605 theDump << "GEOM.ST_ON";
2607 case GEOMAlgo_ST_ONIN:
2608 theDump << "GEOM.ST_ONIN";
2610 case GEOMAlgo_ST_ONOUT:
2611 theDump << "GEOM.ST_ONOUT";
2614 theDump << "GEOM.ST_UNKNOWN";
2620 //=======================================================================
2621 //function : checkTypeShapesOn
2623 * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
2624 * \param theShapeType - the shape type to check
2625 * \retval bool - result of the check
2627 //=======================================================================
2628 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
2630 if (theShapeType != TopAbs_VERTEX &&
2631 theShapeType != TopAbs_EDGE &&
2632 theShapeType != TopAbs_FACE &&
2633 theShapeType != TopAbs_SOLID) {
2634 SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
2640 //=======================================================================
2641 //function : makePlane
2643 * \brief Creates Geom_Plane
2644 * \param theAx1 - shape object defining plane parameters
2645 * \retval Handle(Geom_Surface) - resulting surface
2647 //=======================================================================
2648 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
2650 if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
2651 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2652 TopoDS_Vertex V1, V2;
2653 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2654 if (V1.IsNull() || V2.IsNull()) {
2655 SetErrorCode("Bad edge given for the plane normal vector");
2658 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2659 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2660 if (aVec.Magnitude() < Precision::Confusion()) {
2661 SetErrorCode("Vector with null magnitude given");
2664 return new Geom_Plane(aLoc, aVec);
2667 //=======================================================================
2668 //function : makeCylinder
2670 * \brief Creates Geom_CylindricalSurface
2671 * \param theAx1 - edge defining cylinder axis
2672 * \param theRadius - cylinder radius
2673 * \retval Handle(Geom_Surface) - resulting surface
2675 //=======================================================================
2676 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
2677 const Standard_Real theRadius)
2679 //Axis of the cylinder
2680 if (anAxis.ShapeType() != TopAbs_EDGE) {
2681 SetErrorCode("Not an edge given for the axis");
2684 TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
2685 TopoDS_Vertex V1, V2;
2686 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2687 if (V1.IsNull() || V2.IsNull()) {
2688 SetErrorCode("Bad edge given for the axis");
2691 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2692 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2693 if (aVec.Magnitude() < Precision::Confusion()) {
2694 SetErrorCode("Vector with null magnitude given");
2698 gp_Ax3 anAx3 (aLoc, aVec);
2699 return new Geom_CylindricalSurface(anAx3, theRadius);
2702 //=======================================================================
2703 //function : getShapesOnBoxIDs
2705 * \brief Find IDs of sub-shapes complying with given status about surface
2706 * \param theBox - the box to check state of sub-shapes against
2707 * \param theShape - the shape to explore
2708 * \param theShapeType - type of sub-shape of theShape
2709 * \param theState - required state
2710 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2712 //=======================================================================
2713 Handle(TColStd_HSequenceOfInteger)
2714 GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2715 const Handle(GEOM_Object)& theShape,
2716 const Standard_Integer theShapeType,
2717 GEOMAlgo_State theState)
2719 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2721 TopoDS_Shape aBox = theBox->GetValue();
2722 TopoDS_Shape aShape = theShape->GetValue();
2724 // Check presence of triangulation, build if need
2725 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2726 SetErrorCode("Cannot build triangulation on the shape");
2731 GEOMAlgo_FinderShapeOn2 aFinder;
2732 Standard_Real aTol = 0.0001; // default value
2734 Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
2735 aClsfBox->SetBox(aBox);
2737 aFinder.SetShape(aShape);
2738 aFinder.SetTolerance(aTol);
2739 aFinder.SetClsf(aClsfBox);
2740 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2741 aFinder.SetState(theState);
2744 // Interpret results
2745 Standard_Integer iErr = aFinder.ErrorStatus();
2746 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2748 MESSAGE(" iErr : " << iErr);
2749 TCollection_AsciiString aMsg (" iErr : ");
2750 aMsg += TCollection_AsciiString(iErr);
2754 Standard_Integer iWrn = aFinder.WarningStatus();
2755 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2757 MESSAGE(" *** iWrn : " << iWrn);
2760 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2762 if (listSS.Extent() < 1) {
2763 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2764 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2768 // Fill sequence of object IDs
2769 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2771 TopTools_IndexedMapOfShape anIndices;
2772 TopExp::MapShapes(aShape, anIndices);
2774 TopTools_ListIteratorOfListOfShape itSub (listSS);
2775 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2776 int id = anIndices.FindIndex(itSub.Value());
2777 aSeqOfIDs->Append(id);
2783 //=======================================================================
2784 //function : GetShapesOnBoxIDs
2786 * \brief Find sub-shapes complying with given status about surface
2787 * \param theBox - the box to check state of sub-shapes against
2788 * \param theShape - the shape to explore
2789 * \param theShapeType - type of sub-shape of theShape
2790 * \param theState - required state
2791 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2793 //=======================================================================
2794 Handle(TColStd_HSequenceOfInteger)
2795 GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2796 const Handle(GEOM_Object)& theShape,
2797 const Standard_Integer theShapeType,
2798 GEOMAlgo_State theState)
2800 // Find sub-shapes ids
2801 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2802 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2803 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2806 // The GetShapesOnBox() doesn't change object so no new function is required.
2807 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
2809 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2810 #ifdef DUMP_SUBSHAPE_IDS
2811 // Make a Python command
2812 GEOM::TPythonDump(aFunction, /*append=*/true)
2813 << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
2816 << TopAbs_ShapeEnum(theShapeType) << ", "
2818 #endif // DUMP_SUBSHAPE_IDS
2824 //=======================================================================
2825 //function : GetShapesOnBox
2827 * \brief Find sub-shapes complying with given status about surface
2828 * \param theBox - the box to check state of sub-shapes against
2829 * \param theShape - the shape to explore
2830 * \param theShapeType - type of sub-shape of theShape
2831 * \param theState - required state
2832 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2834 //=======================================================================
2835 Handle(TColStd_HSequenceOfTransient)
2836 GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
2837 const Handle(GEOM_Object)& theShape,
2838 const Standard_Integer theShapeType,
2839 GEOMAlgo_State theState)
2841 // Find sub-shapes ids
2842 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2843 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2844 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2847 // Find objects by indices
2848 TCollection_AsciiString anAsciiList;
2849 Handle(TColStd_HSequenceOfTransient) aSeq;
2850 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2851 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2854 // Make a Python command
2856 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2857 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2859 GEOM::TPythonDump(aFunction)
2860 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
2863 << TopAbs_ShapeEnum(theShapeType) << ", "
2870 //=======================================================================
2871 //function : getShapesOnShapeIDs
2873 * \brief Find IDs of sub-shapes complying with given status about surface
2874 * \param theCheckShape - the shape to check state of sub-shapes against
2875 * \param theShape - the shape to explore
2876 * \param theShapeType - type of sub-shape of theShape
2877 * \param theState - required state
2878 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2880 //=======================================================================
2881 Handle(TColStd_HSequenceOfInteger)
2882 GEOMImpl_IShapesOperations::getShapesOnShapeIDs
2883 (const Handle(GEOM_Object)& theCheckShape,
2884 const Handle(GEOM_Object)& theShape,
2885 const Standard_Integer theShapeType,
2886 GEOMAlgo_State theState)
2888 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2890 TopoDS_Shape aCheckShape = theCheckShape->GetValue();
2891 TopoDS_Shape aShape = theShape->GetValue();
2892 TopTools_ListOfShape res;
2894 // Check presence of triangulation, build if need
2895 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2896 SetErrorCode("Cannot build triangulation on the shape");
2900 // Compute classification tolerance.
2901 TopTools_IndexedMapOfShape aMapVtx;
2902 Standard_Real aTol = Precision::Confusion();
2904 TopExp::MapShapes(aShape, TopAbs_VERTEX, aMapVtx);
2907 Standard_Integer aNbVtx = aMapVtx.Extent();
2909 for (i = 1; i <= aNbVtx; ++i) {
2910 const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(i));
2911 const Standard_Real aVtxTol = BRep_Tool::Tolerance(aVtx);
2913 if (aTol < aVtxTol) {
2918 // Bound the tolerance value.
2919 if (aTol > 0.0001) {
2924 GEOMAlgo_FinderShapeOn2 aFinder;
2926 Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
2927 aClsfSolid->SetShape(aCheckShape);
2929 aFinder.SetShape(aShape);
2930 aFinder.SetTolerance(aTol);
2931 aFinder.SetClsf(aClsfSolid);
2932 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2933 aFinder.SetState(theState);
2936 // Interpret results
2937 Standard_Integer iErr = aFinder.ErrorStatus();
2938 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2941 SetErrorCode("theCheckShape must be a solid");
2944 MESSAGE(" iErr : " << iErr);
2945 TCollection_AsciiString aMsg (" iErr : ");
2946 aMsg += TCollection_AsciiString(iErr);
2951 Standard_Integer iWrn = aFinder.WarningStatus();
2952 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2954 MESSAGE(" *** iWrn : " << iWrn);
2957 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2959 if (listSS.Extent() < 1) {
2960 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2961 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2964 // Fill sequence of object IDs
2965 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2967 TopTools_IndexedMapOfShape anIndices;
2968 TopExp::MapShapes(aShape, anIndices);
2970 TopTools_ListIteratorOfListOfShape itSub (listSS);
2971 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2972 int id = anIndices.FindIndex(itSub.Value());
2973 aSeqOfIDs->Append(id);
2979 //=======================================================================
2980 //function : GetShapesOnShapeIDs
2982 * \brief Find sub-shapes complying with given status about surface
2983 * \param theCheckShape - the shape to check state of sub-shapes against
2984 * \param theShape - the shape to explore
2985 * \param theShapeType - type of sub-shape of theShape
2986 * \param theState - required state
2987 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2989 //=======================================================================
2990 Handle(TColStd_HSequenceOfInteger)
2991 GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
2992 (const Handle(GEOM_Object)& theCheckShape,
2993 const Handle(GEOM_Object)& theShape,
2994 const Standard_Integer theShapeType,
2995 GEOMAlgo_State theState)
2997 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2998 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
3000 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3003 // The GetShapesOnShape() doesn't change object so no new function is required.
3004 Handle(GEOM_Function) aFunction =
3005 GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
3007 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
3008 #ifdef DUMP_SUBSHAPE_IDS
3009 // Make a Python command
3010 GEOM::TPythonDump(aFunction, /*append=*/true)
3011 << "listShapesOnShapeIDs = geompy.GetShapesOnShapeIDs("
3012 << theCheckShape << ", "
3014 << TopAbs_ShapeEnum(theShapeType) << ", "
3016 #endif // DUMP_SUBSHAPE_IDS
3022 //=======================================================================
3023 //function : GetShapesOnShape
3025 * \brief Find sub-shapes complying with given status about surface
3026 * \param theCheckShape - the shape to check state of sub-shapes against
3027 * \param theShape - the shape to explore
3028 * \param theShapeType - type of sub-shape of theShape
3029 * \param theState - required state
3030 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
3032 //=======================================================================
3033 Handle(TColStd_HSequenceOfTransient)
3034 GEOMImpl_IShapesOperations::GetShapesOnShape
3035 (const Handle(GEOM_Object)& theCheckShape,
3036 const Handle(GEOM_Object)& theShape,
3037 const Standard_Integer theShapeType,
3038 GEOMAlgo_State theState)
3040 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3041 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
3042 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3045 // Find objects by indices
3046 TCollection_AsciiString anAsciiList;
3047 Handle(TColStd_HSequenceOfTransient) aSeq;
3048 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
3050 if ( aSeq.IsNull() || aSeq->IsEmpty() )
3053 // Make a Python command
3055 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3056 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3058 GEOM::TPythonDump(aFunction)
3059 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
3060 << theCheckShape << ", "
3062 << TopAbs_ShapeEnum(theShapeType) << ", "
3069 //=======================================================================
3070 //function : GetShapesOnShapeAsCompound
3071 //=======================================================================
3072 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
3073 (const Handle(GEOM_Object)& theCheckShape,
3074 const Handle(GEOM_Object)& theShape,
3075 const Standard_Integer theShapeType,
3076 GEOMAlgo_State theState)
3078 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3079 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
3081 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3084 // Find objects by indices
3085 TCollection_AsciiString anAsciiList;
3086 Handle(TColStd_HSequenceOfTransient) aSeq;
3087 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
3089 if ( aSeq.IsNull() || aSeq->IsEmpty() )
3092 TopoDS_Compound aCompound;
3094 B.MakeCompound(aCompound);
3096 for(; i<=aSeq->Length(); i++) {
3097 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
3098 TopoDS_Shape aShape_i = anObj->GetValue();
3099 B.Add(aCompound,aShape_i);
3102 //Add a new result object
3103 Handle(GEOM_Object) aRes = GetEngine()->AddObject(GEOM_SHAPES_ON_SHAPE);
3104 Handle(GEOM_Function) aFunction =
3105 aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
3106 aFunction->SetValue(aCompound);
3109 aSeq->Append( theCheckShape->GetLastFunction() );
3110 aSeq->Append( theShape->GetLastFunction() );
3112 GEOMImpl_IShapes aCI( aFunction );
3113 aCI.SetShapes( aSeq );
3114 aCI.SetSubShapeType( theShapeType );
3115 aCI.SetTolerance( theState );
3117 GEOM::TPythonDump(aFunction)
3118 << aRes << " = geompy.GetShapesOnShapeAsCompound("
3119 << theCheckShape << ", "
3121 << TopAbs_ShapeEnum(theShapeType) << ", "
3129 //=============================================================================
3131 * GetSubShapeEdgeSorted
3133 //=============================================================================
3134 Handle(TColStd_HSequenceOfTransient)
3135 GEOMImpl_IShapesOperations::GetSubShapeEdgeSorted
3136 (const Handle(GEOM_Object) &theShape,
3137 const Handle(GEOM_Object) &theStartPoint)
3139 // Get the sorted edges indices.
3140 Handle(TColStd_HSequenceOfInteger) aSortedIDs =
3141 getSubShapeEdgeSortedIDs(theShape, theStartPoint);
3143 // Get object by indices.
3144 TCollection_AsciiString anAsciiList;
3145 Handle(TColStd_HSequenceOfTransient) aSeq =
3146 getObjectsShapesOn(theShape, aSortedIDs, anAsciiList);
3148 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3149 SetErrorCode("Empty sequence of edges");
3153 // Make a Python command
3154 Handle(GEOM_Object) anObj =
3155 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3156 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3158 GEOM::TPythonDump(aFunction)
3159 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapeEdgeSorted("
3160 << theShape << ", " << theStartPoint << ")";
3167 //=============================================================================
3169 * GetSubShapesWithTolerance
3171 //=============================================================================
3172 Handle(TColStd_HSequenceOfTransient)
3173 GEOMImpl_IShapesOperations::GetSubShapesWithTolerance
3174 (const Handle(GEOM_Object) &theShape,
3175 const Standard_Integer theShapeType,
3176 const GEOMUtils::ComparisonCondition theCondition,
3177 const Standard_Real theTolerance)
3179 if (theShape.IsNull()) {
3180 SetErrorCode("NULL GEOM object");
3184 TopoDS_Shape aShape = theShape->GetValue();
3186 if (aShape.IsNull()) {
3187 SetErrorCode("NULL Shape");
3191 if (theShapeType != TopAbs_FACE && theShapeType != TopAbs_EDGE &&
3192 theShapeType != TopAbs_VERTEX && aShape.ShapeType() >= theShapeType) {
3193 SetErrorCode("Invalid shape type");
3197 TopTools_IndexedMapOfShape anIndices;
3198 TopTools_MapOfShape aMapFence;
3199 TopExp_Explorer anExp(aShape,
3200 (TopAbs_ShapeEnum) theShapeType);
3201 Handle(TColStd_HSequenceOfInteger) anIDs = new TColStd_HSequenceOfInteger;
3203 TopExp::MapShapes(aShape, anIndices);
3205 for (; anExp.More(); anExp.Next()) {
3206 const TopoDS_Shape &aSubShape = anExp.Current();
3208 if (aMapFence.Add(aSubShape)) {
3209 // Compute tolerance
3210 Standard_Real aTolerance = -1.;
3212 switch (aSubShape.ShapeType()) {
3214 aTolerance = BRep_Tool::Tolerance(TopoDS::Face(aSubShape));
3217 aTolerance = BRep_Tool::Tolerance(TopoDS::Edge(aSubShape));
3220 aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aSubShape));
3226 if (aTolerance < 0.) {
3230 // Compare the tolerance with reference value.
3231 if (GEOMUtils::IsFitCondition (theCondition, aTolerance, theTolerance)) {
3232 anIDs->Append(anIndices.FindIndex(aSubShape));
3237 if (anIDs->IsEmpty()) {
3238 SetErrorCode("Empty sequence of sub-shapes");
3242 // Get objects by indices.
3243 TCollection_AsciiString anAsciiList;
3244 Handle(TColStd_HSequenceOfTransient) aSeq =
3245 getObjectsShapesOn(theShape, anIDs, anAsciiList);
3247 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3248 SetErrorCode("Empty sequence of edges");
3252 // Make a Python command
3253 Handle(GEOM_Object) anObj =
3254 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3255 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3257 GEOM::TPythonDump(aFunction)
3258 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapesWithTolerance("
3259 << theShape << ", " << theShapeType << ", " << theCondition << ", "
3260 << theTolerance << ")";
3267 //=============================================================================
3271 //=============================================================================
3272 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeExtraction
3273 (const Handle(GEOM_Object) &theShape,
3274 const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs,
3275 std::list<ExtractionStat> &theStats)
3279 if (theShape.IsNull()) {
3283 //Add a new Result object
3284 Handle(GEOM_Object) aResult =
3285 GetEngine()->AddObject(GEOM_EXTRACTION);
3287 //Add a new Extraction function
3288 Handle(GEOM_Function) aFunction =
3289 aResult->AddFunction(GEOMImpl_ShapeDriver::GetID(), EXTRACTION);
3291 //Check if the function is set correctly
3292 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
3296 Handle(GEOM_Function) aShape = theShape->GetLastFunction();
3298 if (aShape.IsNull()) {
3302 GEOMImpl_IExtract aCI (aFunction);
3304 aCI.SetShape(aShape);
3305 aCI.SetSubShapeIDs(theSubShapeIDs);
3307 //Compute the Edge value
3310 if (!GetSolver()->ComputeFunction(aFunction)) {
3311 SetErrorCode("Shape driver failed");
3316 catch (Standard_Failure& aFail) {
3317 SetErrorCode(aFail.GetMessageString());
3322 // Fill in statistics.
3325 Handle(TColStd_HArray1OfInteger) aStatIDsArray[3] =
3326 { aCI.GetRemovedIDs(), aCI.GetModifiedIDs(), aCI.GetAddedIDs() };
3330 for (j = 0; j < 3; ++j) {
3331 if (!aStatIDsArray[j].IsNull()) {
3332 const int anUpperID = aStatIDsArray[j]->Upper();
3333 ExtractionStat aStat;
3335 for (i = aStatIDsArray[j]->Lower(); i <= anUpperID; ++i) {
3336 aStat.indices.push_back(aStatIDsArray[j]->Value(i));
3339 aStat.type = (ExtractionStatType) j;
3340 theStats.push_back(aStat);
3344 //Make a Python command
3345 GEOM::TPythonDump pd(aFunction);
3347 pd << aResult << " = geompy.MakeExtraction(" << theShape << ", [";
3349 if (!theSubShapeIDs.IsNull()) {
3350 const int aNbIDs = theSubShapeIDs->Upper();
3352 for (i = theSubShapeIDs->Lower(); i < aNbIDs; ++i) {
3353 pd << theSubShapeIDs->Value(i) << ", ";
3356 // Dump the last value without a comma.
3357 pd << theSubShapeIDs->Value(i);
3367 //=======================================================================
3368 //function : getShapesOnSurfaceIDs
3370 * \brief Find IDs of sub-shapes complying with given status about surface
3371 * \param theSurface - the surface to check state of sub-shapes against
3372 * \param theShape - the shape to explore
3373 * \param theShapeType - type of sub-shape of theShape
3374 * \param theState - required state
3375 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3377 //=======================================================================
3378 Handle(TColStd_HSequenceOfInteger)
3379 GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
3380 const TopoDS_Shape& theShape,
3381 TopAbs_ShapeEnum theShapeType,
3382 GEOMAlgo_State theState)
3384 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3386 // Check presence of triangulation, build if need
3387 if (theShapeType != TopAbs_VERTEX &&
3388 !GEOMUtils::CheckTriangulation(theShape)) {
3389 SetErrorCode("Cannot build triangulation on the shape");
3393 // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
3394 // Compute tolerance
3395 Standard_Real T, VertMax = -RealLast();
3398 for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
3399 TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
3400 T = BRep_Tool::Tolerance(Vertex);
3405 catch (Standard_Failure& aFail) {
3406 SetErrorCode(aFail.GetMessageString());
3409 // END: Mantis issue 0020961
3412 GEOMAlgo_FinderShapeOn2 aFinder;
3413 Handle(GEOMAlgo_ClsfSurf) aClsfSurf = new GEOMAlgo_ClsfSurf;
3414 Standard_Real aTol = VertMax; // Mantis issue 0020961
3416 aClsfSurf->SetSurface(theSurface);
3417 aFinder.SetShape(theShape);
3418 aFinder.SetTolerance(aTol);
3419 aFinder.SetClsf(aClsfSurf);
3420 aFinder.SetShapeType(theShapeType);
3421 aFinder.SetState(theState);
3423 // Sets the minimal number of inner points for the faces that do not have own
3424 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
3426 aFinder.SetNbPntsMin(3);
3427 // Sets the maximal number of inner points for edges or faces.
3428 // It is useful for the cases when this number is very big (e.g =2000) to improve
3429 // the performance. If this value =0, all inner points will be taken into account.
3431 aFinder.SetNbPntsMax(100);
3435 // Interpret results
3436 Standard_Integer iErr = aFinder.ErrorStatus();
3437 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
3439 MESSAGE(" iErr : " << iErr);
3440 TCollection_AsciiString aMsg (" iErr : ");
3441 aMsg += TCollection_AsciiString(iErr);
3445 Standard_Integer iWrn = aFinder.WarningStatus();
3446 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
3448 MESSAGE(" *** iWrn : " << iWrn);
3451 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
3453 if (listSS.Extent() < 1) {
3454 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
3455 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
3459 // Fill sequence of object IDs
3460 aSeqOfIDs = new TColStd_HSequenceOfInteger;
3462 TopTools_IndexedMapOfShape anIndices;
3463 TopExp::MapShapes(theShape, anIndices);
3465 TopTools_ListIteratorOfListOfShape itSub (listSS);
3466 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3467 int id = anIndices.FindIndex(itSub.Value());
3468 aSeqOfIDs->Append(id);
3474 //=======================================================================
3475 //function : getObjectsShapesOn
3477 * \brief Find shape objects and their entries by their ids
3478 * \param theShapeIDs - incoming shape ids
3479 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3480 * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
3482 //=======================================================================
3483 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
3484 getObjectsShapesOn(const Handle(GEOM_Object)& theShape,
3485 const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
3486 TCollection_AsciiString & theShapeEntries)
3488 Handle(TColStd_HSequenceOfTransient) aSeq;
3490 if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
3492 aSeq = new TColStd_HSequenceOfTransient;
3493 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3494 TCollection_AsciiString anEntry;
3495 for ( int i = 1; i <= theShapeIDs->Length(); ++i )
3497 anArray->SetValue(1, theShapeIDs->Value( i ));
3498 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3499 aSeq->Append( anObj );
3501 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3502 if ( i != 1 ) theShapeEntries += ",";
3503 theShapeEntries += anEntry;
3509 //=============================================================================
3511 * getSubShapeEdgeSortedIDs
3513 //=============================================================================
3514 Handle(TColStd_HSequenceOfInteger)
3515 GEOMImpl_IShapesOperations::getSubShapeEdgeSortedIDs
3516 (const Handle(GEOM_Object) &theShape,
3517 const Handle(GEOM_Object) &theStartPoint)
3519 Handle(TColStd_HSequenceOfInteger) aResult;
3521 if (theShape.IsNull() || theStartPoint.IsNull()) {
3522 SetErrorCode("NULL GEOM object");
3526 const TopoDS_Shape aShape = theShape->GetValue();
3527 const TopoDS_Shape aStartPoint = theStartPoint->GetValue();
3529 if (aShape.IsNull() || aStartPoint.IsNull()) {
3530 SetErrorCode("NULL Shape");
3534 if (aStartPoint.ShapeType() != TopAbs_VERTEX) {
3535 SetErrorCode("Starting point is not a vertex");
3539 TopExp_Explorer anExp(aShape, TopAbs_EDGE);
3540 TopTools_MapOfShape aMapFence;
3541 TopTools_ListOfShape anEdges;
3543 for (; anExp.More(); anExp.Next()) {
3544 const TopoDS_Shape &anEdge = anExp.Current();
3546 if (aMapFence.Add(anEdge)) {
3547 anEdges.Append(anEdge);
3551 if (anEdges.IsEmpty()) {
3552 SetErrorCode("Shape doesn't contain edges");
3556 // Step 1: Sort edges
3557 GEOMUtils::SortShapes(anEdges, Standard_False);
3559 TopTools_ListIteratorOfListOfShape anIter(anEdges);
3560 TopoDS_Vertex aV[2];
3561 TopTools_DataMapOfShapeListOfShape aMapVE;
3563 // Step 2: Fill the map vertex - list of edges.
3564 for (; anIter.More(); anIter.Next()) {
3565 TopoDS_Edge anEdge = TopoDS::Edge(anIter.Value());
3567 TopExp::Vertices(anEdge, aV[0], aV[1]);
3569 const Standard_Integer aNbV = aV[0].IsSame(aV[1]) ? 1 : 2;
3572 for (i = 0; i < aNbV; ++i) {
3573 if (aV[i].IsNull() == Standard_False) {
3574 if (!aMapVE.IsBound(aV[i])) {
3575 // There is no this vertex in the map.
3576 aMapVE.Bind(aV[i], TopTools_ListOfShape());
3579 // Add the edge to the list bound with the vertex aV[i].
3580 TopTools_ListOfShape &aLEdges = aMapVE.ChangeFind(aV[i]);
3582 aLEdges.Append(anEdge);
3587 // Step 3: Find starting point in aMapVE.
3588 TopoDS_Vertex aStartVtx = TopoDS::Vertex(aStartPoint);
3590 if (!aMapVE.IsBound(aStartVtx)) {
3591 aStartVtx = getSameVertex(aShape, aStartVtx);
3593 if (aStartVtx.IsNull()) {
3594 SetErrorCode("Invalid Starting point");
3599 TopTools_IndexedMapOfShape anIndices;
3600 TopTools_MapOfShape aMapVFence;
3601 TopoDS_Shape aCurVtx = aStartVtx;
3602 TopoDS_Edge aCurEdge =
3603 TopoDS::Edge(aMapVE.Find(aCurVtx).First());
3605 aResult = new TColStd_HSequenceOfInteger;
3606 TopExp::MapShapes(aShape, anIndices);
3608 // Step 4: Fill the list of sorted edges.
3609 while (aMapVFence.Add(aCurVtx)) {
3610 // Append the ID of the current edge to the list of sorted.
3611 aResult->Append(anIndices.FindIndex(aCurEdge));
3612 TopExp::Vertices(aCurEdge, aV[0], aV[1]);
3614 // Get the next vertex.
3615 if (aCurVtx.IsSame(aV[0])) {
3616 if (aCurVtx.IsSame(aV[1])) {
3617 // There is no next vertex.
3626 if (aCurVtx.IsNull()) {
3627 // There is no next vertex.
3631 // Get the next edge.
3632 const TopTools_ListOfShape &aLEdges = aMapVE.Find(aCurVtx);
3633 TopTools_ListIteratorOfListOfShape anEIter(aLEdges);
3635 for (; anEIter.More(); anEIter.Next()) {
3636 const TopoDS_Shape &aLocalEdge = anEIter.Value();
3638 if (aLocalEdge.IsNull() == Standard_False) {
3639 if (!aCurEdge.IsSame(aLocalEdge)) {
3640 aCurEdge = TopoDS::Edge(aLocalEdge);
3646 if (!anEIter.More()) {
3647 // There is no next edge.
3655 //=======================================================================
3656 //function : getShapesOnSurface
3658 * \brief Find sub-shapes complying with given status about surface
3659 * \param theSurface - the surface to check state of sub-shapes against
3660 * \param theShape - the shape to explore
3661 * \param theShapeType - type of sub-shape of theShape
3662 * \param theState - required state
3663 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3664 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3666 //=======================================================================
3667 Handle(TColStd_HSequenceOfTransient)
3668 GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
3669 const Handle(GEOM_Object)& theShape,
3670 TopAbs_ShapeEnum theShapeType,
3671 GEOMAlgo_State theState,
3672 TCollection_AsciiString & theShapeEntries)
3674 // Find sub-shapes ids
3675 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3676 getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
3677 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3680 return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
3683 //=============================================================================
3687 //=============================================================================
3688 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
3689 (const Handle(GEOM_Object)& theShape,
3690 const Standard_Integer theShapeType,
3691 const Handle(GEOM_Object)& theAx1,
3692 const GEOMAlgo_State theState)
3696 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3698 TopoDS_Shape aShape = theShape->GetValue();
3699 TopoDS_Shape anAx1 = theAx1->GetValue();
3701 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3703 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3704 if ( !checkTypeShapesOn( theShapeType ))
3708 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3709 if ( aPlane.IsNull() )
3713 TCollection_AsciiString anAsciiList;
3714 Handle(TColStd_HSequenceOfTransient) aSeq;
3715 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3716 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3719 // Make a Python command
3721 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3722 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3724 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3725 << "] = geompy.GetShapesOnPlane(" << theShape << ", "
3726 << aShapeType << ", " << theAx1 << ", " << theState << ")";
3732 //=============================================================================
3734 * GetShapesOnPlaneWithLocation
3736 //=============================================================================
3737 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
3738 (const Handle(GEOM_Object)& theShape,
3739 const Standard_Integer theShapeType,
3740 const Handle(GEOM_Object)& theAx1,
3741 const Handle(GEOM_Object)& thePnt,
3742 const GEOMAlgo_State theState)
3746 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3748 TopoDS_Shape aShape = theShape->GetValue();
3749 TopoDS_Shape anAx1 = theAx1->GetValue();
3750 TopoDS_Shape anPnt = thePnt->GetValue();
3752 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3754 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3755 if ( !checkTypeShapesOn( theShapeType ))
3759 if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
3760 TopoDS_Vertex V1, V2, V3;
3761 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3762 TopExp::Vertices(anEdge, V1, V2, Standard_True);
3764 if (V1.IsNull() || V2.IsNull()) {
3765 SetErrorCode("Bad edge given for the plane normal vector");
3768 V3 = TopoDS::Vertex(anPnt);
3771 SetErrorCode("Bad vertex given for the plane location");
3774 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3775 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3777 if (aVec.Magnitude() < Precision::Confusion()) {
3778 SetErrorCode("Vector with null magnitude given");
3781 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3783 if ( aPlane.IsNull() )
3787 TCollection_AsciiString anAsciiList;
3788 Handle(TColStd_HSequenceOfTransient) aSeq;
3789 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3790 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3793 // Make a Python command
3795 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3796 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3798 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3799 << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
3800 << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
3806 //=============================================================================
3808 * GetShapesOnCylinder
3810 //=============================================================================
3811 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
3812 (const Handle(GEOM_Object)& theShape,
3813 const Standard_Integer theShapeType,
3814 const Handle(GEOM_Object)& theAxis,
3815 const Standard_Real theRadius,
3816 const GEOMAlgo_State theState)
3820 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3822 TopoDS_Shape aShape = theShape->GetValue();
3823 TopoDS_Shape anAxis = theAxis->GetValue();
3825 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3827 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3828 if ( !checkTypeShapesOn( aShapeType ))
3831 // Create a cylinder surface
3832 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3833 if ( aCylinder.IsNull() )
3837 TCollection_AsciiString anAsciiList;
3838 Handle(TColStd_HSequenceOfTransient) aSeq;
3839 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3840 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3843 // Make a Python command
3845 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3846 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3848 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3849 << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
3850 << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
3856 //=============================================================================
3858 * GetShapesOnCylinderWithLocation
3860 //=============================================================================
3861 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
3862 (const Handle(GEOM_Object)& theShape,
3863 const Standard_Integer theShapeType,
3864 const Handle(GEOM_Object)& theAxis,
3865 const Handle(GEOM_Object)& thePnt,
3866 const Standard_Real theRadius,
3867 const GEOMAlgo_State theState)
3871 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3873 TopoDS_Shape aShape = theShape->GetValue();
3874 TopoDS_Shape anAxis = theAxis->GetValue();
3875 TopoDS_Shape aPnt = thePnt->GetValue();
3877 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3879 if (aPnt.ShapeType() != TopAbs_VERTEX )
3881 SetErrorCode("Bottom location point must be vertex");
3885 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3886 if ( !checkTypeShapesOn( aShapeType ))
3889 // Create a cylinder surface
3890 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3891 if ( aCylinder.IsNull() )
3894 // translate the surface
3895 Handle(Geom_CylindricalSurface) aCylSurface =
3896 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3897 if ( aCylSurface.IsNull() )
3899 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3902 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3903 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3904 aCylinder->Translate( fromLoc, toLoc );
3907 TCollection_AsciiString anAsciiList;
3908 Handle(TColStd_HSequenceOfTransient) aSeq;
3909 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3910 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3913 // Make a Python command
3915 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3916 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3918 GEOM::TPythonDump(aFunction)
3919 << "[" << anAsciiList.ToCString()
3920 << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
3921 << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
3927 //=============================================================================
3931 //=============================================================================
3932 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
3933 (const Handle(GEOM_Object)& theShape,
3934 const Standard_Integer theShapeType,
3935 const Handle(GEOM_Object)& theCenter,
3936 const Standard_Real theRadius,
3937 const GEOMAlgo_State theState)
3941 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3943 TopoDS_Shape aShape = theShape->GetValue();
3944 TopoDS_Shape aCenter = theCenter->GetValue();
3946 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3948 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3949 if ( !checkTypeShapesOn( aShapeType ))
3952 // Center of the sphere
3953 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3954 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3956 gp_Ax3 anAx3 (aLoc, gp::DZ());
3957 Handle(Geom_SphericalSurface) aSphere =
3958 new Geom_SphericalSurface(anAx3, theRadius);
3961 TCollection_AsciiString anAsciiList;
3962 Handle(TColStd_HSequenceOfTransient) aSeq;
3963 aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
3964 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3967 // Make a Python command
3969 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3970 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3972 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3973 << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
3974 << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
3980 //=============================================================================
3982 * GetShapesOnPlaneIDs
3984 //=============================================================================
3985 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
3986 (const Handle(GEOM_Object)& theShape,
3987 const Standard_Integer theShapeType,
3988 const Handle(GEOM_Object)& theAx1,
3989 const GEOMAlgo_State theState)
3993 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3995 TopoDS_Shape aShape = theShape->GetValue();
3996 TopoDS_Shape anAx1 = theAx1->GetValue();
3998 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
4000 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4001 if ( !checkTypeShapesOn( aShapeType ))
4005 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
4006 if ( aPlane.IsNull() )
4010 Handle(TColStd_HSequenceOfInteger) aSeq;
4011 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
4013 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
4014 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
4016 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4017 #ifdef DUMP_SUBSHAPE_IDS
4018 // Make a Python command
4019 GEOM::TPythonDump(aFunction, /*append=*/true)
4020 << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
4021 << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
4022 #endif // DUMP_SUBSHAPE_IDS
4028 //=============================================================================
4030 * GetShapesOnPlaneWithLocationIDs
4032 //=============================================================================
4033 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
4034 (const Handle(GEOM_Object)& theShape,
4035 const Standard_Integer theShapeType,
4036 const Handle(GEOM_Object)& theAx1,
4037 const Handle(GEOM_Object)& thePnt,
4038 const GEOMAlgo_State theState)
4042 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
4044 TopoDS_Shape aShape = theShape->GetValue();
4045 TopoDS_Shape anAx1 = theAx1->GetValue();
4046 TopoDS_Shape anPnt = thePnt->GetValue();
4048 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
4050 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4051 if ( !checkTypeShapesOn( aShapeType ))
4055 if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
4056 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
4057 TopoDS_Vertex V1, V2, V3;
4058 TopExp::Vertices(anEdge, V1, V2, Standard_True);
4059 if (V1.IsNull() || V2.IsNull()) {
4060 SetErrorCode("Bad edge given for the plane normal vector");
4063 V3 = TopoDS::Vertex(anPnt);
4065 SetErrorCode("Bad vertex given for the plane location");
4068 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
4069 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
4070 if (aVec.Magnitude() < Precision::Confusion()) {
4071 SetErrorCode("Vector with null magnitude given");
4075 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
4076 if ( aPlane.IsNull() )
4080 Handle(TColStd_HSequenceOfInteger) aSeq;
4081 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
4083 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
4084 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
4086 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4087 #ifdef DUMP_SUBSHAPE_IDS
4088 // Make a Python command
4089 GEOM::TPythonDump(aFunction, /*append=*/true)
4090 << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
4091 << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")";
4092 #endif // DUMP_SUBSHAPE_IDS
4098 //=============================================================================
4100 * GetShapesOnCylinderIDs
4102 //=============================================================================
4103 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
4104 (const Handle(GEOM_Object)& theShape,
4105 const Standard_Integer theShapeType,
4106 const Handle(GEOM_Object)& theAxis,
4107 const Standard_Real theRadius,
4108 const GEOMAlgo_State theState)
4112 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
4114 TopoDS_Shape aShape = theShape->GetValue();
4115 TopoDS_Shape anAxis = theAxis->GetValue();
4117 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
4119 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4120 if ( !checkTypeShapesOn( aShapeType ))
4123 // Create a cylinder surface
4124 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4125 if ( aCylinder.IsNull() )
4129 Handle(TColStd_HSequenceOfInteger) aSeq;
4130 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4132 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4133 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
4135 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4136 #ifdef DUMP_SUBSHAPE_IDS
4137 // Make a Python command
4138 GEOM::TPythonDump(aFunction, /*append=*/true)
4139 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
4140 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4141 << theRadius << ", " << theState << ")";
4142 #endif // DUMP_SUBSHAPE_IDS
4148 //=============================================================================
4150 * GetShapesOnCylinderWithLocationIDs
4152 //=============================================================================
4153 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
4154 (const Handle(GEOM_Object)& theShape,
4155 const Standard_Integer theShapeType,
4156 const Handle(GEOM_Object)& theAxis,
4157 const Handle(GEOM_Object)& thePnt,
4158 const Standard_Real theRadius,
4159 const GEOMAlgo_State theState)
4163 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
4165 TopoDS_Shape aShape = theShape->GetValue();
4166 TopoDS_Shape anAxis = theAxis->GetValue();
4167 TopoDS_Shape aPnt = thePnt->GetValue();
4169 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
4171 if (aPnt.ShapeType() != TopAbs_VERTEX )
4173 SetErrorCode("Bottom location point must be vertex");
4177 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4178 if ( !checkTypeShapesOn( aShapeType ))
4181 // Create a cylinder surface
4182 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4183 if ( aCylinder.IsNull() )
4186 // translate the surface
4187 Handle(Geom_CylindricalSurface) aCylSurface =
4188 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
4189 if ( aCylSurface.IsNull() )
4191 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
4194 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
4195 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
4196 aCylinder->Translate( fromLoc, toLoc );
4199 Handle(TColStd_HSequenceOfInteger) aSeq;
4200 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4202 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4203 Handle(GEOM_Function) aFunction =
4204 GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
4206 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4207 #ifdef DUMP_SUBSHAPE_IDS
4208 // Make a Python command
4209 GEOM::TPythonDump(aFunction, /*append=*/true)
4210 << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
4211 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4212 << thePnt << ", " << theRadius << ", " << theState << ")";
4213 #endif // DUMP_SUBSHAPE_IDS
4219 //=============================================================================
4221 * GetShapesOnSphereIDs
4223 //=============================================================================
4224 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
4225 (const Handle(GEOM_Object)& theShape,
4226 const Standard_Integer theShapeType,
4227 const Handle(GEOM_Object)& theCenter,
4228 const Standard_Real theRadius,
4229 const GEOMAlgo_State theState)
4233 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
4235 TopoDS_Shape aShape = theShape->GetValue();
4236 TopoDS_Shape aCenter = theCenter->GetValue();
4238 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
4240 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4241 if ( !checkTypeShapesOn( aShapeType ))
4244 // Center of the sphere
4245 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
4246 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
4248 gp_Ax3 anAx3 (aLoc, gp::DZ());
4249 Handle(Geom_SphericalSurface) aSphere =
4250 new Geom_SphericalSurface(anAx3, theRadius);
4253 Handle(TColStd_HSequenceOfInteger) aSeq;
4254 aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
4256 // The GetShapesOnSphere() doesn't change object so no new function is required.
4257 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
4259 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4260 #ifdef DUMP_SUBSHAPE_IDS
4261 // Make a Python command
4262 GEOM::TPythonDump(aFunction, /*append=*/true)
4263 << "listShapesOnSphere = geompy.GetShapesOnSphereIDs"
4264 << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
4265 << theRadius << ", " << theState << ")";
4266 #endif // DUMP_SUBSHAPE_IDS
4272 //=======================================================================
4273 //function : getShapesOnQuadrangleIDs
4275 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4276 * \param theShape - the shape to explore
4277 * \param theShapeType - type of sub-shape of theShape
4278 * \param theTopLeftPoint - top left quadrangle corner
4279 * \param theTopRightPoint - top right quadrangle corner
4280 * \param theBottomLeftPoint - bottom left quadrangle corner
4281 * \param theBottomRightPoint - bottom right quadrangle corner
4282 * \param theState - required state
4283 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4285 //=======================================================================
4286 Handle(TColStd_HSequenceOfInteger)
4287 GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4288 const Standard_Integer theShapeType,
4289 const Handle(GEOM_Object)& theTopLeftPoint,
4290 const Handle(GEOM_Object)& theTopRightPoint,
4291 const Handle(GEOM_Object)& theBottomLeftPoint,
4292 const Handle(GEOM_Object)& theBottomRightPoint,
4293 const GEOMAlgo_State theState)
4297 if ( theShape.IsNull() ||
4298 theTopLeftPoint.IsNull() ||
4299 theTopRightPoint.IsNull() ||
4300 theBottomLeftPoint.IsNull() ||
4301 theBottomRightPoint.IsNull() )
4304 TopoDS_Shape aShape = theShape->GetValue();
4305 TopoDS_Shape aTL = theTopLeftPoint->GetValue();
4306 TopoDS_Shape aTR = theTopRightPoint->GetValue();
4307 TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
4308 TopoDS_Shape aBR = theBottomRightPoint->GetValue();
4310 if (aShape.IsNull() ||
4315 aTL.ShapeType() != TopAbs_VERTEX ||
4316 aTR.ShapeType() != TopAbs_VERTEX ||
4317 aBL.ShapeType() != TopAbs_VERTEX ||
4318 aBR.ShapeType() != TopAbs_VERTEX )
4321 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4322 if ( !checkTypeShapesOn( aShapeType ))
4325 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
4327 // Check presence of triangulation, build if need
4328 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
4329 SetErrorCode("Cannot build triangulation on the shape");
4334 gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
4335 gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
4336 gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
4337 gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
4339 GEOMAlgo_FinderShapeOn2 aFinder;
4340 Handle(GEOMAlgo_ClsfQuad) aClsfQuad = new GEOMAlgo_ClsfQuad;
4342 Standard_Real aTol = 0.0001; // default value
4344 aClsfQuad->SetCorners(aPntTL, aPntTR, aPntBL, aPntBR);
4345 aFinder.SetShape(aShape);
4346 aFinder.SetTolerance(aTol);
4347 aFinder.SetClsf(aClsfQuad);
4348 aFinder.SetShapeType(aShapeType);
4349 aFinder.SetState(theState);
4351 // Sets the minimal number of inner points for the faces that do not have own
4352 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
4354 aFinder.SetNbPntsMin(3);
4355 // Sets the maximal number of inner points for edges or faces.
4356 // It is useful for the cases when this number is very big (e.g =2000) to improve
4357 // the performance. If this value =0, all inner points will be taken into account.
4359 aFinder.SetNbPntsMax(100);
4363 // Interpret results
4364 Standard_Integer iErr = aFinder.ErrorStatus();
4365 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
4367 MESSAGE(" iErr : " << iErr);
4368 TCollection_AsciiString aMsg (" iErr : ");
4369 aMsg += TCollection_AsciiString(iErr);
4373 Standard_Integer iWrn = aFinder.WarningStatus();
4374 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
4376 MESSAGE(" *** iWrn : " << iWrn);
4379 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
4381 if (listSS.Extent() < 1) {
4382 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
4383 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
4387 // Fill sequence of object IDs
4388 aSeqOfIDs = new TColStd_HSequenceOfInteger;
4390 TopTools_IndexedMapOfShape anIndices;
4391 TopExp::MapShapes(aShape, anIndices);
4393 TopTools_ListIteratorOfListOfShape itSub (listSS);
4394 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
4395 int id = anIndices.FindIndex(itSub.Value());
4396 aSeqOfIDs->Append(id);
4401 //=======================================================================
4402 //function : GetShapesOnQuadrangle
4404 * \brief Find sub-shapes complying with given status about quadrangle
4405 * \param theShape - the shape to explore
4406 * \param theShapeType - type of sub-shape of theShape
4407 * \param theTopLeftPoint - top left quadrangle corner
4408 * \param theTopRightPoint - top right quadrangle corner
4409 * \param theBottomLeftPoint - bottom left quadrangle corner
4410 * \param theBottomRightPoint - bottom right quadrangle corner
4411 * \param theState - required state
4412 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4414 //=======================================================================
4415 Handle(TColStd_HSequenceOfTransient)
4416 GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
4417 const Standard_Integer theShapeType,
4418 const Handle(GEOM_Object)& theTopLeftPoint,
4419 const Handle(GEOM_Object)& theTopRightPoint,
4420 const Handle(GEOM_Object)& theBottomLeftPoint,
4421 const Handle(GEOM_Object)& theBottomRightPoint,
4422 const GEOMAlgo_State theState)
4425 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4426 getShapesOnQuadrangleIDs( theShape,
4431 theBottomRightPoint,
4433 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4436 // Find objects by indices
4437 TCollection_AsciiString anAsciiList;
4438 Handle(TColStd_HSequenceOfTransient) aSeq;
4439 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
4440 if ( aSeq.IsNull() || aSeq->IsEmpty() )
4443 // Make a Python command
4445 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
4446 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
4448 GEOM::TPythonDump(aFunction)
4449 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
4451 << TopAbs_ShapeEnum(theShapeType) << ", "
4452 << theTopLeftPoint << ", "
4453 << theTopRightPoint << ", "
4454 << theBottomLeftPoint << ", "
4455 << theBottomRightPoint << ", "
4462 //=======================================================================
4463 //function : GetShapesOnQuadrangleIDs
4465 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4466 * \param theShape - the shape to explore
4467 * \param theShapeType - type of sub-shape of theShape
4468 * \param theTopLeftPoint - top left quadrangle corner
4469 * \param theTopRightPoint - top right quadrangle corner
4470 * \param theBottomLeftPoint - bottom left quadrangle corner
4471 * \param theBottomRightPoint - bottom right quadrangle corner
4472 * \param theState - required state
4473 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4475 //=======================================================================
4476 Handle(TColStd_HSequenceOfInteger)
4477 GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4478 const Standard_Integer theShapeType,
4479 const Handle(GEOM_Object)& theTopLeftPoint,
4480 const Handle(GEOM_Object)& theTopRightPoint,
4481 const Handle(GEOM_Object)& theBottomLeftPoint,
4482 const Handle(GEOM_Object)& theBottomRightPoint,
4483 const GEOMAlgo_State theState)
4486 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4487 getShapesOnQuadrangleIDs( theShape,
4492 theBottomRightPoint,
4494 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4497 // Make a Python command
4499 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4500 Handle(GEOM_BaseObject) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
4501 lastObj = GEOM::GetCreatedLast(lastObj,theTopRightPoint);
4502 lastObj = GEOM::GetCreatedLast(lastObj,theBottomRightPoint);
4503 lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
4504 Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
4506 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4507 #ifdef DUMP_SUBSHAPE_IDS
4508 GEOM::TPythonDump(aFunction, /*append=*/true)
4509 << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
4511 << TopAbs_ShapeEnum(theShapeType) << ", "
4512 << theTopLeftPoint << ", "
4513 << theTopRightPoint << ", "
4514 << theBottomLeftPoint << ", "
4515 << theBottomRightPoint << ", "
4517 #endif // DUMP_SUBSHAPE_IDS
4523 //=============================================================================
4528 //=============================================================================
4529 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
4530 Handle(GEOM_Object) theShapeWhat)
4534 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4536 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4537 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4539 if (aWhere.IsNull() || aWhat.IsNull()) {
4540 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4544 // Searching for the sub-shapes inside the ShapeWhere shape
4545 GEOMAlgo_GetInPlace aGIP;
4547 if (!GEOMAlgo_GetInPlaceAPI::GetInPlace(aWhere, aWhat, aGIP)) {
4548 SetErrorCode("Error in GEOMAlgo_GetInPlace");
4552 // Add direct result.
4553 TopTools_ListOfShape aLSA;
4554 const TopoDS_Shape &aShapeResult = aGIP.Result();
4555 TopTools_MapOfShape aMFence;
4556 TopTools_IndexedMapOfShape aWhereIndices;
4557 Standard_Integer aShapeType = -1;
4559 TopExp::MapShapes(aWhere, aWhereIndices);
4561 if (aShapeResult.IsNull() == Standard_False) {
4562 TopoDS_Iterator anIt(aShapeResult);
4564 for (; anIt.More(); anIt.Next()) {
4565 const TopoDS_Shape &aPart = anIt.Value();
4567 if(aWhereIndices.Contains(aPart) && aMFence.Add(aPart)) {
4568 const TopAbs_ShapeEnum aType = aPart.ShapeType();
4570 if (aShapeType == -1) {
4573 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4575 aShapeType = TopAbs_SHAPE;
4583 if (aLSA.Extent() == 0) {
4584 SetErrorCode(NOT_FOUND_ANY); // Not found any Results
4588 Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent());
4589 TopTools_ListIteratorOfListOfShape anIterModif (aLSA);
4590 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4591 aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value()));
4595 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4596 if (aResult.IsNull()) {
4597 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4601 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4603 if ((aModifiedArray->Length() > 1 && isSameType) ||
4604 theShapeWhat->GetType() == GEOM_GROUP) {
4606 aResult->SetType(GEOM_GROUP);
4608 //Set a sub-shape type
4609 TopoDS_Shape aFirstFound = aLSA.First();
4610 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4612 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4613 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4616 //Make a Python command
4617 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4619 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4620 << theShapeWhere << ", " << theShapeWhat << ", True)";
4626 //=============================================================================
4628 * case GetInPlaceOld:
4631 //=============================================================================
4632 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld
4633 (Handle(GEOM_Object) theShapeWhere,
4634 Handle(GEOM_Object) theShapeWhat)
4638 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4640 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4641 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4642 TopTools_ListOfShape aModifiedList;
4643 const Standard_Integer iErr =
4644 GEOMAlgo_GetInPlaceAPI::GetInPlaceOld(aWhere, aWhat, aModifiedList);
4649 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4653 ("Error: An attempt to extract a shape of not supported type.");
4656 SetErrorCode(NOT_FOUND_ANY);
4659 SetErrorCode("Shape driver failed");
4666 TopTools_IndexedMapOfShape aWhereIndices;
4667 TopExp::MapShapes(aWhere, aWhereIndices);
4669 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4670 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4671 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4672 Standard_Integer imod;
4673 Standard_Integer aShapeType = -1;
4675 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4676 const Standard_Integer anIndex =
4677 aWhereIndices.FindIndex(anIterModif.Value());
4678 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4680 if (aShapeType == -1) {
4683 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4685 aShapeType = TopAbs_SHAPE;
4688 aModifiedArray->SetValue(imod, anIndex);
4692 Handle(GEOM_Object) aResult =
4693 GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4695 if (aResult.IsNull()) {
4696 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4700 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4702 if ((aModifiedArray->Length() > 1 && isSameType) ||
4703 theShapeWhat->GetType() == GEOM_GROUP) {
4705 aResult->SetType(GEOM_GROUP);
4707 //Set a sub-shape type
4708 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4709 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4711 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4712 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4715 //Make a Python command
4716 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4718 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4719 << theShapeWhere << ", " << theShapeWhat << ", False)";
4726 //=======================================================================
4727 //function : GetInPlaceByHistory
4729 //=======================================================================
4730 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
4731 (Handle(GEOM_Object) theShapeWhere,
4732 Handle(GEOM_Object) theShapeWhat)
4736 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4738 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4739 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4741 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4743 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4744 if (aWhereFunction.IsNull()) return NULL;
4746 //Fill array of indices
4747 TopTools_IndexedMapOfShape aWhereIndices;
4749 TopExp::MapShapes(aWhere, aWhereIndices);
4752 TopTools_ListOfShape aModifiedList;
4753 bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceByHistory
4754 (aWhereFunction, aWhereIndices, aWhat, aModifiedList);
4756 if (!isFound || aModifiedList.Extent() < 1) {
4757 SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
4761 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4762 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4763 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4764 Standard_Integer imod;
4765 Standard_Integer aShapeType = -1;
4767 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4768 const Standard_Integer anIndex =
4769 aWhereIndices.FindIndex(anIterModif.Value());
4770 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4772 if (aShapeType == -1) {
4775 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4777 aShapeType = TopAbs_SHAPE;
4780 aModifiedArray->SetValue(imod, anIndex);
4784 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4785 if (aResult.IsNull()) {
4786 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4790 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4792 if ((aModifiedArray->Length() > 1 && isSameType) ||
4793 theShapeWhat->GetType() == GEOM_GROUP) {
4795 aResult->SetType(GEOM_GROUP);
4797 //Set a sub-shape type
4798 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4799 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4801 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4802 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4805 //Make a Python command
4806 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4808 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
4809 << theShapeWhere << ", " << theShapeWhat << ")";
4815 //=======================================================================
4816 //function : GetInPlaceMap
4818 //=======================================================================
4819 void GEOMImpl_IShapesOperations::GetInPlaceMap (Handle(GEOM_Object) theShapeWhere,
4820 Handle(GEOM_Object) theShapeWhat,
4821 std::vector< std::vector< int > > & theResVec)
4825 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return;
4827 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4828 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4830 if (aWhere.IsNull() || aWhat.IsNull()) return;
4832 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4833 if (aWhereFunction.IsNull()) return;
4835 bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceMap( aWhereFunction, aWhat, theResVec );
4840 Handle(GEOM_Function) aFunction =
4841 GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
4843 GEOM::TPythonDump(aFunction, /*append=*/true)
4844 << "resultList = geompy.GetInPlaceMap( "
4845 << theShapeWhere << ", "
4846 << theShapeWhat << ")";
4851 //=======================================================================
4852 //function : isSameEdge
4853 //purpose : Returns True if two edges coincide
4854 //=======================================================================
4855 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4857 TopoDS_Vertex V11, V12, V21, V22;
4858 TopExp::Vertices(theEdge1, V11, V12);
4859 TopExp::Vertices(theEdge2, V21, V22);
4860 gp_Pnt P11 = BRep_Tool::Pnt(V11);
4861 gp_Pnt P12 = BRep_Tool::Pnt(V12);
4862 gp_Pnt P21 = BRep_Tool::Pnt(V21);
4863 gp_Pnt P22 = BRep_Tool::Pnt(V22);
4864 bool coincide = false;
4866 //Check that ends of edges coincide
4867 if(P11.Distance(P21) <= MAX_TOLERANCE) {
4868 if(P12.Distance(P22) <= MAX_TOLERANCE) coincide = true;
4870 else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4871 if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4874 if(!coincide) return false;
4876 if (BRep_Tool::Degenerated(theEdge1))
4877 if (BRep_Tool::Degenerated(theEdge2)) return true;
4880 if (BRep_Tool::Degenerated(theEdge2)) return false;
4882 double U11, U12, U21, U22;
4883 Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4884 Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4886 //Check that both edges has the same geometry
4887 double range = U12-U11;
4888 double U = U11+ range/3.0;
4889 gp_Pnt P1 = C1->Value(U); //Compute a point on one third of the edge's length
4890 U = U11+range*2.0/3.0;
4891 gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length
4893 C2 = new Geom_TrimmedCurve(C2, U21, U22);
4894 // vsr 04/10/2018: 0023312 - As curve may be periodic, its parameters may be normalized
4895 // so, we re-take them from trimmed curve
4896 U21 = C2->FirstParameter();
4897 U22 = C2->LastParameter();
4899 if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22)
4902 if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4904 if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4907 if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4912 //=======================================================================
4913 //function : isSameFace
4914 //purpose : Returns True if two faces coincide
4915 //=======================================================================
4916 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4918 TopExp_Explorer E(theFace1, TopAbs_EDGE);
4919 TopTools_ListOfShape LS1, LS2;
4920 for(; E.More(); E.Next()) LS1.Append(E.Current());
4922 E.Init(theFace2, TopAbs_EDGE);
4923 for(; E.More(); E.Next()) LS2.Append(E.Current());
4925 //Compare the number of edges in the faces
4926 if(LS1.Extent() != LS2.Extent()) return false;
4928 double aMin = RealFirst(), aMax = RealLast();
4929 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4930 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4932 for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4933 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4934 if(P.X() < xminB1) xminB1 = P.X();
4935 if(P.Y() < yminB1) yminB1 = P.Y();
4936 if(P.Z() < zminB1) zminB1 = P.Z();
4937 if(P.X() > xmaxB1) xmaxB1 = P.X();
4938 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4939 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4942 for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4943 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4944 if(P.X() < xminB2) xminB2 = P.X();
4945 if(P.Y() < yminB2) yminB2 = P.Y();
4946 if(P.Z() < zminB2) zminB2 = P.Z();
4947 if(P.X() > xmaxB2) xmaxB2 = P.X();
4948 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4949 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4952 //Compare the bounding boxes of both faces
4953 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4956 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4959 Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4960 Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4962 //Check if there a coincidence of two surfaces at least in two points
4963 double U11, U12, V11, V12, U21, U22, V21, V22;
4964 BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4965 BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4967 double rangeU = U12-U11;
4968 double rangeV = V12-V11;
4969 double U = U11 + rangeU/3.0;
4970 double V = V11 + rangeV/3.0;
4971 gp_Pnt P1 = S1->Value(U, V);
4972 U = U11+rangeU*2.0/3.0;
4973 V = V11+rangeV*2.0/3.0;
4974 gp_Pnt P2 = S1->Value(U, V);
4976 if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4979 if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4981 if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4984 if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
4986 //Check that each edge of the Face1 has a counterpart in the Face2
4987 TopTools_MapOfOrientedShape aMap;
4988 TopTools_ListIteratorOfListOfShape LSI1(LS1);
4989 for(; LSI1.More(); LSI1.Next()) {
4990 TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
4991 bool isFound = false;
4992 TopTools_ListIteratorOfListOfShape LSI2(LS2);
4993 for(; LSI2.More(); LSI2.Next()) {
4994 TopoDS_Shape aValue = LSI2.Value();
4995 if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
4996 if(isSameEdge(E, TopoDS::Edge(aValue))) {
5002 if(!isFound) return false;
5008 //=======================================================================
5009 //function : isSameSolid
5010 //purpose : Returns True if two solids coincide
5011 //=======================================================================
5012 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
5014 TopExp_Explorer E(theSolid1, TopAbs_FACE);
5015 TopTools_ListOfShape LS1, LS2;
5016 for(; E.More(); E.Next()) LS1.Append(E.Current());
5017 E.Init(theSolid2, TopAbs_FACE);
5018 for(; E.More(); E.Next()) LS2.Append(E.Current());
5020 if(LS1.Extent() != LS2.Extent()) return false;
5022 double aMin = RealFirst(), aMax = RealLast();
5023 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
5024 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
5026 for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
5027 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
5028 if(P.X() < xminB1) xminB1 = P.X();
5029 if(P.Y() < yminB1) yminB1 = P.Y();
5030 if(P.Z() < zminB1) zminB1 = P.Z();
5031 if(P.X() > xmaxB1) xmaxB1 = P.X();
5032 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
5033 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
5036 for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
5037 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
5038 if(P.X() < xminB2) xminB2 = P.X();
5039 if(P.Y() < yminB2) yminB2 = P.Y();
5040 if(P.Z() < zminB2) zminB2 = P.Z();
5041 if(P.X() > xmaxB2) xmaxB2 = P.X();
5042 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
5043 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
5046 //Compare the bounding boxes of both solids
5047 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
5050 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
5053 //Check that each face of the Solid1 has a counterpart in the Solid2
5054 TopTools_MapOfOrientedShape aMap;
5055 TopTools_ListIteratorOfListOfShape LSI1(LS1);
5056 for(; LSI1.More(); LSI1.Next()) {
5057 TopoDS_Face F = TopoDS::Face(LSI1.Value());
5058 bool isFound = false;
5059 TopTools_ListIteratorOfListOfShape LSI2(LS2);
5060 for(; LSI2.More(); LSI2.Next()) {
5061 if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
5062 if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
5063 aMap.Add(LSI2.Value());
5068 if(!isFound) return false;
5074 //=======================================================================
5075 //function : GetSame
5077 //=======================================================================
5078 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
5079 const Handle(GEOM_Object)& theShapeWhat)
5082 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
5084 TopoDS_Shape aWhere = theShapeWhere->GetValue();
5085 TopoDS_Shape aWhat = theShapeWhat->GetValue();
5087 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
5090 bool isFound = false;
5091 TopoDS_Shape aSubShape;
5092 TopTools_MapOfShape aMap;
5094 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
5095 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
5096 if (It.More()) aWhat = It.Value();
5099 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
5104 switch (aWhat.ShapeType()) {
5105 case TopAbs_VERTEX: {
5106 aSubShape = getSameVertex(aWhere, TopoDS::Vertex(aWhat));
5107 isFound = !aSubShape.IsNull();
5111 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
5112 TopExp_Explorer E(aWhere, TopAbs_EDGE);
5113 for(; E.More(); E.Next()) {
5114 if(!aMap.Add(E.Current())) continue;
5115 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
5116 aSubShape = E.Current();
5124 TopoDS_Face aFace = TopoDS::Face(aWhat);
5125 TopExp_Explorer E(aWhere, TopAbs_FACE);
5126 for(; E.More(); E.Next()) {
5127 if(!aMap.Add(E.Current())) continue;
5128 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5129 aSubShape = E.Current();
5136 case TopAbs_SOLID: {
5137 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5138 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5139 for(; E.More(); E.Next()) {
5140 if(!aMap.Add(E.Current())) continue;
5141 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5142 aSubShape = E.Current();
5154 TopTools_IndexedMapOfShape anIndices;
5155 TopExp::MapShapes(aWhere, anIndices);
5156 if (anIndices.Contains(aSubShape))
5157 anIndex = anIndices.FindIndex(aSubShape);
5160 if (anIndex < 0) return NULL;
5162 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
5164 anArray->SetValue(1, anIndex);
5166 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
5167 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
5169 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
5170 << theShapeWhere << ", " << theShapeWhat << ")";
5178 //=======================================================================
5179 //function : GetSameIDs
5181 //=======================================================================
5182 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
5183 (const Handle(GEOM_Object)& theShapeWhere,
5184 const Handle(GEOM_Object)& theShapeWhat)
5187 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
5189 TopoDS_Shape aWhere = theShapeWhere->GetValue();
5190 TopoDS_Shape aWhat = theShapeWhat->GetValue();
5192 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
5194 TopTools_ListOfShape listShape;
5195 TopTools_MapOfShape aMap;
5197 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
5198 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
5199 if (It.More()) aWhat = It.Value();
5202 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
5207 switch (aWhat.ShapeType()) {
5208 case TopAbs_VERTEX: {
5209 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
5210 TopExp_Explorer E(aWhere, TopAbs_VERTEX);
5211 for(; E.More(); E.Next()) {
5212 if(!aMap.Add(E.Current())) continue;
5213 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
5214 if(P.Distance(P2) <= MAX_TOLERANCE) {
5215 listShape.Append(E.Current());
5221 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
5222 TopExp_Explorer E(aWhere, TopAbs_EDGE);
5223 for(; E.More(); E.Next()) {
5224 if(!aMap.Add(E.Current())) continue;
5225 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
5226 listShape.Append(E.Current());
5232 TopoDS_Face aFace = TopoDS::Face(aWhat);
5233 TopExp_Explorer E(aWhere, TopAbs_FACE);
5234 for(; E.More(); E.Next()) {
5235 if(!aMap.Add(E.Current())) continue;
5236 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5237 listShape.Append(E.Current());
5242 case TopAbs_SOLID: {
5243 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5244 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5245 for(; E.More(); E.Next()) {
5246 if(!aMap.Add(E.Current())) continue;
5247 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5248 listShape.Append(E.Current());
5257 if ( !listShape.IsEmpty() ) {
5258 TopTools_IndexedMapOfShape anIndices;
5259 TopExp::MapShapes(aWhere, anIndices);
5260 TopTools_ListIteratorOfListOfShape itSub (listShape);
5261 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
5262 for (; itSub.More(); itSub.Next()) {
5263 if (anIndices.Contains(itSub.Value()))
5264 aSeq->Append(anIndices.FindIndex(itSub.Value()));
5267 // The GetSameIDs() doesn't change object so no new function is required.
5268 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
5270 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
5271 #ifdef DUMP_SUBSHAPE_IDS
5272 // Make a Python command
5273 GEOM::TPythonDump(aFunction, /*append=*/true)
5274 << "listSameIDs = geompy.GetSameIDs("
5275 << theShapeWhere << ", "
5276 << theShapeWhat << ")";
5277 #endif // DUMP_SUBSHAPE_IDS
5280 SetErrorCode(NOT_FOUND_ANY);
5285 //=======================================================================
5286 //function : ExtendEdge
5288 //=======================================================================
5289 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendEdge
5290 (const Handle(GEOM_Object) &theEdge,
5291 const Standard_Real theMin,
5292 const Standard_Real theMax)
5296 if (theEdge.IsNull()) {
5300 //Add a new Edge object
5301 Handle(GEOM_Object) aResEdge = GetEngine()->AddObject(GEOM_EDGE);
5303 //Add a new Vector function
5304 Handle(GEOM_Function) aFunction =
5305 aResEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_UV);
5307 //Check if the function is set correctly
5308 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5312 GEOMImpl_IShapeExtend aCI (aFunction);
5314 Handle(GEOM_Function) anEdge = theEdge->GetLastFunction();
5316 if (anEdge.IsNull()) {
5320 aCI.SetShape(anEdge);
5321 aCI.SetUMin(theMin);
5322 aCI.SetUMax(theMax);
5324 //Compute the Edge value
5327 if (!GetSolver()->ComputeFunction(aFunction)) {
5328 SetErrorCode("Shape driver failed");
5333 catch (Standard_Failure& aFail) {
5334 SetErrorCode(aFail.GetMessageString());
5339 //Make a Python command
5340 GEOM::TPythonDump(aFunction)
5341 << aResEdge << " = geompy.ExtendEdge("
5342 << theEdge << ", " << theMin << ", " << theMax << ")";
5349 //=======================================================================
5350 //function : ExtendFace
5352 //=======================================================================
5353 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendFace
5354 (const Handle(GEOM_Object) &theFace,
5355 const Standard_Real theUMin,
5356 const Standard_Real theUMax,
5357 const Standard_Real theVMin,
5358 const Standard_Real theVMax)
5362 if (theFace.IsNull()) {
5366 //Add a new Face object
5367 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GEOM_FACE);
5369 //Add a new Vector function
5370 Handle(GEOM_Function) aFunction =
5371 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_UV);
5373 //Check if the function is set correctly
5374 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5378 GEOMImpl_IShapeExtend aCI (aFunction);
5380 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5382 if (aFace.IsNull()) {
5386 aCI.SetShape(aFace);
5387 aCI.SetUMin(theUMin);
5388 aCI.SetUMax(theUMax);
5389 aCI.SetVMin(theVMin);
5390 aCI.SetVMax(theVMax);
5392 //Compute the Face value
5395 if (!GetSolver()->ComputeFunction(aFunction)) {
5396 SetErrorCode("Shape driver failed");
5401 catch (Standard_Failure& aFail) {
5402 SetErrorCode(aFail.GetMessageString());
5407 //Make a Python command
5408 GEOM::TPythonDump(aFunction)
5409 << aResFace << " = geompy.ExtendFace("
5410 << theFace << ", " << theUMin << ", " << theUMax << ", "
5411 << theVMin << ", " << theVMax << ")";
5418 //=======================================================================
5419 //function : MakeSurfaceFromFace
5421 //=======================================================================
5422 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSurfaceFromFace
5423 (const Handle(GEOM_Object) &theFace)
5427 if (theFace.IsNull()) {
5431 //Add a new Face object
5432 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GEOM_FACE);
5434 //Add a new Vector function
5435 Handle(GEOM_Function) aFunction =
5436 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), SURFACE_FROM_FACE);
5438 //Check if the function is set correctly
5439 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5443 GEOMImpl_IShapeExtend aCI (aFunction);
5445 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5447 if (aFace.IsNull()) {
5451 aCI.SetShape(aFace);
5453 //Compute the Face value
5456 if (!GetSolver()->ComputeFunction(aFunction)) {
5457 SetErrorCode("Shape driver failed");
5462 catch (Standard_Failure& aFail) {
5463 SetErrorCode(aFail.GetMessageString());
5468 //Make a Python command
5469 GEOM::TPythonDump(aFunction)
5470 << aResFace << " = geompy.MakeSurfaceFromFace("