1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/
20 #include <Standard_Stream.hxx>
22 #include "GEOMImpl_IShapesOperations.hxx"
24 #include "GEOMImpl_Types.hxx"
26 #include "GEOMImpl_VectorDriver.hxx"
27 #include "GEOMImpl_ShapeDriver.hxx"
28 #include "GEOMImpl_CopyDriver.hxx"
29 #include "GEOMImpl_GlueDriver.hxx"
31 #include "GEOMImpl_IVector.hxx"
32 #include "GEOMImpl_IShapes.hxx"
33 #include "GEOMImpl_IGlue.hxx"
35 #include "GEOMImpl_Block6Explorer.hxx"
37 #include "GEOM_Function.hxx"
38 #include "GEOM_PythonDump.hxx"
40 #include "GEOMAlgo_FinderShapeOn1.hxx"
41 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
43 #include "utilities.h"
45 #include "Utils_ExceptHandlers.hxx"
47 #include <TFunction_DriverTable.hxx>
48 #include <TFunction_Driver.hxx>
49 #include <TFunction_Logbook.hxx>
50 #include <TDataStd_Integer.hxx>
51 #include <TDataStd_IntegerArray.hxx>
52 #include <TDF_Tool.hxx>
54 #include <BRepExtrema_ExtCF.hxx>
56 #include <BRep_Tool.hxx>
57 #include <BRepGProp.hxx>
58 #include <BRepAdaptor_Curve.hxx>
59 #include <BRepBndLib.hxx>
60 #include <BRepBuilderAPI_MakeFace.hxx>
61 #include <BRepMesh_IncrementalMesh.hxx>
66 #include <TopoDS_Shape.hxx>
67 #include <TopoDS_Face.hxx>
68 #include <TopoDS_Edge.hxx>
69 #include <TopoDS_Vertex.hxx>
70 #include <TopoDS_Iterator.hxx>
71 #include <TopExp_Explorer.hxx>
72 #include <TopLoc_Location.hxx>
73 #include <TopTools_MapOfShape.hxx>
74 #include <TopTools_Array1OfShape.hxx>
75 #include <TopTools_ListIteratorOfListOfShape.hxx>
76 #include <TopTools_IndexedMapOfShape.hxx>
78 #include <Geom_Surface.hxx>
79 #include <Geom_Plane.hxx>
80 #include <Geom_SphericalSurface.hxx>
81 #include <Geom_CylindricalSurface.hxx>
82 #include <GeomAdaptor_Surface.hxx>
84 #include <Geom2d_Curve.hxx>
86 #include <Bnd_Box.hxx>
87 #include <GProp_GProps.hxx>
90 #include <TColStd_ListOfInteger.hxx>
91 #include <TColStd_ListIteratorOfListOfInteger.hxx>
92 #include <TColStd_Array1OfReal.hxx>
93 #include <TColStd_HArray1OfInteger.hxx>
97 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
99 //=============================================================================
103 //=============================================================================
104 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
105 : GEOM_IOperations(theEngine, theDocID)
107 MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
110 //=============================================================================
114 //=============================================================================
115 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
117 MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
121 //=============================================================================
125 //=============================================================================
126 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
127 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
131 if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
133 //Add a new Edge object
134 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
136 //Add a new Vector function
137 Handle(GEOM_Function) aFunction =
138 anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
140 //Check if the function is set correctly
141 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
143 GEOMImpl_IVector aPI (aFunction);
145 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
146 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
147 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
149 aPI.SetPoint1(aRef1);
150 aPI.SetPoint2(aRef2);
152 //Compute the Edge value
154 if (!GetSolver()->ComputeFunction(aFunction)) {
155 SetErrorCode("Vector driver failed");
159 catch (Standard_Failure) {
160 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
161 SetErrorCode(aFail->GetMessageString());
165 //Make a Python command
166 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
167 << thePnt1 << ", " << thePnt2 << ")";
173 //=============================================================================
177 //=============================================================================
178 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
179 (list<Handle(GEOM_Object)> theShapes)
181 return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
184 //=============================================================================
188 //=============================================================================
189 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
190 const bool isPlanarWanted)
194 if (theWire.IsNull()) return NULL;
196 //Add a new Face object
197 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
199 //Add a new Shape function for creation of a face from a wire
200 Handle(GEOM_Function) aFunction =
201 aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
202 if (aFunction.IsNull()) return NULL;
204 //Check if the function is set correctly
205 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
207 GEOMImpl_IShapes aCI (aFunction);
209 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
211 if (aRefWire.IsNull()) return NULL;
213 aCI.SetBase(aRefWire);
214 aCI.SetIsPlanar(isPlanarWanted);
216 //Compute the Face value
218 if (!GetSolver()->ComputeFunction(aFunction)) {
219 SetErrorCode("Shape driver failed to compute a face");
223 catch (Standard_Failure) {
224 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
225 SetErrorCode(aFail->GetMessageString());
229 //Make a Python command
230 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
231 << theWire << ", " << (int)isPlanarWanted << ")";
237 //=============================================================================
241 //=============================================================================
242 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
243 (list<Handle(GEOM_Object)> theShapes,
244 const bool isPlanarWanted)
249 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
252 Handle(GEOM_Function) aFunction =
253 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
254 if (aFunction.IsNull()) return NULL;
256 //Check if the function is set correctly
257 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
259 GEOMImpl_IShapes aCI (aFunction);
261 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
264 list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
265 for (; it != theShapes.end(); it++) {
266 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
267 if (aRefSh.IsNull()) {
268 SetErrorCode("NULL argument shape for the face construction");
271 aShapesSeq->Append(aRefSh);
273 aCI.SetShapes(aShapesSeq);
275 aCI.SetIsPlanar(isPlanarWanted);
279 if (!GetSolver()->ComputeFunction(aFunction)) {
280 SetErrorCode("Shape driver failed");
284 catch (Standard_Failure) {
285 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
286 SetErrorCode(aFail->GetMessageString());
290 //Make a Python command
291 GEOM::TPythonDump pd (aFunction);
292 pd << aShape << " = geompy.MakeFaceWires([";
295 it = theShapes.begin();
296 if (it != theShapes.end()) {
298 while (it != theShapes.end()) {
299 pd << ", " << (*it++);
302 pd << "], " << (int)isPlanarWanted << ")";
308 //=============================================================================
312 //=============================================================================
313 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
314 (list<Handle(GEOM_Object)> theShapes)
316 return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
319 //=============================================================================
323 //=============================================================================
324 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
325 (list<Handle(GEOM_Object)> theShapes)
327 return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
330 //=============================================================================
334 //=============================================================================
335 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
339 if (theShell.IsNull()) return NULL;
341 //Add a new Solid object
342 Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
344 //Add a new Solid function for creation of a solid from a shell
345 Handle(GEOM_Function) aFunction =
346 aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
347 if (aFunction.IsNull()) return NULL;
349 //Check if the function is set correctly
350 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
352 GEOMImpl_IShapes aCI (aFunction);
354 Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
356 if (aRefShell.IsNull()) return NULL;
358 aCI.SetBase(aRefShell);
360 //Compute the Solid value
362 if (!GetSolver()->ComputeFunction(aFunction)) {
363 SetErrorCode("Solid driver failed");
367 catch (Standard_Failure) {
368 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
369 SetErrorCode(aFail->GetMessageString());
373 //Make a Python command
374 GEOM::TPythonDump(aFunction) << aSolid
375 << " = geompy.MakeSolid(" << theShell << ")";
381 //=============================================================================
385 //=============================================================================
386 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
387 (list<Handle(GEOM_Object)> theShapes)
389 return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
392 //=============================================================================
396 //=============================================================================
397 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
398 (list<Handle(GEOM_Object)> theShapes,
399 const Standard_Integer theObjectType,
400 const Standard_Integer theFunctionType,
401 const TCollection_AsciiString& theMethodName)
406 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
409 Handle(GEOM_Function) aFunction =
410 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
411 if (aFunction.IsNull()) return NULL;
413 //Check if the function is set correctly
414 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
416 GEOMImpl_IShapes aCI (aFunction);
418 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
421 list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
422 for (; it != theShapes.end(); it++) {
423 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
424 if (aRefSh.IsNull()) {
425 SetErrorCode("NULL argument shape for the shape construction");
428 aShapesSeq->Append(aRefSh);
430 aCI.SetShapes(aShapesSeq);
434 if (!GetSolver()->ComputeFunction(aFunction)) {
435 SetErrorCode("Shape driver failed");
439 catch (Standard_Failure) {
440 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
441 SetErrorCode(aFail->GetMessageString());
445 //Make a Python command
446 GEOM::TPythonDump pd (aFunction);
447 pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
450 it = theShapes.begin();
451 if (it != theShapes.end()) {
453 while (it != theShapes.end()) {
454 pd << ", " << (*it++);
463 //=============================================================================
467 //=============================================================================
468 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
469 (Handle(GEOM_Object) theShape,
470 const Standard_Real theTolerance)
474 if (theShape.IsNull()) return NULL;
476 //Add a new Glued object
477 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
479 //Add a new Glue function
480 Handle(GEOM_Function) aFunction;
481 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
482 if (aFunction.IsNull()) return NULL;
484 //Check if the function is set correctly
485 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
487 GEOMImpl_IGlue aCI (aFunction);
489 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
490 if (aRefShape.IsNull()) return NULL;
492 aCI.SetBase(aRefShape);
493 aCI.SetTolerance(theTolerance);
495 //Compute the sub-shape value
496 Standard_Boolean isWarning = Standard_False;
498 if (!GetSolver()->ComputeFunction(aFunction)) {
499 SetErrorCode("Shape driver failed to glue faces");
503 catch (Standard_Failure) {
504 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
505 SetErrorCode(aFail->GetMessageString());
506 // to provide warning
507 if (!aFunction->GetValue().IsNull()) {
508 isWarning = Standard_True;
514 //Make a Python command
515 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
516 << theShape << ", " << theTolerance << ")";
518 // to provide warning
519 if (!isWarning) SetErrorCode(OK);
523 //=============================================================================
527 //=============================================================================
528 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
529 (Handle(GEOM_Object) theShape,
530 const Standard_Integer theShapeType,
531 const Standard_Boolean isSorted)
535 if (theShape.IsNull()) return NULL;
536 TopoDS_Shape aShape = theShape->GetValue();
537 if (aShape.IsNull()) return NULL;
539 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
540 Handle(GEOM_Object) anObj;
541 Handle(GEOM_Function) aFunction;
542 TopTools_MapOfShape mapShape;
543 TopTools_ListOfShape listShape;
545 if (aShape.ShapeType() == TopAbs_COMPOUND &&
546 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
547 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
548 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
549 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
550 for (; It.More(); It.Next()) {
551 if (mapShape.Add(It.Value())) {
552 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
553 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
554 listShape.Append(It.Value());
559 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
560 for (; exp.More(); exp.Next())
561 if (mapShape.Add(exp.Current()))
562 listShape.Append(exp.Current());
565 if (listShape.IsEmpty()) {
566 SetErrorCode("The given shape has no sub-shapes of the requested type");
571 SortShapes(listShape);
573 TopTools_IndexedMapOfShape anIndices;
574 TopExp::MapShapes(aShape, anIndices);
575 Handle(TColStd_HArray1OfInteger) anArray;
577 TopTools_ListIteratorOfListOfShape itSub (listShape);
578 TCollection_AsciiString anAsciiList, anEntry;
579 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
580 TopoDS_Shape aValue = itSub.Value();
581 anArray = new TColStd_HArray1OfInteger(1,1);
582 anArray->SetValue(1, anIndices.FindIndex(aValue));
583 anObj = GetEngine()->AddSubShape(theShape, anArray);
586 // for python command
587 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
588 anAsciiList += anEntry;
592 //Make a Python command
593 anAsciiList.Trunc(anAsciiList.Length() - 1);
595 aFunction = theShape->GetLastFunction();
597 GEOM::TPythonDump pd (aFunction, /*append=*/true);
598 pd << "[" << anAsciiList.ToCString();
599 pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
600 pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
607 //=============================================================================
611 //=============================================================================
612 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
613 (Handle(GEOM_Object) theShape,
614 const Standard_Integer theShapeType,
615 const Standard_Boolean isSorted)
619 if (theShape.IsNull()) return NULL;
620 TopoDS_Shape aShape = theShape->GetValue();
621 if (aShape.IsNull()) return NULL;
623 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
624 TopTools_MapOfShape mapShape;
625 TopTools_ListOfShape listShape;
627 if (aShape.ShapeType() == TopAbs_COMPOUND &&
628 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
629 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
630 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
631 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
632 for (; It.More(); It.Next()) {
633 if (mapShape.Add(It.Value())) {
634 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
635 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
636 listShape.Append(It.Value());
641 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
642 for (; exp.More(); exp.Next())
643 if (mapShape.Add(exp.Current()))
644 listShape.Append(exp.Current());
647 if (listShape.IsEmpty()) {
648 SetErrorCode("The given shape has no sub-shapes of the requested type");
653 SortShapes(listShape);
655 TopTools_IndexedMapOfShape anIndices;
656 TopExp::MapShapes(aShape, anIndices);
657 Handle(TColStd_HArray1OfInteger) anArray;
659 TopTools_ListIteratorOfListOfShape itSub (listShape);
660 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
661 TopoDS_Shape aValue = itSub.Value();
662 aSeq->Append(anIndices.FindIndex(aValue));
665 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
667 //Make a Python command
668 GEOM::TPythonDump pd (aFunction, /*append=*/true);
669 pd << "listSubShapeIDs = geompy.SubShapeAll";
670 pd << (isSorted ? "SortedIDs(" : "IDs(");
671 pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
677 //=============================================================================
681 //=============================================================================
682 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
683 (Handle(GEOM_Object) theMainShape,
684 const Standard_Integer theID)
688 if (theMainShape.IsNull()) return NULL;
690 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
691 anArray->SetValue(1, theID);
692 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
693 if (anObj.IsNull()) {
694 SetErrorCode("Can not get a sub-shape with the given ID");
698 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
700 //Make a Python command
701 GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
702 << theMainShape << ", [" << theID << "])";
709 //=============================================================================
713 //=============================================================================
714 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
718 Standard_Integer nb = 0;
720 if (theShape.IsNull()) return -1;
721 TopoDS_Shape aShape = theShape->GetValue();
722 if (aShape.IsNull()) return -1;
724 TopTools_MapOfShape mapShape;
726 TopExp_Explorer exp (aShape, TopAbs_FACE);
727 for (; exp.More(); exp.Next())
728 if (mapShape.Add(exp.Current()))
735 //=============================================================================
739 //=============================================================================
740 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
744 Standard_Integer nb = 0;
746 if (theShape.IsNull()) return -1;
747 TopoDS_Shape aShape = theShape->GetValue();
748 if (aShape.IsNull()) return -1;
750 TopTools_MapOfShape mapShape;
752 TopExp_Explorer exp (aShape, TopAbs_EDGE);
753 for (; exp.More(); exp.Next())
754 if (mapShape.Add(exp.Current()))
761 //=============================================================================
765 //=============================================================================
766 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
770 if (theShape.IsNull()) return NULL;
772 //Add a new reversed object
773 Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
775 //Add a new Revese function
776 Handle(GEOM_Function) aFunction;
777 aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
778 if (aFunction.IsNull()) return NULL;
780 //Check if the function is set correctly
781 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
783 GEOMImpl_IShapes aSI (aFunction);
785 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
786 if (aRefShape.IsNull()) return NULL;
788 aSI.SetBase(aRefShape);
790 //Compute the sub-shape value
792 if (!GetSolver()->ComputeFunction(aFunction)) {
793 SetErrorCode("Shape driver failed to reverse shape");
797 catch (Standard_Failure) {
798 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
799 SetErrorCode(aFail->GetMessageString());
803 //Make a Python command
804 GEOM::TPythonDump(aFunction) << aReversed
805 << " = geompy.ChangeOrientation(" << theShape << ")";
811 //=============================================================================
815 //=============================================================================
816 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
817 (Handle(GEOM_Object) theShape)
821 if (theShape.IsNull()) return NULL;
822 TopoDS_Shape aShape = theShape->GetValue();
823 if (aShape.IsNull()) return NULL;
825 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
827 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
828 GEOMImpl_Block6Explorer::MapShapesAndAncestors
829 (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
831 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
834 SetErrorCode("The given shape has no faces");
838 TopTools_IndexedMapOfShape anIndices;
839 TopExp::MapShapes(aShape, anIndices);
842 for (; ind <= nbFaces; ind++) {
843 if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
844 id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
849 //The explode doesn't change object so no new function is required.
850 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
852 //Make a Python command
853 GEOM::TPythonDump(aFunction, /*append=*/true)
854 << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
860 //=======================================================================
861 //function : GetSharedShapes
863 //=======================================================================
865 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
866 (Handle(GEOM_Object) theShape1,
867 Handle(GEOM_Object) theShape2,
868 const Standard_Integer theShapeType)
872 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
874 TopoDS_Shape aShape1 = theShape1->GetValue();
875 TopoDS_Shape aShape2 = theShape2->GetValue();
877 if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
879 TopTools_IndexedMapOfShape anIndices;
880 TopExp::MapShapes(aShape1, anIndices);
881 Handle(TColStd_HArray1OfInteger) anArray;
883 TopTools_IndexedMapOfShape mapShape1;
884 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
886 Handle(GEOM_Object) anObj;
887 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
888 TCollection_AsciiString anAsciiList, anEntry;
890 TopTools_MapOfShape mapShape2;
891 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
892 for (; exp.More(); exp.Next()) {
893 TopoDS_Shape aSS = exp.Current();
894 if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
895 anArray = new TColStd_HArray1OfInteger(1,1);
896 anArray->SetValue(1, anIndices.FindIndex(aSS));
897 anObj = GetEngine()->AddSubShape(theShape1, anArray);
900 // for python command
901 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
902 anAsciiList += anEntry;
907 if (aSeq->IsEmpty()) {
908 SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
912 //Make a Python command
913 anAsciiList.Trunc(anAsciiList.Length() - 1);
915 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
917 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
918 << "] = geompy.GetSharedShapes(" << theShape1 << ", "
919 << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
925 //=============================================================================
929 //=============================================================================
930 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump,
931 const GEOMAlgo_State theState)
935 theDump << "geompy.GEOM.ST_IN";
937 case GEOMAlgo_ST_OUT:
938 theDump << "geompy.GEOM.ST_OUT";
941 theDump << "geompy.GEOM.ST_ON";
943 case GEOMAlgo_ST_ONIN:
944 theDump << "geompy.GEOM.ST_ONIN";
946 case GEOMAlgo_ST_ONOUT:
947 theDump << "geompy.GEOM.ST_ONOUT";
950 theDump << "geompy.GEOM.ST_UNKNOWN";
956 //=======================================================================
957 //function : checkTypeShapesOn
959 * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
960 * \param theShapeType - the shape type to check
961 * \retval bool - result of the check
963 //=======================================================================
965 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
967 if (theShapeType != TopAbs_VERTEX &&
968 theShapeType != TopAbs_EDGE &&
969 theShapeType != TopAbs_FACE &&
970 theShapeType != TopAbs_SOLID) {
971 SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
977 //=======================================================================
978 //function : makePlane
980 * \brief Creates Geom_Plane
981 * \param theAx1 - shape object defining plane parameters
982 * \retval Handle(Geom_Surface) - resulting surface
984 //=======================================================================
986 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
988 if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
989 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
990 TopoDS_Vertex V1, V2;
991 TopExp::Vertices(anEdge, V1, V2, Standard_True);
992 if (V1.IsNull() || V2.IsNull()) {
993 SetErrorCode("Bad edge given for the plane normal vector");
996 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
997 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
998 if (aVec.Magnitude() < Precision::Confusion()) {
999 SetErrorCode("Vector with null magnitude given");
1002 return new Geom_Plane(aLoc, aVec);
1005 //=======================================================================
1006 //function : makeCylinder
1008 * \brief Creates Geom_CylindricalSurface
1009 * \param theAx1 - edge defining cylinder axis
1010 * \param theRadius - cylinder radius
1011 * \retval Handle(Geom_Surface) - resulting surface
1013 //=======================================================================
1015 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
1016 const Standard_Real theRadius)
1018 //Axis of the cylinder
1019 if (anAxis.ShapeType() != TopAbs_EDGE) {
1020 SetErrorCode("Not an edge given for the axis");
1023 TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1024 TopoDS_Vertex V1, V2;
1025 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1026 if (V1.IsNull() || V2.IsNull()) {
1027 SetErrorCode("Bad edge given for the axis");
1030 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1031 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1032 if (aVec.Magnitude() < Precision::Confusion()) {
1033 SetErrorCode("Vector with null magnitude given");
1037 gp_Ax3 anAx3 (aLoc, aVec);
1038 return new Geom_CylindricalSurface(anAx3, theRadius);
1042 //=======================================================================
1043 //function : getShapesOnSurfaceIDs
1045 * \brief Find IDs of subshapes complying with given status about surface
1046 * \param theSurface - the surface to check state of subshapes against
1047 * \param theShape - the shape to explore
1048 * \param theShapeType - type of subshape of theShape
1049 * \param theState - required state
1050 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1052 //=======================================================================
1054 Handle(TColStd_HSequenceOfInteger)
1055 GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
1056 const TopoDS_Shape& theShape,
1057 TopAbs_ShapeEnum theShapeType,
1058 GEOMAlgo_State theState)
1060 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1062 // Check presence of triangulation, build if need
1063 if (!CheckTriangulation(theShape))
1067 GEOMAlgo_FinderShapeOn1 aFinder;
1068 Standard_Real aTol = 0.0001; // default value
1070 aFinder.SetShape(theShape);
1071 aFinder.SetTolerance(aTol);
1072 aFinder.SetSurface(theSurface);
1073 aFinder.SetShapeType(theShapeType);
1074 aFinder.SetState(theState);
1076 // Sets the minimal number of inner points for the faces that do not have own
1077 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1079 aFinder.SetNbPntsMin(3);
1080 // Sets the maximal number of inner points for edges or faces.
1081 // It is usefull for the cases when this number is very big (e.g =2000) to improve
1082 // the performance. If this value =0, all inner points will be taken into account.
1084 aFinder.SetNbPntsMax(100);
1088 // Interprete results
1089 Standard_Integer iErr = aFinder.ErrorStatus();
1090 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1092 MESSAGE(" iErr : " << iErr);
1093 TCollection_AsciiString aMsg (" iErr : ");
1094 aMsg += TCollection_AsciiString(iErr);
1098 Standard_Integer iWrn = aFinder.WarningStatus();
1099 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1101 MESSAGE(" *** iWrn : " << iWrn);
1104 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1106 if (listSS.Extent() < 1) {
1107 SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1111 // Fill sequence of object IDs
1112 aSeqOfIDs = new TColStd_HSequenceOfInteger;
1114 TopTools_IndexedMapOfShape anIndices;
1115 TopExp::MapShapes(theShape, anIndices);
1117 TopTools_ListIteratorOfListOfShape itSub (listSS);
1118 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1119 int id = anIndices.FindIndex(itSub.Value());
1120 aSeqOfIDs->Append(id);
1126 //=======================================================================
1127 //function : getObjectsShapesOn
1129 * \brief Find shape objects and their entries by their ids
1130 * \param theShapeIDs - incoming shape ids
1131 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1132 * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
1134 //=======================================================================
1136 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
1137 getObjectsShapesOn(const Handle(GEOM_Object)& theShape,
1138 const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
1139 TCollection_AsciiString & theShapeEntries)
1141 Handle(TColStd_HSequenceOfTransient) aSeq;
1143 if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
1145 aSeq = new TColStd_HSequenceOfTransient;
1146 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1147 TCollection_AsciiString anEntry;
1148 for ( int i = 1; i <= theShapeIDs->Length(); ++i )
1150 anArray->SetValue(1, theShapeIDs->Value( i ));
1151 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
1152 aSeq->Append( anObj );
1154 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1155 if ( i != 1 ) theShapeEntries += ",";
1156 theShapeEntries += anEntry;
1162 //=======================================================================
1163 //function : getShapesOnSurface
1165 * \brief Find subshapes complying with given status about surface
1166 * \param theSurface - the surface to check state of subshapes against
1167 * \param theShape - the shape to explore
1168 * \param theShapeType - type of subshape of theShape
1169 * \param theState - required state
1170 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1171 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1173 //=======================================================================
1175 Handle(TColStd_HSequenceOfTransient)
1176 GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
1177 const Handle(GEOM_Object)& theShape,
1178 TopAbs_ShapeEnum theShapeType,
1179 GEOMAlgo_State theState,
1180 TCollection_AsciiString & theShapeEntries)
1182 // Find subshapes ids
1183 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1184 getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
1185 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1188 return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
1191 //=============================================================================
1195 //=============================================================================
1196 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
1197 (const Handle(GEOM_Object)& theShape,
1198 const Standard_Integer theShapeType,
1199 const Handle(GEOM_Object)& theAx1,
1200 const GEOMAlgo_State theState)
1204 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1206 TopoDS_Shape aShape = theShape->GetValue();
1207 TopoDS_Shape anAx1 = theAx1->GetValue();
1209 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1211 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1212 if ( !checkTypeShapesOn( theShapeType ))
1216 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1217 if ( aPlane.IsNull() )
1221 TCollection_AsciiString anAsciiList;
1222 Handle(TColStd_HSequenceOfTransient) aSeq;
1223 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1224 if ( aSeq.IsNull() || aSeq->Length() == 0 )
1227 // Make a Python command
1229 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1230 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1232 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1233 << "] = geompy.GetShapesOnPlane(" << theShape << ", "
1234 << aShapeType << ", " << theAx1 << ", " << theState << ")";
1240 //=============================================================================
1242 * GetShapesOnCylinder
1244 //=============================================================================
1245 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
1246 (const Handle(GEOM_Object)& theShape,
1247 const Standard_Integer theShapeType,
1248 const Handle(GEOM_Object)& theAxis,
1249 const Standard_Real theRadius,
1250 const GEOMAlgo_State theState)
1254 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1256 TopoDS_Shape aShape = theShape->GetValue();
1257 TopoDS_Shape anAxis = theAxis->GetValue();
1259 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1261 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1262 if ( !checkTypeShapesOn( aShapeType ))
1265 // Create a cylinder surface
1266 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1267 if ( aCylinder.IsNull() )
1271 TCollection_AsciiString anAsciiList;
1272 Handle(TColStd_HSequenceOfTransient) aSeq;
1273 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
1274 if ( aSeq.IsNull() || aSeq->Length() == 0 )
1277 // Make a Python command
1279 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1280 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1282 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1283 << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
1284 << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
1290 //=============================================================================
1294 //=============================================================================
1295 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
1296 (const Handle(GEOM_Object)& theShape,
1297 const Standard_Integer theShapeType,
1298 const Handle(GEOM_Object)& theCenter,
1299 const Standard_Real theRadius,
1300 const GEOMAlgo_State theState)
1304 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1306 TopoDS_Shape aShape = theShape->GetValue();
1307 TopoDS_Shape aCenter = theCenter->GetValue();
1309 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1311 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1312 if ( !checkTypeShapesOn( aShapeType ))
1315 // Center of the sphere
1316 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1317 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1319 gp_Ax3 anAx3 (aLoc, gp::DZ());
1320 Handle(Geom_SphericalSurface) aSphere =
1321 new Geom_SphericalSurface(anAx3, theRadius);
1324 TCollection_AsciiString anAsciiList;
1325 Handle(TColStd_HSequenceOfTransient) aSeq;
1326 aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
1327 if ( aSeq.IsNull() || aSeq->Length() == 0 )
1330 // Make a Python command
1332 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1333 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1335 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1336 << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
1337 << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
1343 //=============================================================================
1345 * GetShapesOnPlaneIDs
1347 //=============================================================================
1348 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
1349 (const Handle(GEOM_Object)& theShape,
1350 const Standard_Integer theShapeType,
1351 const Handle(GEOM_Object)& theAx1,
1352 const GEOMAlgo_State theState)
1356 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1358 TopoDS_Shape aShape = theShape->GetValue();
1359 TopoDS_Shape anAx1 = theAx1->GetValue();
1361 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1363 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1364 if ( !checkTypeShapesOn( aShapeType ))
1368 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1369 if ( aPlane.IsNull() )
1373 Handle(TColStd_HSequenceOfInteger) aSeq;
1374 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
1376 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
1377 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
1379 // Make a Python command
1380 GEOM::TPythonDump(aFunction, /*append=*/true)
1381 << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
1382 << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
1388 //=============================================================================
1390 * GetShapesOnCylinderIDs
1392 //=============================================================================
1393 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
1394 (const Handle(GEOM_Object)& theShape,
1395 const Standard_Integer theShapeType,
1396 const Handle(GEOM_Object)& theAxis,
1397 const Standard_Real theRadius,
1398 const GEOMAlgo_State theState)
1402 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1404 TopoDS_Shape aShape = theShape->GetValue();
1405 TopoDS_Shape anAxis = theAxis->GetValue();
1407 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1409 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1410 if ( !checkTypeShapesOn( aShapeType ))
1413 // Create a cylinder surface
1414 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1415 if ( aCylinder.IsNull() )
1419 Handle(TColStd_HSequenceOfInteger) aSeq;
1420 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
1422 // The GetShapesOnCylinder() doesn't change object so no new function is required.
1423 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
1425 // Make a Python command
1426 GEOM::TPythonDump(aFunction, /*append=*/true)
1427 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
1428 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
1429 << theRadius << ", " << theState << ")";
1435 //=============================================================================
1437 * GetShapesOnSphereIDs
1439 //=============================================================================
1440 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
1441 (const Handle(GEOM_Object)& theShape,
1442 const Standard_Integer theShapeType,
1443 const Handle(GEOM_Object)& theCenter,
1444 const Standard_Real theRadius,
1445 const GEOMAlgo_State theState)
1449 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1451 TopoDS_Shape aShape = theShape->GetValue();
1452 TopoDS_Shape aCenter = theCenter->GetValue();
1454 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1456 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1457 if ( !checkTypeShapesOn( aShapeType ))
1460 // Center of the sphere
1461 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1462 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1464 gp_Ax3 anAx3 (aLoc, gp::DZ());
1465 Handle(Geom_SphericalSurface) aSphere =
1466 new Geom_SphericalSurface(anAx3, theRadius);
1469 Handle(TColStd_HSequenceOfInteger) aSeq;
1470 aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
1472 // The GetShapesOnSphere() doesn't change object so no new function is required.
1473 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
1475 // Make a Python command
1476 GEOM::TPythonDump(aFunction, /*append=*/true)
1477 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
1478 << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
1479 << theRadius << ", " << theState << ")";
1485 //=======================================================================
1486 //function : getShapesOnQuadrangleIDs
1488 * \brief Find IDs of subshapes complying with given status about quadrangle
1489 * \param theShape - the shape to explore
1490 * \param theShapeType - type of subshape of theShape
1491 * \param theTopLeftPoint - top left quadrangle corner
1492 * \param theTopRigthPoint - top right quadrangle corner
1493 * \param theBottomLeftPoint - bottom left quadrangle corner
1494 * \param theBottomRigthPoint - bottom right quadrangle corner
1495 * \param theState - required state
1496 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1498 //=======================================================================
1500 Handle(TColStd_HSequenceOfInteger)
1501 GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
1502 const Standard_Integer theShapeType,
1503 const Handle(GEOM_Object)& theTopLeftPoint,
1504 const Handle(GEOM_Object)& theTopRigthPoint,
1505 const Handle(GEOM_Object)& theBottomLeftPoint,
1506 const Handle(GEOM_Object)& theBottomRigthPoint,
1507 const GEOMAlgo_State theState)
1511 if ( theShape.IsNull() ||
1512 theTopLeftPoint.IsNull() ||
1513 theTopRigthPoint.IsNull() ||
1514 theBottomLeftPoint.IsNull() ||
1515 theBottomRigthPoint.IsNull() )
1518 TopoDS_Shape aShape = theShape->GetValue();
1519 TopoDS_Shape aTL = theTopLeftPoint->GetValue();
1520 TopoDS_Shape aTR = theTopRigthPoint->GetValue();
1521 TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
1522 TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
1524 if (aShape.IsNull() ||
1529 aTL.ShapeType() != TopAbs_VERTEX ||
1530 aTR.ShapeType() != TopAbs_VERTEX ||
1531 aBL.ShapeType() != TopAbs_VERTEX ||
1532 aBR.ShapeType() != TopAbs_VERTEX )
1535 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1536 if ( !checkTypeShapesOn( aShapeType ))
1539 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1541 // Check presence of triangulation, build if need
1542 if (!CheckTriangulation(aShape))
1546 gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
1547 gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
1548 gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
1549 gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
1551 GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
1552 Standard_Real aTol = 0.0001; // default value
1554 aFinder.SetShape(aShape);
1555 aFinder.SetTolerance(aTol);
1556 //aFinder.SetSurface(theSurface);
1557 aFinder.SetShapeType(aShapeType);
1558 aFinder.SetState(theState);
1560 // Sets the minimal number of inner points for the faces that do not have own
1561 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1563 aFinder.SetNbPntsMin(3);
1564 // Sets the maximal number of inner points for edges or faces.
1565 // It is usefull for the cases when this number is very big (e.g =2000) to improve
1566 // the performance. If this value =0, all inner points will be taken into account.
1568 aFinder.SetNbPntsMax(100);
1572 // Interprete results
1573 Standard_Integer iErr = aFinder.ErrorStatus();
1574 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1576 MESSAGE(" iErr : " << iErr);
1577 TCollection_AsciiString aMsg (" iErr : ");
1578 aMsg += TCollection_AsciiString(iErr);
1582 Standard_Integer iWrn = aFinder.WarningStatus();
1583 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1585 MESSAGE(" *** iWrn : " << iWrn);
1588 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1590 if (listSS.Extent() < 1) {
1591 SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1595 // Fill sequence of object IDs
1596 aSeqOfIDs = new TColStd_HSequenceOfInteger;
1598 TopTools_IndexedMapOfShape anIndices;
1599 TopExp::MapShapes(aShape, anIndices);
1601 TopTools_ListIteratorOfListOfShape itSub (listSS);
1602 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1603 int id = anIndices.FindIndex(itSub.Value());
1604 aSeqOfIDs->Append(id);
1609 //=======================================================================
1610 //function : GetShapesOnQuadrangle
1612 * \brief Find subshapes complying with given status about quadrangle
1613 * \param theShape - the shape to explore
1614 * \param theShapeType - type of subshape of theShape
1615 * \param theTopLeftPoint - top left quadrangle corner
1616 * \param theTopRigthPoint - top right quadrangle corner
1617 * \param theBottomLeftPoint - bottom left quadrangle corner
1618 * \param theBottomRigthPoint - bottom right quadrangle corner
1619 * \param theState - required state
1620 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1622 //=======================================================================
1624 Handle(TColStd_HSequenceOfTransient)
1625 GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
1626 const Standard_Integer theShapeType,
1627 const Handle(GEOM_Object)& theTopLeftPoint,
1628 const Handle(GEOM_Object)& theTopRigthPoint,
1629 const Handle(GEOM_Object)& theBottomLeftPoint,
1630 const Handle(GEOM_Object)& theBottomRigthPoint,
1631 const GEOMAlgo_State theState)
1634 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1635 getShapesOnQuadrangleIDs( theShape,
1640 theBottomRigthPoint,
1642 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
1645 // Find objects by indices
1646 TCollection_AsciiString anAsciiList;
1647 Handle(TColStd_HSequenceOfTransient) aSeq;
1648 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1649 if ( aSeq.IsNull() || aSeq->IsEmpty() )
1652 // Make a Python command
1654 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1655 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1657 GEOM::TPythonDump(aFunction)
1658 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
1660 << TopAbs_ShapeEnum(theShapeType) << ", "
1661 << theTopLeftPoint << ", "
1662 << theTopRigthPoint << ", "
1663 << theBottomLeftPoint << ", "
1664 << theBottomRigthPoint << ", "
1671 //=======================================================================
1672 //function : GetShapesOnQuadrangleIDs
1674 * \brief Find IDs of subshapes complying with given status about quadrangle
1675 * \param theShape - the shape to explore
1676 * \param theShapeType - type of subshape of theShape
1677 * \param theTopLeftPoint - top left quadrangle corner
1678 * \param theTopRigthPoint - top right quadrangle corner
1679 * \param theBottomLeftPoint - bottom left quadrangle corner
1680 * \param theBottomRigthPoint - bottom right quadrangle corner
1681 * \param theState - required state
1682 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1684 //=======================================================================
1686 Handle(TColStd_HSequenceOfInteger)
1687 GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
1688 const Standard_Integer theShapeType,
1689 const Handle(GEOM_Object)& theTopLeftPoint,
1690 const Handle(GEOM_Object)& theTopRigthPoint,
1691 const Handle(GEOM_Object)& theBottomLeftPoint,
1692 const Handle(GEOM_Object)& theBottomRigthPoint,
1693 const GEOMAlgo_State theState)
1696 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1697 getShapesOnQuadrangleIDs( theShape,
1702 theBottomRigthPoint,
1704 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
1707 // Make a Python command
1709 // The GetShapesOnCylinder() doesn't change object so no new function is required.
1710 Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
1711 lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
1712 lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
1713 lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
1714 Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
1716 GEOM::TPythonDump(aFunction, /*append=*/true)
1717 << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
1719 << TopAbs_ShapeEnum(theShapeType) << ", "
1720 << theTopLeftPoint << ", "
1721 << theTopRigthPoint << ", "
1722 << theBottomLeftPoint << ", "
1723 << theBottomRigthPoint << ", "
1731 //=============================================================================
1735 //=============================================================================
1736 static void SimplifyWhat (TopoDS_Shape& theWhat,
1737 TopTools_IndexedMapOfShape& theArgumentIndices,
1738 TColStd_ListOfInteger& theSimpleSubWhat)
1740 TopTools_MapOfShape mapShape;
1741 TopoDS_Iterator It (theWhat, Standard_True, Standard_True);
1742 for (; It.More(); It.Next()) {
1743 if (mapShape.Add(It.Value())) {
1744 TopoDS_Shape curSh = It.Value();
1745 if (curSh.ShapeType() == TopAbs_COMPOUND ||
1746 curSh.ShapeType() == TopAbs_COMPSOLID) {
1747 SimplifyWhat(curSh, theArgumentIndices, theSimpleSubWhat);
1749 theSimpleSubWhat.Append(theArgumentIndices.FindIndex(curSh));
1755 static bool GetInPlaceOfCompound (Handle(GEOM_Function)& theWhereFunction,
1756 TopoDS_Shape& theWhat,
1757 TColStd_ListOfInteger& theModifiedArray)
1759 bool isFoundAny = false;
1760 TopTools_MapOfShape mapShape;
1761 TopoDS_Iterator It (theWhat, Standard_True, Standard_True);
1762 for (; It.More(); It.Next()) {
1763 if (mapShape.Add(It.Value())) {
1764 TopoDS_Shape curWhat = It.Value();
1765 if (curWhat.ShapeType() == TopAbs_COMPOUND ||
1766 curWhat.ShapeType() == TopAbs_COMPSOLID) {
1767 // Recursive call for compound or compsolid
1768 if (GetInPlaceOfCompound(theWhereFunction, curWhat, theModifiedArray))
1771 // Try to find for "simple" shape
1772 bool isFound = false;
1774 TDF_LabelSequence aLabelSeq;
1775 theWhereFunction->GetDependency(aLabelSeq);
1776 Standard_Integer nbArg = aLabelSeq.Length();
1778 for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
1780 TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
1782 Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
1783 TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
1785 TopTools_IndexedMapOfShape anArgumentIndices;
1786 TopExp::MapShapes(anArgumentShape, anArgumentIndices);
1788 if (anArgumentIndices.Contains(curWhat)) {
1789 isFound = Standard_True;
1790 Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(curWhat);
1792 // Find corresponding label in history
1793 TDF_Label anArgumentHistoryLabel =
1794 theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
1795 if (!anArgumentHistoryLabel.IsNull()) {
1796 TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
1797 if (!aWhatHistoryLabel.IsNull()) {
1798 Handle(TDataStd_IntegerArray) anIntegerArray;
1799 if (aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
1800 Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
1801 for (imod = 1; imod <= aModifLen; imod++) {
1802 theModifiedArray.Append(anIntegerArray->Array()->Value(imod));
1817 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
1818 (Handle(GEOM_Object) theShapeWhere,
1819 Handle(GEOM_Object) theShapeWhat)
1823 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
1825 TopoDS_Shape aWhere = theShapeWhere->GetValue();
1826 TopoDS_Shape aWhat = theShapeWhat->GetValue();
1828 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
1830 //Fill array of indices
1831 Handle(TColStd_HArray1OfInteger) aModifiedArray;
1833 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
1835 TopTools_IndexedMapOfShape aWhereIndices;
1836 TopExp::MapShapes(aWhere, aWhereIndices);
1838 if (aWhereIndices.Contains(aWhat)) {
1840 // entity was not changed by the operation
1841 Standard_Integer aWhatIndex = aWhereIndices.FindIndex(aWhat);
1842 aModifiedArray = new TColStd_HArray1OfInteger(1,1);
1843 aModifiedArray->SetValue(1, aWhatIndex);
1847 TDF_Label aHistoryLabel = aWhereFunction->GetHistoryEntry(Standard_False);
1848 if (aHistoryLabel.IsNull()) {
1849 SetErrorCode("Modifications history does not exist for the shape under consideration.");
1853 // search in history for all argument shapes
1854 Standard_Boolean isFound = Standard_False;
1856 TDF_LabelSequence aLabelSeq;
1857 aWhereFunction->GetDependency(aLabelSeq);
1858 Standard_Integer nbArg = aLabelSeq.Length();
1860 for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
1862 TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
1864 Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
1865 TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
1867 TopTools_IndexedMapOfShape anArgumentIndices;
1868 TopExp::MapShapes(anArgumentShape, anArgumentIndices);
1870 if (anArgumentIndices.Contains(aWhat)) {
1871 isFound = Standard_True;
1872 Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(aWhat);
1874 // Find corresponding label in history
1875 TDF_Label anArgumentHistoryLabel =
1876 aWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
1877 if (anArgumentHistoryLabel.IsNull()) {
1878 // Lost History of operation argument. Possibly, all its entities was removed.
1883 TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
1884 if (aWhatHistoryLabel.IsNull()) {
1885 // Check, if the sought shape is Compound or Compsolid.
1886 // In that case we will try to find history for its sub-shapes
1887 if (aWhat.ShapeType() == TopAbs_COMPOUND ||
1888 aWhat.ShapeType() == TopAbs_COMPSOLID) {
1889 TColStd_ListOfInteger aSimpleSubWhat, aModifiedList;
1890 SimplifyWhat(aWhat, anArgumentIndices, aSimpleSubWhat);
1891 TColStd_ListIteratorOfListOfInteger anIterSub (aSimpleSubWhat);
1892 for (; anIterSub.More(); anIterSub.Next()) {
1893 Standard_Integer aSubWhatIndex = anIterSub.Value();
1894 TDF_Label aSubWhatHistoryLabel =
1895 anArgumentHistoryLabel.FindChild(aSubWhatIndex, Standard_False);
1896 if (!aSubWhatHistoryLabel.IsNull()) {
1897 Handle(TDataStd_IntegerArray) anIntegerArray;
1898 if (aSubWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
1899 for (Standard_Integer isub = 1; isub <= anIntegerArray->Length(); isub++) {
1900 aModifiedList.Append(anIntegerArray->Value(isub));
1905 if (aModifiedList.Extent() > 0) {
1906 Handle(TColStd_HArray1OfInteger) aModifiedArraySub =
1907 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
1908 TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
1909 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
1910 aModifiedArraySub->SetValue(imod, anIterModif.Value());
1912 aModifiedArray = aModifiedArraySub;
1924 Handle(TDataStd_IntegerArray) anIntegerArray;
1925 if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
1926 SetErrorCode("Error: Empty modifications history for the sought shape.");
1930 aModifiedArray = anIntegerArray->Array();
1931 if (aModifiedArray->Length() == 0) {
1932 SetErrorCode("Error: Empty modifications history for the sought shape.");
1940 // try compound element by element
1941 if (aWhat.ShapeType() == TopAbs_COMPOUND ||
1942 aWhat.ShapeType() == TopAbs_COMPSOLID) {
1943 TColStd_ListOfInteger aModifiedList;
1944 isFound = GetInPlaceOfCompound(aWhereFunction, aWhat, aModifiedList);
1946 aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
1947 TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
1948 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
1949 aModifiedArray->SetValue(imod, anIterModif.Value());
1954 SetErrorCode("The sought shape does not belong to any operation argument.");
1961 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
1963 if (aModifiedArray->Length() > 1) {
1965 aResult->SetType(GEOM_GROUP);
1967 //Set a sub shape type
1968 TDF_Label aFreeLabel = aResult->GetFreeLabel();
1969 TopAbs_ShapeEnum aShapeType = aWhat.ShapeType();
1970 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
1973 //Make a Python command
1974 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
1976 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
1977 << theShapeWhere << ", " << theShapeWhat << ")";
1983 //=======================================================================
1984 //function : SortShapes
1986 //=======================================================================
1987 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
1989 Standard_Integer MaxShapes = SL.Extent();
1990 TopTools_Array1OfShape aShapes (1,MaxShapes);
1991 TColStd_Array1OfInteger OrderInd(1,MaxShapes);
1992 TColStd_Array1OfReal MidXYZ (1,MaxShapes); //X,Y,Z;
1993 TColStd_Array1OfReal Length (1,MaxShapes); //X,Y,Z;
1995 // Computing of CentreOfMass
1996 Standard_Integer Index;
1999 TopTools_ListIteratorOfListOfShape it(SL);
2000 for (Index=1; it.More(); Index++)
2002 TopoDS_Shape S = it.Value();
2003 SL.Remove( it ); // == it.Next()
2005 OrderInd.SetValue (Index, Index);
2006 if (S.ShapeType() == TopAbs_VERTEX)
2008 GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
2009 Length.SetValue( Index, (Standard_Real) S.Orientation());
2013 BRepGProp::LinearProperties (S, GPr);
2014 GPoint = GPr.CentreOfMass();
2015 Length.SetValue( Index, GPr.Mass() );
2017 MidXYZ.SetValue(Index,
2018 GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
2022 Standard_Integer aTemp;
2023 Standard_Boolean exchange, Sort = Standard_True;
2026 Sort = Standard_False;
2027 for (Index=1; Index < MaxShapes; Index++)
2029 if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
2030 exchange = Standard_True;
2031 else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
2032 Length(OrderInd(Index)) > Length(OrderInd(Index+1)) )
2033 exchange = Standard_True;
2035 exchange = Standard_False;
2038 aTemp = OrderInd(Index);
2039 OrderInd(Index) = OrderInd(Index+1);
2040 OrderInd(Index+1) = aTemp;
2041 Sort = Standard_True;
2045 for (Index=1; Index <= MaxShapes; Index++)
2046 SL.Append( aShapes( OrderInd(Index) ));
2049 //=======================================================================
2050 //function : CheckTriangulation
2052 //=======================================================================
2053 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
2055 TopExp_Explorer exp (aShape, TopAbs_FACE);
2057 SetErrorCode("Shape without faces given");
2061 TopLoc_Location aTopLoc;
2062 Handle(Poly_Triangulation) aTRF;
2063 aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
2064 if (aTRF.IsNull()) {
2065 // calculate deflection
2066 Standard_Real aDeviationCoefficient = 0.001;
2069 BRepBndLib::Add(aShape, B);
2070 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
2071 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
2073 Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
2074 Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
2075 Standard_Real aHLRAngle = 0.349066;
2077 BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);