Salome HOME
NPAL16373: EDF485: GetShapesOn... doesn't work with a wire. Use Poly_Polygon3D, if...
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
8 //
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20
21 #include <Standard_Stream.hxx>
22
23 #include "GEOMImpl_IShapesOperations.hxx"
24
25 #include "GEOMImpl_Types.hxx"
26
27 #include "GEOMImpl_VectorDriver.hxx"
28 #include "GEOMImpl_ShapeDriver.hxx"
29 #include "GEOMImpl_CopyDriver.hxx"
30 #include "GEOMImpl_GlueDriver.hxx"
31
32 #include "GEOMImpl_IVector.hxx"
33 #include "GEOMImpl_IShapes.hxx"
34 #include "GEOMImpl_IGlue.hxx"
35
36 #include "GEOMImpl_Block6Explorer.hxx"
37
38 #include "GEOM_Function.hxx"
39 #include "GEOM_PythonDump.hxx"
40
41 #include "GEOMAlgo_FinderShapeOn1.hxx"
42 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
43 #include "GEOMAlgo_FinderShapeOn2.hxx"
44 #include "GEOMAlgo_ClsfBox.hxx"
45 #include "GEOMAlgo_Gluer1.hxx"
46 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
47 #include "GEOMAlgo_CoupleOfShapes.hxx"
48 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
49
50 #include "utilities.h"
51 #include "OpUtil.hxx"
52 #include "Utils_ExceptHandlers.hxx"
53
54 #include <TFunction_DriverTable.hxx>
55 #include <TFunction_Driver.hxx>
56 #include <TFunction_Logbook.hxx>
57 #include <TDataStd_Integer.hxx>
58 #include <TDataStd_IntegerArray.hxx>
59 #include <TDF_Tool.hxx>
60
61 #include <BRepExtrema_ExtCF.hxx>
62
63 #include <BRep_Tool.hxx>
64 #include <BRep_Builder.hxx>
65 #include <BRepTools.hxx>
66 #include <BRepGProp.hxx>
67 #include <BRepAdaptor_Curve.hxx>
68 #include <BRepAdaptor_Surface.hxx>
69 #include <BRepBndLib.hxx>
70 #include <BRepBuilderAPI_MakeFace.hxx>
71 #include <BRepMesh_IncrementalMesh.hxx>
72
73 #include <TopAbs.hxx>
74 #include <TopExp.hxx>
75 #include <TopoDS.hxx>
76 #include <TopoDS_Shape.hxx>
77 #include <TopoDS_Solid.hxx>
78 #include <TopoDS_Face.hxx>
79 #include <TopoDS_Edge.hxx>
80 #include <TopoDS_Vertex.hxx>
81 #include <TopoDS_Compound.hxx>
82 #include <TopoDS_Iterator.hxx>
83 #include <TopExp_Explorer.hxx>
84 #include <TopLoc_Location.hxx>
85 #include <TopTools_MapOfShape.hxx>
86 #include <TopTools_MapOfOrientedShape.hxx>
87 #include <TopTools_Array1OfShape.hxx>
88 #include <TopTools_ListIteratorOfListOfShape.hxx>
89 #include <TopTools_IndexedMapOfShape.hxx>
90
91 #include <Geom_Surface.hxx>
92 #include <Geom_Plane.hxx>
93 #include <Geom_SphericalSurface.hxx>
94 #include <Geom_CylindricalSurface.hxx>
95 #include <GeomAdaptor_Surface.hxx>
96
97 #include <GeomLib_Tool.hxx>
98 #include <Geom2d_Curve.hxx>
99
100 #include <Bnd_Box.hxx>
101 #include <GProp_GProps.hxx>
102 #include <gp_Pnt.hxx>
103 #include <gp_Lin.hxx>
104 #include <TColStd_ListOfInteger.hxx>
105 #include <TColStd_ListIteratorOfListOfInteger.hxx>
106 #include <TColStd_Array1OfReal.hxx>
107 #include <TColStd_HArray1OfInteger.hxx>
108
109 #include <vector>
110
111 #include <Standard_Failure.hxx>
112 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
113
114 //=============================================================================
115 /*!
116  *   constructor:
117  */
118 //=============================================================================
119 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
120 : GEOM_IOperations(theEngine, theDocID)
121 {
122   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
123 }
124
125 //=============================================================================
126 /*!
127  *  destructor
128  */
129 //=============================================================================
130 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
131 {
132   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
133 }
134
135
136 //=============================================================================
137 /*!
138  *  MakeEdge
139  */
140 //=============================================================================
141 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
142                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
143 {
144   SetErrorCode(KO);
145
146   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
147
148   //Add a new Edge object
149   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
150
151   //Add a new Vector function
152   Handle(GEOM_Function) aFunction =
153     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
154
155   //Check if the function is set correctly
156   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
157
158   GEOMImpl_IVector aPI (aFunction);
159
160   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
161   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
162   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
163
164   aPI.SetPoint1(aRef1);
165   aPI.SetPoint2(aRef2);
166
167   //Compute the Edge value
168   try {
169 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
170     OCC_CATCH_SIGNALS;
171 #endif
172     if (!GetSolver()->ComputeFunction(aFunction)) {
173       SetErrorCode("Vector driver failed");
174       return NULL;
175     }
176   }
177   catch (Standard_Failure) {
178     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
179     SetErrorCode(aFail->GetMessageString());
180     return NULL;
181   }
182
183   //Make a Python command
184   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
185                                << thePnt1 << ", " << thePnt2 << ")";
186
187   SetErrorCode(OK);
188   return anEdge;
189 }
190
191 //=============================================================================
192 /*!
193  *  MakeWire
194  */
195 //=============================================================================
196 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
197                              (list<Handle(GEOM_Object)> theShapes)
198 {
199   return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
200 }
201
202 //=============================================================================
203 /*!
204  *  MakeFace
205  */
206 //=============================================================================
207 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
208                                                           const bool isPlanarWanted)
209 {
210   SetErrorCode(KO);
211
212   if (theWire.IsNull()) return NULL;
213
214   //Add a new Face object
215   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
216
217   //Add a new Shape function for creation of a face from a wire
218   Handle(GEOM_Function) aFunction =
219     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
220   if (aFunction.IsNull()) return NULL;
221
222   //Check if the function is set correctly
223   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
224
225   GEOMImpl_IShapes aCI (aFunction);
226
227   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
228
229   if (aRefWire.IsNull()) return NULL;
230
231   aCI.SetBase(aRefWire);
232   aCI.SetIsPlanar(isPlanarWanted);
233
234   //Compute the Face value
235   try {
236 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
237     OCC_CATCH_SIGNALS;
238 #endif
239     if (!GetSolver()->ComputeFunction(aFunction)) {
240       SetErrorCode("Shape driver failed to compute a face");
241       return NULL;
242     }
243   }
244   catch (Standard_Failure) {
245     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
246     SetErrorCode(aFail->GetMessageString());
247     return NULL;
248   }
249
250   //Make a Python command
251   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
252     << theWire << ", " << (int)isPlanarWanted << ")";
253
254   SetErrorCode(OK);
255   return aFace;
256 }
257
258 //=============================================================================
259 /*!
260  *  MakeFaceWires
261  */
262 //=============================================================================
263 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
264                              (list<Handle(GEOM_Object)> theShapes,
265                               const bool isPlanarWanted)
266 {
267   SetErrorCode(KO);
268
269   //Add a new object
270   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
271
272   //Add a new function
273   Handle(GEOM_Function) aFunction =
274     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
275   if (aFunction.IsNull()) return NULL;
276
277   //Check if the function is set correctly
278   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
279
280   GEOMImpl_IShapes aCI (aFunction);
281
282   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
283
284   // Shapes
285   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
286   for (; it != theShapes.end(); it++) {
287     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
288     if (aRefSh.IsNull()) {
289       SetErrorCode("NULL argument shape for the face construction");
290       return NULL;
291     }
292     aShapesSeq->Append(aRefSh);
293   }
294   aCI.SetShapes(aShapesSeq);
295
296   aCI.SetIsPlanar(isPlanarWanted);
297
298   //Compute the shape
299   try {
300 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
301     OCC_CATCH_SIGNALS;
302 #endif
303     if (!GetSolver()->ComputeFunction(aFunction)) {
304       SetErrorCode("Shape driver failed");
305       return NULL;
306     }
307   }
308   catch (Standard_Failure) {
309     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
310     SetErrorCode(aFail->GetMessageString());
311     return NULL;
312   }
313
314   //Make a Python command
315   GEOM::TPythonDump pd (aFunction);
316   pd << aShape << " = geompy.MakeFaceWires([";
317
318   // Shapes
319   it = theShapes.begin();
320   if (it != theShapes.end()) {
321     pd << (*it++);
322     while (it != theShapes.end()) {
323       pd << ", " << (*it++);
324     }
325   }
326   pd << "], " << (int)isPlanarWanted << ")";
327
328   SetErrorCode(OK);
329   return aShape;
330 }
331
332 //=============================================================================
333 /*!
334  *  MakeShell
335  */
336 //=============================================================================
337 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
338                              (list<Handle(GEOM_Object)> theShapes)
339 {
340   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
341 }
342
343 //=============================================================================
344 /*!
345  *  MakeSolidShells
346  */
347 //=============================================================================
348 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
349                              (list<Handle(GEOM_Object)> theShapes)
350 {
351   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
352 }
353
354 //=============================================================================
355 /*!
356  *  MakeSolidShell
357  */
358 //=============================================================================
359 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
360 {
361   SetErrorCode(KO);
362
363   if (theShell.IsNull()) return NULL;
364
365   //Add a new Solid object
366   Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
367
368   //Add a new Solid function for creation of a solid from a shell
369   Handle(GEOM_Function) aFunction =
370     aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
371   if (aFunction.IsNull()) return NULL;
372
373   //Check if the function is set correctly
374   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
375
376   GEOMImpl_IShapes aCI (aFunction);
377
378   Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
379
380   if (aRefShell.IsNull()) return NULL;
381
382   aCI.SetBase(aRefShell);
383
384   //Compute the Solid value
385   try {
386 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
387     OCC_CATCH_SIGNALS;
388 #endif
389     if (!GetSolver()->ComputeFunction(aFunction)) {
390       SetErrorCode("Solid driver failed");
391       return NULL;
392     }
393   }
394   catch (Standard_Failure) {
395     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
396     SetErrorCode(aFail->GetMessageString());
397     return NULL;
398   }
399
400   //Make a Python command
401   GEOM::TPythonDump(aFunction) << aSolid
402     << " = geompy.MakeSolid(" << theShell << ")";
403
404   SetErrorCode(OK);
405   return aSolid;
406 }
407
408 //=============================================================================
409 /*!
410  *  MakeCompound
411  */
412 //=============================================================================
413 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
414                              (list<Handle(GEOM_Object)> theShapes)
415 {
416   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
417 }
418
419 //=============================================================================
420 /*!
421  *  MakeShape
422  */
423 //=============================================================================
424 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
425                              (list<Handle(GEOM_Object)>      theShapes,
426                               const Standard_Integer         theObjectType,
427                               const Standard_Integer         theFunctionType,
428                               const TCollection_AsciiString& theMethodName)
429 {
430   SetErrorCode(KO);
431
432   //Add a new object
433   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
434
435   //Add a new function
436   Handle(GEOM_Function) aFunction =
437     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
438   if (aFunction.IsNull()) return NULL;
439
440   //Check if the function is set correctly
441   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
442
443   GEOMImpl_IShapes aCI (aFunction);
444
445   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
446
447   // Shapes
448   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
449   for (; it != theShapes.end(); it++) {
450     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
451     if (aRefSh.IsNull()) {
452       SetErrorCode("NULL argument shape for the shape construction");
453       return NULL;
454     }
455     aShapesSeq->Append(aRefSh);
456   }
457   aCI.SetShapes(aShapesSeq);
458
459   //Compute the shape
460   try {
461 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
462     OCC_CATCH_SIGNALS;
463 #endif
464     if (!GetSolver()->ComputeFunction(aFunction)) {
465       SetErrorCode("Shape driver failed");
466       return NULL;
467     }
468   }
469   catch (Standard_Failure) {
470     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
471     SetErrorCode(aFail->GetMessageString());
472     return NULL;
473   }
474
475   //Make a Python command
476   GEOM::TPythonDump pd (aFunction);
477   pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
478
479   // Shapes
480   it = theShapes.begin();
481   if (it != theShapes.end()) {
482     pd << (*it++);
483     while (it != theShapes.end()) {
484       pd << ", " << (*it++);
485     }
486   }
487   pd << "])";
488
489   SetErrorCode(OK);
490   return aShape;
491 }
492
493 //=============================================================================
494 /*!
495  *  MakeGlueFaces
496  */
497 //=============================================================================
498 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
499                                                 (Handle(GEOM_Object) theShape,
500                                                  const Standard_Real theTolerance)
501 {
502   SetErrorCode(KO);
503
504   if (theShape.IsNull()) return NULL;
505
506   //Add a new Glued object
507   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
508
509   //Add a new Glue function
510   Handle(GEOM_Function) aFunction;
511   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
512   if (aFunction.IsNull()) return NULL;
513
514   //Check if the function is set correctly
515   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
516
517   GEOMImpl_IGlue aCI (aFunction);
518
519   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
520   if (aRefShape.IsNull()) return NULL;
521
522   aCI.SetBase(aRefShape);
523   aCI.SetTolerance(theTolerance);
524
525   //Compute the sub-shape value
526   Standard_Boolean isWarning = Standard_False;
527   try {
528 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
529     OCC_CATCH_SIGNALS;
530 #endif
531     if (!GetSolver()->ComputeFunction(aFunction)) {
532       SetErrorCode("Shape driver failed to glue faces");
533       return NULL;
534     }
535   }
536   catch (Standard_Failure) {
537     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
538     SetErrorCode(aFail->GetMessageString());
539     // to provide warning
540     if (!aFunction->GetValue().IsNull()) {
541       isWarning = Standard_True;
542     } else {
543       return NULL;
544     }
545   }
546
547   //Make a Python command
548   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
549     << theShape << ", " << theTolerance << ")";
550
551   // to provide warning
552   if (!isWarning) SetErrorCode(OK);
553   return aGlued;
554 }
555
556 //=============================================================================
557 /*!
558  *  GetGlueFaces
559  */
560 //=============================================================================
561 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
562                                                 (Handle(GEOM_Object) theShape,
563                                                  const Standard_Real theTolerance)
564 {
565   SetErrorCode(KO);
566
567   if (theShape.IsNull()) return NULL;
568   TopoDS_Shape aShape = theShape->GetValue();
569   if (aShape.IsNull()) return NULL;
570
571   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
572
573   Standard_Integer iErr;
574   TopoDS_Shape aS;
575   GEOMAlgo_Gluer1 aGluer;
576   GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
577   GEOMAlgo_CoupleOfShapes aCS;
578   GEOMAlgo_ListOfCoupleOfShapes aLCS;
579
580   //aGluer = new GEOMAlgo_Gluer1;
581   aGluer.SetShape(aShape);
582   aGluer.SetTolerance(theTolerance);
583   aGluer.Perform();
584   iErr = aGluer.ErrorStatus();
585   if (iErr) return NULL;
586
587   TopTools_ListOfShape listShape;
588   const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
589   // Access to faces
590   aItCS.Initialize(aLCSG);
591   for (; aItCS.More(); aItCS.Next()) {
592     const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
593     listShape.Append(aCSG.Shape1());
594   }
595
596   TopTools_ListIteratorOfListOfShape itSub (listShape);
597   TCollection_AsciiString anAsciiList, anEntry;
598   TopTools_IndexedMapOfShape anIndices;
599   TopExp::MapShapes(aShape, anIndices);
600   Handle(TColStd_HArray1OfInteger) anArray;
601   Handle(GEOM_Object) anObj;
602   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
603     TopoDS_Shape aValue = itSub.Value();
604     anArray = new TColStd_HArray1OfInteger(1,1);
605     anArray->SetValue(1, anIndices.FindIndex(aValue));
606     anObj = GetEngine()->AddSubShape(theShape, anArray);
607     if (!anObj.IsNull()) {
608       aSeq->Append(anObj);
609
610       // for python command
611       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
612       anAsciiList += anEntry;
613       anAsciiList += ",";
614     }
615   }
616
617   //Make a Python command
618   if(anAsciiList.Length()>0)
619     anAsciiList.Trunc(anAsciiList.Length() - 1);
620   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
621   GEOM::TPythonDump pd (aFunction, /*append=*/true);
622   pd << "[" << anAsciiList.ToCString();
623   pd << "] = geompy.GetGlueFaces" << theShape << ", " << theTolerance << ")";
624
625   SetErrorCode(OK);
626
627   return aSeq;
628 }
629
630
631 //=============================================================================
632 /*!
633  *  MakeGlueFacesByList
634  */
635 //=============================================================================
636 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList
637                                                 (Handle(GEOM_Object) theShape,
638                                                  const Standard_Real theTolerance,
639                                                  list<Handle(GEOM_Object)> theFaces)
640 {
641   SetErrorCode(KO);
642
643   if (theShape.IsNull()) return NULL;
644
645   //Add a new Glued object
646   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
647
648   //Add a new Glue function
649   Handle(GEOM_Function) aFunction;
650   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
651   if (aFunction.IsNull()) return NULL;
652
653   //Check if the function is set correctly
654   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
655
656   GEOMImpl_IGlue aCI (aFunction);
657
658   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
659   if (aRefShape.IsNull()) return NULL;
660
661   aCI.SetBase(aRefShape);
662   aCI.SetTolerance(theTolerance);
663   Handle(TColStd_HSequenceOfTransient) aFaces = new TColStd_HSequenceOfTransient;
664   list<Handle(GEOM_Object)>::iterator it = theFaces.begin();
665   for (; it != theFaces.end(); it++) {
666     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
667     if (aRefSh.IsNull()) {
668       SetErrorCode("NULL argument shape for the shape construction");
669       return NULL;
670     }
671     aFaces->Append(aRefSh);
672   }
673   aCI.SetFaces(aFaces);
674
675   //Compute the sub-shape value
676   Standard_Boolean isWarning = Standard_False;
677   try {
678 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
679     OCC_CATCH_SIGNALS;
680 #endif
681     if (!GetSolver()->ComputeFunction(aFunction)) {
682       SetErrorCode("Shape driver failed to glue faces");
683       return NULL;
684     }
685   }
686   catch (Standard_Failure) {
687     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
688     SetErrorCode(aFail->GetMessageString());
689     // to provide warning
690     if (!aFunction->GetValue().IsNull()) {
691       isWarning = Standard_True;
692     } else {
693       return NULL;
694     }
695   }
696
697   //Make a Python command
698   
699   GEOM::TPythonDump pd(aFunction);
700   pd << aGlued << " = geompy.MakeGlueFacesByList("
701      << theShape << ", " << theTolerance << ", [";
702   // Faces
703   it = theFaces.begin();
704   if (it != theFaces.end()) {
705     pd << (*it++);
706     while (it != theFaces.end()) {
707       pd << ", " << (*it++);
708     }
709   }
710   pd << "])";
711
712
713   // to provide warning
714   if (!isWarning) SetErrorCode(OK);
715   return aGlued;
716 }
717
718
719
720 //=============================================================================
721 /*!
722  *  MakeExplode
723  */
724 //=============================================================================
725 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
726                                           (Handle(GEOM_Object)    theShape,
727                                            const Standard_Integer theShapeType,
728                                            const Standard_Boolean isSorted)
729 {
730   SetErrorCode(KO);
731
732   if (theShape.IsNull()) return NULL;
733   TopoDS_Shape aShape = theShape->GetValue();
734   if (aShape.IsNull()) return NULL;
735
736   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
737   Handle(GEOM_Object) anObj;
738   Handle(GEOM_Function) aFunction;
739   TopTools_MapOfShape mapShape;
740   TopTools_ListOfShape listShape;
741
742   if (aShape.ShapeType() == TopAbs_COMPOUND &&
743       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
744        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
745        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
746     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
747     for (; It.More(); It.Next()) {
748       if (mapShape.Add(It.Value())) {
749         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
750             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
751           listShape.Append(It.Value());
752         }
753       }
754     }
755   } else {
756     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
757     for (; exp.More(); exp.Next())
758       if (mapShape.Add(exp.Current()))
759         listShape.Append(exp.Current());
760   }
761
762   if (listShape.IsEmpty()) {
763     SetErrorCode("The given shape has no sub-shapes of the requested type");
764     return aSeq;
765   }
766
767   if (isSorted)
768     SortShapes(listShape);
769
770   TopTools_IndexedMapOfShape anIndices;
771   TopExp::MapShapes(aShape, anIndices);
772   Handle(TColStd_HArray1OfInteger) anArray;
773
774   TopTools_ListIteratorOfListOfShape itSub (listShape);
775   TCollection_AsciiString anAsciiList, anEntry;
776   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
777     TopoDS_Shape aValue = itSub.Value();
778     anArray = new TColStd_HArray1OfInteger(1,1);
779     anArray->SetValue(1, anIndices.FindIndex(aValue));
780     anObj = GetEngine()->AddSubShape(theShape, anArray);
781     if (!anObj.IsNull()) {
782       aSeq->Append(anObj);
783
784       // for python command
785       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
786       anAsciiList += anEntry;
787       anAsciiList += ",";
788     }
789   }
790
791   //Make a Python command
792   anAsciiList.Trunc(anAsciiList.Length() - 1);
793
794   aFunction = theShape->GetLastFunction();
795
796   GEOM::TPythonDump pd (aFunction, /*append=*/true);
797   pd << "[" << anAsciiList.ToCString();
798   pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
799   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
800
801   SetErrorCode(OK);
802
803   return aSeq;
804 }
805
806 //=============================================================================
807 /*!
808  *  GetSubShapeAllIDs
809  */
810 //=============================================================================
811 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
812                                           (Handle(GEOM_Object)    theShape,
813                                            const Standard_Integer theShapeType,
814                                            const Standard_Boolean isSorted)
815 {
816   SetErrorCode(KO);
817
818   if (theShape.IsNull()) return NULL;
819   TopoDS_Shape aShape = theShape->GetValue();
820   if (aShape.IsNull()) return NULL;
821
822   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
823   TopTools_MapOfShape mapShape;
824   TopTools_ListOfShape listShape;
825
826   if (aShape.ShapeType() == TopAbs_COMPOUND &&
827       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
828        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
829        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
830     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
831     for (; It.More(); It.Next()) {
832       if (mapShape.Add(It.Value())) {
833         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
834             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
835           listShape.Append(It.Value());
836         }
837       }
838     }
839   } else {
840     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
841     for (; exp.More(); exp.Next())
842       if (mapShape.Add(exp.Current()))
843         listShape.Append(exp.Current());
844   }
845
846   if (listShape.IsEmpty()) {
847     SetErrorCode("The given shape has no sub-shapes of the requested type");
848     return aSeq;
849   }
850
851   if (isSorted)
852     SortShapes(listShape);
853
854   TopTools_IndexedMapOfShape anIndices;
855   TopExp::MapShapes(aShape, anIndices);
856   Handle(TColStd_HArray1OfInteger) anArray;
857
858   TopTools_ListIteratorOfListOfShape itSub (listShape);
859   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
860     TopoDS_Shape aValue = itSub.Value();
861     aSeq->Append(anIndices.FindIndex(aValue));
862   }
863
864   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
865
866   //Make a Python command
867   GEOM::TPythonDump pd (aFunction, /*append=*/true);
868   pd << "listSubShapeIDs = geompy.SubShapeAll";
869   pd << (isSorted ? "SortedIDs(" : "IDs(");
870   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
871
872   SetErrorCode(OK);
873   return aSeq;
874 }
875
876 //=============================================================================
877 /*!
878  *  GetSubShape
879  */
880 //=============================================================================
881 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
882                                           (Handle(GEOM_Object)    theMainShape,
883                                            const Standard_Integer theID)
884 {
885   SetErrorCode(KO);
886
887   if (theMainShape.IsNull()) return NULL;
888
889   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
890   anArray->SetValue(1, theID);
891   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
892   if (anObj.IsNull()) {
893     SetErrorCode("Can not get a sub-shape with the given ID");
894     return NULL;
895   }
896
897   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
898
899   //Make a Python command
900   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
901                                << theMainShape << ", [" << theID << "])";
902
903   SetErrorCode(OK);
904   return anObj;
905 }
906
907 //=============================================================================
908 /*!
909  *  GetSubShapeIndex
910  */
911 //=============================================================================
912 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
913                                                                Handle(GEOM_Object) theSubShape)
914 {
915   SetErrorCode(KO);
916
917   TopoDS_Shape aMainShape = theMainShape->GetValue();
918   TopoDS_Shape aSubShape = theSubShape->GetValue();
919
920   if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
921
922   TopTools_IndexedMapOfShape anIndices;
923   TopExp::MapShapes(aMainShape, anIndices);
924   if (anIndices.Contains(aSubShape)) {
925     SetErrorCode(OK);
926     return anIndices.FindIndex(aSubShape);
927   }
928
929   return -1;
930 }
931
932 //=============================================================================
933 /*!
934  *  GetTopologyIndex
935  */
936 //=============================================================================
937 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
938                                                                Handle(GEOM_Object) theSubShape)
939 {
940   SetErrorCode(OK);
941
942   TopoDS_Shape aMainShape = theMainShape->GetValue();
943   TopoDS_Shape aSubShape = theSubShape->GetValue();
944
945   if (aMainShape.IsNull() || aSubShape.IsNull()) {
946     SetErrorCode("Null argument shape given");
947     return -1;
948   }
949
950   int index = 1;
951   if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
952     TopoDS_Iterator it;
953     TopTools_ListOfShape CL;
954     CL.Append(aMainShape);
955     TopTools_ListIteratorOfListOfShape itC;
956     for (itC.Initialize(CL); itC.More(); itC.Next()) {
957       for (it.Initialize(itC.Value()); it.More(); it.Next()) {
958         if (it.Value().ShapeType() == TopAbs_COMPOUND) {
959           if (it.Value().IsSame(aSubShape))
960             return index;
961           else
962             index++;
963           CL.Append(it.Value());
964         }
965       }
966     }
967   } else {
968     TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
969     TopTools_MapOfShape M;
970     for (; anExp.More(); anExp.Next()) {
971       if (M.Add(anExp.Current())) {
972         if (anExp.Current().IsSame(aSubShape))
973           return index;
974         index++;
975       }
976     }
977   }
978
979   SetErrorCode("The sub-shape does not belong to the main shape");
980   return -1;
981 }
982
983 //=============================================================================
984 /*!
985  *  GetShapeTypeString
986  */
987 //=============================================================================
988 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
989 {
990   SetErrorCode(KO);
991
992   TCollection_AsciiString aTypeName ("Null Shape");
993
994   TopoDS_Shape aShape = theShape->GetValue();
995   if (aShape.IsNull())
996     return aTypeName;
997
998   switch (aShape.ShapeType() )
999   {
1000   case TopAbs_COMPOUND:
1001     aTypeName = "Compound";
1002     break;
1003   case  TopAbs_COMPSOLID:
1004     aTypeName = "Compound Solid";
1005     break;
1006   case TopAbs_SOLID:
1007     aTypeName = "Solid";
1008     break;
1009   case TopAbs_SHELL:
1010     aTypeName = "Shell";
1011     break;
1012   case TopAbs_FACE:
1013     {
1014       BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1015       if (surf.GetType() == GeomAbs_Plane)
1016         aTypeName = "Plane";
1017       else if (surf.GetType() == GeomAbs_Cylinder)
1018         aTypeName = "Cylindrical Face";
1019       else if (surf.GetType() == GeomAbs_Sphere)
1020         aTypeName = "Spherical Face";
1021       else if (surf.GetType() == GeomAbs_Torus)
1022         aTypeName = "Toroidal Face";
1023       else if (surf.GetType() == GeomAbs_Cone)
1024         aTypeName = "Conical Face";
1025       else
1026         aTypeName = "GEOM::FACE";
1027     }
1028     break;
1029   case TopAbs_WIRE:
1030     aTypeName = "Wire";
1031     break;
1032   case TopAbs_EDGE:
1033     {
1034       BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1035       if (curv.GetType() == GeomAbs_Line) {
1036         if ((Abs(curv.FirstParameter()) >= 1E6) ||
1037             (Abs(curv.LastParameter()) >= 1E6))
1038           aTypeName = "Line";
1039         else
1040           aTypeName = "Edge" ;
1041       } else if (curv.GetType() == GeomAbs_Circle) {
1042         if (curv.IsClosed())
1043           aTypeName = "Circle";
1044         else
1045           aTypeName = "Arc";
1046       } else {
1047         aTypeName = "Edge";
1048       }
1049     }
1050     break;
1051   case TopAbs_VERTEX:
1052     aTypeName = "Vertex";
1053     break;
1054   case TopAbs_SHAPE:
1055     aTypeName = "Shape";
1056     break;
1057   default:
1058     aTypeName = "Shape of unknown type";
1059   }
1060
1061   return aTypeName;
1062 }
1063
1064
1065 //=============================================================================
1066 /*!
1067  *  NumberOfFaces
1068  */
1069 //=============================================================================
1070 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
1071 {
1072   SetErrorCode(KO);
1073
1074   Standard_Integer nb = 0;
1075
1076   if (theShape.IsNull()) return -1;
1077   TopoDS_Shape aShape = theShape->GetValue();
1078   if (aShape.IsNull()) return -1;
1079
1080   TopTools_MapOfShape mapShape;
1081
1082   TopExp_Explorer exp (aShape, TopAbs_FACE);
1083   for (; exp.More(); exp.Next())
1084     if (mapShape.Add(exp.Current()))
1085       nb++;
1086
1087   SetErrorCode(OK);
1088   return nb;
1089 }
1090
1091 //=============================================================================
1092 /*!
1093  *  NumberOfEdges
1094  */
1095 //=============================================================================
1096 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
1097 {
1098   SetErrorCode(KO);
1099
1100   Standard_Integer nb = 0;
1101
1102   if (theShape.IsNull()) return -1;
1103   TopoDS_Shape aShape = theShape->GetValue();
1104   if (aShape.IsNull()) return -1;
1105
1106   TopTools_MapOfShape mapShape;
1107
1108   TopExp_Explorer exp (aShape, TopAbs_EDGE);
1109   for (; exp.More(); exp.Next())
1110     if (mapShape.Add(exp.Current()))
1111       nb++;
1112
1113   SetErrorCode(OK);
1114   return nb;
1115 }
1116
1117 //=============================================================================
1118 /*!
1119  *  ReverseShape
1120  */
1121 //=============================================================================
1122 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
1123 {
1124   SetErrorCode(KO);
1125
1126   if (theShape.IsNull()) return NULL;
1127
1128   //Add a new reversed object
1129   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
1130
1131   //Add a new Revese function
1132   Handle(GEOM_Function) aFunction;
1133   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
1134   if (aFunction.IsNull()) return NULL;
1135
1136   //Check if the function is set correctly
1137   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
1138
1139   GEOMImpl_IShapes aSI (aFunction);
1140
1141   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1142   if (aRefShape.IsNull()) return NULL;
1143
1144   aSI.SetBase(aRefShape);
1145
1146   //Compute the sub-shape value
1147   try {
1148 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1149     OCC_CATCH_SIGNALS;
1150 #endif
1151     if (!GetSolver()->ComputeFunction(aFunction)) {
1152       SetErrorCode("Shape driver failed to reverse shape");
1153       return NULL;
1154     }
1155   }
1156   catch (Standard_Failure) {
1157     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1158     SetErrorCode(aFail->GetMessageString());
1159     return NULL;
1160   }
1161
1162   //Make a Python command
1163   GEOM::TPythonDump(aFunction) << aReversed
1164     << " = geompy.ChangeOrientation(" << theShape << ")";
1165
1166   SetErrorCode(OK);
1167   return aReversed;
1168 }
1169
1170 //=============================================================================
1171 /*!
1172  *  GetFreeFacesIDs
1173  */
1174 //=============================================================================
1175 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
1176                                                  (Handle(GEOM_Object) theShape)
1177 {
1178   SetErrorCode(KO);
1179
1180   if (theShape.IsNull()) return NULL;
1181   TopoDS_Shape aShape = theShape->GetValue();
1182   if (aShape.IsNull()) return NULL;
1183
1184   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1185
1186   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1187   GEOMImpl_Block6Explorer::MapShapesAndAncestors
1188     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1189
1190   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1191
1192   if (nbFaces == 0) {
1193     SetErrorCode("The given shape has no faces");
1194     return aSeq;
1195   }
1196
1197   TopTools_IndexedMapOfShape anIndices;
1198   TopExp::MapShapes(aShape, anIndices);
1199
1200   Standard_Integer id;
1201   for (; ind <= nbFaces; ind++) {
1202     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1203       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1204       aSeq->Append(id);
1205     }
1206   }
1207
1208   //The explode doesn't change object so no new function is required.
1209   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1210
1211   //Make a Python command
1212   GEOM::TPythonDump(aFunction, /*append=*/true)
1213     << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
1214
1215   SetErrorCode(OK);
1216   return aSeq;
1217 }
1218
1219 //=======================================================================
1220 //function : GetSharedShapes
1221 //purpose  :
1222 //=======================================================================
1223
1224 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1225                                                 (Handle(GEOM_Object)    theShape1,
1226                                                  Handle(GEOM_Object)    theShape2,
1227                                                  const Standard_Integer theShapeType)
1228 {
1229   SetErrorCode(KO);
1230
1231   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
1232
1233   TopoDS_Shape aShape1 = theShape1->GetValue();
1234   TopoDS_Shape aShape2 = theShape2->GetValue();
1235
1236   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
1237
1238   TopTools_IndexedMapOfShape anIndices;
1239   TopExp::MapShapes(aShape1, anIndices);
1240   Handle(TColStd_HArray1OfInteger) anArray;
1241
1242   TopTools_IndexedMapOfShape mapShape1;
1243   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
1244
1245   Handle(GEOM_Object) anObj;
1246   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1247   TCollection_AsciiString anAsciiList, anEntry;
1248
1249   TopTools_MapOfShape mapShape2;
1250   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
1251   for (; exp.More(); exp.Next()) {
1252     TopoDS_Shape aSS = exp.Current();
1253     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
1254       anArray = new TColStd_HArray1OfInteger(1,1);
1255       anArray->SetValue(1, anIndices.FindIndex(aSS));
1256       anObj = GetEngine()->AddSubShape(theShape1, anArray);
1257       aSeq->Append(anObj);
1258
1259       // for python command
1260       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1261       anAsciiList += anEntry;
1262       anAsciiList += ",";
1263     }
1264   }
1265
1266   if (aSeq->IsEmpty()) {
1267     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
1268     return aSeq;
1269   }
1270
1271   //Make a Python command
1272   anAsciiList.Trunc(anAsciiList.Length() - 1);
1273
1274   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1275
1276   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1277     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
1278       << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1279
1280   SetErrorCode(OK);
1281   return aSeq;
1282 }
1283
1284 //=============================================================================
1285 /*!
1286  *
1287  */
1288 //=============================================================================
1289 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
1290                                       const GEOMAlgo_State theState)
1291 {
1292   switch (theState) {
1293   case GEOMAlgo_ST_IN:
1294     theDump << "geompy.GEOM.ST_IN";
1295     break;
1296   case GEOMAlgo_ST_OUT:
1297     theDump << "geompy.GEOM.ST_OUT";
1298     break;
1299   case GEOMAlgo_ST_ON:
1300     theDump << "geompy.GEOM.ST_ON";
1301     break;
1302   case GEOMAlgo_ST_ONIN:
1303     theDump << "geompy.GEOM.ST_ONIN";
1304     break;
1305   case GEOMAlgo_ST_ONOUT:
1306     theDump << "geompy.GEOM.ST_ONOUT";
1307     break;
1308   default:
1309     theDump << "geompy.GEOM.ST_UNKNOWN";
1310     break;
1311   }
1312   return theDump;
1313 }
1314
1315 //=======================================================================
1316 //function : checkTypeShapesOn
1317 /*!
1318  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
1319  * \param theShapeType - the shape type to check
1320  * \retval bool  - result of the check
1321  */
1322 //=======================================================================
1323
1324 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
1325 {
1326   if (theShapeType != TopAbs_VERTEX &&
1327       theShapeType != TopAbs_EDGE &&
1328       theShapeType != TopAbs_FACE &&
1329       theShapeType != TopAbs_SOLID) {
1330     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1331     return false;
1332   }
1333   return true;
1334 }
1335
1336 //=======================================================================
1337 //function : makePlane
1338   /*!
1339    * \brief Creates Geom_Plane
1340     * \param theAx1 - shape object defining plane parameters
1341     * \retval Handle(Geom_Surface) - resulting surface
1342    */
1343 //=======================================================================
1344
1345 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
1346 {
1347   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1348   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1349   TopoDS_Vertex V1, V2;
1350   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1351   if (V1.IsNull() || V2.IsNull()) {
1352     SetErrorCode("Bad edge given for the plane normal vector");
1353     return NULL;
1354   }
1355   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1356   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1357   if (aVec.Magnitude() < Precision::Confusion()) {
1358     SetErrorCode("Vector with null magnitude given");
1359     return NULL;
1360   }
1361   return new Geom_Plane(aLoc, aVec);
1362 }
1363
1364 //=======================================================================
1365 //function : makeCylinder
1366   /*!
1367    * \brief Creates Geom_CylindricalSurface
1368     * \param theAx1 - edge defining cylinder axis
1369     * \param theRadius - cylinder radius
1370     * \retval Handle(Geom_Surface) - resulting surface
1371    */
1372 //=======================================================================
1373
1374 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
1375                                                               const Standard_Real theRadius)
1376 {
1377   //Axis of the cylinder
1378   if (anAxis.ShapeType() != TopAbs_EDGE) {
1379     SetErrorCode("Not an edge given for the axis");
1380     return NULL;
1381   }
1382   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1383   TopoDS_Vertex V1, V2;
1384   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1385   if (V1.IsNull() || V2.IsNull()) {
1386     SetErrorCode("Bad edge given for the axis");
1387     return NULL;
1388   }
1389   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1390   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1391   if (aVec.Magnitude() < Precision::Confusion()) {
1392     SetErrorCode("Vector with null magnitude given");
1393     return NULL;
1394   }
1395
1396   gp_Ax3 anAx3 (aLoc, aVec);
1397   return new Geom_CylindricalSurface(anAx3, theRadius);
1398 }
1399
1400
1401 //=======================================================================
1402 //function : getShapesOnBoxIDs
1403   /*!
1404    * \brief Find IDs of subshapes complying with given status about surface
1405     * \param theBox - the box to check state of subshapes against
1406     * \param theShape - the shape to explore
1407     * \param theShapeType - type of subshape of theShape
1408     * \param theState - required state
1409     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1410    */
1411 //=======================================================================
1412
1413 Handle(TColStd_HSequenceOfInteger)
1414   GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1415                                                 const Handle(GEOM_Object)& theShape,
1416                                                 const Standard_Integer theShapeType,
1417                                                 GEOMAlgo_State theState)
1418 {
1419   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1420
1421   TopoDS_Shape aBox = theBox->GetValue();
1422   TopoDS_Shape aShape = theShape->GetValue();
1423
1424   // Check presence of triangulation, build if need
1425   if (!CheckTriangulation(aShape)) {
1426     SetErrorCode("Cannot build triangulation on the shape");
1427     return aSeqOfIDs;
1428   }
1429
1430   // Call algo
1431   GEOMAlgo_FinderShapeOn2 aFinder;
1432   Standard_Real aTol = 0.0001; // default value
1433
1434   Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
1435   aClsfBox->SetBox(aBox);
1436
1437   aFinder.SetShape(aShape);
1438   aFinder.SetTolerance(aTol);
1439   aFinder.SetClsf(aClsfBox);
1440   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1441   aFinder.SetState(theState);
1442   aFinder.Perform();
1443
1444   // Interprete results
1445   Standard_Integer iErr = aFinder.ErrorStatus();
1446   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1447   if (iErr) {
1448     MESSAGE(" iErr : " << iErr);
1449     TCollection_AsciiString aMsg (" iErr : ");
1450     aMsg += TCollection_AsciiString(iErr);
1451     SetErrorCode(aMsg);
1452     return aSeqOfIDs;
1453   }
1454   Standard_Integer iWrn = aFinder.WarningStatus();
1455   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1456   if (iWrn) {
1457     MESSAGE(" *** iWrn : " << iWrn);
1458   }
1459
1460   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1461
1462   if (listSS.Extent() < 1) {
1463     SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1464     return aSeqOfIDs;
1465   }
1466
1467   // Fill sequence of object IDs
1468   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1469
1470   TopTools_IndexedMapOfShape anIndices;
1471   TopExp::MapShapes(aShape, anIndices);
1472
1473   TopTools_ListIteratorOfListOfShape itSub (listSS);
1474   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1475     int id = anIndices.FindIndex(itSub.Value());
1476     aSeqOfIDs->Append(id);
1477   }
1478
1479   return aSeqOfIDs;
1480 }
1481
1482
1483 //=======================================================================
1484 //function : GetShapesOnBoxIDs
1485 /*!
1486    * \brief Find subshapes complying with given status about surface
1487     * \param theBox - the box to check state of subshapes against
1488     * \param theShape - the shape to explore
1489     * \param theShapeType - type of subshape of theShape
1490     * \param theState - required state
1491     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1492  */
1493 //=======================================================================
1494
1495 Handle(TColStd_HSequenceOfInteger)
1496     GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1497                                                   const Handle(GEOM_Object)& theShape,
1498                                                   const Standard_Integer theShapeType,
1499                                                   GEOMAlgo_State theState)
1500 {
1501   // Find subshapes ids
1502   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1503     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1504   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1505     return NULL;
1506
1507   // The GetShapesOnBox() doesn't change object so no new function is required.
1508   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
1509
1510   // Make a Python command
1511   GEOM::TPythonDump(aFunction)
1512     << "listShapesOnBoxIDs = geompy.GetShapesOnQuadrangleIDs("
1513     << theBox << ", "
1514     << theShape << ", "
1515     << TopAbs_ShapeEnum(theShapeType) << ", "
1516     << theState << ")";
1517
1518   SetErrorCode(OK);
1519   return aSeqOfIDs;
1520 }
1521
1522 //=======================================================================
1523 //function : GetShapesOnBox
1524 /*!
1525    * \brief Find subshapes complying with given status about surface
1526     * \param theBox - the box to check state of subshapes against
1527     * \param theShape - the shape to explore
1528     * \param theShapeType - type of subshape of theShape
1529     * \param theState - required state
1530     * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1531  */
1532 //=======================================================================
1533
1534 Handle(TColStd_HSequenceOfTransient)
1535     GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
1536                                                const Handle(GEOM_Object)&  theShape,
1537                                                const Standard_Integer theShapeType,
1538                                                GEOMAlgo_State theState)
1539 {
1540   // Find subshapes ids
1541   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1542     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1543   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1544     return NULL;
1545
1546   // Find objects by indices
1547   TCollection_AsciiString anAsciiList;
1548   Handle(TColStd_HSequenceOfTransient) aSeq;
1549   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1550   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1551     return NULL;
1552
1553   // Make a Python command
1554
1555   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1556   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1557
1558   GEOM::TPythonDump(aFunction)
1559     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
1560     << theBox << ", "
1561     << theShape << ", "
1562     << TopAbs_ShapeEnum(theShapeType) << ", "
1563     << theState << ")";
1564
1565   SetErrorCode(OK);
1566   return aSeq;
1567 }
1568
1569
1570 //=======================================================================
1571 //function : getShapesOnSurfaceIDs
1572   /*!
1573    * \brief Find IDs of subshapes complying with given status about surface
1574     * \param theSurface - the surface to check state of subshapes against
1575     * \param theShape - the shape to explore
1576     * \param theShapeType - type of subshape of theShape
1577     * \param theState - required state
1578     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1579    */
1580 //=======================================================================
1581
1582 Handle(TColStd_HSequenceOfInteger)
1583   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
1584                                                     const TopoDS_Shape&         theShape,
1585                                                     TopAbs_ShapeEnum            theShapeType,
1586                                                     GEOMAlgo_State              theState)
1587 {
1588   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1589
1590   // Check presence of triangulation, build if need
1591   if (!CheckTriangulation(theShape)) {
1592     SetErrorCode("Cannot build triangulation on the shape");
1593     return aSeqOfIDs;
1594   }
1595
1596   // Call algo
1597   GEOMAlgo_FinderShapeOn1 aFinder;
1598   Standard_Real aTol = 0.0001; // default value
1599
1600   aFinder.SetShape(theShape);
1601   aFinder.SetTolerance(aTol);
1602   aFinder.SetSurface(theSurface);
1603   aFinder.SetShapeType(theShapeType);
1604   aFinder.SetState(theState);
1605
1606   // Sets the minimal number of inner points for the faces that do not have own
1607   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1608   // Default value=3
1609   aFinder.SetNbPntsMin(3);
1610   // Sets the maximal number of inner points for edges or faces.
1611   // It is usefull for the cases when this number is very big (e.g =2000) to improve
1612   // the performance. If this value =0, all inner points will be taken into account.
1613   // Default value=0
1614   aFinder.SetNbPntsMax(100);
1615
1616   aFinder.Perform();
1617
1618   // Interprete results
1619   Standard_Integer iErr = aFinder.ErrorStatus();
1620   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1621   if (iErr) {
1622     MESSAGE(" iErr : " << iErr);
1623     TCollection_AsciiString aMsg (" iErr : ");
1624     aMsg += TCollection_AsciiString(iErr);
1625     SetErrorCode(aMsg);
1626     return aSeqOfIDs;
1627   }
1628   Standard_Integer iWrn = aFinder.WarningStatus();
1629   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1630   if (iWrn) {
1631     MESSAGE(" *** iWrn : " << iWrn);
1632   }
1633
1634   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1635
1636   if (listSS.Extent() < 1) {
1637     SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1638     return aSeqOfIDs;
1639   }
1640
1641   // Fill sequence of object IDs
1642   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1643
1644   TopTools_IndexedMapOfShape anIndices;
1645   TopExp::MapShapes(theShape, anIndices);
1646
1647   TopTools_ListIteratorOfListOfShape itSub (listSS);
1648   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1649     int id = anIndices.FindIndex(itSub.Value());
1650     aSeqOfIDs->Append(id);
1651   }
1652
1653   return aSeqOfIDs;
1654 }
1655
1656 //=======================================================================
1657 //function : getObjectsShapesOn
1658 /*!
1659  * \brief Find shape objects and their entries by their ids
1660  * \param theShapeIDs - incoming shape ids
1661  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1662  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
1663  */
1664 //=======================================================================
1665
1666 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
1667  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
1668                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
1669                     TCollection_AsciiString &                 theShapeEntries)
1670 {
1671   Handle(TColStd_HSequenceOfTransient) aSeq;
1672
1673   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
1674   {
1675     aSeq = new TColStd_HSequenceOfTransient;
1676     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1677     TCollection_AsciiString anEntry;
1678     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
1679     {
1680       anArray->SetValue(1, theShapeIDs->Value( i ));
1681       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
1682       aSeq->Append( anObj );
1683
1684       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1685       if ( i != 1 ) theShapeEntries += ",";
1686       theShapeEntries += anEntry;
1687     }
1688   }
1689   return aSeq;
1690 }
1691
1692 //=======================================================================
1693 //function : getShapesOnSurface
1694 /*!
1695    * \brief Find subshapes complying with given status about surface
1696     * \param theSurface - the surface to check state of subshapes against
1697     * \param theShape - the shape to explore
1698     * \param theShapeType - type of subshape of theShape
1699     * \param theState - required state
1700     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1701     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1702  */
1703 //=======================================================================
1704
1705 Handle(TColStd_HSequenceOfTransient)
1706     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
1707                                                    const Handle(GEOM_Object)&  theShape,
1708                                                    TopAbs_ShapeEnum            theShapeType,
1709                                                    GEOMAlgo_State              theState,
1710                                                    TCollection_AsciiString &   theShapeEntries)
1711 {
1712   // Find subshapes ids
1713   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1714     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
1715   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1716     return NULL;
1717
1718   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
1719 }
1720
1721 //=============================================================================
1722 /*!
1723  *  GetShapesOnPlane
1724  */
1725 //=============================================================================
1726 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
1727                                         (const Handle(GEOM_Object)& theShape,
1728                                          const Standard_Integer     theShapeType,
1729                                          const Handle(GEOM_Object)& theAx1,
1730                                          const GEOMAlgo_State       theState)
1731 {
1732   SetErrorCode(KO);
1733
1734   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1735
1736   TopoDS_Shape aShape = theShape->GetValue();
1737   TopoDS_Shape anAx1  = theAx1->GetValue();
1738
1739   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1740
1741   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1742   if ( !checkTypeShapesOn( theShapeType ))
1743     return NULL;
1744
1745   // Create plane
1746   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1747   if ( aPlane.IsNull() )
1748     return NULL;
1749
1750   // Find objects
1751   TCollection_AsciiString anAsciiList;
1752   Handle(TColStd_HSequenceOfTransient) aSeq;
1753   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1754   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1755     return NULL;
1756
1757   // Make a Python command
1758
1759   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1760   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1761
1762   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1763     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
1764       << aShapeType << ", " << theAx1 << ", " << theState << ")";
1765
1766   SetErrorCode(OK);
1767   return aSeq;
1768 }
1769
1770 //=============================================================================
1771 /*!
1772  *  GetShapesOnPlaneWithLocation
1773  */
1774 //=============================================================================
1775 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
1776                                         (const Handle(GEOM_Object)& theShape,
1777                                          const Standard_Integer     theShapeType,
1778                                          const Handle(GEOM_Object)& theAx1,
1779                                          const Handle(GEOM_Object)& thePnt,
1780                                          const GEOMAlgo_State       theState)
1781 {
1782   SetErrorCode(KO);
1783
1784   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
1785
1786   TopoDS_Shape aShape = theShape->GetValue();
1787   TopoDS_Shape anAx1  = theAx1->GetValue();
1788   TopoDS_Shape anPnt = thePnt->GetValue();
1789
1790   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
1791
1792   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1793   if ( !checkTypeShapesOn( theShapeType ))
1794     return NULL;
1795
1796   // Create plane
1797   if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
1798   TopoDS_Vertex V1, V2, V3;
1799   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1800   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1801
1802   if (V1.IsNull() || V2.IsNull()) {
1803     SetErrorCode("Bad edge given for the plane normal vector");
1804     return NULL;
1805   }
1806   V3 = TopoDS::Vertex(anPnt);
1807
1808   if(V3.IsNull()) {
1809     SetErrorCode("Bad vertex given for the plane location");
1810       return NULL;
1811   }
1812   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
1813   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
1814
1815   if (aVec.Magnitude() < Precision::Confusion()) {
1816      SetErrorCode("Vector with null magnitude given");
1817     return NULL;
1818   }
1819   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
1820
1821   if ( aPlane.IsNull() )
1822     return NULL;
1823
1824   // Find objects
1825   TCollection_AsciiString anAsciiList;
1826   Handle(TColStd_HSequenceOfTransient) aSeq;
1827   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1828   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1829     return NULL;
1830
1831   // Make a Python command
1832
1833   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1834   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1835
1836   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1837     << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
1838     << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
1839
1840   SetErrorCode(OK);
1841   return aSeq;
1842 }
1843
1844 //=============================================================================
1845 /*!
1846  *  GetShapesOnCylinder
1847  */
1848 //=============================================================================
1849 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
1850                                           (const Handle(GEOM_Object)& theShape,
1851                                            const Standard_Integer     theShapeType,
1852                                            const Handle(GEOM_Object)& theAxis,
1853                                            const Standard_Real        theRadius,
1854                                            const GEOMAlgo_State       theState)
1855 {
1856   SetErrorCode(KO);
1857
1858   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1859
1860   TopoDS_Shape aShape = theShape->GetValue();
1861   TopoDS_Shape anAxis = theAxis->GetValue();
1862
1863   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1864
1865   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1866   if ( !checkTypeShapesOn( aShapeType ))
1867     return NULL;
1868
1869   // Create a cylinder surface
1870   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1871   if ( aCylinder.IsNull() )
1872     return NULL;
1873
1874   // Find objects
1875   TCollection_AsciiString anAsciiList;
1876   Handle(TColStd_HSequenceOfTransient) aSeq;
1877   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
1878   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1879     return NULL;
1880
1881   // Make a Python command
1882
1883   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1884   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1885
1886   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1887     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
1888       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
1889
1890   SetErrorCode(OK);
1891   return aSeq;
1892 }
1893
1894 //=============================================================================
1895 /*!
1896  *  GetShapesOnSphere
1897  */
1898 //=============================================================================
1899 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
1900                                           (const Handle(GEOM_Object)& theShape,
1901                                            const Standard_Integer     theShapeType,
1902                                            const Handle(GEOM_Object)& theCenter,
1903                                            const Standard_Real        theRadius,
1904                                            const GEOMAlgo_State       theState)
1905 {
1906   SetErrorCode(KO);
1907
1908   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1909
1910   TopoDS_Shape aShape  = theShape->GetValue();
1911   TopoDS_Shape aCenter = theCenter->GetValue();
1912
1913   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1914
1915   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1916   if ( !checkTypeShapesOn( aShapeType ))
1917     return NULL;
1918
1919   // Center of the sphere
1920   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1921   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1922
1923   gp_Ax3 anAx3 (aLoc, gp::DZ());
1924   Handle(Geom_SphericalSurface) aSphere =
1925     new Geom_SphericalSurface(anAx3, theRadius);
1926
1927   // Find objects
1928   TCollection_AsciiString anAsciiList;
1929   Handle(TColStd_HSequenceOfTransient) aSeq;
1930   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
1931   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1932     return NULL;
1933
1934   // Make a Python command
1935
1936   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1937   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1938
1939   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1940     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
1941       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
1942
1943   SetErrorCode(OK);
1944   return aSeq;
1945 }
1946
1947 //=============================================================================
1948 /*!
1949  *  GetShapesOnPlaneIDs
1950  */
1951 //=============================================================================
1952 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
1953                                         (const Handle(GEOM_Object)& theShape,
1954                                          const Standard_Integer     theShapeType,
1955                                          const Handle(GEOM_Object)& theAx1,
1956                                          const GEOMAlgo_State       theState)
1957 {
1958   SetErrorCode(KO);
1959
1960   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1961
1962   TopoDS_Shape aShape = theShape->GetValue();
1963   TopoDS_Shape anAx1  = theAx1->GetValue();
1964
1965   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1966
1967   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1968   if ( !checkTypeShapesOn( aShapeType ))
1969     return NULL;
1970
1971   // Create plane
1972   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1973   if ( aPlane.IsNull() )
1974     return NULL;
1975
1976   // Find object IDs
1977   Handle(TColStd_HSequenceOfInteger) aSeq;
1978   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
1979
1980   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
1981   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
1982
1983   // Make a Python command
1984   GEOM::TPythonDump(aFunction, /*append=*/true)
1985     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
1986     << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
1987
1988   SetErrorCode(OK);
1989   return aSeq;
1990 }
1991
1992 //=============================================================================
1993 /*!
1994  *  GetShapesOnPlaneWithLocationIDs
1995  */
1996 //=============================================================================
1997 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
1998                                         (const Handle(GEOM_Object)& theShape,
1999                                          const Standard_Integer     theShapeType,
2000                                          const Handle(GEOM_Object)& theAx1,
2001                                          const Handle(GEOM_Object)& thePnt,
2002                                          const GEOMAlgo_State       theState)
2003 {
2004   SetErrorCode(KO);
2005
2006   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2007
2008   TopoDS_Shape aShape = theShape->GetValue();
2009   TopoDS_Shape anAx1  = theAx1->GetValue();
2010   TopoDS_Shape anPnt  = thePnt->GetValue();
2011
2012   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2013
2014   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2015   if ( !checkTypeShapesOn( aShapeType ))
2016     return NULL;
2017
2018   // Create plane
2019   if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
2020   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2021   TopoDS_Vertex V1, V2, V3;
2022   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2023   if (V1.IsNull() || V2.IsNull()) {
2024     SetErrorCode("Bad edge given for the plane normal vector");
2025     return NULL;
2026   }
2027   V3 = TopoDS::Vertex(anPnt);
2028   if(V3.IsNull()) {
2029     SetErrorCode("Bad vertex given for the plane location");
2030       return NULL;
2031   }
2032   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2033   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2034   if (aVec.Magnitude() < Precision::Confusion()) {
2035     SetErrorCode("Vector with null magnitude given");
2036     return NULL;
2037   }
2038
2039   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2040   if ( aPlane.IsNull() )
2041     return NULL;
2042
2043   // Find object IDs
2044   Handle(TColStd_HSequenceOfInteger) aSeq;
2045   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
2046
2047   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
2048   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
2049
2050   // Make a Python command
2051   GEOM::TPythonDump(aFunction, /*append=*/true)
2052     << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
2053     << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
2054
2055   SetErrorCode(OK);
2056   return aSeq;
2057 }
2058
2059 //=============================================================================
2060 /*!
2061  *  GetShapesOnCylinderIDs
2062  */
2063 //=============================================================================
2064 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
2065                                           (const Handle(GEOM_Object)& theShape,
2066                                            const Standard_Integer     theShapeType,
2067                                            const Handle(GEOM_Object)& theAxis,
2068                                            const Standard_Real        theRadius,
2069                                            const GEOMAlgo_State       theState)
2070 {
2071   SetErrorCode(KO);
2072
2073   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
2074
2075   TopoDS_Shape aShape = theShape->GetValue();
2076   TopoDS_Shape anAxis = theAxis->GetValue();
2077
2078   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
2079
2080   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2081   if ( !checkTypeShapesOn( aShapeType ))
2082     return NULL;
2083
2084   // Create a cylinder surface
2085   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
2086   if ( aCylinder.IsNull() )
2087     return NULL;
2088
2089   // Find object IDs
2090   Handle(TColStd_HSequenceOfInteger) aSeq;
2091   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
2092
2093   // The GetShapesOnCylinder() doesn't change object so no new function is required.
2094   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
2095
2096   // Make a Python command
2097   GEOM::TPythonDump(aFunction, /*append=*/true)
2098     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2099     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
2100     << theRadius << ", " << theState << ")";
2101
2102   SetErrorCode(OK);
2103   return aSeq;
2104 }
2105
2106 //=============================================================================
2107 /*!
2108  *  GetShapesOnSphereIDs
2109  */
2110 //=============================================================================
2111 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
2112                                           (const Handle(GEOM_Object)& theShape,
2113                                            const Standard_Integer     theShapeType,
2114                                            const Handle(GEOM_Object)& theCenter,
2115                                            const Standard_Real        theRadius,
2116                                            const GEOMAlgo_State       theState)
2117 {
2118   SetErrorCode(KO);
2119
2120   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
2121
2122   TopoDS_Shape aShape  = theShape->GetValue();
2123   TopoDS_Shape aCenter = theCenter->GetValue();
2124
2125   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
2126
2127   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2128   if ( !checkTypeShapesOn( aShapeType ))
2129     return NULL;
2130
2131   // Center of the sphere
2132   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
2133   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
2134
2135   gp_Ax3 anAx3 (aLoc, gp::DZ());
2136   Handle(Geom_SphericalSurface) aSphere =
2137     new Geom_SphericalSurface(anAx3, theRadius);
2138
2139   // Find object IDs
2140   Handle(TColStd_HSequenceOfInteger) aSeq;
2141   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
2142
2143   // The GetShapesOnSphere() doesn't change object so no new function is required.
2144   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
2145
2146   // Make a Python command
2147   GEOM::TPythonDump(aFunction, /*append=*/true)
2148     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
2149     << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
2150     << theRadius << ", " << theState << ")";
2151
2152   SetErrorCode(OK);
2153   return aSeq;
2154 }
2155
2156 //=======================================================================
2157 //function : getShapesOnQuadrangleIDs
2158   /*!
2159    * \brief Find IDs of subshapes complying with given status about quadrangle
2160     * \param theShape - the shape to explore
2161     * \param theShapeType - type of subshape of theShape
2162     * \param theTopLeftPoint - top left quadrangle corner
2163     * \param theTopRigthPoint - top right quadrangle corner
2164     * \param theBottomLeftPoint - bottom left quadrangle corner
2165     * \param theBottomRigthPoint - bottom right quadrangle corner
2166     * \param theState - required state
2167     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2168    */
2169 //=======================================================================
2170
2171 Handle(TColStd_HSequenceOfInteger)
2172   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2173                                                         const Standard_Integer     theShapeType,
2174                                                         const Handle(GEOM_Object)& theTopLeftPoint,
2175                                                         const Handle(GEOM_Object)& theTopRigthPoint,
2176                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
2177                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
2178                                                         const GEOMAlgo_State       theState)
2179 {
2180   SetErrorCode(KO);
2181
2182   if ( theShape.IsNull() ||
2183        theTopLeftPoint.IsNull() ||
2184        theTopRigthPoint.IsNull() ||
2185        theBottomLeftPoint.IsNull() ||
2186        theBottomRigthPoint.IsNull() )
2187     return NULL;
2188
2189   TopoDS_Shape aShape = theShape->GetValue();
2190   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
2191   TopoDS_Shape aTR = theTopRigthPoint->GetValue();
2192   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
2193   TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
2194
2195   if (aShape.IsNull() ||
2196       aTL.IsNull() ||
2197       aTR.IsNull() ||
2198       aBL.IsNull() ||
2199       aBR.IsNull() ||
2200       aTL.ShapeType() != TopAbs_VERTEX ||
2201       aTR.ShapeType() != TopAbs_VERTEX ||
2202       aBL.ShapeType() != TopAbs_VERTEX ||
2203       aBR.ShapeType() != TopAbs_VERTEX )
2204     return NULL;
2205
2206   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2207   if ( !checkTypeShapesOn( aShapeType ))
2208     return NULL;
2209
2210   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2211
2212   // Check presence of triangulation, build if need
2213   if (!CheckTriangulation(aShape)) {
2214     SetErrorCode("Cannot build triangulation on the shape");
2215     return aSeqOfIDs;
2216   }
2217
2218   // Call algo
2219   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
2220   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
2221   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
2222   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
2223
2224   GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
2225   Standard_Real aTol = 0.0001; // default value
2226
2227   aFinder.SetShape(aShape);
2228   aFinder.SetTolerance(aTol);
2229   //aFinder.SetSurface(theSurface);
2230   aFinder.SetShapeType(aShapeType);
2231   aFinder.SetState(theState);
2232
2233   // Sets the minimal number of inner points for the faces that do not have own
2234   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
2235   // Default value=3
2236   aFinder.SetNbPntsMin(3);
2237   // Sets the maximal number of inner points for edges or faces.
2238   // It is usefull for the cases when this number is very big (e.g =2000) to improve
2239   // the performance. If this value =0, all inner points will be taken into account.
2240   // Default value=0
2241   aFinder.SetNbPntsMax(100);
2242
2243   aFinder.Perform();
2244
2245   // Interprete results
2246   Standard_Integer iErr = aFinder.ErrorStatus();
2247   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2248   if (iErr) {
2249     MESSAGE(" iErr : " << iErr);
2250     TCollection_AsciiString aMsg (" iErr : ");
2251     aMsg += TCollection_AsciiString(iErr);
2252     SetErrorCode(aMsg);
2253     return aSeqOfIDs;
2254   }
2255   Standard_Integer iWrn = aFinder.WarningStatus();
2256   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2257   if (iWrn) {
2258     MESSAGE(" *** iWrn : " << iWrn);
2259   }
2260
2261   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2262
2263   if (listSS.Extent() < 1) {
2264     SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2265     return aSeqOfIDs;
2266   }
2267
2268   // Fill sequence of object IDs
2269   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2270
2271   TopTools_IndexedMapOfShape anIndices;
2272   TopExp::MapShapes(aShape, anIndices);
2273
2274   TopTools_ListIteratorOfListOfShape itSub (listSS);
2275   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2276     int id = anIndices.FindIndex(itSub.Value());
2277     aSeqOfIDs->Append(id);
2278   }
2279   return aSeqOfIDs;
2280 }
2281
2282 //=======================================================================
2283 //function : GetShapesOnQuadrangle
2284   /*!
2285    * \brief Find subshapes complying with given status about quadrangle
2286     * \param theShape - the shape to explore
2287     * \param theShapeType - type of subshape of theShape
2288     * \param theTopLeftPoint - top left quadrangle corner
2289     * \param theTopRigthPoint - top right quadrangle corner
2290     * \param theBottomLeftPoint - bottom left quadrangle corner
2291     * \param theBottomRigthPoint - bottom right quadrangle corner
2292     * \param theState - required state
2293     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2294    */
2295 //=======================================================================
2296
2297 Handle(TColStd_HSequenceOfTransient)
2298     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
2299                                                        const Standard_Integer     theShapeType,
2300                                                        const Handle(GEOM_Object)& theTopLeftPoint,
2301                                                        const Handle(GEOM_Object)& theTopRigthPoint,
2302                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
2303                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
2304                                                        const GEOMAlgo_State       theState)
2305 {
2306   // Find indices
2307   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2308     getShapesOnQuadrangleIDs( theShape,
2309                               theShapeType,
2310                               theTopLeftPoint,
2311                               theTopRigthPoint,
2312                               theBottomLeftPoint,
2313                               theBottomRigthPoint,
2314                               theState);
2315   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2316     return NULL;
2317
2318   // Find objects by indices
2319   TCollection_AsciiString anAsciiList;
2320   Handle(TColStd_HSequenceOfTransient) aSeq;
2321   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2322   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2323     return NULL;
2324
2325   // Make a Python command
2326
2327   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2328   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2329
2330   GEOM::TPythonDump(aFunction)
2331     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
2332     << theShape << ", "
2333     << TopAbs_ShapeEnum(theShapeType) << ", "
2334     << theTopLeftPoint << ", "
2335     << theTopRigthPoint << ", "
2336     << theBottomLeftPoint << ", "
2337     << theBottomRigthPoint << ", "
2338     << theState << ")";
2339
2340   SetErrorCode(OK);
2341   return aSeq;
2342 }
2343
2344 //=======================================================================
2345 //function : GetShapesOnQuadrangleIDs
2346   /*!
2347    * \brief Find IDs of subshapes complying with given status about quadrangle
2348     * \param theShape - the shape to explore
2349     * \param theShapeType - type of subshape of theShape
2350     * \param theTopLeftPoint - top left quadrangle corner
2351     * \param theTopRigthPoint - top right quadrangle corner
2352     * \param theBottomLeftPoint - bottom left quadrangle corner
2353     * \param theBottomRigthPoint - bottom right quadrangle corner
2354     * \param theState - required state
2355     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2356    */
2357 //=======================================================================
2358
2359 Handle(TColStd_HSequenceOfInteger)
2360   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2361                                                         const Standard_Integer     theShapeType,
2362                                                         const Handle(GEOM_Object)& theTopLeftPoint,
2363                                                         const Handle(GEOM_Object)& theTopRigthPoint,
2364                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
2365                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
2366                                                         const GEOMAlgo_State       theState)
2367 {
2368   // Find indices
2369   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2370     getShapesOnQuadrangleIDs( theShape,
2371                               theShapeType,
2372                               theTopLeftPoint,
2373                               theTopRigthPoint,
2374                               theBottomLeftPoint,
2375                               theBottomRigthPoint,
2376                               theState);
2377   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2378     return NULL;
2379
2380   // Make a Python command
2381
2382   // The GetShapesOnCylinder() doesn't change object so no new function is required.
2383   Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
2384   lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
2385   lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
2386   lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
2387   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
2388
2389   GEOM::TPythonDump(aFunction, /*append=*/true)
2390     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
2391     << theShape << ", "
2392     << TopAbs_ShapeEnum(theShapeType) << ", "
2393     << theTopLeftPoint << ", "
2394     << theTopRigthPoint << ", "
2395     << theBottomLeftPoint << ", "
2396     << theBottomRigthPoint << ", "
2397     << theState << ")";
2398
2399   SetErrorCode(OK);
2400   return aSeqOfIDs;
2401 }
2402
2403
2404 //=============================================================================
2405 /*!
2406  *  GetInPlace
2407  */
2408 //=============================================================================
2409 static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
2410                                const TopTools_IndexedMapOfShape& theWhereIndices,
2411                                const TopoDS_Shape& theWhat,
2412                                TColStd_ListOfInteger& theModifiedList)
2413 {
2414   if (theWhereFunction.IsNull() || theWhat.IsNull()) return false;
2415
2416   if (theWhereIndices.Contains(theWhat)) {
2417     // entity was not changed by the operation
2418     Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
2419     theModifiedList.Append(aWhatIndex);
2420     return true;
2421   }
2422
2423   // try to find in history
2424   TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
2425
2426   // search in history for all argument shapes
2427   Standard_Boolean isFound = Standard_False;
2428   Standard_Boolean isGood = Standard_False;
2429
2430   TDF_LabelSequence aLabelSeq;
2431   theWhereFunction->GetDependency(aLabelSeq);
2432   Standard_Integer nbArg = aLabelSeq.Length();
2433
2434   for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
2435
2436     TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
2437
2438     Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
2439     TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
2440
2441     TopTools_IndexedMapOfShape anArgumentIndices;
2442     TopExp::MapShapes(anArgumentShape, anArgumentIndices);
2443
2444     if (anArgumentIndices.Contains(theWhat)) {
2445       isFound = Standard_True;
2446       Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
2447
2448       // Find corresponding label in history
2449       TDF_Label anArgumentHistoryLabel =
2450         theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
2451       if (anArgumentHistoryLabel.IsNull()) {
2452         // Lost History of operation argument. Possibly, all its entities was removed.
2453         isGood = Standard_True;
2454       }
2455       else {
2456         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
2457
2458         if (aWhatHistoryLabel.IsNull()) {
2459           // Removed entity ? Compound ? Compsolid ? Shell ? Wire
2460           isGood = Standard_False;
2461         } else {
2462           Handle(TDataStd_IntegerArray) anIntegerArray;
2463           if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2464             //Error: Empty modifications history for the sought shape.
2465             isGood = Standard_False;
2466           }
2467           else {
2468             isGood = Standard_True;
2469             Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
2470             for (imod = 1; imod <= aModifLen; imod++) {
2471               theModifiedList.Append(anIntegerArray->Array()->Value(imod));
2472             }
2473           }
2474         }
2475       }
2476     }
2477   }
2478
2479   isFound = isGood;
2480
2481   if (!isFound) {
2482     // try compound/compsolid/shell/wire element by element
2483     bool isFoundAny = false;
2484     TopTools_MapOfShape mapShape;
2485
2486     if (theWhat.ShapeType() == TopAbs_COMPOUND ||
2487         theWhat.ShapeType() == TopAbs_COMPSOLID) {
2488       // recursive processing of compound/compsolid
2489       TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
2490       for (; anIt.More(); anIt.Next()) {
2491         if (mapShape.Add(anIt.Value())) {
2492           TopoDS_Shape curWhat = anIt.Value();
2493           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2494           if (isFoundAny) isFound = Standard_True;
2495         }
2496       }
2497     }
2498     else if (theWhat.ShapeType() == TopAbs_SHELL) {
2499       // try to replace a shell by its faces images
2500       TopExp_Explorer anExp (theWhat, TopAbs_FACE);
2501       for (; anExp.More(); anExp.Next()) {
2502         if (mapShape.Add(anExp.Current())) {
2503           TopoDS_Shape curWhat = anExp.Current();
2504           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2505           if (isFoundAny) isFound = Standard_True;
2506         }
2507       }
2508     }
2509     else if (theWhat.ShapeType() == TopAbs_WIRE) {
2510       // try to replace a wire by its edges images
2511       TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
2512       for (; anExp.More(); anExp.Next()) {
2513         if (mapShape.Add(anExp.Current())) {
2514           TopoDS_Shape curWhat = anExp.Current();
2515           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2516           if (isFoundAny) isFound = Standard_True;
2517         }
2518       }
2519     }
2520     else {
2521       // Removed entity
2522     }
2523   }
2524
2525   return isFound;
2526 }
2527
2528 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
2529                                           (Handle(GEOM_Object) theShapeWhere,
2530                                            Handle(GEOM_Object) theShapeWhat)
2531 {
2532   SetErrorCode(KO);
2533
2534   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2535
2536   TopoDS_Shape aWhere = theShapeWhere->GetValue();
2537   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
2538
2539   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
2540
2541   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
2542   if (aWhereFunction.IsNull()) return NULL;
2543
2544   //Fill array of indices
2545   TopTools_IndexedMapOfShape aWhereIndices;
2546   TopExp::MapShapes(aWhere, aWhereIndices);
2547
2548   // process shape
2549   TColStd_ListOfInteger aModifiedList;
2550   bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
2551
2552   if (!isFound || aModifiedList.Extent() < 1) {
2553     SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
2554     return NULL;
2555   }
2556
2557   Handle(TColStd_HArray1OfInteger) aModifiedArray =
2558     new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
2559   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
2560   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
2561     aModifiedArray->SetValue(imod, anIterModif.Value());
2562   }
2563
2564   //Add a new object
2565   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
2566   if (aResult.IsNull()) {
2567     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2568     return NULL;
2569   }
2570
2571   if (aModifiedArray->Length() > 1) {
2572     //Set a GROUP type
2573     aResult->SetType(GEOM_GROUP);
2574
2575     //Set a sub shape type
2576     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
2577     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
2578
2579     TDF_Label aFreeLabel = aResult->GetFreeLabel();
2580     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
2581   }
2582
2583   //Make a Python command
2584   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
2585
2586   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
2587     << theShapeWhere << ", " << theShapeWhat << ")";
2588
2589   SetErrorCode(OK);
2590   return aResult;
2591 }
2592
2593 //=======================================================================
2594 //function : SortShapes
2595 //purpose  :
2596 //=======================================================================
2597 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
2598 {
2599   Standard_Integer MaxShapes = SL.Extent();
2600   TopTools_Array1OfShape  aShapes (1,MaxShapes);
2601   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
2602   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
2603   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
2604
2605   // Computing of CentreOfMass
2606   Standard_Integer Index;
2607   GProp_GProps GPr;
2608   gp_Pnt GPoint;
2609   TopTools_ListIteratorOfListOfShape it(SL);
2610   for (Index=1;  it.More();  Index++)
2611   {
2612     TopoDS_Shape S = it.Value();
2613     SL.Remove( it ); // == it.Next()
2614     aShapes(Index) = S;
2615     OrderInd.SetValue (Index, Index);
2616     if (S.ShapeType() == TopAbs_VERTEX)
2617     {
2618       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
2619       Length.SetValue( Index, (Standard_Real) S.Orientation());
2620     }
2621     else
2622     {
2623       BRepGProp::LinearProperties (S, GPr);
2624       GPoint = GPr.CentreOfMass();
2625       Length.SetValue( Index, GPr.Mass() );
2626     }
2627     MidXYZ.SetValue(Index,
2628                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
2629   }
2630
2631   // Sorting
2632   Standard_Integer aTemp;
2633   Standard_Boolean exchange, Sort = Standard_True;
2634   while (Sort)
2635   {
2636     Sort = Standard_False;
2637     for (Index=1; Index < MaxShapes; Index++)
2638     {
2639       if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
2640         exchange = Standard_True;
2641       else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
2642                Length(OrderInd(Index)) >  Length(OrderInd(Index+1)) )
2643         exchange = Standard_True;
2644       else
2645         exchange = Standard_False;
2646       if (exchange)
2647       {
2648         aTemp = OrderInd(Index);
2649         OrderInd(Index) = OrderInd(Index+1);
2650         OrderInd(Index+1) = aTemp;
2651         Sort = Standard_True;
2652       }
2653     }
2654   }
2655   for (Index=1; Index <= MaxShapes; Index++)
2656     SL.Append( aShapes( OrderInd(Index) ));
2657 }
2658
2659 //=======================================================================
2660 //function : CompsolidToCompound
2661 //purpose  :
2662 //=======================================================================
2663 TopoDS_Shape GEOMImpl_IShapesOperations::CompsolidToCompound (const TopoDS_Shape& theCompsolid)
2664 {
2665   if (theCompsolid.ShapeType() != TopAbs_COMPSOLID) {
2666     return theCompsolid;
2667   }
2668
2669   TopoDS_Compound aCompound;
2670   BRep_Builder B;
2671   B.MakeCompound(aCompound);
2672
2673   TopTools_MapOfShape mapShape;
2674   TopoDS_Iterator It (theCompsolid, Standard_True, Standard_True);
2675
2676   for (; It.More(); It.Next()) {
2677     TopoDS_Shape aShape_i = It.Value();
2678     if (mapShape.Add(aShape_i)) {
2679       B.Add(aCompound, aShape_i);
2680     }
2681   }
2682
2683   return aCompound;
2684 }
2685
2686 //=======================================================================
2687 //function : CheckTriangulation
2688 //purpose  :
2689 //=======================================================================
2690 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
2691 {
2692   bool isTriangulation = true;
2693
2694   TopExp_Explorer exp (aShape, TopAbs_FACE);
2695   if (exp.More())
2696   {
2697     TopLoc_Location aTopLoc;
2698     Handle(Poly_Triangulation) aTRF;
2699     aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
2700     if (aTRF.IsNull()) {
2701       isTriangulation = false;
2702     }
2703   }
2704   else // no faces, try edges
2705   {
2706     TopExp_Explorer expe (aShape, TopAbs_EDGE);
2707     if (!expe.More()) {
2708       return false;
2709     }
2710     TopLoc_Location aLoc;
2711     Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
2712     if (aPE.IsNull()) {
2713       isTriangulation = false;
2714     }
2715   }
2716
2717   if (!isTriangulation) {
2718     // calculate deflection
2719     Standard_Real aDeviationCoefficient = 0.001;
2720
2721     Bnd_Box B;
2722     BRepBndLib::Add(aShape, B);
2723     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
2724     B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
2725
2726     Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
2727     Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
2728     Standard_Real aHLRAngle = 0.349066;
2729
2730     BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
2731   }
2732
2733   return true;
2734 }
2735
2736 #define MAX_TOLERANCE 1.e-7
2737
2738
2739 //=======================================================================
2740 //function : isSameEdge
2741 //purpose  : Returns True if two edges coincide
2742 //=======================================================================
2743 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
2744 {
2745   TopoDS_Vertex V11, V12, V21, V22;
2746   TopExp::Vertices(theEdge1, V11, V12);
2747   TopExp::Vertices(theEdge2, V21, V22);
2748   gp_Pnt P11 = BRep_Tool::Pnt(V11);
2749   gp_Pnt P12 = BRep_Tool::Pnt(V12);
2750   gp_Pnt P21 = BRep_Tool::Pnt(V21);
2751   gp_Pnt P22 = BRep_Tool::Pnt(V22);
2752   bool coincide = false;
2753
2754   //Check that ends of edges coincide
2755   if(P11.Distance(P21) <= MAX_TOLERANCE) {
2756     if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
2757   }
2758   else if(P11.Distance(P22) <= MAX_TOLERANCE) {
2759     if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
2760   }
2761
2762   if(!coincide) return false;
2763
2764   double U11, U12, U21, U22;
2765   Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
2766   Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
2767   if(C1->DynamicType() == C2->DynamicType()) return true;
2768
2769   //Check that both edges has the same geometry
2770   double range = U12-U11;
2771   double U = U11+ range/3.0;
2772   gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
2773   U = U11+range*2.0/3.0;
2774   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
2775
2776   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
2777     return false;
2778
2779   if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
2780
2781   if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
2782     return false;
2783
2784   if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
2785
2786   return true;
2787 }
2788
2789 #include <TopoDS_TShape.hxx>
2790 //=======================================================================
2791 //function : isSameFace
2792 //purpose  : Returns True if two faces coincide
2793 //=======================================================================
2794 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
2795 {
2796   TopExp_Explorer E(theFace1, TopAbs_EDGE);
2797   TopTools_ListOfShape LS1, LS2;
2798   for(; E.More(); E.Next()) LS1.Append(E.Current());
2799
2800   E.Init(theFace2, TopAbs_EDGE);
2801   for(; E.More(); E.Next()) LS2.Append(E.Current());
2802
2803   //Compare the number of edges in the faces
2804   if(LS1.Extent() != LS2.Extent()) return false;
2805
2806   double aMin = RealFirst(), aMax = RealLast();
2807   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
2808   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
2809
2810   for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
2811     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2812     if(P.X() < xminB1) xminB1 = P.X();
2813     if(P.Y() < yminB1) yminB1 = P.Y();
2814     if(P.Z() < zminB1) zminB1 = P.Z();
2815     if(P.X() > xmaxB1) xmaxB1 = P.X();
2816     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
2817     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
2818   }
2819
2820   for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
2821     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2822     if(P.X() < xminB2) xminB2 = P.X();
2823     if(P.Y() < yminB2) yminB2 = P.Y();
2824     if(P.Z() < zminB2) zminB2 = P.Z();
2825     if(P.X() > xmaxB2) xmaxB2 = P.X();
2826     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
2827     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
2828   }
2829
2830   //Compare the bounding boxes of both faces
2831   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
2832     return false;
2833
2834   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
2835     return false;
2836
2837   //Check that each edge of the Face1 has a counterpart in the Face2
2838   TopTools_MapOfOrientedShape aMap;
2839   TopTools_ListIteratorOfListOfShape LSI1(LS1);
2840   for(; LSI1.More(); LSI1.Next()) {
2841     TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
2842     bool isFound = false;
2843     TopTools_ListIteratorOfListOfShape LSI2(LS2);
2844     for(; LSI2.More(); LSI2.Next()) {
2845       TopoDS_Shape aValue = LSI2.Value();
2846       if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
2847       if(isSameEdge(E, TopoDS::Edge(aValue))) {
2848         aMap.Add(aValue);
2849         isFound = true;
2850         break;
2851       }
2852     }
2853     if(!isFound) return false;
2854   }
2855
2856   Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
2857   Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
2858   if(S1->DynamicType() == S2->DynamicType()) {
2859     return true;
2860   }
2861   else {   //Check if there a coincidence of two surfaces at least in two points
2862     double U11, U12, V11, V12, U21, U22, V21, V22;
2863     BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
2864     BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
2865
2866     double rangeU = U12-U11;
2867     double rangeV = V12-V11;
2868     double U = U11 + rangeU/3.0;
2869     double V = V11 + rangeV/3.0;
2870     gp_Pnt P1 = S1->Value(U, V);
2871     U = U11+rangeU*2.0/3.0;
2872     V = V11+rangeV*2.0/3.0;
2873     gp_Pnt P2 = S1->Value(U, V);
2874
2875     if(!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
2876       return false;
2877
2878     if(P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
2879
2880     if(!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
2881       return false;
2882
2883     if(P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
2884   }
2885
2886   return true;
2887 }
2888
2889 //=======================================================================
2890 //function : isSameSolid
2891 //purpose  : Returns True if two solids coincide
2892 //=======================================================================
2893 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
2894 {
2895   TopExp_Explorer E(theSolid1, TopAbs_FACE);
2896   TopTools_ListOfShape LS1, LS2;
2897   for(; E.More(); E.Next()) LS1.Append(E.Current());
2898   E.Init(theSolid2, TopAbs_FACE);
2899   for(; E.More(); E.Next()) LS2.Append(E.Current());
2900
2901   if(LS1.Extent() != LS2.Extent()) return false;
2902
2903   double aMin = RealFirst(), aMax = RealLast();
2904   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
2905   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
2906
2907   for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
2908     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2909     if(P.X() < xminB1) xminB1 = P.X();
2910     if(P.Y() < yminB1) yminB1 = P.Y();
2911     if(P.Z() < zminB1) zminB1 = P.Z();
2912     if(P.X() > xmaxB1) xmaxB1 = P.X();
2913     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
2914     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
2915   }
2916
2917   for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
2918     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2919     if(P.X() < xminB2) xminB2 = P.X();
2920     if(P.Y() < yminB2) yminB2 = P.Y();
2921     if(P.Z() < zminB2) zminB2 = P.Z();
2922     if(P.X() > xmaxB2) xmaxB2 = P.X();
2923     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
2924     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
2925   }
2926
2927   //Compare the bounding boxes of both solids
2928   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
2929     return false;
2930
2931   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
2932     return false;
2933
2934   //Check that each face of the Solid1 has a counterpart in the Solid2
2935   TopTools_MapOfOrientedShape aMap;
2936   TopTools_ListIteratorOfListOfShape LSI1(LS1);
2937   for(; LSI1.More(); LSI1.Next()) {
2938     TopoDS_Face F = TopoDS::Face(LSI1.Value());
2939     bool isFound = false;
2940     TopTools_ListIteratorOfListOfShape LSI2(LS2);
2941     for(; LSI2.More(); LSI2.Next()) {
2942       if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
2943       if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
2944         aMap.Add(LSI2.Value());
2945         isFound = true;
2946         break;
2947       }
2948     }
2949     if(!isFound) return false;
2950   }
2951
2952   return true;
2953 }
2954
2955 //=======================================================================
2956 //function : GetSame
2957 //purpose  :
2958 //=======================================================================
2959 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
2960                                                         const Handle(GEOM_Object)& theShapeWhat)
2961 {
2962   SetErrorCode(KO);
2963   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2964
2965   TopoDS_Shape aWhere = theShapeWhere->GetValue();
2966   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
2967
2968   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
2969
2970   int anIndex = -1;
2971   bool isFound = false;
2972   TopoDS_Shape aSubShape;
2973   TopTools_MapOfShape aMap;
2974
2975   switch(aWhat.ShapeType()) {
2976     case TopAbs_VERTEX: {
2977       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
2978       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
2979       for(; E.More(); E.Next()) {
2980         if(!aMap.Add(E.Current())) continue;
2981         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2982         if(P.Distance(P2) <= MAX_TOLERANCE) {
2983           isFound = true;
2984           aSubShape = E.Current();
2985           break;
2986         }
2987       }
2988       break;
2989                         }
2990     case TopAbs_FACE: {
2991       TopoDS_Face aFace = TopoDS::Face(aWhat);
2992       TopExp_Explorer E(aWhere, TopAbs_FACE);
2993       for(; E.More(); E.Next()) {
2994         if(!aMap.Add(E.Current())) continue;
2995         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
2996           aSubShape = E.Current();
2997           isFound = true;
2998           break;
2999         }
3000       }
3001       break;
3002                       }
3003     case TopAbs_EDGE: {
3004       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
3005       TopExp_Explorer E(aWhere, TopAbs_EDGE);
3006       for(; E.More(); E.Next()) {
3007         if(!aMap.Add(E.Current())) continue;
3008         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
3009           aSubShape = E.Current();
3010           isFound = true;
3011           break;
3012         }
3013       }
3014       break;
3015                       }
3016     case TopAbs_SOLID: {
3017       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
3018       TopExp_Explorer E(aWhere, TopAbs_SOLID);
3019       for(; E.More(); E.Next()) {
3020         if(!aMap.Add(E.Current())) continue;
3021         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
3022           aSubShape = E.Current();
3023           isFound = true;
3024           break;
3025         }
3026       }
3027       break;
3028                        }
3029     default:
3030       return NULL;
3031   }
3032
3033   if(isFound) {
3034     TopTools_IndexedMapOfShape anIndices;
3035     TopExp::MapShapes(aWhere, anIndices);
3036     if (anIndices.Contains(aSubShape))
3037       anIndex = anIndices.FindIndex(aSubShape);
3038   }
3039
3040   if(anIndex < 0) return NULL;
3041
3042   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3043
3044   anArray->SetValue(1, anIndex);
3045
3046   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
3047   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
3048
3049   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
3050     << theShapeWhere << ", " << theShapeWhat << ")";
3051
3052   SetErrorCode(OK);
3053
3054   return aResult;
3055 }