1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : GEOMImpl_IShapesOperations.cxx
25 // Author : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
28 //#include <Standard_Stream.hxx>
30 #include "GEOMImpl_IShapesOperations.hxx"
32 #include "GEOMImpl_Types.hxx"
34 #include "GEOMImpl_VectorDriver.hxx"
35 #include "GEOMImpl_ShapeDriver.hxx"
36 #include "GEOMImpl_GlueDriver.hxx"
37 #include "GEOMImpl_FillingDriver.hxx"
39 #include "GEOMImpl_IExtract.hxx"
40 #include "GEOMImpl_IVector.hxx"
41 #include "GEOMImpl_IShapes.hxx"
42 #include "GEOMImpl_IShapeExtend.hxx"
43 #include "GEOMImpl_IGlue.hxx"
44 #include "GEOMImpl_IFilling.hxx"
46 #include "GEOMImpl_Block6Explorer.hxx"
47 #include "GEOMImpl_IHealingOperations.hxx"
49 #include "GEOMImpl_Gen.hxx"
51 #include "GEOM_Function.hxx"
52 #include "GEOM_ISubShape.hxx"
53 #include "GEOM_PythonDump.hxx"
55 #include "GEOMUtils.hxx"
57 #include "GEOMAlgo_ClsfBox.hxx"
58 #include "GEOMAlgo_ClsfQuad.hxx"
59 #include "GEOMAlgo_ClsfSolid.hxx"
60 #include "GEOMAlgo_ClsfSurf.hxx"
61 #include "GEOMAlgo_FinderShapeOn2.hxx"
62 #include "GEOMAlgo_GetInPlace.hxx"
63 #include "GEOMAlgo_GetInPlaceAPI.hxx"
64 #include "GEOMAlgo_GlueDetector.hxx"
66 #include <utilities.h>
68 #include <BRepAdaptor_Curve.hxx>
69 #include <BRepAdaptor_Surface.hxx>
70 #include <BRepTools.hxx>
71 #include <BRep_Builder.hxx>
72 #include <BRep_Tool.hxx>
73 #include <GeomLib_Tool.hxx>
74 #include <Geom_CylindricalSurface.hxx>
75 #include <Geom_Plane.hxx>
76 #include <Geom_SphericalSurface.hxx>
77 #include <Geom_Surface.hxx>
78 #include <Geom_TrimmedCurve.hxx>
79 #include <Precision.hxx>
80 #include <TDF_Tool.hxx>
81 #include <TDataStd_Integer.hxx>
82 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
84 #include <TopExp_Explorer.hxx>
85 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
86 #include <TopTools_IndexedMapOfShape.hxx>
87 #include <TopTools_ListIteratorOfListOfShape.hxx>
88 #include <TopTools_MapOfOrientedShape.hxx>
89 #include <TopTools_MapOfShape.hxx>
90 #include <TopTools_SequenceOfShape.hxx>
92 #include <TopoDS_TShape.hxx>
93 #include <TopoDS_Compound.hxx>
94 #include <TopoDS_Edge.hxx>
95 #include <TopoDS_Face.hxx>
96 #include <TopoDS_Iterator.hxx>
97 #include <TopoDS_Shape.hxx>
98 #include <TopoDS_Solid.hxx>
99 #include <TopoDS_Vertex.hxx>
100 #include <gp_Cylinder.hxx>
101 #include <gp_Pnt.hxx>
105 #include <Standard_Failure.hxx>
106 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
108 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
109 // Next macro, when defined, causes appearing of SubShapeAllIDs(), SubShapeAllSortedIDs(), GetSameIDs()
110 // and other such commands in Python dump.
111 // See also GEOM_Engine.cxx.
112 // ---------------------------------------
113 // #define DUMP_SUBSHAPE_IDS
114 // ---------------------------------------
118 void AddFlatSubShapes(const TopoDS_Shape& S, TopTools_ListOfShape& L, TopTools_MapOfShape& M)
120 if (S.ShapeType() != TopAbs_COMPOUND) {
124 TopoDS_Iterator It(S, Standard_True, Standard_True);
125 for (; It.More(); It.Next()) {
126 TopoDS_Shape SS = It.Value();
128 AddFlatSubShapes(SS, L, M);
136 const double MAX_TOLERANCE = 1.e-7;
139 * \brief Returns the vertex from theWhere shape that is coincident with
142 * \param theWhere the shape where the coinsident vertex is searched.
143 * \param theVertex the vertex to be searched.
144 * \return the coincident vertex if it is found. Otherwise null object.
146 static TopoDS_Vertex getSameVertex(const TopoDS_Shape &theWhere,
147 const TopoDS_Vertex &theVertex)
149 TopoDS_Vertex aResult;
150 gp_Pnt aPoint = BRep_Tool::Pnt(theVertex);
151 TopExp_Explorer anExp(theWhere, TopAbs_VERTEX);
152 TopTools_MapOfShape aMap;
154 for(; anExp.More(); anExp.Next()) {
155 const TopoDS_Shape &aLocalShape = anExp.Current();
157 if(!aMap.Add(aLocalShape)) {
161 TopoDS_Vertex aVertex = TopoDS::Vertex(aLocalShape);
162 gp_Pnt aPoint2 = BRep_Tool::Pnt(aVertex);
164 if(aPoint.Distance(aPoint2) <= MAX_TOLERANCE) {
172 } // end of namespace
174 //=============================================================================
178 //=============================================================================
179 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
180 : GEOM_IOperations(theEngine, theDocID)
182 MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
185 //=============================================================================
189 //=============================================================================
190 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
192 MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
195 //=============================================================================
199 //=============================================================================
200 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
201 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
205 if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
207 //Add a new Edge object
208 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
210 //Add a new Vector function
211 Handle(GEOM_Function) aFunction =
212 anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
214 //Check if the function is set correctly
215 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
217 GEOMImpl_IVector aPI (aFunction);
219 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
220 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
221 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
223 aPI.SetPoint1(aRef1);
224 aPI.SetPoint2(aRef2);
226 //Compute the Edge value
229 if (!GetSolver()->ComputeFunction(aFunction)) {
230 SetErrorCode("Vector driver failed");
234 catch (Standard_Failure) {
235 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
236 SetErrorCode(aFail->GetMessageString());
240 //Make a Python command
241 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
242 << thePnt1 << ", " << thePnt2 << ")";
248 //=============================================================================
250 * MakeEdgeOnCurveByLength
252 //=============================================================================
253 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeOnCurveByLength
254 (Handle(GEOM_Object) theRefCurve,
255 const Standard_Real theLength,
256 Handle(GEOM_Object) theStartPoint)
260 if (theRefCurve.IsNull()) return NULL;
262 //Add a new Edge object
263 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
265 //Add a new Vector function
266 Handle(GEOM_Function) aFunction =
267 anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_CURVE_LENGTH);
269 //Check if the function is set correctly
270 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
272 GEOMImpl_IVector aPI (aFunction);
274 Handle(GEOM_Function) aRef1 = theRefCurve->GetLastFunction();
275 if (aRef1.IsNull()) return NULL;
276 aPI.SetPoint1(aRef1);
278 if (!theStartPoint.IsNull()) {
279 Handle(GEOM_Function) aRef2 = theStartPoint->GetLastFunction();
280 aPI.SetPoint2(aRef2);
283 aPI.SetParameter(theLength);
285 //Compute the Edge value
288 if (!GetSolver()->ComputeFunction(aFunction)) {
289 SetErrorCode("Vector driver failed");
293 catch (Standard_Failure) {
294 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
295 SetErrorCode(aFail->GetMessageString());
299 //Make a Python command
300 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeOnCurveByLength("
301 << theRefCurve << ", " << theLength << ", " << theStartPoint << ")";
307 //=============================================================================
311 //=============================================================================
312 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire
313 (Handle(GEOM_Object) theWire,
314 const Standard_Real theLinearTolerance,
315 const Standard_Real theAngularTolerance)
319 if (theWire.IsNull()) return NULL;
321 //Add a new Edge object
322 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
324 //Add a new Vector function
325 Handle(GEOM_Function) aFunction =
326 anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_WIRE);
328 //Check if the function is set correctly
329 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
331 GEOMImpl_IShapes aCI (aFunction);
333 Handle(GEOM_Function) aWire = theWire->GetLastFunction();
335 if (aWire.IsNull()) return NULL;
338 aCI.SetTolerance(theLinearTolerance);
339 aCI.SetAngularTolerance(theAngularTolerance);
341 //Compute the Edge value
344 if (!GetSolver()->ComputeFunction(aFunction)) {
345 SetErrorCode("Shape driver failed");
349 catch (Standard_Failure) {
350 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
351 SetErrorCode(aFail->GetMessageString());
355 const double DEF_LIN_TOL = Precision::Confusion();
356 const double DEF_ANG_TOL = Precision::Angular();
357 //Make a Python command
358 if ( theAngularTolerance == DEF_ANG_TOL ) {
359 if ( theLinearTolerance == DEF_LIN_TOL )
360 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
363 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
364 << theWire << ", " << theLinearTolerance << ")";
367 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire("
368 << theWire << ", " << theLinearTolerance << ", "
369 << theAngularTolerance << ")";
376 //=============================================================================
380 //=============================================================================
381 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
382 (std::list<Handle(GEOM_Object)> theShapes,
383 const Standard_Real theTolerance)
388 Handle(GEOM_Object) aWire = GetEngine()->AddObject(GetDocID(), GEOM_WIRE);
391 Handle(GEOM_Function) aFunction =
392 aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES);
393 if (aFunction.IsNull()) return NULL;
395 //Check if the function is set correctly
396 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
398 GEOMImpl_IShapes aCI (aFunction);
399 aCI.SetTolerance(theTolerance);
401 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
404 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
405 for (; it != theShapes.end(); it++) {
406 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
407 if (aRefSh.IsNull()) {
408 SetErrorCode("NULL argument shape for the shape construction");
411 aShapesSeq->Append(aRefSh);
413 aCI.SetShapes(aShapesSeq);
418 if (!GetSolver()->ComputeFunction(aFunction)) {
419 SetErrorCode("Shape driver failed");
423 catch (Standard_Failure) {
424 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
425 SetErrorCode(aFail->GetMessageString());
429 //Make a Python command
430 GEOM::TPythonDump pd (aFunction);
431 pd << aWire << " = geompy.MakeWire([";
434 it = theShapes.begin();
435 if (it != theShapes.end()) {
437 while (it != theShapes.end()) {
438 pd << ", " << (*it++);
441 pd << "], " << theTolerance << ")";
447 //=============================================================================
451 //=============================================================================
452 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
453 const bool isPlanarWanted)
457 if (theWire.IsNull()) return NULL;
459 //Add a new Face object
460 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
462 //Add a new Shape function for creation of a face from a wire
463 Handle(GEOM_Function) aFunction =
464 aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
465 if (aFunction.IsNull()) return NULL;
467 //Check if the function is set correctly
468 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
470 GEOMImpl_IShapes aCI (aFunction);
472 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
474 if (aRefWire.IsNull()) return NULL;
476 aCI.SetBase(aRefWire);
477 aCI.SetIsPlanar(isPlanarWanted);
479 //Compute the Face value
480 Standard_Boolean isWarning = Standard_False;
483 if (!GetSolver()->ComputeFunction(aFunction)) {
484 SetErrorCode("Shape driver failed to compute a face");
488 catch (Standard_Failure) {
489 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
490 SetErrorCode(aFail->GetMessageString());
491 // to provide warning
492 if (!aFunction->GetValue().IsNull()) {
493 isWarning = Standard_True;
499 //Make a Python command
500 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
501 << theWire << ", " << (int)isPlanarWanted << ")";
503 // to provide warning
504 if (!isWarning) SetErrorCode(OK);
508 //=============================================================================
512 //=============================================================================
513 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
514 (std::list<Handle(GEOM_Object)> theShapes,
515 const bool isPlanarWanted)
520 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
523 Handle(GEOM_Function) aFunction =
524 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
525 if (aFunction.IsNull()) return NULL;
527 //Check if the function is set correctly
528 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
530 GEOMImpl_IShapes aCI (aFunction);
532 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
535 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
536 for (; it != theShapes.end(); it++) {
537 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
538 if (aRefSh.IsNull()) {
539 SetErrorCode("NULL argument shape for the face construction");
542 aShapesSeq->Append(aRefSh);
544 aCI.SetShapes(aShapesSeq);
546 aCI.SetIsPlanar(isPlanarWanted);
549 Standard_Boolean isWarning = Standard_False;
552 if (!GetSolver()->ComputeFunction(aFunction)) {
553 SetErrorCode("Shape driver failed");
557 catch (Standard_Failure) {
558 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
559 SetErrorCode(aFail->GetMessageString());
560 // to provide warning
561 if (!aFunction->GetValue().IsNull()) {
562 isWarning = Standard_True;
568 //Make a Python command
569 GEOM::TPythonDump pd (aFunction);
570 pd << aShape << " = geompy.MakeFaceWires([";
573 it = theShapes.begin();
574 if (it != theShapes.end()) {
576 while (it != theShapes.end()) {
577 pd << ", " << (*it++);
580 pd << "], " << (int)isPlanarWanted << ")";
582 // to provide warning
583 if (!isWarning) SetErrorCode(OK);
587 //=============================================================================
589 * MakeFaceFromSurface
591 //=============================================================================
592 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface
593 (Handle(GEOM_Object) theFace,
594 Handle(GEOM_Object) theWire)
599 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
602 Handle(GEOM_Function) aFunction =
603 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_FROM_SURFACE);
605 if (aFunction.IsNull()) {
609 //Check if the function is set correctly
610 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
614 GEOMImpl_IShapes aCI (aFunction);
615 Handle(TColStd_HSequenceOfTransient) aShapesSeq =
616 new TColStd_HSequenceOfTransient;
617 Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
618 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
620 if (aRefFace.IsNull()) {
621 SetErrorCode("NULL argument face for the face construction");
625 if (aRefWire.IsNull()) {
626 SetErrorCode("NULL argument wire for the face construction");
630 aShapesSeq->Append(aRefFace);
631 aShapesSeq->Append(aRefWire);
633 aCI.SetShapes(aShapesSeq);
638 if (!GetSolver()->ComputeFunction(aFunction)) {
639 SetErrorCode("Shape driver failed");
643 catch (Standard_Failure) {
644 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
645 SetErrorCode(aFail->GetMessageString());
649 //Make a Python command
650 GEOM::TPythonDump (aFunction) << aShape
651 << " = geompy.MakeFaceFromSurface(" << theFace << ", " << theWire << ")";
658 //=============================================================================
660 * MakeFaceWithConstraints
662 //=============================================================================
663 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWithConstraints
664 (std::list<Handle(GEOM_Object)> theConstraints)
669 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FILLING);
672 Handle(GEOM_Function) aFunction =
673 aShape->AddFunction(GEOMImpl_FillingDriver::GetID(), FILLING_ON_CONSTRAINTS);
674 if (aFunction.IsNull()) return NULL;
676 //Check if the function is set correctly
677 if (aFunction->GetDriverGUID() != GEOMImpl_FillingDriver::GetID()) return NULL;
679 GEOMImpl_IFilling aCI (aFunction);
680 Handle(TColStd_HSequenceOfTransient) aConstraints = new TColStd_HSequenceOfTransient;
683 std::list<Handle(GEOM_Object)>::iterator it = theConstraints.begin();
684 while (it != theConstraints.end()) {
685 Handle(GEOM_Object) anObject = (*it);
686 if ( anObject.IsNull() || anObject->GetValue().ShapeType() != TopAbs_EDGE ) {
687 SetErrorCode("NULL argument edge for the face construction");
690 Handle(GEOM_Function) aRefSh = anObject->GetLastFunction();
691 aConstraints->Append(aRefSh);
693 if ( it != theConstraints.end() ) {
694 Handle(GEOM_Object) aFace = (*it);
695 if ( aFace.IsNull() ) {
696 // null constraint face - it is a valid case
700 if ( aFace->GetValue().ShapeType() != TopAbs_FACE )
701 // constraint face can be omitted - it is a valid case
703 // Keep the old error code as IsSubShapeBelongsTo changes it.
704 TCollection_AsciiString anOldCode = GetErrorCode();
706 if ( IsSubShapeBelongsTo( anObject, 0, aFace, 0 ) ) {
708 SetErrorCode(anOldCode);
709 aRefSh = aFace->GetLastFunction();
710 aConstraints->Append(aRefSh);
715 SetErrorCode("Face is NULL or not connected to the Edge");
720 aCI.SetShapes( aConstraints );
723 Standard_Boolean isWarning = Standard_False;
726 if (!GetSolver()->ComputeFunction(aFunction)) {
727 SetErrorCode("Shape driver failed");
731 catch (Standard_Failure) {
732 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
733 SetErrorCode(aFail->GetMessageString());
734 // to provide warning
735 if (!aFunction->GetValue().IsNull()) {
736 isWarning = Standard_True;
742 //Make a Python command
743 GEOM::TPythonDump pd (aFunction);
744 pd << aShape << " = geompy.MakeFaceWithConstraints([";
747 it = theConstraints.begin();
748 if (it != theConstraints.end() ) {
750 while (it != theConstraints.end()) {
751 Handle(GEOM_Object) anObject = (*it++);
752 if( !anObject.IsNull() )
753 pd << ", " << anObject;
758 // to provide warning
759 if (!isWarning) SetErrorCode(OK);
763 //=============================================================================
767 //=============================================================================
768 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
769 (std::list<Handle(GEOM_Object)> theShapes)
771 return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
774 //=============================================================================
778 //=============================================================================
779 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
780 (std::list<Handle(GEOM_Object)> theShapes)
782 return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
785 //=============================================================================
789 //=============================================================================
790 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
791 (std::list<Handle(GEOM_Object)> theShapes)
793 return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
796 //=============================================================================
800 //=============================================================================
801 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
802 (std::list<Handle(GEOM_Object)> theShapes,
803 const Standard_Integer theObjectType,
804 const Standard_Integer theFunctionType,
805 const TCollection_AsciiString& theMethodName)
810 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
813 Handle(GEOM_Function) aFunction =
814 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
815 if (aFunction.IsNull()) return NULL;
817 //Check if the function is set correctly
818 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
820 GEOMImpl_IShapes aCI (aFunction);
822 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
825 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
826 for (; it != theShapes.end(); it++) {
827 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
828 if (aRefSh.IsNull()) {
829 SetErrorCode("NULL argument shape for the shape construction");
832 aShapesSeq->Append(aRefSh);
834 aCI.SetShapes(aShapesSeq);
839 if (!GetSolver()->ComputeFunction(aFunction)) {
840 SetErrorCode("Shape driver failed");
844 catch (Standard_Failure) {
845 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
846 SetErrorCode(aFail->GetMessageString());
850 //Make a Python command
851 GEOM::TPythonDump pd (aFunction);
852 pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
855 it = theShapes.begin();
856 if (it != theShapes.end()) {
858 while (it != theShapes.end()) {
859 pd << ", " << (*it++);
868 //=============================================================================
870 * MakeSolidFromConnectedFaces
872 //=============================================================================
873 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidFromConnectedFaces
874 (std::list<Handle(GEOM_Object)> theFacesOrShells,
875 const Standard_Boolean isIntersect)
880 Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
883 Handle(GEOM_Function) aFunction =
884 aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_FACES);
885 if (aFunction.IsNull()) return NULL;
887 //Check if the function is set correctly
888 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
890 GEOMImpl_IShapes aCI (aFunction);
892 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
895 std::list<Handle(GEOM_Object)>::iterator it = theFacesOrShells.begin();
896 for (; it != theFacesOrShells.end(); it++) {
897 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
898 if (aRefSh.IsNull()) {
899 SetErrorCode("NULL argument shape for the shape construction");
902 aShapesSeq->Append(aRefSh);
904 aCI.SetShapes(aShapesSeq);
905 aCI.SetIsIntersect(isIntersect);
910 if (!GetSolver()->ComputeFunction(aFunction)) {
911 SetErrorCode("Shape driver failed");
915 catch (Standard_Failure) {
916 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
917 SetErrorCode(aFail->GetMessageString());
921 //Make a Python command
922 GEOM::TPythonDump pd (aFunction);
923 pd << aSolid << " = geompy.MakeSolidFromConnectedFaces([";
926 it = theFacesOrShells.begin();
927 if (it != theFacesOrShells.end()) {
929 while (it != theFacesOrShells.end()) {
930 pd << ", " << (*it++);
933 pd << "]," << (isIntersect ? "True" : "False") << ")";
939 //=============================================================================
943 //=============================================================================
945 GEOMImpl_IShapesOperations::MakeGlueFaces (std::list< Handle(GEOM_Object) >& theShapes,
946 const Standard_Real theTolerance,
947 const Standard_Boolean doKeepNonSolids)
951 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
952 if ( objects.IsNull() || objects->IsEmpty() ) {
953 SetErrorCode("NULL argument shape");
957 //Add a new Glued object
958 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
960 //Add a new Glue function
961 Handle(GEOM_Function) aFunction;
962 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
963 if (aFunction.IsNull()) return NULL;
965 //Check if the function is set correctly
966 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
968 GEOMImpl_IGlue aCI (aFunction);
970 aCI.SetBase( objects );
971 aCI.SetTolerance(theTolerance);
972 aCI.SetKeepNonSolids(doKeepNonSolids);
974 //Compute the sub-shape value
975 Standard_Boolean isWarning = Standard_False;
978 if (!GetSolver()->ComputeFunction(aFunction)) {
979 SetErrorCode("Shape driver failed to glue faces");
983 catch (Standard_Failure) {
984 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
985 SetErrorCode(aFail->GetMessageString());
986 // to provide warning
987 if (!aFunction->GetValue().IsNull()) {
988 isWarning = Standard_True;
994 //Make a Python command
995 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
996 << theShapes << ", " << theTolerance << ")";
998 // to provide warning
999 if (!isWarning) SetErrorCode(OK);
1003 //=============================================================================
1007 //=============================================================================
1009 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
1010 (Handle(GEOM_Object) theShape,
1011 const Standard_Real theTolerance)
1015 if (theShape.IsNull()) return NULL;
1016 TopoDS_Shape aShape = theShape->GetValue();
1017 if (aShape.IsNull()) return NULL;
1019 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1021 Standard_Integer iErr;
1023 GEOMAlgo_Gluer1 aGluer;
1024 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
1025 GEOMAlgo_CoupleOfShapes aCS;
1026 GEOMAlgo_ListOfCoupleOfShapes aLCS;
1028 //aGluer = new GEOMAlgo_Gluer1;
1029 aGluer.SetShape(aShape);
1030 aGluer.SetTolerance(theTolerance);
1032 iErr = aGluer.ErrorStatus();
1033 if (iErr) return NULL;
1035 TopTools_ListOfShape listShape;
1036 const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
1038 aItCS.Initialize(aLCSG);
1039 for (; aItCS.More(); aItCS.Next()) {
1040 const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
1041 listShape.Append(aCSG.Shape1());
1044 TopTools_ListIteratorOfListOfShape itSub (listShape);
1045 TCollection_AsciiString anAsciiList, anEntry;
1046 TopTools_IndexedMapOfShape anIndices;
1047 TopExp::MapShapes(aShape, anIndices);
1048 Handle(TColStd_HArray1OfInteger) anArray;
1049 Handle(GEOM_Object) anObj;
1050 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1051 TopoDS_Shape aValue = itSub.Value();
1052 anArray = new TColStd_HArray1OfInteger(1,1);
1053 anArray->SetValue(1, anIndices.FindIndex(aValue));
1054 anObj = GetEngine()->AddSubShape(theShape, anArray);
1055 if (!anObj.IsNull()) {
1056 aSeq->Append(anObj);
1058 // for python command
1059 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1060 anAsciiList += anEntry;
1065 //Make a Python command
1066 if( anAsciiList.Length() > 0 ) {
1067 anAsciiList.Trunc(anAsciiList.Length() - 1);
1068 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1069 GEOM::TPythonDump pd (aFunction, true);
1070 pd << "[" << anAsciiList.ToCString();
1071 pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
1080 //=============================================================================
1082 * MakeGlueFacesByList
1084 //=============================================================================
1086 GEOMImpl_IShapesOperations::MakeGlueFacesByList(std::list< Handle(GEOM_Object) >& theShapes,
1087 const Standard_Real theTolerance,
1088 std::list<Handle(GEOM_Object)> & theFaces,
1089 const Standard_Boolean doKeepNonSolids,
1090 const Standard_Boolean doGlueAllEdges)
1094 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1095 if ( objects.IsNull() || objects->IsEmpty() ) {
1096 SetErrorCode("NULL argument shape");
1099 Handle(TColStd_HSequenceOfTransient) aFaces = GEOM_Object::GetLastFunctions( theFaces );
1100 if ( aFaces.IsNull() ) {
1101 SetErrorCode("NULL argument shape for the shape construction");
1105 //Add a new Glued object
1106 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
1108 //Add a new Glue function
1109 Handle(GEOM_Function) aFunction;
1110 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
1111 if (aFunction.IsNull()) return NULL;
1113 //Check if the function is set correctly
1114 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1116 GEOMImpl_IGlue aCI (aFunction);
1118 aCI.SetBase( objects );
1119 aCI.SetTolerance(theTolerance);
1120 aCI.SetKeepNonSolids(doKeepNonSolids);
1121 aCI.SetGlueAllEdges(doGlueAllEdges);
1122 aCI.SetFaces(aFaces);
1124 //Compute the sub-shape value
1125 Standard_Boolean isWarning = Standard_False;
1128 if (!GetSolver()->ComputeFunction(aFunction)) {
1129 SetErrorCode("Shape driver failed to glue faces");
1133 catch (Standard_Failure) {
1134 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1135 SetErrorCode(aFail->GetMessageString());
1136 // to provide warning
1137 if (!aFunction->GetValue().IsNull()) {
1138 isWarning = Standard_True;
1144 //Make a Python command
1146 GEOM::TPythonDump pd(aFunction);
1147 pd << aGlued << " = geompy.MakeGlueFacesByList("
1148 << theShapes << ", " << theTolerance << ", " << theFaces << ", "
1149 << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")";
1151 // to provide warning
1152 if (!isWarning) SetErrorCode(OK);
1156 //=============================================================================
1160 //=============================================================================
1162 GEOMImpl_IShapesOperations::MakeGlueEdges (std::list< Handle(GEOM_Object) >& theShapes,
1163 const Standard_Real theTolerance)
1167 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1168 if ( objects.IsNull() || objects->IsEmpty() ) {
1169 SetErrorCode("NULL argument shape");
1173 //Add a new Glued object
1174 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
1176 //Add a new Glue function
1177 Handle(GEOM_Function) aFunction;
1178 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES);
1179 if (aFunction.IsNull()) return NULL;
1181 //Check if the function is set correctly
1182 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1184 GEOMImpl_IGlue aCI (aFunction);
1186 aCI.SetBase( objects );
1187 aCI.SetTolerance(theTolerance);
1188 aCI.SetKeepNonSolids(true);
1190 //Compute the sub-shape value
1191 Standard_Boolean isWarning = Standard_False;
1194 if (!GetSolver()->ComputeFunction(aFunction)) {
1195 SetErrorCode("Shape driver failed to glue edges");
1199 catch (Standard_Failure) {
1200 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1201 SetErrorCode(aFail->GetMessageString());
1202 // to provide warning
1203 if (!aFunction->GetValue().IsNull()) {
1204 isWarning = Standard_True;
1210 //Make a Python command
1211 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueEdges("
1212 << theShapes << ", " << theTolerance << ")";
1214 // to provide warning
1215 if (!isWarning) SetErrorCode(OK);
1219 //=============================================================================
1223 //=============================================================================
1224 Handle(TColStd_HSequenceOfTransient)
1225 GEOMImpl_IShapesOperations::GetGlueShapes (std::list< Handle(GEOM_Object) >& theShapes,
1226 const Standard_Real theTolerance,
1227 const TopAbs_ShapeEnum theType)
1231 TopoDS_Shape aShape;
1232 TopTools_SequenceOfShape shapes;
1233 std::list< Handle(GEOM_Object) >::iterator s = theShapes.begin();
1234 Handle(GEOM_Object) lastCreatedGO;
1235 for ( ; s != theShapes.end(); ++s )
1237 Handle(GEOM_Object) go = *s;
1238 if ( go.IsNull() ) return NULL;
1239 aShape = go->GetValue();
1240 if ( aShape.IsNull() ) return NULL;
1241 shapes.Append( aShape );
1242 lastCreatedGO = GEOM::GetCreatedLast( lastCreatedGO, go );
1244 if ( shapes.Length() > 1 )
1246 TopoDS_Compound compound;
1247 BRep_Builder builder;
1248 builder.MakeCompound( compound );
1249 for ( int i = 1; i <= shapes.Length(); ++i )
1250 builder.Add( compound, shapes( i ) );
1255 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1257 GEOMAlgo_GlueDetector aGluer;
1258 aGluer.SetArgument(aShape);
1259 aGluer.SetTolerance(theTolerance);
1261 Standard_Integer iErr = aGluer.ErrorStatus();
1262 if (iErr) return NULL;
1264 std::vector< TopTools_IndexedMapOfShape* > anIndices( shapes.Length(), NULL );
1265 Handle(TColStd_HArray1OfInteger) anArray;
1266 Handle(GEOM_Object) anObj;
1268 TopTools_ListOfShape listOnePerSet;
1270 const TopTools_DataMapOfShapeListOfShape& aImages = aGluer.Images();
1271 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS (aImages);
1272 for (int index = 1; aItDMSLS.More(); aItDMSLS.Next(), ++index) {
1274 //const TopoDS_Shape& aSkey = aItDMSLS.Key();
1276 // list of shapes of the argument that can be glued
1277 const TopTools_ListOfShape& aLSD = aItDMSLS.Value();
1279 //listShape.Append(aLSD.First());
1280 TopoDS_Shape aValue = aLSD.First();
1282 if (aValue.ShapeType() == theType) {
1283 listOnePerSet.Append(aValue);
1287 // for stable order of returned entities
1288 GEOMUtils::SortShapes(listOnePerSet, Standard_False);
1290 TopTools_ListIteratorOfListOfShape aListIt (listOnePerSet);
1291 for (; aListIt.More(); aListIt.Next())
1293 TopoDS_Shape aValue = aListIt.Value();
1294 // find a shape to add aValue as a sub-shape
1296 s = theShapes.begin();
1297 for ( int i = 0; i < shapes.Length(); ++i, ++s )
1299 Handle(GEOM_Object) object = *s;
1300 if ( !anIndices[i] ) {
1301 anIndices[i] = new TopTools_IndexedMapOfShape;
1302 TopExp::MapShapes( object->GetValue(), *anIndices[i]);
1304 if (int index = anIndices[i]->FindIndex( aValue )) {
1305 anArray = new TColStd_HArray1OfInteger(1,1);
1306 anArray->SetValue(1, index);
1307 anObj = GetEngine()->AddSubShape( object, anArray);
1311 if (!anObj.IsNull())
1312 aSeq->Append(anObj);
1314 for ( size_t i = 0 ; i < anIndices.size(); ++i )
1315 delete anIndices[i];
1317 // Make a Python command
1318 if ( aSeq->Length() > 0)
1320 Handle(GEOM_Function) aFunction = lastCreatedGO->GetLastFunction();
1321 GEOM::TPythonDump pd (aFunction, /*append=*/true);
1323 << " = geompy." << (theType == TopAbs_FACE ? "GetGlueFaces" : "GetGlueEdges" )
1324 << "( " << theShapes << ", " << theTolerance << ")";
1332 //=============================================================================
1334 * MakeGlueEdgesByList
1336 //=============================================================================
1338 GEOMImpl_IShapesOperations::MakeGlueEdgesByList (std::list< Handle(GEOM_Object) >& theShapes,
1339 const Standard_Real theTolerance,
1340 std::list<Handle(GEOM_Object)>& theEdges)
1344 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1345 if ( objects.IsNull() || objects->IsEmpty() ) {
1346 SetErrorCode("NULL argument shape");
1349 Handle(TColStd_HSequenceOfTransient) anEdges = GEOM_Object::GetLastFunctions( theEdges );
1350 if ( anEdges.IsNull() ) {
1351 SetErrorCode("NULL argument shape for the shape construction");
1354 //Add a new Glued object
1355 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
1357 //Add a new Glue function
1358 Handle(GEOM_Function) aFunction;
1359 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES_BY_LIST);
1360 if (aFunction.IsNull()) return NULL;
1362 //Check if the function is set correctly
1363 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1365 GEOMImpl_IGlue aCI (aFunction);
1367 aCI.SetBase( objects );
1368 aCI.SetTolerance(theTolerance);
1369 aCI.SetKeepNonSolids(true);
1370 aCI.SetFaces(anEdges);
1372 //Compute the sub-shape value
1373 Standard_Boolean isWarning = Standard_False;
1376 if (!GetSolver()->ComputeFunction(aFunction)) {
1377 SetErrorCode("Shape driver failed to glue edges");
1381 catch (Standard_Failure) {
1382 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1383 SetErrorCode(aFail->GetMessageString());
1384 // to provide warning
1385 if (!aFunction->GetValue().IsNull()) {
1386 isWarning = Standard_True;
1392 //Make a Python command
1394 GEOM::TPythonDump pd (aFunction);
1395 pd << aGlued << " = geompy.MakeGlueEdgesByList("
1396 << theShapes << ", " << theTolerance << ", " << theEdges << " )";
1398 // to provide warning
1399 if (!isWarning) SetErrorCode(OK);
1403 //=============================================================================
1405 * GetExistingSubObjects
1407 //=============================================================================
1408 Handle(TColStd_HSequenceOfTransient)
1409 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape,
1410 const Standard_Boolean theGroupsOnly)
1412 // note: this method does not return fields
1414 Standard_Integer types = theGroupsOnly ? Groups : Groups|SubShapes;
1415 Handle(TColStd_HSequenceOfTransient) results = GetExistingSubObjects(theShape, types);
1417 if (results->Length() > 0) {
1418 //Make a Python command
1419 TCollection_AsciiString anAsciiList;
1420 for (int i = 1; i <= results->Length(); i++)
1422 Handle(GEOM_BaseObject) obj = Handle(GEOM_BaseObject)::DownCast( results->Value(i));
1423 obj->GetEntryString();
1424 if ( i < results->Length() )
1428 GEOM::TPythonDump pd (theShape->GetLastFunction(), /*append=*/true);
1429 pd << "[" << anAsciiList.ToCString();
1430 pd << "] = geompy.GetExistingSubObjects(";
1431 pd << theShape << ", " << (bool)theGroupsOnly << ")";
1437 Handle(TColStd_HSequenceOfTransient)
1438 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape,
1439 const Standard_Integer theTypes)
1443 if (theShape.IsNull()) return NULL;
1445 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1446 if (aMainShape.IsNull()) return NULL;
1448 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1449 SetErrorCode(NOT_FOUND_ANY);
1451 if (!aMainShape->HasSubShapeReferences()) return aSeq;
1452 const TDataStd_ListOfExtendedString& aListEntries = aMainShape->GetSubShapeReferences();
1453 if (aListEntries.IsEmpty()) return aSeq;
1457 TDataStd_ListIteratorOfListOfExtendedString anIt (aListEntries);
1458 for (; anIt.More(); anIt.Next()) {
1459 TCollection_ExtendedString anEntry = anIt.Value();
1460 Standard_Integer aStrLen = anEntry.LengthOfCString();
1461 char* anEntryStr = new char[aStrLen+1];
1462 anEntry.ToUTF8CString(anEntryStr);
1463 Handle(GEOM_BaseObject) anObj = GetEngine()->GetObject(GetDocID(), anEntryStr, false);
1464 if (!anObj.IsNull() ) {
1465 bool isGroup = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() == GEOM_GROUP;
1466 bool isSubShape = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() != GEOM_GROUP;
1467 bool isField = anObj->IsKind(STANDARD_TYPE(GEOM_Field));
1468 if (theTypes & Groups && isGroup ||
1469 theTypes & SubShapes && isSubShape ||
1470 theTypes & Fields && isField) {
1471 aSeq->Append(anObj);
1474 delete [] anEntryStr;
1477 if (aSeq->Length() == 0) {
1478 SetErrorCode(NOT_FOUND_ANY);
1487 //=============================================================================
1491 //=============================================================================
1492 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
1493 (Handle(GEOM_Object) theShape,
1494 const Standard_Integer theShapeType,
1495 const Standard_Boolean isSorted,
1496 const ExplodeType theExplodeType)
1500 if (theShape.IsNull()) return NULL;
1501 TopoDS_Shape aShape = theShape->GetValue();
1502 if (aShape.IsNull()) return NULL;
1504 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1506 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1507 Handle(GEOM_Object) anObj;
1508 TopTools_MapOfShape mapShape;
1509 TopTools_ListOfShape listShape;
1511 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1512 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1514 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1515 for (; It.More(); It.Next()) {
1516 TopoDS_Shape SS = It.Value();
1517 if (mapShape.Add(SS)) {
1518 if (theShapeType == TopAbs_FLAT) {
1519 AddFlatSubShapes(SS, listShape, mapShape);
1521 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1522 listShape.Append(SS);
1524 // VSR: for EXPLODE_NEW_INCLUDE_MAIN and EXPLODE_OLD_INCLUDE_MAIN:
1525 // it seems it is necessary to add top-level shape if theShapeType == TopAbs_COMPOUND
1529 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1531 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1532 for (; exp.More(); exp.Next())
1533 if (mapShape.Add(exp.Current()))
1534 listShape.Append(exp.Current());
1537 if (listShape.IsEmpty()){
1538 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1539 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1544 bool isOldSorting = false;
1545 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1546 isOldSorting = true;
1547 GEOMUtils::SortShapes(listShape, isOldSorting);
1550 TopTools_IndexedMapOfShape anIndices;
1551 TopExp::MapShapes(aShape, anIndices);
1552 Handle(TColStd_HArray1OfInteger) anArray;
1554 TopTools_ListIteratorOfListOfShape itSub (listShape);
1555 TCollection_AsciiString anAsciiList, anEntry;
1556 for (int index = 1; itSub.More(); itSub.Next(), ++index)
1558 TopoDS_Shape aValue = itSub.Value();
1559 anArray = new TColStd_HArray1OfInteger(1,1);
1560 anArray->SetValue(1, anIndices.FindIndex(aValue));
1562 //anObj = GetEngine()->AddSubShape(theShape, anArray);
1564 anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1565 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1566 if (aFunction.IsNull()) return aSeq;
1568 GEOM_ISubShape aSSI (aFunction);
1569 aSSI.SetMainShape(aMainShape);
1570 aSSI.SetIndices(anArray);
1572 // Set function value directly, as we know it.
1573 // Usage of Solver here would lead to significant loss of time,
1574 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1575 // on the main shape for each being calculated sub-shape separately.
1576 aFunction->SetValue(aValue);
1578 // Put this subshape in the list of sub-shapes of theMainShape
1579 aMainShape->AddSubShapeReference(aFunction);
1581 if (!anObj.IsNull()) {
1582 aSeq->Append(anObj);
1584 // for python command
1585 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1586 anAsciiList += anEntry;
1591 //Make a Python command
1592 anAsciiList.Trunc(anAsciiList.Length() - 1);
1594 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1595 pd << "[" << anAsciiList.ToCString() << "] = geompy.";
1596 switch (theExplodeType) {
1597 case EXPLODE_NEW_EXCLUDE_MAIN:
1598 pd << "ExtractShapes(" << theShape << ", "
1599 << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")";
1601 case EXPLODE_NEW_INCLUDE_MAIN:
1602 pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(")
1603 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1605 case EXPLODE_OLD_INCLUDE_MAIN:
1606 pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(")
1607 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1616 //=============================================================================
1620 //=============================================================================
1621 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
1622 (Handle(GEOM_Object) theShape,
1623 const Standard_Integer theShapeType,
1624 const Standard_Boolean isSorted,
1625 const ExplodeType theExplodeType)
1629 if (theShape.IsNull()) return NULL;
1630 TopoDS_Shape aShape = theShape->GetValue();
1631 if (aShape.IsNull()) return NULL;
1633 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1634 TopTools_MapOfShape mapShape;
1635 TopTools_ListOfShape listShape;
1637 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1638 (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1640 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1641 for (; It.More(); It.Next()) {
1642 TopoDS_Shape SS = It.Value();
1643 if (mapShape.Add(SS)) {
1644 if (theShapeType == TopAbs_FLAT) {
1645 AddFlatSubShapes(SS, listShape, mapShape);
1647 else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1648 listShape.Append(SS);
1653 else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1655 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1656 for (; exp.More(); exp.Next())
1657 if (mapShape.Add(exp.Current()))
1658 listShape.Append(exp.Current());
1661 if (listShape.IsEmpty()) {
1662 //SetErrorCode("The given shape has no sub-shapes of the requested type");
1663 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1668 bool isOldSorting = false;
1669 if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1670 isOldSorting = true;
1671 GEOMUtils::SortShapes(listShape, isOldSorting);
1674 TopTools_IndexedMapOfShape anIndices;
1675 TopExp::MapShapes(aShape, anIndices);
1676 Handle(TColStd_HArray1OfInteger) anArray;
1678 TopTools_ListIteratorOfListOfShape itSub (listShape);
1679 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1680 TopoDS_Shape aValue = itSub.Value();
1681 aSeq->Append(anIndices.FindIndex(aValue));
1684 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1686 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
1687 #ifdef DUMP_SUBSHAPE_IDS
1688 //Make a Python command
1689 GEOM::TPythonDump pd (aFunction, /*append=*/true);
1690 pd << "listSubShapeIDs = geompy.SubShapeAll";
1691 switch (theExplodeType) {
1692 case EXPLODE_NEW_EXCLUDE_MAIN:
1694 case EXPLODE_NEW_INCLUDE_MAIN:
1695 pd << (isSorted ? "SortedCentresIDs(" : "IDs(")
1696 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1698 case EXPLODE_OLD_INCLUDE_MAIN:
1699 pd << (isSorted ? "SortedIDs(" : "IDs(")
1700 << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1704 #endif // DUMP_SUBSHAPE_IDS
1710 //=============================================================================
1714 //=============================================================================
1715 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
1716 (Handle(GEOM_Object) theMainShape,
1717 const Standard_Integer theID)
1721 if (theMainShape.IsNull()) return NULL;
1723 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1724 anArray->SetValue(1, theID);
1725 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
1726 if (anObj.IsNull()) {
1727 SetErrorCode("Can not get a sub-shape with the given ID");
1731 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1733 //Make a Python command
1734 GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1735 << theMainShape << ", [" << theID << "])";
1741 //=============================================================================
1745 //=============================================================================
1746 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes
1747 (Handle(GEOM_Object) theMainShape,
1748 Handle(TColStd_HArray1OfInteger) theIndices)
1752 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1754 if (!theIndices->Length()) {
1755 SetErrorCode(NOT_FOUND_ANY);
1759 if (theMainShape.IsNull()) return NULL;
1760 TopoDS_Shape aShape = theMainShape->GetValue();
1761 if (aShape.IsNull()) return NULL;
1763 Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
1765 TopTools_IndexedMapOfShape anIndices;
1766 TopExp::MapShapes(aShape, anIndices);
1768 Handle(TColStd_HArray1OfInteger) anArray;
1769 Handle(GEOM_Object) anObj;
1771 TCollection_AsciiString anAsciiList, anEntry;
1772 Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper();
1773 for (i = low; i <= up; i++) {
1774 int id = theIndices->Value(i);
1775 if (1 <= id && id <= anIndices.Extent()) {
1776 TopoDS_Shape aValue = anIndices.FindKey(id);
1777 anArray = new TColStd_HArray1OfInteger(1,1);
1778 anArray->SetValue(1, id);
1780 anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1781 if (!anObj.IsNull()) {
1782 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1783 if (aFunction.IsNull()) return aSeq;
1785 GEOM_ISubShape aSSI (aFunction);
1786 aSSI.SetMainShape(aMainShape);
1787 aSSI.SetIndices(anArray);
1789 // Set function value directly, as we know it.
1790 // Usage of Solver here would lead to significant loss of time,
1791 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1792 // on the main shape for each being calculated sub-shape separately.
1793 aFunction->SetValue(aValue);
1795 // Put this sub-shape in the list of sub-shapes of theMainShape
1796 aMainShape->AddSubShapeReference(aFunction);
1798 aSeq->Append(anObj);
1800 // for python command
1801 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1802 anAsciiList += anEntry;
1808 //Make a Python command
1809 anAsciiList.Trunc(anAsciiList.Length() - 1);
1811 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1812 pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes("
1813 << theMainShape << ", [" ;
1814 for (i = low; i <= up - 1; i++) {
1815 pd << theIndices->Value(i) << ", ";
1817 pd << theIndices->Value(up) << "])";
1824 //=============================================================================
1828 //=============================================================================
1829 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1830 Handle(GEOM_Object) theSubShape)
1834 TopoDS_Shape aMainShape = theMainShape->GetValue();
1835 TopoDS_Shape aSubShape = theSubShape->GetValue();
1837 if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1839 TopTools_IndexedMapOfShape anIndices;
1840 TopExp::MapShapes(aMainShape, anIndices);
1841 // if (anIndices.Contains(aSubShape)) {
1842 // SetErrorCode(OK);
1843 // return anIndices.FindIndex(aSubShape);
1845 int id = anIndices.FindIndex(aSubShape);
1856 //=============================================================================
1858 * GetSubShapeIndices
1860 //=============================================================================
1861 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSubShapesIndices (Handle(GEOM_Object) theMainShape,
1862 std::list<Handle(GEOM_Object)> theSubShapes)
1864 MESSAGE("GEOMImpl_IShapesOperations::GetSubShapesIndices")
1867 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1869 TopoDS_Shape aMainShape = theMainShape->GetValue();
1870 if (aMainShape.IsNull())
1872 MESSAGE("NULL main shape")
1876 TopTools_IndexedMapOfShape anIndices;
1877 TopExp::MapShapes(aMainShape, anIndices);
1879 std::list<Handle(GEOM_Object)>::iterator it;
1880 for (it=theSubShapes.begin(); it != theSubShapes.end(); ++it)
1882 TopoDS_Shape aSubShape = (*it)->GetValue();
1883 if (aSubShape.IsNull())
1885 MESSAGE("NULL subshape")
1888 int id = anIndices.FindIndex(aSubShape);
1897 //=============================================================================
1901 //=============================================================================
1902 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1903 Handle(GEOM_Object) theSubShape)
1907 TopoDS_Shape aMainShape = theMainShape->GetValue();
1908 TopoDS_Shape aSubShape = theSubShape->GetValue();
1910 if (aMainShape.IsNull() || aSubShape.IsNull()) {
1911 SetErrorCode("Null argument shape given");
1916 if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1918 TopTools_ListOfShape CL;
1919 CL.Append(aMainShape);
1920 TopTools_ListIteratorOfListOfShape itC;
1921 for (itC.Initialize(CL); itC.More(); itC.Next()) {
1922 for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1923 if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1924 if (it.Value().IsSame(aSubShape))
1928 CL.Append(it.Value());
1933 TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1934 TopTools_MapOfShape M;
1935 for (; anExp.More(); anExp.Next()) {
1936 if (M.Add(anExp.Current())) {
1937 if (anExp.Current().IsSame(aSubShape))
1944 SetErrorCode("The sub-shape does not belong to the main shape");
1948 //=============================================================================
1950 * GetShapeTypeString
1952 //=============================================================================
1953 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1957 TCollection_AsciiString aTypeName ("Null Shape");
1959 TopoDS_Shape aShape = theShape->GetValue();
1960 if (aShape.IsNull())
1963 switch (aShape.ShapeType() )
1965 case TopAbs_COMPOUND:
1966 aTypeName = "Compound";
1968 case TopAbs_COMPSOLID:
1969 aTypeName = "Compound Solid";
1972 aTypeName = "Solid";
1975 aTypeName = "Shell";
1979 BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1980 if (surf.GetType() == GeomAbs_Plane)
1981 aTypeName = "Plane";
1982 else if (surf.GetType() == GeomAbs_Cylinder)
1983 aTypeName = "Cylindrical Face";
1984 else if (surf.GetType() == GeomAbs_Sphere)
1985 aTypeName = "Spherical Face";
1986 else if (surf.GetType() == GeomAbs_Torus)
1987 aTypeName = "Toroidal Face";
1988 else if (surf.GetType() == GeomAbs_Cone)
1989 aTypeName = "Conical Face";
1991 aTypeName = "GEOM::FACE";
1999 BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
2000 if (curv.GetType() == GeomAbs_Line) {
2001 if ((Abs(curv.FirstParameter()) >= 1E6) ||
2002 (Abs(curv.LastParameter()) >= 1E6))
2006 } else if (curv.GetType() == GeomAbs_Circle) {
2007 if (curv.IsClosed())
2008 aTypeName = "Circle";
2017 aTypeName = "Vertex";
2020 aTypeName = "Shape";
2023 aTypeName = "Shape of unknown type";
2029 //=============================================================================
2031 * IsSubShapeBelongsTo
2033 //=============================================================================
2034 Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject,
2035 const Standard_Integer theSubObjectIndex,
2036 Handle(GEOM_Object) theObject,
2037 const Standard_Integer theObjectIndex)
2041 if ( theObject.IsNull() || theSubObject.IsNull() )
2044 TopoDS_Shape shape = theObject->GetValue();
2045 TopoDS_Shape subShape = theSubObject->GetValue();
2047 if ( shape.IsNull() || subShape.IsNull() )
2050 TopTools_IndexedMapOfShape anIndices;
2051 if ( theObjectIndex > 0 ) {
2052 TopExp::MapShapes( shape, anIndices );
2053 shape = anIndices.FindKey(theObjectIndex);
2055 if ( theSubObjectIndex > 0 ) {
2056 TopExp::MapShapes( subShape, anIndices );
2057 subShape = anIndices.FindKey(theSubObjectIndex);
2060 TopExp::MapShapes( shape, anIndices );
2062 const Standard_Boolean isBelongTo = anIndices.Contains(subShape);
2069 //=============================================================================
2073 //=============================================================================
2074 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
2075 (Handle(GEOM_Object) theShape,
2076 const Standard_Integer theShapeType)
2079 Standard_Integer nbShapes = 0;
2081 if (theShape.IsNull()) return -1;
2082 TopoDS_Shape aShape = theShape->GetValue();
2083 if (aShape.IsNull()) return -1;
2086 TopTools_MapOfShape mapShape;
2088 if (aShape.ShapeType() == TopAbs_COMPOUND &&
2089 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2090 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
2091 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
2092 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
2093 for (; It.More(); It.Next()) {
2094 if (mapShape.Add(It.Value())) {
2095 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2096 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
2102 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
2103 for (; exp.More(); exp.Next())
2104 if (mapShape.Add(exp.Current()))
2110 if (theShapeType == TopAbs_FLAT) {
2111 TopTools_MapOfShape aMapOfShape;
2112 TopTools_ListOfShape aListOfShape;
2113 AddFlatSubShapes(aShape, aListOfShape, aMapOfShape);
2114 nbShapes = aListOfShape.Extent();
2118 int iType, nbTypes [TopAbs_SHAPE];
2119 for (iType = 0; iType < TopAbs_SHAPE; ++iType)
2121 nbTypes[aShape.ShapeType()]++;
2123 TopTools_MapOfShape aMapOfShape;
2124 aMapOfShape.Add(aShape);
2125 TopTools_ListOfShape aListOfShape;
2126 aListOfShape.Append(aShape);
2128 TopTools_ListIteratorOfListOfShape itL (aListOfShape);
2129 for (; itL.More(); itL.Next()) {
2130 TopoDS_Iterator it (itL.Value());
2131 for (; it.More(); it.Next()) {
2132 TopoDS_Shape s = it.Value();
2133 if (aMapOfShape.Add(s)) {
2134 aListOfShape.Append(s);
2135 nbTypes[s.ShapeType()]++;
2140 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
2141 nbShapes = aMapOfShape.Extent();
2143 nbShapes = nbTypes[theShapeType];
2146 catch (Standard_Failure) {
2147 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2148 SetErrorCode(aFail->GetMessageString());
2156 //=============================================================================
2160 //=============================================================================
2161 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
2165 if (theShape.IsNull()) return NULL;
2168 //Add a new reversed object
2169 Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
2171 //Add a new Revese function
2172 Handle(GEOM_Function) aFunction;
2173 aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
2174 if (aFunction.IsNull()) return NULL;
2176 //Check if the function is set correctly
2177 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
2179 GEOMImpl_IShapes aSI (aFunction);
2181 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2182 if (aRefShape.IsNull()) return NULL;
2184 aSI.SetBase(aRefShape);
2186 //Compute the sub-shape value
2189 if (!GetSolver()->ComputeFunction(aFunction)) {
2190 SetErrorCode("Shape driver failed to reverse shape");
2194 catch (Standard_Failure) {
2195 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2196 SetErrorCode(aFail->GetMessageString());
2200 //Make a Python command
2201 GEOM::TPythonDump(aFunction) << aReversed
2202 << " = geompy.ChangeOrientation(" << theShape << ")";
2207 Handle(GEOM_Object) aReversed;
2209 GEOM_Engine* anEngine = GetEngine();
2210 //GEOMImpl_Gen* aGen = dynamic_cast<GEOMImpl_Gen*>(anEngine);
2211 GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine;
2214 GEOMImpl_IHealingOperations* anIHealingOperations =
2215 aGen->GetIHealingOperations(GetDocID());
2216 aReversed = anIHealingOperations->ChangeOrientationCopy(theShape);
2217 SetErrorCode(anIHealingOperations->GetErrorCode());
2223 //=============================================================================
2227 //=============================================================================
2228 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
2229 (Handle(GEOM_Object) theShape)
2233 if (theShape.IsNull()) return NULL;
2234 TopoDS_Shape aShape = theShape->GetValue();
2235 if (aShape.IsNull()) return NULL;
2237 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
2239 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2240 GEOMImpl_Block6Explorer::MapShapesAndAncestors
2241 (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2243 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2246 SetErrorCode("The given shape has no faces");
2250 TopTools_IndexedMapOfShape anIndices;
2251 TopExp::MapShapes(aShape, anIndices);
2253 Standard_Integer id;
2254 for (; ind <= nbFaces; ind++) {
2255 if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
2256 id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
2261 //The explode doesn't change object so no new function is required.
2262 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
2264 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2265 #ifdef DUMP_SUBSHAPE_IDS
2266 //Make a Python command
2267 GEOM::TPythonDump(aFunction, /*append=*/true)
2268 << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
2269 #endif // DUMP_SUBSHAPE_IDS
2275 //=======================================================================
2276 //function : GetSharedShapes
2278 //=======================================================================
2279 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2280 (Handle(GEOM_Object) theShape1,
2281 Handle(GEOM_Object) theShape2,
2282 const Standard_Integer theShapeType)
2286 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
2288 TopoDS_Shape aShape1 = theShape1->GetValue();
2289 TopoDS_Shape aShape2 = theShape2->GetValue();
2291 if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
2293 TopTools_IndexedMapOfShape anIndices;
2294 TopExp::MapShapes(aShape1, anIndices);
2295 Handle(TColStd_HArray1OfInteger) anArray;
2297 TopTools_IndexedMapOfShape mapShape1;
2298 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
2300 Handle(GEOM_Object) anObj;
2301 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2302 TCollection_AsciiString anAsciiList, anEntry;
2304 TopTools_MapOfShape mapShape2;
2305 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2306 for (; exp.More(); exp.Next()) {
2307 TopoDS_Shape aSS = exp.Current();
2308 if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
2309 anArray = new TColStd_HArray1OfInteger(1,1);
2310 anArray->SetValue(1, anIndices.FindIndex(aSS));
2311 anObj = GetEngine()->AddSubShape(theShape1, anArray);
2312 aSeq->Append(anObj);
2314 // for python command
2315 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2316 anAsciiList += anEntry;
2321 if (aSeq->IsEmpty()) {
2322 SetErrorCode(NOT_FOUND_ANY);
2326 //Make a Python command
2327 anAsciiList.Trunc(anAsciiList.Length() - 1);
2329 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2331 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2332 << "] = geompy.GetSharedShapes(" << theShape1 << ", "
2333 << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
2339 //=======================================================================
2340 //function : GetSharedShapes
2343 // NOTE on the implementation
2345 // 1) Resulting sub-shapes are published as a children of the 1st input shape
2346 // from theShapes list. Due to this reason only direct sub-shapes of the 1st
2347 // shape can be contained in the result of the operation (i.e. shares between
2348 // 2nd/3rd, etc couples cannot be retrieved.
2349 // 2) An exception from above case is when a single compound is specified as an
2350 // input. In this case we search shares between its top-level content, so we
2351 // are able to search shares between all possible couples of shapes.
2352 // 3) Parameter theMultiShare controls what types of shares to search:
2353 // - True: get sub-shapes that are shared between ALL input shapes;
2354 // - False: get shares between couples of input sub-shapes (see points 1 and 2).
2356 // Thus, we have the following cases:
2357 // [1] theShapes = N shapes (N>1), theMultiShare = True
2358 // Result: sub-shapes that are shared by all theShapes
2359 // [2] theShapes = N shapes (N>1), theMultiShare = False
2360 // Result: sub-shapes of 1st shape from theShapes that are shared with any shape
2362 // [3] theShapes = 1 shape, theMultiShare = True
2363 // Result: sub-shapes that are shared by all top-level sub-objects of theShapes[0]
2364 // [4] theShapes = 1 shape, theMultiShare = False
2365 // Result: sub-shapes of all possible couples of all top-level sub-objects of
2367 //=======================================================================
2368 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2369 (std::list<Handle(GEOM_Object)> & theShapes,
2370 const Standard_Integer theShapeType,
2371 const bool theMultiShare)
2375 int aLen = theShapes.size();
2376 if (aLen < 1) return NULL;
2378 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
2380 // main object is always first in the input list
2381 // it is the object from which sub-shapes indices are taken
2382 // and where results are published
2383 Handle(GEOM_Object) aMainObj = *it;
2384 Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
2386 // collect all shapes from the input list (including first one) for processing
2387 TopTools_SequenceOfShape shapeSeq;
2388 for (; it != theShapes.end(); it++) {
2389 Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
2390 if (aRefShape.IsNull()) {
2391 SetErrorCode("NULL shape for GetSharedShapes");
2394 TopoDS_Shape aShape = aRefShape->GetValue();
2395 if (aShape.IsNull()) {
2396 SetErrorCode("NULL shape for GetSharedShapes");
2399 shapeSeq.Append( aShape );
2402 // if only single shape is specified as input
2403 // collect all ites top-level sub-shapes for processing
2404 if ( shapeSeq.Length() == 1 )
2406 TopoDS_Shape aShape = shapeSeq.First();
2408 for ( TopoDS_Iterator it( aShape ); it.More(); it.Next() )
2409 shapeSeq.Append( it.Value() );
2412 // map all sub-shapes in a main shape to their indices
2413 TopTools_IndexedMapOfShape anIndices;
2414 TopExp::MapShapes(aMainShape->GetValue(), anIndices);
2415 TopTools_MapOfShape mapShape;
2417 // find shared shapes
2419 // here we will collect all shares
2420 TopTools_ListOfShape aShared;
2422 // number of iterations
2423 int nbIters = theMultiShare || theShapes.size() > 1 ? 1 : shapeSeq.Length()-1;
2424 // numShares factor to search (i.e. by what nb of shapes each found sub-shape should be shared)
2425 int nbShares = theMultiShare ? shapeSeq.Length()-1 : 1;
2427 for ( int iter = 1; iter <= nbIters; iter++) {
2428 for ( int ind = iter+1; ind <= shapeSeq.Length(); ind++) {
2429 if ( ind-1+nbShares > shapeSeq.Length() ) break;
2430 TopoDS_Compound aCurrSelection;
2431 TopoDS_Shape aShape1 = shapeSeq.Value( iter );
2432 TopTools_IndexedMapOfShape mapSelected;
2433 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
2434 for ( int s = 0; s < nbShares; s++ ) {
2436 TopoDS_Compound aCompound;
2437 B.MakeCompound(aCompound);
2438 const TopoDS_Shape& aShape2 = shapeSeq.Value( ind+s );
2439 TopTools_MapOfShape mapShape2;
2440 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2441 for (; exp.More(); exp.Next()) {
2442 const TopoDS_Shape& aSS = exp.Current();
2443 if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
2444 B.Add(aCompound, aSS);
2447 mapSelected.Clear();
2448 aCurrSelection = aCompound;
2449 TopExp::MapShapes(aCurrSelection, TopAbs_ShapeEnum(theShapeType), mapSelected);
2451 TopoDS_Iterator itSel(aCurrSelection, Standard_True, Standard_True);
2452 for (; itSel.More(); itSel.Next()) {
2453 const TopoDS_Shape& aSS = itSel.Value();
2454 if (mapShape.Add(aSS) )
2455 aShared.Append(aSS);
2460 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2462 if (aShared.IsEmpty()){
2463 SetErrorCode(NOT_FOUND_ANY);
2467 // create GEOM_Object for each found shared shape (collected in aShared)
2468 TCollection_AsciiString anAsciiList;
2469 Handle(GEOM_Object) anObj;
2470 TopTools_ListIteratorOfListOfShape itSub (aShared);
2471 for (; itSub.More(); itSub.Next()) {
2472 TopoDS_Shape aValue = itSub.Value();
2473 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2474 anArray->SetValue(1, anIndices.FindIndex(aValue));
2475 anObj = GetEngine()->AddSubShape(aMainObj, anArray);
2476 aSeq->Append(anObj);
2478 // for python command
2479 TCollection_AsciiString anEntry;
2480 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2481 anAsciiList += anEntry;
2485 // make a Python command
2486 anAsciiList.Trunc(anAsciiList.Length() - 1);
2488 GEOM::TPythonDump pd (anObj->GetLastFunction());
2489 pd << "[" << anAsciiList.ToCString()
2490 << "] = geompy.GetSharedShapesMulti(";
2495 it = theShapes.begin();
2497 while (it != theShapes.end()) {
2498 pd << ", " << (*it++);
2503 pd << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theMultiShare << ")";
2509 //=============================================================================
2513 //=============================================================================
2514 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump,
2515 const GEOMAlgo_State theState)
2518 case GEOMAlgo_ST_IN:
2519 theDump << "GEOM.ST_IN";
2521 case GEOMAlgo_ST_OUT:
2522 theDump << "GEOM.ST_OUT";
2524 case GEOMAlgo_ST_ON:
2525 theDump << "GEOM.ST_ON";
2527 case GEOMAlgo_ST_ONIN:
2528 theDump << "GEOM.ST_ONIN";
2530 case GEOMAlgo_ST_ONOUT:
2531 theDump << "GEOM.ST_ONOUT";
2534 theDump << "GEOM.ST_UNKNOWN";
2540 //=======================================================================
2541 //function : checkTypeShapesOn
2543 * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
2544 * \param theShapeType - the shape type to check
2545 * \retval bool - result of the check
2547 //=======================================================================
2548 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
2550 if (theShapeType != TopAbs_VERTEX &&
2551 theShapeType != TopAbs_EDGE &&
2552 theShapeType != TopAbs_FACE &&
2553 theShapeType != TopAbs_SOLID) {
2554 SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
2560 //=======================================================================
2561 //function : makePlane
2563 * \brief Creates Geom_Plane
2564 * \param theAx1 - shape object defining plane parameters
2565 * \retval Handle(Geom_Surface) - resulting surface
2567 //=======================================================================
2568 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
2570 if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
2571 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2572 TopoDS_Vertex V1, V2;
2573 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2574 if (V1.IsNull() || V2.IsNull()) {
2575 SetErrorCode("Bad edge given for the plane normal vector");
2578 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2579 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2580 if (aVec.Magnitude() < Precision::Confusion()) {
2581 SetErrorCode("Vector with null magnitude given");
2584 return new Geom_Plane(aLoc, aVec);
2587 //=======================================================================
2588 //function : makeCylinder
2590 * \brief Creates Geom_CylindricalSurface
2591 * \param theAx1 - edge defining cylinder axis
2592 * \param theRadius - cylinder radius
2593 * \retval Handle(Geom_Surface) - resulting surface
2595 //=======================================================================
2596 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
2597 const Standard_Real theRadius)
2599 //Axis of the cylinder
2600 if (anAxis.ShapeType() != TopAbs_EDGE) {
2601 SetErrorCode("Not an edge given for the axis");
2604 TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
2605 TopoDS_Vertex V1, V2;
2606 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2607 if (V1.IsNull() || V2.IsNull()) {
2608 SetErrorCode("Bad edge given for the axis");
2611 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2612 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2613 if (aVec.Magnitude() < Precision::Confusion()) {
2614 SetErrorCode("Vector with null magnitude given");
2618 gp_Ax3 anAx3 (aLoc, aVec);
2619 return new Geom_CylindricalSurface(anAx3, theRadius);
2622 //=======================================================================
2623 //function : getShapesOnBoxIDs
2625 * \brief Find IDs of sub-shapes complying with given status about surface
2626 * \param theBox - the box to check state of sub-shapes against
2627 * \param theShape - the shape to explore
2628 * \param theShapeType - type of sub-shape of theShape
2629 * \param theState - required state
2630 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2632 //=======================================================================
2633 Handle(TColStd_HSequenceOfInteger)
2634 GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2635 const Handle(GEOM_Object)& theShape,
2636 const Standard_Integer theShapeType,
2637 GEOMAlgo_State theState)
2639 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2641 TopoDS_Shape aBox = theBox->GetValue();
2642 TopoDS_Shape aShape = theShape->GetValue();
2644 // Check presence of triangulation, build if need
2645 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2646 SetErrorCode("Cannot build triangulation on the shape");
2651 GEOMAlgo_FinderShapeOn2 aFinder;
2652 Standard_Real aTol = 0.0001; // default value
2654 Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
2655 aClsfBox->SetBox(aBox);
2657 aFinder.SetShape(aShape);
2658 aFinder.SetTolerance(aTol);
2659 aFinder.SetClsf(aClsfBox);
2660 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2661 aFinder.SetState(theState);
2664 // Interprete results
2665 Standard_Integer iErr = aFinder.ErrorStatus();
2666 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2668 MESSAGE(" iErr : " << iErr);
2669 TCollection_AsciiString aMsg (" iErr : ");
2670 aMsg += TCollection_AsciiString(iErr);
2674 Standard_Integer iWrn = aFinder.WarningStatus();
2675 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2677 MESSAGE(" *** iWrn : " << iWrn);
2680 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2682 if (listSS.Extent() < 1) {
2683 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2684 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2688 // Fill sequence of object IDs
2689 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2691 TopTools_IndexedMapOfShape anIndices;
2692 TopExp::MapShapes(aShape, anIndices);
2694 TopTools_ListIteratorOfListOfShape itSub (listSS);
2695 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2696 int id = anIndices.FindIndex(itSub.Value());
2697 aSeqOfIDs->Append(id);
2703 //=======================================================================
2704 //function : GetShapesOnBoxIDs
2706 * \brief Find sub-shapes complying with given status about surface
2707 * \param theBox - the box to check state of sub-shapes against
2708 * \param theShape - the shape to explore
2709 * \param theShapeType - type of sub-shape of theShape
2710 * \param theState - required state
2711 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2713 //=======================================================================
2714 Handle(TColStd_HSequenceOfInteger)
2715 GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2716 const Handle(GEOM_Object)& theShape,
2717 const Standard_Integer theShapeType,
2718 GEOMAlgo_State theState)
2720 // Find sub-shapes ids
2721 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2722 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2723 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2726 // The GetShapesOnBox() doesn't change object so no new function is required.
2727 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
2729 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2730 #ifdef DUMP_SUBSHAPE_IDS
2731 // Make a Python command
2732 GEOM::TPythonDump(aFunction, /*append=*/true)
2733 << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
2736 << TopAbs_ShapeEnum(theShapeType) << ", "
2738 #endif // DUMP_SUBSHAPE_IDS
2744 //=======================================================================
2745 //function : GetShapesOnBox
2747 * \brief Find sub-shapes complying with given status about surface
2748 * \param theBox - the box to check state of sub-shapes against
2749 * \param theShape - the shape to explore
2750 * \param theShapeType - type of sub-shape of theShape
2751 * \param theState - required state
2752 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2754 //=======================================================================
2755 Handle(TColStd_HSequenceOfTransient)
2756 GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
2757 const Handle(GEOM_Object)& theShape,
2758 const Standard_Integer theShapeType,
2759 GEOMAlgo_State theState)
2761 // Find sub-shapes ids
2762 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2763 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2764 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2767 // Find objects by indices
2768 TCollection_AsciiString anAsciiList;
2769 Handle(TColStd_HSequenceOfTransient) aSeq;
2770 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2771 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2774 // Make a Python command
2776 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2777 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2779 GEOM::TPythonDump(aFunction)
2780 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
2783 << TopAbs_ShapeEnum(theShapeType) << ", "
2790 //=======================================================================
2791 //function : getShapesOnShapeIDs
2793 * \brief Find IDs of sub-shapes complying with given status about surface
2794 * \param theCheckShape - the shape to check state of sub-shapes against
2795 * \param theShape - the shape to explore
2796 * \param theShapeType - type of sub-shape of theShape
2797 * \param theState - required state
2798 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2800 //=======================================================================
2801 Handle(TColStd_HSequenceOfInteger)
2802 GEOMImpl_IShapesOperations::getShapesOnShapeIDs
2803 (const Handle(GEOM_Object)& theCheckShape,
2804 const Handle(GEOM_Object)& theShape,
2805 const Standard_Integer theShapeType,
2806 GEOMAlgo_State theState)
2808 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2810 TopoDS_Shape aCheckShape = theCheckShape->GetValue();
2811 TopoDS_Shape aShape = theShape->GetValue();
2812 TopTools_ListOfShape res;
2814 // Check presence of triangulation, build if need
2815 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
2816 SetErrorCode("Cannot build triangulation on the shape");
2820 // Compute classification tolerance.
2821 TopTools_IndexedMapOfShape aMapVtx;
2822 Standard_Real aTol = Precision::Confusion();
2824 TopExp::MapShapes(aShape, TopAbs_VERTEX, aMapVtx);
2827 Standard_Integer aNbVtx = aMapVtx.Extent();
2829 for (i = 1; i <= aNbVtx; ++i) {
2830 const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(i));
2831 const Standard_Real aVtxTol = BRep_Tool::Tolerance(aVtx);
2833 if (aTol < aVtxTol) {
2838 // Bound the tolerance value.
2839 if (aTol > 0.0001) {
2844 GEOMAlgo_FinderShapeOn2 aFinder;
2846 Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
2847 aClsfSolid->SetShape(aCheckShape);
2849 aFinder.SetShape(aShape);
2850 aFinder.SetTolerance(aTol);
2851 aFinder.SetClsf(aClsfSolid);
2852 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2853 aFinder.SetState(theState);
2856 // Interprete results
2857 Standard_Integer iErr = aFinder.ErrorStatus();
2858 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2861 SetErrorCode("theCheckShape must be a solid");
2864 MESSAGE(" iErr : " << iErr);
2865 TCollection_AsciiString aMsg (" iErr : ");
2866 aMsg += TCollection_AsciiString(iErr);
2871 Standard_Integer iWrn = aFinder.WarningStatus();
2872 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2874 MESSAGE(" *** iWrn : " << iWrn);
2877 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2879 if (listSS.Extent() < 1) {
2880 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2881 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2884 // Fill sequence of object IDs
2885 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2887 TopTools_IndexedMapOfShape anIndices;
2888 TopExp::MapShapes(aShape, anIndices);
2890 TopTools_ListIteratorOfListOfShape itSub (listSS);
2891 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2892 int id = anIndices.FindIndex(itSub.Value());
2893 aSeqOfIDs->Append(id);
2899 //=======================================================================
2900 //function : GetShapesOnShapeIDs
2902 * \brief Find sub-shapes complying with given status about surface
2903 * \param theCheckShape - the shape to check state of sub-shapes against
2904 * \param theShape - the shape to explore
2905 * \param theShapeType - type of sub-shape of theShape
2906 * \param theState - required state
2907 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2909 //=======================================================================
2910 Handle(TColStd_HSequenceOfInteger)
2911 GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
2912 (const Handle(GEOM_Object)& theCheckShape,
2913 const Handle(GEOM_Object)& theShape,
2914 const Standard_Integer theShapeType,
2915 GEOMAlgo_State theState)
2917 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2918 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2920 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2923 // The GetShapesOnShape() doesn't change object so no new function is required.
2924 Handle(GEOM_Function) aFunction =
2925 GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
2927 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
2928 #ifdef DUMP_SUBSHAPE_IDS
2929 // Make a Python command
2930 GEOM::TPythonDump(aFunction, /*append=*/true)
2931 << "listShapesOnShapeIDs = geompy.GetShapesOnShapeIDs("
2932 << theCheckShape << ", "
2934 << TopAbs_ShapeEnum(theShapeType) << ", "
2936 #endif // DUMP_SUBSHAPE_IDS
2942 //=======================================================================
2943 //function : GetShapesOnShape
2945 * \brief Find sub-shapes complying with given status about surface
2946 * \param theCheckShape - the shape to check state of sub-shapes against
2947 * \param theShape - the shape to explore
2948 * \param theShapeType - type of sub-shape of theShape
2949 * \param theState - required state
2950 * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2952 //=======================================================================
2953 Handle(TColStd_HSequenceOfTransient)
2954 GEOMImpl_IShapesOperations::GetShapesOnShape
2955 (const Handle(GEOM_Object)& theCheckShape,
2956 const Handle(GEOM_Object)& theShape,
2957 const Standard_Integer theShapeType,
2958 GEOMAlgo_State theState)
2960 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2961 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2962 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2965 // Find objects by indices
2966 TCollection_AsciiString anAsciiList;
2967 Handle(TColStd_HSequenceOfTransient) aSeq;
2968 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2970 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2973 // Make a Python command
2975 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2976 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2978 GEOM::TPythonDump(aFunction)
2979 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
2980 << theCheckShape << ", "
2982 << TopAbs_ShapeEnum(theShapeType) << ", "
2989 //=======================================================================
2990 //function : GetShapesOnShapeAsCompound
2991 //=======================================================================
2992 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
2993 (const Handle(GEOM_Object)& theCheckShape,
2994 const Handle(GEOM_Object)& theShape,
2995 const Standard_Integer theShapeType,
2996 GEOMAlgo_State theState)
2998 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2999 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
3001 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3004 // Find objects by indices
3005 TCollection_AsciiString anAsciiList;
3006 Handle(TColStd_HSequenceOfTransient) aSeq;
3007 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
3009 if ( aSeq.IsNull() || aSeq->IsEmpty() )
3012 TopoDS_Compound aCompound;
3014 B.MakeCompound(aCompound);
3016 for(; i<=aSeq->Length(); i++) {
3017 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
3018 TopoDS_Shape aShape_i = anObj->GetValue();
3019 B.Add(aCompound,aShape_i);
3022 //Add a new result object
3023 Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
3024 Handle(GEOM_Function) aFunction =
3025 aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
3026 aFunction->SetValue(aCompound);
3029 aSeq->Append( theCheckShape->GetLastFunction() );
3030 aSeq->Append( theShape->GetLastFunction() );
3032 GEOMImpl_IShapes aCI( aFunction );
3033 aCI.SetShapes( aSeq );
3034 aCI.SetSubShapeType( theShapeType );
3035 aCI.SetTolerance( theState );
3037 GEOM::TPythonDump(aFunction)
3038 << aRes << " = geompy.GetShapesOnShapeAsCompound("
3039 << theCheckShape << ", "
3041 << TopAbs_ShapeEnum(theShapeType) << ", "
3049 //=============================================================================
3051 * GetSubShapeEdgeSorted
3053 //=============================================================================
3054 Handle(TColStd_HSequenceOfTransient)
3055 GEOMImpl_IShapesOperations::GetSubShapeEdgeSorted
3056 (const Handle(GEOM_Object) &theShape,
3057 const Handle(GEOM_Object) &theStartPoint)
3059 // Get the sorted edges indices.
3060 Handle(TColStd_HSequenceOfInteger) aSortedIDs =
3061 getSubShapeEdgeSortedIDs(theShape, theStartPoint);
3063 // Get object by indices.
3064 TCollection_AsciiString anAsciiList;
3065 Handle(TColStd_HSequenceOfTransient) aSeq =
3066 getObjectsShapesOn(theShape, aSortedIDs, anAsciiList);
3068 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3069 SetErrorCode("Empty sequence of edges");
3073 // Make a Python command
3074 Handle(GEOM_Object) anObj =
3075 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3076 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3078 GEOM::TPythonDump(aFunction)
3079 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapeEdgeSorted("
3080 << theShape << ", " << theStartPoint << ")";
3087 //=============================================================================
3089 * GetSubShapesWithTolerance
3091 //=============================================================================
3092 Handle(TColStd_HSequenceOfTransient)
3093 GEOMImpl_IShapesOperations::GetSubShapesWithTolerance
3094 (const Handle(GEOM_Object) &theShape,
3095 const Standard_Integer theShapeType,
3096 const GEOMUtils::ComparisonCondition theCondition,
3097 const Standard_Real theTolerance)
3099 if (theShape.IsNull()) {
3100 SetErrorCode("NULL GEOM object");
3104 TopoDS_Shape aShape = theShape->GetValue();
3106 if (aShape.IsNull()) {
3107 SetErrorCode("NULL Shape");
3111 if (theShapeType != TopAbs_FACE && theShapeType != TopAbs_EDGE &&
3112 theShapeType != TopAbs_VERTEX && aShape.ShapeType() >= theShapeType) {
3113 SetErrorCode("Invalid shape type");
3117 TopTools_IndexedMapOfShape anIndices;
3118 TopTools_MapOfShape aMapFence;
3119 TopExp_Explorer anExp(aShape,
3120 (TopAbs_ShapeEnum) theShapeType);
3121 Handle(TColStd_HSequenceOfInteger) anIDs = new TColStd_HSequenceOfInteger;
3123 TopExp::MapShapes(aShape, anIndices);
3125 for (; anExp.More(); anExp.Next()) {
3126 const TopoDS_Shape &aSubShape = anExp.Current();
3128 if (aMapFence.Add(aSubShape)) {
3129 // Compute tolerance
3130 Standard_Real aTolerance = -1.;
3132 switch (aSubShape.ShapeType()) {
3134 aTolerance = BRep_Tool::Tolerance(TopoDS::Face(aSubShape));
3137 aTolerance = BRep_Tool::Tolerance(TopoDS::Edge(aSubShape));
3140 aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aSubShape));
3146 if (aTolerance < 0.) {
3150 // Compare the tolerance with reference value.
3151 if (GEOMUtils::IsFitCondition (theCondition, aTolerance, theTolerance)) {
3152 anIDs->Append(anIndices.FindIndex(aSubShape));
3157 if (anIDs->IsEmpty()) {
3158 SetErrorCode("Empty sequence of sub-shapes");
3162 // Get objects by indices.
3163 TCollection_AsciiString anAsciiList;
3164 Handle(TColStd_HSequenceOfTransient) aSeq =
3165 getObjectsShapesOn(theShape, anIDs, anAsciiList);
3167 if (aSeq.IsNull() || aSeq->IsEmpty()) {
3168 SetErrorCode("Empty sequence of edges");
3172 // Make a Python command
3173 Handle(GEOM_Object) anObj =
3174 Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3175 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3177 GEOM::TPythonDump(aFunction)
3178 << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapesWithTolerance("
3179 << theShape << ", " << theShapeType << ", " << theCondition << ", "
3180 << theTolerance << ")";
3187 //=============================================================================
3191 //=============================================================================
3192 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeExtraction
3193 (const Handle(GEOM_Object) &theShape,
3194 const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs,
3195 std::list<ExtractionStat> &theStats)
3199 if (theShape.IsNull()) {
3203 //Add a new Result object
3204 Handle(GEOM_Object) aResult =
3205 GetEngine()->AddObject(GetDocID(), GEOM_EXTRACTION);
3207 //Add a new Extraction function
3208 Handle(GEOM_Function) aFunction =
3209 aResult->AddFunction(GEOMImpl_ShapeDriver::GetID(), EXTRACTION);
3211 //Check if the function is set correctly
3212 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
3216 Handle(GEOM_Function) aShape = theShape->GetLastFunction();
3218 if (aShape.IsNull()) {
3222 GEOMImpl_IExtract aCI (aFunction);
3224 aCI.SetShape(aShape);
3225 aCI.SetSubShapeIDs(theSubShapeIDs);
3227 //Compute the Edge value
3230 if (!GetSolver()->ComputeFunction(aFunction)) {
3231 SetErrorCode("Shape driver failed");
3236 catch (Standard_Failure) {
3237 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3238 SetErrorCode(aFail->GetMessageString());
3243 // Fill in statistics.
3246 Handle(TColStd_HArray1OfInteger) aStatIDsArray[3] =
3247 { aCI.GetRemovedIDs(), aCI.GetModifiedIDs(), aCI.GetAddedIDs() };
3251 for (j = 0; j < 3; ++j) {
3252 if (!aStatIDsArray[j].IsNull()) {
3253 const int anUpperID = aStatIDsArray[j]->Upper();
3254 ExtractionStat aStat;
3256 for (i = aStatIDsArray[j]->Lower(); i <= anUpperID; ++i) {
3257 aStat.indices.push_back(aStatIDsArray[j]->Value(i));
3260 aStat.type = (ExtractionStatType) j;
3261 theStats.push_back(aStat);
3265 //Make a Python command
3266 GEOM::TPythonDump pd(aFunction);
3268 pd << aResult << " = geompy.MakeExtraction(" << theShape << ", [";
3270 if (!theSubShapeIDs.IsNull()) {
3271 const int aNbIDs = theSubShapeIDs->Upper();
3273 for (i = theSubShapeIDs->Lower(); i < aNbIDs; ++i) {
3274 pd << theSubShapeIDs->Value(i) << ", ";
3277 // Dump the last value without a comma.
3278 pd << theSubShapeIDs->Value(i);
3288 //=======================================================================
3289 //function : getShapesOnSurfaceIDs
3291 * \brief Find IDs of sub-shapes complying with given status about surface
3292 * \param theSurface - the surface to check state of sub-shapes against
3293 * \param theShape - the shape to explore
3294 * \param theShapeType - type of sub-shape of theShape
3295 * \param theState - required state
3296 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3298 //=======================================================================
3299 Handle(TColStd_HSequenceOfInteger)
3300 GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
3301 const TopoDS_Shape& theShape,
3302 TopAbs_ShapeEnum theShapeType,
3303 GEOMAlgo_State theState)
3305 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3307 // Check presence of triangulation, build if need
3308 if (theShapeType != TopAbs_VERTEX &&
3309 !GEOMUtils::CheckTriangulation(theShape)) {
3310 SetErrorCode("Cannot build triangulation on the shape");
3314 // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
3315 // Compute tolerance
3316 Standard_Real T, VertMax = -RealLast();
3319 for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
3320 TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
3321 T = BRep_Tool::Tolerance(Vertex);
3326 catch (Standard_Failure) {
3327 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3328 SetErrorCode(aFail->GetMessageString());
3331 // END: Mantis issue 0020961
3334 GEOMAlgo_FinderShapeOn2 aFinder;
3335 Handle(GEOMAlgo_ClsfSurf) aClsfSurf = new GEOMAlgo_ClsfSurf;
3336 Standard_Real aTol = VertMax; // Mantis issue 0020961
3338 aClsfSurf->SetSurface(theSurface);
3339 aFinder.SetShape(theShape);
3340 aFinder.SetTolerance(aTol);
3341 aFinder.SetClsf(aClsfSurf);
3342 aFinder.SetShapeType(theShapeType);
3343 aFinder.SetState(theState);
3345 // Sets the minimal number of inner points for the faces that do not have own
3346 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
3348 aFinder.SetNbPntsMin(3);
3349 // Sets the maximal number of inner points for edges or faces.
3350 // It is usefull for the cases when this number is very big (e.g =2000) to improve
3351 // the performance. If this value =0, all inner points will be taken into account.
3353 aFinder.SetNbPntsMax(100);
3357 // Interprete results
3358 Standard_Integer iErr = aFinder.ErrorStatus();
3359 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
3361 MESSAGE(" iErr : " << iErr);
3362 TCollection_AsciiString aMsg (" iErr : ");
3363 aMsg += TCollection_AsciiString(iErr);
3367 Standard_Integer iWrn = aFinder.WarningStatus();
3368 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
3370 MESSAGE(" *** iWrn : " << iWrn);
3373 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
3375 if (listSS.Extent() < 1) {
3376 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
3377 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
3381 // Fill sequence of object IDs
3382 aSeqOfIDs = new TColStd_HSequenceOfInteger;
3384 TopTools_IndexedMapOfShape anIndices;
3385 TopExp::MapShapes(theShape, anIndices);
3387 TopTools_ListIteratorOfListOfShape itSub (listSS);
3388 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3389 int id = anIndices.FindIndex(itSub.Value());
3390 aSeqOfIDs->Append(id);
3396 //=======================================================================
3397 //function : getObjectsShapesOn
3399 * \brief Find shape objects and their entries by their ids
3400 * \param theShapeIDs - incoming shape ids
3401 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3402 * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
3404 //=======================================================================
3405 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
3406 getObjectsShapesOn(const Handle(GEOM_Object)& theShape,
3407 const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
3408 TCollection_AsciiString & theShapeEntries)
3410 Handle(TColStd_HSequenceOfTransient) aSeq;
3412 if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
3414 aSeq = new TColStd_HSequenceOfTransient;
3415 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3416 TCollection_AsciiString anEntry;
3417 for ( int i = 1; i <= theShapeIDs->Length(); ++i )
3419 anArray->SetValue(1, theShapeIDs->Value( i ));
3420 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3421 aSeq->Append( anObj );
3423 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3424 if ( i != 1 ) theShapeEntries += ",";
3425 theShapeEntries += anEntry;
3431 //=============================================================================
3433 * getSubShapeEdgeSortedIDs
3435 //=============================================================================
3436 Handle(TColStd_HSequenceOfInteger)
3437 GEOMImpl_IShapesOperations::getSubShapeEdgeSortedIDs
3438 (const Handle(GEOM_Object) &theShape,
3439 const Handle(GEOM_Object) &theStartPoint)
3441 Handle(TColStd_HSequenceOfInteger) aResult;
3443 if (theShape.IsNull() || theStartPoint.IsNull()) {
3444 SetErrorCode("NULL GEOM object");
3448 const TopoDS_Shape aShape = theShape->GetValue();
3449 const TopoDS_Shape aStartPoint = theStartPoint->GetValue();
3451 if (aShape.IsNull() || aStartPoint.IsNull()) {
3452 SetErrorCode("NULL Shape");
3456 if (aStartPoint.ShapeType() != TopAbs_VERTEX) {
3457 SetErrorCode("Starting point is not a vertex");
3461 TopExp_Explorer anExp(aShape, TopAbs_EDGE);
3462 TopTools_MapOfShape aMapFence;
3463 TopTools_ListOfShape anEdges;
3465 for (; anExp.More(); anExp.Next()) {
3466 const TopoDS_Shape &anEdge = anExp.Current();
3468 if (aMapFence.Add(anEdge)) {
3469 anEdges.Append(anEdge);
3473 if (anEdges.IsEmpty()) {
3474 SetErrorCode("Shape doesn't contain edges");
3478 // Step 1: Sort edges
3479 GEOMUtils::SortShapes(anEdges, Standard_False);
3481 TopTools_ListIteratorOfListOfShape anIter(anEdges);
3482 TopoDS_Vertex aV[2];
3483 TopTools_DataMapOfShapeListOfShape aMapVE;
3485 // Step 2: Fill the map vertex - list of edges.
3486 for (; anIter.More(); anIter.Next()) {
3487 TopoDS_Edge anEdge = TopoDS::Edge(anIter.Value());
3489 TopExp::Vertices(anEdge, aV[0], aV[1]);
3491 const Standard_Integer aNbV = aV[0].IsSame(aV[1]) ? 1 : 2;
3494 for (i = 0; i < aNbV; ++i) {
3495 if (aV[i].IsNull() == Standard_False) {
3496 if (!aMapVE.IsBound(aV[i])) {
3497 // There is no this vertex in the map.
3498 aMapVE.Bind(aV[i], TopTools_ListOfShape());
3501 // Add the edge to the list bound with the vertex aV[i].
3502 TopTools_ListOfShape &aLEdges = aMapVE.ChangeFind(aV[i]);
3504 aLEdges.Append(anEdge);
3509 // Step 3: Find starting point in aMapVE.
3510 TopoDS_Vertex aStartVtx = TopoDS::Vertex(aStartPoint);
3512 if (!aMapVE.IsBound(aStartVtx)) {
3513 aStartVtx = getSameVertex(aShape, aStartVtx);
3515 if (aStartVtx.IsNull()) {
3516 SetErrorCode("Invalid Starting point");
3521 TopTools_IndexedMapOfShape anIndices;
3522 TopTools_MapOfShape aMapVFence;
3523 TopoDS_Shape aCurVtx = aStartVtx;
3524 TopoDS_Edge aCurEdge =
3525 TopoDS::Edge(aMapVE.Find(aCurVtx).First());
3527 aResult = new TColStd_HSequenceOfInteger;
3528 TopExp::MapShapes(aShape, anIndices);
3530 // Step 4: Fill the list of sorted edges.
3531 while (aMapVFence.Add(aCurVtx)) {
3532 // Append the ID of the current edge to the list of sorted.
3533 aResult->Append(anIndices.FindIndex(aCurEdge));
3534 TopExp::Vertices(aCurEdge, aV[0], aV[1]);
3536 // Get the next vertex.
3537 if (aCurVtx.IsSame(aV[0])) {
3538 if (aCurVtx.IsSame(aV[1])) {
3539 // There is no next vertex.
3548 if (aCurVtx.IsNull()) {
3549 // There is no next vertex.
3553 // Get the next edge.
3554 const TopTools_ListOfShape &aLEdges = aMapVE.Find(aCurVtx);
3555 TopTools_ListIteratorOfListOfShape anEIter(aLEdges);
3557 for (; anEIter.More(); anEIter.Next()) {
3558 const TopoDS_Shape &aLocalEdge = anEIter.Value();
3560 if (aLocalEdge.IsNull() == Standard_False) {
3561 if (!aCurEdge.IsSame(aLocalEdge)) {
3562 aCurEdge = TopoDS::Edge(aLocalEdge);
3568 if (!anEIter.More()) {
3569 // There is no next edge.
3577 //=======================================================================
3578 //function : getShapesOnSurface
3580 * \brief Find sub-shapes complying with given status about surface
3581 * \param theSurface - the surface to check state of sub-shapes against
3582 * \param theShape - the shape to explore
3583 * \param theShapeType - type of sub-shape of theShape
3584 * \param theState - required state
3585 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3586 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3588 //=======================================================================
3589 Handle(TColStd_HSequenceOfTransient)
3590 GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
3591 const Handle(GEOM_Object)& theShape,
3592 TopAbs_ShapeEnum theShapeType,
3593 GEOMAlgo_State theState,
3594 TCollection_AsciiString & theShapeEntries)
3596 // Find sub-shapes ids
3597 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3598 getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
3599 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
3602 return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
3605 //=============================================================================
3609 //=============================================================================
3610 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
3611 (const Handle(GEOM_Object)& theShape,
3612 const Standard_Integer theShapeType,
3613 const Handle(GEOM_Object)& theAx1,
3614 const GEOMAlgo_State theState)
3618 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3620 TopoDS_Shape aShape = theShape->GetValue();
3621 TopoDS_Shape anAx1 = theAx1->GetValue();
3623 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3625 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3626 if ( !checkTypeShapesOn( theShapeType ))
3630 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3631 if ( aPlane.IsNull() )
3635 TCollection_AsciiString anAsciiList;
3636 Handle(TColStd_HSequenceOfTransient) aSeq;
3637 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3638 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3641 // Make a Python command
3643 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3644 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3646 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3647 << "] = geompy.GetShapesOnPlane(" << theShape << ", "
3648 << aShapeType << ", " << theAx1 << ", " << theState << ")";
3654 //=============================================================================
3656 * GetShapesOnPlaneWithLocation
3658 //=============================================================================
3659 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
3660 (const Handle(GEOM_Object)& theShape,
3661 const Standard_Integer theShapeType,
3662 const Handle(GEOM_Object)& theAx1,
3663 const Handle(GEOM_Object)& thePnt,
3664 const GEOMAlgo_State theState)
3668 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3670 TopoDS_Shape aShape = theShape->GetValue();
3671 TopoDS_Shape anAx1 = theAx1->GetValue();
3672 TopoDS_Shape anPnt = thePnt->GetValue();
3674 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3676 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3677 if ( !checkTypeShapesOn( theShapeType ))
3681 if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
3682 TopoDS_Vertex V1, V2, V3;
3683 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3684 TopExp::Vertices(anEdge, V1, V2, Standard_True);
3686 if (V1.IsNull() || V2.IsNull()) {
3687 SetErrorCode("Bad edge given for the plane normal vector");
3690 V3 = TopoDS::Vertex(anPnt);
3693 SetErrorCode("Bad vertex given for the plane location");
3696 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3697 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3699 if (aVec.Magnitude() < Precision::Confusion()) {
3700 SetErrorCode("Vector with null magnitude given");
3703 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3705 if ( aPlane.IsNull() )
3709 TCollection_AsciiString anAsciiList;
3710 Handle(TColStd_HSequenceOfTransient) aSeq;
3711 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3712 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3715 // Make a Python command
3717 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3718 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3720 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3721 << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
3722 << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
3728 //=============================================================================
3730 * GetShapesOnCylinder
3732 //=============================================================================
3733 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
3734 (const Handle(GEOM_Object)& theShape,
3735 const Standard_Integer theShapeType,
3736 const Handle(GEOM_Object)& theAxis,
3737 const Standard_Real theRadius,
3738 const GEOMAlgo_State theState)
3742 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3744 TopoDS_Shape aShape = theShape->GetValue();
3745 TopoDS_Shape anAxis = theAxis->GetValue();
3747 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3749 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3750 if ( !checkTypeShapesOn( aShapeType ))
3753 // Create a cylinder surface
3754 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3755 if ( aCylinder.IsNull() )
3759 TCollection_AsciiString anAsciiList;
3760 Handle(TColStd_HSequenceOfTransient) aSeq;
3761 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3762 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3765 // Make a Python command
3767 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3768 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3770 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3771 << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
3772 << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
3778 //=============================================================================
3780 * GetShapesOnCylinderWithLocation
3782 //=============================================================================
3783 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
3784 (const Handle(GEOM_Object)& theShape,
3785 const Standard_Integer theShapeType,
3786 const Handle(GEOM_Object)& theAxis,
3787 const Handle(GEOM_Object)& thePnt,
3788 const Standard_Real theRadius,
3789 const GEOMAlgo_State theState)
3793 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3795 TopoDS_Shape aShape = theShape->GetValue();
3796 TopoDS_Shape anAxis = theAxis->GetValue();
3797 TopoDS_Shape aPnt = thePnt->GetValue();
3799 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3801 if (aPnt.ShapeType() != TopAbs_VERTEX )
3803 SetErrorCode("Bottom location point must be vertex");
3807 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3808 if ( !checkTypeShapesOn( aShapeType ))
3811 // Create a cylinder surface
3812 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3813 if ( aCylinder.IsNull() )
3816 // translate the surface
3817 Handle(Geom_CylindricalSurface) aCylSurface =
3818 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3819 if ( aCylSurface.IsNull() )
3821 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3824 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3825 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3826 aCylinder->Translate( fromLoc, toLoc );
3829 TCollection_AsciiString anAsciiList;
3830 Handle(TColStd_HSequenceOfTransient) aSeq;
3831 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3832 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3835 // Make a Python command
3837 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3838 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3840 GEOM::TPythonDump(aFunction)
3841 << "[" << anAsciiList.ToCString()
3842 << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
3843 << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
3849 //=============================================================================
3853 //=============================================================================
3854 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
3855 (const Handle(GEOM_Object)& theShape,
3856 const Standard_Integer theShapeType,
3857 const Handle(GEOM_Object)& theCenter,
3858 const Standard_Real theRadius,
3859 const GEOMAlgo_State theState)
3863 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3865 TopoDS_Shape aShape = theShape->GetValue();
3866 TopoDS_Shape aCenter = theCenter->GetValue();
3868 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3870 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3871 if ( !checkTypeShapesOn( aShapeType ))
3874 // Center of the sphere
3875 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3876 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3878 gp_Ax3 anAx3 (aLoc, gp::DZ());
3879 Handle(Geom_SphericalSurface) aSphere =
3880 new Geom_SphericalSurface(anAx3, theRadius);
3883 TCollection_AsciiString anAsciiList;
3884 Handle(TColStd_HSequenceOfTransient) aSeq;
3885 aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
3886 if ( aSeq.IsNull() || aSeq->Length() == 0 )
3889 // Make a Python command
3891 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3892 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3894 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3895 << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
3896 << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
3902 //=============================================================================
3904 * GetShapesOnPlaneIDs
3906 //=============================================================================
3907 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
3908 (const Handle(GEOM_Object)& theShape,
3909 const Standard_Integer theShapeType,
3910 const Handle(GEOM_Object)& theAx1,
3911 const GEOMAlgo_State theState)
3915 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3917 TopoDS_Shape aShape = theShape->GetValue();
3918 TopoDS_Shape anAx1 = theAx1->GetValue();
3920 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3922 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3923 if ( !checkTypeShapesOn( aShapeType ))
3927 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3928 if ( aPlane.IsNull() )
3932 Handle(TColStd_HSequenceOfInteger) aSeq;
3933 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3935 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3936 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3938 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
3939 #ifdef DUMP_SUBSHAPE_IDS
3940 // Make a Python command
3941 GEOM::TPythonDump(aFunction, /*append=*/true)
3942 << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
3943 << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
3944 #endif // DUMP_SUBSHAPE_IDS
3950 //=============================================================================
3952 * GetShapesOnPlaneWithLocationIDs
3954 //=============================================================================
3955 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
3956 (const Handle(GEOM_Object)& theShape,
3957 const Standard_Integer theShapeType,
3958 const Handle(GEOM_Object)& theAx1,
3959 const Handle(GEOM_Object)& thePnt,
3960 const GEOMAlgo_State theState)
3964 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3966 TopoDS_Shape aShape = theShape->GetValue();
3967 TopoDS_Shape anAx1 = theAx1->GetValue();
3968 TopoDS_Shape anPnt = thePnt->GetValue();
3970 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3972 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3973 if ( !checkTypeShapesOn( aShapeType ))
3977 if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
3978 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3979 TopoDS_Vertex V1, V2, V3;
3980 TopExp::Vertices(anEdge, V1, V2, Standard_True);
3981 if (V1.IsNull() || V2.IsNull()) {
3982 SetErrorCode("Bad edge given for the plane normal vector");
3985 V3 = TopoDS::Vertex(anPnt);
3987 SetErrorCode("Bad vertex given for the plane location");
3990 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3991 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3992 if (aVec.Magnitude() < Precision::Confusion()) {
3993 SetErrorCode("Vector with null magnitude given");
3997 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3998 if ( aPlane.IsNull() )
4002 Handle(TColStd_HSequenceOfInteger) aSeq;
4003 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
4005 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
4006 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
4008 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4009 #ifdef DUMP_SUBSHAPE_IDS
4010 // Make a Python command
4011 GEOM::TPythonDump(aFunction, /*append=*/true)
4012 << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
4013 << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")";
4014 #endif // DUMP_SUBSHAPE_IDS
4020 //=============================================================================
4022 * GetShapesOnCylinderIDs
4024 //=============================================================================
4025 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
4026 (const Handle(GEOM_Object)& theShape,
4027 const Standard_Integer theShapeType,
4028 const Handle(GEOM_Object)& theAxis,
4029 const Standard_Real theRadius,
4030 const GEOMAlgo_State theState)
4034 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
4036 TopoDS_Shape aShape = theShape->GetValue();
4037 TopoDS_Shape anAxis = theAxis->GetValue();
4039 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
4041 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4042 if ( !checkTypeShapesOn( aShapeType ))
4045 // Create a cylinder surface
4046 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4047 if ( aCylinder.IsNull() )
4051 Handle(TColStd_HSequenceOfInteger) aSeq;
4052 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4054 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4055 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
4057 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4058 #ifdef DUMP_SUBSHAPE_IDS
4059 // Make a Python command
4060 GEOM::TPythonDump(aFunction, /*append=*/true)
4061 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
4062 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4063 << theRadius << ", " << theState << ")";
4064 #endif // DUMP_SUBSHAPE_IDS
4070 //=============================================================================
4072 * GetShapesOnCylinderWithLocationIDs
4074 //=============================================================================
4075 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
4076 (const Handle(GEOM_Object)& theShape,
4077 const Standard_Integer theShapeType,
4078 const Handle(GEOM_Object)& theAxis,
4079 const Handle(GEOM_Object)& thePnt,
4080 const Standard_Real theRadius,
4081 const GEOMAlgo_State theState)
4085 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
4087 TopoDS_Shape aShape = theShape->GetValue();
4088 TopoDS_Shape anAxis = theAxis->GetValue();
4089 TopoDS_Shape aPnt = thePnt->GetValue();
4091 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
4093 if (aPnt.ShapeType() != TopAbs_VERTEX )
4095 SetErrorCode("Bottom location point must be vertex");
4099 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4100 if ( !checkTypeShapesOn( aShapeType ))
4103 // Create a cylinder surface
4104 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
4105 if ( aCylinder.IsNull() )
4108 // translate the surface
4109 Handle(Geom_CylindricalSurface) aCylSurface =
4110 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
4111 if ( aCylSurface.IsNull() )
4113 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
4116 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
4117 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
4118 aCylinder->Translate( fromLoc, toLoc );
4121 Handle(TColStd_HSequenceOfInteger) aSeq;
4122 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
4124 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4125 Handle(GEOM_Function) aFunction =
4126 GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
4128 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4129 #ifdef DUMP_SUBSHAPE_IDS
4130 // Make a Python command
4131 GEOM::TPythonDump(aFunction, /*append=*/true)
4132 << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
4133 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
4134 << thePnt << ", " << theRadius << ", " << theState << ")";
4135 #endif // DUMP_SUBSHAPE_IDS
4141 //=============================================================================
4143 * GetShapesOnSphereIDs
4145 //=============================================================================
4146 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
4147 (const Handle(GEOM_Object)& theShape,
4148 const Standard_Integer theShapeType,
4149 const Handle(GEOM_Object)& theCenter,
4150 const Standard_Real theRadius,
4151 const GEOMAlgo_State theState)
4155 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
4157 TopoDS_Shape aShape = theShape->GetValue();
4158 TopoDS_Shape aCenter = theCenter->GetValue();
4160 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
4162 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4163 if ( !checkTypeShapesOn( aShapeType ))
4166 // Center of the sphere
4167 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
4168 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
4170 gp_Ax3 anAx3 (aLoc, gp::DZ());
4171 Handle(Geom_SphericalSurface) aSphere =
4172 new Geom_SphericalSurface(anAx3, theRadius);
4175 Handle(TColStd_HSequenceOfInteger) aSeq;
4176 aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
4178 // The GetShapesOnSphere() doesn't change object so no new function is required.
4179 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
4181 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4182 #ifdef DUMP_SUBSHAPE_IDS
4183 // Make a Python command
4184 GEOM::TPythonDump(aFunction, /*append=*/true)
4185 << "listShapesOnSphere = geompy.GetShapesOnSphereIDs"
4186 << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
4187 << theRadius << ", " << theState << ")";
4188 #endif // DUMP_SUBSHAPE_IDS
4194 //=======================================================================
4195 //function : getShapesOnQuadrangleIDs
4197 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4198 * \param theShape - the shape to explore
4199 * \param theShapeType - type of sub-shape of theShape
4200 * \param theTopLeftPoint - top left quadrangle corner
4201 * \param theTopRigthPoint - top right quadrangle corner
4202 * \param theBottomLeftPoint - bottom left quadrangle corner
4203 * \param theBottomRigthPoint - bottom right quadrangle corner
4204 * \param theState - required state
4205 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4207 //=======================================================================
4208 Handle(TColStd_HSequenceOfInteger)
4209 GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4210 const Standard_Integer theShapeType,
4211 const Handle(GEOM_Object)& theTopLeftPoint,
4212 const Handle(GEOM_Object)& theTopRigthPoint,
4213 const Handle(GEOM_Object)& theBottomLeftPoint,
4214 const Handle(GEOM_Object)& theBottomRigthPoint,
4215 const GEOMAlgo_State theState)
4219 if ( theShape.IsNull() ||
4220 theTopLeftPoint.IsNull() ||
4221 theTopRigthPoint.IsNull() ||
4222 theBottomLeftPoint.IsNull() ||
4223 theBottomRigthPoint.IsNull() )
4226 TopoDS_Shape aShape = theShape->GetValue();
4227 TopoDS_Shape aTL = theTopLeftPoint->GetValue();
4228 TopoDS_Shape aTR = theTopRigthPoint->GetValue();
4229 TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
4230 TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
4232 if (aShape.IsNull() ||
4237 aTL.ShapeType() != TopAbs_VERTEX ||
4238 aTR.ShapeType() != TopAbs_VERTEX ||
4239 aBL.ShapeType() != TopAbs_VERTEX ||
4240 aBR.ShapeType() != TopAbs_VERTEX )
4243 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
4244 if ( !checkTypeShapesOn( aShapeType ))
4247 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
4249 // Check presence of triangulation, build if need
4250 if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) {
4251 SetErrorCode("Cannot build triangulation on the shape");
4256 gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
4257 gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
4258 gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
4259 gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
4261 GEOMAlgo_FinderShapeOn2 aFinder;
4262 Handle(GEOMAlgo_ClsfQuad) aClsfQuad = new GEOMAlgo_ClsfQuad;
4264 Standard_Real aTol = 0.0001; // default value
4266 aClsfQuad->SetCorners(aPntTL, aPntTR, aPntBL, aPntBR);
4267 aFinder.SetShape(aShape);
4268 aFinder.SetTolerance(aTol);
4269 aFinder.SetClsf(aClsfQuad);
4270 aFinder.SetShapeType(aShapeType);
4271 aFinder.SetState(theState);
4273 // Sets the minimal number of inner points for the faces that do not have own
4274 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
4276 aFinder.SetNbPntsMin(3);
4277 // Sets the maximal number of inner points for edges or faces.
4278 // It is usefull for the cases when this number is very big (e.g =2000) to improve
4279 // the performance. If this value =0, all inner points will be taken into account.
4281 aFinder.SetNbPntsMax(100);
4285 // Interprete results
4286 Standard_Integer iErr = aFinder.ErrorStatus();
4287 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
4289 MESSAGE(" iErr : " << iErr);
4290 TCollection_AsciiString aMsg (" iErr : ");
4291 aMsg += TCollection_AsciiString(iErr);
4295 Standard_Integer iWrn = aFinder.WarningStatus();
4296 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
4298 MESSAGE(" *** iWrn : " << iWrn);
4301 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
4303 if (listSS.Extent() < 1) {
4304 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
4305 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
4309 // Fill sequence of object IDs
4310 aSeqOfIDs = new TColStd_HSequenceOfInteger;
4312 TopTools_IndexedMapOfShape anIndices;
4313 TopExp::MapShapes(aShape, anIndices);
4315 TopTools_ListIteratorOfListOfShape itSub (listSS);
4316 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
4317 int id = anIndices.FindIndex(itSub.Value());
4318 aSeqOfIDs->Append(id);
4323 //=======================================================================
4324 //function : GetShapesOnQuadrangle
4326 * \brief Find sub-shapes complying with given status about quadrangle
4327 * \param theShape - the shape to explore
4328 * \param theShapeType - type of sub-shape of theShape
4329 * \param theTopLeftPoint - top left quadrangle corner
4330 * \param theTopRigthPoint - top right quadrangle corner
4331 * \param theBottomLeftPoint - bottom left quadrangle corner
4332 * \param theBottomRigthPoint - bottom right quadrangle corner
4333 * \param theState - required state
4334 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4336 //=======================================================================
4337 Handle(TColStd_HSequenceOfTransient)
4338 GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
4339 const Standard_Integer theShapeType,
4340 const Handle(GEOM_Object)& theTopLeftPoint,
4341 const Handle(GEOM_Object)& theTopRigthPoint,
4342 const Handle(GEOM_Object)& theBottomLeftPoint,
4343 const Handle(GEOM_Object)& theBottomRigthPoint,
4344 const GEOMAlgo_State theState)
4347 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4348 getShapesOnQuadrangleIDs( theShape,
4353 theBottomRigthPoint,
4355 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4358 // Find objects by indices
4359 TCollection_AsciiString anAsciiList;
4360 Handle(TColStd_HSequenceOfTransient) aSeq;
4361 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
4362 if ( aSeq.IsNull() || aSeq->IsEmpty() )
4365 // Make a Python command
4367 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
4368 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
4370 GEOM::TPythonDump(aFunction)
4371 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
4373 << TopAbs_ShapeEnum(theShapeType) << ", "
4374 << theTopLeftPoint << ", "
4375 << theTopRigthPoint << ", "
4376 << theBottomLeftPoint << ", "
4377 << theBottomRigthPoint << ", "
4384 //=======================================================================
4385 //function : GetShapesOnQuadrangleIDs
4387 * \brief Find IDs of sub-shapes complying with given status about quadrangle
4388 * \param theShape - the shape to explore
4389 * \param theShapeType - type of sub-shape of theShape
4390 * \param theTopLeftPoint - top left quadrangle corner
4391 * \param theTopRigthPoint - top right quadrangle corner
4392 * \param theBottomLeftPoint - bottom left quadrangle corner
4393 * \param theBottomRigthPoint - bottom right quadrangle corner
4394 * \param theState - required state
4395 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4397 //=======================================================================
4398 Handle(TColStd_HSequenceOfInteger)
4399 GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4400 const Standard_Integer theShapeType,
4401 const Handle(GEOM_Object)& theTopLeftPoint,
4402 const Handle(GEOM_Object)& theTopRigthPoint,
4403 const Handle(GEOM_Object)& theBottomLeftPoint,
4404 const Handle(GEOM_Object)& theBottomRigthPoint,
4405 const GEOMAlgo_State theState)
4408 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4409 getShapesOnQuadrangleIDs( theShape,
4414 theBottomRigthPoint,
4416 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4419 // Make a Python command
4421 // The GetShapesOnCylinder() doesn't change object so no new function is required.
4422 Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
4423 lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
4424 lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
4425 lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
4426 Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
4428 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
4429 #ifdef DUMP_SUBSHAPE_IDS
4430 GEOM::TPythonDump(aFunction, /*append=*/true)
4431 << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
4433 << TopAbs_ShapeEnum(theShapeType) << ", "
4434 << theTopLeftPoint << ", "
4435 << theTopRigthPoint << ", "
4436 << theBottomLeftPoint << ", "
4437 << theBottomRigthPoint << ", "
4439 #endif // DUMP_SUBSHAPE_IDS
4445 //=============================================================================
4450 //=============================================================================
4451 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
4452 Handle(GEOM_Object) theShapeWhat)
4456 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4458 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4459 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4461 if (aWhere.IsNull() || aWhat.IsNull()) {
4462 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4466 // Searching for the sub-shapes inside the ShapeWhere shape
4467 GEOMAlgo_GetInPlace aGIP;
4469 if (!GEOMAlgo_GetInPlaceAPI::GetInPlace(aWhere, aWhat, aGIP)) {
4470 SetErrorCode("Error in GEOMAlgo_GetInPlace");
4474 // Add direct result.
4475 TopTools_ListOfShape aLSA;
4476 const TopoDS_Shape &aShapeResult = aGIP.Result();
4477 TopTools_MapOfShape aMFence;
4478 TopTools_IndexedMapOfShape aWhereIndices;
4479 Standard_Integer aShapeType = -1;
4481 TopExp::MapShapes(aWhere, aWhereIndices);
4483 if (aShapeResult.IsNull() == Standard_False) {
4484 TopoDS_Iterator anIt(aShapeResult);
4485 Standard_Boolean isFirst = Standard_True;
4487 for (; anIt.More(); anIt.Next()) {
4488 const TopoDS_Shape &aPart = anIt.Value();
4490 if(aWhereIndices.Contains(aPart) && aMFence.Add(aPart)) {
4491 const TopAbs_ShapeEnum aType = aPart.ShapeType();
4493 if (aShapeType == -1) {
4496 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4498 aShapeType = TopAbs_SHAPE;
4506 if (aLSA.Extent() == 0) {
4507 SetErrorCode(NOT_FOUND_ANY); // Not found any Results
4511 Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent());
4512 TopTools_ListIteratorOfListOfShape anIterModif (aLSA);
4513 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4514 aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value()));
4518 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4519 if (aResult.IsNull()) {
4520 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4524 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4526 if ((aModifiedArray->Length() > 1 && isSameType) ||
4527 theShapeWhat->GetType() == GEOM_GROUP) {
4529 aResult->SetType(GEOM_GROUP);
4531 //Set a sub-shape type
4532 TopoDS_Shape aFirstFound = aLSA.First();
4533 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4535 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4536 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4539 //Make a Python command
4540 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4542 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4543 << theShapeWhere << ", " << theShapeWhat << ", True)";
4549 //=============================================================================
4551 * case GetInPlaceOld:
4554 //=============================================================================
4555 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld
4556 (Handle(GEOM_Object) theShapeWhere,
4557 Handle(GEOM_Object) theShapeWhat)
4561 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4563 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4564 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4565 TopTools_ListOfShape aModifiedList;
4566 const Standard_Integer iErr =
4567 GEOMAlgo_GetInPlaceAPI::GetInPlaceOld(aWhere, aWhat, aModifiedList);
4572 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4576 ("Error: An attempt to extract a shape of not supported type.");
4579 SetErrorCode(NOT_FOUND_ANY);
4582 SetErrorCode("Shape driver failed");
4589 TopTools_IndexedMapOfShape aWhereIndices;
4590 TopExp::MapShapes(aWhere, aWhereIndices);
4592 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4593 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4594 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4595 Standard_Integer imod;
4596 Standard_Integer aShapeType = -1;
4598 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4599 const Standard_Integer anIndex =
4600 aWhereIndices.FindIndex(anIterModif.Value());
4601 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4603 if (aShapeType == -1) {
4606 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4608 aShapeType = TopAbs_SHAPE;
4611 aModifiedArray->SetValue(imod, anIndex);
4615 Handle(GEOM_Object) aResult =
4616 GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4618 if (aResult.IsNull()) {
4619 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4623 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4625 if ((aModifiedArray->Length() > 1 && isSameType) ||
4626 theShapeWhat->GetType() == GEOM_GROUP) {
4628 aResult->SetType(GEOM_GROUP);
4630 //Set a sub-shape type
4631 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4632 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4634 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4635 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4638 //Make a Python command
4639 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4641 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4642 << theShapeWhere << ", " << theShapeWhat << ", False)";
4649 //=======================================================================
4650 //function : GetInPlaceByHistory
4652 //=======================================================================
4653 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
4654 (Handle(GEOM_Object) theShapeWhere,
4655 Handle(GEOM_Object) theShapeWhat)
4659 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4661 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4662 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4664 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4666 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4667 if (aWhereFunction.IsNull()) return NULL;
4669 //Fill array of indices
4670 TopTools_IndexedMapOfShape aWhereIndices;
4672 TopExp::MapShapes(aWhere, aWhereIndices);
4675 TopTools_ListOfShape aModifiedList;
4676 bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceByHistory
4677 (aWhereFunction, aWhereIndices, aWhat, aModifiedList);
4679 if (!isFound || aModifiedList.Extent() < 1) {
4680 SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
4684 Handle(TColStd_HArray1OfInteger) aModifiedArray =
4685 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4686 TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4687 Standard_Integer imod;
4688 Standard_Integer aShapeType = -1;
4690 for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4691 const Standard_Integer anIndex =
4692 aWhereIndices.FindIndex(anIterModif.Value());
4693 const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType();
4695 if (aShapeType == -1) {
4698 } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) {
4700 aShapeType = TopAbs_SHAPE;
4703 aModifiedArray->SetValue(imod, anIndex);
4707 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4708 if (aResult.IsNull()) {
4709 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4713 const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE);
4715 if ((aModifiedArray->Length() > 1 && isSameType) ||
4716 theShapeWhat->GetType() == GEOM_GROUP) {
4718 aResult->SetType(GEOM_GROUP);
4720 //Set a sub-shape type
4721 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4722 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4724 TDF_Label aFreeLabel = aResult->GetFreeLabel();
4725 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4728 //Make a Python command
4729 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4731 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
4732 << theShapeWhere << ", " << theShapeWhat << ")";
4738 //=======================================================================
4739 //function : isSameEdge
4740 //purpose : Returns True if two edges coincide
4741 //=======================================================================
4742 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4744 TopoDS_Vertex V11, V12, V21, V22;
4745 TopExp::Vertices(theEdge1, V11, V12);
4746 TopExp::Vertices(theEdge2, V21, V22);
4747 gp_Pnt P11 = BRep_Tool::Pnt(V11);
4748 gp_Pnt P12 = BRep_Tool::Pnt(V12);
4749 gp_Pnt P21 = BRep_Tool::Pnt(V21);
4750 gp_Pnt P22 = BRep_Tool::Pnt(V22);
4751 bool coincide = false;
4753 //Check that ends of edges coincide
4754 if(P11.Distance(P21) <= MAX_TOLERANCE) {
4755 if(P12.Distance(P22) <= MAX_TOLERANCE) coincide = true;
4757 else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4758 if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4761 if(!coincide) return false;
4763 if (BRep_Tool::Degenerated(theEdge1))
4764 if (BRep_Tool::Degenerated(theEdge2)) return true;
4767 if (BRep_Tool::Degenerated(theEdge2)) return false;
4769 double U11, U12, U21, U22;
4770 Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4771 Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4773 //Check that both edges has the same geometry
4774 double range = U12-U11;
4775 double U = U11+ range/3.0;
4776 gp_Pnt P1 = C1->Value(U); //Compute a point on one third of the edge's length
4777 U = U11+range*2.0/3.0;
4778 gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length
4780 C2 = new Geom_TrimmedCurve(C2, U21, U22);
4782 if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22)
4785 if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4787 if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4790 if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4795 //=======================================================================
4796 //function : isSameFace
4797 //purpose : Returns True if two faces coincide
4798 //=======================================================================
4799 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4801 TopExp_Explorer E(theFace1, TopAbs_EDGE);
4802 TopTools_ListOfShape LS1, LS2;
4803 for(; E.More(); E.Next()) LS1.Append(E.Current());
4805 E.Init(theFace2, TopAbs_EDGE);
4806 for(; E.More(); E.Next()) LS2.Append(E.Current());
4808 //Compare the number of edges in the faces
4809 if(LS1.Extent() != LS2.Extent()) return false;
4811 double aMin = RealFirst(), aMax = RealLast();
4812 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4813 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4815 for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4816 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4817 if(P.X() < xminB1) xminB1 = P.X();
4818 if(P.Y() < yminB1) yminB1 = P.Y();
4819 if(P.Z() < zminB1) zminB1 = P.Z();
4820 if(P.X() > xmaxB1) xmaxB1 = P.X();
4821 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4822 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4825 for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4826 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4827 if(P.X() < xminB2) xminB2 = P.X();
4828 if(P.Y() < yminB2) yminB2 = P.Y();
4829 if(P.Z() < zminB2) zminB2 = P.Z();
4830 if(P.X() > xmaxB2) xmaxB2 = P.X();
4831 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4832 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4835 //Compare the bounding boxes of both faces
4836 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4839 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4842 Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4843 Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4845 //Check if there a coincidence of two surfaces at least in two points
4846 double U11, U12, V11, V12, U21, U22, V21, V22;
4847 BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4848 BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4850 double rangeU = U12-U11;
4851 double rangeV = V12-V11;
4852 double U = U11 + rangeU/3.0;
4853 double V = V11 + rangeV/3.0;
4854 gp_Pnt P1 = S1->Value(U, V);
4855 U = U11+rangeU*2.0/3.0;
4856 V = V11+rangeV*2.0/3.0;
4857 gp_Pnt P2 = S1->Value(U, V);
4859 if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4862 if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4864 if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4867 if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
4869 //Check that each edge of the Face1 has a counterpart in the Face2
4870 TopTools_MapOfOrientedShape aMap;
4871 TopTools_ListIteratorOfListOfShape LSI1(LS1);
4872 for(; LSI1.More(); LSI1.Next()) {
4873 TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
4874 bool isFound = false;
4875 TopTools_ListIteratorOfListOfShape LSI2(LS2);
4876 for(; LSI2.More(); LSI2.Next()) {
4877 TopoDS_Shape aValue = LSI2.Value();
4878 if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
4879 if(isSameEdge(E, TopoDS::Edge(aValue))) {
4885 if(!isFound) return false;
4891 //=======================================================================
4892 //function : isSameSolid
4893 //purpose : Returns True if two solids coincide
4894 //=======================================================================
4895 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
4897 TopExp_Explorer E(theSolid1, TopAbs_FACE);
4898 TopTools_ListOfShape LS1, LS2;
4899 for(; E.More(); E.Next()) LS1.Append(E.Current());
4900 E.Init(theSolid2, TopAbs_FACE);
4901 for(; E.More(); E.Next()) LS2.Append(E.Current());
4903 if(LS1.Extent() != LS2.Extent()) return false;
4905 double aMin = RealFirst(), aMax = RealLast();
4906 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4907 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4909 for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
4910 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4911 if(P.X() < xminB1) xminB1 = P.X();
4912 if(P.Y() < yminB1) yminB1 = P.Y();
4913 if(P.Z() < zminB1) zminB1 = P.Z();
4914 if(P.X() > xmaxB1) xmaxB1 = P.X();
4915 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4916 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4919 for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
4920 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4921 if(P.X() < xminB2) xminB2 = P.X();
4922 if(P.Y() < yminB2) yminB2 = P.Y();
4923 if(P.Z() < zminB2) zminB2 = P.Z();
4924 if(P.X() > xmaxB2) xmaxB2 = P.X();
4925 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4926 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4929 //Compare the bounding boxes of both solids
4930 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4933 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4936 //Check that each face of the Solid1 has a counterpart in the Solid2
4937 TopTools_MapOfOrientedShape aMap;
4938 TopTools_ListIteratorOfListOfShape LSI1(LS1);
4939 for(; LSI1.More(); LSI1.Next()) {
4940 TopoDS_Face F = TopoDS::Face(LSI1.Value());
4941 bool isFound = false;
4942 TopTools_ListIteratorOfListOfShape LSI2(LS2);
4943 for(; LSI2.More(); LSI2.Next()) {
4944 if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
4945 if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
4946 aMap.Add(LSI2.Value());
4951 if(!isFound) return false;
4957 //=======================================================================
4958 //function : GetSame
4960 //=======================================================================
4961 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
4962 const Handle(GEOM_Object)& theShapeWhat)
4965 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4967 TopoDS_Shape aWhere = theShapeWhere->GetValue();
4968 TopoDS_Shape aWhat = theShapeWhat->GetValue();
4970 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4973 bool isFound = false;
4974 TopoDS_Shape aSubShape;
4975 TopTools_MapOfShape aMap;
4977 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4978 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4979 if (It.More()) aWhat = It.Value();
4982 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4987 switch (aWhat.ShapeType()) {
4988 case TopAbs_VERTEX: {
4989 aSubShape = getSameVertex(aWhere, TopoDS::Vertex(aWhat));
4990 isFound = !aSubShape.IsNull();
4994 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4995 TopExp_Explorer E(aWhere, TopAbs_EDGE);
4996 for(; E.More(); E.Next()) {
4997 if(!aMap.Add(E.Current())) continue;
4998 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4999 aSubShape = E.Current();
5007 TopoDS_Face aFace = TopoDS::Face(aWhat);
5008 TopExp_Explorer E(aWhere, TopAbs_FACE);
5009 for(; E.More(); E.Next()) {
5010 if(!aMap.Add(E.Current())) continue;
5011 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5012 aSubShape = E.Current();
5019 case TopAbs_SOLID: {
5020 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5021 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5022 for(; E.More(); E.Next()) {
5023 if(!aMap.Add(E.Current())) continue;
5024 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5025 aSubShape = E.Current();
5037 TopTools_IndexedMapOfShape anIndices;
5038 TopExp::MapShapes(aWhere, anIndices);
5039 if (anIndices.Contains(aSubShape))
5040 anIndex = anIndices.FindIndex(aSubShape);
5043 if (anIndex < 0) return NULL;
5045 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
5047 anArray->SetValue(1, anIndex);
5049 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
5050 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
5052 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
5053 << theShapeWhere << ", " << theShapeWhat << ")";
5061 //=======================================================================
5062 //function : GetSameIDs
5064 //=======================================================================
5065 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
5066 (const Handle(GEOM_Object)& theShapeWhere,
5067 const Handle(GEOM_Object)& theShapeWhat)
5070 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
5072 TopoDS_Shape aWhere = theShapeWhere->GetValue();
5073 TopoDS_Shape aWhat = theShapeWhat->GetValue();
5075 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
5077 TopTools_ListOfShape listShape;
5078 TopTools_MapOfShape aMap;
5080 if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
5081 TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
5082 if (It.More()) aWhat = It.Value();
5085 SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
5090 switch (aWhat.ShapeType()) {
5091 case TopAbs_VERTEX: {
5092 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
5093 TopExp_Explorer E(aWhere, TopAbs_VERTEX);
5094 for(; E.More(); E.Next()) {
5095 if(!aMap.Add(E.Current())) continue;
5096 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
5097 if(P.Distance(P2) <= MAX_TOLERANCE) {
5098 listShape.Append(E.Current());
5104 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
5105 TopExp_Explorer E(aWhere, TopAbs_EDGE);
5106 for(; E.More(); E.Next()) {
5107 if(!aMap.Add(E.Current())) continue;
5108 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
5109 listShape.Append(E.Current());
5115 TopoDS_Face aFace = TopoDS::Face(aWhat);
5116 TopExp_Explorer E(aWhere, TopAbs_FACE);
5117 for(; E.More(); E.Next()) {
5118 if(!aMap.Add(E.Current())) continue;
5119 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
5120 listShape.Append(E.Current());
5125 case TopAbs_SOLID: {
5126 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
5127 TopExp_Explorer E(aWhere, TopAbs_SOLID);
5128 for(; E.More(); E.Next()) {
5129 if(!aMap.Add(E.Current())) continue;
5130 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
5131 listShape.Append(E.Current());
5140 if ( !listShape.IsEmpty() ) {
5141 TopTools_IndexedMapOfShape anIndices;
5142 TopExp::MapShapes(aWhere, anIndices);
5143 TopTools_ListIteratorOfListOfShape itSub (listShape);
5144 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
5145 for (; itSub.More(); itSub.Next()) {
5146 if (anIndices.Contains(itSub.Value()))
5147 aSeq->Append(anIndices.FindIndex(itSub.Value()));
5150 // The GetSameIDs() doesn't change object so no new function is required.
5151 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
5153 // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
5154 #ifdef DUMP_SUBSHAPE_IDS
5155 // Make a Python command
5156 GEOM::TPythonDump(aFunction, /*append=*/true)
5157 << "listSameIDs = geompy.GetSameIDs("
5158 << theShapeWhere << ", "
5159 << theShapeWhat << ")";
5160 #endif // DUMP_SUBSHAPE_IDS
5163 SetErrorCode(NOT_FOUND_ANY);
5168 //=======================================================================
5169 //function : ExtendEdge
5171 //=======================================================================
5172 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendEdge
5173 (const Handle(GEOM_Object) &theEdge,
5174 const Standard_Real theMin,
5175 const Standard_Real theMax)
5179 if (theEdge.IsNull()) {
5183 //Add a new Edge object
5184 Handle(GEOM_Object) aResEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
5186 //Add a new Vector function
5187 Handle(GEOM_Function) aFunction =
5188 aResEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_UV);
5190 //Check if the function is set correctly
5191 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5195 GEOMImpl_IShapeExtend aCI (aFunction);
5197 Handle(GEOM_Function) anEdge = theEdge->GetLastFunction();
5199 if (anEdge.IsNull()) {
5203 aCI.SetShape(anEdge);
5204 aCI.SetUMin(theMin);
5205 aCI.SetUMax(theMax);
5207 //Compute the Edge value
5210 if (!GetSolver()->ComputeFunction(aFunction)) {
5211 SetErrorCode("Shape driver failed");
5216 catch (Standard_Failure) {
5217 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
5218 SetErrorCode(aFail->GetMessageString());
5223 //Make a Python command
5224 GEOM::TPythonDump(aFunction)
5225 << aResEdge << " = geompy.ExtendEdge("
5226 << theEdge << ", " << theMin << ", " << theMax << ")";
5233 //=======================================================================
5234 //function : ExtendFace
5236 //=======================================================================
5237 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendFace
5238 (const Handle(GEOM_Object) &theFace,
5239 const Standard_Real theUMin,
5240 const Standard_Real theUMax,
5241 const Standard_Real theVMin,
5242 const Standard_Real theVMax)
5246 if (theFace.IsNull()) {
5250 //Add a new Face object
5251 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
5253 //Add a new Vector function
5254 Handle(GEOM_Function) aFunction =
5255 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_UV);
5257 //Check if the function is set correctly
5258 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5262 GEOMImpl_IShapeExtend aCI (aFunction);
5264 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5266 if (aFace.IsNull()) {
5270 aCI.SetShape(aFace);
5271 aCI.SetUMin(theUMin);
5272 aCI.SetUMax(theUMax);
5273 aCI.SetVMin(theVMin);
5274 aCI.SetVMax(theVMax);
5276 //Compute the Face value
5279 if (!GetSolver()->ComputeFunction(aFunction)) {
5280 SetErrorCode("Shape driver failed");
5285 catch (Standard_Failure) {
5286 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
5287 SetErrorCode(aFail->GetMessageString());
5292 //Make a Python command
5293 GEOM::TPythonDump(aFunction)
5294 << aResFace << " = geompy.ExtendFace("
5295 << theFace << ", " << theUMin << ", " << theUMax << ", "
5296 << theVMin << ", " << theVMax << ")";
5303 //=======================================================================
5304 //function : MakeSurfaceFromFace
5306 //=======================================================================
5307 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSurfaceFromFace
5308 (const Handle(GEOM_Object) &theFace)
5312 if (theFace.IsNull()) {
5316 //Add a new Face object
5317 Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
5319 //Add a new Vector function
5320 Handle(GEOM_Function) aFunction =
5321 aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), SURFACE_FROM_FACE);
5323 //Check if the function is set correctly
5324 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5328 GEOMImpl_IShapeExtend aCI (aFunction);
5330 Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5332 if (aFace.IsNull()) {
5336 aCI.SetShape(aFace);
5338 //Compute the Face value
5341 if (!GetSolver()->ComputeFunction(aFunction)) {
5342 SetErrorCode("Shape driver failed");
5347 catch (Standard_Failure) {
5348 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
5349 SetErrorCode(aFail->GetMessageString());
5354 //Make a Python command
5355 GEOM::TPythonDump(aFunction)
5356 << aResFace << " = geompy.MakeSurfaceFromFace("