1 // Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : GEOMImpl_IShapesOperations.cxx
25 // Author : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
28 //#include <Standard_Stream.hxx>
30 #include "GEOMImpl_IShapesOperations.hxx"
32 #include "GEOMImpl_Types.hxx"
34 #include "GEOMImpl_VectorDriver.hxx"
35 #include "GEOMImpl_ShapeDriver.hxx"
36 #include "GEOMImpl_GlueDriver.hxx"
37 #include "GEOMImpl_FillingDriver.hxx"
39 #include "GEOMImpl_IExtract.hxx"
40 #include "GEOMImpl_IVector.hxx"
41 #include "GEOMImpl_IShapes.hxx"
42 #include "GEOMImpl_IShapeExtend.hxx"
43 #include "GEOMImpl_IGlue.hxx"
44 #include "GEOMImpl_IFilling.hxx"
46 #include "GEOMImpl_Block6Explorer.hxx"
47 #include "GEOMImpl_IHealingOperations.hxx"
49 #include "GEOMImpl_Gen.hxx"
51 #include "GEOM_Function.hxx"
52 #include "GEOM_ISubShape.hxx"
53 #include "GEOM_PythonDump.hxx"
55 #include "GEOMUtils.hxx"
57 #include "GEOMAlgo_ClsfBox.hxx"
58 #include "GEOMAlgo_ClsfQuad.hxx"
59 #include "GEOMAlgo_ClsfSolid.hxx"
60 #include "GEOMAlgo_ClsfSurf.hxx"
61 #include "GEOMAlgo_FinderShapeOn2.hxx"
62 #include "GEOMAlgo_GetInPlace.hxx"
63 #include "GEOMAlgo_GetInPlaceAPI.hxx"
64 #include "GEOMAlgo_GlueDetector.hxx"
66 #include <utilities.h>
68 #include <BRepAdaptor_Curve.hxx>
69 #include <BRepAdaptor_Surface.hxx>
70 #include <BRepTools.hxx>
71 #include <BRep_Builder.hxx>
72 #include <BRep_Tool.hxx>
73 #include <GeomLib_Tool.hxx>
74 #include <Geom_CylindricalSurface.hxx>
75 #include <Geom_Plane.hxx>
76 #include <Geom_SphericalSurface.hxx>
77 #include <Geom_Surface.hxx>
78 #include <Geom_TrimmedCurve.hxx>
79 #include <Precision.hxx>
80 #include <TDF_Tool.hxx>
81 #include <TDataStd_Integer.hxx>
82 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
84 #include <TopExp_Explorer.hxx>
85 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
86 #include <TopTools_IndexedMapOfShape.hxx>
87 #include <TopTools_ListIteratorOfListOfShape.hxx>
88 #include <TopTools_MapOfOrientedShape.hxx>
89 #include <TopTools_MapOfShape.hxx>
90 #include <TopTools_SequenceOfShape.hxx>
92 #include <TopoDS_TShape.hxx>
93 #include <TopoDS_Compound.hxx>
94 #include <TopoDS_Edge.hxx>
95 #include <TopoDS_Face.hxx>
96 #include <TopoDS_Iterator.hxx>
97 #include <TopoDS_Shape.hxx>
98 #include <TopoDS_Solid.hxx>
99 #include <TopoDS_Vertex.hxx>
100 #include <gp_Cylinder.hxx>
101 #include <gp_Pnt.hxx>
105 #include <Standard_Failure.hxx>
106 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
108 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
109 // Next macro, when defined, causes appearing of SubShapeAllIDs(), SubShapeAllSortedIDs(), GetSameIDs()
110 // and other such commands in Python dump.
111 // See also GEOM_Engine.cxx.
112 // ---------------------------------------
113 // #define DUMP_SUBSHAPE_IDS
114 // ---------------------------------------
118 void AddFlatSubShapes(const TopoDS_Shape& S, TopTools_ListOfShape& L, TopTools_MapOfShape& M)
120 if (S.ShapeType() != TopAbs_COMPOUND) {
124 TopoDS_Iterator It(S, Standard_True, Standard_True);
125 for (; It.More(); It.Next()) {
126 TopoDS_Shape SS = It.Value();
128 AddFlatSubShapes(SS, L, M);
136 const double MAX_TOLERANCE = 1.e-7;
139 * \brief Returns the vertex from theWhere shape that is coincident with
142 * \param theWhere the shape where the coincident vertex is searched.
143 * \param theVertex the vertex to be searched.
144 * \return the coincident vertex if it is found. Otherwise null object.
146 static TopoDS_Vertex getSameVertex(const TopoDS_Shape &theWhere,
147 const TopoDS_Vertex &theVertex)
149 TopoDS_Vertex aResult;
150 gp_Pnt aPoint = BRep_Tool::Pnt(theVertex);
151 TopExp_Explorer anExp(theWhere, TopAbs_VERTEX);
152 TopTools_MapOfShape aMap;
154 for(; anExp.More(); anExp.Next()) {
155 const TopoDS_Shape &aLocalShape = anExp.Current();
157 if(!aMap.Add(aLocalShape)) {
161 TopoDS_Vertex aVertex = TopoDS::Vertex(aLocalShape);
162 gp_Pnt aPoint2 = BRep_Tool::Pnt(aVertex);
164 if(aPoint.Distance(aPoint2) <= MAX_TOLERANCE) {
172 } // end of namespace
174 //=============================================================================
178 //=============================================================================
179 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine)
180 : GEOM_IOperations(theEngine)
182 MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
185 //=============================================================================
189 //=============================================================================
190 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
192 MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
195 //=============================================================================
199 //=============================================================================
200 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
201 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
205 if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
207 //Add a new Edge object
208 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GEOM_EDGE);
210 //Add a new Vector function
211 Handle(GEOM_Function) aFunction =
212 anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
214 //Check if the function is set correctly
215 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
217 GEOMImpl_IVector aPI (aFunction);
219 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
220 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
221 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
223 aPI.SetPoint1(aRef1);
224 aPI.SetPoint2(aRef2);
226 //Compute the Edge value
229 if (!GetSolver()->ComputeFunction(aFunction)) {
230 SetErrorCode("Vector driver failed");
234 catch (Standard_Failure& aFail) {
235 SetErrorCode(aFail.GetMessageString());
239 //Make a Python command
240 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
241 << thePnt1 << ", " << thePnt2 << ")";
247 //=============================================================================
249 * MakeEdgeOnCurveByLength
251 //=============================================================================
252 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeOnCurveByLength
253 (Handle(GEOM_Object) theRefCurve,
254 const Standard_Real theLength,
255 Handle(GEOM_Object) theStartPoint)
259 if (theRefCurve.IsNull()) return NULL;
261 //Add a new Edge object
262 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GEOM_EDGE);
264 //Add a new Vector function
265 Handle(GEOM_Function) aFunction =
266 anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_CURVE_LENGTH);
268 //Check if the function is set correctly
269 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
271 GEOMImpl_IVector aPI (aFunction);
273 Handle(GEOM_Function) aRef1 = theRefCurve->GetLastFunction();
274 if (aRef1.IsNull()) return NULL;
275 aPI.SetPoint1(aRef1);
277 if (!theStartPoint.IsNull()) {
278 Handle(GEOM_Function) aRef2 = theStartPoint->GetLastFunction();
279 aPI.SetPoint2(aRef2);
282 aPI.SetParameter(theLength);
284 //Compute the Edge value
287 if (!GetSolver()->ComputeFunction(aFunction)) {
288 SetErrorCode("Vector driver failed");
292 catch (Standard_Failure& aFail) {
293 SetErrorCode(aFail.GetMessageString());
297 //Make a Python command
298 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeOnCurveByLength("
299 << theRefCurve << ", " << theLength << ", " << theStartPoint << ")";
305 //=============================================================================
309 //=============================================================================
310 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire
311 (Handle(GEOM_Object) theWire,
312 const Standard_Real theLinearTolerance,
313 const Standard_Real theAngularTolerance)
317 if (theWire.IsNull()) return NULL;
319 //Add a new Edge object
320 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GEOM_EDGE);
322 //Add a new Vector function
323 Handle(GEOM_Function) aFunction =
324 anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_WIRE);
326 //Check if the function is set correctly
327 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
329 GEOMImpl_IShapes aCI (aFunction);
331 Handle(GEOM_Function) aWire = theWire->GetLastFunction();
333 if (aWire.IsNull()) return NULL;
336 aCI.SetTolerance(theLinearTolerance);
337 aCI.SetAngularTolerance(theAngularTolerance);
339 //Compute the Edge value
342 if (!GetSolver()->ComputeFunction(aFunction)) {
343 SetErrorCode("Shape driver failed");
347 catch (Standard_Failure& aFail) {
348 SetErrorCode(aFail.GetMessageString());
352 const double DEF_LIN_TOL = Precision::Confusion();
353 const double DEF_ANG_TOL = Precision::Angular();
354 //Make a Python command
355 if ( theAngularTolerance == DEF_ANG_TOL ) {
356 if ( theLinearTolerance == DEF_LIN_TOL )
357 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
360 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
361 << theWire << ", " << theLinearTolerance << ")";
364 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
365 << theWire << ", " << theLinearTolerance << ", "
366 << theAngularTolerance << ")";
373 //=============================================================================
377 //=============================================================================
378 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
379 (std::list<Handle(GEOM_Object)> theShapes,
380 const Standard_Real theTolerance)
385 Handle(GEOM_Object) aWire = GetEngine()->AddObject(GEOM_WIRE);
388 Handle(GEOM_Function) aFunction =
389 aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES);
390 if (aFunction.IsNull()) return NULL;
392 //Check if the function is set correctly
393 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
395 GEOMImpl_IShapes aCI (aFunction);
396 aCI.SetTolerance(theTolerance);
398 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
401 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
402 for (; it != theShapes.end(); it++) {
403 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
404 if (aRefSh.IsNull()) {
405 SetErrorCode("NULL argument shape for the shape construction");
408 aShapesSeq->Append(aRefSh);
410 aCI.SetShapes(aShapesSeq);
415 if (!GetSolver()->ComputeFunction(aFunction)) {
416 SetErrorCode("Shape driver failed");
420 catch (Standard_Failure& aFail) {
421 SetErrorCode(aFail.GetMessageString());
425 //Make a Python command
426 GEOM::TPythonDump pd (aFunction);
427 pd << aWire << " = geompy.MakeWire([";
430 it = theShapes.begin();
431 if (it != theShapes.end()) {
433 while (it != theShapes.end()) {
434 pd << ", " << (*it++);
437 pd << "], " << theTolerance << ")";
443 //=============================================================================
447 //=============================================================================
448 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
449 const bool isPlanarWanted)
453 if (theWire.IsNull()) return NULL;
455 //Add a new Face object
456 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GEOM_FACE);
458 //Add a new Shape function for creation of a face from a wire
459 Handle(GEOM_Function) aFunction =
460 aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
461 if (aFunction.IsNull()) return NULL;
463 //Check if the function is set correctly
464 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
466 GEOMImpl_IShapes aCI (aFunction);
468 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
470 if (aRefWire.IsNull()) return NULL;
472 aCI.SetBase(aRefWire);
473 aCI.SetIsPlanar(isPlanarWanted);
475 //Compute the Face value
476 Standard_Boolean isWarning = Standard_False;
479 if (!GetSolver()->ComputeFunction(aFunction)) {
480 SetErrorCode("Shape driver failed to compute a face");
484 catch (Standard_Failure& aFail) {
485 SetErrorCode(aFail.GetMessageString());
486 // to provide warning
487 if (!aFunction->GetValue().IsNull()) {
488 isWarning = Standard_True;
494 //Make a Python command
495 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
496 << theWire << ", " << (int)isPlanarWanted << ")";
498 // to provide warning
499 if (!isWarning) SetErrorCode(OK);
503 //=============================================================================
507 //=============================================================================
508 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
509 (std::list<Handle(GEOM_Object)> theShapes,
510 const bool isPlanarWanted)
515 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FACE);
518 Handle(GEOM_Function) aFunction =
519 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
520 if (aFunction.IsNull()) return NULL;
522 //Check if the function is set correctly
523 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
525 GEOMImpl_IShapes aCI (aFunction);
527 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
530 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
531 for (; it != theShapes.end(); it++) {
532 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
533 if (aRefSh.IsNull()) {
534 SetErrorCode("NULL argument shape for the face construction");
537 aShapesSeq->Append(aRefSh);
539 aCI.SetShapes(aShapesSeq);
541 aCI.SetIsPlanar(isPlanarWanted);
544 Standard_Boolean isWarning = Standard_False;
547 if (!GetSolver()->ComputeFunction(aFunction)) {
548 SetErrorCode("Shape driver failed");
552 catch (Standard_Failure& aFail) {
553 SetErrorCode(aFail.GetMessageString());
554 // to provide warning
555 if (!aFunction->GetValue().IsNull()) {
556 isWarning = Standard_True;
562 //Make a Python command
563 GEOM::TPythonDump pd (aFunction);
564 pd << aShape << " = geompy.MakeFaceWires([";
567 it = theShapes.begin();
568 if (it != theShapes.end()) {
570 while (it != theShapes.end()) {
571 pd << ", " << (*it++);
574 pd << "], " << (int)isPlanarWanted << ")";
576 // to provide warning
577 if (!isWarning) SetErrorCode(OK);
581 //=============================================================================
583 * MakeFaceFromSurface
585 //=============================================================================
586 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface
587 (Handle(GEOM_Object) theFace,
588 Handle(GEOM_Object) theWire)
593 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FACE);
596 Handle(GEOM_Function) aFunction =
597 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_FROM_SURFACE);
599 if (aFunction.IsNull()) {
603 //Check if the function is set correctly
604 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
608 GEOMImpl_IShapes aCI (aFunction);
609 Handle(TColStd_HSequenceOfTransient) aShapesSeq =
610 new TColStd_HSequenceOfTransient;
611 Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
612 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
614 if (aRefFace.IsNull()) {
615 SetErrorCode("NULL argument face for the face construction");
619 if (aRefWire.IsNull()) {
620 SetErrorCode("NULL argument wire for the face construction");
624 aShapesSeq->Append(aRefFace);
625 aShapesSeq->Append(aRefWire);
627 aCI.SetShapes(aShapesSeq);
632 if (!GetSolver()->ComputeFunction(aFunction)) {
633 SetErrorCode("Shape driver failed");
637 catch (Standard_Failure& aFail) {
638 SetErrorCode(aFail.GetMessageString());
642 //Make a Python command
643 GEOM::TPythonDump (aFunction) << aShape
644 << " = geompy.MakeFaceFromSurface(" << theFace << ", " << theWire << ")";
651 //=============================================================================
653 * MakeFaceWithConstraints
655 //=============================================================================
656 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWithConstraints
657 (std::list<Handle(GEOM_Object)> theConstraints)
662 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FILLING);
665 Handle(GEOM_Function) aFunction =
666 aShape->AddFunction(GEOMImpl_FillingDriver::GetID(), FILLING_ON_CONSTRAINTS);
667 if (aFunction.IsNull()) return NULL;
669 //Check if the function is set correctly
670 if (aFunction->GetDriverGUID() != GEOMImpl_FillingDriver::GetID()) return NULL;
672 GEOMImpl_IFilling aCI (aFunction);
673 Handle(TColStd_HSequenceOfTransient) aConstraints = new TColStd_HSequenceOfTransient;
676 std::list<Handle(GEOM_Object)>::iterator it = theConstraints.begin();
677 while (it != theConstraints.end()) {
678 Handle(GEOM_Object) anObject = (*it);
679 if ( anObject.IsNull() || anObject->GetValue().ShapeType() != TopAbs_EDGE ) {
680 SetErrorCode("NULL argument edge for the face construction");
683 Handle(GEOM_Function) aRefSh = anObject->GetLastFunction();
684 aConstraints->Append(aRefSh);
686 if ( it != theConstraints.end() ) {
687 Handle(GEOM_Object) aFace = (*it);
688 if ( aFace.IsNull() ) {
689 // null constraint face - it is a valid case
693 if ( aFace->GetValue().ShapeType() != TopAbs_FACE )
694 // constraint face can be omitted - it is a valid case
696 // Keep the old error code as IsSubShapeBelongsTo changes it.
697 TCollection_AsciiString anOldCode = GetErrorCode();
699 if ( IsSubShapeBelongsTo( anObject, 0, aFace, 0 ) ) {
701 SetErrorCode(anOldCode);
702 aRefSh = aFace->GetLastFunction();
703 aConstraints->Append(aRefSh);
708 SetErrorCode("Face is NULL or not connected to the Edge");
713 aCI.SetShapes( aConstraints );
716 Standard_Boolean isWarning = Standard_False;
719 if (!GetSolver()->ComputeFunction(aFunction)) {
720 SetErrorCode("Shape driver failed");
724 catch (Standard_Failure& aFail) {
725 SetErrorCode(aFail.GetMessageString());
726 // to provide warning
727 if (!aFunction->GetValue().IsNull()) {
728 isWarning = Standard_True;
734 //Make a Python command
735 GEOM::TPythonDump pd (aFunction);
736 pd << aShape << " = geompy.MakeFaceWithConstraints([";
739 it = theConstraints.begin();
740 if (it != theConstraints.end() ) {
742 while (it != theConstraints.end()) {
743 Handle(GEOM_Object) anObject = (*it++);
744 if( !anObject.IsNull() )
745 pd << ", " << anObject;
750 // to provide warning
751 if (!isWarning) SetErrorCode(OK);
755 //=============================================================================
759 //=============================================================================
760 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
761 (std::list<Handle(GEOM_Object)> theShapes)
763 return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
766 //=============================================================================
770 //=============================================================================
771 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
772 (std::list<Handle(GEOM_Object)> theShapes)
774 return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
777 //=============================================================================
781 //=============================================================================
782 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
783 (std::list<Handle(GEOM_Object)> theShapes)
785 return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
788 //=============================================================================
792 //=============================================================================
793 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
794 (std::list<Handle(GEOM_Object)> theShapes,
795 const Standard_Integer theObjectType,
796 const Standard_Integer theFunctionType,
797 const TCollection_AsciiString& theMethodName)
802 Handle(GEOM_Object) aShape = GetEngine()->AddObject(theObjectType);
805 Handle(GEOM_Function) aFunction =
806 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
807 if (aFunction.IsNull()) return NULL;
809 //Check if the function is set correctly
810 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
812 GEOMImpl_IShapes aCI (aFunction);
814 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
817 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
818 for (; it != theShapes.end(); it++) {
819 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
820 if (aRefSh.IsNull()) {
821 SetErrorCode("NULL argument shape for the shape construction");
824 aShapesSeq->Append(aRefSh);
826 aCI.SetShapes(aShapesSeq);
831 if (!GetSolver()->ComputeFunction(aFunction)) {
832 SetErrorCode("Shape driver failed");
836 catch (Standard_Failure& aFail) {
837 SetErrorCode(aFail.GetMessageString());
841 //Make a Python command
842 GEOM::TPythonDump pd (aFunction);
843 pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
846 it = theShapes.begin();
847 if (it != theShapes.end()) {
849 while (it != theShapes.end()) {
850 pd << ", " << (*it++);
859 //=============================================================================
861 * MakeSolidFromConnectedFaces
863 //=============================================================================
864 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidFromConnectedFaces
865 (std::list<Handle(GEOM_Object)> theFacesOrShells,
866 const Standard_Boolean isIntersect)
871 Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GEOM_SOLID);
874 Handle(GEOM_Function) aFunction =
875 aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_FACES);
876 if (aFunction.IsNull()) return NULL;
878 //Check if the function is set correctly
879 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
881 GEOMImpl_IShapes aCI (aFunction);
883 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
886 std::list<Handle(GEOM_Object)>::iterator it = theFacesOrShells.begin();
887 for (; it != theFacesOrShells.end(); it++) {
888 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
889 if (aRefSh.IsNull()) {
890 SetErrorCode("NULL argument shape for the shape construction");
893 aShapesSeq->Append(aRefSh);
895 aCI.SetShapes(aShapesSeq);
896 aCI.SetIsIntersect(isIntersect);
901 if (!GetSolver()->ComputeFunction(aFunction)) {
902 SetErrorCode("Shape driver failed");
906 catch (Standard_Failure& aFail) {
907 SetErrorCode(aFail.GetMessageString());
911 //Make a Python command
912 GEOM::TPythonDump pd (aFunction);
913 pd << aSolid << " = geompy.MakeSolidFromConnectedFaces([";
916 it = theFacesOrShells.begin();
917 if (it != theFacesOrShells.end()) {
919 while (it != theFacesOrShells.end()) {
920 pd << ", " << (*it++);
923 pd << "]," << (isIntersect ? "True" : "False") << ")";
929 //=============================================================================
933 //=============================================================================
935 GEOMImpl_IShapesOperations::MakeGlueFaces (std::list< Handle(GEOM_Object) >& theShapes,
936 const Standard_Real theTolerance,
937 const Standard_Boolean doKeepNonSolids)
941 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
942 if ( objects.IsNull() || objects->IsEmpty() ) {
943 SetErrorCode("NULL argument shape");
947 //Add a new Glued object
948 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
950 //Add a new Glue function
951 Handle(GEOM_Function) aFunction;
952 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
953 if (aFunction.IsNull()) return NULL;
955 //Check if the function is set correctly
956 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
958 GEOMImpl_IGlue aCI (aFunction);
960 aCI.SetBase( objects );
961 aCI.SetTolerance(theTolerance);
962 aCI.SetKeepNonSolids(doKeepNonSolids);
964 //Compute the sub-shape value
965 Standard_Boolean isWarning = Standard_False;
968 if (!GetSolver()->ComputeFunction(aFunction)) {
969 SetErrorCode("Shape driver failed to glue faces");
973 catch (Standard_Failure& aFail) {
974 SetErrorCode(aFail.GetMessageString());
975 // to provide warning
976 if (!aFunction->GetValue().IsNull()) {
977 isWarning = Standard_True;
983 //Make a Python command
984 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
985 << theShapes << ", " << theTolerance << ")";
987 // to provide warning
988 if (!isWarning) SetErrorCode(OK);
992 //=============================================================================
996 //=============================================================================
998 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
999 (Handle(GEOM_Object) theShape,
1000 const Standard_Real theTolerance)
1004 if (theShape.IsNull()) return NULL;
1005 TopoDS_Shape aShape = theShape->GetValue();
1006 if (aShape.IsNull()) return NULL;
1008 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1010 Standard_Integer iErr;
1012 GEOMAlgo_Gluer1 aGluer;
1013 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
1014 GEOMAlgo_CoupleOfShapes aCS;
1015 GEOMAlgo_ListOfCoupleOfShapes aLCS;
1017 //aGluer = new GEOMAlgo_Gluer1;
1018 aGluer.SetShape(aShape);
1019 aGluer.SetTolerance(theTolerance);
1021 iErr = aGluer.ErrorStatus();
1022 if (iErr) return NULL;
1024 TopTools_ListOfShape listShape;
1025 const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
1027 aItCS.Initialize(aLCSG);
1028 for (; aItCS.More(); aItCS.Next()) {
1029 const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
1030 listShape.Append(aCSG.Shape1());
1033 TopTools_ListIteratorOfListOfShape itSub (listShape);
1034 TCollection_AsciiString anAsciiList, anEntry;
1035 TopTools_IndexedMapOfShape anIndices;
1036 TopExp::MapShapes(aShape, anIndices);
1037 Handle(TColStd_HArray1OfInteger) anArray;
1038 Handle(GEOM_Object) anObj;
1039 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1040 TopoDS_Shape aValue = itSub.Value();
1041 anArray = new TColStd_HArray1OfInteger(1,1);
1042 anArray->SetValue(1, anIndices.FindIndex(aValue));
1043 anObj = GetEngine()->AddSubShape(theShape, anArray);
1044 if (!anObj.IsNull()) {
1045 aSeq->Append(anObj);
1047 // for python command
1048 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1049 anAsciiList += anEntry;
1054 //Make a Python command
1055 if( anAsciiList.Length() > 0 ) {
1056 anAsciiList.Trunc(anAsciiList.Length() - 1);
1057 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1058 GEOM::TPythonDump pd (aFunction, true);
1059 pd << "[" << anAsciiList.ToCString();
1060 pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
1069 //=============================================================================
1071 * MakeGlueFacesByList
1073 //=============================================================================
1075 GEOMImpl_IShapesOperations::MakeGlueFacesByList(std::list< Handle(GEOM_Object) >& theShapes,
1076 const Standard_Real theTolerance,
1077 std::list<Handle(GEOM_Object)> & theFaces,
1078 const Standard_Boolean doKeepNonSolids,
1079 const Standard_Boolean doGlueAllEdges)
1083 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1084 if ( objects.IsNull() || objects->IsEmpty() ) {
1085 SetErrorCode("NULL argument shape");
1088 Handle(TColStd_HSequenceOfTransient) aFaces = GEOM_Object::GetLastFunctions( theFaces );
1089 if ( aFaces.IsNull() ) {
1090 SetErrorCode("NULL argument shape for the shape construction");
1094 //Add a new Glued object
1095 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
1097 //Add a new Glue function
1098 Handle(GEOM_Function) aFunction;
1099 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
1100 if (aFunction.IsNull()) return NULL;
1102 //Check if the function is set correctly
1103 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1105 GEOMImpl_IGlue aCI (aFunction);
1107 aCI.SetBase( objects );
1108 aCI.SetTolerance(theTolerance);
1109 aCI.SetKeepNonSolids(doKeepNonSolids);
1110 aCI.SetGlueAllEdges(doGlueAllEdges);
1111 aCI.SetFaces(aFaces);
1113 //Compute the sub-shape value
1114 Standard_Boolean isWarning = Standard_False;
1117 if (!GetSolver()->ComputeFunction(aFunction)) {
1118 SetErrorCode("Shape driver failed to glue faces");
1122 catch (Standard_Failure& aFail) {
1123 SetErrorCode(aFail.GetMessageString());
1124 // to provide warning
1125 if (!aFunction->GetValue().IsNull()) {
1126 isWarning = Standard_True;
1132 //Make a Python command
1134 GEOM::TPythonDump pd(aFunction);
1135 pd << aGlued << " = geompy.MakeGlueFacesByList("
1136 << theShapes << ", " << theTolerance << ", " << theFaces << ", "
1137 << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")";
1139 // to provide warning
1140 if (!isWarning) SetErrorCode(OK);
1144 //=============================================================================
1148 //=============================================================================
1150 GEOMImpl_IShapesOperations::MakeGlueEdges (std::list< Handle(GEOM_Object) >& theShapes,
1151 const Standard_Real theTolerance)
1155 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1156 if ( objects.IsNull() || objects->IsEmpty() ) {
1157 SetErrorCode("NULL argument shape");
1161 //Add a new Glued object
1162 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
1164 //Add a new Glue function
1165 Handle(GEOM_Function) aFunction;
1166 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES);
1167 if (aFunction.IsNull()) return NULL;
1169 //Check if the function is set correctly
1170 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1172 GEOMImpl_IGlue aCI (aFunction);
1174 aCI.SetBase( objects );
1175 aCI.SetTolerance(theTolerance);
1176 aCI.SetKeepNonSolids(true);
1178 //Compute the sub-shape value
1179 Standard_Boolean isWarning = Standard_False;
1182 if (!GetSolver()->ComputeFunction(aFunction)) {
1183 SetErrorCode("Shape driver failed to glue edges");
1187 catch (Standard_Failure& aFail) {
1188 SetErrorCode(aFail.GetMessageString());
1189 // to provide warning
1190 if (!aFunction->GetValue().IsNull()) {
1191 isWarning = Standard_True;
1197 //Make a Python command
1198 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueEdges("
1199 << theShapes << ", " << theTolerance << ")";
1201 // to provide warning
1202 if (!isWarning) SetErrorCode(OK);
1206 //=============================================================================
1210 //=============================================================================
1211 Handle(TColStd_HSequenceOfTransient)
1212 GEOMImpl_IShapesOperations::GetGlueShapes (std::list< Handle(GEOM_Object) >& theShapes,
1213 const Standard_Real theTolerance,
1214 const TopAbs_ShapeEnum theType)
1218 TopoDS_Shape aShape;
1219 TopTools_SequenceOfShape shapes;
1220 std::list< Handle(GEOM_Object) >::iterator s = theShapes.begin();
1221 Handle(GEOM_BaseObject) lastCreatedGO;
1222 for ( ; s != theShapes.end(); ++s )
1224 Handle(GEOM_Object) go = *s;
1225 if ( go.IsNull() ) return NULL;
1226 aShape = go->GetValue();
1227 if ( aShape.IsNull() ) return NULL;
1228 shapes.Append( aShape );
1229 lastCreatedGO = GEOM::GetCreatedLast( lastCreatedGO, go );
1231 if ( shapes.Length() > 1 )
1233 TopoDS_Compound compound;
1234 BRep_Builder builder;
1235 builder.MakeCompound( compound );
1236 for ( int i = 1; i <= shapes.Length(); ++i )
1237 builder.Add( compound, shapes( i ) );
1242 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1244 GEOMAlgo_GlueDetector aGluer;
1245 aGluer.SetArgument(aShape);
1246 aGluer.SetTolerance(theTolerance);
1248 Standard_Integer iErr = aGluer.ErrorStatus();
1249 if (iErr) return NULL;
1251 std::vector< TopTools_IndexedMapOfShape* > anIndices( shapes.Length(), NULL );
1252 Handle(TColStd_HArray1OfInteger) anArray;
1253 Handle(GEOM_Object) anObj;
1255 TopTools_ListOfShape listOnePerSet;
1257 const TopTools_DataMapOfShapeListOfShape& aImages = aGluer.Images();
1258 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS (aImages);
1259 for (int index = 1; aItDMSLS.More(); aItDMSLS.Next(), ++index) {
1261 //const TopoDS_Shape& aSkey = aItDMSLS.Key();
1263 // list of shapes of the argument that can be glued
1264 const TopTools_ListOfShape& aLSD = aItDMSLS.Value();
1266 //listShape.Append(aLSD.First());
1267 TopoDS_Shape aValue = aLSD.First();
1269 if (aValue.ShapeType() == theType) {
1270 listOnePerSet.Append(aValue);
1274 // for stable order of returned entities
1275 GEOMUtils::SortShapes(listOnePerSet, Standard_False);
1277 TopTools_ListIteratorOfListOfShape aListIt (listOnePerSet);
1278 for (; aListIt.More(); aListIt.Next())
1280 TopoDS_Shape aValue = aListIt.Value();
1281 // find a shape to add aValue as a sub-shape
1283 s = theShapes.begin();
1284 for ( int i = 0; i < shapes.Length(); ++i, ++s )
1286 Handle(GEOM_Object) object = *s;
1287 if ( !anIndices[i] ) {
1288 anIndices[i] = new TopTools_IndexedMapOfShape;
1289 TopExp::MapShapes( object->GetValue(), *anIndices[i]);
1291 if (int index = anIndices[i]->FindIndex( aValue )) {
1292 anArray = new TColStd_HArray1OfInteger(1,1);
1293 anArray->SetValue(1, index);
1294 anObj = GetEngine()->AddSubShape( object, anArray);
1298 if (!anObj.IsNull())
1299 aSeq->Append(anObj);
1301 for ( size_t i = 0 ; i < anIndices.size(); ++i )
1302 delete anIndices[i];
1304 // Make a Python command
1305 if ( aSeq->Length() > 0)
1307 Handle(GEOM_Function) aFunction = lastCreatedGO->GetLastFunction();
1308 GEOM::TPythonDump pd (aFunction, /*append=*/true);
1310 << " = geompy." << (theType == TopAbs_FACE ? "GetGlueFaces" : "GetGlueEdges" )
1311 << "( " << theShapes << ", " << theTolerance << ")";
1319 //=============================================================================
1321 * MakeGlueEdgesByList
1323 //=============================================================================
1325 GEOMImpl_IShapesOperations::MakeGlueEdgesByList (std::list< Handle(GEOM_Object) >& theShapes,
1326 const Standard_Real theTolerance,
1327 std::list<Handle(GEOM_Object)>& theEdges)
1331 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1332 if ( objects.IsNull() || objects->IsEmpty() ) {
1333 SetErrorCode("NULL argument shape");
1336 Handle(TColStd_HSequenceOfTransient) anEdges = GEOM_Object::GetLastFunctions( theEdges );
1337 if ( anEdges.IsNull() ) {
1338 SetErrorCode("NULL argument shape for the shape construction");
1341 //Add a new Glued object
1342 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED);
1344 //Add a new Glue function
1345 Handle(GEOM_Function) aFunction;
1346 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES_BY_LIST);
1347 if (aFunction.IsNull()) return NULL;
1349 //Check if the function is set correctly
1350 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1352 GEOMImpl_IGlue aCI (aFunction);
1354 aCI.SetBase( objects );
1355 aCI.SetTolerance(theTolerance);
1356 aCI.SetKeepNonSolids(true);
1357 aCI.SetFaces(anEdges);
1359 //Compute the sub-shape value
1360 Standard_Boolean isWarning = Standard_False;
1363 if (!GetSolver()->ComputeFunction(aFunction)) {
1364 SetErrorCode("Shape driver failed to glue edges");
1368 catch (Standard_Failure& aFail) {
1369 SetErrorCode(aFail.GetMessageString());
1370 // to provide warning
1371 if (!aFunction->GetValue().IsNull()) {
1372 isWarning = Standard_True;
1378 //Make a Python command
1380 GEOM::TPythonDump pd (aFunction);
1381 pd << aGlued << " = geompy.MakeGlueEdgesByList("
1382 << theShapes << ", " << theTolerance << ", " << theEdges << " )";
1384 // to provide warning
1385 if (!isWarning) SetErrorCode(OK);
1389 //=============================================================================
1391 * GetExistingSubObjects
1393 //=============================================================================
1394 Handle(TColStd_HSequenceOfTransient)
1395 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape,
1396 const Standard_Boolean theGroupsOnly)
1398 // note: this method does not return fields
1400 Standard_Integer types = theGroupsOnly ? Groups : Groups|SubShapes;
1401 Handle(TColStd_HSequenceOfTransient) results = GetExistingSubObjects(theShape, types);
1403 Handle(GEOM_BaseObject) lastCreatedGO = GEOM::GetCreatedLast(results);
1404 lastCreatedGO = GEOM::GetCreatedLast(lastCreatedGO, theShape);
1406 if (results->Length() > 0) {
1407 // Make a Python command
1408 GEOM::TPythonDump pd (lastCreatedGO->GetLastFunction(), /*append=*/true);
1410 Standard_Integer i, aLen = results->Length();
1411 for (i = 1; i <= aLen; i++)
1413 Handle(GEOM_BaseObject) obj = Handle(GEOM_BaseObject)::DownCast(results->Value(i));
1414 pd << obj << ((i < aLen) ? ", " : "");
1416 pd << "] = geompy.GetExistingSubObjects(";
1417 pd << theShape << ", " << (bool)theGroupsOnly << ")";
1423 Handle(TColStd_HSequenceOfTransient)
1424 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape,
1425 const Standard_Integer theTypes)
1429 if (theShape.IsNull()) return NULL;
1431 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1432 if (aMainShape.IsNull()) return NULL;
1434 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1435 SetErrorCode(NOT_FOUND_ANY);
1437 if (!aMainShape->HasSubShapeReferences()) return aSeq;
1438 const TDataStd_ListOfExtendedString& aListEntries = aMainShape->GetSubShapeReferences();
1439 if (aListEntries.IsEmpty()) return aSeq;
1443 TDataStd_ListIteratorOfListOfExtendedString anIt (aListEntries);
1444 for (; anIt.More(); anIt.Next()) {
1445 TCollection_ExtendedString anEntry = anIt.Value();
1446 Standard_Integer aStrLen = anEntry.LengthOfCString();
1447 char* anEntryStr = new char[aStrLen+1];
1448 anEntry.ToUTF8CString(anEntryStr);
1449 Handle(GEOM_BaseObject) anObj = GetEngine()->GetObject(anEntryStr, false);
1450 if (!anObj.IsNull() ) {
1451 bool isGroup = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() == GEOM_GROUP;
1452 bool isSubShape = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() != GEOM_GROUP;
1453 bool isField = anObj->IsKind(STANDARD_TYPE(GEOM_Field));
1454 if ((theTypes & Groups && isGroup ) ||
1455 (theTypes & SubShapes && isSubShape ) ||
1456 (theTypes & Fields && isField ))
1457 aSeq->Append(anObj);
1459 delete [] anEntryStr;
1462 if (aSeq->Length() == 0) {
1463 SetErrorCode(NOT_FOUND_ANY);
1472 //=============================================================================
1476 //=============================================================================
1477 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
1478 (Handle(GEOM_Object) theShape,
1479 const Standard_Integer theShapeType,
1480 const Standard_Boolean isSorted,
1481 const ExplodeType theExplodeType)
1485 if (theShape.IsNull()) return NULL;
1486 TopoDS_Shape aShape = theShape->GetValue();
1487 if (aShape.IsNull()) return NULL;
1489 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1491 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1492 Handle(GEOM_Object) anObj;
1493 TopTools_MapOfShape mapShape;
1494 TopTools_ListOfShape listShape;
1496 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1497 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1499 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1500 for (; It.More(); It.Next()) {
1501 TopoDS_Shape SS = It.Value();
1502 if (mapShape.Add(SS)) {
1503 if (theShapeType == TopAbs_FLAT) {
1504 AddFlatSubShapes(SS, listShape, mapShape);
1506 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1507 listShape.Append(SS);
1509 // VSR: for EXPLODE_NEW_INCLUDE_MAIN and EXPLODE_OLD_INCLUDE_MAIN:
1510 // it seems it is necessary to add top-level shape if theShapeType == TopAbs_COMPOUND
1514 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1516 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1517 for (; exp.More(); exp.Next())
1518 if (mapShape.Add(exp.Current()))
1519 listShape.Append(exp.Current());
1522 if (listShape.IsEmpty()){
1523 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1524 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1529 bool isOldSorting = false;
1530 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1531 isOldSorting = true;
1532 GEOMUtils::SortShapes(listShape, isOldSorting);
1535 TopTools_IndexedMapOfShape anIndices;
1536 TopExp::MapShapes(aShape, anIndices);
1537 Handle(TColStd_HArray1OfInteger) anArray;
1539 TopTools_ListIteratorOfListOfShape itSub (listShape);
1540 TCollection_AsciiString anAsciiList, anEntry;
1541 for (int index = 1; itSub.More(); itSub.Next(), ++index)
1543 TopoDS_Shape aValue = itSub.Value();
1544 anArray = new TColStd_HArray1OfInteger(1,1);
1545 anArray->SetValue(1, anIndices.FindIndex(aValue));
1547 //anObj = GetEngine()->AddSubShape(theShape, anArray);
1549 anObj = GetEngine()->AddObject(GEOM_SUBSHAPE);
1550 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1551 if (aFunction.IsNull()) return aSeq;
1553 GEOM_ISubShape aSSI (aFunction);
1554 aSSI.SetMainShape(aMainShape);
1555 aSSI.SetIndices(anArray);
1557 // Set function value directly, as we know it.
1558 // Usage of Solver here would lead to significant loss of time,
1559 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1560 // on the main shape for each being calculated sub-shape separately.
1561 aFunction->SetValue(aValue);
1563 // Put this subshape in the list of sub-shapes of theMainShape
1564 aMainShape->AddSubShapeReference(aFunction);
1566 if (!anObj.IsNull()) {
1567 aSeq->Append(anObj);
1569 // for python command
1570 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1571 anAsciiList += anEntry;
1576 //Make a Python command
1577 anAsciiList.Trunc(anAsciiList.Length() - 1);
1579 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1580 pd << "[" << anAsciiList.ToCString() << "] = geompy.";
1581 switch (theExplodeType) {
1582 case EXPLODE_NEW_EXCLUDE_MAIN:
1583 pd << "ExtractShapes(" << theShape << ", "
1584 << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")";
1586 case EXPLODE_NEW_INCLUDE_MAIN:
1587 pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(")
1588 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1590 case EXPLODE_OLD_INCLUDE_MAIN:
1591 pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(")
1592 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1601 //=============================================================================
1605 //=============================================================================
1606 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
1607 (Handle(GEOM_Object) theShape,
1608 const Standard_Integer theShapeType,
1609 const Standard_Boolean isSorted,
1610 const ExplodeType theExplodeType)
1614 if (theShape.IsNull()) return NULL;
1615 TopoDS_Shape aShape = theShape->GetValue();
1616 if (aShape.IsNull()) return NULL;
1618 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1619 TopTools_MapOfShape mapShape;
1620 TopTools_ListOfShape listShape;
1622 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1623 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1625 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1626 for (; It.More(); It.Next()) {
1627 TopoDS_Shape SS = It.Value();
1628 if (mapShape.Add(SS)) {
1629 if (theShapeType == TopAbs_FLAT) {
1630 AddFlatSubShapes(SS, listShape, mapShape);
1632 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1633 listShape.Append(SS);
1638 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1640 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1641 for (; exp.More(); exp.Next())
1642 if (mapShape.Add(exp.Current()))
1643 listShape.Append(exp.Current());
1646 if (listShape.IsEmpty()) {
1647 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1648 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1653 bool isOldSorting = false;
1654 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1655 isOldSorting = true;
1656 GEOMUtils::SortShapes(listShape, isOldSorting);
1659 TopTools_IndexedMapOfShape anIndices;
1660 TopExp::MapShapes(aShape, anIndices);
1661 Handle(TColStd_HArray1OfInteger) anArray;
1663 TopTools_ListIteratorOfListOfShape itSub (listShape);
1664 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1665 TopoDS_Shape aValue = itSub.Value();
1666 aSeq->Append(anIndices.FindIndex(aValue));
1669 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1671 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
1672 #ifdef DUMP_SUBSHAPE_IDS
1673 //Make a Python command
1674 GEOM::TPythonDump pd (aFunction, /*append=*/true);
1675 pd << "listSubShapeIDs = geompy.SubShapeAll";
1676 switch (theExplodeType) {
1677 case EXPLODE_NEW_EXCLUDE_MAIN:
1679 case EXPLODE_NEW_INCLUDE_MAIN:
1680 pd << (isSorted ? "SortedCentresIDs(" : "IDs(")
1681 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1683 case EXPLODE_OLD_INCLUDE_MAIN:
1684 pd << (isSorted ? "SortedIDs(" : "IDs(")
1685 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1689 #endif // DUMP_SUBSHAPE_IDS
1695 //=============================================================================
1699 //=============================================================================
1700 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
1701 (Handle(GEOM_Object) theMainShape,
1702 const Standard_Integer theID)
1706 if (theMainShape.IsNull()) return NULL;
1708 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1709 anArray->SetValue(1, theID);
1710 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
1711 if (anObj.IsNull()) {
1712 SetErrorCode("Can not get a sub-shape with the given ID");
1716 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1718 //Make a Python command
1719 GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1720 << theMainShape << ", [" << theID << "])";
1726 //=============================================================================
1730 //=============================================================================
1731 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes
1732 (Handle(GEOM_Object) theMainShape,
1733 Handle(TColStd_HArray1OfInteger) theIndices)
1737 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1739 if (!theIndices->Length()) {
1740 SetErrorCode(NOT_FOUND_ANY);
1744 if (theMainShape.IsNull()) return NULL;
1745 TopoDS_Shape aShape = theMainShape->GetValue();
1746 if (aShape.IsNull()) return NULL;
1748 Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
1750 TopTools_IndexedMapOfShape anIndices;
1751 TopExp::MapShapes(aShape, anIndices);
1753 Handle(TColStd_HArray1OfInteger) anArray;
1754 Handle(GEOM_Object) anObj;
1756 TCollection_AsciiString anAsciiList, anEntry;
1757 Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper();
1758 for (i = low; i <= up; i++) {
1759 int id = theIndices->Value(i);
1760 if (1 <= id && id <= anIndices.Extent()) {
1761 TopoDS_Shape aValue = anIndices.FindKey(id);
1762 anArray = new TColStd_HArray1OfInteger(1,1);
1763 anArray->SetValue(1, id);
1765 anObj = GetEngine()->AddObject(GEOM_SUBSHAPE);
1766 if (!anObj.IsNull()) {
1767 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1768 if (aFunction.IsNull()) return aSeq;
1770 GEOM_ISubShape aSSI (aFunction);
1771 aSSI.SetMainShape(aMainShape);
1772 aSSI.SetIndices(anArray);
1774 // Set function value directly, as we know it.
1775 // Usage of Solver here would lead to significant loss of time,
1776 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1777 // on the main shape for each being calculated sub-shape separately.
1778 aFunction->SetValue(aValue);
1780 // Put this sub-shape in the list of sub-shapes of theMainShape
1781 aMainShape->AddSubShapeReference(aFunction);
1783 aSeq->Append(anObj);
1785 // for python command
1786 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1787 anAsciiList += anEntry;
1793 //Make a Python command
1794 anAsciiList.Trunc(anAsciiList.Length() - 1);
1796 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1797 pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes("
1798 << theMainShape << ", [" ;
1799 for (i = low; i <= up - 1; i++) {
1800 pd << theIndices->Value(i) << ", ";
1802 pd << theIndices->Value(up) << "])";
1809 //=============================================================================
1813 //=============================================================================
1814 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1815 Handle(GEOM_Object) theSubShape)
1819 TopoDS_Shape aMainShape = theMainShape->GetValue();
1820 TopoDS_Shape aSubShape = theSubShape->GetValue();
1822 if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1824 TopTools_IndexedMapOfShape anIndices;
1825 TopExp::MapShapes(aMainShape, anIndices);
1826 // if (anIndices.Contains(aSubShape)) {
1827 // SetErrorCode(OK);
1828 // return anIndices.FindIndex(aSubShape);
1830 int id = anIndices.FindIndex(aSubShape);
1841 //=============================================================================
1843 * GetSubShapeIndices
1845 //=============================================================================
1846 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSubShapesIndices (Handle(GEOM_Object) theMainShape,
1847 std::list<Handle(GEOM_Object)> theSubShapes)
1849 MESSAGE("GEOMImpl_IShapesOperations::GetSubShapesIndices")
1852 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1854 TopoDS_Shape aMainShape = theMainShape->GetValue();
1855 if (aMainShape.IsNull())
1857 MESSAGE("NULL main shape")
1861 TopTools_IndexedMapOfShape anIndices;
1862 TopExp::MapShapes(aMainShape, anIndices);
1864 std::list<Handle(GEOM_Object)>::iterator it;
1865 for (it=theSubShapes.begin(); it != theSubShapes.end(); ++it)
1867 TopoDS_Shape aSubShape = (*it)->GetValue();
1868 if (aSubShape.IsNull())
1870 MESSAGE("NULL subshape")
1873 int id = anIndices.FindIndex(aSubShape);
1882 //=============================================================================
1886 //=============================================================================
1887 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1888 Handle(GEOM_Object) theSubShape)
1892 TopoDS_Shape aMainShape = theMainShape->GetValue();
1893 TopoDS_Shape aSubShape = theSubShape->GetValue();
1895 if (aMainShape.IsNull() || aSubShape.IsNull()) {
1896 SetErrorCode("Null argument shape given");
1901 if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1903 TopTools_ListOfShape CL;
1904 CL.Append(aMainShape);
1905 TopTools_ListIteratorOfListOfShape itC;
1906 for (itC.Initialize(CL); itC.More(); itC.Next()) {
1907 for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1908 if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1909 if (it.Value().IsSame(aSubShape))
1913 CL.Append(it.Value());
1918 TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1919 TopTools_MapOfShape M;
1920 for (; anExp.More(); anExp.Next()) {
1921 if (M.Add(anExp.Current())) {
1922 if (anExp.Current().IsSame(aSubShape))
1929 SetErrorCode("The sub-shape does not belong to the main shape");
1933 //=============================================================================
1935 * GetShapeTypeString
1937 //=============================================================================
1938 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1942 TCollection_AsciiString aTypeName ("Null Shape");
1944 TopoDS_Shape aShape = theShape->GetValue();
1945 if (aShape.IsNull())
1948 switch (aShape.ShapeType() )
1950 case TopAbs_COMPOUND:
1951 aTypeName = "Compound";
1953 case TopAbs_COMPSOLID:
1954 aTypeName = "Compound Solid";
1957 aTypeName = "Solid";
1960 aTypeName = "Shell";
1964 BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1965 if (surf.GetType() == GeomAbs_Plane)
1966 aTypeName = "Plane";
1967 else if (surf.GetType() == GeomAbs_Cylinder)
1968 aTypeName = "Cylindrical Face";
1969 else if (surf.GetType() == GeomAbs_Sphere)
1970 aTypeName = "Spherical Face";
1971 else if (surf.GetType() == GeomAbs_Torus)
1972 aTypeName = "Toroidal Face";
1973 else if (surf.GetType() == GeomAbs_Cone)
1974 aTypeName = "Conical Face";
1976 aTypeName = "GEOM::FACE";
1984 BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1985 if (curv.GetType() == GeomAbs_Line) {
1986 if ((Abs(curv.FirstParameter()) >= 1E6) ||
1987 (Abs(curv.LastParameter()) >= 1E6))
1991 } else if (curv.GetType() == GeomAbs_Circle) {
1992 if (curv.IsClosed())
1993 aTypeName = "Circle";
2002 aTypeName = "Vertex";
2005 aTypeName = "Shape";
2008 aTypeName = "Shape of unknown type";
2014 //=============================================================================
2016 * IsSubShapeBelongsTo
2018 //=============================================================================
2019 Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject,
2020 const Standard_Integer theSubObjectIndex,
2021 Handle(GEOM_Object) theObject,
2022 const Standard_Integer theObjectIndex)
2026 if ( theObject.IsNull() || theSubObject.IsNull() )
2029 TopoDS_Shape shape = theObject->GetValue();
2030 TopoDS_Shape subShape = theSubObject->GetValue();
2032 if ( shape.IsNull() || subShape.IsNull() )
2035 TopTools_IndexedMapOfShape anIndices;
2036 if ( theObjectIndex > 0 ) {
2037 TopExp::MapShapes( shape, anIndices );
2038 shape = anIndices.FindKey(theObjectIndex);
2041 if ( theSubObjectIndex > 0 ) {
2042 TopExp::MapShapes( subShape, anIndices );
2043 subShape = anIndices.FindKey(theSubObjectIndex);
2047 TopExp::MapShapes( shape, anIndices );
2049 const Standard_Boolean isBelongTo = anIndices.Contains(subShape);
2056 //=============================================================================
2060 //=============================================================================
2061 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
2062 (Handle(GEOM_Object) theShape,
2063 const Standard_Integer theShapeType)
2066 Standard_Integer nbShapes = 0;
2068 if (theShape.IsNull()) return -1;
2069 TopoDS_Shape aShape = theShape->GetValue();
2070 if (aShape.IsNull()) return -1;
2073 TopTools_MapOfShape mapShape;
2075 if (aShape.ShapeType() == TopAbs_COMPOUND &&
2076 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2077 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
2078 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
2079 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
2080 for (; It.More(); It.Next()) {
2081 if (mapShape.Add(It.Value())) {
2082 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2083 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
2089 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
2090 for (; exp.More(); exp.Next())
2091 if (mapShape.Add(exp.Current()))
2097 if (theShapeType == TopAbs_FLAT) {
2098 TopTools_MapOfShape aMapOfShape;
2099 TopTools_ListOfShape aListOfShape;
2100 AddFlatSubShapes(aShape, aListOfShape, aMapOfShape);
2101 nbShapes = aListOfShape.Extent();
2105 int iType, nbTypes [TopAbs_SHAPE];
2106 for (iType = 0; iType < TopAbs_SHAPE; ++iType)
2108 nbTypes[aShape.ShapeType()]++;
2110 TopTools_MapOfShape aMapOfShape;
2111 aMapOfShape.Add(aShape);
2112 TopTools_ListOfShape aListOfShape;
2113 aListOfShape.Append(aShape);
2115 TopTools_ListIteratorOfListOfShape itL (aListOfShape);
2116 for (; itL.More(); itL.Next()) {
2117 TopoDS_Iterator it (itL.Value());
2118 for (; it.More(); it.Next()) {
2119 TopoDS_Shape s = it.Value();
2120 if (aMapOfShape.Add(s)) {
2121 aListOfShape.Append(s);
2122 nbTypes[s.ShapeType()]++;
2127 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
2128 nbShapes = aMapOfShape.Extent();
2130 nbShapes = nbTypes[theShapeType];
2133 catch (Standard_Failure& aFail) {
2134 SetErrorCode(aFail.GetMessageString());
2142 //=============================================================================
2146 //=============================================================================
2147 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
2151 if (theShape.IsNull()) return NULL;
2154 //Add a new reversed object
2155 Handle(GEOM_Object) aReversed = GetEngine()->AddObject(theShape->GetType());
2157 //Add a new Revese function
2158 Handle(GEOM_Function) aFunction;
2159 aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
2160 if (aFunction.IsNull()) return NULL;
2162 //Check if the function is set correctly
2163 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
2165 GEOMImpl_IShapes aSI (aFunction);
2167 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2168 if (aRefShape.IsNull()) return NULL;
2170 aSI.SetBase(aRefShape);
2172 //Compute the sub-shape value
2175 if (!GetSolver()->ComputeFunction(aFunction)) {
2176 SetErrorCode("Shape driver failed to reverse shape");
2180 catch (Standard_Failure& aFail) {
2181 SetErrorCode(aFail.GetMessageString());
2185 //Make a Python command
2186 GEOM::TPythonDump(aFunction) << aReversed
2187 << " = geompy.ChangeOrientation(" << theShape << ")";
2192 Handle(GEOM_Object) aReversed;
2194 GEOM_Engine* anEngine = GetEngine();
2195 //GEOMImpl_Gen* aGen = dynamic_cast<GEOMImpl_Gen*>(anEngine);
2196 GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine;
2199 GEOMImpl_IHealingOperations* anIHealingOperations =
2200 aGen->GetIHealingOperations();
2201 aReversed = anIHealingOperations->ChangeOrientationCopy(theShape);
2202 SetErrorCode(anIHealingOperations->GetErrorCode());
2208 //=============================================================================
2212 //=============================================================================
2213 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
2214 (Handle(GEOM_Object) theShape)
2218 if (theShape.IsNull()) return NULL;
2219 TopoDS_Shape aShape = theShape->GetValue();
2220 if (aShape.IsNull()) return NULL;
2222 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
2224 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2225 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2226 (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2228 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2231 SetErrorCode("The given shape has no faces");
2235 TopTools_IndexedMapOfShape anIndices;
2236 TopExp::MapShapes(aShape, anIndices);
2238 Standard_Integer id;
2239 for (; ind <= nbFaces; ind++) {
2240 if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
2241 id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
2246 //The explode doesn't change object so no new function is required.
2247 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
2249 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2250 #ifdef DUMP_SUBSHAPE_IDS
2251 //Make a Python command
2252 GEOM::TPythonDump(aFunction, /*append=*/true)
2253 << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
2254 #endif // DUMP_SUBSHAPE_IDS
2260 //=======================================================================
2261 //function : GetSharedShapes
2263 //=======================================================================
2264 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2265 (Handle(GEOM_Object) theShape1,
2266 Handle(GEOM_Object) theShape2,
2267 const Standard_Integer theShapeType)
2271 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
2273 TopoDS_Shape aShape1 = theShape1->GetValue();
2274 TopoDS_Shape aShape2 = theShape2->GetValue();
2276 if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
2278 TopTools_IndexedMapOfShape anIndices;
2279 TopExp::MapShapes(aShape1, anIndices);
2280 Handle(TColStd_HArray1OfInteger) anArray;
2282 TopTools_IndexedMapOfShape mapShape1;
2283 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
2285 Handle(GEOM_Object) anObj;
2286 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2287 TCollection_AsciiString anAsciiList, anEntry;
2289 TopTools_MapOfShape mapShape2;
2290 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2291 for (; exp.More(); exp.Next()) {
2292 TopoDS_Shape aSS = exp.Current();
2293 if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
2294 anArray = new TColStd_HArray1OfInteger(1,1);
2295 anArray->SetValue(1, anIndices.FindIndex(aSS));
2296 anObj = GetEngine()->AddSubShape(theShape1, anArray);
2297 aSeq->Append(anObj);
2299 // for python command
2300 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2301 anAsciiList += anEntry;
2306 if (aSeq->IsEmpty()) {
2307 SetErrorCode(NOT_FOUND_ANY);
2311 //Make a Python command
2312 anAsciiList.Trunc(anAsciiList.Length() - 1);
2314 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2316 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2317 << "] = geompy.GetSharedShapes(" << theShape1 << ", "
2318 << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
2324 //=======================================================================
2325 //function : GetSharedShapes
2328 // NOTE on the implementation
2330 // 1) Resulting sub-shapes are published as a children of the 1st input shape
2331 // from theShapes list. Due to this reason only direct sub-shapes of the 1st
2332 // shape can be contained in the result of the operation (i.e. shares between
2333 // 2nd/3rd, etc couples cannot be retrieved.
2334 // 2) An exception from above case is when a single compound is specified as an
2335 // input. In this case we search shares between its top-level content, so we
2336 // are able to search shares between all possible couples of shapes.
2337 // 3) Parameter theMultiShare controls what types of shares to search:
2338 // - True: get sub-shapes that are shared between ALL input shapes;
2339 // - False: get shares between couples of input sub-shapes (see points 1 and 2).
2341 // Thus, we have the following cases:
2342 // [1] theShapes = N shapes (N>1), theMultiShare = True
2343 // Result: sub-shapes that are shared by all theShapes
2344 // [2] theShapes = N shapes (N>1), theMultiShare = False
2345 // Result: sub-shapes of 1st shape from theShapes that are shared with any shape
2347 // [3] theShapes = 1 shape, theMultiShare = True
2348 // Result: sub-shapes that are shared by all top-level sub-objects of theShapes[0]
2349 // [4] theShapes = 1 shape, theMultiShare = False
2350 // Result: sub-shapes of all possible couples of all top-level sub-objects of
2352 //=======================================================================
2353 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2354 (std::list<Handle(GEOM_Object)> & theShapes,
2355 const Standard_Integer theShapeType,
2356 const bool theMultiShare)
2360 int aLen = theShapes.size();
2361 if (aLen < 1) return NULL;
2363 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
2365 // main object is always first in the input list
2366 // it is the object from which sub-shapes indices are taken
2367 // and where results are published
2368 Handle(GEOM_Object) aMainObj = *it;
2369 Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
2371 // collect all shapes from the input list (including first one) for processing
2372 TopTools_SequenceOfShape shapeSeq;
2373 for (; it != theShapes.end(); it++) {
2374 Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
2375 if (aRefShape.IsNull()) {
2376 SetErrorCode("NULL shape for GetSharedShapes");
2379 TopoDS_Shape aShape = aRefShape->GetValue();
2380 if (aShape.IsNull()) {
2381 SetErrorCode("NULL shape for GetSharedShapes");
2384 shapeSeq.Append( aShape );
2387 // if only single shape is specified as input
2388 // collect all ites top-level sub-shapes for processing
2389 if ( shapeSeq.Length() == 1 )
2391 TopoDS_Shape aShape = shapeSeq.First();
2393 for ( TopoDS_Iterator it( aShape ); it.More(); it.Next() )
2394 shapeSeq.Append( it.Value() );
2397 // map all sub-shapes in a main shape to their indices
2398 TopTools_IndexedMapOfShape anIndices;
2399 TopExp::MapShapes(aMainShape->GetValue(), anIndices);
2400 TopTools_MapOfShape mapShape;
2402 // find shared shapes
2404 // here we will collect all shares
2405 TopTools_ListOfShape aShared;
2407 // number of iterations
2408 int nbIters = theMultiShare || theShapes.size() > 1 ? 1 : shapeSeq.Length()-1;
2409 // numShares factor to search (i.e. by what nb of shapes each found sub-shape should be shared)
2410 int nbShares = theMultiShare ? shapeSeq.Length()-1 : 1;
2412 for ( int iter = 1; iter <= nbIters; iter++) {
2413 for ( int ind = iter+1; ind <= shapeSeq.Length(); ind++) {
2414 if ( ind-1+nbShares > shapeSeq.Length() ) break;
2415 TopoDS_Compound aCurrSelection;
2416 TopoDS_Shape aShape1 = shapeSeq.Value( iter );
2417 TopTools_IndexedMapOfShape mapSelected;
2418 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
2419 for ( int s = 0; s < nbShares; s++ ) {
2421 TopoDS_Compound aCompound;
2422 B.MakeCompound(aCompound);
2423 const TopoDS_Shape& aShape2 = shapeSeq.Value( ind+s );
2424 TopTools_MapOfShape mapShape2;
2425 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2426 for (; exp.More(); exp.Next()) {
2427 const TopoDS_Shape& aSS = exp.Current();
2428 if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
2429 B.Add(aCompound, aSS);
2432 mapSelected.Clear();
2433 aCurrSelection = aCompound;
2434 TopExp::MapShapes(aCurrSelection, TopAbs_ShapeEnum(theShapeType), mapSelected);
2436 TopoDS_Iterator itSel(aCurrSelection, Standard_True, Standard_True);
2437 for (; itSel.More(); itSel.Next()) {
2438 const TopoDS_Shape& aSS = itSel.Value();
2439 if (mapShape.Add(aSS) )
2440 aShared.Append(aSS);
2445 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2447 if (aShared.IsEmpty()){
2448 SetErrorCode(NOT_FOUND_ANY);
2452 // create GEOM_Object for each found shared shape (collected in aShared)
2453 TCollection_AsciiString anAsciiList;
2454 Handle(GEOM_Object) anObj;
2455 TopTools_ListIteratorOfListOfShape itSub (aShared);
2456 for (; itSub.More(); itSub.Next()) {
2457 TopoDS_Shape aValue = itSub.Value();
2458 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2459 anArray->SetValue(1, anIndices.FindIndex(aValue));
2460 anObj = GetEngine()->AddSubShape(aMainObj, anArray);
2461 aSeq->Append(anObj);
2463 // for python command
2464 TCollection_AsciiString anEntry;
2465 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2466 anAsciiList += anEntry;
2470 // make a Python command
2471 anAsciiList.Trunc(anAsciiList.Length() - 1);
2473 GEOM::TPythonDump pd (anObj->GetLastFunction());
2474 pd << "[" << anAsciiList.ToCString()
2475 << "] = geompy.GetSharedShapesMulti(";
2480 it = theShapes.begin();
2482 while (it != theShapes.end()) {
2483 pd << ", " << (*it++);
2488 pd << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theMultiShare << ")";
2494 //=============================================================================
2498 //=============================================================================
2499 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump,
2500 const GEOMAlgo_State theState)
2503 case GEOMAlgo_ST_IN:
2504 theDump << "GEOM.ST_IN";
2506 case GEOMAlgo_ST_OUT:
2507 theDump << "GEOM.ST_OUT";
2509 case GEOMAlgo_ST_ON:
2510 theDump << "GEOM.ST_ON";
2512 case GEOMAlgo_ST_ONIN:
2513 theDump << "GEOM.ST_ONIN";
2515 case GEOMAlgo_ST_ONOUT:
2516 theDump << "GEOM.ST_ONOUT";
2519 theDump << "GEOM.ST_UNKNOWN";
2525 //=======================================================================
2526 //function : checkTypeShapesOn
2528 * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
2529 * \param theShapeType - the shape type to check
2530 * \retval bool - result of the check
2532 //=======================================================================
2533 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
2535 if (theShapeType != TopAbs_VERTEX &&
2536 theShapeType != TopAbs_EDGE &&
2537 theShapeType != TopAbs_FACE &&
2538 theShapeType != TopAbs_SOLID) {
2539 SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
2545 //=======================================================================
2546 //function : makePlane
2548 * \brief Creates Geom_Plane
2549 * \param theAx1 - shape object defining plane parameters
2550 * \retval Handle(Geom_Surface) - resulting surface
2552 //=======================================================================
2553 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
2555 if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
2556 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2557 TopoDS_Vertex V1, V2;
2558 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2559 if (V1.IsNull() || V2.IsNull()) {
2560 SetErrorCode("Bad edge given for the plane normal vector");
2563 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2564 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2565 if (aVec.Magnitude() < Precision::Confusion()) {
2566 SetErrorCode("Vector with null magnitude given");
2569 return new Geom_Plane(aLoc, aVec);
2572 //=======================================================================
2573 //function : makeCylinder
2575 * \brief Creates Geom_CylindricalSurface
2576 * \param theAx1 - edge defining cylinder axis
2577 * \param theRadius - cylinder radius
2578 * \retval Handle(Geom_Surface) - resulting surface
2580 //=======================================================================
2581 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
2582 const Standard_Real theRadius)
2584 //Axis of the cylinder
2585 if (anAxis.ShapeType() != TopAbs_EDGE) {
2586 SetErrorCode("Not an edge given for the axis");
2589 TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
2590 TopoDS_Vertex V1, V2;
2591 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2592 if (V1.IsNull() || V2.IsNull()) {
2593 SetErrorCode("Bad edge given for the axis");
2596 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2597 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2598 if (aVec.Magnitude() < Precision::Confusion()) {
2599 SetErrorCode("Vector with null magnitude given");
2603 gp_Ax3 anAx3 (aLoc, aVec);
2604 return new Geom_CylindricalSurface(anAx3, theRadius);
2607 //=======================================================================
2608 //function : getShapesOnBoxIDs
2610 * \brief Find IDs of sub-shapes complying with given status about surface
2611 * \param theBox - the box to check state of sub-shapes against
2612 * \param theShape - the shape to explore
2613 * \param theShapeType - type of sub-shape of theShape
2614 * \param theState - required state
2615 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2617 //=======================================================================
2618 Handle(TColStd_HSequenceOfInteger)
2619 GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2620 const Handle(GEOM_Object)& theShape,
2621 const Standard_Integer theShapeType,
2622 GEOMAlgo_State theState)
2624 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2626 TopoDS_Shape aBox = theBox->GetValue();
2627 TopoDS_Shape aShape = theShape->GetValue();
2629 // Check presence of triangulation, build if need
2630 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2631 SetErrorCode("Cannot build triangulation on the shape");
2636 GEOMAlgo_FinderShapeOn2 aFinder;
2637 Standard_Real aTol = 0.0001; // default value
2639 Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
2640 aClsfBox->SetBox(aBox);
2642 aFinder.SetShape(aShape);
2643 aFinder.SetTolerance(aTol);
2644 aFinder.SetClsf(aClsfBox);
2645 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2646 aFinder.SetState(theState);
2649 // Interpret results
2650 Standard_Integer iErr = aFinder.ErrorStatus();
2651 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2653 MESSAGE(" iErr : " << iErr);
2654 TCollection_AsciiString aMsg (" iErr : ");
2655 aMsg += TCollection_AsciiString(iErr);
2659 Standard_Integer iWrn = aFinder.WarningStatus();
2660 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2662 MESSAGE(" *** iWrn : " << iWrn);
2665 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2667 if (listSS.Extent() < 1) {
2668 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2669 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2673 // Fill sequence of object IDs
2674 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2676 TopTools_IndexedMapOfShape anIndices;
2677 TopExp::MapShapes(aShape, anIndices);
2679 TopTools_ListIteratorOfListOfShape itSub (listSS);
2680 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2681 int id = anIndices.FindIndex(itSub.Value());
2682 aSeqOfIDs->Append(id);
2688 //=======================================================================
2689 //function : GetShapesOnBoxIDs
2691 * \brief Find sub-shapes complying with given status about surface
2692 * \param theBox - the box to check state of sub-shapes against
2693 * \param theShape - the shape to explore
2694 * \param theShapeType - type of sub-shape of theShape
2695 * \param theState - required state
2696 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2698 //=======================================================================
2699 Handle(TColStd_HSequenceOfInteger)
2700 GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2701 const Handle(GEOM_Object)& theShape,
2702 const Standard_Integer theShapeType,
2703 GEOMAlgo_State theState)
2705 // Find sub-shapes ids
2706 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2707 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2708 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2711 // The GetShapesOnBox() doesn't change object so no new function is required.
2712 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
2714 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2715 #ifdef DUMP_SUBSHAPE_IDS
2716 // Make a Python command
2717 GEOM::TPythonDump(aFunction, /*append=*/true)
2718 << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
2721 << TopAbs_ShapeEnum(theShapeType) << ", "
2723 #endif // DUMP_SUBSHAPE_IDS
2729 //=======================================================================
2730 //function : GetShapesOnBox
2732 * \brief Find sub-shapes complying with given status about surface
2733 * \param theBox - the box to check state of sub-shapes against
2734 * \param theShape - the shape to explore
2735 * \param theShapeType - type of sub-shape of theShape
2736 * \param theState - required state
2737 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2739 //=======================================================================
2740 Handle(TColStd_HSequenceOfTransient)
2741 GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
2742 const Handle(GEOM_Object)& theShape,
2743 const Standard_Integer theShapeType,
2744 GEOMAlgo_State theState)
2746 // Find sub-shapes ids
2747 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2748 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2749 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2752 // Find objects by indices
2753 TCollection_AsciiString anAsciiList;
2754 Handle(TColStd_HSequenceOfTransient) aSeq;
2755 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2756 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2759 // Make a Python command
2761 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2762 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2764 GEOM::TPythonDump(aFunction)
2765 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
2768 << TopAbs_ShapeEnum(theShapeType) << ", "
2775 //=======================================================================
2776 //function : getShapesOnShapeIDs
2778 * \brief Find IDs of sub-shapes complying with given status about surface
2779 * \param theCheckShape - the shape to check state of sub-shapes against
2780 * \param theShape - the shape to explore
2781 * \param theShapeType - type of sub-shape of theShape
2782 * \param theState - required state
2783 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2785 //=======================================================================
2786 Handle(TColStd_HSequenceOfInteger)
2787 GEOMImpl_IShapesOperations::getShapesOnShapeIDs
2788 (const Handle(GEOM_Object)& theCheckShape,
2789 const Handle(GEOM_Object)& theShape,
2790 const Standard_Integer theShapeType,
2791 GEOMAlgo_State theState)
2793 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2795 TopoDS_Shape aCheckShape = theCheckShape->GetValue();
2796 TopoDS_Shape aShape = theShape->GetValue();
2797 TopTools_ListOfShape res;
2799 // Check presence of triangulation, build if need
2800 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2801 SetErrorCode("Cannot build triangulation on the shape");
2805 // Compute classification tolerance.
2806 TopTools_IndexedMapOfShape aMapVtx;
2807 Standard_Real aTol = Precision::Confusion();
2809 TopExp::MapShapes(aShape, TopAbs_VERTEX, aMapVtx);
2812 Standard_Integer aNbVtx = aMapVtx.Extent();
2814 for (i = 1; i <= aNbVtx; ++i) {
2815 const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(i));
2816 const Standard_Real aVtxTol = BRep_Tool::Tolerance(aVtx);
2818 if (aTol < aVtxTol) {
2823 // Bound the tolerance value.
2824 if (aTol > 0.0001) {
2829 GEOMAlgo_FinderShapeOn2 aFinder;
2831 Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
2832 aClsfSolid->SetShape(aCheckShape);
2834 aFinder.SetShape(aShape);
2835 aFinder.SetTolerance(aTol);
2836 aFinder.SetClsf(aClsfSolid);
2837 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2838 aFinder.SetState(theState);
2841 // Interpret results
2842 Standard_Integer iErr = aFinder.ErrorStatus();
2843 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2846 SetErrorCode("theCheckShape must be a solid");
2849 MESSAGE(" iErr : " << iErr);
2850 TCollection_AsciiString aMsg (" iErr : ");
2851 aMsg += TCollection_AsciiString(iErr);
2856 Standard_Integer iWrn = aFinder.WarningStatus();
2857 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2859 MESSAGE(" *** iWrn : " << iWrn);
2862 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2864 if (listSS.Extent() < 1) {
2865 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2866 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2869 // Fill sequence of object IDs
2870 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2872 TopTools_IndexedMapOfShape anIndices;
2873 TopExp::MapShapes(aShape, anIndices);
2875 TopTools_ListIteratorOfListOfShape itSub (listSS);
2876 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2877 int id = anIndices.FindIndex(itSub.Value());
2878 aSeqOfIDs->Append(id);
2884 //=======================================================================
2885 //function : GetShapesOnShapeIDs
2887 * \brief Find sub-shapes complying with given status about surface
2888 * \param theCheckShape - the shape to check state of sub-shapes against
2889 * \param theShape - the shape to explore
2890 * \param theShapeType - type of sub-shape of theShape
2891 * \param theState - required state
2892 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2894 //=======================================================================
2895 Handle(TColStd_HSequenceOfInteger)
2896 GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
2897 (const Handle(GEOM_Object)& theCheckShape,
2898 const Handle(GEOM_Object)& theShape,
2899 const Standard_Integer theShapeType,
2900 GEOMAlgo_State theState)
2902 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2903 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2905 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2908 // The GetShapesOnShape() doesn't change object so no new function is required.
2909 Handle(GEOM_Function) aFunction =
2910 GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
2912 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2913 #ifdef DUMP_SUBSHAPE_IDS
2914 // Make a Python command
2915 GEOM::TPythonDump(aFunction, /*append=*/true)
2916 << "listShapesOnShapeIDs = geompy.GetShapesOnShapeIDs("
2917 << theCheckShape << ", "
2919 << TopAbs_ShapeEnum(theShapeType) << ", "
2921 #endif // DUMP_SUBSHAPE_IDS
2927 //=======================================================================
2928 //function : GetShapesOnShape
2930 * \brief Find sub-shapes complying with given status about surface
2931 * \param theCheckShape - the shape to check state of sub-shapes against
2932 * \param theShape - the shape to explore
2933 * \param theShapeType - type of sub-shape of theShape
2934 * \param theState - required state
2935 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2937 //=======================================================================
2938 Handle(TColStd_HSequenceOfTransient)
2939 GEOMImpl_IShapesOperations::GetShapesOnShape
2940 (const Handle(GEOM_Object)& theCheckShape,
2941 const Handle(GEOM_Object)& theShape,
2942 const Standard_Integer theShapeType,
2943 GEOMAlgo_State theState)
2945 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2946 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2947 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2950 // Find objects by indices
2951 TCollection_AsciiString anAsciiList;
2952 Handle(TColStd_HSequenceOfTransient) aSeq;
2953 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2955 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2958 // Make a Python command
2960 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2961 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2963 GEOM::TPythonDump(aFunction)
2964 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
2965 << theCheckShape << ", "
2967 << TopAbs_ShapeEnum(theShapeType) << ", "
2974 //=======================================================================
2975 //function : GetShapesOnShapeAsCompound
2976 //=======================================================================
2977 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
2978 (const Handle(GEOM_Object)& theCheckShape,
2979 const Handle(GEOM_Object)& theShape,
2980 const Standard_Integer theShapeType,
2981 GEOMAlgo_State theState)
2983 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2984 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2986 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2989 // Find objects by indices
2990 TCollection_AsciiString anAsciiList;
2991 Handle(TColStd_HSequenceOfTransient) aSeq;
2992 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2994 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2997 TopoDS_Compound aCompound;
2999 B.MakeCompound(aCompound);
3001 for(; i<=aSeq->Length(); i++) {
3002 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
3003 TopoDS_Shape aShape_i = anObj->GetValue();
3004 B.Add(aCompound,aShape_i);
3007 //Add a new result object
3008 Handle(GEOM_Object) aRes = GetEngine()->AddObject(GEOM_SHAPES_ON_SHAPE);
3009 Handle(GEOM_Function) aFunction =
3010 aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
3011 aFunction->SetValue(aCompound);
3014 aSeq->Append( theCheckShape->GetLastFunction() );
3015 aSeq->Append( theShape->GetLastFunction() );
3017 GEOMImpl_IShapes aCI( aFunction );
3018 aCI.SetShapes( aSeq );
3019 aCI.SetSubShapeType( theShapeType );
3020 aCI.SetTolerance( theState );
3022 GEOM::TPythonDump(aFunction)
3023 << aRes << " = geompy.GetShapesOnShapeAsCompound("
3024 << theCheckShape << ", "
3026 << TopAbs_ShapeEnum(theShapeType) << ", "
3034 //=============================================================================
3036 * GetSubShapeEdgeSorted
3038 //=============================================================================
3039 Handle(TColStd_HSequenceOfTransient)
3040 GEOMImpl_IShapesOperations::GetSubShapeEdgeSorted
3041 (const Handle(GEOM_Object) &theShape,
3042 const Handle(GEOM_Object) &theStartPoint)
3044 // Get the sorted edges indices.
3045 Handle(TColStd_HSequenceOfInteger) aSortedIDs =
3046 getSubShapeEdgeSortedIDs(theShape, theStartPoint);
3048 // Get object by indices.
3049 TCollection_AsciiString anAsciiList;
3050 Handle(TColStd_HSequenceOfTransient) aSeq =
3051 getObjectsShapesOn(theShape, aSortedIDs, anAsciiList);
3053 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3054 SetErrorCode("Empty sequence of edges");
3058 // Make a Python command
3059 Handle(GEOM_Object) anObj =
3060 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3061 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3063 GEOM::TPythonDump(aFunction)
3064 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapeEdgeSorted("
3065 << theShape << ", " << theStartPoint << ")";
3072 //=============================================================================
3074 * GetSubShapesWithTolerance
3076 //=============================================================================
3077 Handle(TColStd_HSequenceOfTransient)
3078 GEOMImpl_IShapesOperations::GetSubShapesWithTolerance
3079 (const Handle(GEOM_Object) &theShape,
3080 const Standard_Integer theShapeType,
3081 const GEOMUtils::ComparisonCondition theCondition,
3082 const Standard_Real theTolerance)
3084 if (theShape.IsNull()) {
3085 SetErrorCode("NULL GEOM object");
3089 TopoDS_Shape aShape = theShape->GetValue();
3091 if (aShape.IsNull()) {
3092 SetErrorCode("NULL Shape");
3096 if (theShapeType != TopAbs_FACE && theShapeType != TopAbs_EDGE &&
3097 theShapeType != TopAbs_VERTEX && aShape.ShapeType() >= theShapeType) {
3098 SetErrorCode("Invalid shape type");
3102 TopTools_IndexedMapOfShape anIndices;
3103 TopTools_MapOfShape aMapFence;
3104 TopExp_Explorer anExp(aShape,
3105 (TopAbs_ShapeEnum) theShapeType);
3106 Handle(TColStd_HSequenceOfInteger) anIDs = new TColStd_HSequenceOfInteger;
3108 TopExp::MapShapes(aShape, anIndices);
3110 for (; anExp.More(); anExp.Next()) {
3111 const TopoDS_Shape &aSubShape = anExp.Current();
3113 if (aMapFence.Add(aSubShape)) {
3114 // Compute tolerance
3115 Standard_Real aTolerance = -1.;
3117 switch (aSubShape.ShapeType()) {
3119 aTolerance = BRep_Tool::Tolerance(TopoDS::Face(aSubShape));
3122 aTolerance = BRep_Tool::Tolerance(TopoDS::Edge(aSubShape));
3125 aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aSubShape));
3131 if (aTolerance < 0.) {
3135 // Compare the tolerance with reference value.
3136 if (GEOMUtils::IsFitCondition (theCondition, aTolerance, theTolerance)) {
3137 anIDs->Append(anIndices.FindIndex(aSubShape));
3142 if (anIDs->IsEmpty()) {
3143 SetErrorCode("Empty sequence of sub-shapes");
3147 // Get objects by indices.
3148 TCollection_AsciiString anAsciiList;
3149 Handle(TColStd_HSequenceOfTransient) aSeq =
3150 getObjectsShapesOn(theShape, anIDs, anAsciiList);
3152 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3153 SetErrorCode("Empty sequence of edges");
3157 // Make a Python command
3158 Handle(GEOM_Object) anObj =
3159 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3160 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3162 GEOM::TPythonDump(aFunction)
3163 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapesWithTolerance("
3164 << theShape << ", " << theShapeType << ", " << theCondition << ", "
3165 << theTolerance << ")";
3172 //=============================================================================
3176 //=============================================================================
3177 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeExtraction
3178 (const Handle(GEOM_Object) &theShape,
3179 const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs,
3180 std::list<ExtractionStat> &theStats)
3184 if (theShape.IsNull()) {
3188 //Add a new Result object
3189 Handle(GEOM_Object) aResult =
3190 GetEngine()->AddObject(GEOM_EXTRACTION);
3192 //Add a new Extraction function
3193 Handle(GEOM_Function) aFunction =
3194 aResult->AddFunction(GEOMImpl_ShapeDriver::GetID(), EXTRACTION);
3196 //Check if the function is set correctly
3197 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
3201 Handle(GEOM_Function) aShape = theShape->GetLastFunction();
3203 if (aShape.IsNull()) {
3207 GEOMImpl_IExtract aCI (aFunction);
3209 aCI.SetShape(aShape);
3210 aCI.SetSubShapeIDs(theSubShapeIDs);
3212 //Compute the Edge value
3215 if (!GetSolver()->ComputeFunction(aFunction)) {
3216 SetErrorCode("Shape driver failed");
3221 catch (Standard_Failure& aFail) {
3222 SetErrorCode(aFail.GetMessageString());
3227 // Fill in statistics.
3230 Handle(TColStd_HArray1OfInteger) aStatIDsArray[3] =
3231 { aCI.GetRemovedIDs(), aCI.GetModifiedIDs(), aCI.GetAddedIDs() };
3235 for (j = 0; j < 3; ++j) {
3236 if (!aStatIDsArray[j].IsNull()) {
3237 const int anUpperID = aStatIDsArray[j]->Upper();
3238 ExtractionStat aStat;
3240 for (i = aStatIDsArray[j]->Lower(); i <= anUpperID; ++i) {
3241 aStat.indices.push_back(aStatIDsArray[j]->Value(i));
3244 aStat.type = (ExtractionStatType) j;
3245 theStats.push_back(aStat);
3249 //Make a Python command
3250 GEOM::TPythonDump pd(aFunction);
3252 pd << aResult << " = geompy.MakeExtraction(" << theShape << ", [";
3254 if (!theSubShapeIDs.IsNull()) {
3255 const int aNbIDs = theSubShapeIDs->Upper();
3257 for (i = theSubShapeIDs->Lower(); i < aNbIDs; ++i) {
3258 pd << theSubShapeIDs->Value(i) << ", ";
3261 // Dump the last value without a comma.
3262 pd << theSubShapeIDs->Value(i);
3272 //=======================================================================
3273 //function : getShapesOnSurfaceIDs
3275 * \brief Find IDs of sub-shapes complying with given status about surface
3276 * \param theSurface - the surface to check state of sub-shapes against
3277 * \param theShape - the shape to explore
3278 * \param theShapeType - type of sub-shape of theShape
3279 * \param theState - required state
3280 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3282 //=======================================================================
3283 Handle(TColStd_HSequenceOfInteger)
3284 GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
3285 const TopoDS_Shape& theShape,
3286 TopAbs_ShapeEnum theShapeType,
3287 GEOMAlgo_State theState)
3289 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3291 // Check presence of triangulation, build if need
3292 if (theShapeType != TopAbs_VERTEX &&
3293 !GEOMUtils::CheckTriangulation(theShape)) {
3294 SetErrorCode("Cannot build triangulation on the shape");
3298 // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
3299 // Compute tolerance
3300 Standard_Real T, VertMax = -RealLast();
3303 for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
3304 TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
3305 T = BRep_Tool::Tolerance(Vertex);
3310 catch (Standard_Failure& aFail) {
3311 SetErrorCode(aFail.GetMessageString());
3314 // END: Mantis issue 0020961
3317 GEOMAlgo_FinderShapeOn2 aFinder;
3318 Handle(GEOMAlgo_ClsfSurf) aClsfSurf = new GEOMAlgo_ClsfSurf;
3319 Standard_Real aTol = VertMax; // Mantis issue 0020961
3321 aClsfSurf->SetSurface(theSurface);
3322 aFinder.SetShape(theShape);
3323 aFinder.SetTolerance(aTol);
3324 aFinder.SetClsf(aClsfSurf);
3325 aFinder.SetShapeType(theShapeType);
3326 aFinder.SetState(theState);
3328 // Sets the minimal number of inner points for the faces that do not have own
3329 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
3331 aFinder.SetNbPntsMin(3);
3332 // Sets the maximal number of inner points for edges or faces.
3333 // It is useful for the cases when this number is very big (e.g =2000) to improve
3334 // the performance. If this value =0, all inner points will be taken into account.
3336 aFinder.SetNbPntsMax(100);
3340 // Interpret results
3341 Standard_Integer iErr = aFinder.ErrorStatus();
3342 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
3344 MESSAGE(" iErr : " << iErr);
3345 TCollection_AsciiString aMsg (" iErr : ");
3346 aMsg += TCollection_AsciiString(iErr);
3350 Standard_Integer iWrn = aFinder.WarningStatus();
3351 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
3353 MESSAGE(" *** iWrn : " << iWrn);
3356 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
3358 if (listSS.Extent() < 1) {
3359 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
3360 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
3364 // Fill sequence of object IDs
3365 aSeqOfIDs = new TColStd_HSequenceOfInteger;
3367 TopTools_IndexedMapOfShape anIndices;
3368 TopExp::MapShapes(theShape, anIndices);
3370 TopTools_ListIteratorOfListOfShape itSub (listSS);
3371 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3372 int id = anIndices.FindIndex(itSub.Value());
3373 aSeqOfIDs->Append(id);
3379 //=======================================================================
3380 //function : getObjectsShapesOn
3382 * \brief Find shape objects and their entries by their ids
3383 * \param theShapeIDs - incoming shape ids
3384 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3385 * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
3387 //=======================================================================
3388 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
3389 getObjectsShapesOn(const Handle(GEOM_Object)& theShape,
3390 const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
3391 TCollection_AsciiString & theShapeEntries)
3393 Handle(TColStd_HSequenceOfTransient) aSeq;
3395 if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
3397 aSeq = new TColStd_HSequenceOfTransient;
3398 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3399 TCollection_AsciiString anEntry;
3400 for ( int i = 1; i <= theShapeIDs->Length(); ++i )
3402 anArray->SetValue(1, theShapeIDs->Value( i ));
3403 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3404 aSeq->Append( anObj );
3406 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3407 if ( i != 1 ) theShapeEntries += ",";
3408 theShapeEntries += anEntry;
3414 //=============================================================================
3416 * getSubShapeEdgeSortedIDs
3418 //=============================================================================
3419 Handle(TColStd_HSequenceOfInteger)
3420 GEOMImpl_IShapesOperations::getSubShapeEdgeSortedIDs
3421 (const Handle(GEOM_Object) &theShape,
3422 const Handle(GEOM_Object) &theStartPoint)
3424 Handle(TColStd_HSequenceOfInteger) aResult;
3426 if (theShape.IsNull() || theStartPoint.IsNull()) {
3427 SetErrorCode("NULL GEOM object");
3431 const TopoDS_Shape aShape = theShape->GetValue();
3432 const TopoDS_Shape aStartPoint = theStartPoint->GetValue();
3434 if (aShape.IsNull() || aStartPoint.IsNull()) {
3435 SetErrorCode("NULL Shape");
3439 if (aStartPoint.ShapeType() != TopAbs_VERTEX) {
3440 SetErrorCode("Starting point is not a vertex");
3444 TopExp_Explorer anExp(aShape, TopAbs_EDGE);
3445 TopTools_MapOfShape aMapFence;
3446 TopTools_ListOfShape anEdges;
3448 for (; anExp.More(); anExp.Next()) {
3449 const TopoDS_Shape &anEdge = anExp.Current();
3451 if (aMapFence.Add(anEdge)) {
3452 anEdges.Append(anEdge);
3456 if (anEdges.IsEmpty()) {
3457 SetErrorCode("Shape doesn't contain edges");
3461 // Step 1: Sort edges
3462 GEOMUtils::SortShapes(anEdges, Standard_False);
3464 TopTools_ListIteratorOfListOfShape anIter(anEdges);
3465 TopoDS_Vertex aV[2];
3466 TopTools_DataMapOfShapeListOfShape aMapVE;
3468 // Step 2: Fill the map vertex - list of edges.
3469 for (; anIter.More(); anIter.Next()) {
3470 TopoDS_Edge anEdge = TopoDS::Edge(anIter.Value());
3472 TopExp::Vertices(anEdge, aV[0], aV[1]);
3474 const Standard_Integer aNbV = aV[0].IsSame(aV[1]) ? 1 : 2;
3477 for (i = 0; i < aNbV; ++i) {
3478 if (aV[i].IsNull() == Standard_False) {
3479 if (!aMapVE.IsBound(aV[i])) {
3480 // There is no this vertex in the map.
3481 aMapVE.Bind(aV[i], TopTools_ListOfShape());
3484 // Add the edge to the list bound with the vertex aV[i].
3485 TopTools_ListOfShape &aLEdges = aMapVE.ChangeFind(aV[i]);
3487 aLEdges.Append(anEdge);
3492 // Step 3: Find starting point in aMapVE.
3493 TopoDS_Vertex aStartVtx = TopoDS::Vertex(aStartPoint);
3495 if (!aMapVE.IsBound(aStartVtx)) {
3496 aStartVtx = getSameVertex(aShape, aStartVtx);
3498 if (aStartVtx.IsNull()) {
3499 SetErrorCode("Invalid Starting point");
3504 TopTools_IndexedMapOfShape anIndices;
3505 TopTools_MapOfShape aMapVFence;
3506 TopoDS_Shape aCurVtx = aStartVtx;
3507 TopoDS_Edge aCurEdge =
3508 TopoDS::Edge(aMapVE.Find(aCurVtx).First());
3510 aResult = new TColStd_HSequenceOfInteger;
3511 TopExp::MapShapes(aShape, anIndices);
3513 // Step 4: Fill the list of sorted edges.
3514 while (aMapVFence.Add(aCurVtx)) {
3515 // Append the ID of the current edge to the list of sorted.
3516 aResult->Append(anIndices.FindIndex(aCurEdge));
3517 TopExp::Vertices(aCurEdge, aV[0], aV[1]);
3519 // Get the next vertex.
3520 if (aCurVtx.IsSame(aV[0])) {
3521 if (aCurVtx.IsSame(aV[1])) {
3522 // There is no next vertex.
3531 if (aCurVtx.IsNull()) {
3532 // There is no next vertex.
3536 // Get the next edge.
3537 const TopTools_ListOfShape &aLEdges = aMapVE.Find(aCurVtx);
3538 TopTools_ListIteratorOfListOfShape anEIter(aLEdges);
3540 for (; anEIter.More(); anEIter.Next()) {
3541 const TopoDS_Shape &aLocalEdge = anEIter.Value();
3543 if (aLocalEdge.IsNull() == Standard_False) {
3544 if (!aCurEdge.IsSame(aLocalEdge)) {
3545 aCurEdge = TopoDS::Edge(aLocalEdge);
3551 if (!anEIter.More()) {
3552 // There is no next edge.
3560 //=======================================================================
3561 //function : getShapesOnSurface
3563 * \brief Find sub-shapes complying with given status about surface
3564 * \param theSurface - the surface to check state of sub-shapes against
3565 * \param theShape - the shape to explore
3566 * \param theShapeType - type of sub-shape of theShape
3567 * \param theState - required state
3568 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3569 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3571 //=======================================================================
3572 Handle(TColStd_HSequenceOfTransient)
3573 GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
3574 const Handle(GEOM_Object)& theShape,
3575 TopAbs_ShapeEnum theShapeType,
3576 GEOMAlgo_State theState,
3577 TCollection_AsciiString & theShapeEntries)
3579 // Find sub-shapes ids
3580 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3581 getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
3582 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3585 return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
3588 //=============================================================================
3592 //=============================================================================
3593 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
3594 (const Handle(GEOM_Object)& theShape,
3595 const Standard_Integer theShapeType,
3596 const Handle(GEOM_Object)& theAx1,
3597 const GEOMAlgo_State theState)
3601 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3603 TopoDS_Shape aShape = theShape->GetValue();
3604 TopoDS_Shape anAx1 = theAx1->GetValue();
3606 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3608 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3609 if ( !checkTypeShapesOn( theShapeType ))
3613 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3614 if ( aPlane.IsNull() )
3618 TCollection_AsciiString anAsciiList;
3619 Handle(TColStd_HSequenceOfTransient) aSeq;
3620 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3621 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3624 // Make a Python command
3626 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3627 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3629 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3630 << "] = geompy.GetShapesOnPlane(" << theShape << ", "
3631 << aShapeType << ", " << theAx1 << ", " << theState << ")";
3637 //=============================================================================
3639 * GetShapesOnPlaneWithLocation
3641 //=============================================================================
3642 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
3643 (const Handle(GEOM_Object)& theShape,
3644 const Standard_Integer theShapeType,
3645 const Handle(GEOM_Object)& theAx1,
3646 const Handle(GEOM_Object)& thePnt,
3647 const GEOMAlgo_State theState)
3651 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3653 TopoDS_Shape aShape = theShape->GetValue();
3654 TopoDS_Shape anAx1 = theAx1->GetValue();
3655 TopoDS_Shape anPnt = thePnt->GetValue();
3657 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3659 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3660 if ( !checkTypeShapesOn( theShapeType ))
3664 if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
3665 TopoDS_Vertex V1, V2, V3;
3666 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3667 TopExp::Vertices(anEdge, V1, V2, Standard_True);
3669 if (V1.IsNull() || V2.IsNull()) {
3670 SetErrorCode("Bad edge given for the plane normal vector");
3673 V3 = TopoDS::Vertex(anPnt);
3676 SetErrorCode("Bad vertex given for the plane location");
3679 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3680 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3682 if (aVec.Magnitude() < Precision::Confusion()) {
3683 SetErrorCode("Vector with null magnitude given");
3686 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3688 if ( aPlane.IsNull() )
3692 TCollection_AsciiString anAsciiList;
3693 Handle(TColStd_HSequenceOfTransient) aSeq;
3694 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3695 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3698 // Make a Python command
3700 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3701 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3703 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3704 << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
3705 << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
3711 //=============================================================================
3713 * GetShapesOnCylinder
3715 //=============================================================================
3716 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
3717 (const Handle(GEOM_Object)& theShape,
3718 const Standard_Integer theShapeType,
3719 const Handle(GEOM_Object)& theAxis,
3720 const Standard_Real theRadius,
3721 const GEOMAlgo_State theState)
3725 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3727 TopoDS_Shape aShape = theShape->GetValue();
3728 TopoDS_Shape anAxis = theAxis->GetValue();
3730 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3732 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3733 if ( !checkTypeShapesOn( aShapeType ))
3736 // Create a cylinder surface
3737 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3738 if ( aCylinder.IsNull() )
3742 TCollection_AsciiString anAsciiList;
3743 Handle(TColStd_HSequenceOfTransient) aSeq;
3744 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3745 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3748 // Make a Python command
3750 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3751 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3753 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3754 << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
3755 << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
3761 //=============================================================================
3763 * GetShapesOnCylinderWithLocation
3765 //=============================================================================
3766 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
3767 (const Handle(GEOM_Object)& theShape,
3768 const Standard_Integer theShapeType,
3769 const Handle(GEOM_Object)& theAxis,
3770 const Handle(GEOM_Object)& thePnt,
3771 const Standard_Real theRadius,
3772 const GEOMAlgo_State theState)
3776 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3778 TopoDS_Shape aShape = theShape->GetValue();
3779 TopoDS_Shape anAxis = theAxis->GetValue();
3780 TopoDS_Shape aPnt = thePnt->GetValue();
3782 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3784 if (aPnt.ShapeType() != TopAbs_VERTEX )
3786 SetErrorCode("Bottom location point must be vertex");
3790 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3791 if ( !checkTypeShapesOn( aShapeType ))
3794 // Create a cylinder surface
3795 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3796 if ( aCylinder.IsNull() )
3799 // translate the surface
3800 Handle(Geom_CylindricalSurface) aCylSurface =
3801 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3802 if ( aCylSurface.IsNull() )
3804 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3807 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3808 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3809 aCylinder->Translate( fromLoc, toLoc );
3812 TCollection_AsciiString anAsciiList;
3813 Handle(TColStd_HSequenceOfTransient) aSeq;
3814 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3815 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3818 // Make a Python command
3820 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3821 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3823 GEOM::TPythonDump(aFunction)
3824 << "[" << anAsciiList.ToCString()
3825 << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
3826 << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
3832 //=============================================================================
3836 //=============================================================================
3837 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
3838 (const Handle(GEOM_Object)& theShape,
3839 const Standard_Integer theShapeType,
3840 const Handle(GEOM_Object)& theCenter,
3841 const Standard_Real theRadius,
3842 const GEOMAlgo_State theState)
3846 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3848 TopoDS_Shape aShape = theShape->GetValue();
3849 TopoDS_Shape aCenter = theCenter->GetValue();
3851 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3853 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3854 if ( !checkTypeShapesOn( aShapeType ))
3857 // Center of the sphere
3858 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3859 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3861 gp_Ax3 anAx3 (aLoc, gp::DZ());
3862 Handle(Geom_SphericalSurface) aSphere =
3863 new Geom_SphericalSurface(anAx3, theRadius);
3866 TCollection_AsciiString anAsciiList;
3867 Handle(TColStd_HSequenceOfTransient) aSeq;
3868 aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
3869 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3872 // Make a Python command
3874 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3875 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3877 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3878 << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
3879 << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
3885 //=============================================================================
3887 * GetShapesOnPlaneIDs
3889 //=============================================================================
3890 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
3891 (const Handle(GEOM_Object)& theShape,
3892 const Standard_Integer theShapeType,
3893 const Handle(GEOM_Object)& theAx1,
3894 const GEOMAlgo_State theState)
3898 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3900 TopoDS_Shape aShape = theShape->GetValue();
3901 TopoDS_Shape anAx1 = theAx1->GetValue();
3903 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3905 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3906 if ( !checkTypeShapesOn( aShapeType ))
3910 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3911 if ( aPlane.IsNull() )
3915 Handle(TColStd_HSequenceOfInteger) aSeq;
3916 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3918 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3919 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3921 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
3922 #ifdef DUMP_SUBSHAPE_IDS
3923 // Make a Python command
3924 GEOM::TPythonDump(aFunction, /*append=*/true)
3925 << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
3926 << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
3927 #endif // DUMP_SUBSHAPE_IDS
3933 //=============================================================================
3935 * GetShapesOnPlaneWithLocationIDs
3937 //=============================================================================
3938 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
3939 (const Handle(GEOM_Object)& theShape,
3940 const Standard_Integer theShapeType,
3941 const Handle(GEOM_Object)& theAx1,
3942 const Handle(GEOM_Object)& thePnt,
3943 const GEOMAlgo_State theState)
3947 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3949 TopoDS_Shape aShape = theShape->GetValue();
3950 TopoDS_Shape anAx1 = theAx1->GetValue();
3951 TopoDS_Shape anPnt = thePnt->GetValue();
3953 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3955 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3956 if ( !checkTypeShapesOn( aShapeType ))
3960 if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
3961 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3962 TopoDS_Vertex V1, V2, V3;
3963 TopExp::Vertices(anEdge, V1, V2, Standard_True);
3964 if (V1.IsNull() || V2.IsNull()) {
3965 SetErrorCode("Bad edge given for the plane normal vector");
3968 V3 = TopoDS::Vertex(anPnt);
3970 SetErrorCode("Bad vertex given for the plane location");
3973 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3974 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3975 if (aVec.Magnitude() < Precision::Confusion()) {
3976 SetErrorCode("Vector with null magnitude given");
3980 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3981 if ( aPlane.IsNull() )
3985 Handle(TColStd_HSequenceOfInteger) aSeq;
3986 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3988 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3989 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3991 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
3992 #ifdef DUMP_SUBSHAPE_IDS
3993 // Make a Python command
3994 GEOM::TPythonDump(aFunction, /*append=*/true)
3995 << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
3996 << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")";
3997 #endif // DUMP_SUBSHAPE_IDS
4003 //=============================================================================
4005 * GetShapesOnCylinderIDs
4007 //=============================================================================
4008 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
4009 (const Handle(GEOM_Object)& theShape,
4010 const Standard_Integer theShapeType,
4011 const Handle(GEOM_Object)& theAxis,
4012 const Standard_Real theRadius,
4013 const GEOMAlgo_State theState)
4017 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
4019 TopoDS_Shape aShape = theShape->GetValue();
4020 TopoDS_Shape anAxis = theAxis->GetValue();
4022 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
4024 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4025 if ( !checkTypeShapesOn( aShapeType ))
4028 // Create a cylinder surface
4029 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4030 if ( aCylinder.IsNull() )
4034 Handle(TColStd_HSequenceOfInteger) aSeq;
4035 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4037 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4038 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
4040 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4041 #ifdef DUMP_SUBSHAPE_IDS
4042 // Make a Python command
4043 GEOM::TPythonDump(aFunction, /*append=*/true)
4044 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
4045 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4046 << theRadius << ", " << theState << ")";
4047 #endif // DUMP_SUBSHAPE_IDS
4053 //=============================================================================
4055 * GetShapesOnCylinderWithLocationIDs
4057 //=============================================================================
4058 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
4059 (const Handle(GEOM_Object)& theShape,
4060 const Standard_Integer theShapeType,
4061 const Handle(GEOM_Object)& theAxis,
4062 const Handle(GEOM_Object)& thePnt,
4063 const Standard_Real theRadius,
4064 const GEOMAlgo_State theState)
4068 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
4070 TopoDS_Shape aShape = theShape->GetValue();
4071 TopoDS_Shape anAxis = theAxis->GetValue();
4072 TopoDS_Shape aPnt = thePnt->GetValue();
4074 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
4076 if (aPnt.ShapeType() != TopAbs_VERTEX )
4078 SetErrorCode("Bottom location point must be vertex");
4082 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4083 if ( !checkTypeShapesOn( aShapeType ))
4086 // Create a cylinder surface
4087 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4088 if ( aCylinder.IsNull() )
4091 // translate the surface
4092 Handle(Geom_CylindricalSurface) aCylSurface =
4093 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
4094 if ( aCylSurface.IsNull() )
4096 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
4099 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
4100 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
4101 aCylinder->Translate( fromLoc, toLoc );
4104 Handle(TColStd_HSequenceOfInteger) aSeq;
4105 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4107 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4108 Handle(GEOM_Function) aFunction =
4109 GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
4111 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4112 #ifdef DUMP_SUBSHAPE_IDS
4113 // Make a Python command
4114 GEOM::TPythonDump(aFunction, /*append=*/true)
4115 << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
4116 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4117 << thePnt << ", " << theRadius << ", " << theState << ")";
4118 #endif // DUMP_SUBSHAPE_IDS
4124 //=============================================================================
4126 * GetShapesOnSphereIDs
4128 //=============================================================================
4129 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
4130 (const Handle(GEOM_Object)& theShape,
4131 const Standard_Integer theShapeType,
4132 const Handle(GEOM_Object)& theCenter,
4133 const Standard_Real theRadius,
4134 const GEOMAlgo_State theState)
4138 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
4140 TopoDS_Shape aShape = theShape->GetValue();
4141 TopoDS_Shape aCenter = theCenter->GetValue();
4143 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
4145 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4146 if ( !checkTypeShapesOn( aShapeType ))
4149 // Center of the sphere
4150 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
4151 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
4153 gp_Ax3 anAx3 (aLoc, gp::DZ());
4154 Handle(Geom_SphericalSurface) aSphere =
4155 new Geom_SphericalSurface(anAx3, theRadius);
4158 Handle(TColStd_HSequenceOfInteger) aSeq;
4159 aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
4161 // The GetShapesOnSphere() doesn't change object so no new function is required.
4162 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
4164 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4165 #ifdef DUMP_SUBSHAPE_IDS
4166 // Make a Python command
4167 GEOM::TPythonDump(aFunction, /*append=*/true)
4168 << "listShapesOnSphere = geompy.GetShapesOnSphereIDs"
4169 << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
4170 << theRadius << ", " << theState << ")";
4171 #endif // DUMP_SUBSHAPE_IDS
4177 //=======================================================================
4178 //function : getShapesOnQuadrangleIDs
4180 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4181 * \param theShape - the shape to explore
4182 * \param theShapeType - type of sub-shape of theShape
4183 * \param theTopLeftPoint - top left quadrangle corner
4184 * \param theTopRightPoint - top right quadrangle corner
4185 * \param theBottomLeftPoint - bottom left quadrangle corner
4186 * \param theBottomRightPoint - bottom right quadrangle corner
4187 * \param theState - required state
4188 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4190 //=======================================================================
4191 Handle(TColStd_HSequenceOfInteger)
4192 GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4193 const Standard_Integer theShapeType,
4194 const Handle(GEOM_Object)& theTopLeftPoint,
4195 const Handle(GEOM_Object)& theTopRightPoint,
4196 const Handle(GEOM_Object)& theBottomLeftPoint,
4197 const Handle(GEOM_Object)& theBottomRightPoint,
4198 const GEOMAlgo_State theState)
4202 if ( theShape.IsNull() ||
4203 theTopLeftPoint.IsNull() ||
4204 theTopRightPoint.IsNull() ||
4205 theBottomLeftPoint.IsNull() ||
4206 theBottomRightPoint.IsNull() )
4209 TopoDS_Shape aShape = theShape->GetValue();
4210 TopoDS_Shape aTL = theTopLeftPoint->GetValue();
4211 TopoDS_Shape aTR = theTopRightPoint->GetValue();
4212 TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
4213 TopoDS_Shape aBR = theBottomRightPoint->GetValue();
4215 if (aShape.IsNull() ||
4220 aTL.ShapeType() != TopAbs_VERTEX ||
4221 aTR.ShapeType() != TopAbs_VERTEX ||
4222 aBL.ShapeType() != TopAbs_VERTEX ||
4223 aBR.ShapeType() != TopAbs_VERTEX )
4226 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4227 if ( !checkTypeShapesOn( aShapeType ))
4230 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
4232 // Check presence of triangulation, build if need
4233 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
4234 SetErrorCode("Cannot build triangulation on the shape");
4239 gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
4240 gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
4241 gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
4242 gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
4244 GEOMAlgo_FinderShapeOn2 aFinder;
4245 Handle(GEOMAlgo_ClsfQuad) aClsfQuad = new GEOMAlgo_ClsfQuad;
4247 Standard_Real aTol = 0.0001; // default value
4249 aClsfQuad->SetCorners(aPntTL, aPntTR, aPntBL, aPntBR);
4250 aFinder.SetShape(aShape);
4251 aFinder.SetTolerance(aTol);
4252 aFinder.SetClsf(aClsfQuad);
4253 aFinder.SetShapeType(aShapeType);
4254 aFinder.SetState(theState);
4256 // Sets the minimal number of inner points for the faces that do not have own
4257 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
4259 aFinder.SetNbPntsMin(3);
4260 // Sets the maximal number of inner points for edges or faces.
4261 // It is useful for the cases when this number is very big (e.g =2000) to improve
4262 // the performance. If this value =0, all inner points will be taken into account.
4264 aFinder.SetNbPntsMax(100);
4268 // Interpret results
4269 Standard_Integer iErr = aFinder.ErrorStatus();
4270 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
4272 MESSAGE(" iErr : " << iErr);
4273 TCollection_AsciiString aMsg (" iErr : ");
4274 aMsg += TCollection_AsciiString(iErr);
4278 Standard_Integer iWrn = aFinder.WarningStatus();
4279 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
4281 MESSAGE(" *** iWrn : " << iWrn);
4284 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
4286 if (listSS.Extent() < 1) {
4287 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
4288 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
4292 // Fill sequence of object IDs
4293 aSeqOfIDs = new TColStd_HSequenceOfInteger;
4295 TopTools_IndexedMapOfShape anIndices;
4296 TopExp::MapShapes(aShape, anIndices);
4298 TopTools_ListIteratorOfListOfShape itSub (listSS);
4299 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
4300 int id = anIndices.FindIndex(itSub.Value());
4301 aSeqOfIDs->Append(id);
4306 //=======================================================================
4307 //function : GetShapesOnQuadrangle
4309 * \brief Find sub-shapes complying with given status about quadrangle
4310 * \param theShape - the shape to explore
4311 * \param theShapeType - type of sub-shape of theShape
4312 * \param theTopLeftPoint - top left quadrangle corner
4313 * \param theTopRightPoint - top right quadrangle corner
4314 * \param theBottomLeftPoint - bottom left quadrangle corner
4315 * \param theBottomRightPoint - bottom right quadrangle corner
4316 * \param theState - required state
4317 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4319 //=======================================================================
4320 Handle(TColStd_HSequenceOfTransient)
4321 GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
4322 const Standard_Integer theShapeType,
4323 const Handle(GEOM_Object)& theTopLeftPoint,
4324 const Handle(GEOM_Object)& theTopRightPoint,
4325 const Handle(GEOM_Object)& theBottomLeftPoint,
4326 const Handle(GEOM_Object)& theBottomRightPoint,
4327 const GEOMAlgo_State theState)
4330 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4331 getShapesOnQuadrangleIDs( theShape,
4336 theBottomRightPoint,
4338 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4341 // Find objects by indices
4342 TCollection_AsciiString anAsciiList;
4343 Handle(TColStd_HSequenceOfTransient) aSeq;
4344 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
4345 if ( aSeq.IsNull() || aSeq->IsEmpty() )
4348 // Make a Python command
4350 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
4351 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
4353 GEOM::TPythonDump(aFunction)
4354 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
4356 << TopAbs_ShapeEnum(theShapeType) << ", "
4357 << theTopLeftPoint << ", "
4358 << theTopRightPoint << ", "
4359 << theBottomLeftPoint << ", "
4360 << theBottomRightPoint << ", "
4367 //=======================================================================
4368 //function : GetShapesOnQuadrangleIDs
4370 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4371 * \param theShape - the shape to explore
4372 * \param theShapeType - type of sub-shape of theShape
4373 * \param theTopLeftPoint - top left quadrangle corner
4374 * \param theTopRightPoint - top right quadrangle corner
4375 * \param theBottomLeftPoint - bottom left quadrangle corner
4376 * \param theBottomRightPoint - bottom right quadrangle corner
4377 * \param theState - required state
4378 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4380 //=======================================================================
4381 Handle(TColStd_HSequenceOfInteger)
4382 GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4383 const Standard_Integer theShapeType,
4384 const Handle(GEOM_Object)& theTopLeftPoint,
4385 const Handle(GEOM_Object)& theTopRightPoint,
4386 const Handle(GEOM_Object)& theBottomLeftPoint,
4387 const Handle(GEOM_Object)& theBottomRightPoint,
4388 const GEOMAlgo_State theState)
4391 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4392 getShapesOnQuadrangleIDs( theShape,
4397 theBottomRightPoint,
4399 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4402 // Make a Python command
4404 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4405 Handle(GEOM_BaseObject) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
4406 lastObj = GEOM::GetCreatedLast(lastObj,theTopRightPoint);
4407 lastObj = GEOM::GetCreatedLast(lastObj,theBottomRightPoint);
4408 lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
4409 Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
4411 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4412 #ifdef DUMP_SUBSHAPE_IDS
4413 GEOM::TPythonDump(aFunction, /*append=*/true)
4414 << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
4416 << TopAbs_ShapeEnum(theShapeType) << ", "
4417 << theTopLeftPoint << ", "
4418 << theTopRightPoint << ", "
4419 << theBottomLeftPoint << ", "
4420 << theBottomRightPoint << ", "
4422 #endif // DUMP_SUBSHAPE_IDS
4428 //=============================================================================
4433 //=============================================================================
4434 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
4435 Handle(GEOM_Object) theShapeWhat)
4439 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4441 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4442 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4444 if (aWhere.IsNull() || aWhat.IsNull()) {
4445 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4449 // Searching for the sub-shapes inside the ShapeWhere shape
4450 GEOMAlgo_GetInPlace aGIP;
4452 if (!GEOMAlgo_GetInPlaceAPI::GetInPlace(aWhere, aWhat, aGIP)) {
4453 SetErrorCode("Error in GEOMAlgo_GetInPlace");
4457 // Add direct result.
4458 TopTools_ListOfShape aLSA;
4459 const TopoDS_Shape &aShapeResult = aGIP.Result();
4460 TopTools_MapOfShape aMFence;
4461 TopTools_IndexedMapOfShape aWhereIndices;
4462 Standard_Integer aShapeType = -1;
4464 TopExp::MapShapes(aWhere, aWhereIndices);
4466 if (aShapeResult.IsNull() == Standard_False) {
4467 TopoDS_Iterator anIt(aShapeResult);
4469 for (; anIt.More(); anIt.Next()) {
4470 const TopoDS_Shape &aPart = anIt.Value();
4472 if(aWhereIndices.Contains(aPart) && aMFence.Add(aPart)) {
4473 const TopAbs_ShapeEnum aType = aPart.ShapeType();
4475 if (aShapeType == -1) {
4478 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4480 aShapeType = TopAbs_SHAPE;
4488 if (aLSA.Extent() == 0) {
4489 SetErrorCode(NOT_FOUND_ANY); // Not found any Results
4493 Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent());
4494 TopTools_ListIteratorOfListOfShape anIterModif (aLSA);
4495 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4496 aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value()));
4500 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4501 if (aResult.IsNull()) {
4502 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4506 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4508 if ((aModifiedArray->Length() > 1 && isSameType) ||
4509 theShapeWhat->GetType() == GEOM_GROUP) {
4511 aResult->SetType(GEOM_GROUP);
4513 //Set a sub-shape type
4514 TopoDS_Shape aFirstFound = aLSA.First();
4515 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4517 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4518 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4521 //Make a Python command
4522 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4524 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4525 << theShapeWhere << ", " << theShapeWhat << ", True)";
4531 //=============================================================================
4533 * case GetInPlaceOld:
4536 //=============================================================================
4537 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld
4538 (Handle(GEOM_Object) theShapeWhere,
4539 Handle(GEOM_Object) theShapeWhat)
4543 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4545 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4546 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4547 TopTools_ListOfShape aModifiedList;
4548 const Standard_Integer iErr =
4549 GEOMAlgo_GetInPlaceAPI::GetInPlaceOld(aWhere, aWhat, aModifiedList);
4554 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4558 ("Error: An attempt to extract a shape of not supported type.");
4561 SetErrorCode(NOT_FOUND_ANY);
4564 SetErrorCode("Shape driver failed");
4571 TopTools_IndexedMapOfShape aWhereIndices;
4572 TopExp::MapShapes(aWhere, aWhereIndices);
4574 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4575 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4576 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4577 Standard_Integer imod;
4578 Standard_Integer aShapeType = -1;
4580 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4581 const Standard_Integer anIndex =
4582 aWhereIndices.FindIndex(anIterModif.Value());
4583 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4585 if (aShapeType == -1) {
4588 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4590 aShapeType = TopAbs_SHAPE;
4593 aModifiedArray->SetValue(imod, anIndex);
4597 Handle(GEOM_Object) aResult =
4598 GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4600 if (aResult.IsNull()) {
4601 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4605 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4607 if ((aModifiedArray->Length() > 1 && isSameType) ||
4608 theShapeWhat->GetType() == GEOM_GROUP) {
4610 aResult->SetType(GEOM_GROUP);
4612 //Set a sub-shape type
4613 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4614 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4616 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4617 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4620 //Make a Python command
4621 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4623 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4624 << theShapeWhere << ", " << theShapeWhat << ", False)";
4631 //=======================================================================
4632 //function : GetInPlaceByHistory
4634 //=======================================================================
4635 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
4636 (Handle(GEOM_Object) theShapeWhere,
4637 Handle(GEOM_Object) theShapeWhat)
4641 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4643 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4644 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4646 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4648 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4649 if (aWhereFunction.IsNull()) return NULL;
4651 //Fill array of indices
4652 TopTools_IndexedMapOfShape aWhereIndices;
4654 TopExp::MapShapes(aWhere, aWhereIndices);
4657 TopTools_ListOfShape aModifiedList;
4658 bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceByHistory
4659 (aWhereFunction, aWhereIndices, aWhat, aModifiedList);
4661 if (!isFound || aModifiedList.Extent() < 1) {
4662 SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
4666 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4667 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4668 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4669 Standard_Integer imod;
4670 Standard_Integer aShapeType = -1;
4672 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4673 const Standard_Integer anIndex =
4674 aWhereIndices.FindIndex(anIterModif.Value());
4675 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4677 if (aShapeType == -1) {
4680 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4682 aShapeType = TopAbs_SHAPE;
4685 aModifiedArray->SetValue(imod, anIndex);
4689 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4690 if (aResult.IsNull()) {
4691 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4695 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4697 if ((aModifiedArray->Length() > 1 && isSameType) ||
4698 theShapeWhat->GetType() == GEOM_GROUP) {
4700 aResult->SetType(GEOM_GROUP);
4702 //Set a sub-shape type
4703 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4704 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4706 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4707 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4710 //Make a Python command
4711 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4713 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
4714 << theShapeWhere << ", " << theShapeWhat << ")";
4720 //=======================================================================
4721 //function : GetInPlaceMap
4723 //=======================================================================
4724 void GEOMImpl_IShapesOperations::GetInPlaceMap (Handle(GEOM_Object) theShapeWhere,
4725 Handle(GEOM_Object) theShapeWhat,
4726 std::vector< std::vector< int > > & theResVec)
4730 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return;
4732 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4733 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4735 if (aWhere.IsNull() || aWhat.IsNull()) return;
4737 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4738 if (aWhereFunction.IsNull()) return;
4740 bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceMap( aWhereFunction, aWhat, theResVec );
4745 Handle(GEOM_Function) aFunction =
4746 GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
4748 GEOM::TPythonDump(aFunction, /*append=*/true)
4749 << "resultList = geompy.GetInPlaceMap( "
4750 << theShapeWhere << ", "
4751 << theShapeWhat << ")";
4756 //=======================================================================
4757 //function : isSameEdge
4758 //purpose : Returns True if two edges coincide
4759 //=======================================================================
4760 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4762 TopoDS_Vertex V11, V12, V21, V22;
4763 TopExp::Vertices(theEdge1, V11, V12);
4764 TopExp::Vertices(theEdge2, V21, V22);
4765 gp_Pnt P11 = BRep_Tool::Pnt(V11);
4766 gp_Pnt P12 = BRep_Tool::Pnt(V12);
4767 gp_Pnt P21 = BRep_Tool::Pnt(V21);
4768 gp_Pnt P22 = BRep_Tool::Pnt(V22);
4769 bool coincide = false;
4771 //Check that ends of edges coincide
4772 if(P11.Distance(P21) <= MAX_TOLERANCE) {
4773 if(P12.Distance(P22) <= MAX_TOLERANCE) coincide = true;
4775 else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4776 if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4779 if(!coincide) return false;
4781 if (BRep_Tool::Degenerated(theEdge1))
4782 if (BRep_Tool::Degenerated(theEdge2)) return true;
4785 if (BRep_Tool::Degenerated(theEdge2)) return false;
4787 double U11, U12, U21, U22;
4788 Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4789 Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4791 //Check that both edges has the same geometry
4792 double range = U12-U11;
4793 double U = U11+ range/3.0;
4794 gp_Pnt P1 = C1->Value(U); //Compute a point on one third of the edge's length
4795 U = U11+range*2.0/3.0;
4796 gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length
4798 C2 = new Geom_TrimmedCurve(C2, U21, U22);
4799 // vsr 04/10/2018: 0023312 - As curve may be periodic, its parameters may be normalized
4800 // so, we re-take them from trimmed curve
4801 U21 = C2->FirstParameter();
4802 U22 = C2->LastParameter();
4804 if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22)
4807 if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4809 if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4812 if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4817 //=======================================================================
4818 //function : isSameFace
4819 //purpose : Returns True if two faces coincide
4820 //=======================================================================
4821 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4823 TopExp_Explorer E(theFace1, TopAbs_EDGE);
4824 TopTools_ListOfShape LS1, LS2;
4825 for(; E.More(); E.Next()) LS1.Append(E.Current());
4827 E.Init(theFace2, TopAbs_EDGE);
4828 for(; E.More(); E.Next()) LS2.Append(E.Current());
4830 //Compare the number of edges in the faces
4831 if(LS1.Extent() != LS2.Extent()) return false;
4833 double aMin = RealFirst(), aMax = RealLast();
4834 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4835 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4837 for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4838 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4839 if(P.X() < xminB1) xminB1 = P.X();
4840 if(P.Y() < yminB1) yminB1 = P.Y();
4841 if(P.Z() < zminB1) zminB1 = P.Z();
4842 if(P.X() > xmaxB1) xmaxB1 = P.X();
4843 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4844 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4847 for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4848 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4849 if(P.X() < xminB2) xminB2 = P.X();
4850 if(P.Y() < yminB2) yminB2 = P.Y();
4851 if(P.Z() < zminB2) zminB2 = P.Z();
4852 if(P.X() > xmaxB2) xmaxB2 = P.X();
4853 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4854 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4857 //Compare the bounding boxes of both faces
4858 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4861 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4864 Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4865 Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4867 //Check if there a coincidence of two surfaces at least in two points
4868 double U11, U12, V11, V12, U21, U22, V21, V22;
4869 BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4870 BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4872 double rangeU = U12-U11;
4873 double rangeV = V12-V11;
4874 double U = U11 + rangeU/3.0;
4875 double V = V11 + rangeV/3.0;
4876 gp_Pnt P1 = S1->Value(U, V);
4877 U = U11+rangeU*2.0/3.0;
4878 V = V11+rangeV*2.0/3.0;
4879 gp_Pnt P2 = S1->Value(U, V);
4881 if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4884 if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4886 if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4889 if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
4891 //Check that each edge of the Face1 has a counterpart in the Face2
4892 TopTools_MapOfOrientedShape aMap;
4893 TopTools_ListIteratorOfListOfShape LSI1(LS1);
4894 for(; LSI1.More(); LSI1.Next()) {
4895 TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
4896 bool isFound = false;
4897 TopTools_ListIteratorOfListOfShape LSI2(LS2);
4898 for(; LSI2.More(); LSI2.Next()) {
4899 TopoDS_Shape aValue = LSI2.Value();
4900 if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
4901 if(isSameEdge(E, TopoDS::Edge(aValue))) {
4907 if(!isFound) return false;
4913 //=======================================================================
4914 //function : isSameSolid
4915 //purpose : Returns True if two solids coincide
4916 //=======================================================================
4917 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
4919 TopExp_Explorer E(theSolid1, TopAbs_FACE);
4920 TopTools_ListOfShape LS1, LS2;
4921 for(; E.More(); E.Next()) LS1.Append(E.Current());
4922 E.Init(theSolid2, TopAbs_FACE);
4923 for(; E.More(); E.Next()) LS2.Append(E.Current());
4925 if(LS1.Extent() != LS2.Extent()) return false;
4927 double aMin = RealFirst(), aMax = RealLast();
4928 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4929 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4931 for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
4932 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4933 if(P.X() < xminB1) xminB1 = P.X();
4934 if(P.Y() < yminB1) yminB1 = P.Y();
4935 if(P.Z() < zminB1) zminB1 = P.Z();
4936 if(P.X() > xmaxB1) xmaxB1 = P.X();
4937 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4938 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4941 for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
4942 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4943 if(P.X() < xminB2) xminB2 = P.X();
4944 if(P.Y() < yminB2) yminB2 = P.Y();
4945 if(P.Z() < zminB2) zminB2 = P.Z();
4946 if(P.X() > xmaxB2) xmaxB2 = P.X();
4947 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4948 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4951 //Compare the bounding boxes of both solids
4952 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4955 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4958 //Check that each face of the Solid1 has a counterpart in the Solid2
4959 TopTools_MapOfOrientedShape aMap;
4960 TopTools_ListIteratorOfListOfShape LSI1(LS1);
4961 for(; LSI1.More(); LSI1.Next()) {
4962 TopoDS_Face F = TopoDS::Face(LSI1.Value());
4963 bool isFound = false;
4964 TopTools_ListIteratorOfListOfShape LSI2(LS2);
4965 for(; LSI2.More(); LSI2.Next()) {
4966 if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
4967 if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
4968 aMap.Add(LSI2.Value());
4973 if(!isFound) return false;
4979 //=======================================================================
4980 //function : GetSame
4982 //=======================================================================
4983 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
4984 const Handle(GEOM_Object)& theShapeWhat)
4987 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4989 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4990 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4992 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4995 bool isFound = false;
4996 TopoDS_Shape aSubShape;
4997 TopTools_MapOfShape aMap;
4999 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
5000 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
5001 if (It.More()) aWhat = It.Value();
5004 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
5009 switch (aWhat.ShapeType()) {
5010 case TopAbs_VERTEX: {
5011 aSubShape = getSameVertex(aWhere, TopoDS::Vertex(aWhat));
5012 isFound = !aSubShape.IsNull();
5016 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
5017 TopExp_Explorer E(aWhere, TopAbs_EDGE);
5018 for(; E.More(); E.Next()) {
5019 if(!aMap.Add(E.Current())) continue;
5020 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
5021 aSubShape = E.Current();
5029 TopoDS_Face aFace = TopoDS::Face(aWhat);
5030 TopExp_Explorer E(aWhere, TopAbs_FACE);
5031 for(; E.More(); E.Next()) {
5032 if(!aMap.Add(E.Current())) continue;
5033 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5034 aSubShape = E.Current();
5041 case TopAbs_SOLID: {
5042 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5043 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5044 for(; E.More(); E.Next()) {
5045 if(!aMap.Add(E.Current())) continue;
5046 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5047 aSubShape = E.Current();
5059 TopTools_IndexedMapOfShape anIndices;
5060 TopExp::MapShapes(aWhere, anIndices);
5061 if (anIndices.Contains(aSubShape))
5062 anIndex = anIndices.FindIndex(aSubShape);
5065 if (anIndex < 0) return NULL;
5067 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
5069 anArray->SetValue(1, anIndex);
5071 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
5072 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
5074 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
5075 << theShapeWhere << ", " << theShapeWhat << ")";
5083 //=======================================================================
5084 //function : GetSameIDs
5086 //=======================================================================
5087 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
5088 (const Handle(GEOM_Object)& theShapeWhere,
5089 const Handle(GEOM_Object)& theShapeWhat)
5092 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
5094 TopoDS_Shape aWhere = theShapeWhere->GetValue();
5095 TopoDS_Shape aWhat = theShapeWhat->GetValue();
5097 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
5099 TopTools_ListOfShape listShape;
5100 TopTools_MapOfShape aMap;
5102 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
5103 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
5104 if (It.More()) aWhat = It.Value();
5107 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
5112 switch (aWhat.ShapeType()) {
5113 case TopAbs_VERTEX: {
5114 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
5115 TopExp_Explorer E(aWhere, TopAbs_VERTEX);
5116 for(; E.More(); E.Next()) {
5117 if(!aMap.Add(E.Current())) continue;
5118 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
5119 if(P.Distance(P2) <= MAX_TOLERANCE) {
5120 listShape.Append(E.Current());
5126 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
5127 TopExp_Explorer E(aWhere, TopAbs_EDGE);
5128 for(; E.More(); E.Next()) {
5129 if(!aMap.Add(E.Current())) continue;
5130 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
5131 listShape.Append(E.Current());
5137 TopoDS_Face aFace = TopoDS::Face(aWhat);
5138 TopExp_Explorer E(aWhere, TopAbs_FACE);
5139 for(; E.More(); E.Next()) {
5140 if(!aMap.Add(E.Current())) continue;
5141 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5142 listShape.Append(E.Current());
5147 case TopAbs_SOLID: {
5148 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5149 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5150 for(; E.More(); E.Next()) {
5151 if(!aMap.Add(E.Current())) continue;
5152 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5153 listShape.Append(E.Current());
5162 if ( !listShape.IsEmpty() ) {
5163 TopTools_IndexedMapOfShape anIndices;
5164 TopExp::MapShapes(aWhere, anIndices);
5165 TopTools_ListIteratorOfListOfShape itSub (listShape);
5166 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
5167 for (; itSub.More(); itSub.Next()) {
5168 if (anIndices.Contains(itSub.Value()))
5169 aSeq->Append(anIndices.FindIndex(itSub.Value()));
5172 // The GetSameIDs() doesn't change object so no new function is required.
5173 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
5175 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
5176 #ifdef DUMP_SUBSHAPE_IDS
5177 // Make a Python command
5178 GEOM::TPythonDump(aFunction, /*append=*/true)
5179 << "listSameIDs = geompy.GetSameIDs("
5180 << theShapeWhere << ", "
5181 << theShapeWhat << ")";
5182 #endif // DUMP_SUBSHAPE_IDS
5185 SetErrorCode(NOT_FOUND_ANY);
5190 //=======================================================================
5191 //function : ExtendEdge
5193 //=======================================================================
5194 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendEdge
5195 (const Handle(GEOM_Object) &theEdge,
5196 const Standard_Real theMin,
5197 const Standard_Real theMax)
5201 if (theEdge.IsNull()) {
5205 //Add a new Edge object
5206 Handle(GEOM_Object) aResEdge = GetEngine()->AddObject(GEOM_EDGE);
5208 //Add a new Vector function
5209 Handle(GEOM_Function) aFunction =
5210 aResEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_UV);
5212 //Check if the function is set correctly
5213 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5217 GEOMImpl_IShapeExtend aCI (aFunction);
5219 Handle(GEOM_Function) anEdge = theEdge->GetLastFunction();
5221 if (anEdge.IsNull()) {
5225 aCI.SetShape(anEdge);
5226 aCI.SetUMin(theMin);
5227 aCI.SetUMax(theMax);
5229 //Compute the Edge value
5232 if (!GetSolver()->ComputeFunction(aFunction)) {
5233 SetErrorCode("Shape driver failed");
5238 catch (Standard_Failure& aFail) {
5239 SetErrorCode(aFail.GetMessageString());
5244 //Make a Python command
5245 GEOM::TPythonDump(aFunction)
5246 << aResEdge << " = geompy.ExtendEdge("
5247 << theEdge << ", " << theMin << ", " << theMax << ")";
5254 //=======================================================================
5255 //function : ExtendFace
5257 //=======================================================================
5258 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendFace
5259 (const Handle(GEOM_Object) &theFace,
5260 const Standard_Real theUMin,
5261 const Standard_Real theUMax,
5262 const Standard_Real theVMin,
5263 const Standard_Real theVMax)
5267 if (theFace.IsNull()) {
5271 //Add a new Face object
5272 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GEOM_FACE);
5274 //Add a new Vector function
5275 Handle(GEOM_Function) aFunction =
5276 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_UV);
5278 //Check if the function is set correctly
5279 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5283 GEOMImpl_IShapeExtend aCI (aFunction);
5285 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5287 if (aFace.IsNull()) {
5291 aCI.SetShape(aFace);
5292 aCI.SetUMin(theUMin);
5293 aCI.SetUMax(theUMax);
5294 aCI.SetVMin(theVMin);
5295 aCI.SetVMax(theVMax);
5297 //Compute the Face value
5300 if (!GetSolver()->ComputeFunction(aFunction)) {
5301 SetErrorCode("Shape driver failed");
5306 catch (Standard_Failure& aFail) {
5307 SetErrorCode(aFail.GetMessageString());
5312 //Make a Python command
5313 GEOM::TPythonDump(aFunction)
5314 << aResFace << " = geompy.ExtendFace("
5315 << theFace << ", " << theUMin << ", " << theUMax << ", "
5316 << theVMin << ", " << theVMax << ")";
5323 //=======================================================================
5324 //function : MakeSurfaceFromFace
5326 //=======================================================================
5327 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSurfaceFromFace
5328 (const Handle(GEOM_Object) &theFace)
5332 if (theFace.IsNull()) {
5336 //Add a new Face object
5337 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GEOM_FACE);
5339 //Add a new Vector function
5340 Handle(GEOM_Function) aFunction =
5341 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), SURFACE_FROM_FACE);
5343 //Check if the function is set correctly
5344 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5348 GEOMImpl_IShapeExtend aCI (aFunction);
5350 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5352 if (aFace.IsNull()) {
5356 aCI.SetShape(aFace);
5358 //Compute the Face value
5361 if (!GetSolver()->ComputeFunction(aFunction)) {
5362 SetErrorCode("Shape driver failed");
5367 catch (Standard_Failure& aFail) {
5368 SetErrorCode(aFail.GetMessageString());
5373 //Make a Python command
5374 GEOM::TPythonDump(aFunction)
5375 << aResFace << " = geompy.MakeSurfaceFromFace("