1 // Copyright (C) 2007-2010 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.
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
22 // File : GEOMImpl_IShapesOperations.cxx
24 // 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_CopyDriver.hxx"
37 #include "GEOMImpl_GlueDriver.hxx"
39 #include "GEOMImpl_IVector.hxx"
40 #include "GEOMImpl_IShapes.hxx"
41 #include "GEOMImpl_IGlue.hxx"
43 #include "GEOMImpl_Block6Explorer.hxx"
45 #include "GEOM_Function.hxx"
46 #include "GEOM_ISubShape.hxx"
47 #include "GEOM_PythonDump.hxx"
49 #include "GEOMAlgo_FinderShapeOn1.hxx"
50 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
51 #include "GEOMAlgo_FinderShapeOn2.hxx"
52 #include "GEOMAlgo_ClsfBox.hxx"
53 #include "GEOMAlgo_ClsfSolid.hxx"
54 #include "GEOMAlgo_Gluer1.hxx"
55 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
56 #include "GEOMAlgo_CoupleOfShapes.hxx"
57 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
59 #include "utilities.h"
61 #include "Utils_ExceptHandlers.hxx"
63 #include <TFunction_DriverTable.hxx>
64 #include <TFunction_Driver.hxx>
65 #include <TFunction_Logbook.hxx>
66 #include <TDataStd_Integer.hxx>
67 #include <TDataStd_IntegerArray.hxx>
68 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
69 #include <TDF_Tool.hxx>
71 #include <BRepExtrema_ExtCF.hxx>
72 #include <BRepExtrema_DistShapeShape.hxx>
74 #include <BRep_Tool.hxx>
75 #include <BRep_Builder.hxx>
76 #include <BRepTools.hxx>
77 #include <BRepGProp.hxx>
78 #include <BRepAdaptor_Curve.hxx>
79 #include <BRepAdaptor_Surface.hxx>
80 #include <BRepBndLib.hxx>
81 #include <BRepBuilderAPI_MakeFace.hxx>
82 #include <BRepMesh_IncrementalMesh.hxx>
87 #include <TopoDS_Shape.hxx>
88 #include <TopoDS_Solid.hxx>
89 #include <TopoDS_Face.hxx>
90 #include <TopoDS_Edge.hxx>
91 #include <TopoDS_Vertex.hxx>
92 #include <TopoDS_Compound.hxx>
93 #include <TopoDS_Iterator.hxx>
94 #include <TopExp_Explorer.hxx>
95 #include <TopLoc_Location.hxx>
96 #include <TopTools_MapOfShape.hxx>
97 #include <TopTools_MapOfOrientedShape.hxx>
98 #include <TopTools_Array1OfShape.hxx>
99 #include <TopTools_ListIteratorOfListOfShape.hxx>
100 #include <TopTools_IndexedMapOfShape.hxx>
102 #include <Geom_Surface.hxx>
103 #include <Geom_Plane.hxx>
104 #include <Geom_SphericalSurface.hxx>
105 #include <Geom_CylindricalSurface.hxx>
106 #include <GeomAdaptor_Surface.hxx>
108 #include <GeomLib_Tool.hxx>
109 #include <Geom2d_Curve.hxx>
111 #include <Bnd_Box.hxx>
112 #include <GProp_GProps.hxx>
113 #include <TColStd_Array1OfReal.hxx>
114 #include <TColStd_HArray1OfInteger.hxx>
115 #include <TColStd_ListIteratorOfListOfInteger.hxx>
116 #include <TColStd_ListOfInteger.hxx>
117 #include <gp_Cylinder.hxx>
118 #include <gp_Lin.hxx>
119 #include <gp_Pnt.hxx>
123 #include <Standard_NullObject.hxx>
124 #include <Standard_Failure.hxx>
125 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
127 // Includes added for GetInPlace algorithm improvement
129 #include <GEOMImpl_MeasureDriver.hxx>
130 #include <GEOMImpl_IMeasure.hxx>
131 #include <BRepBuilderAPI_MakeVertex.hxx>
133 #include <BRepClass_FaceClassifier.hxx>
134 #include <BRepClass3d_SolidClassifier.hxx>
135 #include <Precision.hxx>
137 //=============================================================================
141 //=============================================================================
142 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
143 : GEOM_IOperations(theEngine, theDocID)
145 MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
148 //=============================================================================
152 //=============================================================================
153 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
155 MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
158 //=============================================================================
162 //=============================================================================
163 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
164 (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
168 if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
170 //Add a new Edge object
171 Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
173 //Add a new Vector function
174 Handle(GEOM_Function) aFunction =
175 anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
177 //Check if the function is set correctly
178 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
180 GEOMImpl_IVector aPI (aFunction);
182 Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
183 Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
184 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
186 aPI.SetPoint1(aRef1);
187 aPI.SetPoint2(aRef2);
189 //Compute the Edge value
191 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
194 if (!GetSolver()->ComputeFunction(aFunction)) {
195 SetErrorCode("Vector driver failed");
199 catch (Standard_Failure) {
200 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
201 SetErrorCode(aFail->GetMessageString());
205 //Make a Python command
206 GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
207 << thePnt1 << ", " << thePnt2 << ")";
213 //=============================================================================
217 //=============================================================================
218 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
219 (std::list<Handle(GEOM_Object)> theShapes,
220 const Standard_Real theTolerance)
225 Handle(GEOM_Object) aWire = GetEngine()->AddObject(GetDocID(), GEOM_WIRE);
228 Handle(GEOM_Function) aFunction =
229 aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES);
230 if (aFunction.IsNull()) return NULL;
232 //Check if the function is set correctly
233 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
235 GEOMImpl_IShapes aCI (aFunction);
236 aCI.SetTolerance(theTolerance);
238 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
241 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
242 for (; it != theShapes.end(); it++) {
243 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
244 if (aRefSh.IsNull()) {
245 SetErrorCode("NULL argument shape for the shape construction");
248 aShapesSeq->Append(aRefSh);
250 aCI.SetShapes(aShapesSeq);
254 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
257 if (!GetSolver()->ComputeFunction(aFunction)) {
258 SetErrorCode("Shape driver failed");
262 catch (Standard_Failure) {
263 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
264 SetErrorCode(aFail->GetMessageString());
268 //Make a Python command
269 GEOM::TPythonDump pd (aFunction);
270 pd << aWire << " = geompy.MakeWire([";
273 it = theShapes.begin();
274 if (it != theShapes.end()) {
276 while (it != theShapes.end()) {
277 pd << ", " << (*it++);
280 pd << "], " << theTolerance << ")";
286 //=============================================================================
290 //=============================================================================
291 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
292 const bool isPlanarWanted)
296 if (theWire.IsNull()) return NULL;
298 //Add a new Face object
299 Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
301 //Add a new Shape function for creation of a face from a wire
302 Handle(GEOM_Function) aFunction =
303 aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
304 if (aFunction.IsNull()) return NULL;
306 //Check if the function is set correctly
307 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
309 GEOMImpl_IShapes aCI (aFunction);
311 Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
313 if (aRefWire.IsNull()) return NULL;
315 aCI.SetBase(aRefWire);
316 aCI.SetIsPlanar(isPlanarWanted);
318 //Compute the Face value
320 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
323 if (!GetSolver()->ComputeFunction(aFunction)) {
324 SetErrorCode("Shape driver failed to compute a face");
328 catch (Standard_Failure) {
329 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
330 SetErrorCode(aFail->GetMessageString());
334 //Make a Python command
335 GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
336 << theWire << ", " << (int)isPlanarWanted << ")";
342 //=============================================================================
346 //=============================================================================
347 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
348 (std::list<Handle(GEOM_Object)> theShapes,
349 const bool isPlanarWanted)
354 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
357 Handle(GEOM_Function) aFunction =
358 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
359 if (aFunction.IsNull()) return NULL;
361 //Check if the function is set correctly
362 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
364 GEOMImpl_IShapes aCI (aFunction);
366 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
369 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
370 for (; it != theShapes.end(); it++) {
371 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
372 if (aRefSh.IsNull()) {
373 SetErrorCode("NULL argument shape for the face construction");
376 aShapesSeq->Append(aRefSh);
378 aCI.SetShapes(aShapesSeq);
380 aCI.SetIsPlanar(isPlanarWanted);
384 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
387 if (!GetSolver()->ComputeFunction(aFunction)) {
388 SetErrorCode("Shape driver failed");
392 catch (Standard_Failure) {
393 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
394 SetErrorCode(aFail->GetMessageString());
398 //Make a Python command
399 GEOM::TPythonDump pd (aFunction);
400 pd << aShape << " = geompy.MakeFaceWires([";
403 it = theShapes.begin();
404 if (it != theShapes.end()) {
406 while (it != theShapes.end()) {
407 pd << ", " << (*it++);
410 pd << "], " << (int)isPlanarWanted << ")";
416 //=============================================================================
420 //=============================================================================
421 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
422 (std::list<Handle(GEOM_Object)> theShapes)
424 return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
427 //=============================================================================
431 //=============================================================================
432 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
433 (std::list<Handle(GEOM_Object)> theShapes)
435 return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
438 //=============================================================================
442 //=============================================================================
443 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
444 (std::list<Handle(GEOM_Object)> theShapes)
446 return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
449 //=============================================================================
453 //=============================================================================
454 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
455 (std::list<Handle(GEOM_Object)> theShapes,
456 const Standard_Integer theObjectType,
457 const Standard_Integer theFunctionType,
458 const TCollection_AsciiString& theMethodName)
463 Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
466 Handle(GEOM_Function) aFunction =
467 aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
468 if (aFunction.IsNull()) return NULL;
470 //Check if the function is set correctly
471 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
473 GEOMImpl_IShapes aCI (aFunction);
475 Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
478 std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
479 for (; it != theShapes.end(); it++) {
480 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
481 if (aRefSh.IsNull()) {
482 SetErrorCode("NULL argument shape for the shape construction");
485 aShapesSeq->Append(aRefSh);
487 aCI.SetShapes(aShapesSeq);
491 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
494 if (!GetSolver()->ComputeFunction(aFunction)) {
495 SetErrorCode("Shape driver failed");
499 catch (Standard_Failure) {
500 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
501 SetErrorCode(aFail->GetMessageString());
505 //Make a Python command
506 GEOM::TPythonDump pd (aFunction);
507 pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
510 it = theShapes.begin();
511 if (it != theShapes.end()) {
513 while (it != theShapes.end()) {
514 pd << ", " << (*it++);
523 //=============================================================================
527 //=============================================================================
528 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
529 (Handle(GEOM_Object) theShape,
530 const Standard_Real theTolerance,
531 const Standard_Boolean doKeepNonSolids)
535 if (theShape.IsNull()) return NULL;
537 //Add a new Glued object
538 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
540 //Add a new Glue function
541 Handle(GEOM_Function) aFunction;
542 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
543 if (aFunction.IsNull()) return NULL;
545 //Check if the function is set correctly
546 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
548 GEOMImpl_IGlue aCI (aFunction);
550 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
551 if (aRefShape.IsNull()) return NULL;
553 aCI.SetBase(aRefShape);
554 aCI.SetTolerance(theTolerance);
555 aCI.SetKeepNonSolids(doKeepNonSolids);
557 //Compute the sub-shape value
558 Standard_Boolean isWarning = Standard_False;
560 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
563 if (!GetSolver()->ComputeFunction(aFunction)) {
564 SetErrorCode("Shape driver failed to glue faces");
568 catch (Standard_Failure) {
569 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
570 SetErrorCode(aFail->GetMessageString());
571 // to provide warning
572 if (!aFunction->GetValue().IsNull()) {
573 isWarning = Standard_True;
579 //Make a Python command
580 GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
581 << theShape << ", " << theTolerance << ")";
583 // to provide warning
584 if (!isWarning) SetErrorCode(OK);
588 //=============================================================================
592 //=============================================================================
593 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
594 (Handle(GEOM_Object) theShape,
595 const Standard_Real theTolerance)
599 if (theShape.IsNull()) return NULL;
600 TopoDS_Shape aShape = theShape->GetValue();
601 if (aShape.IsNull()) return NULL;
603 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
605 Standard_Integer iErr;
607 GEOMAlgo_Gluer1 aGluer;
608 GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
609 GEOMAlgo_CoupleOfShapes aCS;
610 GEOMAlgo_ListOfCoupleOfShapes aLCS;
612 //aGluer = new GEOMAlgo_Gluer1;
613 aGluer.SetShape(aShape);
614 aGluer.SetTolerance(theTolerance);
616 iErr = aGluer.ErrorStatus();
617 if (iErr) return NULL;
619 TopTools_ListOfShape listShape;
620 const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
622 aItCS.Initialize(aLCSG);
623 for (; aItCS.More(); aItCS.Next()) {
624 const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
625 listShape.Append(aCSG.Shape1());
628 TopTools_ListIteratorOfListOfShape itSub (listShape);
629 TCollection_AsciiString anAsciiList, anEntry;
630 TopTools_IndexedMapOfShape anIndices;
631 TopExp::MapShapes(aShape, anIndices);
632 Handle(TColStd_HArray1OfInteger) anArray;
633 Handle(GEOM_Object) anObj;
634 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
635 TopoDS_Shape aValue = itSub.Value();
636 anArray = new TColStd_HArray1OfInteger(1,1);
637 anArray->SetValue(1, anIndices.FindIndex(aValue));
638 anObj = GetEngine()->AddSubShape(theShape, anArray);
639 if (!anObj.IsNull()) {
642 // for python command
643 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
644 anAsciiList += anEntry;
649 //Make a Python command
650 if( anAsciiList.Length() > 0 ) {
651 anAsciiList.Trunc(anAsciiList.Length() - 1);
652 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
653 GEOM::TPythonDump pd (aFunction, /*append=*/true);
654 pd << "[" << anAsciiList.ToCString();
655 pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
663 //=============================================================================
665 * MakeGlueFacesByList
667 //=============================================================================
668 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList
669 (Handle(GEOM_Object) theShape,
670 const Standard_Real theTolerance,
671 std::list<Handle(GEOM_Object)> theFaces,
672 const Standard_Boolean doKeepNonSolids)
676 if (theShape.IsNull()) return NULL;
678 //Add a new Glued object
679 Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
681 //Add a new Glue function
682 Handle(GEOM_Function) aFunction;
683 aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
684 if (aFunction.IsNull()) return NULL;
686 //Check if the function is set correctly
687 if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
689 GEOMImpl_IGlue aCI (aFunction);
691 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
692 if (aRefShape.IsNull()) return NULL;
694 aCI.SetBase(aRefShape);
695 aCI.SetTolerance(theTolerance);
696 aCI.SetKeepNonSolids(doKeepNonSolids);
698 Handle(TColStd_HSequenceOfTransient) aFaces = new TColStd_HSequenceOfTransient;
699 std::list<Handle(GEOM_Object)>::iterator it = theFaces.begin();
700 for (; it != theFaces.end(); it++) {
701 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
702 if (aRefSh.IsNull()) {
703 SetErrorCode("NULL argument shape for the shape construction");
706 aFaces->Append(aRefSh);
708 aCI.SetFaces(aFaces);
710 //Compute the sub-shape value
711 Standard_Boolean isWarning = Standard_False;
713 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
716 if (!GetSolver()->ComputeFunction(aFunction)) {
717 SetErrorCode("Shape driver failed to glue faces");
721 catch (Standard_Failure) {
722 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
723 SetErrorCode(aFail->GetMessageString());
724 // to provide warning
725 if (!aFunction->GetValue().IsNull()) {
726 isWarning = Standard_True;
732 //Make a Python command
734 GEOM::TPythonDump pd(aFunction);
735 pd << aGlued << " = geompy.MakeGlueFacesByList("
736 << theShape << ", " << theTolerance << ", [";
738 it = theFaces.begin();
739 if (it != theFaces.end()) {
741 while (it != theFaces.end()) {
742 pd << ", " << (*it++);
747 // to provide warning
748 if (!isWarning) SetErrorCode(OK);
752 //=============================================================================
754 * GetExistingSubObjects
756 //=============================================================================
757 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetExistingSubObjects
758 (Handle(GEOM_Object) theShape,
759 const Standard_Boolean theGroupsOnly)
763 if (theShape.IsNull()) return NULL;
765 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
766 if (aMainShape.IsNull()) return NULL;
768 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
769 SetErrorCode(NOT_FOUND_ANY);
771 if (!aMainShape->HasSubShapeReferences()) return aSeq;
772 const TDataStd_ListOfExtendedString& aListEntries = aMainShape->GetSubShapeReferences();
773 if (aListEntries.IsEmpty()) return aSeq;
777 TCollection_AsciiString anAsciiList;
779 TDataStd_ListIteratorOfListOfExtendedString anIt (aListEntries);
780 for (; anIt.More(); anIt.Next()) {
781 TCollection_ExtendedString anEntry = anIt.Value();
782 Standard_Integer aStrLen = anEntry.LengthOfCString();
783 char* anEntryStr = new char[aStrLen];
784 anEntry.ToUTF8CString(anEntryStr);
785 Handle(GEOM_Object) anObj = GetEngine()->GetObject(GetDocID(), anEntryStr, false);
786 if (!anObj.IsNull()) {
787 if (!theGroupsOnly || anObj->GetType() == GEOM_GROUP) {
790 // for python command
791 anAsciiList += anEntryStr;
795 delete [] anEntryStr;
798 if (aSeq->Length() == 0) {
799 SetErrorCode(NOT_FOUND_ANY);
803 //Make a Python command
804 anAsciiList.Trunc(anAsciiList.Length() - 1);
806 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
807 pd << "[" << anAsciiList.ToCString();
808 pd << "] = geompy.GetExistingSubObjects(";
809 pd << theShape << ", " << (int)theGroupsOnly << ")";
816 //=============================================================================
820 //=============================================================================
821 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
822 (Handle(GEOM_Object) theShape,
823 const Standard_Integer theShapeType,
824 const Standard_Boolean isSorted)
828 if (theShape.IsNull()) return NULL;
829 TopoDS_Shape aShape = theShape->GetValue();
830 if (aShape.IsNull()) return NULL;
832 Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
834 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
835 Handle(GEOM_Object) anObj;
836 TopTools_MapOfShape mapShape;
837 TopTools_ListOfShape listShape;
839 if (aShape.ShapeType() == TopAbs_COMPOUND &&
840 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
841 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
842 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
843 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
844 for (; It.More(); It.Next()) {
845 if (mapShape.Add(It.Value())) {
846 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
847 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
848 listShape.Append(It.Value());
853 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
854 for (; exp.More(); exp.Next())
855 if (mapShape.Add(exp.Current()))
856 listShape.Append(exp.Current());
859 if (listShape.IsEmpty()) {
860 //SetErrorCode("The given shape has no sub-shapes of the requested type");
861 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
866 SortShapes(listShape);
868 TopTools_IndexedMapOfShape anIndices;
869 TopExp::MapShapes(aShape, anIndices);
870 Handle(TColStd_HArray1OfInteger) anArray;
872 TopTools_ListIteratorOfListOfShape itSub (listShape);
873 TCollection_AsciiString anAsciiList, anEntry;
874 for (int index = 1; itSub.More(); itSub.Next(), ++index)
876 TopoDS_Shape aValue = itSub.Value();
877 anArray = new TColStd_HArray1OfInteger(1,1);
878 anArray->SetValue(1, anIndices.FindIndex(aValue));
880 //anObj = GetEngine()->AddSubShape(theShape, anArray);
882 anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
883 Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
884 if (aFunction.IsNull()) return aSeq;
886 GEOM_ISubShape aSSI (aFunction);
887 aSSI.SetMainShape(aMainShape);
888 aSSI.SetIndices(anArray);
890 // Set function value directly, as we know it.
891 // Usage of Solver here would lead to significant loss of time,
892 // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
893 // on the main shape for each being calculated sub-shape separately.
894 aFunction->SetValue(aValue);
897 if (!anObj.IsNull()) {
900 // for python command
901 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
902 anAsciiList += anEntry;
907 //Make a Python command
908 anAsciiList.Trunc(anAsciiList.Length() - 1);
910 GEOM::TPythonDump pd (aMainShape, /*append=*/true);
911 pd << "[" << anAsciiList.ToCString();
912 pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
913 pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
920 //=============================================================================
924 //=============================================================================
925 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
926 (Handle(GEOM_Object) theShape,
927 const Standard_Integer theShapeType,
928 const Standard_Boolean isSorted)
932 if (theShape.IsNull()) return NULL;
933 TopoDS_Shape aShape = theShape->GetValue();
934 if (aShape.IsNull()) return NULL;
936 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
937 TopTools_MapOfShape mapShape;
938 TopTools_ListOfShape listShape;
940 if (aShape.ShapeType() == TopAbs_COMPOUND &&
941 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
942 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
943 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
944 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
945 for (; It.More(); It.Next()) {
946 if (mapShape.Add(It.Value())) {
947 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
948 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
949 listShape.Append(It.Value());
954 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
955 for (; exp.More(); exp.Next())
956 if (mapShape.Add(exp.Current()))
957 listShape.Append(exp.Current());
960 if (listShape.IsEmpty()) {
961 //SetErrorCode("The given shape has no sub-shapes of the requested type");
962 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
967 SortShapes(listShape);
969 TopTools_IndexedMapOfShape anIndices;
970 TopExp::MapShapes(aShape, anIndices);
971 Handle(TColStd_HArray1OfInteger) anArray;
973 TopTools_ListIteratorOfListOfShape itSub (listShape);
974 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
975 TopoDS_Shape aValue = itSub.Value();
976 aSeq->Append(anIndices.FindIndex(aValue));
979 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
981 //Make a Python command
982 GEOM::TPythonDump pd (aFunction, /*append=*/true);
983 pd << "listSubShapeIDs = geompy.SubShapeAll";
984 pd << (isSorted ? "SortedIDs(" : "IDs(");
985 pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
991 //=============================================================================
995 //=============================================================================
996 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
997 (Handle(GEOM_Object) theMainShape,
998 const Standard_Integer theID)
1002 if (theMainShape.IsNull()) return NULL;
1004 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1005 anArray->SetValue(1, theID);
1006 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
1007 if (anObj.IsNull()) {
1008 SetErrorCode("Can not get a sub-shape with the given ID");
1012 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1014 //Make a Python command
1015 GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1016 << theMainShape << ", [" << theID << "])";
1022 //=============================================================================
1026 //=============================================================================
1027 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1028 Handle(GEOM_Object) theSubShape)
1032 TopoDS_Shape aMainShape = theMainShape->GetValue();
1033 TopoDS_Shape aSubShape = theSubShape->GetValue();
1035 if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1037 TopTools_IndexedMapOfShape anIndices;
1038 TopExp::MapShapes(aMainShape, anIndices);
1039 if (anIndices.Contains(aSubShape)) {
1041 return anIndices.FindIndex(aSubShape);
1047 //=============================================================================
1051 //=============================================================================
1052 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1053 Handle(GEOM_Object) theSubShape)
1057 TopoDS_Shape aMainShape = theMainShape->GetValue();
1058 TopoDS_Shape aSubShape = theSubShape->GetValue();
1060 if (aMainShape.IsNull() || aSubShape.IsNull()) {
1061 SetErrorCode("Null argument shape given");
1066 if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1068 TopTools_ListOfShape CL;
1069 CL.Append(aMainShape);
1070 TopTools_ListIteratorOfListOfShape itC;
1071 for (itC.Initialize(CL); itC.More(); itC.Next()) {
1072 for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1073 if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1074 if (it.Value().IsSame(aSubShape))
1078 CL.Append(it.Value());
1083 TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1084 TopTools_MapOfShape M;
1085 for (; anExp.More(); anExp.Next()) {
1086 if (M.Add(anExp.Current())) {
1087 if (anExp.Current().IsSame(aSubShape))
1094 SetErrorCode("The sub-shape does not belong to the main shape");
1098 //=============================================================================
1100 * GetShapeTypeString
1102 //=============================================================================
1103 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1107 TCollection_AsciiString aTypeName ("Null Shape");
1109 TopoDS_Shape aShape = theShape->GetValue();
1110 if (aShape.IsNull())
1113 switch (aShape.ShapeType() )
1115 case TopAbs_COMPOUND:
1116 aTypeName = "Compound";
1118 case TopAbs_COMPSOLID:
1119 aTypeName = "Compound Solid";
1122 aTypeName = "Solid";
1125 aTypeName = "Shell";
1129 BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1130 if (surf.GetType() == GeomAbs_Plane)
1131 aTypeName = "Plane";
1132 else if (surf.GetType() == GeomAbs_Cylinder)
1133 aTypeName = "Cylindrical Face";
1134 else if (surf.GetType() == GeomAbs_Sphere)
1135 aTypeName = "Spherical Face";
1136 else if (surf.GetType() == GeomAbs_Torus)
1137 aTypeName = "Toroidal Face";
1138 else if (surf.GetType() == GeomAbs_Cone)
1139 aTypeName = "Conical Face";
1141 aTypeName = "GEOM::FACE";
1149 BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1150 if (curv.GetType() == GeomAbs_Line) {
1151 if ((Abs(curv.FirstParameter()) >= 1E6) ||
1152 (Abs(curv.LastParameter()) >= 1E6))
1156 } else if (curv.GetType() == GeomAbs_Circle) {
1157 if (curv.IsClosed())
1158 aTypeName = "Circle";
1167 aTypeName = "Vertex";
1170 aTypeName = "Shape";
1173 aTypeName = "Shape of unknown type";
1179 //=============================================================================
1183 //=============================================================================
1184 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
1185 (Handle(GEOM_Object) theShape,
1186 const Standard_Integer theShapeType)
1189 Standard_Integer nbShapes = 0;
1191 if (theShape.IsNull()) return -1;
1192 TopoDS_Shape aShape = theShape->GetValue();
1193 if (aShape.IsNull()) return -1;
1196 TopTools_MapOfShape mapShape;
1198 if (aShape.ShapeType() == TopAbs_COMPOUND &&
1199 (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1200 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
1201 TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
1202 TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1203 for (; It.More(); It.Next()) {
1204 if (mapShape.Add(It.Value())) {
1205 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1206 TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
1212 TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1213 for (; exp.More(); exp.Next())
1214 if (mapShape.Add(exp.Current()))
1220 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1223 int iType, nbTypes [TopAbs_SHAPE];
1224 for (iType = 0; iType < TopAbs_SHAPE; ++iType)
1226 nbTypes[aShape.ShapeType()]++;
1228 TopTools_MapOfShape aMapOfShape;
1229 aMapOfShape.Add(aShape);
1230 TopTools_ListOfShape aListOfShape;
1231 aListOfShape.Append(aShape);
1233 TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1234 for (; itL.More(); itL.Next()) {
1235 TopoDS_Iterator it (itL.Value());
1236 for (; it.More(); it.Next()) {
1237 TopoDS_Shape s = it.Value();
1238 if (aMapOfShape.Add(s)) {
1239 aListOfShape.Append(s);
1240 nbTypes[s.ShapeType()]++;
1245 if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
1246 nbShapes = aMapOfShape.Extent();
1248 nbShapes = nbTypes[theShapeType];
1250 catch (Standard_Failure) {
1251 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1252 SetErrorCode(aFail->GetMessageString());
1260 //=============================================================================
1264 //=============================================================================
1265 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
1269 if (theShape.IsNull()) return NULL;
1271 //Add a new reversed object
1272 Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
1274 //Add a new Revese function
1275 Handle(GEOM_Function) aFunction;
1276 aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
1277 if (aFunction.IsNull()) return NULL;
1279 //Check if the function is set correctly
1280 if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
1282 GEOMImpl_IShapes aSI (aFunction);
1284 Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1285 if (aRefShape.IsNull()) return NULL;
1287 aSI.SetBase(aRefShape);
1289 //Compute the sub-shape value
1291 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1294 if (!GetSolver()->ComputeFunction(aFunction)) {
1295 SetErrorCode("Shape driver failed to reverse shape");
1299 catch (Standard_Failure) {
1300 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1301 SetErrorCode(aFail->GetMessageString());
1305 //Make a Python command
1306 GEOM::TPythonDump(aFunction) << aReversed
1307 << " = geompy.ChangeOrientation(" << theShape << ")";
1313 //=============================================================================
1317 //=============================================================================
1318 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
1319 (Handle(GEOM_Object) theShape)
1323 if (theShape.IsNull()) return NULL;
1324 TopoDS_Shape aShape = theShape->GetValue();
1325 if (aShape.IsNull()) return NULL;
1327 Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1329 TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1330 GEOMImpl_Block6Explorer::MapShapesAndAncestors
1331 (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1333 Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1336 SetErrorCode("The given shape has no faces");
1340 TopTools_IndexedMapOfShape anIndices;
1341 TopExp::MapShapes(aShape, anIndices);
1343 Standard_Integer id;
1344 for (; ind <= nbFaces; ind++) {
1345 if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1346 id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1351 //The explode doesn't change object so no new function is required.
1352 Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1354 //Make a Python command
1355 GEOM::TPythonDump(aFunction, /*append=*/true)
1356 << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
1362 //=======================================================================
1363 //function : GetSharedShapes
1365 //=======================================================================
1366 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1367 (Handle(GEOM_Object) theShape1,
1368 Handle(GEOM_Object) theShape2,
1369 const Standard_Integer theShapeType)
1373 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
1375 TopoDS_Shape aShape1 = theShape1->GetValue();
1376 TopoDS_Shape aShape2 = theShape2->GetValue();
1378 if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
1380 TopTools_IndexedMapOfShape anIndices;
1381 TopExp::MapShapes(aShape1, anIndices);
1382 Handle(TColStd_HArray1OfInteger) anArray;
1384 TopTools_IndexedMapOfShape mapShape1;
1385 TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
1387 Handle(GEOM_Object) anObj;
1388 Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1389 TCollection_AsciiString anAsciiList, anEntry;
1391 TopTools_MapOfShape mapShape2;
1392 TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
1393 for (; exp.More(); exp.Next()) {
1394 TopoDS_Shape aSS = exp.Current();
1395 if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
1396 anArray = new TColStd_HArray1OfInteger(1,1);
1397 anArray->SetValue(1, anIndices.FindIndex(aSS));
1398 anObj = GetEngine()->AddSubShape(theShape1, anArray);
1399 aSeq->Append(anObj);
1401 // for python command
1402 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1403 anAsciiList += anEntry;
1408 if (aSeq->IsEmpty()) {
1409 SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
1413 //Make a Python command
1414 anAsciiList.Trunc(anAsciiList.Length() - 1);
1416 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1418 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1419 << "] = geompy.GetSharedShapes(" << theShape1 << ", "
1420 << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1426 //=============================================================================
1430 //=============================================================================
1431 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump,
1432 const GEOMAlgo_State theState)
1435 case GEOMAlgo_ST_IN:
1436 theDump << "geompy.GEOM.ST_IN";
1438 case GEOMAlgo_ST_OUT:
1439 theDump << "geompy.GEOM.ST_OUT";
1441 case GEOMAlgo_ST_ON:
1442 theDump << "geompy.GEOM.ST_ON";
1444 case GEOMAlgo_ST_ONIN:
1445 theDump << "geompy.GEOM.ST_ONIN";
1447 case GEOMAlgo_ST_ONOUT:
1448 theDump << "geompy.GEOM.ST_ONOUT";
1451 theDump << "geompy.GEOM.ST_UNKNOWN";
1457 //=======================================================================
1458 //function : checkTypeShapesOn
1460 * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
1461 * \param theShapeType - the shape type to check
1462 * \retval bool - result of the check
1464 //=======================================================================
1465 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
1467 if (theShapeType != TopAbs_VERTEX &&
1468 theShapeType != TopAbs_EDGE &&
1469 theShapeType != TopAbs_FACE &&
1470 theShapeType != TopAbs_SOLID) {
1471 SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1477 //=======================================================================
1478 //function : makePlane
1480 * \brief Creates Geom_Plane
1481 * \param theAx1 - shape object defining plane parameters
1482 * \retval Handle(Geom_Surface) - resulting surface
1484 //=======================================================================
1485 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
1487 if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1488 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1489 TopoDS_Vertex V1, V2;
1490 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1491 if (V1.IsNull() || V2.IsNull()) {
1492 SetErrorCode("Bad edge given for the plane normal vector");
1495 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1496 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1497 if (aVec.Magnitude() < Precision::Confusion()) {
1498 SetErrorCode("Vector with null magnitude given");
1501 return new Geom_Plane(aLoc, aVec);
1504 //=======================================================================
1505 //function : makeCylinder
1507 * \brief Creates Geom_CylindricalSurface
1508 * \param theAx1 - edge defining cylinder axis
1509 * \param theRadius - cylinder radius
1510 * \retval Handle(Geom_Surface) - resulting surface
1512 //=======================================================================
1513 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
1514 const Standard_Real theRadius)
1516 //Axis of the cylinder
1517 if (anAxis.ShapeType() != TopAbs_EDGE) {
1518 SetErrorCode("Not an edge given for the axis");
1521 TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1522 TopoDS_Vertex V1, V2;
1523 TopExp::Vertices(anEdge, V1, V2, Standard_True);
1524 if (V1.IsNull() || V2.IsNull()) {
1525 SetErrorCode("Bad edge given for the axis");
1528 gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1529 gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1530 if (aVec.Magnitude() < Precision::Confusion()) {
1531 SetErrorCode("Vector with null magnitude given");
1535 gp_Ax3 anAx3 (aLoc, aVec);
1536 return new Geom_CylindricalSurface(anAx3, theRadius);
1539 //=======================================================================
1540 //function : getShapesOnBoxIDs
1542 * \brief Find IDs of subshapes complying with given status about surface
1543 * \param theBox - the box to check state of subshapes against
1544 * \param theShape - the shape to explore
1545 * \param theShapeType - type of subshape of theShape
1546 * \param theState - required state
1547 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1549 //=======================================================================
1550 Handle(TColStd_HSequenceOfInteger)
1551 GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1552 const Handle(GEOM_Object)& theShape,
1553 const Standard_Integer theShapeType,
1554 GEOMAlgo_State theState)
1556 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1558 TopoDS_Shape aBox = theBox->GetValue();
1559 TopoDS_Shape aShape = theShape->GetValue();
1561 // Check presence of triangulation, build if need
1562 if (!CheckTriangulation(aShape)) {
1563 SetErrorCode("Cannot build triangulation on the shape");
1568 GEOMAlgo_FinderShapeOn2 aFinder;
1569 Standard_Real aTol = 0.0001; // default value
1571 Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
1572 aClsfBox->SetBox(aBox);
1574 aFinder.SetShape(aShape);
1575 aFinder.SetTolerance(aTol);
1576 aFinder.SetClsf(aClsfBox);
1577 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1578 aFinder.SetState(theState);
1581 // Interprete results
1582 Standard_Integer iErr = aFinder.ErrorStatus();
1583 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1585 MESSAGE(" iErr : " << iErr);
1586 TCollection_AsciiString aMsg (" iErr : ");
1587 aMsg += TCollection_AsciiString(iErr);
1591 Standard_Integer iWrn = aFinder.WarningStatus();
1592 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1594 MESSAGE(" *** iWrn : " << iWrn);
1597 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1599 if (listSS.Extent() < 1) {
1600 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1601 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1605 // Fill sequence of object IDs
1606 aSeqOfIDs = new TColStd_HSequenceOfInteger;
1608 TopTools_IndexedMapOfShape anIndices;
1609 TopExp::MapShapes(aShape, anIndices);
1611 TopTools_ListIteratorOfListOfShape itSub (listSS);
1612 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1613 int id = anIndices.FindIndex(itSub.Value());
1614 aSeqOfIDs->Append(id);
1620 //=======================================================================
1621 //function : GetShapesOnBoxIDs
1623 * \brief Find subshapes complying with given status about surface
1624 * \param theBox - the box to check state of subshapes against
1625 * \param theShape - the shape to explore
1626 * \param theShapeType - type of subshape of theShape
1627 * \param theState - required state
1628 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1630 //=======================================================================
1631 Handle(TColStd_HSequenceOfInteger)
1632 GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1633 const Handle(GEOM_Object)& theShape,
1634 const Standard_Integer theShapeType,
1635 GEOMAlgo_State theState)
1637 // Find subshapes ids
1638 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1639 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1640 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1643 // The GetShapesOnBox() doesn't change object so no new function is required.
1644 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
1646 // Make a Python command
1647 GEOM::TPythonDump(aFunction)
1648 << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
1651 << TopAbs_ShapeEnum(theShapeType) << ", "
1658 //=======================================================================
1659 //function : GetShapesOnBox
1661 * \brief Find subshapes complying with given status about surface
1662 * \param theBox - the box to check state of subshapes against
1663 * \param theShape - the shape to explore
1664 * \param theShapeType - type of subshape of theShape
1665 * \param theState - required state
1666 * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1668 //=======================================================================
1669 Handle(TColStd_HSequenceOfTransient)
1670 GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
1671 const Handle(GEOM_Object)& theShape,
1672 const Standard_Integer theShapeType,
1673 GEOMAlgo_State theState)
1675 // Find subshapes ids
1676 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1677 getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1678 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1681 // Find objects by indices
1682 TCollection_AsciiString anAsciiList;
1683 Handle(TColStd_HSequenceOfTransient) aSeq;
1684 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1685 if ( aSeq.IsNull() || aSeq->IsEmpty() )
1688 // Make a Python command
1690 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1691 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1693 GEOM::TPythonDump(aFunction)
1694 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
1697 << TopAbs_ShapeEnum(theShapeType) << ", "
1704 //=======================================================================
1705 //function : getShapesOnShapeIDs
1707 * \brief Find IDs of subshapes complying with given status about surface
1708 * \param theCheckShape - the shape to check state of subshapes against
1709 * \param theShape - the shape to explore
1710 * \param theShapeType - type of subshape of theShape
1711 * \param theState - required state
1712 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1714 //=======================================================================
1715 Handle(TColStd_HSequenceOfInteger)
1716 GEOMImpl_IShapesOperations::getShapesOnShapeIDs
1717 (const Handle(GEOM_Object)& theCheckShape,
1718 const Handle(GEOM_Object)& theShape,
1719 const Standard_Integer theShapeType,
1720 GEOMAlgo_State theState)
1722 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1724 TopoDS_Shape aCheckShape = theCheckShape->GetValue();
1725 TopoDS_Shape aShape = theShape->GetValue();
1726 TopTools_ListOfShape res;
1728 // Check presence of triangulation, build if need
1729 if (!CheckTriangulation(aShape)) {
1730 SetErrorCode("Cannot build triangulation on the shape");
1735 GEOMAlgo_FinderShapeOn2 aFinder;
1736 Standard_Real aTol = 0.0001; // default value
1738 Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
1739 aClsfSolid->SetShape(aCheckShape);
1741 aFinder.SetShape(aShape);
1742 aFinder.SetTolerance(aTol);
1743 aFinder.SetClsf(aClsfSolid);
1744 aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1745 aFinder.SetState(theState);
1748 // Interprete results
1749 Standard_Integer iErr = aFinder.ErrorStatus();
1750 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1753 SetErrorCode("theCheckShape must be a solid");
1756 MESSAGE(" iErr : " << iErr);
1757 TCollection_AsciiString aMsg (" iErr : ");
1758 aMsg += TCollection_AsciiString(iErr);
1763 Standard_Integer iWrn = aFinder.WarningStatus();
1764 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1766 MESSAGE(" *** iWrn : " << iWrn);
1769 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1771 if (listSS.Extent() < 1) {
1772 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1773 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1776 // Fill sequence of object IDs
1777 aSeqOfIDs = new TColStd_HSequenceOfInteger;
1779 TopTools_IndexedMapOfShape anIndices;
1780 TopExp::MapShapes(aShape, anIndices);
1782 TopTools_ListIteratorOfListOfShape itSub (listSS);
1783 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1784 int id = anIndices.FindIndex(itSub.Value());
1785 aSeqOfIDs->Append(id);
1791 //=======================================================================
1792 //function : GetShapesOnShapeIDs
1794 * \brief Find subshapes complying with given status about surface
1795 * \param theCheckShape - the shape to check state of subshapes against
1796 * \param theShape - the shape to explore
1797 * \param theShapeType - type of subshape of theShape
1798 * \param theState - required state
1799 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1801 //=======================================================================
1802 Handle(TColStd_HSequenceOfInteger)
1803 GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
1804 (const Handle(GEOM_Object)& theCheckShape,
1805 const Handle(GEOM_Object)& theShape,
1806 const Standard_Integer theShapeType,
1807 GEOMAlgo_State theState)
1809 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1810 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1812 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1815 // The GetShapesOnShape() doesn't change object so no new function is required.
1816 Handle(GEOM_Function) aFunction =
1817 GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
1819 // Make a Python command
1820 GEOM::TPythonDump(aFunction)
1821 << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs("
1822 << theCheckShape << ", "
1824 << TopAbs_ShapeEnum(theShapeType) << ", "
1831 //=======================================================================
1832 //function : GetShapesOnShape
1834 * \brief Find subshapes complying with given status about surface
1835 * \param theCheckShape - the shape to check state of subshapes against
1836 * \param theShape - the shape to explore
1837 * \param theShapeType - type of subshape of theShape
1838 * \param theState - required state
1839 * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1841 //=======================================================================
1842 Handle(TColStd_HSequenceOfTransient)
1843 GEOMImpl_IShapesOperations::GetShapesOnShape
1844 (const Handle(GEOM_Object)& theCheckShape,
1845 const Handle(GEOM_Object)& theShape,
1846 const Standard_Integer theShapeType,
1847 GEOMAlgo_State theState)
1849 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1850 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1851 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1854 // Find objects by indices
1855 TCollection_AsciiString anAsciiList;
1856 Handle(TColStd_HSequenceOfTransient) aSeq;
1857 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1859 if ( aSeq.IsNull() || aSeq->IsEmpty() )
1862 // Make a Python command
1864 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1865 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1867 GEOM::TPythonDump(aFunction)
1868 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
1869 << theCheckShape << ", "
1871 << TopAbs_ShapeEnum(theShapeType) << ", "
1878 //=======================================================================
1879 //function : GetShapesOnShapeAsCompound
1880 //=======================================================================
1881 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
1882 (const Handle(GEOM_Object)& theCheckShape,
1883 const Handle(GEOM_Object)& theShape,
1884 const Standard_Integer theShapeType,
1885 GEOMAlgo_State theState)
1887 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1888 getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
1890 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
1893 // Find objects by indices
1894 TCollection_AsciiString anAsciiList;
1895 Handle(TColStd_HSequenceOfTransient) aSeq;
1896 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1898 if ( aSeq.IsNull() || aSeq->IsEmpty() )
1901 TopoDS_Compound aCompound;
1903 B.MakeCompound(aCompound);
1905 for(; i<=aSeq->Length(); i++) {
1906 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
1907 TopoDS_Shape aShape_i = anObj->GetValue();
1908 B.Add(aCompound,aShape_i);
1911 //Add a new result object
1912 Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
1913 Handle(GEOM_Function) aFunction =
1914 aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
1915 aFunction->SetValue(aCompound);
1917 GEOM::TPythonDump(aFunction)
1918 << aRes << " = geompy.GetShapesOnShapeAsCompound("
1919 << theCheckShape << ", "
1921 << TopAbs_ShapeEnum(theShapeType) << ", "
1929 //=======================================================================
1930 //function : getShapesOnSurfaceIDs
1932 * \brief Find IDs of subshapes complying with given status about surface
1933 * \param theSurface - the surface to check state of subshapes against
1934 * \param theShape - the shape to explore
1935 * \param theShapeType - type of subshape of theShape
1936 * \param theState - required state
1937 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1939 //=======================================================================
1940 Handle(TColStd_HSequenceOfInteger)
1941 GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
1942 const TopoDS_Shape& theShape,
1943 TopAbs_ShapeEnum theShapeType,
1944 GEOMAlgo_State theState)
1946 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1948 // Check presence of triangulation, build if need
1949 if (!CheckTriangulation(theShape)) {
1950 SetErrorCode("Cannot build triangulation on the shape");
1954 // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
1955 // Compute tolerance
1956 Standard_Real T, VertMax = -RealLast();
1958 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1961 for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1962 TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
1963 T = BRep_Tool::Tolerance(Vertex);
1968 catch (Standard_Failure) {
1969 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1970 SetErrorCode(aFail->GetMessageString());
1973 // END: Mantis issue 0020961
1976 GEOMAlgo_FinderShapeOn1 aFinder;
1977 //Standard_Real aTol = 0.0001; // default value
1978 Standard_Real aTol = VertMax; // Mantis issue 0020961
1980 aFinder.SetShape(theShape);
1981 aFinder.SetTolerance(aTol);
1982 aFinder.SetSurface(theSurface);
1983 aFinder.SetShapeType(theShapeType);
1984 aFinder.SetState(theState);
1986 // Sets the minimal number of inner points for the faces that do not have own
1987 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1989 aFinder.SetNbPntsMin(3);
1990 // Sets the maximal number of inner points for edges or faces.
1991 // It is usefull for the cases when this number is very big (e.g =2000) to improve
1992 // the performance. If this value =0, all inner points will be taken into account.
1994 aFinder.SetNbPntsMax(100);
1998 // Interprete results
1999 Standard_Integer iErr = aFinder.ErrorStatus();
2000 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2002 MESSAGE(" iErr : " << iErr);
2003 TCollection_AsciiString aMsg (" iErr : ");
2004 aMsg += TCollection_AsciiString(iErr);
2008 Standard_Integer iWrn = aFinder.WarningStatus();
2009 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2011 MESSAGE(" *** iWrn : " << iWrn);
2014 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2016 if (listSS.Extent() < 1) {
2017 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2018 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2022 // Fill sequence of object IDs
2023 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2025 TopTools_IndexedMapOfShape anIndices;
2026 TopExp::MapShapes(theShape, anIndices);
2028 TopTools_ListIteratorOfListOfShape itSub (listSS);
2029 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2030 int id = anIndices.FindIndex(itSub.Value());
2031 aSeqOfIDs->Append(id);
2037 //=======================================================================
2038 //function : getObjectsShapesOn
2040 * \brief Find shape objects and their entries by their ids
2041 * \param theShapeIDs - incoming shape ids
2042 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
2043 * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
2045 //=======================================================================
2046 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
2047 getObjectsShapesOn(const Handle(GEOM_Object)& theShape,
2048 const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
2049 TCollection_AsciiString & theShapeEntries)
2051 Handle(TColStd_HSequenceOfTransient) aSeq;
2053 if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
2055 aSeq = new TColStd_HSequenceOfTransient;
2056 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2057 TCollection_AsciiString anEntry;
2058 for ( int i = 1; i <= theShapeIDs->Length(); ++i )
2060 anArray->SetValue(1, theShapeIDs->Value( i ));
2061 Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
2062 aSeq->Append( anObj );
2064 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2065 if ( i != 1 ) theShapeEntries += ",";
2066 theShapeEntries += anEntry;
2072 //=======================================================================
2073 //function : getShapesOnSurface
2075 * \brief Find subshapes complying with given status about surface
2076 * \param theSurface - the surface to check state of subshapes against
2077 * \param theShape - the shape to explore
2078 * \param theShapeType - type of subshape of theShape
2079 * \param theState - required state
2080 * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
2081 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2083 //=======================================================================
2084 Handle(TColStd_HSequenceOfTransient)
2085 GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
2086 const Handle(GEOM_Object)& theShape,
2087 TopAbs_ShapeEnum theShapeType,
2088 GEOMAlgo_State theState,
2089 TCollection_AsciiString & theShapeEntries)
2091 // Find subshapes ids
2092 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2093 getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
2094 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
2097 return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
2100 //=============================================================================
2104 //=============================================================================
2105 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
2106 (const Handle(GEOM_Object)& theShape,
2107 const Standard_Integer theShapeType,
2108 const Handle(GEOM_Object)& theAx1,
2109 const GEOMAlgo_State theState)
2113 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
2115 TopoDS_Shape aShape = theShape->GetValue();
2116 TopoDS_Shape anAx1 = theAx1->GetValue();
2118 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
2120 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2121 if ( !checkTypeShapesOn( theShapeType ))
2125 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
2126 if ( aPlane.IsNull() )
2130 TCollection_AsciiString anAsciiList;
2131 Handle(TColStd_HSequenceOfTransient) aSeq;
2132 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2133 if ( aSeq.IsNull() || aSeq->Length() == 0 )
2136 // Make a Python command
2138 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2139 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2141 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2142 << "] = geompy.GetShapesOnPlane(" << theShape << ", "
2143 << aShapeType << ", " << theAx1 << ", " << theState << ")";
2149 //=============================================================================
2151 * GetShapesOnPlaneWithLocation
2153 //=============================================================================
2154 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
2155 (const Handle(GEOM_Object)& theShape,
2156 const Standard_Integer theShapeType,
2157 const Handle(GEOM_Object)& theAx1,
2158 const Handle(GEOM_Object)& thePnt,
2159 const GEOMAlgo_State theState)
2163 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2165 TopoDS_Shape aShape = theShape->GetValue();
2166 TopoDS_Shape anAx1 = theAx1->GetValue();
2167 TopoDS_Shape anPnt = thePnt->GetValue();
2169 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2171 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2172 if ( !checkTypeShapesOn( theShapeType ))
2176 if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
2177 TopoDS_Vertex V1, V2, V3;
2178 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2179 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2181 if (V1.IsNull() || V2.IsNull()) {
2182 SetErrorCode("Bad edge given for the plane normal vector");
2185 V3 = TopoDS::Vertex(anPnt);
2188 SetErrorCode("Bad vertex given for the plane location");
2191 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2192 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2194 if (aVec.Magnitude() < Precision::Confusion()) {
2195 SetErrorCode("Vector with null magnitude given");
2198 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2200 if ( aPlane.IsNull() )
2204 TCollection_AsciiString anAsciiList;
2205 Handle(TColStd_HSequenceOfTransient) aSeq;
2206 aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2207 if ( aSeq.IsNull() || aSeq->Length() == 0 )
2210 // Make a Python command
2212 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2213 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2215 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2216 << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
2217 << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
2223 //=============================================================================
2225 * GetShapesOnCylinder
2227 //=============================================================================
2228 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
2229 (const Handle(GEOM_Object)& theShape,
2230 const Standard_Integer theShapeType,
2231 const Handle(GEOM_Object)& theAxis,
2232 const Standard_Real theRadius,
2233 const GEOMAlgo_State theState)
2237 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2239 TopoDS_Shape aShape = theShape->GetValue();
2240 TopoDS_Shape anAxis = theAxis->GetValue();
2242 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2244 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2245 if ( !checkTypeShapesOn( aShapeType ))
2248 // Create a cylinder surface
2249 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2250 if ( aCylinder.IsNull() )
2254 TCollection_AsciiString anAsciiList;
2255 Handle(TColStd_HSequenceOfTransient) aSeq;
2256 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
2257 if ( aSeq.IsNull() || aSeq->Length() == 0 )
2260 // Make a Python command
2262 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2263 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2265 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2266 << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
2267 << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
2273 //=============================================================================
2275 * GetShapesOnCylinderWithLocation
2277 //=============================================================================
2278 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
2279 (const Handle(GEOM_Object)& theShape,
2280 const Standard_Integer theShapeType,
2281 const Handle(GEOM_Object)& theAxis,
2282 const Handle(GEOM_Object)& thePnt,
2283 const Standard_Real theRadius,
2284 const GEOMAlgo_State theState)
2288 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
2290 TopoDS_Shape aShape = theShape->GetValue();
2291 TopoDS_Shape anAxis = theAxis->GetValue();
2292 TopoDS_Shape aPnt = thePnt->GetValue();
2294 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
2296 if (aPnt.ShapeType() != TopAbs_VERTEX )
2298 SetErrorCode("Bottom location point must be vertex");
2302 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2303 if ( !checkTypeShapesOn( aShapeType ))
2306 // Create a cylinder surface
2307 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2308 if ( aCylinder.IsNull() )
2311 // translate the surface
2312 Handle(Geom_CylindricalSurface) aCylSurface =
2313 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
2314 if ( aCylSurface.IsNull() )
2316 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
2319 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
2320 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
2321 aCylinder->Translate( fromLoc, toLoc );
2324 TCollection_AsciiString anAsciiList;
2325 Handle(TColStd_HSequenceOfTransient) aSeq;
2326 aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
2327 if ( aSeq.IsNull() || aSeq->Length() == 0 )
2330 // Make a Python command
2332 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2333 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2335 GEOM::TPythonDump(aFunction)
2336 << "[" << anAsciiList.ToCString()
2337 << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
2338 << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
2344 //=============================================================================
2348 //=============================================================================
2349 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
2350 (const Handle(GEOM_Object)& theShape,
2351 const Standard_Integer theShapeType,
2352 const Handle(GEOM_Object)& theCenter,
2353 const Standard_Real theRadius,
2354 const GEOMAlgo_State theState)
2358 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
2360 TopoDS_Shape aShape = theShape->GetValue();
2361 TopoDS_Shape aCenter = theCenter->GetValue();
2363 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
2365 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2366 if ( !checkTypeShapesOn( aShapeType ))
2369 // Center of the sphere
2370 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
2371 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
2373 gp_Ax3 anAx3 (aLoc, gp::DZ());
2374 Handle(Geom_SphericalSurface) aSphere =
2375 new Geom_SphericalSurface(anAx3, theRadius);
2378 TCollection_AsciiString anAsciiList;
2379 Handle(TColStd_HSequenceOfTransient) aSeq;
2380 aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
2381 if ( aSeq.IsNull() || aSeq->Length() == 0 )
2384 // Make a Python command
2386 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2387 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2389 GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2390 << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
2391 << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
2397 //=============================================================================
2399 * GetShapesOnPlaneIDs
2401 //=============================================================================
2402 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
2403 (const Handle(GEOM_Object)& theShape,
2404 const Standard_Integer theShapeType,
2405 const Handle(GEOM_Object)& theAx1,
2406 const GEOMAlgo_State theState)
2410 if (theShape.IsNull() || theAx1.IsNull()) return NULL;
2412 TopoDS_Shape aShape = theShape->GetValue();
2413 TopoDS_Shape anAx1 = theAx1->GetValue();
2415 if (aShape.IsNull() || anAx1.IsNull()) return NULL;
2417 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2418 if ( !checkTypeShapesOn( aShapeType ))
2422 Handle(Geom_Surface) aPlane = makePlane( anAx1 );
2423 if ( aPlane.IsNull() )
2427 Handle(TColStd_HSequenceOfInteger) aSeq;
2428 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
2430 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
2431 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
2433 // Make a Python command
2434 GEOM::TPythonDump(aFunction, /*append=*/true)
2435 << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
2436 << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
2442 //=============================================================================
2444 * GetShapesOnPlaneWithLocationIDs
2446 //=============================================================================
2447 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
2448 (const Handle(GEOM_Object)& theShape,
2449 const Standard_Integer theShapeType,
2450 const Handle(GEOM_Object)& theAx1,
2451 const Handle(GEOM_Object)& thePnt,
2452 const GEOMAlgo_State theState)
2456 if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2458 TopoDS_Shape aShape = theShape->GetValue();
2459 TopoDS_Shape anAx1 = theAx1->GetValue();
2460 TopoDS_Shape anPnt = thePnt->GetValue();
2462 if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2464 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2465 if ( !checkTypeShapesOn( aShapeType ))
2469 if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
2470 TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2471 TopoDS_Vertex V1, V2, V3;
2472 TopExp::Vertices(anEdge, V1, V2, Standard_True);
2473 if (V1.IsNull() || V2.IsNull()) {
2474 SetErrorCode("Bad edge given for the plane normal vector");
2477 V3 = TopoDS::Vertex(anPnt);
2479 SetErrorCode("Bad vertex given for the plane location");
2482 gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2483 gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2484 if (aVec.Magnitude() < Precision::Confusion()) {
2485 SetErrorCode("Vector with null magnitude given");
2489 Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2490 if ( aPlane.IsNull() )
2494 Handle(TColStd_HSequenceOfInteger) aSeq;
2495 aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
2497 // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
2498 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
2500 // Make a Python command
2501 GEOM::TPythonDump(aFunction, /*append=*/true)
2502 << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
2503 << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")";
2509 //=============================================================================
2511 * GetShapesOnCylinderIDs
2513 //=============================================================================
2514 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
2515 (const Handle(GEOM_Object)& theShape,
2516 const Standard_Integer theShapeType,
2517 const Handle(GEOM_Object)& theAxis,
2518 const Standard_Real theRadius,
2519 const GEOMAlgo_State theState)
2523 if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2525 TopoDS_Shape aShape = theShape->GetValue();
2526 TopoDS_Shape anAxis = theAxis->GetValue();
2528 if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2530 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2531 if ( !checkTypeShapesOn( aShapeType ))
2534 // Create a cylinder surface
2535 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2536 if ( aCylinder.IsNull() )
2540 Handle(TColStd_HSequenceOfInteger) aSeq;
2541 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
2543 // The GetShapesOnCylinder() doesn't change object so no new function is required.
2544 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
2546 // Make a Python command
2547 GEOM::TPythonDump(aFunction, /*append=*/true)
2548 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2549 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
2550 << theRadius << ", " << theState << ")";
2556 //=============================================================================
2558 * GetShapesOnCylinderWithLocationIDs
2560 //=============================================================================
2561 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
2562 (const Handle(GEOM_Object)& theShape,
2563 const Standard_Integer theShapeType,
2564 const Handle(GEOM_Object)& theAxis,
2565 const Handle(GEOM_Object)& thePnt,
2566 const Standard_Real theRadius,
2567 const GEOMAlgo_State theState)
2571 if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
2573 TopoDS_Shape aShape = theShape->GetValue();
2574 TopoDS_Shape anAxis = theAxis->GetValue();
2575 TopoDS_Shape aPnt = thePnt->GetValue();
2577 if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
2579 if (aPnt.ShapeType() != TopAbs_VERTEX )
2581 SetErrorCode("Bottom location point must be vertex");
2585 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2586 if ( !checkTypeShapesOn( aShapeType ))
2589 // Create a cylinder surface
2590 Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2591 if ( aCylinder.IsNull() )
2594 // translate the surface
2595 Handle(Geom_CylindricalSurface) aCylSurface =
2596 Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
2597 if ( aCylSurface.IsNull() )
2599 SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
2602 gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
2603 gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
2604 aCylinder->Translate( fromLoc, toLoc );
2607 Handle(TColStd_HSequenceOfInteger) aSeq;
2608 aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
2610 // The GetShapesOnCylinder() doesn't change object so no new function is required.
2611 Handle(GEOM_Function) aFunction =
2612 GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
2614 // Make a Python command
2615 GEOM::TPythonDump(aFunction, /*append=*/true)
2616 << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
2617 << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
2618 << thePnt << ", " << theRadius << ", " << theState << ")";
2624 //=============================================================================
2626 * GetShapesOnSphereIDs
2628 //=============================================================================
2629 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
2630 (const Handle(GEOM_Object)& theShape,
2631 const Standard_Integer theShapeType,
2632 const Handle(GEOM_Object)& theCenter,
2633 const Standard_Real theRadius,
2634 const GEOMAlgo_State theState)
2638 if (theShape.IsNull() || theCenter.IsNull()) return NULL;
2640 TopoDS_Shape aShape = theShape->GetValue();
2641 TopoDS_Shape aCenter = theCenter->GetValue();
2643 if (aShape.IsNull() || aCenter.IsNull()) return NULL;
2645 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2646 if ( !checkTypeShapesOn( aShapeType ))
2649 // Center of the sphere
2650 if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
2651 gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
2653 gp_Ax3 anAx3 (aLoc, gp::DZ());
2654 Handle(Geom_SphericalSurface) aSphere =
2655 new Geom_SphericalSurface(anAx3, theRadius);
2658 Handle(TColStd_HSequenceOfInteger) aSeq;
2659 aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
2661 // The GetShapesOnSphere() doesn't change object so no new function is required.
2662 Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
2664 // Make a Python command
2665 GEOM::TPythonDump(aFunction, /*append=*/true)
2666 << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2667 << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
2668 << theRadius << ", " << theState << ")";
2674 //=======================================================================
2675 //function : getShapesOnQuadrangleIDs
2677 * \brief Find IDs of subshapes complying with given status about quadrangle
2678 * \param theShape - the shape to explore
2679 * \param theShapeType - type of subshape of theShape
2680 * \param theTopLeftPoint - top left quadrangle corner
2681 * \param theTopRigthPoint - top right quadrangle corner
2682 * \param theBottomLeftPoint - bottom left quadrangle corner
2683 * \param theBottomRigthPoint - bottom right quadrangle corner
2684 * \param theState - required state
2685 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2687 //=======================================================================
2688 Handle(TColStd_HSequenceOfInteger)
2689 GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2690 const Standard_Integer theShapeType,
2691 const Handle(GEOM_Object)& theTopLeftPoint,
2692 const Handle(GEOM_Object)& theTopRigthPoint,
2693 const Handle(GEOM_Object)& theBottomLeftPoint,
2694 const Handle(GEOM_Object)& theBottomRigthPoint,
2695 const GEOMAlgo_State theState)
2699 if ( theShape.IsNull() ||
2700 theTopLeftPoint.IsNull() ||
2701 theTopRigthPoint.IsNull() ||
2702 theBottomLeftPoint.IsNull() ||
2703 theBottomRigthPoint.IsNull() )
2706 TopoDS_Shape aShape = theShape->GetValue();
2707 TopoDS_Shape aTL = theTopLeftPoint->GetValue();
2708 TopoDS_Shape aTR = theTopRigthPoint->GetValue();
2709 TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
2710 TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
2712 if (aShape.IsNull() ||
2717 aTL.ShapeType() != TopAbs_VERTEX ||
2718 aTR.ShapeType() != TopAbs_VERTEX ||
2719 aBL.ShapeType() != TopAbs_VERTEX ||
2720 aBR.ShapeType() != TopAbs_VERTEX )
2723 TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2724 if ( !checkTypeShapesOn( aShapeType ))
2727 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2729 // Check presence of triangulation, build if need
2730 if (!CheckTriangulation(aShape)) {
2731 SetErrorCode("Cannot build triangulation on the shape");
2736 gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
2737 gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
2738 gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
2739 gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
2741 GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
2742 Standard_Real aTol = 0.0001; // default value
2744 aFinder.SetShape(aShape);
2745 aFinder.SetTolerance(aTol);
2746 //aFinder.SetSurface(theSurface);
2747 aFinder.SetShapeType(aShapeType);
2748 aFinder.SetState(theState);
2750 // Sets the minimal number of inner points for the faces that do not have own
2751 // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
2753 aFinder.SetNbPntsMin(3);
2754 // Sets the maximal number of inner points for edges or faces.
2755 // It is usefull for the cases when this number is very big (e.g =2000) to improve
2756 // the performance. If this value =0, all inner points will be taken into account.
2758 aFinder.SetNbPntsMax(100);
2762 // Interprete results
2763 Standard_Integer iErr = aFinder.ErrorStatus();
2764 // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2766 MESSAGE(" iErr : " << iErr);
2767 TCollection_AsciiString aMsg (" iErr : ");
2768 aMsg += TCollection_AsciiString(iErr);
2772 Standard_Integer iWrn = aFinder.WarningStatus();
2773 // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2775 MESSAGE(" *** iWrn : " << iWrn);
2778 const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2780 if (listSS.Extent() < 1) {
2781 //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2782 SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2786 // Fill sequence of object IDs
2787 aSeqOfIDs = new TColStd_HSequenceOfInteger;
2789 TopTools_IndexedMapOfShape anIndices;
2790 TopExp::MapShapes(aShape, anIndices);
2792 TopTools_ListIteratorOfListOfShape itSub (listSS);
2793 for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2794 int id = anIndices.FindIndex(itSub.Value());
2795 aSeqOfIDs->Append(id);
2800 //=======================================================================
2801 //function : GetShapesOnQuadrangle
2803 * \brief Find subshapes complying with given status about quadrangle
2804 * \param theShape - the shape to explore
2805 * \param theShapeType - type of subshape of theShape
2806 * \param theTopLeftPoint - top left quadrangle corner
2807 * \param theTopRigthPoint - top right quadrangle corner
2808 * \param theBottomLeftPoint - bottom left quadrangle corner
2809 * \param theBottomRigthPoint - bottom right quadrangle corner
2810 * \param theState - required state
2811 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2813 //=======================================================================
2814 Handle(TColStd_HSequenceOfTransient)
2815 GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
2816 const Standard_Integer theShapeType,
2817 const Handle(GEOM_Object)& theTopLeftPoint,
2818 const Handle(GEOM_Object)& theTopRigthPoint,
2819 const Handle(GEOM_Object)& theBottomLeftPoint,
2820 const Handle(GEOM_Object)& theBottomRigthPoint,
2821 const GEOMAlgo_State theState)
2824 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2825 getShapesOnQuadrangleIDs( theShape,
2830 theBottomRigthPoint,
2832 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2835 // Find objects by indices
2836 TCollection_AsciiString anAsciiList;
2837 Handle(TColStd_HSequenceOfTransient) aSeq;
2838 aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2839 if ( aSeq.IsNull() || aSeq->IsEmpty() )
2842 // Make a Python command
2844 Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2845 Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2847 GEOM::TPythonDump(aFunction)
2848 << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
2850 << TopAbs_ShapeEnum(theShapeType) << ", "
2851 << theTopLeftPoint << ", "
2852 << theTopRigthPoint << ", "
2853 << theBottomLeftPoint << ", "
2854 << theBottomRigthPoint << ", "
2861 //=======================================================================
2862 //function : GetShapesOnQuadrangleIDs
2864 * \brief Find IDs of subshapes complying with given status about quadrangle
2865 * \param theShape - the shape to explore
2866 * \param theShapeType - type of subshape of theShape
2867 * \param theTopLeftPoint - top left quadrangle corner
2868 * \param theTopRigthPoint - top right quadrangle corner
2869 * \param theBottomLeftPoint - bottom left quadrangle corner
2870 * \param theBottomRigthPoint - bottom right quadrangle corner
2871 * \param theState - required state
2872 * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2874 //=======================================================================
2875 Handle(TColStd_HSequenceOfInteger)
2876 GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2877 const Standard_Integer theShapeType,
2878 const Handle(GEOM_Object)& theTopLeftPoint,
2879 const Handle(GEOM_Object)& theTopRigthPoint,
2880 const Handle(GEOM_Object)& theBottomLeftPoint,
2881 const Handle(GEOM_Object)& theBottomRigthPoint,
2882 const GEOMAlgo_State theState)
2885 Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2886 getShapesOnQuadrangleIDs( theShape,
2891 theBottomRigthPoint,
2893 if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2896 // Make a Python command
2898 // The GetShapesOnCylinder() doesn't change object so no new function is required.
2899 Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
2900 lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
2901 lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
2902 lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
2903 Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
2905 GEOM::TPythonDump(aFunction, /*append=*/true)
2906 << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
2908 << TopAbs_ShapeEnum(theShapeType) << ", "
2909 << theTopLeftPoint << ", "
2910 << theTopRigthPoint << ", "
2911 << theBottomLeftPoint << ", "
2912 << theBottomRigthPoint << ", "
2919 //=============================================================================
2923 //=============================================================================
2924 static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
2925 const TopTools_IndexedMapOfShape& theWhereIndices,
2926 const TopoDS_Shape& theWhat,
2927 TColStd_ListOfInteger& theModifiedList)
2929 if (theWhereFunction.IsNull() || theWhat.IsNull()) return false;
2931 if (theWhereIndices.Contains(theWhat)) {
2932 // entity was not changed by the operation
2933 Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
2934 theModifiedList.Append(aWhatIndex);
2938 // try to find in history
2939 TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
2941 // search in history for all argument shapes
2942 Standard_Boolean isFound = Standard_False;
2943 Standard_Boolean isGood = Standard_False;
2945 TDF_LabelSequence aLabelSeq;
2946 theWhereFunction->GetDependency(aLabelSeq);
2947 Standard_Integer nbArg = aLabelSeq.Length();
2949 for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
2951 TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
2953 Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
2954 TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
2956 TopTools_IndexedMapOfShape anArgumentIndices;
2957 TopExp::MapShapes(anArgumentShape, anArgumentIndices);
2959 if (anArgumentIndices.Contains(theWhat)) {
2960 isFound = Standard_True;
2961 Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
2963 // Find corresponding label in history
2964 TDF_Label anArgumentHistoryLabel =
2965 theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
2966 if (anArgumentHistoryLabel.IsNull()) {
2967 // Lost History of operation argument. Possibly, all its entities was removed.
2968 isGood = Standard_True;
2971 TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
2973 if (aWhatHistoryLabel.IsNull()) {
2974 // Removed entity ? Compound ? Compsolid ? Shell ? Wire
2975 isGood = Standard_False;
2977 Handle(TDataStd_IntegerArray) anIntegerArray;
2978 if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2979 //Error: Empty modifications history for the sought shape.
2980 isGood = Standard_False;
2983 isGood = Standard_True;
2984 Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
2985 for (imod = 1; imod <= aModifLen; imod++) {
2986 theModifiedList.Append(anIntegerArray->Array()->Value(imod));
2997 // try compound/compsolid/shell/wire element by element
2998 bool isFoundAny = false;
2999 TopTools_MapOfShape mapShape;
3001 if (theWhat.ShapeType() == TopAbs_COMPOUND ||
3002 theWhat.ShapeType() == TopAbs_COMPSOLID) {
3003 // recursive processing of compound/compsolid
3004 TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
3005 for (; anIt.More(); anIt.Next()) {
3006 if (mapShape.Add(anIt.Value())) {
3007 TopoDS_Shape curWhat = anIt.Value();
3008 isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3009 if (isFoundAny) isFound = Standard_True;
3013 else if (theWhat.ShapeType() == TopAbs_SHELL) {
3014 // try to replace a shell by its faces images
3015 TopExp_Explorer anExp (theWhat, TopAbs_FACE);
3016 for (; anExp.More(); anExp.Next()) {
3017 if (mapShape.Add(anExp.Current())) {
3018 TopoDS_Shape curWhat = anExp.Current();
3019 isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3020 if (isFoundAny) isFound = Standard_True;
3024 else if (theWhat.ShapeType() == TopAbs_WIRE) {
3025 // try to replace a wire by its edges images
3026 TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
3027 for (; anExp.More(); anExp.Next()) {
3028 if (mapShape.Add(anExp.Current())) {
3029 TopoDS_Shape curWhat = anExp.Current();
3030 isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3031 if (isFoundAny) isFound = Standard_True;
3043 //=============================================================================
3045 * GetShapeProperties
3047 //=============================================================================
3048 void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[],
3051 GProp_GProps theProps;
3053 //TopoDS_Shape aPntShape;
3054 Standard_Real aShapeSize;
3056 if (aShape.ShapeType() == TopAbs_VERTEX) aCenterMass = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
3057 else if (aShape.ShapeType() == TopAbs_EDGE) BRepGProp::LinearProperties(aShape, theProps);
3058 else if (aShape.ShapeType() == TopAbs_FACE) BRepGProp::SurfaceProperties(aShape, theProps);
3059 else BRepGProp::VolumeProperties(aShape, theProps);
3061 if (aShape.ShapeType() == TopAbs_VERTEX)
3064 aCenterMass = theProps.CentreOfMass();
3065 aShapeSize = theProps.Mass();
3068 // aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
3069 // aVertex = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) );
3070 aVertex = aCenterMass;
3071 tab[0] = aVertex.X();
3072 tab[1] = aVertex.Y();
3073 tab[2] = aVertex.Z();
3074 tab[3] = aShapeSize;
3080 //================================================================================
3082 * \brief Return normal to face at extrema point
3084 //================================================================================
3086 gp_Vec GetNormal(const TopoDS_Face& face, const BRepExtrema_DistShapeShape& extrema)
3088 gp_Vec defaultNorm(1,0,0); // to have same normals on different faces
3090 // get UV at extrema point
3091 Standard_Real u,v, f,l;
3092 switch ( extrema.SupportTypeShape2(1) ) {
3093 case BRepExtrema_IsInFace: {
3094 extrema.ParOnFaceS2(1, u, v );
3097 case BRepExtrema_IsOnEdge: {
3098 TopoDS_Edge edge = TopoDS::Edge( extrema.SupportOnShape2(1));
3099 Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f,l );
3100 extrema.ParOnEdgeS2( 1, u );
3101 gp_Pnt2d uv = pcurve->Value( u );
3106 case BRepExtrema_IsVertex: return defaultNorm;
3109 BRepAdaptor_Surface surface( face, false );
3110 gp_Vec du, dv; gp_Pnt p;
3111 surface.D1( u, v, p, du, dv );
3115 } catch (Standard_Failure ) {
3121 //=============================================================================
3126 //=============================================================================
3127 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
3128 Handle(GEOM_Object) theShapeWhat)
3132 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3134 TopoDS_Shape aWhere = theShapeWhere->GetValue();
3135 TopoDS_Shape aWhat = theShapeWhat->GetValue();
3136 TopoDS_Shape aPntShape;
3137 TopoDS_Vertex aVertex;
3139 if (aWhere.IsNull() || aWhat.IsNull()) {
3140 SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
3144 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
3145 if (aWhereFunction.IsNull()) {
3146 SetErrorCode("Error: aWhereFunction is Null.");
3150 TopTools_IndexedMapOfShape aWhereIndices;
3151 TopExp::MapShapes(aWhere, aWhereIndices);
3153 TColStd_ListOfInteger aModifiedList;
3154 Standard_Integer aWhereIndex;
3155 Handle(TColStd_HArray1OfInteger) aModifiedArray;
3156 Handle(GEOM_Object) aResult;
3158 bool isFound = false;
3159 Standard_Integer iType = TopAbs_SOLID;
3160 Standard_Integer compType = TopAbs_SOLID;
3161 Standard_Real aWhat_Mass = 0., aWhere_Mass = 0.;
3162 Standard_Real tab_aWhat[4], tab_aWhere[4];
3163 Standard_Real dl_l = 1e-3;
3164 Standard_Real min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
3165 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
3166 Bnd_Box BoundingBox;
3167 gp_Pnt aPnt, aPnt_aWhat, tab_Pnt[2];
3168 GProp_GProps aProps;
3170 // Find the iType of the aWhat shape
3171 if ( aWhat.ShapeType() == TopAbs_VERTEX ) iType = TopAbs_VERTEX;
3172 else if ( aWhat.ShapeType() == TopAbs_EDGE || aWhat.ShapeType() == TopAbs_WIRE ) iType = TopAbs_EDGE;
3173 else if ( aWhat.ShapeType() == TopAbs_FACE || aWhat.ShapeType() == TopAbs_SHELL ) iType = TopAbs_FACE;
3174 else if ( aWhat.ShapeType() == TopAbs_SOLID || aWhat.ShapeType() == TopAbs_COMPSOLID ) iType = TopAbs_SOLID;
3175 else if ( aWhat.ShapeType() == TopAbs_COMPOUND ) {
3176 // Only the iType of the first shape in the compound is taken into account
3177 TopoDS_Iterator It (aWhat, Standard_False, Standard_False);
3179 SetErrorCode("Error: theShapeWhat is an empty COMPOUND.");
3182 compType = It.Value().ShapeType();
3183 if ( compType == TopAbs_VERTEX ) iType = TopAbs_VERTEX;
3184 else if ( compType == TopAbs_EDGE || compType == TopAbs_WIRE ) iType = TopAbs_EDGE;
3185 else if ( compType == TopAbs_FACE || compType == TopAbs_SHELL) iType = TopAbs_FACE;
3186 else if ( compType == TopAbs_SOLID || compType == TopAbs_COMPSOLID) iType = TopAbs_SOLID;
3189 SetErrorCode("Error: An attempt to extract a shape of not supported type.");
3193 TopExp_Explorer Exp_aWhat( aWhat, TopAbs_ShapeEnum( iType ) );
3194 TopExp_Explorer Exp_aWhere( aWhere, TopAbs_ShapeEnum( iType ) );
3195 TopExp_Explorer Exp_Edge( aWhere, TopAbs_EDGE );
3197 // Find the shortest edge in theShapeWhere shape
3198 BRepBndLib::Add(aWhere, BoundingBox);
3199 BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3200 min_l = fabs(aXmax - aXmin);
3201 if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin);
3202 if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin);
3204 // Mantis issue 0020908 BEGIN
3205 if (!Exp_Edge.More()) {
3206 min_l = Precision::Confusion();
3208 // Mantis issue 0020908 END
3209 for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
3210 TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX);
3211 for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) {
3212 aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) );
3213 tab_Pnt[nbVertex] = aPnt;
3215 if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) {
3216 BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
3217 if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
3221 // Compute tolerances
3223 Tol_1D = dl_l * min_l;
3224 Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
3225 Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
3227 if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion();
3228 if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion();
3229 if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion();
3230 if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion();
3232 //if (Tol_1D > 1.0) Tol_1D = 1.0;
3233 //if (Tol_2D > 1.0) Tol_2D = 1.0;
3234 //if (Tol_3D > 1.0) Tol_3D = 1.0;
3237 if ( iType == TopAbs_VERTEX ) Tol_Mass = Tol_0D;
3238 else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D;
3239 else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
3241 // Compute the ShapeWhat Mass
3242 for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) {
3243 if ( iType == TopAbs_VERTEX ) {
3247 else if ( iType == TopAbs_EDGE ) BRepGProp::LinearProperties(Exp_aWhat.Current(), aProps);
3248 else if ( iType == TopAbs_FACE ) BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps);
3249 else BRepGProp::VolumeProperties(Exp_aWhat.Current(), aProps);
3250 aWhat_Mass += aProps.Mass();
3253 // Searching for the sub-shapes inside the ShapeWhere shape
3254 TopTools_MapOfShape map_aWhere;
3255 for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) {
3256 if (!map_aWhere.Add(Exp_aWhere.Current()))
3257 continue; // skip repeated shape to avoid mass addition
3258 GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
3259 for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
3260 GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
3261 if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D )
3264 if ( (tab_aWhat[3] - tab_aWhere[3]) > Tol_Mass ) {
3265 aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
3266 aVertex = TopoDS::Vertex( aPntShape );
3267 BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() );
3268 BRepExtrema_DistShapeShape aWhatDistance ( aVertex, Exp_aWhat.Current() );
3269 if ( aWhereDistance.IsDone() && aWhatDistance.IsDone() &&
3270 fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= Tol_1D )
3272 // 0020162: "EDF 961 GEOM : Getinplace is getting additionnal orthogonal faces"
3273 // aVertex must be projected to the same point on Where and on What
3274 gp_Pnt pOnWhat = aWhatDistance.PointOnShape2(1);
3275 gp_Pnt pOnWhere = aWhereDistance.PointOnShape2(1);
3276 isFound = ( pOnWhat.Distance(pOnWhere) <= Tol_1D );
3277 if ( isFound && iType == TopAbs_FACE )
3279 // check normals at pOnWhat and pOnWhere
3280 const double angleTol = PI/180.;
3281 gp_Vec normToWhat = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance);
3282 gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance);
3283 if ( normToWhat * normToWhere < 0 )
3284 normToWhat.Reverse();
3285 isFound = ( normToWhat.Angle( normToWhere ) < angleTol );
3291 aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current());
3292 aModifiedList.Append(aWhereIndex);
3293 aWhere_Mass += tab_aWhere[3];
3298 if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass ) break;
3301 if (aModifiedList.Extent() == 0) { // Not found any Results
3302 SetErrorCode(NOT_FOUND_ANY);
3306 aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
3307 TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
3308 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
3309 aModifiedArray->SetValue(imod, anIterModif.Value());
3312 aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
3313 if (aResult.IsNull()) {
3314 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
3318 if (aModifiedArray->Length() > 1) {
3320 aResult->SetType(GEOM_GROUP);
3322 //Set a sub shape type
3323 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
3324 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
3326 TDF_Label aFreeLabel = aResult->GetFreeLabel();
3327 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
3330 //Make a Python command
3331 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
3333 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
3334 << theShapeWhere << ", " << theShapeWhat << ")";
3340 //=======================================================================
3341 //function : GetInPlaceByHistory
3343 //=======================================================================
3344 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
3345 (Handle(GEOM_Object) theShapeWhere,
3346 Handle(GEOM_Object) theShapeWhat)
3350 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3352 TopoDS_Shape aWhere = theShapeWhere->GetValue();
3353 TopoDS_Shape aWhat = theShapeWhat->GetValue();
3355 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
3357 Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
3358 if (aWhereFunction.IsNull()) return NULL;
3360 //Fill array of indices
3361 TopTools_IndexedMapOfShape aWhereIndices;
3362 TopExp::MapShapes(aWhere, aWhereIndices);
3365 TColStd_ListOfInteger aModifiedList;
3366 bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
3368 if (!isFound || aModifiedList.Extent() < 1) {
3369 SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
3373 Handle(TColStd_HArray1OfInteger) aModifiedArray =
3374 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
3375 TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
3376 for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
3377 aModifiedArray->SetValue(imod, anIterModif.Value());
3381 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
3382 if (aResult.IsNull()) {
3383 SetErrorCode("Error in algorithm: result found, but cannot be returned.");
3387 if (aModifiedArray->Length() > 1) {
3389 aResult->SetType(GEOM_GROUP);
3391 //Set a sub shape type
3392 TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
3393 TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
3395 TDF_Label aFreeLabel = aResult->GetFreeLabel();
3396 TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
3399 //Make a Python command
3400 Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
3402 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
3403 << theShapeWhere << ", " << theShapeWhat << ")";
3409 //=======================================================================
3410 //function : SortShapes
3412 //=======================================================================
3413 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
3415 Standard_Integer MaxShapes = SL.Extent();
3416 TopTools_Array1OfShape aShapes (1,MaxShapes);
3417 TColStd_Array1OfInteger OrderInd(1,MaxShapes);
3418 TColStd_Array1OfReal MidXYZ (1,MaxShapes); //X,Y,Z;
3419 TColStd_Array1OfReal Length (1,MaxShapes); //X,Y,Z;
3421 // Computing of CentreOfMass
3422 Standard_Integer Index;
3425 TopTools_ListIteratorOfListOfShape it(SL);
3426 for (Index=1; it.More(); Index++)
3428 TopoDS_Shape S = it.Value();
3429 SL.Remove( it ); // == it.Next()
3431 OrderInd.SetValue (Index, Index);
3432 if (S.ShapeType() == TopAbs_VERTEX)
3434 GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
3435 Length.SetValue( Index, (Standard_Real) S.Orientation());
3439 BRepGProp::LinearProperties (S, GPr);
3440 GPoint = GPr.CentreOfMass();
3441 Length.SetValue( Index, GPr.Mass() );
3443 MidXYZ.SetValue(Index,
3444 GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
3445 //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl;
3449 Standard_Integer aTemp;
3450 Standard_Boolean exchange, Sort = Standard_True;
3451 Standard_Real tol = Precision::Confusion();
3454 Sort = Standard_False;
3455 for (Index=1; Index < MaxShapes; Index++)
3457 exchange = Standard_False;
3458 Standard_Real dMidXYZ = MidXYZ(OrderInd(Index)) - MidXYZ(OrderInd(Index+1));
3459 Standard_Real dLength = Length(OrderInd(Index)) - Length(OrderInd(Index+1));
3460 if ( dMidXYZ >= tol ) {
3461 // cout << "MidXYZ: " << MidXYZ(OrderInd(Index))<< " > " <<MidXYZ(OrderInd(Index+1))
3462 // << " d: " << dMidXYZ << endl;
3463 exchange = Standard_True;
3465 else if ( Abs(dMidXYZ) < tol && dLength >= tol ) {
3466 // cout << "Length: " << Length(OrderInd(Index))<< " > " <<Length(OrderInd(Index+1))
3467 // << " d: " << dLength << endl;
3468 exchange = Standard_True;
3470 else if ( Abs(dMidXYZ) < tol && Abs(dLength) < tol &&
3471 aShapes(OrderInd(Index)).ShapeType() <= TopAbs_FACE) {
3473 // equal values possible on shapes such as two halves of a sphere and
3474 // a membrane inside the sphere
3476 BRepBndLib::Add( aShapes( OrderInd(Index) ), box1 );
3477 if ( box1.IsVoid() ) continue;
3478 BRepBndLib::Add( aShapes( OrderInd(Index+1) ), box2 );
3479 Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
3480 if ( dSquareExtent >= tol ) {
3481 // cout << "SquareExtent: " << box1.SquareExtent()<<" > "<<box2.SquareExtent() << endl;
3482 exchange = Standard_True;
3484 else if ( Abs(dSquareExtent) < tol ) {
3485 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
3486 box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3487 val1 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
3488 box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3489 val2 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
3490 //exchange = val1 > val2;
3491 if ((val1 - val2) >= tol) {
3492 exchange = Standard_True;
3494 //cout << "box: " << val1<<" > "<<val2 << endl;
3500 // cout << "exchange " << Index << " & " << Index+1 << endl;
3501 aTemp = OrderInd(Index);
3502 OrderInd(Index) = OrderInd(Index+1);
3503 OrderInd(Index+1) = aTemp;
3504 Sort = Standard_True;
3509 for (Index=1; Index <= MaxShapes; Index++)
3510 SL.Append( aShapes( OrderInd(Index) ));
3513 //=======================================================================
3514 //function : CompsolidToCompound
3516 //=======================================================================
3517 TopoDS_Shape GEOMImpl_IShapesOperations::CompsolidToCompound (const TopoDS_Shape& theCompsolid)
3519 if (theCompsolid.ShapeType() != TopAbs_COMPSOLID) {
3520 return theCompsolid;
3523 TopoDS_Compound aCompound;
3525 B.MakeCompound(aCompound);
3527 TopTools_MapOfShape mapShape;
3528 TopoDS_Iterator It (theCompsolid, Standard_True, Standard_True);
3530 for (; It.More(); It.Next()) {
3531 TopoDS_Shape aShape_i = It.Value();
3532 if (mapShape.Add(aShape_i)) {
3533 B.Add(aCompound, aShape_i);
3540 //=======================================================================
3541 //function : CheckTriangulation
3543 //=======================================================================
3544 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
3546 bool isTriangulation = true;
3548 TopExp_Explorer exp (aShape, TopAbs_FACE);
3551 TopLoc_Location aTopLoc;
3552 Handle(Poly_Triangulation) aTRF;
3553 aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
3554 if (aTRF.IsNull()) {
3555 isTriangulation = false;
3558 else // no faces, try edges
3560 TopExp_Explorer expe (aShape, TopAbs_EDGE);
3564 TopLoc_Location aLoc;
3565 Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
3567 isTriangulation = false;
3571 if (!isTriangulation) {
3572 // calculate deflection
3573 Standard_Real aDeviationCoefficient = 0.001;
3576 BRepBndLib::Add(aShape, B);
3577 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
3578 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3580 Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
3581 Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
3582 Standard_Real aHLRAngle = 0.349066;
3584 BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
3590 #define MAX_TOLERANCE 1.e-7
3592 //=======================================================================
3593 //function : isSameEdge
3594 //purpose : Returns True if two edges coincide
3595 //=======================================================================
3596 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
3598 TopoDS_Vertex V11, V12, V21, V22;
3599 TopExp::Vertices(theEdge1, V11, V12);
3600 TopExp::Vertices(theEdge2, V21, V22);
3601 gp_Pnt P11 = BRep_Tool::Pnt(V11);
3602 gp_Pnt P12 = BRep_Tool::Pnt(V12);
3603 gp_Pnt P21 = BRep_Tool::Pnt(V21);
3604 gp_Pnt P22 = BRep_Tool::Pnt(V22);
3605 bool coincide = false;
3607 //Check that ends of edges coincide
3608 if(P11.Distance(P21) <= MAX_TOLERANCE) {
3609 if(P12.Distance(P22) <= MAX_TOLERANCE) coincide = true;
3611 else if(P11.Distance(P22) <= MAX_TOLERANCE) {
3612 if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
3615 if(!coincide) return false;
3617 if (BRep_Tool::Degenerated(theEdge1))
3618 if (BRep_Tool::Degenerated(theEdge2)) return true;
3621 if (BRep_Tool::Degenerated(theEdge2)) return false;
3623 double U11, U12, U21, U22;
3624 Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
3625 Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
3626 if(C1->DynamicType() == C2->DynamicType()) return true;
3628 //Check that both edges has the same geometry
3629 double range = U12-U11;
3630 double U = U11+ range/3.0;
3631 gp_Pnt P1 = C1->Value(U); //Compute a point on one third of the edge's length
3632 U = U11+range*2.0/3.0;
3633 gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length
3635 if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22)
3638 if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
3640 if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
3643 if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
3648 #include <TopoDS_TShape.hxx>
3649 //=======================================================================
3650 //function : isSameFace
3651 //purpose : Returns True if two faces coincide
3652 //=======================================================================
3653 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
3655 TopExp_Explorer E(theFace1, TopAbs_EDGE);
3656 TopTools_ListOfShape LS1, LS2;
3657 for(; E.More(); E.Next()) LS1.Append(E.Current());
3659 E.Init(theFace2, TopAbs_EDGE);
3660 for(; E.More(); E.Next()) LS2.Append(E.Current());
3662 //Compare the number of edges in the faces
3663 if(LS1.Extent() != LS2.Extent()) return false;
3665 double aMin = RealFirst(), aMax = RealLast();
3666 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
3667 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
3669 for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
3670 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3671 if(P.X() < xminB1) xminB1 = P.X();
3672 if(P.Y() < yminB1) yminB1 = P.Y();
3673 if(P.Z() < zminB1) zminB1 = P.Z();
3674 if(P.X() > xmaxB1) xmaxB1 = P.X();
3675 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
3676 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
3679 for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
3680 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3681 if(P.X() < xminB2) xminB2 = P.X();
3682 if(P.Y() < yminB2) yminB2 = P.Y();
3683 if(P.Z() < zminB2) zminB2 = P.Z();
3684 if(P.X() > xmaxB2) xmaxB2 = P.X();
3685 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
3686 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
3689 //Compare the bounding boxes of both faces
3690 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
3693 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
3696 Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
3697 Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
3699 //Check if there a coincidence of two surfaces at least in two points
3700 double U11, U12, V11, V12, U21, U22, V21, V22;
3701 BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
3702 BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
3704 double rangeU = U12-U11;
3705 double rangeV = V12-V11;
3706 double U = U11 + rangeU/3.0;
3707 double V = V11 + rangeV/3.0;
3708 gp_Pnt P1 = S1->Value(U, V);
3709 U = U11+rangeU*2.0/3.0;
3710 V = V11+rangeV*2.0/3.0;
3711 gp_Pnt P2 = S1->Value(U, V);
3713 if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
3716 if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
3718 if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
3721 if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
3723 //Check that each edge of the Face1 has a counterpart in the Face2
3724 TopTools_MapOfOrientedShape aMap;
3725 TopTools_ListIteratorOfListOfShape LSI1(LS1);
3726 for(; LSI1.More(); LSI1.Next()) {
3727 TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
3728 bool isFound = false;
3729 TopTools_ListIteratorOfListOfShape LSI2(LS2);
3730 for(; LSI2.More(); LSI2.Next()) {
3731 TopoDS_Shape aValue = LSI2.Value();
3732 if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
3733 if(isSameEdge(E, TopoDS::Edge(aValue))) {
3739 if(!isFound) return false;
3745 //=======================================================================
3746 //function : isSameSolid
3747 //purpose : Returns True if two solids coincide
3748 //=======================================================================
3749 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
3751 TopExp_Explorer E(theSolid1, TopAbs_FACE);
3752 TopTools_ListOfShape LS1, LS2;
3753 for(; E.More(); E.Next()) LS1.Append(E.Current());
3754 E.Init(theSolid2, TopAbs_FACE);
3755 for(; E.More(); E.Next()) LS2.Append(E.Current());
3757 if(LS1.Extent() != LS2.Extent()) return false;
3759 double aMin = RealFirst(), aMax = RealLast();
3760 double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
3761 double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
3763 for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
3764 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3765 if(P.X() < xminB1) xminB1 = P.X();
3766 if(P.Y() < yminB1) yminB1 = P.Y();
3767 if(P.Z() < zminB1) zminB1 = P.Z();
3768 if(P.X() > xmaxB1) xmaxB1 = P.X();
3769 if(P.Y() > ymaxB1) ymaxB1 = P.Y();
3770 if(P.Z() > zmaxB1) zmaxB1 = P.Z();
3773 for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
3774 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3775 if(P.X() < xminB2) xminB2 = P.X();
3776 if(P.Y() < yminB2) yminB2 = P.Y();
3777 if(P.Z() < zminB2) zminB2 = P.Z();
3778 if(P.X() > xmaxB2) xmaxB2 = P.X();
3779 if(P.Y() > ymaxB2) ymaxB2 = P.Y();
3780 if(P.Z() > zmaxB2) zmaxB2 = P.Z();
3783 //Compare the bounding boxes of both solids
3784 if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
3787 if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
3790 //Check that each face of the Solid1 has a counterpart in the Solid2
3791 TopTools_MapOfOrientedShape aMap;
3792 TopTools_ListIteratorOfListOfShape LSI1(LS1);
3793 for(; LSI1.More(); LSI1.Next()) {
3794 TopoDS_Face F = TopoDS::Face(LSI1.Value());
3795 bool isFound = false;
3796 TopTools_ListIteratorOfListOfShape LSI2(LS2);
3797 for(; LSI2.More(); LSI2.Next()) {
3798 if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
3799 if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
3800 aMap.Add(LSI2.Value());
3805 if(!isFound) return false;
3811 //=======================================================================
3812 //function : GetSame
3814 //=======================================================================
3815 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
3816 const Handle(GEOM_Object)& theShapeWhat)
3819 if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3821 TopoDS_Shape aWhere = theShapeWhere->GetValue();
3822 TopoDS_Shape aWhat = theShapeWhat->GetValue();
3824 if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
3827 bool isFound = false;
3828 TopoDS_Shape aSubShape;
3829 TopTools_MapOfShape aMap;
3831 switch(aWhat.ShapeType()) {
3832 case TopAbs_VERTEX: {
3833 gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
3834 TopExp_Explorer E(aWhere, TopAbs_VERTEX);
3835 for(; E.More(); E.Next()) {
3836 if(!aMap.Add(E.Current())) continue;
3837 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
3838 if(P.Distance(P2) <= MAX_TOLERANCE) {
3840 aSubShape = E.Current();
3847 TopoDS_Face aFace = TopoDS::Face(aWhat);
3848 TopExp_Explorer E(aWhere, TopAbs_FACE);
3849 for(; E.More(); E.Next()) {
3850 if(!aMap.Add(E.Current())) continue;
3851 if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
3852 aSubShape = E.Current();
3860 TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
3861 TopExp_Explorer E(aWhere, TopAbs_EDGE);
3862 for(; E.More(); E.Next()) {
3863 if(!aMap.Add(E.Current())) continue;
3864 if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
3865 aSubShape = E.Current();
3872 case TopAbs_SOLID: {
3873 TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
3874 TopExp_Explorer E(aWhere, TopAbs_SOLID);
3875 for(; E.More(); E.Next()) {
3876 if(!aMap.Add(E.Current())) continue;
3877 if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
3878 aSubShape = E.Current();
3890 TopTools_IndexedMapOfShape anIndices;
3891 TopExp::MapShapes(aWhere, anIndices);
3892 if (anIndices.Contains(aSubShape))
3893 anIndex = anIndices.FindIndex(aSubShape);
3896 if(anIndex < 0) return NULL;
3898 Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3900 anArray->SetValue(1, anIndex);
3902 Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
3903 Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
3905 GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
3906 << theShapeWhere << ", " << theShapeWhat << ")";