Salome HOME
0022758: [EDF] Creation of a face from a surface and limiting edges
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File      : GEOMImpl_IShapesOperations.cxx
24 //  Created   :
25 //  Author    : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
26 //  Project   : SALOME
27
28 #include <Standard_Stream.hxx>
29
30 #include "GEOMImpl_IShapesOperations.hxx"
31
32 #include "GEOMImpl_Types.hxx"
33
34 #include "GEOMImpl_VectorDriver.hxx"
35 #include "GEOMImpl_ShapeDriver.hxx"
36 #include "GEOMImpl_GlueDriver.hxx"
37
38 #include "GEOMImpl_IVector.hxx"
39 #include "GEOMImpl_IShapes.hxx"
40 #include "GEOMImpl_IGlue.hxx"
41
42 #include "GEOMImpl_Block6Explorer.hxx"
43 #include "GEOMImpl_IHealingOperations.hxx"
44
45 #include "GEOMImpl_Gen.hxx"
46
47 #include "GEOM_Function.hxx"
48 #include "GEOM_ISubShape.hxx"
49 #include "GEOM_PythonDump.hxx"
50
51 #include "GEOMUtils.hxx"
52
53 #include "GEOMAlgo_ClsfBox.hxx"
54 #include "GEOMAlgo_ClsfSolid.hxx"
55 #include "GEOMAlgo_CoupleOfShapes.hxx"
56 #include "GEOMAlgo_FinderShapeOn1.hxx"
57 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
58 #include "GEOMAlgo_FinderShapeOn2.hxx"
59 #include "GEOMAlgo_GetInPlace.hxx"
60 #include "GEOMAlgo_GlueDetector.hxx"
61 #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx"
62 #include "GEOMAlgo_ListOfCoupleOfShapes.hxx"
63
64 #include <Basics_OCCTVersion.hxx>
65
66 #include <utilities.h>
67 #include <OpUtil.hxx>
68 #include <Utils_ExceptHandlers.hxx>
69
70 #include <BRepAdaptor_Curve.hxx>
71 #include <BRepAdaptor_Surface.hxx>
72 #include <BRepBndLib.hxx>
73 #include <BRepBuilderAPI_MakeVertex.hxx>
74 #include <BRepClass3d_SolidClassifier.hxx>
75 #include <BRepClass_FaceClassifier.hxx>
76 #include <BRepExtrema_DistShapeShape.hxx>
77 #include <BRepExtrema_ExtCF.hxx>
78 #include <BRepGProp.hxx>
79 #include <BRepMesh_IncrementalMesh.hxx>
80 #include <BRepTools.hxx>
81 #include <BRep_Builder.hxx>
82 #include <BRep_Tool.hxx>
83 #include <Bnd_Box.hxx>
84 #include <GEOMImpl_IMeasure.hxx>
85 #include <GEOMImpl_MeasureDriver.hxx>
86 #include <GProp_GProps.hxx>
87 #include <Geom2d_Curve.hxx>
88 #include <GeomAdaptor_Surface.hxx>
89 #include <GeomLib_Tool.hxx>
90 #include <Geom_CylindricalSurface.hxx>
91 #include <Geom_Plane.hxx>
92 #include <Geom_SphericalSurface.hxx>
93 #include <Geom_Surface.hxx>
94 #include <Precision.hxx>
95 #include <TColStd_Array1OfReal.hxx>
96 #include <TColStd_HArray1OfInteger.hxx>
97 #include <TColStd_ListIteratorOfListOfInteger.hxx>
98 #include <TColStd_ListOfInteger.hxx>
99 #include <TDF_Tool.hxx>
100 #include <TDataStd_Integer.hxx>
101 #include <TDataStd_IntegerArray.hxx>
102 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
103 #include <TFunction_Driver.hxx>
104 #include <TFunction_DriverTable.hxx>
105 #include <TFunction_Logbook.hxx>
106 #include <TopAbs.hxx>
107 #include <TopExp.hxx>
108 #include <TopExp_Explorer.hxx>
109 #include <TopLoc_Location.hxx>
110 #include <TopTools_Array1OfShape.hxx>
111 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
112 #include <TopTools_IndexedMapOfShape.hxx>
113 #include <TopTools_ListIteratorOfListOfShape.hxx>
114 #include <TopTools_MapOfOrientedShape.hxx>
115 #include <TopTools_MapOfShape.hxx>
116 #include <TopTools_SequenceOfShape.hxx>
117 #include <TopoDS.hxx>
118 #include <TopoDS_Compound.hxx>
119 #include <TopoDS_Edge.hxx>
120 #include <TopoDS_Face.hxx>
121 #include <TopoDS_Iterator.hxx>
122 #include <TopoDS_Shape.hxx>
123 #include <TopoDS_Solid.hxx>
124 #include <TopoDS_Vertex.hxx>
125 #include <gp_Cylinder.hxx>
126 #include <gp_Lin.hxx>
127 #include <gp_Pnt.hxx>
128
129 #include <vector>
130 #include <algorithm>
131 #include <functional>
132
133 #include <Standard_NullObject.hxx>
134 #include <Standard_Failure.hxx>
135 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
136
137
138 //=============================================================================
139 /*!
140  *   constructor:
141  */
142 //=============================================================================
143 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
144 : GEOM_IOperations(theEngine, theDocID)
145 {
146   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
147 }
148
149 //=============================================================================
150 /*!
151  *  destructor
152  */
153 //=============================================================================
154 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
155 {
156   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
157 }
158
159 //=============================================================================
160 /*!
161  *  MakeEdge
162  */
163 //=============================================================================
164 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
165                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
166 {
167   SetErrorCode(KO);
168
169   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
170
171   //Add a new Edge object
172   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
173
174   //Add a new Vector function
175   Handle(GEOM_Function) aFunction =
176     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
177
178   //Check if the function is set correctly
179   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
180
181   GEOMImpl_IVector aPI (aFunction);
182
183   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
184   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
185   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
186
187   aPI.SetPoint1(aRef1);
188   aPI.SetPoint2(aRef2);
189
190   //Compute the Edge value
191   try {
192     OCC_CATCH_SIGNALS;
193     if (!GetSolver()->ComputeFunction(aFunction)) {
194       SetErrorCode("Vector driver failed");
195       return NULL;
196     }
197   }
198   catch (Standard_Failure) {
199     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
200     SetErrorCode(aFail->GetMessageString());
201     return NULL;
202   }
203
204   //Make a Python command
205   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
206                                << thePnt1 << ", " << thePnt2 << ")";
207
208   SetErrorCode(OK);
209   return anEdge;
210 }
211
212 //=============================================================================
213 /*!
214  *  MakeEdgeOnCurveByLength
215  */
216 //=============================================================================
217 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeOnCurveByLength
218                      (Handle(GEOM_Object) theRefCurve,
219                       const Standard_Real theLength,
220                       Handle(GEOM_Object) theStartPoint)
221 {
222   SetErrorCode(KO);
223
224   if (theRefCurve.IsNull()) return NULL;
225
226   //Add a new Edge object
227   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
228
229   //Add a new Vector function
230   Handle(GEOM_Function) aFunction =
231     anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_CURVE_LENGTH);
232
233   //Check if the function is set correctly
234   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
235
236   GEOMImpl_IVector aPI (aFunction);
237
238   Handle(GEOM_Function) aRef1 = theRefCurve->GetLastFunction();
239   if (aRef1.IsNull()) return NULL;
240   aPI.SetPoint1(aRef1);
241
242   if (!theStartPoint.IsNull()) {
243     Handle(GEOM_Function) aRef2 = theStartPoint->GetLastFunction();
244     aPI.SetPoint2(aRef2);
245   }
246
247   aPI.SetParameter(theLength);
248
249   //Compute the Edge value
250   try {
251     OCC_CATCH_SIGNALS;
252     if (!GetSolver()->ComputeFunction(aFunction)) {
253       SetErrorCode("Vector driver failed");
254       return NULL;
255     }
256   }
257   catch (Standard_Failure) {
258     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
259     SetErrorCode(aFail->GetMessageString());
260     return NULL;
261   }
262
263   //Make a Python command
264   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeOnCurveByLength("
265                                << theRefCurve << ", " << theLength << ", " << theStartPoint << ")";
266
267   SetErrorCode(OK);
268   return anEdge;
269 }
270
271 //=============================================================================
272 /*!
273  *  MakeEdgeWire
274  */
275 //=============================================================================
276 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire
277                     (Handle(GEOM_Object) theWire,
278                      const Standard_Real theLinearTolerance,
279                      const Standard_Real theAngularTolerance)
280 {
281   SetErrorCode(KO);
282
283   if (theWire.IsNull()) return NULL;
284
285   //Add a new Edge object
286   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
287
288   //Add a new Vector function
289   Handle(GEOM_Function) aFunction =
290     anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_WIRE);
291
292   //Check if the function is set correctly
293   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
294
295   GEOMImpl_IShapes aCI (aFunction);
296
297   Handle(GEOM_Function) aWire = theWire->GetLastFunction();
298
299   if (aWire.IsNull()) return NULL;
300
301   aCI.SetBase(aWire);
302   aCI.SetTolerance(theLinearTolerance);
303   aCI.SetAngularTolerance(theAngularTolerance);
304
305   //Compute the Edge value
306   try {
307     OCC_CATCH_SIGNALS;
308     if (!GetSolver()->ComputeFunction(aFunction)) {
309       SetErrorCode("Shape driver failed");
310       return NULL;
311     }
312   }
313   catch (Standard_Failure) {
314     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
315     SetErrorCode(aFail->GetMessageString());
316     return NULL;
317   }
318
319   const double DEF_LIN_TOL = Precision::Confusion();
320   const double DEF_ANG_TOL = Precision::Angular();
321   //Make a Python command
322   if ( theAngularTolerance == DEF_ANG_TOL ) {
323     if ( theLinearTolerance == DEF_LIN_TOL )
324       GEOM::TPythonDump(aFunction) << anEdge  << " = geompy.MakeEdgeWire("
325                                    << theWire << ")";
326     else
327       GEOM::TPythonDump(aFunction) << anEdge  << " = geompy.MakeEdgeWire("
328                                    << theWire << ", " << theLinearTolerance << ")";
329   }
330   else {
331     GEOM::TPythonDump(aFunction) << anEdge  << " = geompy.MakeEdgeWire("
332                                  << theWire << ", " << theLinearTolerance << ", "
333                                  << theAngularTolerance << ")";
334   }
335
336   SetErrorCode(OK);
337   return anEdge;
338 }
339
340 //=============================================================================
341 /*!
342  *  MakeWire
343  */
344 //=============================================================================
345 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
346                              (std::list<Handle(GEOM_Object)> theShapes,
347                               const Standard_Real            theTolerance)
348 {
349   SetErrorCode(KO);
350
351   //Add a new object
352   Handle(GEOM_Object) aWire = GetEngine()->AddObject(GetDocID(), GEOM_WIRE);
353
354   //Add a new function
355   Handle(GEOM_Function) aFunction =
356     aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES);
357   if (aFunction.IsNull()) return NULL;
358
359   //Check if the function is set correctly
360   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
361
362   GEOMImpl_IShapes aCI (aFunction);
363   aCI.SetTolerance(theTolerance);
364
365   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
366
367   // Shapes
368   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
369   for (; it != theShapes.end(); it++) {
370     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
371     if (aRefSh.IsNull()) {
372       SetErrorCode("NULL argument shape for the shape construction");
373       return NULL;
374     }
375     aShapesSeq->Append(aRefSh);
376   }
377   aCI.SetShapes(aShapesSeq);
378
379   //Compute the shape
380   try {
381     OCC_CATCH_SIGNALS;
382     if (!GetSolver()->ComputeFunction(aFunction)) {
383       SetErrorCode("Shape driver failed");
384       return NULL;
385     }
386   }
387   catch (Standard_Failure) {
388     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
389     SetErrorCode(aFail->GetMessageString());
390     return NULL;
391   }
392
393   //Make a Python command
394   GEOM::TPythonDump pd (aFunction);
395   pd << aWire << " = geompy.MakeWire([";
396
397   // Shapes
398   it = theShapes.begin();
399   if (it != theShapes.end()) {
400     pd << (*it++);
401     while (it != theShapes.end()) {
402       pd << ", " << (*it++);
403     }
404   }
405   pd << "], " << theTolerance << ")";
406
407   SetErrorCode(OK);
408   return aWire;
409 }
410
411 //=============================================================================
412 /*!
413  *  MakeFace
414  */
415 //=============================================================================
416 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
417                                                           const bool isPlanarWanted)
418 {
419   SetErrorCode(KO);
420
421   if (theWire.IsNull()) return NULL;
422
423   //Add a new Face object
424   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
425
426   //Add a new Shape function for creation of a face from a wire
427   Handle(GEOM_Function) aFunction =
428     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
429   if (aFunction.IsNull()) return NULL;
430
431   //Check if the function is set correctly
432   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
433
434   GEOMImpl_IShapes aCI (aFunction);
435
436   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
437
438   if (aRefWire.IsNull()) return NULL;
439
440   aCI.SetBase(aRefWire);
441   aCI.SetIsPlanar(isPlanarWanted);
442
443   //Compute the Face value
444   Standard_Boolean isWarning = Standard_False;
445   try {
446     OCC_CATCH_SIGNALS;
447     if (!GetSolver()->ComputeFunction(aFunction)) {
448       SetErrorCode("Shape driver failed to compute a face");
449       return NULL;
450     }
451   }
452   catch (Standard_Failure) {
453     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
454     SetErrorCode(aFail->GetMessageString());
455     // to provide warning
456     if (!aFunction->GetValue().IsNull()) {
457       isWarning = Standard_True;
458     } else {
459       return NULL;
460     }
461   }
462
463   //Make a Python command
464   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
465     << theWire << ", " << (int)isPlanarWanted << ")";
466
467   // to provide warning
468   if (!isWarning) SetErrorCode(OK);
469   return aFace;
470 }
471
472 //=============================================================================
473 /*!
474  *  MakeFaceWires
475  */
476 //=============================================================================
477 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
478                              (std::list<Handle(GEOM_Object)> theShapes,
479                               const bool isPlanarWanted)
480 {
481   SetErrorCode(KO);
482
483   //Add a new object
484   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
485
486   //Add a new function
487   Handle(GEOM_Function) aFunction =
488     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
489   if (aFunction.IsNull()) return NULL;
490
491   //Check if the function is set correctly
492   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
493
494   GEOMImpl_IShapes aCI (aFunction);
495
496   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
497
498   // Shapes
499   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
500   for (; it != theShapes.end(); it++) {
501     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
502     if (aRefSh.IsNull()) {
503       SetErrorCode("NULL argument shape for the face construction");
504       return NULL;
505     }
506     aShapesSeq->Append(aRefSh);
507   }
508   aCI.SetShapes(aShapesSeq);
509
510   aCI.SetIsPlanar(isPlanarWanted);
511
512   //Compute the shape
513   Standard_Boolean isWarning = Standard_False;
514   try {
515     OCC_CATCH_SIGNALS;
516     if (!GetSolver()->ComputeFunction(aFunction)) {
517       SetErrorCode("Shape driver failed");
518       return NULL;
519     }
520   }
521   catch (Standard_Failure) {
522     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
523     SetErrorCode(aFail->GetMessageString());
524     // to provide warning
525     if (!aFunction->GetValue().IsNull()) {
526       isWarning = Standard_True;
527     } else {
528       return NULL;
529     }
530   }
531
532   //Make a Python command
533   GEOM::TPythonDump pd (aFunction);
534   pd << aShape << " = geompy.MakeFaceWires([";
535
536   // Shapes
537   it = theShapes.begin();
538   if (it != theShapes.end()) {
539     pd << (*it++);
540     while (it != theShapes.end()) {
541       pd << ", " << (*it++);
542     }
543   }
544   pd << "], " << (int)isPlanarWanted << ")";
545
546   // to provide warning
547   if (!isWarning) SetErrorCode(OK);
548   return aShape;
549 }
550
551 //=============================================================================
552 /*!
553  *  MakeFaceFromSurface
554  */
555 //=============================================================================
556 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface
557                                               (Handle(GEOM_Object) theFace,
558                                                Handle(GEOM_Object) theWire)
559 {
560   SetErrorCode(KO);
561
562   //Add a new object
563   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
564
565   //Add a new function
566   Handle(GEOM_Function) aFunction =
567     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_FROM_SURFACE);
568
569   if (aFunction.IsNull()) {
570     return NULL;
571   }
572
573   //Check if the function is set correctly
574   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
575     return NULL;
576   }
577
578   GEOMImpl_IShapes aCI (aFunction);
579   Handle(TColStd_HSequenceOfTransient) aShapesSeq =
580     new TColStd_HSequenceOfTransient;
581   Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
582   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
583
584   if (aRefFace.IsNull()) {
585     SetErrorCode("NULL argument face for the face construction");
586     return NULL;
587   }
588
589   if (aRefWire.IsNull()) {
590     SetErrorCode("NULL argument wire for the face construction");
591     return NULL;
592   }
593
594   aShapesSeq->Append(aRefFace);
595   aShapesSeq->Append(aRefWire);
596
597   aCI.SetShapes(aShapesSeq);
598
599   //Compute the face
600   try {
601     OCC_CATCH_SIGNALS;
602     if (!GetSolver()->ComputeFunction(aFunction)) {
603       SetErrorCode("Shape driver failed");
604       return NULL;
605     }
606   }
607   catch (Standard_Failure) {
608     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
609     SetErrorCode(aFail->GetMessageString());
610     return NULL;
611   }
612
613   //Make a Python command
614   GEOM::TPythonDump (aFunction) << aShape
615     << " = geompy.MakeFaceFromSurface(" << theFace << ", " << theWire << ")";
616
617   SetErrorCode(OK);
618
619   return aShape;
620 }
621
622 //=============================================================================
623 /*!
624  *  MakeShell
625  */
626 //=============================================================================
627 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
628                              (std::list<Handle(GEOM_Object)> theShapes)
629 {
630   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
631 }
632
633 //=============================================================================
634 /*!
635  *  MakeSolidShells
636  */
637 //=============================================================================
638 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
639                              (std::list<Handle(GEOM_Object)> theShapes)
640 {
641   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
642 }
643
644 //=============================================================================
645 /*!
646  *  MakeCompound
647  */
648 //=============================================================================
649 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
650                              (std::list<Handle(GEOM_Object)> theShapes)
651 {
652   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
653 }
654
655 //=============================================================================
656 /*!
657  *  MakeShape
658  */
659 //=============================================================================
660 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
661                              (std::list<Handle(GEOM_Object)> theShapes,
662                               const Standard_Integer         theObjectType,
663                               const Standard_Integer         theFunctionType,
664                               const TCollection_AsciiString& theMethodName)
665 {
666   SetErrorCode(KO);
667
668   //Add a new object
669   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
670
671   //Add a new function
672   Handle(GEOM_Function) aFunction =
673     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
674   if (aFunction.IsNull()) return NULL;
675
676   //Check if the function is set correctly
677   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
678
679   GEOMImpl_IShapes aCI (aFunction);
680
681   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
682
683   // Shapes
684   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
685   for (; it != theShapes.end(); it++) {
686     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
687     if (aRefSh.IsNull()) {
688       SetErrorCode("NULL argument shape for the shape construction");
689       return NULL;
690     }
691     aShapesSeq->Append(aRefSh);
692   }
693   aCI.SetShapes(aShapesSeq);
694
695   //Compute the shape
696   try {
697     OCC_CATCH_SIGNALS;
698     if (!GetSolver()->ComputeFunction(aFunction)) {
699       SetErrorCode("Shape driver failed");
700       return NULL;
701     }
702   }
703   catch (Standard_Failure) {
704     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
705     SetErrorCode(aFail->GetMessageString());
706     return NULL;
707   }
708
709   //Make a Python command
710   GEOM::TPythonDump pd (aFunction);
711   pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
712
713   // Shapes
714   it = theShapes.begin();
715   if (it != theShapes.end()) {
716     pd << (*it++);
717     while (it != theShapes.end()) {
718       pd << ", " << (*it++);
719     }
720   }
721   pd << "])";
722
723   SetErrorCode(OK);
724   return aShape;
725 }
726
727 //=============================================================================
728 /*!
729  *  MakeGlueFaces
730  */
731 //=============================================================================
732 Handle(GEOM_Object)
733 GEOMImpl_IShapesOperations::MakeGlueFaces (std::list< Handle(GEOM_Object) >& theShapes,
734                                            const Standard_Real               theTolerance,
735                                            const Standard_Boolean            doKeepNonSolids)
736 {
737   SetErrorCode(KO);
738
739   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
740   if ( objects.IsNull() || objects->IsEmpty() ) {
741     SetErrorCode("NULL argument shape");
742     return NULL;
743   }
744
745   //Add a new Glued object
746   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
747
748   //Add a new Glue function
749   Handle(GEOM_Function) aFunction;
750   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
751   if (aFunction.IsNull()) return NULL;
752
753   //Check if the function is set correctly
754   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
755
756   GEOMImpl_IGlue aCI (aFunction);
757
758   aCI.SetBase( objects );
759   aCI.SetTolerance(theTolerance);
760   aCI.SetKeepNonSolids(doKeepNonSolids);
761
762   //Compute the sub-shape value
763   Standard_Boolean isWarning = Standard_False;
764   try {
765     OCC_CATCH_SIGNALS;
766     if (!GetSolver()->ComputeFunction(aFunction)) {
767       SetErrorCode("Shape driver failed to glue faces");
768       return NULL;
769     }
770   }
771   catch (Standard_Failure) {
772     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
773     SetErrorCode(aFail->GetMessageString());
774     // to provide warning
775     if (!aFunction->GetValue().IsNull()) {
776       isWarning = Standard_True;
777     } else {
778       return NULL;
779     }
780   }
781
782   //Make a Python command
783   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
784     << theShapes << ", " << theTolerance << ")";
785
786   // to provide warning
787   if (!isWarning) SetErrorCode(OK);
788   return aGlued;
789 }
790
791 //=============================================================================
792 /*!
793  *  GetGlueFaces
794  */
795 //=============================================================================
796 /*
797 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
798                                                 (Handle(GEOM_Object) theShape,
799                                                  const Standard_Real theTolerance)
800 {
801   SetErrorCode(KO);
802
803   if (theShape.IsNull()) return NULL;
804   TopoDS_Shape aShape = theShape->GetValue();
805   if (aShape.IsNull()) return NULL;
806
807   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
808
809   Standard_Integer iErr;
810   TopoDS_Shape aS;
811   GEOMAlgo_Gluer1 aGluer;
812   GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
813   GEOMAlgo_CoupleOfShapes aCS;
814   GEOMAlgo_ListOfCoupleOfShapes aLCS;
815
816   //aGluer = new GEOMAlgo_Gluer1;
817   aGluer.SetShape(aShape);
818   aGluer.SetTolerance(theTolerance);
819   aGluer.Perform();
820   iErr = aGluer.ErrorStatus();
821   if (iErr) return NULL;
822
823   TopTools_ListOfShape listShape;
824   const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
825   // Access to faces
826   aItCS.Initialize(aLCSG);
827   for (; aItCS.More(); aItCS.Next()) {
828     const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
829     listShape.Append(aCSG.Shape1());
830   }
831
832   TopTools_ListIteratorOfListOfShape itSub (listShape);
833   TCollection_AsciiString anAsciiList, anEntry;
834   TopTools_IndexedMapOfShape anIndices;
835   TopExp::MapShapes(aShape, anIndices);
836   Handle(TColStd_HArray1OfInteger) anArray;
837   Handle(GEOM_Object) anObj;
838   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
839     TopoDS_Shape aValue = itSub.Value();
840     anArray = new TColStd_HArray1OfInteger(1,1);
841     anArray->SetValue(1, anIndices.FindIndex(aValue));
842     anObj = GetEngine()->AddSubShape(theShape, anArray);
843     if (!anObj.IsNull()) {
844       aSeq->Append(anObj);
845
846       // for python command
847       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
848       anAsciiList += anEntry;
849       anAsciiList += ",";
850     }
851   }
852
853   //Make a Python command
854   if( anAsciiList.Length() > 0 ) {
855     anAsciiList.Trunc(anAsciiList.Length() - 1);
856     Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
857     GEOM::TPythonDump pd (aFunction, true);
858     pd << "[" << anAsciiList.ToCString();
859     pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
860   }
861
862   SetErrorCode(OK);
863
864   return aSeq;
865 }
866 */
867
868 //=============================================================================
869 /*!
870  *  MakeGlueFacesByList
871  */
872 //=============================================================================
873 Handle(GEOM_Object)
874 GEOMImpl_IShapesOperations::MakeGlueFacesByList(std::list< Handle(GEOM_Object) >& theShapes,
875                                                 const Standard_Real               theTolerance,
876                                                 std::list<Handle(GEOM_Object)> &  theFaces,
877                                                 const Standard_Boolean            doKeepNonSolids,
878                                                 const Standard_Boolean            doGlueAllEdges)
879 {
880   SetErrorCode(KO);
881
882   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
883   if ( objects.IsNull() || objects->IsEmpty() ) {
884     SetErrorCode("NULL argument shape");
885     return NULL;
886   }
887   Handle(TColStd_HSequenceOfTransient) aFaces = GEOM_Object::GetLastFunctions( theFaces );
888   if ( aFaces.IsNull() ) {
889     SetErrorCode("NULL argument shape for the shape construction");
890     return NULL;
891   }
892
893   //Add a new Glued object
894   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
895
896   //Add a new Glue function
897   Handle(GEOM_Function) aFunction;
898   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
899   if (aFunction.IsNull()) return NULL;
900
901   //Check if the function is set correctly
902   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
903
904   GEOMImpl_IGlue aCI (aFunction);
905
906   aCI.SetBase( objects );
907   aCI.SetTolerance(theTolerance);
908   aCI.SetKeepNonSolids(doKeepNonSolids);
909   aCI.SetGlueAllEdges(doGlueAllEdges);
910   aCI.SetFaces(aFaces);
911
912   //Compute the sub-shape value
913   Standard_Boolean isWarning = Standard_False;
914   try {
915     OCC_CATCH_SIGNALS;
916     if (!GetSolver()->ComputeFunction(aFunction)) {
917       SetErrorCode("Shape driver failed to glue faces");
918       return NULL;
919     }
920   }
921   catch (Standard_Failure) {
922     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
923     SetErrorCode(aFail->GetMessageString());
924     // to provide warning
925     if (!aFunction->GetValue().IsNull()) {
926       isWarning = Standard_True;
927     } else {
928       return NULL;
929     }
930   }
931
932   //Make a Python command
933
934   GEOM::TPythonDump pd(aFunction);
935   pd << aGlued << " = geompy.MakeGlueFacesByList("
936      << theShapes << ", " << theTolerance << ", " << theFaces << ", "
937      << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")";
938
939   // to provide warning
940   if (!isWarning) SetErrorCode(OK);
941   return aGlued;
942 }
943
944 //=============================================================================
945 /*!
946  *  MakeGlueEdges
947  */
948 //=============================================================================
949 Handle(GEOM_Object)
950 GEOMImpl_IShapesOperations::MakeGlueEdges (std::list< Handle(GEOM_Object) >& theShapes,
951                                            const Standard_Real               theTolerance)
952 {
953   SetErrorCode(KO);
954
955   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
956   if ( objects.IsNull() || objects->IsEmpty() ) {
957     SetErrorCode("NULL argument shape");
958     return NULL;
959   }
960
961   //Add a new Glued object
962   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
963
964   //Add a new Glue function
965   Handle(GEOM_Function) aFunction;
966   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES);
967   if (aFunction.IsNull()) return NULL;
968
969   //Check if the function is set correctly
970   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
971
972   GEOMImpl_IGlue aCI (aFunction);
973
974   aCI.SetBase( objects );
975   aCI.SetTolerance(theTolerance);
976   aCI.SetKeepNonSolids(true);
977
978   //Compute the sub-shape value
979   Standard_Boolean isWarning = Standard_False;
980   try {
981     OCC_CATCH_SIGNALS;
982     if (!GetSolver()->ComputeFunction(aFunction)) {
983       SetErrorCode("Shape driver failed to glue edges");
984       return NULL;
985     }
986   }
987   catch (Standard_Failure) {
988     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
989     SetErrorCode(aFail->GetMessageString());
990     // to provide warning
991     if (!aFunction->GetValue().IsNull()) {
992       isWarning = Standard_True;
993     } else {
994       return NULL;
995     }
996   }
997
998   //Make a Python command
999   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueEdges("
1000     << theShapes << ", " << theTolerance << ")";
1001
1002   // to provide warning
1003   if (!isWarning) SetErrorCode(OK);
1004   return aGlued;
1005 }
1006
1007 //=============================================================================
1008 /*!
1009  *  GetGlueShapes
1010  */
1011 //=============================================================================
1012 Handle(TColStd_HSequenceOfTransient)
1013 GEOMImpl_IShapesOperations::GetGlueShapes (std::list< Handle(GEOM_Object) >& theShapes,
1014                                            const Standard_Real               theTolerance,
1015                                            const TopAbs_ShapeEnum            theType)
1016 {
1017   SetErrorCode(KO);
1018
1019   TopoDS_Shape aShape;
1020   TopTools_SequenceOfShape shapes;
1021   std::list< Handle(GEOM_Object) >::iterator s = theShapes.begin();
1022   Handle(GEOM_Object) lastCreatedGO;
1023   for ( ; s != theShapes.end(); ++s )
1024   {
1025     Handle(GEOM_Object) go = *s;
1026     if ( go.IsNull() ) return NULL;
1027     aShape = go->GetValue();
1028     if ( aShape.IsNull() ) return NULL;
1029     shapes.Append( aShape );
1030     lastCreatedGO = GEOM::GetCreatedLast( lastCreatedGO, go );
1031   }
1032   if ( shapes.Length() > 1 )
1033   {
1034     TopoDS_Compound compound;
1035     BRep_Builder builder;
1036     builder.MakeCompound( compound );
1037     for ( int i = 1; i <= shapes.Length(); ++i )
1038       builder.Add( compound, shapes( i ) );
1039
1040     aShape = compound;
1041   }
1042
1043   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1044
1045   GEOMAlgo_GlueDetector aGluer;
1046   aGluer.SetArgument(aShape);
1047   aGluer.SetTolerance(theTolerance);
1048   aGluer.Perform();
1049   Standard_Integer iErr = aGluer.ErrorStatus();
1050   if (iErr) return NULL;
1051
1052   std::vector< TopTools_IndexedMapOfShape* > anIndices( shapes.Length(), NULL );
1053   Handle(TColStd_HArray1OfInteger) anArray;
1054   Handle(GEOM_Object) anObj;
1055
1056   TopTools_ListOfShape listOnePerSet;
1057
1058   const TopTools_DataMapOfShapeListOfShape& aImages = aGluer.Images();
1059   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS (aImages);
1060   for (int index = 1; aItDMSLS.More(); aItDMSLS.Next(), ++index) {
1061     // some key shape
1062     //const TopoDS_Shape& aSkey = aItDMSLS.Key();
1063
1064     // list of shapes of the argument that can be glued
1065     const TopTools_ListOfShape& aLSD = aItDMSLS.Value();
1066
1067     //listShape.Append(aLSD.First());
1068     TopoDS_Shape aValue = aLSD.First();
1069
1070     if (aValue.ShapeType() == theType) {
1071       listOnePerSet.Append(aValue);
1072     }
1073   }
1074
1075   // for stable order of returned entities
1076   GEOMUtils::SortShapes(listOnePerSet, Standard_False);
1077
1078   TopTools_ListIteratorOfListOfShape aListIt (listOnePerSet);
1079   for (; aListIt.More(); aListIt.Next())
1080   {
1081     TopoDS_Shape aValue = aListIt.Value();
1082     // find a shape to add aValue as a sub-shape
1083     anObj.Nullify();
1084     s = theShapes.begin();
1085     for ( int i = 0; i < shapes.Length(); ++i, ++s )
1086     {
1087       Handle(GEOM_Object) object = *s;
1088       if ( !anIndices[i] ) {
1089         anIndices[i] = new TopTools_IndexedMapOfShape;
1090         TopExp::MapShapes( object->GetValue(), *anIndices[i]);
1091       }
1092       if (int index = anIndices[i]->FindIndex( aValue )) {
1093         anArray = new TColStd_HArray1OfInteger(1,1);
1094         anArray->SetValue(1, index);
1095         anObj = GetEngine()->AddSubShape( object, anArray);
1096         break;
1097       }
1098     }
1099     if (!anObj.IsNull())
1100       aSeq->Append(anObj);
1101   }
1102   for ( size_t i = 0 ; i < anIndices.size(); ++i )
1103     delete anIndices[i];
1104
1105   // Make a Python command
1106   if ( aSeq->Length() > 0)
1107   {
1108     Handle(GEOM_Function) aFunction = lastCreatedGO->GetLastFunction();
1109     GEOM::TPythonDump pd (aFunction, /*append=*/true);
1110     pd << aSeq
1111        << " = geompy." << (theType == TopAbs_FACE ? "GetGlueFaces" : "GetGlueEdges" )
1112        << "( " << theShapes << ", " << theTolerance << ")";
1113   }
1114
1115   SetErrorCode(OK);
1116
1117   return aSeq;
1118 }
1119
1120 //=============================================================================
1121 /*!
1122  *  MakeGlueEdgesByList
1123  */
1124 //=============================================================================
1125 Handle(GEOM_Object)
1126 GEOMImpl_IShapesOperations::MakeGlueEdgesByList (std::list< Handle(GEOM_Object) >& theShapes,
1127                                                  const Standard_Real               theTolerance,
1128                                                  std::list<Handle(GEOM_Object)>&   theEdges)
1129 {
1130   SetErrorCode(KO);
1131
1132   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1133   if ( objects.IsNull() || objects->IsEmpty() ) {
1134     SetErrorCode("NULL argument shape");
1135     return NULL;
1136   }
1137   Handle(TColStd_HSequenceOfTransient) anEdges = GEOM_Object::GetLastFunctions( theEdges );
1138   if ( anEdges.IsNull() ) {
1139     SetErrorCode("NULL argument shape for the shape construction");
1140     return NULL;
1141   }
1142   //Add a new Glued object
1143   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
1144
1145   //Add a new Glue function
1146   Handle(GEOM_Function) aFunction;
1147   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES_BY_LIST);
1148   if (aFunction.IsNull()) return NULL;
1149
1150   //Check if the function is set correctly
1151   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1152
1153   GEOMImpl_IGlue aCI (aFunction);
1154
1155   aCI.SetBase( objects );
1156   aCI.SetTolerance(theTolerance);
1157   aCI.SetKeepNonSolids(true);
1158   aCI.SetFaces(anEdges);
1159
1160   //Compute the sub-shape value
1161   Standard_Boolean isWarning = Standard_False;
1162   try {
1163     OCC_CATCH_SIGNALS;
1164     if (!GetSolver()->ComputeFunction(aFunction)) {
1165       SetErrorCode("Shape driver failed to glue edges");
1166       return NULL;
1167     }
1168   }
1169   catch (Standard_Failure) {
1170     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1171     SetErrorCode(aFail->GetMessageString());
1172     // to provide warning
1173     if (!aFunction->GetValue().IsNull()) {
1174       isWarning = Standard_True;
1175     } else {
1176       return NULL;
1177     }
1178   }
1179
1180   //Make a Python command
1181
1182   GEOM::TPythonDump pd (aFunction);
1183   pd << aGlued << " = geompy.MakeGlueEdgesByList("
1184      << theShapes << ", " << theTolerance << ", " << theEdges << " )";
1185
1186   // to provide warning
1187   if (!isWarning) SetErrorCode(OK);
1188   return aGlued;
1189 }
1190
1191 //=============================================================================
1192 /*!
1193  *  GetExistingSubObjects
1194  */
1195 //=============================================================================
1196 Handle(TColStd_HSequenceOfTransient)
1197 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object)    theShape,
1198                                                   const Standard_Boolean theGroupsOnly)
1199 {
1200   // note: this method does not return fields
1201
1202   Standard_Integer types = theGroupsOnly ? Groups : Groups|SubShapes;
1203   Handle(TColStd_HSequenceOfTransient) results = GetExistingSubObjects(theShape, types);
1204
1205   if (results->Length() > 0) {
1206     //Make a Python command
1207     TCollection_AsciiString anAsciiList;
1208     for (int i = 1; i <= results->Length(); i++)
1209     {
1210       Handle(GEOM_BaseObject) obj = Handle(GEOM_BaseObject)::DownCast( results->Value(i));
1211       obj->GetEntryString();
1212       if ( i < results->Length() )
1213         anAsciiList += ",";
1214     }
1215     
1216     GEOM::TPythonDump pd (theShape->GetLastFunction(), /*append=*/true);
1217     pd << "[" << anAsciiList.ToCString();
1218     pd << "] = geompy.GetExistingSubObjects(";
1219     pd << theShape << ", " << (bool)theGroupsOnly << ")";
1220   }
1221
1222   return results;
1223 }
1224
1225 Handle(TColStd_HSequenceOfTransient)
1226 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object)    theShape,
1227                                                   const Standard_Integer theTypes)
1228 {
1229   SetErrorCode(KO);
1230
1231   if (theShape.IsNull()) return NULL;
1232
1233   Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1234   if (aMainShape.IsNull()) return NULL;
1235
1236   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1237   SetErrorCode(NOT_FOUND_ANY);
1238
1239   if (!aMainShape->HasSubShapeReferences()) return aSeq;
1240   const TDataStd_ListOfExtendedString& aListEntries = aMainShape->GetSubShapeReferences();
1241   if (aListEntries.IsEmpty()) return aSeq;
1242
1243   SetErrorCode(KO);
1244
1245   TDataStd_ListIteratorOfListOfExtendedString anIt (aListEntries);
1246   for (; anIt.More(); anIt.Next()) {
1247     TCollection_ExtendedString anEntry = anIt.Value();
1248     Standard_Integer aStrLen = anEntry.LengthOfCString();
1249     char* anEntryStr = new char[aStrLen+1];
1250     anEntry.ToUTF8CString(anEntryStr);
1251     Handle(GEOM_BaseObject) anObj = GetEngine()->GetObject(GetDocID(), anEntryStr, false);
1252     if (!anObj.IsNull() ) {
1253       bool isGroup    = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() == GEOM_GROUP;
1254       bool isSubShape = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() != GEOM_GROUP;
1255       bool isField    = anObj->IsKind(STANDARD_TYPE(GEOM_Field));
1256       if (theTypes & Groups    && isGroup ||
1257           theTypes & SubShapes && isSubShape ||
1258           theTypes & Fields    && isField) {
1259         aSeq->Append(anObj);
1260       }
1261     }
1262     delete [] anEntryStr;
1263   }
1264
1265   if (aSeq->Length() == 0) {
1266     SetErrorCode(NOT_FOUND_ANY);
1267     return aSeq;
1268   }
1269
1270   SetErrorCode(OK);
1271
1272   return aSeq;
1273 }
1274
1275 //=============================================================================
1276 /*!
1277  *  MakeExplode
1278  */
1279 //=============================================================================
1280 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
1281                                           (Handle(GEOM_Object)    theShape,
1282                                            const Standard_Integer theShapeType,
1283                                            const Standard_Boolean isSorted,
1284                                            const ExplodeType      theExplodeType)
1285 {
1286   SetErrorCode(KO);
1287
1288   if (theShape.IsNull()) return NULL;
1289   TopoDS_Shape aShape = theShape->GetValue();
1290   if (aShape.IsNull()) return NULL;
1291
1292   Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1293
1294   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1295   Handle(GEOM_Object) anObj;
1296   TopTools_MapOfShape mapShape;
1297   TopTools_ListOfShape listShape;
1298
1299   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1300       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1301        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
1302        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND))
1303   {
1304     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1305     for (; It.More(); It.Next()) {
1306       if (mapShape.Add(It.Value())) {
1307         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1308             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
1309           listShape.Append(It.Value());
1310         }
1311       }
1312     }
1313   }
1314   else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1315   {
1316     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1317     for (; exp.More(); exp.Next())
1318       if (mapShape.Add(exp.Current()))
1319         listShape.Append(exp.Current());
1320   }
1321
1322   if (listShape.IsEmpty()) {
1323     //SetErrorCode("The given shape has no sub-shapes of the requested type");
1324     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1325     return aSeq;
1326   }
1327
1328   if (isSorted) {
1329     bool isOldSorting = false;
1330     if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1331       isOldSorting = true;
1332     GEOMUtils::SortShapes(listShape, isOldSorting);
1333   }
1334
1335   TopTools_IndexedMapOfShape anIndices;
1336   TopExp::MapShapes(aShape, anIndices);
1337   Handle(TColStd_HArray1OfInteger) anArray;
1338
1339   TopTools_ListIteratorOfListOfShape itSub (listShape);
1340   TCollection_AsciiString anAsciiList, anEntry;
1341   for (int index = 1; itSub.More(); itSub.Next(), ++index)
1342   {
1343     TopoDS_Shape aValue = itSub.Value();
1344     anArray = new TColStd_HArray1OfInteger(1,1);
1345     anArray->SetValue(1, anIndices.FindIndex(aValue));
1346
1347     //anObj = GetEngine()->AddSubShape(theShape, anArray);
1348     {
1349       anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1350       Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1351       if (aFunction.IsNull()) return aSeq;
1352
1353       GEOM_ISubShape aSSI (aFunction);
1354       aSSI.SetMainShape(aMainShape);
1355       aSSI.SetIndices(anArray);
1356
1357       // Set function value directly, as we know it.
1358       // Usage of Solver here would lead to significant loss of time,
1359       // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1360       // on the main shape for each being calculated sub-shape separately.
1361       aFunction->SetValue(aValue);
1362
1363       // Put this subshape in the list of sub-shapes of theMainShape
1364       aMainShape->AddSubShapeReference(aFunction);
1365     }
1366
1367     if (!anObj.IsNull()) {
1368       aSeq->Append(anObj);
1369
1370       // for python command
1371       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1372       anAsciiList += anEntry;
1373       anAsciiList += ",";
1374     }
1375   }
1376
1377   //Make a Python command
1378   anAsciiList.Trunc(anAsciiList.Length() - 1);
1379
1380   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1381   pd << "[" << anAsciiList.ToCString() << "] = geompy.";
1382   switch (theExplodeType) {
1383   case EXPLODE_NEW_EXCLUDE_MAIN:
1384     pd << "ExtractShapes(" << theShape << ", "
1385        << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")";
1386     break;
1387   case EXPLODE_NEW_INCLUDE_MAIN:
1388     pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(")
1389        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1390     break;
1391   case EXPLODE_OLD_INCLUDE_MAIN:
1392     pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(")
1393        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1394     break;
1395   default: ;
1396   }
1397   SetErrorCode(OK);
1398
1399   return aSeq;
1400 }
1401
1402 //=============================================================================
1403 /*!
1404  *  SubShapeAllIDs
1405  */
1406 //=============================================================================
1407 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
1408                                           (Handle(GEOM_Object)    theShape,
1409                                            const Standard_Integer theShapeType,
1410                                            const Standard_Boolean isSorted,
1411                                            const ExplodeType      theExplodeType)
1412 {
1413   SetErrorCode(KO);
1414
1415   if (theShape.IsNull()) return NULL;
1416   TopoDS_Shape aShape = theShape->GetValue();
1417   if (aShape.IsNull()) return NULL;
1418
1419   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1420   TopTools_MapOfShape mapShape;
1421   TopTools_ListOfShape listShape;
1422
1423   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1424       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1425        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
1426        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND))
1427   {
1428     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1429     for (; It.More(); It.Next()) {
1430       if (mapShape.Add(It.Value())) {
1431         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1432             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
1433           listShape.Append(It.Value());
1434         }
1435       }
1436     }
1437   }
1438   else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1439   {
1440     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1441     for (; exp.More(); exp.Next())
1442       if (mapShape.Add(exp.Current()))
1443         listShape.Append(exp.Current());
1444   }
1445
1446   if (listShape.IsEmpty()) {
1447     //SetErrorCode("The given shape has no sub-shapes of the requested type");
1448     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1449     return aSeq;
1450   }
1451
1452   if (isSorted) {
1453     bool isOldSorting = false;
1454     if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1455       isOldSorting = true;
1456     GEOMUtils::SortShapes(listShape, isOldSorting);
1457   }
1458
1459   TopTools_IndexedMapOfShape anIndices;
1460   TopExp::MapShapes(aShape, anIndices);
1461   Handle(TColStd_HArray1OfInteger) anArray;
1462
1463   TopTools_ListIteratorOfListOfShape itSub (listShape);
1464   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1465     TopoDS_Shape aValue = itSub.Value();
1466     aSeq->Append(anIndices.FindIndex(aValue));
1467   }
1468
1469   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1470
1471   //Make a Python command
1472   GEOM::TPythonDump pd (aFunction, /*append=*/true);
1473   pd << "listSubShapeIDs = geompy.SubShapeAll";
1474   switch (theExplodeType) {
1475   case EXPLODE_NEW_EXCLUDE_MAIN:
1476     break;
1477   case EXPLODE_NEW_INCLUDE_MAIN:
1478     pd << (isSorted ? "SortedCentresIDs(" : "IDs(")
1479        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1480     break;
1481   case EXPLODE_OLD_INCLUDE_MAIN:
1482     pd << (isSorted ? "SortedIDs(" : "IDs(")
1483        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1484     break;
1485   default: ;
1486   }
1487
1488   SetErrorCode(OK);
1489   return aSeq;
1490 }
1491
1492 //=============================================================================
1493 /*!
1494  *  GetSubShape
1495  */
1496 //=============================================================================
1497 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
1498                                           (Handle(GEOM_Object)    theMainShape,
1499                                            const Standard_Integer theID)
1500 {
1501   SetErrorCode(KO);
1502
1503   if (theMainShape.IsNull()) return NULL;
1504
1505   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1506   anArray->SetValue(1, theID);
1507   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
1508   if (anObj.IsNull()) {
1509     SetErrorCode("Can not get a sub-shape with the given ID");
1510     return NULL;
1511   }
1512
1513   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1514
1515   //Make a Python command
1516   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1517                                << theMainShape << ", [" << theID << "])";
1518
1519   SetErrorCode(OK);
1520   return anObj;
1521 }
1522
1523 //=============================================================================
1524 /*!
1525  *  MakeSubShapes
1526  */
1527 //=============================================================================
1528 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes
1529                                 (Handle(GEOM_Object)              theMainShape,
1530                                  Handle(TColStd_HArray1OfInteger) theIndices)
1531 {
1532   SetErrorCode(KO);
1533
1534   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1535
1536   if (!theIndices->Length()) {
1537     SetErrorCode(NOT_FOUND_ANY);
1538     return aSeq;
1539   }
1540
1541   if (theMainShape.IsNull()) return NULL;
1542   TopoDS_Shape aShape = theMainShape->GetValue();
1543   if (aShape.IsNull()) return NULL;
1544
1545   Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
1546
1547   TopTools_IndexedMapOfShape anIndices;
1548   TopExp::MapShapes(aShape, anIndices);
1549
1550   Handle(TColStd_HArray1OfInteger) anArray;
1551   Handle(GEOM_Object) anObj;
1552
1553   TCollection_AsciiString anAsciiList, anEntry;
1554   Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper();
1555   for (i = low; i <= up; i++) {
1556     int id = theIndices->Value(i);
1557     if (1 <= id && id <= anIndices.Extent()) {
1558       TopoDS_Shape aValue = anIndices.FindKey(id);
1559       anArray = new TColStd_HArray1OfInteger(1,1);
1560       anArray->SetValue(1, id);
1561
1562       anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1563       if (!anObj.IsNull()) {
1564         Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1565         if (aFunction.IsNull()) return aSeq;
1566
1567         GEOM_ISubShape aSSI (aFunction);
1568         aSSI.SetMainShape(aMainShape);
1569         aSSI.SetIndices(anArray);
1570
1571         // Set function value directly, as we know it.
1572         // Usage of Solver here would lead to significant loss of time,
1573         // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1574         // on the main shape for each being calculated sub-shape separately.
1575         aFunction->SetValue(aValue);
1576
1577         // Put this sub-shape in the list of sub-shapes of theMainShape
1578         aMainShape->AddSubShapeReference(aFunction);
1579
1580         aSeq->Append(anObj);
1581
1582         // for python command
1583         TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1584         anAsciiList += anEntry;
1585         anAsciiList += ",";
1586       }
1587     }
1588   }
1589
1590   //Make a Python command
1591   anAsciiList.Trunc(anAsciiList.Length() - 1);
1592
1593   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1594   pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes("
1595      << theMainShape << ", [" ;
1596   for (i = low; i <= up - 1; i++) {
1597     pd << theIndices->Value(i) << ", ";
1598   }
1599   pd << theIndices->Value(up) << "])";
1600
1601   SetErrorCode(OK);
1602
1603   return aSeq;
1604 }
1605
1606 //=============================================================================
1607 /*!
1608  *  GetSubShapeIndex
1609  */
1610 //=============================================================================
1611 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1612                                                                Handle(GEOM_Object) theSubShape)
1613 {
1614   SetErrorCode(KO);
1615
1616   TopoDS_Shape aMainShape = theMainShape->GetValue();
1617   TopoDS_Shape aSubShape = theSubShape->GetValue();
1618
1619   if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1620
1621   TopTools_IndexedMapOfShape anIndices;
1622   TopExp::MapShapes(aMainShape, anIndices);
1623 //   if (anIndices.Contains(aSubShape)) {
1624 //     SetErrorCode(OK);
1625 //     return anIndices.FindIndex(aSubShape);
1626 //   }
1627   int id = anIndices.FindIndex(aSubShape);
1628   if (id > 0)
1629   {
1630     SetErrorCode(OK);
1631     return id;
1632   }
1633   return -1;
1634 }
1635
1636
1637
1638 //=============================================================================
1639 /*!
1640  *  GetSubShapeIndices
1641  */
1642 //=============================================================================
1643 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSubShapesIndices (Handle(GEOM_Object) theMainShape,
1644                                                                                     std::list<Handle(GEOM_Object)> theSubShapes)
1645 {
1646   MESSAGE("GEOMImpl_IShapesOperations::GetSubShapesIndices")
1647   SetErrorCode(KO);
1648   
1649   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1650   
1651   TopoDS_Shape aMainShape = theMainShape->GetValue();
1652   if (aMainShape.IsNull())
1653   {
1654     MESSAGE("NULL main shape")
1655     return NULL;
1656   }
1657   
1658   TopTools_IndexedMapOfShape anIndices;
1659   TopExp::MapShapes(aMainShape, anIndices);
1660   
1661   std::list<Handle(GEOM_Object)>::iterator it;
1662   for (it=theSubShapes.begin(); it != theSubShapes.end(); ++it)
1663   {
1664     TopoDS_Shape aSubShape = (*it)->GetValue(); 
1665     if (aSubShape.IsNull())
1666     {
1667       MESSAGE("NULL subshape")
1668       return NULL;
1669     }
1670     int id = anIndices.FindIndex(aSubShape);
1671     aSeq->Append(id);
1672   }  
1673   
1674   SetErrorCode(OK);
1675   return aSeq;
1676 }
1677
1678
1679 //=============================================================================
1680 /*!
1681  *  GetTopologyIndex
1682  */
1683 //=============================================================================
1684 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1685                                                                Handle(GEOM_Object) theSubShape)
1686 {
1687   SetErrorCode(OK);
1688
1689   TopoDS_Shape aMainShape = theMainShape->GetValue();
1690   TopoDS_Shape aSubShape = theSubShape->GetValue();
1691
1692   if (aMainShape.IsNull() || aSubShape.IsNull()) {
1693     SetErrorCode("Null argument shape given");
1694     return -1;
1695   }
1696
1697   int index = 1;
1698   if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1699     TopoDS_Iterator it;
1700     TopTools_ListOfShape CL;
1701     CL.Append(aMainShape);
1702     TopTools_ListIteratorOfListOfShape itC;
1703     for (itC.Initialize(CL); itC.More(); itC.Next()) {
1704       for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1705         if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1706           if (it.Value().IsSame(aSubShape))
1707             return index;
1708           else
1709             index++;
1710           CL.Append(it.Value());
1711         }
1712       }
1713     }
1714   } else {
1715     TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1716     TopTools_MapOfShape M;
1717     for (; anExp.More(); anExp.Next()) {
1718       if (M.Add(anExp.Current())) {
1719         if (anExp.Current().IsSame(aSubShape))
1720           return index;
1721         index++;
1722       }
1723     }
1724   }
1725
1726   SetErrorCode("The sub-shape does not belong to the main shape");
1727   return -1;
1728 }
1729
1730 //=============================================================================
1731 /*!
1732  *  GetShapeTypeString
1733  */
1734 //=============================================================================
1735 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1736 {
1737   SetErrorCode(KO);
1738
1739   TCollection_AsciiString aTypeName ("Null Shape");
1740
1741   TopoDS_Shape aShape = theShape->GetValue();
1742   if (aShape.IsNull())
1743     return aTypeName;
1744
1745   switch (aShape.ShapeType() )
1746   {
1747   case TopAbs_COMPOUND:
1748     aTypeName = "Compound";
1749     break;
1750   case  TopAbs_COMPSOLID:
1751     aTypeName = "Compound Solid";
1752     break;
1753   case TopAbs_SOLID:
1754     aTypeName = "Solid";
1755     break;
1756   case TopAbs_SHELL:
1757     aTypeName = "Shell";
1758     break;
1759   case TopAbs_FACE:
1760     {
1761       BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1762       if (surf.GetType() == GeomAbs_Plane)
1763         aTypeName = "Plane";
1764       else if (surf.GetType() == GeomAbs_Cylinder)
1765         aTypeName = "Cylindrical Face";
1766       else if (surf.GetType() == GeomAbs_Sphere)
1767         aTypeName = "Spherical Face";
1768       else if (surf.GetType() == GeomAbs_Torus)
1769         aTypeName = "Toroidal Face";
1770       else if (surf.GetType() == GeomAbs_Cone)
1771         aTypeName = "Conical Face";
1772       else
1773         aTypeName = "GEOM::FACE";
1774     }
1775     break;
1776   case TopAbs_WIRE:
1777     aTypeName = "Wire";
1778     break;
1779   case TopAbs_EDGE:
1780     {
1781       BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1782       if (curv.GetType() == GeomAbs_Line) {
1783         if ((Abs(curv.FirstParameter()) >= 1E6) ||
1784             (Abs(curv.LastParameter()) >= 1E6))
1785           aTypeName = "Line";
1786         else
1787           aTypeName = "Edge";
1788       } else if (curv.GetType() == GeomAbs_Circle) {
1789         if (curv.IsClosed())
1790           aTypeName = "Circle";
1791         else
1792           aTypeName = "Arc";
1793       } else {
1794         aTypeName = "Edge";
1795       }
1796     }
1797     break;
1798   case TopAbs_VERTEX:
1799     aTypeName = "Vertex";
1800     break;
1801   case TopAbs_SHAPE:
1802     aTypeName = "Shape";
1803     break;
1804   default:
1805     aTypeName = "Shape of unknown type";
1806   }
1807
1808   return aTypeName;
1809 }
1810
1811 //=============================================================================
1812 /*!
1813  *  NumberOfSubShapes
1814  */
1815 //=============================================================================
1816 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
1817                                           (Handle(GEOM_Object)    theShape,
1818                                            const Standard_Integer theShapeType)
1819 {
1820   SetErrorCode(KO);
1821   Standard_Integer nbShapes = 0;
1822
1823   if (theShape.IsNull()) return -1;
1824   TopoDS_Shape aShape = theShape->GetValue();
1825   if (aShape.IsNull()) return -1;
1826
1827   /*
1828   TopTools_MapOfShape mapShape;
1829
1830   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1831       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1832        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
1833        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
1834     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1835     for (; It.More(); It.Next()) {
1836       if (mapShape.Add(It.Value())) {
1837         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
1838             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
1839           nbShapes++;
1840         }
1841       }
1842     }
1843   } else {
1844     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1845     for (; exp.More(); exp.Next())
1846       if (mapShape.Add(exp.Current()))
1847         nbShapes++;
1848   }
1849   */
1850
1851   try {
1852     OCC_CATCH_SIGNALS;
1853     int iType, nbTypes [TopAbs_SHAPE];
1854     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
1855       nbTypes[iType] = 0;
1856     nbTypes[aShape.ShapeType()]++;
1857
1858     TopTools_MapOfShape aMapOfShape;
1859     aMapOfShape.Add(aShape);
1860     TopTools_ListOfShape aListOfShape;
1861     aListOfShape.Append(aShape);
1862
1863     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
1864     for (; itL.More(); itL.Next()) {
1865       TopoDS_Iterator it (itL.Value());
1866       for (; it.More(); it.Next()) {
1867         TopoDS_Shape s = it.Value();
1868         if (aMapOfShape.Add(s)) {
1869           aListOfShape.Append(s);
1870           nbTypes[s.ShapeType()]++;
1871         }
1872       }
1873     }
1874
1875     if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
1876       nbShapes = aMapOfShape.Extent();
1877     else
1878       nbShapes = nbTypes[theShapeType];
1879   }
1880   catch (Standard_Failure) {
1881     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1882     SetErrorCode(aFail->GetMessageString());
1883     return -1;
1884   }
1885
1886   SetErrorCode(OK);
1887   return nbShapes;
1888 }
1889
1890 //=============================================================================
1891 /*!
1892  *  ReverseShape
1893  */
1894 //=============================================================================
1895 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
1896 {
1897   SetErrorCode(KO);
1898
1899   if (theShape.IsNull()) return NULL;
1900
1901   /*
1902   //Add a new reversed object
1903   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
1904
1905   //Add a new Revese function
1906   Handle(GEOM_Function) aFunction;
1907   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
1908   if (aFunction.IsNull()) return NULL;
1909
1910   //Check if the function is set correctly
1911   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
1912
1913   GEOMImpl_IShapes aSI (aFunction);
1914
1915   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
1916   if (aRefShape.IsNull()) return NULL;
1917
1918   aSI.SetBase(aRefShape);
1919
1920   //Compute the sub-shape value
1921   try {
1922     OCC_CATCH_SIGNALS;
1923     if (!GetSolver()->ComputeFunction(aFunction)) {
1924       SetErrorCode("Shape driver failed to reverse shape");
1925       return NULL;
1926     }
1927   }
1928   catch (Standard_Failure) {
1929     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1930     SetErrorCode(aFail->GetMessageString());
1931     return NULL;
1932   }
1933
1934   //Make a Python command
1935   GEOM::TPythonDump(aFunction) << aReversed
1936     << " = geompy.ChangeOrientation(" << theShape << ")";
1937
1938   SetErrorCode(OK);
1939   */
1940
1941   Handle(GEOM_Object) aReversed;
1942
1943   GEOM_Engine* anEngine = GetEngine();
1944   //GEOMImpl_Gen* aGen = dynamic_cast<GEOMImpl_Gen*>(anEngine);
1945   GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine;
1946
1947   if (aGen) {
1948     GEOMImpl_IHealingOperations* anIHealingOperations =
1949       aGen->GetIHealingOperations(GetDocID());
1950     aReversed = anIHealingOperations->ChangeOrientationCopy(theShape);
1951     SetErrorCode(anIHealingOperations->GetErrorCode());
1952   }
1953
1954   return aReversed;
1955 }
1956
1957 //=============================================================================
1958 /*!
1959  *  GetFreeFacesIDs
1960  */
1961 //=============================================================================
1962 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
1963                                                  (Handle(GEOM_Object) theShape)
1964 {
1965   SetErrorCode(KO);
1966
1967   if (theShape.IsNull()) return NULL;
1968   TopoDS_Shape aShape = theShape->GetValue();
1969   if (aShape.IsNull()) return NULL;
1970
1971   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1972
1973   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1974   GEOMImpl_Block6Explorer::MapShapesAndAncestors
1975     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1976
1977   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1978
1979   if (nbFaces == 0) {
1980     SetErrorCode("The given shape has no faces");
1981     return aSeq;
1982   }
1983
1984   TopTools_IndexedMapOfShape anIndices;
1985   TopExp::MapShapes(aShape, anIndices);
1986
1987   Standard_Integer id;
1988   for (; ind <= nbFaces; ind++) {
1989     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1990       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1991       aSeq->Append(id);
1992     }
1993   }
1994
1995   //The explode doesn't change object so no new function is required.
1996   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1997
1998   //Make a Python command
1999   GEOM::TPythonDump(aFunction, /*append=*/true)
2000     << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
2001
2002   SetErrorCode(OK);
2003   return aSeq;
2004 }
2005
2006 //=======================================================================
2007 //function : GetSharedShapes
2008 //purpose  :
2009 //=======================================================================
2010 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2011                                                 (Handle(GEOM_Object)    theShape1,
2012                                                  Handle(GEOM_Object)    theShape2,
2013                                                  const Standard_Integer theShapeType)
2014 {
2015   SetErrorCode(KO);
2016
2017   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
2018
2019   TopoDS_Shape aShape1 = theShape1->GetValue();
2020   TopoDS_Shape aShape2 = theShape2->GetValue();
2021
2022   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
2023
2024   TopTools_IndexedMapOfShape anIndices;
2025   TopExp::MapShapes(aShape1, anIndices);
2026   Handle(TColStd_HArray1OfInteger) anArray;
2027
2028   TopTools_IndexedMapOfShape mapShape1;
2029   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
2030
2031   Handle(GEOM_Object) anObj;
2032   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2033   TCollection_AsciiString anAsciiList, anEntry;
2034
2035   TopTools_MapOfShape mapShape2;
2036   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2037   for (; exp.More(); exp.Next()) {
2038     TopoDS_Shape aSS = exp.Current();
2039     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
2040       anArray = new TColStd_HArray1OfInteger(1,1);
2041       anArray->SetValue(1, anIndices.FindIndex(aSS));
2042       anObj = GetEngine()->AddSubShape(theShape1, anArray);
2043       aSeq->Append(anObj);
2044
2045       // for python command
2046       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2047       anAsciiList += anEntry;
2048       anAsciiList += ",";
2049     }
2050   }
2051
2052   if (aSeq->IsEmpty()) {
2053     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
2054     return aSeq;
2055   }
2056
2057   //Make a Python command
2058   anAsciiList.Trunc(anAsciiList.Length() - 1);
2059
2060   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2061
2062   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2063     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
2064       << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
2065
2066   SetErrorCode(OK);
2067   return aSeq;
2068 }
2069
2070 //=======================================================================
2071 //function : GetSharedShapes
2072 //purpose  :
2073 //=======================================================================
2074 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2075                                      (std::list<Handle(GEOM_Object)> & theShapes,
2076                                       const Standard_Integer           theShapeType)
2077 {
2078   SetErrorCode(KO);
2079
2080   int aLen = theShapes.size();
2081   if (aLen < 1) return NULL;
2082
2083   int ind = 1;
2084   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
2085
2086   Handle(GEOM_Object) aMainObj = *it;
2087   Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
2088
2089   TopTools_SequenceOfShape shapeSeq;
2090   for (; it != theShapes.end(); it++, ind++) {
2091     Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
2092     if (aRefShape.IsNull()) {
2093       SetErrorCode("NULL shape for GetSharedShapes");
2094       return NULL;
2095     }
2096     TopoDS_Shape aShape2 = aRefShape->GetValue();
2097     if (aShape2.IsNull()) return NULL;
2098     shapeSeq.Append( aShape2 );
2099   }
2100
2101   TopoDS_Shape aShape1 = shapeSeq.First();
2102
2103   if ( shapeSeq.Length() == 1 )
2104   {
2105     shapeSeq.Clear();
2106     for ( TopoDS_Iterator it( aShape1); it.More(); it.Next() )
2107       shapeSeq.Append( it.Value() );
2108     aShape1 = shapeSeq.First();
2109   }
2110
2111   TopTools_IndexedMapOfShape anIndices;
2112   TopExp::MapShapes(aMainShape->GetValue(), anIndices);
2113
2114   TopTools_IndexedMapOfShape mapSelected;
2115   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
2116
2117   // Find shared shapes
2118   BRep_Builder B;
2119   TopoDS_Compound aCurrSelection;
2120
2121   for ( ind = 2; ind <= shapeSeq.Length(); ind++) {
2122
2123     TopoDS_Compound aCompound;
2124     B.MakeCompound(aCompound);
2125
2126     const TopoDS_Shape& aShape2 = shapeSeq.Value( ind );
2127
2128     TopTools_MapOfShape mapShape2;
2129     TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2130     for (; exp.More(); exp.Next()) {
2131       const TopoDS_Shape& aSS = exp.Current();
2132       if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
2133         B.Add(aCompound, aSS);
2134       }
2135     }
2136
2137     mapSelected.Clear();
2138     TopExp::MapShapes(aCompound, TopAbs_ShapeEnum(theShapeType), mapSelected);
2139     aCurrSelection = aCompound;
2140   }
2141
2142   // Create GEOM_Object for each found shared shape (collected in aCurrSelection)
2143   Handle(GEOM_Object) anObj, aLastCreated;
2144   Handle(TColStd_HArray1OfInteger) anArray;
2145   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2146   TCollection_AsciiString anAsciiList, anEntry;
2147
2148   TopoDS_Iterator itSel (aCurrSelection, Standard_True, Standard_True);
2149   for (; itSel.More(); itSel.Next()) {
2150     anArray = new TColStd_HArray1OfInteger(1,1);
2151     anArray->SetValue(1, anIndices.FindIndex(itSel.Value()));
2152     anObj = GetEngine()->AddSubShape(aMainObj, anArray);
2153     aSeq->Append(anObj);
2154
2155     aLastCreated = GEOM::GetCreatedLast( aLastCreated, anObj );
2156
2157     // for python command
2158     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2159     anAsciiList += anEntry;
2160     anAsciiList += ",";
2161   }
2162
2163   if (aSeq->IsEmpty()) {
2164     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
2165     return aSeq;
2166   }
2167
2168   // Make a Python command
2169   anAsciiList.Trunc(anAsciiList.Length() - 1);
2170
2171   // IPAL22904: TC6.5.0: order of python commands is wrong after dump study
2172   // Get the function of the latest published object
2173   Handle(GEOM_Function) aFunction = aLastCreated->GetLastFunction();
2174   if( aFunction.IsNull() ) // just in case
2175     aFunction = aMainShape;
2176
2177   GEOM::TPythonDump pd (aFunction, /*append=*/true);
2178   pd << "[" << anAsciiList.ToCString()
2179      << "] = geompy.GetSharedShapesMulti([";
2180
2181   it = theShapes.begin();
2182   pd << (*it++);
2183   while (it != theShapes.end()) {
2184     pd << ", " << (*it++);
2185   }
2186
2187   pd << "], " << TopAbs_ShapeEnum(theShapeType) << ")";
2188
2189   SetErrorCode(OK);
2190   return aSeq;
2191 }
2192
2193 //=============================================================================
2194 /*!
2195  *
2196  */
2197 //=============================================================================
2198 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
2199                                       const GEOMAlgo_State theState)
2200 {
2201   switch (theState) {
2202   case GEOMAlgo_ST_IN:
2203     theDump << "GEOM.ST_IN";
2204     break;
2205   case GEOMAlgo_ST_OUT:
2206     theDump << "GEOM.ST_OUT";
2207     break;
2208   case GEOMAlgo_ST_ON:
2209     theDump << "GEOM.ST_ON";
2210     break;
2211   case GEOMAlgo_ST_ONIN:
2212     theDump << "GEOM.ST_ONIN";
2213     break;
2214   case GEOMAlgo_ST_ONOUT:
2215     theDump << "GEOM.ST_ONOUT";
2216     break;
2217   default:
2218     theDump << "GEOM.ST_UNKNOWN";
2219     break;
2220   }
2221   return theDump;
2222 }
2223
2224 //=======================================================================
2225 //function : checkTypeShapesOn
2226 /*!
2227  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
2228  * \param theShapeType - the shape type to check
2229  * \retval bool  - result of the check
2230  */
2231 //=======================================================================
2232 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
2233 {
2234   if (theShapeType != TopAbs_VERTEX &&
2235       theShapeType != TopAbs_EDGE &&
2236       theShapeType != TopAbs_FACE &&
2237       theShapeType != TopAbs_SOLID) {
2238     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
2239     return false;
2240   }
2241   return true;
2242 }
2243
2244 //=======================================================================
2245 //function : makePlane
2246   /*!
2247    * \brief Creates Geom_Plane
2248     * \param theAx1 - shape object defining plane parameters
2249     * \retval Handle(Geom_Surface) - resulting surface
2250    */
2251 //=======================================================================
2252 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
2253 {
2254   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
2255   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2256   TopoDS_Vertex V1, V2;
2257   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2258   if (V1.IsNull() || V2.IsNull()) {
2259     SetErrorCode("Bad edge given for the plane normal vector");
2260     return NULL;
2261   }
2262   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2263   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2264   if (aVec.Magnitude() < Precision::Confusion()) {
2265     SetErrorCode("Vector with null magnitude given");
2266     return NULL;
2267   }
2268   return new Geom_Plane(aLoc, aVec);
2269 }
2270
2271 //=======================================================================
2272 //function : makeCylinder
2273   /*!
2274    * \brief Creates Geom_CylindricalSurface
2275     * \param theAx1 - edge defining cylinder axis
2276     * \param theRadius - cylinder radius
2277     * \retval Handle(Geom_Surface) - resulting surface
2278    */
2279 //=======================================================================
2280 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
2281                                                               const Standard_Real theRadius)
2282 {
2283   //Axis of the cylinder
2284   if (anAxis.ShapeType() != TopAbs_EDGE) {
2285     SetErrorCode("Not an edge given for the axis");
2286     return NULL;
2287   }
2288   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
2289   TopoDS_Vertex V1, V2;
2290   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2291   if (V1.IsNull() || V2.IsNull()) {
2292     SetErrorCode("Bad edge given for the axis");
2293     return NULL;
2294   }
2295   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2296   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2297   if (aVec.Magnitude() < Precision::Confusion()) {
2298     SetErrorCode("Vector with null magnitude given");
2299     return NULL;
2300   }
2301
2302   gp_Ax3 anAx3 (aLoc, aVec);
2303   return new Geom_CylindricalSurface(anAx3, theRadius);
2304 }
2305
2306 //=======================================================================
2307 //function : getShapesOnBoxIDs
2308   /*!
2309    * \brief Find IDs of sub-shapes complying with given status about surface
2310     * \param theBox - the box to check state of sub-shapes against
2311     * \param theShape - the shape to explore
2312     * \param theShapeType - type of sub-shape of theShape
2313     * \param theState - required state
2314     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2315    */
2316 //=======================================================================
2317 Handle(TColStd_HSequenceOfInteger)
2318   GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2319                                                 const Handle(GEOM_Object)& theShape,
2320                                                 const Standard_Integer theShapeType,
2321                                                 GEOMAlgo_State theState)
2322 {
2323   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2324
2325   TopoDS_Shape aBox = theBox->GetValue();
2326   TopoDS_Shape aShape = theShape->GetValue();
2327
2328   // Check presence of triangulation, build if need
2329   if (!GEOMUtils::CheckTriangulation(aShape)) {
2330     SetErrorCode("Cannot build triangulation on the shape");
2331     return aSeqOfIDs;
2332   }
2333
2334   // Call algo
2335   GEOMAlgo_FinderShapeOn2 aFinder;
2336   Standard_Real aTol = 0.0001; // default value
2337
2338   Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
2339   aClsfBox->SetBox(aBox);
2340
2341   aFinder.SetShape(aShape);
2342   aFinder.SetTolerance(aTol);
2343   aFinder.SetClsf(aClsfBox);
2344   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2345   aFinder.SetState(theState);
2346   aFinder.Perform();
2347
2348   // Interprete results
2349   Standard_Integer iErr = aFinder.ErrorStatus();
2350   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2351   if (iErr) {
2352     MESSAGE(" iErr : " << iErr);
2353     TCollection_AsciiString aMsg (" iErr : ");
2354     aMsg += TCollection_AsciiString(iErr);
2355     SetErrorCode(aMsg);
2356     return aSeqOfIDs;
2357   }
2358   Standard_Integer iWrn = aFinder.WarningStatus();
2359   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2360   if (iWrn) {
2361     MESSAGE(" *** iWrn : " << iWrn);
2362   }
2363
2364   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2365
2366   if (listSS.Extent() < 1) {
2367     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2368     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2369     return aSeqOfIDs;
2370   }
2371
2372   // Fill sequence of object IDs
2373   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2374
2375   TopTools_IndexedMapOfShape anIndices;
2376   TopExp::MapShapes(aShape, anIndices);
2377
2378   TopTools_ListIteratorOfListOfShape itSub (listSS);
2379   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2380     int id = anIndices.FindIndex(itSub.Value());
2381     aSeqOfIDs->Append(id);
2382   }
2383
2384   return aSeqOfIDs;
2385 }
2386
2387 //=======================================================================
2388 //function : GetShapesOnBoxIDs
2389 /*!
2390    * \brief Find sub-shapes complying with given status about surface
2391     * \param theBox - the box to check state of sub-shapes against
2392     * \param theShape - the shape to explore
2393     * \param theShapeType - type of sub-shape of theShape
2394     * \param theState - required state
2395     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2396  */
2397 //=======================================================================
2398 Handle(TColStd_HSequenceOfInteger)
2399     GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2400                                                   const Handle(GEOM_Object)& theShape,
2401                                                   const Standard_Integer theShapeType,
2402                                                   GEOMAlgo_State theState)
2403 {
2404   // Find sub-shapes ids
2405   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2406     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2407   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2408     return NULL;
2409
2410   // The GetShapesOnBox() doesn't change object so no new function is required.
2411   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
2412
2413   // Make a Python command
2414   GEOM::TPythonDump(aFunction, /*append=*/true)
2415     << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
2416     << theBox << ", "
2417     << theShape << ", "
2418     << TopAbs_ShapeEnum(theShapeType) << ", "
2419     << theState << ")";
2420
2421   SetErrorCode(OK);
2422   return aSeqOfIDs;
2423 }
2424
2425 //=======================================================================
2426 //function : GetShapesOnBox
2427 /*!
2428    * \brief Find sub-shapes complying with given status about surface
2429     * \param theBox - the box to check state of sub-shapes against
2430     * \param theShape - the shape to explore
2431     * \param theShapeType - type of sub-shape of theShape
2432     * \param theState - required state
2433     * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2434  */
2435 //=======================================================================
2436 Handle(TColStd_HSequenceOfTransient)
2437     GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
2438                                                const Handle(GEOM_Object)&  theShape,
2439                                                const Standard_Integer theShapeType,
2440                                                GEOMAlgo_State theState)
2441 {
2442   // Find sub-shapes ids
2443   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2444     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2445   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2446     return NULL;
2447
2448   // Find objects by indices
2449   TCollection_AsciiString anAsciiList;
2450   Handle(TColStd_HSequenceOfTransient) aSeq;
2451   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2452   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2453     return NULL;
2454
2455   // Make a Python command
2456
2457   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2458   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2459
2460   GEOM::TPythonDump(aFunction)
2461     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
2462     << theBox << ", "
2463     << theShape << ", "
2464     << TopAbs_ShapeEnum(theShapeType) << ", "
2465     << theState << ")";
2466
2467   SetErrorCode(OK);
2468   return aSeq;
2469 }
2470
2471 //=======================================================================
2472 //function : getShapesOnShapeIDs
2473 /*!
2474  * \brief Find IDs of sub-shapes complying with given status about surface
2475  * \param theCheckShape - the shape to check state of sub-shapes against
2476  * \param theShape - the shape to explore
2477  * \param theShapeType - type of sub-shape of theShape
2478  * \param theState - required state
2479  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2480  */
2481 //=======================================================================
2482 Handle(TColStd_HSequenceOfInteger)
2483   GEOMImpl_IShapesOperations::getShapesOnShapeIDs
2484                                  (const Handle(GEOM_Object)& theCheckShape,
2485                                   const Handle(GEOM_Object)& theShape,
2486                                   const Standard_Integer theShapeType,
2487                                   GEOMAlgo_State theState)
2488 {
2489   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2490
2491   TopoDS_Shape aCheckShape = theCheckShape->GetValue();
2492   TopoDS_Shape aShape = theShape->GetValue();
2493   TopTools_ListOfShape res;
2494
2495   // Check presence of triangulation, build if need
2496   if (!GEOMUtils::CheckTriangulation(aShape)) {
2497     SetErrorCode("Cannot build triangulation on the shape");
2498     return aSeqOfIDs;
2499   }
2500
2501   // Call algo
2502   GEOMAlgo_FinderShapeOn2 aFinder;
2503   Standard_Real aTol = 0.0001; // default value
2504
2505   Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
2506   aClsfSolid->SetShape(aCheckShape);
2507
2508   aFinder.SetShape(aShape);
2509   aFinder.SetTolerance(aTol);
2510   aFinder.SetClsf(aClsfSolid);
2511   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2512   aFinder.SetState(theState);
2513   aFinder.Perform();
2514
2515   // Interprete results
2516   Standard_Integer iErr = aFinder.ErrorStatus();
2517   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2518   if (iErr) {
2519     if (iErr == 41) {
2520       SetErrorCode("theCheckShape must be a solid");
2521     }
2522     else {
2523       MESSAGE(" iErr : " << iErr);
2524       TCollection_AsciiString aMsg (" iErr : ");
2525       aMsg += TCollection_AsciiString(iErr);
2526       SetErrorCode(aMsg);
2527     }
2528     return aSeqOfIDs;
2529   }
2530   Standard_Integer iWrn = aFinder.WarningStatus();
2531   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2532   if (iWrn) {
2533     MESSAGE(" *** iWrn : " << iWrn);
2534   }
2535
2536   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2537
2538   if (listSS.Extent() < 1) {
2539     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2540     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2541   }
2542
2543   // Fill sequence of object IDs
2544   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2545
2546   TopTools_IndexedMapOfShape anIndices;
2547   TopExp::MapShapes(aShape, anIndices);
2548
2549   TopTools_ListIteratorOfListOfShape itSub (listSS);
2550   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2551     int id = anIndices.FindIndex(itSub.Value());
2552     aSeqOfIDs->Append(id);
2553   }
2554
2555   return aSeqOfIDs;
2556 }
2557
2558 //=======================================================================
2559 //function : GetShapesOnShapeIDs
2560 /*!
2561  * \brief Find sub-shapes complying with given status about surface
2562  * \param theCheckShape - the shape to check state of sub-shapes against
2563  * \param theShape - the shape to explore
2564  * \param theShapeType - type of sub-shape of theShape
2565  * \param theState - required state
2566  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2567  */
2568 //=======================================================================
2569 Handle(TColStd_HSequenceOfInteger)
2570     GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
2571                             (const Handle(GEOM_Object)& theCheckShape,
2572                              const Handle(GEOM_Object)& theShape,
2573                              const Standard_Integer theShapeType,
2574                              GEOMAlgo_State theState)
2575 {
2576   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2577     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2578
2579   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2580     return NULL;
2581
2582   // The GetShapesOnShape() doesn't change object so no new function is required.
2583   Handle(GEOM_Function) aFunction =
2584     GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
2585
2586   // Make a Python command
2587   GEOM::TPythonDump(aFunction, /*append=*/true)
2588     << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs("
2589     << theCheckShape << ", "
2590     << theShape << ", "
2591     << TopAbs_ShapeEnum(theShapeType) << ", "
2592     << theState << ")";
2593
2594   SetErrorCode(OK);
2595   return aSeqOfIDs;
2596 }
2597
2598 //=======================================================================
2599 //function : GetShapesOnShape
2600 /*!
2601  * \brief Find sub-shapes complying with given status about surface
2602  * \param theCheckShape - the shape to check state of sub-shapes against
2603  * \param theShape - the shape to explore
2604  * \param theShapeType - type of sub-shape of theShape
2605  * \param theState - required state
2606  * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2607  */
2608 //=======================================================================
2609 Handle(TColStd_HSequenceOfTransient)
2610   GEOMImpl_IShapesOperations::GetShapesOnShape
2611                              (const Handle(GEOM_Object)& theCheckShape,
2612                               const Handle(GEOM_Object)&  theShape,
2613                               const Standard_Integer theShapeType,
2614                               GEOMAlgo_State theState)
2615 {
2616   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2617     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2618   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2619     return NULL;
2620
2621   // Find objects by indices
2622   TCollection_AsciiString anAsciiList;
2623   Handle(TColStd_HSequenceOfTransient) aSeq;
2624   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2625
2626   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2627     return NULL;
2628
2629   // Make a Python command
2630
2631   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2632   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2633
2634   GEOM::TPythonDump(aFunction)
2635     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
2636     << theCheckShape << ", "
2637     << theShape << ", "
2638     << TopAbs_ShapeEnum(theShapeType) << ", "
2639     << theState << ")";
2640
2641   SetErrorCode(OK);
2642   return aSeq;
2643 }
2644
2645 //=======================================================================
2646 //function : GetShapesOnShapeAsCompound
2647 //=======================================================================
2648 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
2649                              (const Handle(GEOM_Object)& theCheckShape,
2650                               const Handle(GEOM_Object)&  theShape,
2651                               const Standard_Integer theShapeType,
2652                               GEOMAlgo_State theState)
2653 {
2654   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2655     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2656
2657   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2658     return NULL;
2659
2660   // Find objects by indices
2661   TCollection_AsciiString anAsciiList;
2662   Handle(TColStd_HSequenceOfTransient) aSeq;
2663   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2664
2665   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2666     return NULL;
2667
2668   TopoDS_Compound aCompound;
2669   BRep_Builder B;
2670   B.MakeCompound(aCompound);
2671   int i = 1;
2672   for(; i<=aSeq->Length(); i++) {
2673     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
2674     TopoDS_Shape aShape_i = anObj->GetValue();
2675     B.Add(aCompound,aShape_i);
2676   }
2677
2678   //Add a new result object
2679   Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
2680   Handle(GEOM_Function) aFunction =
2681     aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
2682   aFunction->SetValue(aCompound);
2683
2684   aSeq->Clear();
2685   aSeq->Append( theCheckShape->GetLastFunction() );
2686   aSeq->Append( theShape->GetLastFunction() );
2687
2688   GEOMImpl_IShapes aCI( aFunction );
2689   aCI.SetShapes( aSeq );
2690   aCI.SetSubShapeType( theShapeType );
2691   aCI.SetTolerance( theState );
2692
2693   GEOM::TPythonDump(aFunction)
2694     << aRes << " = geompy.GetShapesOnShapeAsCompound("
2695     << theCheckShape << ", "
2696     << theShape << ", "
2697     << TopAbs_ShapeEnum(theShapeType) << ", "
2698     << theState << ")";
2699
2700   SetErrorCode(OK);
2701
2702   return aRes;
2703 }
2704
2705 //=======================================================================
2706 //function : getShapesOnSurfaceIDs
2707   /*!
2708    * \brief Find IDs of sub-shapes complying with given status about surface
2709     * \param theSurface - the surface to check state of sub-shapes against
2710     * \param theShape - the shape to explore
2711     * \param theShapeType - type of sub-shape of theShape
2712     * \param theState - required state
2713     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2714    */
2715 //=======================================================================
2716 Handle(TColStd_HSequenceOfInteger)
2717   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
2718                                                     const TopoDS_Shape&         theShape,
2719                                                     TopAbs_ShapeEnum            theShapeType,
2720                                                     GEOMAlgo_State              theState)
2721 {
2722   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2723
2724   // Check presence of triangulation, build if need
2725   if (!GEOMUtils::CheckTriangulation(theShape)) {
2726     SetErrorCode("Cannot build triangulation on the shape");
2727     return aSeqOfIDs;
2728   }
2729
2730   // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
2731   // Compute tolerance
2732   Standard_Real T, VertMax = -RealLast();
2733   try {
2734     OCC_CATCH_SIGNALS;
2735     for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
2736       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
2737       T = BRep_Tool::Tolerance(Vertex);
2738       if (T > VertMax)
2739         VertMax = T;
2740     }
2741   }
2742   catch (Standard_Failure) {
2743     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2744     SetErrorCode(aFail->GetMessageString());
2745     return aSeqOfIDs;
2746   }
2747   // END: Mantis issue 0020961
2748
2749   // Call algo
2750   GEOMAlgo_FinderShapeOn1 aFinder;
2751   //Standard_Real aTol = 0.0001; // default value
2752   Standard_Real aTol = VertMax; // Mantis issue 0020961
2753
2754   aFinder.SetShape(theShape);
2755   aFinder.SetTolerance(aTol);
2756   aFinder.SetSurface(theSurface);
2757   aFinder.SetShapeType(theShapeType);
2758   aFinder.SetState(theState);
2759
2760   // Sets the minimal number of inner points for the faces that do not have own
2761   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
2762   // Default value=3
2763   aFinder.SetNbPntsMin(3);
2764   // Sets the maximal number of inner points for edges or faces.
2765   // It is usefull for the cases when this number is very big (e.g =2000) to improve
2766   // the performance. If this value =0, all inner points will be taken into account.
2767   // Default value=0
2768   aFinder.SetNbPntsMax(100);
2769
2770   aFinder.Perform();
2771
2772   // Interprete results
2773   Standard_Integer iErr = aFinder.ErrorStatus();
2774   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2775   if (iErr) {
2776     MESSAGE(" iErr : " << iErr);
2777     TCollection_AsciiString aMsg (" iErr : ");
2778     aMsg += TCollection_AsciiString(iErr);
2779     SetErrorCode(aMsg);
2780     return aSeqOfIDs;
2781   }
2782   Standard_Integer iWrn = aFinder.WarningStatus();
2783   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2784   if (iWrn) {
2785     MESSAGE(" *** iWrn : " << iWrn);
2786   }
2787
2788   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2789
2790   if (listSS.Extent() < 1) {
2791     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2792     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2793     return aSeqOfIDs;
2794   }
2795
2796   // Fill sequence of object IDs
2797   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2798
2799   TopTools_IndexedMapOfShape anIndices;
2800   TopExp::MapShapes(theShape, anIndices);
2801
2802   TopTools_ListIteratorOfListOfShape itSub (listSS);
2803   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2804     int id = anIndices.FindIndex(itSub.Value());
2805     aSeqOfIDs->Append(id);
2806   }
2807
2808   return aSeqOfIDs;
2809 }
2810
2811 //=======================================================================
2812 //function : getObjectsShapesOn
2813 /*!
2814  * \brief Find shape objects and their entries by their ids
2815  * \param theShapeIDs - incoming shape ids
2816  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
2817  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
2818  */
2819 //=======================================================================
2820 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
2821  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
2822                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
2823                     TCollection_AsciiString &                 theShapeEntries)
2824 {
2825   Handle(TColStd_HSequenceOfTransient) aSeq;
2826
2827   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
2828   {
2829     aSeq = new TColStd_HSequenceOfTransient;
2830     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2831     TCollection_AsciiString anEntry;
2832     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
2833     {
2834       anArray->SetValue(1, theShapeIDs->Value( i ));
2835       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
2836       aSeq->Append( anObj );
2837
2838       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2839       if ( i != 1 ) theShapeEntries += ",";
2840       theShapeEntries += anEntry;
2841     }
2842   }
2843   return aSeq;
2844 }
2845
2846 //=======================================================================
2847 //function : getShapesOnSurface
2848 /*!
2849    * \brief Find sub-shapes complying with given status about surface
2850     * \param theSurface - the surface to check state of sub-shapes against
2851     * \param theShape - the shape to explore
2852     * \param theShapeType - type of sub-shape of theShape
2853     * \param theState - required state
2854     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
2855     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2856  */
2857 //=======================================================================
2858 Handle(TColStd_HSequenceOfTransient)
2859     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
2860                                                    const Handle(GEOM_Object)&  theShape,
2861                                                    TopAbs_ShapeEnum            theShapeType,
2862                                                    GEOMAlgo_State              theState,
2863                                                    TCollection_AsciiString &   theShapeEntries)
2864 {
2865   // Find sub-shapes ids
2866   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2867     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
2868   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2869     return NULL;
2870
2871   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
2872 }
2873
2874 //=============================================================================
2875 /*!
2876  *  GetShapesOnPlane
2877  */
2878 //=============================================================================
2879 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
2880                                         (const Handle(GEOM_Object)& theShape,
2881                                          const Standard_Integer     theShapeType,
2882                                          const Handle(GEOM_Object)& theAx1,
2883                                          const GEOMAlgo_State       theState)
2884 {
2885   SetErrorCode(KO);
2886
2887   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
2888
2889   TopoDS_Shape aShape = theShape->GetValue();
2890   TopoDS_Shape anAx1  = theAx1->GetValue();
2891
2892   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
2893
2894   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2895   if ( !checkTypeShapesOn( theShapeType ))
2896     return NULL;
2897
2898   // Create plane
2899   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
2900   if ( aPlane.IsNull() )
2901     return NULL;
2902
2903   // Find objects
2904   TCollection_AsciiString anAsciiList;
2905   Handle(TColStd_HSequenceOfTransient) aSeq;
2906   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2907   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2908     return NULL;
2909
2910   // Make a Python command
2911
2912   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2913   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2914
2915   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2916     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
2917       << aShapeType << ", " << theAx1 << ", " << theState << ")";
2918
2919   SetErrorCode(OK);
2920   return aSeq;
2921 }
2922
2923 //=============================================================================
2924 /*!
2925  *  GetShapesOnPlaneWithLocation
2926  */
2927 //=============================================================================
2928 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
2929                                         (const Handle(GEOM_Object)& theShape,
2930                                          const Standard_Integer     theShapeType,
2931                                          const Handle(GEOM_Object)& theAx1,
2932                                          const Handle(GEOM_Object)& thePnt,
2933                                          const GEOMAlgo_State       theState)
2934 {
2935   SetErrorCode(KO);
2936
2937   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
2938
2939   TopoDS_Shape aShape = theShape->GetValue();
2940   TopoDS_Shape anAx1  = theAx1->GetValue();
2941   TopoDS_Shape anPnt = thePnt->GetValue();
2942
2943   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
2944
2945   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2946   if ( !checkTypeShapesOn( theShapeType ))
2947     return NULL;
2948
2949   // Create plane
2950   if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
2951   TopoDS_Vertex V1, V2, V3;
2952   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2953   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2954
2955   if (V1.IsNull() || V2.IsNull()) {
2956     SetErrorCode("Bad edge given for the plane normal vector");
2957     return NULL;
2958   }
2959   V3 = TopoDS::Vertex(anPnt);
2960
2961   if(V3.IsNull()) {
2962     SetErrorCode("Bad vertex given for the plane location");
2963       return NULL;
2964   }
2965   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
2966   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
2967
2968   if (aVec.Magnitude() < Precision::Confusion()) {
2969     SetErrorCode("Vector with null magnitude given");
2970     return NULL;
2971   }
2972   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
2973
2974   if ( aPlane.IsNull() )
2975     return NULL;
2976
2977   // Find objects
2978   TCollection_AsciiString anAsciiList;
2979   Handle(TColStd_HSequenceOfTransient) aSeq;
2980   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
2981   if ( aSeq.IsNull() || aSeq->Length() == 0 )
2982     return NULL;
2983
2984   // Make a Python command
2985
2986   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2987   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2988
2989   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2990     << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
2991     << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
2992
2993   SetErrorCode(OK);
2994   return aSeq;
2995 }
2996
2997 //=============================================================================
2998 /*!
2999  *  GetShapesOnCylinder
3000  */
3001 //=============================================================================
3002 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
3003                                           (const Handle(GEOM_Object)& theShape,
3004                                            const Standard_Integer     theShapeType,
3005                                            const Handle(GEOM_Object)& theAxis,
3006                                            const Standard_Real        theRadius,
3007                                            const GEOMAlgo_State       theState)
3008 {
3009   SetErrorCode(KO);
3010
3011   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3012
3013   TopoDS_Shape aShape = theShape->GetValue();
3014   TopoDS_Shape anAxis = theAxis->GetValue();
3015
3016   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3017
3018   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3019   if ( !checkTypeShapesOn( aShapeType ))
3020     return NULL;
3021
3022   // Create a cylinder surface
3023   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3024   if ( aCylinder.IsNull() )
3025     return NULL;
3026
3027   // Find objects
3028   TCollection_AsciiString anAsciiList;
3029   Handle(TColStd_HSequenceOfTransient) aSeq;
3030   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3031   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3032     return NULL;
3033
3034   // Make a Python command
3035
3036   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3037   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3038
3039   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3040     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
3041       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
3042
3043   SetErrorCode(OK);
3044   return aSeq;
3045 }
3046
3047 //=============================================================================
3048 /*!
3049  *  GetShapesOnCylinderWithLocation
3050  */
3051 //=============================================================================
3052 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
3053                                           (const Handle(GEOM_Object)& theShape,
3054                                            const Standard_Integer     theShapeType,
3055                                            const Handle(GEOM_Object)& theAxis,
3056                                            const Handle(GEOM_Object)& thePnt,
3057                                            const Standard_Real        theRadius,
3058                                            const GEOMAlgo_State       theState)
3059 {
3060   SetErrorCode(KO);
3061
3062   if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3063
3064   TopoDS_Shape aShape = theShape->GetValue();
3065   TopoDS_Shape anAxis = theAxis->GetValue();
3066   TopoDS_Shape aPnt   = thePnt->GetValue();
3067
3068   if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3069
3070   if (aPnt.ShapeType() != TopAbs_VERTEX )
3071   {
3072     SetErrorCode("Bottom location point must be vertex");
3073     return NULL;
3074   }
3075
3076   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3077   if ( !checkTypeShapesOn( aShapeType ))
3078     return NULL;
3079
3080   // Create a cylinder surface
3081   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3082   if ( aCylinder.IsNull() )
3083     return NULL;
3084
3085   // translate the surface
3086   Handle(Geom_CylindricalSurface) aCylSurface =
3087     Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3088   if ( aCylSurface.IsNull() )
3089   {
3090     SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3091     return NULL;
3092   }
3093   gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3094   gp_Pnt toLoc   = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3095   aCylinder->Translate( fromLoc, toLoc );
3096
3097   // Find objects
3098   TCollection_AsciiString anAsciiList;
3099   Handle(TColStd_HSequenceOfTransient) aSeq;
3100   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3101   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3102     return NULL;
3103
3104   // Make a Python command
3105
3106   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3107   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3108
3109   GEOM::TPythonDump(aFunction)
3110     << "[" << anAsciiList.ToCString()
3111     << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
3112     << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
3113
3114   SetErrorCode(OK);
3115   return aSeq;
3116 }
3117
3118 //=============================================================================
3119 /*!
3120  *  GetShapesOnSphere
3121  */
3122 //=============================================================================
3123 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
3124                                           (const Handle(GEOM_Object)& theShape,
3125                                            const Standard_Integer     theShapeType,
3126                                            const Handle(GEOM_Object)& theCenter,
3127                                            const Standard_Real        theRadius,
3128                                            const GEOMAlgo_State       theState)
3129 {
3130   SetErrorCode(KO);
3131
3132   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3133
3134   TopoDS_Shape aShape  = theShape->GetValue();
3135   TopoDS_Shape aCenter = theCenter->GetValue();
3136
3137   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3138
3139   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3140   if ( !checkTypeShapesOn( aShapeType ))
3141     return NULL;
3142
3143   // Center of the sphere
3144   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3145   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3146
3147   gp_Ax3 anAx3 (aLoc, gp::DZ());
3148   Handle(Geom_SphericalSurface) aSphere =
3149     new Geom_SphericalSurface(anAx3, theRadius);
3150
3151   // Find objects
3152   TCollection_AsciiString anAsciiList;
3153   Handle(TColStd_HSequenceOfTransient) aSeq;
3154   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
3155   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3156     return NULL;
3157
3158   // Make a Python command
3159
3160   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3161   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3162
3163   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3164     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
3165       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
3166
3167   SetErrorCode(OK);
3168   return aSeq;
3169 }
3170
3171 //=============================================================================
3172 /*!
3173  *  GetShapesOnPlaneIDs
3174  */
3175 //=============================================================================
3176 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
3177                                         (const Handle(GEOM_Object)& theShape,
3178                                          const Standard_Integer     theShapeType,
3179                                          const Handle(GEOM_Object)& theAx1,
3180                                          const GEOMAlgo_State       theState)
3181 {
3182   SetErrorCode(KO);
3183
3184   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3185
3186   TopoDS_Shape aShape = theShape->GetValue();
3187   TopoDS_Shape anAx1  = theAx1->GetValue();
3188
3189   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3190
3191   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3192   if ( !checkTypeShapesOn( aShapeType ))
3193     return NULL;
3194
3195   // Create plane
3196   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3197   if ( aPlane.IsNull() )
3198     return NULL;
3199
3200   // Find object IDs
3201   Handle(TColStd_HSequenceOfInteger) aSeq;
3202   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3203
3204   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3205   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3206
3207   // Make a Python command
3208   GEOM::TPythonDump(aFunction, /*append=*/true)
3209     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
3210     << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
3211
3212   SetErrorCode(OK);
3213   return aSeq;
3214 }
3215
3216 //=============================================================================
3217 /*!
3218  *  GetShapesOnPlaneWithLocationIDs
3219  */
3220 //=============================================================================
3221 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
3222                                         (const Handle(GEOM_Object)& theShape,
3223                                          const Standard_Integer     theShapeType,
3224                                          const Handle(GEOM_Object)& theAx1,
3225                                          const Handle(GEOM_Object)& thePnt,
3226                                          const GEOMAlgo_State       theState)
3227 {
3228   SetErrorCode(KO);
3229
3230   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3231
3232   TopoDS_Shape aShape = theShape->GetValue();
3233   TopoDS_Shape anAx1  = theAx1->GetValue();
3234   TopoDS_Shape anPnt  = thePnt->GetValue();
3235
3236   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3237
3238   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3239   if ( !checkTypeShapesOn( aShapeType ))
3240     return NULL;
3241
3242   // Create plane
3243   if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
3244   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3245   TopoDS_Vertex V1, V2, V3;
3246   TopExp::Vertices(anEdge, V1, V2, Standard_True);
3247   if (V1.IsNull() || V2.IsNull()) {
3248     SetErrorCode("Bad edge given for the plane normal vector");
3249     return NULL;
3250   }
3251   V3 = TopoDS::Vertex(anPnt);
3252   if(V3.IsNull()) {
3253     SetErrorCode("Bad vertex given for the plane location");
3254       return NULL;
3255   }
3256   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3257   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3258   if (aVec.Magnitude() < Precision::Confusion()) {
3259     SetErrorCode("Vector with null magnitude given");
3260     return NULL;
3261   }
3262
3263   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3264   if ( aPlane.IsNull() )
3265     return NULL;
3266
3267   // Find object IDs
3268   Handle(TColStd_HSequenceOfInteger) aSeq;
3269   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3270
3271   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3272   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3273
3274   // Make a Python command
3275   GEOM::TPythonDump(aFunction, /*append=*/true)
3276     << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
3277     << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
3278
3279   SetErrorCode(OK);
3280   return aSeq;
3281 }
3282
3283 //=============================================================================
3284 /*!
3285  *  GetShapesOnCylinderIDs
3286  */
3287 //=============================================================================
3288 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
3289                                           (const Handle(GEOM_Object)& theShape,
3290                                            const Standard_Integer     theShapeType,
3291                                            const Handle(GEOM_Object)& theAxis,
3292                                            const Standard_Real        theRadius,
3293                                            const GEOMAlgo_State       theState)
3294 {
3295   SetErrorCode(KO);
3296
3297   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3298
3299   TopoDS_Shape aShape = theShape->GetValue();
3300   TopoDS_Shape anAxis = theAxis->GetValue();
3301
3302   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3303
3304   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3305   if ( !checkTypeShapesOn( aShapeType ))
3306     return NULL;
3307
3308   // Create a cylinder surface
3309   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3310   if ( aCylinder.IsNull() )
3311     return NULL;
3312
3313   // Find object IDs
3314   Handle(TColStd_HSequenceOfInteger) aSeq;
3315   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
3316
3317   // The GetShapesOnCylinder() doesn't change object so no new function is required.
3318   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
3319
3320   // Make a Python command
3321   GEOM::TPythonDump(aFunction, /*append=*/true)
3322     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
3323     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
3324     << theRadius << ", " << theState << ")";
3325
3326   SetErrorCode(OK);
3327   return aSeq;
3328 }
3329
3330 //=============================================================================
3331 /*!
3332  *  GetShapesOnCylinderWithLocationIDs
3333  */
3334 //=============================================================================
3335 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
3336                                           (const Handle(GEOM_Object)& theShape,
3337                                            const Standard_Integer     theShapeType,
3338                                            const Handle(GEOM_Object)& theAxis,
3339                                            const Handle(GEOM_Object)& thePnt,
3340                                            const Standard_Real        theRadius,
3341                                            const GEOMAlgo_State       theState)
3342 {
3343   SetErrorCode(KO);
3344
3345   if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3346
3347   TopoDS_Shape aShape = theShape->GetValue();
3348   TopoDS_Shape anAxis = theAxis->GetValue();
3349   TopoDS_Shape aPnt   = thePnt->GetValue();
3350
3351   if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3352
3353   if (aPnt.ShapeType() != TopAbs_VERTEX )
3354   {
3355     SetErrorCode("Bottom location point must be vertex");
3356     return NULL;
3357   }
3358
3359   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3360   if ( !checkTypeShapesOn( aShapeType ))
3361     return NULL;
3362
3363   // Create a cylinder surface
3364   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3365   if ( aCylinder.IsNull() )
3366     return NULL;
3367
3368   // translate the surface
3369   Handle(Geom_CylindricalSurface) aCylSurface =
3370     Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3371   if ( aCylSurface.IsNull() )
3372   {
3373     SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3374     return NULL;
3375   }
3376   gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3377   gp_Pnt toLoc   = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3378   aCylinder->Translate( fromLoc, toLoc );
3379
3380   // Find object IDs
3381   Handle(TColStd_HSequenceOfInteger) aSeq;
3382   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
3383
3384   // The GetShapesOnCylinder() doesn't change object so no new function is required.
3385   Handle(GEOM_Function) aFunction =
3386     GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
3387
3388   // Make a Python command
3389   GEOM::TPythonDump(aFunction, /*append=*/true)
3390     << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
3391     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
3392     << thePnt << ", " << theRadius << ", " << theState << ")";
3393
3394   SetErrorCode(OK);
3395   return aSeq;
3396 }
3397
3398 //=============================================================================
3399 /*!
3400  *  GetShapesOnSphereIDs
3401  */
3402 //=============================================================================
3403 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
3404                                           (const Handle(GEOM_Object)& theShape,
3405                                            const Standard_Integer     theShapeType,
3406                                            const Handle(GEOM_Object)& theCenter,
3407                                            const Standard_Real        theRadius,
3408                                            const GEOMAlgo_State       theState)
3409 {
3410   SetErrorCode(KO);
3411
3412   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3413
3414   TopoDS_Shape aShape  = theShape->GetValue();
3415   TopoDS_Shape aCenter = theCenter->GetValue();
3416
3417   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3418
3419   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3420   if ( !checkTypeShapesOn( aShapeType ))
3421     return NULL;
3422
3423   // Center of the sphere
3424   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3425   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3426
3427   gp_Ax3 anAx3 (aLoc, gp::DZ());
3428   Handle(Geom_SphericalSurface) aSphere =
3429     new Geom_SphericalSurface(anAx3, theRadius);
3430
3431   // Find object IDs
3432   Handle(TColStd_HSequenceOfInteger) aSeq;
3433   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
3434
3435   // The GetShapesOnSphere() doesn't change object so no new function is required.
3436   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
3437
3438   // Make a Python command
3439   GEOM::TPythonDump(aFunction, /*append=*/true)
3440     << "listShapesOnCylinder = geompy.GetShapesOnSphereIDs"
3441     << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
3442     << theRadius << ", " << theState << ")";
3443
3444   SetErrorCode(OK);
3445   return aSeq;
3446 }
3447
3448 //=======================================================================
3449 //function : getShapesOnQuadrangleIDs
3450   /*!
3451    * \brief Find IDs of sub-shapes complying with given status about quadrangle
3452     * \param theShape - the shape to explore
3453     * \param theShapeType - type of sub-shape of theShape
3454     * \param theTopLeftPoint - top left quadrangle corner
3455     * \param theTopRigthPoint - top right quadrangle corner
3456     * \param theBottomLeftPoint - bottom left quadrangle corner
3457     * \param theBottomRigthPoint - bottom right quadrangle corner
3458     * \param theState - required state
3459     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3460    */
3461 //=======================================================================
3462 Handle(TColStd_HSequenceOfInteger)
3463   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
3464                                                         const Standard_Integer     theShapeType,
3465                                                         const Handle(GEOM_Object)& theTopLeftPoint,
3466                                                         const Handle(GEOM_Object)& theTopRigthPoint,
3467                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
3468                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
3469                                                         const GEOMAlgo_State       theState)
3470 {
3471   SetErrorCode(KO);
3472
3473   if ( theShape.IsNull() ||
3474        theTopLeftPoint.IsNull() ||
3475        theTopRigthPoint.IsNull() ||
3476        theBottomLeftPoint.IsNull() ||
3477        theBottomRigthPoint.IsNull() )
3478     return NULL;
3479
3480   TopoDS_Shape aShape = theShape->GetValue();
3481   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
3482   TopoDS_Shape aTR = theTopRigthPoint->GetValue();
3483   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
3484   TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
3485
3486   if (aShape.IsNull() ||
3487       aTL.IsNull() ||
3488       aTR.IsNull() ||
3489       aBL.IsNull() ||
3490       aBR.IsNull() ||
3491       aTL.ShapeType() != TopAbs_VERTEX ||
3492       aTR.ShapeType() != TopAbs_VERTEX ||
3493       aBL.ShapeType() != TopAbs_VERTEX ||
3494       aBR.ShapeType() != TopAbs_VERTEX )
3495     return NULL;
3496
3497   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3498   if ( !checkTypeShapesOn( aShapeType ))
3499     return NULL;
3500
3501   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3502
3503   // Check presence of triangulation, build if need
3504   if (!GEOMUtils::CheckTriangulation(aShape)) {
3505     SetErrorCode("Cannot build triangulation on the shape");
3506     return aSeqOfIDs;
3507   }
3508
3509   // Call algo
3510   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
3511   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
3512   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
3513   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
3514
3515   GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
3516   Standard_Real aTol = 0.0001; // default value
3517
3518   aFinder.SetShape(aShape);
3519   aFinder.SetTolerance(aTol);
3520   //aFinder.SetSurface(theSurface);
3521   aFinder.SetShapeType(aShapeType);
3522   aFinder.SetState(theState);
3523
3524   // Sets the minimal number of inner points for the faces that do not have own
3525   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
3526   // Default value=3
3527   aFinder.SetNbPntsMin(3);
3528   // Sets the maximal number of inner points for edges or faces.
3529   // It is usefull for the cases when this number is very big (e.g =2000) to improve
3530   // the performance. If this value =0, all inner points will be taken into account.
3531   // Default value=0
3532   aFinder.SetNbPntsMax(100);
3533
3534   aFinder.Perform();
3535
3536   // Interprete results
3537   Standard_Integer iErr = aFinder.ErrorStatus();
3538   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
3539   if (iErr) {
3540     MESSAGE(" iErr : " << iErr);
3541     TCollection_AsciiString aMsg (" iErr : ");
3542     aMsg += TCollection_AsciiString(iErr);
3543     SetErrorCode(aMsg);
3544     return aSeqOfIDs;
3545   }
3546   Standard_Integer iWrn = aFinder.WarningStatus();
3547   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
3548   if (iWrn) {
3549     MESSAGE(" *** iWrn : " << iWrn);
3550   }
3551
3552   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
3553
3554   if (listSS.Extent() < 1) {
3555     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
3556     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
3557     return aSeqOfIDs;
3558   }
3559
3560   // Fill sequence of object IDs
3561   aSeqOfIDs = new TColStd_HSequenceOfInteger;
3562
3563   TopTools_IndexedMapOfShape anIndices;
3564   TopExp::MapShapes(aShape, anIndices);
3565
3566   TopTools_ListIteratorOfListOfShape itSub (listSS);
3567   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3568     int id = anIndices.FindIndex(itSub.Value());
3569     aSeqOfIDs->Append(id);
3570   }
3571   return aSeqOfIDs;
3572 }
3573
3574 //=======================================================================
3575 //function : GetShapesOnQuadrangle
3576   /*!
3577    * \brief Find sub-shapes complying with given status about quadrangle
3578     * \param theShape - the shape to explore
3579     * \param theShapeType - type of sub-shape of theShape
3580     * \param theTopLeftPoint - top left quadrangle corner
3581     * \param theTopRigthPoint - top right quadrangle corner
3582     * \param theBottomLeftPoint - bottom left quadrangle corner
3583     * \param theBottomRigthPoint - bottom right quadrangle corner
3584     * \param theState - required state
3585     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3586    */
3587 //=======================================================================
3588 Handle(TColStd_HSequenceOfTransient)
3589     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
3590                                                        const Standard_Integer     theShapeType,
3591                                                        const Handle(GEOM_Object)& theTopLeftPoint,
3592                                                        const Handle(GEOM_Object)& theTopRigthPoint,
3593                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
3594                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
3595                                                        const GEOMAlgo_State       theState)
3596 {
3597   // Find indices
3598   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3599     getShapesOnQuadrangleIDs( theShape,
3600                               theShapeType,
3601                               theTopLeftPoint,
3602                               theTopRigthPoint,
3603                               theBottomLeftPoint,
3604                               theBottomRigthPoint,
3605                               theState);
3606   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
3607     return NULL;
3608
3609   // Find objects by indices
3610   TCollection_AsciiString anAsciiList;
3611   Handle(TColStd_HSequenceOfTransient) aSeq;
3612   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
3613   if ( aSeq.IsNull() || aSeq->IsEmpty() )
3614     return NULL;
3615
3616   // Make a Python command
3617
3618   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3619   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3620
3621   GEOM::TPythonDump(aFunction)
3622     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
3623     << theShape << ", "
3624     << TopAbs_ShapeEnum(theShapeType) << ", "
3625     << theTopLeftPoint << ", "
3626     << theTopRigthPoint << ", "
3627     << theBottomLeftPoint << ", "
3628     << theBottomRigthPoint << ", "
3629     << theState << ")";
3630
3631   SetErrorCode(OK);
3632   return aSeq;
3633 }
3634
3635 //=======================================================================
3636 //function : GetShapesOnQuadrangleIDs
3637   /*!
3638    * \brief Find IDs of sub-shapes complying with given status about quadrangle
3639     * \param theShape - the shape to explore
3640     * \param theShapeType - type of sub-shape of theShape
3641     * \param theTopLeftPoint - top left quadrangle corner
3642     * \param theTopRigthPoint - top right quadrangle corner
3643     * \param theBottomLeftPoint - bottom left quadrangle corner
3644     * \param theBottomRigthPoint - bottom right quadrangle corner
3645     * \param theState - required state
3646     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3647    */
3648 //=======================================================================
3649 Handle(TColStd_HSequenceOfInteger)
3650   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
3651                                                         const Standard_Integer     theShapeType,
3652                                                         const Handle(GEOM_Object)& theTopLeftPoint,
3653                                                         const Handle(GEOM_Object)& theTopRigthPoint,
3654                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
3655                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
3656                                                         const GEOMAlgo_State       theState)
3657 {
3658   // Find indices
3659   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3660     getShapesOnQuadrangleIDs( theShape,
3661                               theShapeType,
3662                               theTopLeftPoint,
3663                               theTopRigthPoint,
3664                               theBottomLeftPoint,
3665                               theBottomRigthPoint,
3666                               theState);
3667   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
3668     return NULL;
3669
3670   // Make a Python command
3671
3672   // The GetShapesOnCylinder() doesn't change object so no new function is required.
3673   Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
3674   lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
3675   lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
3676   lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
3677   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
3678
3679   GEOM::TPythonDump(aFunction, /*append=*/true)
3680     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
3681     << theShape << ", "
3682     << TopAbs_ShapeEnum(theShapeType) << ", "
3683     << theTopLeftPoint << ", "
3684     << theTopRigthPoint << ", "
3685     << theBottomLeftPoint << ", "
3686     << theBottomRigthPoint << ", "
3687     << theState << ")";
3688
3689   SetErrorCode(OK);
3690   return aSeqOfIDs;
3691 }
3692
3693 //=============================================================================
3694 /*!
3695  *  GetInPlaceOfShape
3696  */
3697 //=============================================================================
3698 static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
3699                                const TopTools_IndexedMapOfShape& theWhereIndices,
3700                                const TopoDS_Shape& theWhat,
3701                                TColStd_ListOfInteger& theModifiedList)
3702 {
3703   if (theWhereFunction.IsNull() || theWhat.IsNull()) return false;
3704
3705   if (theWhereIndices.Contains(theWhat)) {
3706     // entity was not changed by the operation
3707     Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
3708     theModifiedList.Append(aWhatIndex);
3709     return true;
3710   }
3711
3712   // try to find in history
3713   TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
3714
3715   // search in history for all argument shapes
3716   Standard_Boolean isFound = Standard_False;
3717   Standard_Boolean isGood = Standard_False;
3718
3719   TDF_LabelSequence aLabelSeq;
3720   theWhereFunction->GetDependency(aLabelSeq);
3721   Standard_Integer nbArg = aLabelSeq.Length();
3722
3723   for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
3724
3725     TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
3726
3727     Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
3728     TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
3729
3730     TopTools_IndexedMapOfShape anArgumentIndices;
3731     TopExp::MapShapes(anArgumentShape, anArgumentIndices);
3732
3733     if (anArgumentIndices.Contains(theWhat)) {
3734       isFound = Standard_True;
3735       Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
3736
3737       // Find corresponding label in history
3738       TDF_Label anArgumentHistoryLabel =
3739         theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
3740       if (anArgumentHistoryLabel.IsNull()) {
3741         // Lost History of operation argument. Possibly, all its entities was removed.
3742         isGood = Standard_True;
3743       }
3744       else {
3745         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
3746
3747         if (aWhatHistoryLabel.IsNull()) {
3748           // Removed entity ? Compound ? Compsolid ? Shell ? Wire
3749           isGood = Standard_False;
3750         } else {
3751           Handle(TDataStd_IntegerArray) anIntegerArray;
3752           if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
3753             //Error: Empty modifications history for the sought shape.
3754             isGood = Standard_False;
3755           }
3756           else {
3757             isGood = Standard_True;
3758             Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
3759             for (imod = 1; imod <= aModifLen; imod++) {
3760               theModifiedList.Append(anIntegerArray->Array()->Value(imod));
3761             }
3762           }
3763         }
3764       }
3765     }
3766   }
3767
3768   isFound = isGood;
3769
3770   if (!isFound) {
3771     // try compound/compsolid/shell/wire element by element
3772     bool isFoundAny = false;
3773     TopTools_MapOfShape mapShape;
3774
3775     if (theWhat.ShapeType() == TopAbs_COMPOUND ||
3776         theWhat.ShapeType() == TopAbs_COMPSOLID) {
3777       // recursive processing of compound/compsolid
3778       TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
3779       for (; anIt.More(); anIt.Next()) {
3780         if (mapShape.Add(anIt.Value())) {
3781           TopoDS_Shape curWhat = anIt.Value();
3782           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3783           if (isFoundAny) isFound = Standard_True;
3784         }
3785       }
3786     }
3787     else if (theWhat.ShapeType() == TopAbs_SHELL) {
3788       // try to replace a shell by its faces images
3789       TopExp_Explorer anExp (theWhat, TopAbs_FACE);
3790       for (; anExp.More(); anExp.Next()) {
3791         if (mapShape.Add(anExp.Current())) {
3792           TopoDS_Shape curWhat = anExp.Current();
3793           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3794           if (isFoundAny) isFound = Standard_True;
3795         }
3796       }
3797     }
3798     else if (theWhat.ShapeType() == TopAbs_WIRE) {
3799       // try to replace a wire by its edges images
3800       TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
3801       for (; anExp.More(); anExp.Next()) {
3802         if (mapShape.Add(anExp.Current())) {
3803           TopoDS_Shape curWhat = anExp.Current();
3804           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
3805           if (isFoundAny) isFound = Standard_True;
3806         }
3807       }
3808     }
3809     else {
3810       // Removed entity
3811     }
3812   }
3813
3814   return isFound;
3815 }
3816
3817 //=============================================================================
3818 /*!
3819  *  GetShapeProperties
3820  */
3821 //=============================================================================
3822 void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[],
3823                                                      gp_Pnt & aVertex )
3824 {
3825   GProp_GProps theProps;
3826   gp_Pnt aCenterMass;
3827   //TopoDS_Shape aPntShape;
3828   Standard_Real aShapeSize;
3829
3830   if    (aShape.ShapeType() == TopAbs_VERTEX) aCenterMass = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) );
3831   else if (aShape.ShapeType() == TopAbs_EDGE) BRepGProp::LinearProperties(aShape,  theProps);
3832   else if (aShape.ShapeType() == TopAbs_FACE) BRepGProp::SurfaceProperties(aShape, theProps);
3833   else                                        BRepGProp::VolumeProperties(aShape,  theProps);
3834
3835   if (aShape.ShapeType() == TopAbs_VERTEX)
3836     aShapeSize = 1;
3837   else {
3838     aCenterMass = theProps.CentreOfMass();
3839     aShapeSize  = theProps.Mass();
3840   }
3841
3842 //   aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
3843 //   aVertex   = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) );
3844   aVertex = aCenterMass;
3845   tab[0] = aVertex.X();
3846   tab[1] = aVertex.Y();
3847   tab[2] = aVertex.Z();
3848   tab[3] = aShapeSize;
3849   return;
3850 }
3851
3852 namespace {
3853
3854   //================================================================================
3855   /*!
3856    * \brief Return normal to face at extrema point
3857    */
3858   //================================================================================
3859
3860   gp_Vec GetNormal (const TopoDS_Face& face, const BRepExtrema_DistShapeShape& extrema)
3861   {
3862     gp_Vec defaultNorm(1,0,0); // to have same normals on different faces
3863     try {
3864       // get UV at extrema point
3865       Standard_Real u,v, f,l;
3866       switch ( extrema.SupportTypeShape2(1) ) {
3867       case BRepExtrema_IsInFace: {
3868         extrema.ParOnFaceS2(1, u, v );
3869         break;
3870       }
3871       case BRepExtrema_IsOnEdge: {
3872         TopoDS_Edge edge = TopoDS::Edge( extrema.SupportOnShape2(1));
3873         Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f,l );
3874         extrema.ParOnEdgeS2( 1, u );
3875         gp_Pnt2d uv = pcurve->Value( u );
3876         u = uv.Coord(1);
3877         v = uv.Coord(2);
3878         break;
3879       }
3880       case BRepExtrema_IsVertex: return defaultNorm;
3881       }
3882       // get derivatives
3883       BRepAdaptor_Surface surface( face, false );
3884       gp_Vec du, dv; gp_Pnt p;
3885       surface.D1( u, v, p, du, dv );
3886
3887       return du ^ dv;
3888
3889     } catch (Standard_Failure ) {
3890     }
3891     return defaultNorm;
3892   }
3893 }
3894
3895 //=============================================================================
3896 /*!
3897  *  case GetInPlace:
3898  *  default:
3899  */
3900 //=============================================================================
3901 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
3902                                                             Handle(GEOM_Object) theShapeWhat)
3903 {
3904   SetErrorCode(KO);
3905
3906   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
3907
3908   TopoDS_Shape aWhere = theShapeWhere->GetValue();
3909   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
3910
3911   if (aWhere.IsNull() || aWhat.IsNull()) {
3912     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
3913     return NULL;
3914   }
3915
3916   // Compute confusion tolerance.
3917   Standard_Real    aTolConf = Precision::Confusion();
3918   Standard_Integer i;
3919
3920   for (i = 0; i < 2; ++i) {
3921     TopExp_Explorer anExp(i == 0 ? aWhere : aWhat, TopAbs_VERTEX);
3922
3923     for (; anExp.More(); anExp.Next()) {
3924       const TopoDS_Vertex aVtx = TopoDS::Vertex(anExp.Current());
3925       const Standard_Real aTolVtx = BRep_Tool::Tolerance(aVtx);
3926
3927       if (aTolVtx > aTolConf) {
3928         aTolConf = aTolVtx;
3929       }
3930     }
3931   }
3932
3933   // Compute mass tolerance.
3934   Bnd_Box       aBoundingBox;
3935   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
3936   Standard_Real aMassTol;
3937
3938   BRepBndLib::Add(aWhere, aBoundingBox);
3939   BRepBndLib::Add(aWhat,  aBoundingBox);
3940   aBoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
3941   aMassTol = Max(aXmax - aXmin, aYmax - aYmin);
3942   aMassTol = Max(aMassTol, aZmax - aZmin);
3943   aMassTol *= aTolConf;
3944
3945   // Searching for the sub-shapes inside the ShapeWhere shape
3946   GEOMAlgo_GetInPlace aGIP;
3947   aGIP.SetTolerance(aTolConf);
3948   aGIP.SetTolMass(aMassTol);
3949   aGIP.SetTolCG(aTolConf);
3950
3951   aGIP.SetArgument(aWhat);
3952   aGIP.SetShapeWhere(aWhere);
3953
3954   aGIP.Perform();
3955   int iErr = aGIP.ErrorStatus();
3956   if (iErr) {
3957     SetErrorCode("Error in GEOMAlgo_GetInPlace");
3958     return NULL;
3959   }
3960
3961   // Add direct result.
3962   TopTools_ListOfShape        aLSA;
3963   const TopoDS_Shape         &aShapeResult = aGIP.Result();
3964   TopTools_MapOfShape         aMFence;
3965   TopTools_IndexedMapOfShape  aWhereIndices;
3966
3967   TopExp::MapShapes(aWhere, aWhereIndices);
3968
3969   if (aShapeResult.IsNull() == Standard_False) {
3970     TopoDS_Iterator anIt(aShapeResult);
3971
3972     for (; anIt.More(); anIt.Next()) {
3973       const TopoDS_Shape &aPart = anIt.Value();
3974
3975       if(aWhereIndices.Contains(aPart) && aMFence.Add(aPart)) {
3976         aLSA.Append(aPart);
3977       }
3978     }
3979   }
3980
3981   if (aLSA.Extent() == 0) {
3982     SetErrorCode(NOT_FOUND_ANY); // Not found any Results
3983     return NULL;
3984   }
3985
3986   Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent());
3987   TopTools_ListIteratorOfListOfShape anIterModif (aLSA);
3988   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
3989     if (aWhereIndices.Contains(anIterModif.Value())) {
3990       aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value()));
3991     }
3992     else {
3993       SetErrorCode("Error: wrong sub-shape returned");
3994       return NULL;
3995     }
3996   }
3997
3998   //Add a new object
3999   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4000   if (aResult.IsNull()) {
4001     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4002     return NULL;
4003   }
4004
4005   if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) {
4006     //Set a GROUP type
4007     aResult->SetType(GEOM_GROUP);
4008
4009     //Set a sub-shape type
4010     TopoDS_Shape aFirstFound = aLSA.First();
4011     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4012
4013     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4014     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4015   }
4016
4017   //Make a Python command
4018   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4019
4020   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4021     << theShapeWhere << ", " << theShapeWhat << ", True)";
4022
4023   SetErrorCode(OK);
4024   return aResult;
4025 }
4026
4027 //=============================================================================
4028 /*!
4029  *  case GetInPlaceOld:
4030  *  default:
4031  */
4032 //=============================================================================
4033 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld (Handle(GEOM_Object) theShapeWhere,
4034                                                                Handle(GEOM_Object) theShapeWhat)
4035 {
4036   SetErrorCode(KO);
4037
4038   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4039
4040   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4041   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4042   TopoDS_Shape aPntShape;
4043   TopoDS_Vertex aVertex;
4044
4045   if (aWhere.IsNull() || aWhat.IsNull()) {
4046     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4047     return NULL;
4048   }
4049
4050   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4051   if (aWhereFunction.IsNull()) {
4052     SetErrorCode("Error: aWhereFunction is Null.");
4053     return NULL;
4054   }
4055
4056   TopTools_IndexedMapOfShape aWhereIndices;
4057   TopExp::MapShapes(aWhere, aWhereIndices);
4058
4059   TColStd_ListOfInteger aModifiedList;
4060   Standard_Integer aWhereIndex;
4061   Handle(TColStd_HArray1OfInteger) aModifiedArray;
4062   Handle(GEOM_Object) aResult;
4063
4064   bool isFound = false;
4065   TopAbs_ShapeEnum iType = TopAbs_SOLID;
4066   //Standard_Real    aWhat_Mass = 0., aWhere_Mass = 0.;
4067   Standard_Real    tab_aWhat[4],    tab_aWhere[4];
4068   Standard_Real    dl_l = 1e-3;
4069   Standard_Real    min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
4070   Standard_Real    aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
4071   Bnd_Box          BoundingBox;
4072   gp_Pnt           aPnt, aPnt_aWhat, tab_Pnt[2];
4073   GProp_GProps     aProps;
4074
4075   // Find the iType of the aWhat shape
4076   /*
4077   if      ( aWhat.ShapeType() == TopAbs_VERTEX )                                         iType = TopAbs_VERTEX;
4078   else if ( aWhat.ShapeType() == TopAbs_EDGE  || aWhat.ShapeType() == TopAbs_WIRE )      iType = TopAbs_EDGE;
4079   else if ( aWhat.ShapeType() == TopAbs_FACE  || aWhat.ShapeType() == TopAbs_SHELL )     iType = TopAbs_FACE;
4080   else if ( aWhat.ShapeType() == TopAbs_SOLID || aWhat.ShapeType() == TopAbs_COMPSOLID ) iType = TopAbs_SOLID;
4081   else if ( aWhat.ShapeType() == TopAbs_COMPOUND ) {
4082     // Only the iType of the first shape in the compound is taken into account
4083     TopoDS_Iterator It (aWhat, Standard_False, Standard_False);
4084     if ( !It.More() ) {
4085       SetErrorCode("Error: theShapeWhat is an empty COMPOUND.");
4086       return NULL;
4087     }
4088     TopAbs_ShapeEnum compType = It.Value().ShapeType();
4089     if      ( compType == TopAbs_VERTEX )                               iType = TopAbs_VERTEX;
4090     else if ( compType == TopAbs_EDGE  || compType == TopAbs_WIRE )     iType = TopAbs_EDGE;
4091     else if ( compType == TopAbs_FACE  || compType == TopAbs_SHELL)     iType = TopAbs_FACE;
4092     else if ( compType == TopAbs_SOLID || compType == TopAbs_COMPSOLID) iType = TopAbs_SOLID;
4093   }
4094   else {
4095     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
4096     return NULL;
4097   }
4098   */
4099   iType = GEOMUtils::GetTypeOfSimplePart(aWhat);
4100   if (iType == TopAbs_SHAPE) {
4101     SetErrorCode("Error: An attempt to extract a shape of not supported type.");
4102     return NULL;
4103   }
4104
4105   TopExp_Explorer Exp_aWhat  ( aWhat,  iType );
4106   TopExp_Explorer Exp_aWhere ( aWhere, iType );
4107   TopExp_Explorer Exp_Edge   ( aWhere, TopAbs_EDGE );
4108
4109   // Find the shortest edge in theShapeWhere shape
4110   BRepBndLib::Add(aWhere, BoundingBox);
4111   BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
4112   min_l = fabs(aXmax - aXmin);
4113   if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin);
4114   if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin);
4115   min_l /= dl_l;
4116   // Mantis issue 0020908 BEGIN
4117   if (!Exp_Edge.More()) {
4118     min_l = Precision::Confusion();
4119   }
4120   // Mantis issue 0020908 END
4121   for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
4122     TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX);
4123     for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) {
4124       aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) );
4125       tab_Pnt[nbVertex] = aPnt;
4126     }
4127     if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) {
4128       BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
4129       if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
4130     }
4131   }
4132
4133   // Compute tolerances
4134   Tol_0D = dl_l;
4135   Tol_1D = dl_l * min_l;
4136   Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
4137   Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
4138
4139   if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion();
4140   if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion();
4141   if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion();
4142   if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion();
4143
4144   //if (Tol_1D > 1.0) Tol_1D = 1.0;
4145   //if (Tol_2D > 1.0) Tol_2D = 1.0;
4146   //if (Tol_3D > 1.0) Tol_3D = 1.0;
4147
4148   Tol_Mass = Tol_3D;
4149   if ( iType == TopAbs_VERTEX )    Tol_Mass = Tol_0D;
4150   else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D;
4151   else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
4152
4153   // Compute the ShapeWhat Mass
4154   /*
4155   for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) {
4156     if ( iType == TopAbs_VERTEX ) {
4157       aWhat_Mass += 1;
4158       continue;
4159     }
4160     else if ( iType == TopAbs_EDGE ) BRepGProp::LinearProperties(Exp_aWhat.Current(),  aProps);
4161     else if ( iType == TopAbs_FACE ) BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps);
4162     else                             BRepGProp::VolumeProperties(Exp_aWhat.Current(),  aProps);
4163     aWhat_Mass += aProps.Mass();
4164   }
4165   */
4166
4167   // Searching for the sub-shapes inside the ShapeWhere shape
4168   TopTools_MapOfShape map_aWhere;
4169   for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) {
4170     if (!map_aWhere.Add(Exp_aWhere.Current()))
4171       continue; // skip repeated shape to avoid mass addition
4172     GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
4173     for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
4174       GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
4175       if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D )
4176         isFound = true;
4177       else {
4178         if ( (tab_aWhat[3] - tab_aWhere[3]) > Tol_Mass ) {
4179           aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
4180           aVertex   = TopoDS::Vertex( aPntShape );
4181           BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() );
4182           BRepExtrema_DistShapeShape aWhatDistance  ( aVertex, Exp_aWhat.Current() );
4183           if ( aWhereDistance.IsDone() && aWhatDistance.IsDone() &&
4184                fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= Tol_1D )
4185           {
4186             // 0020162: "EDF 961 GEOM : Getinplace is getting additionnal orthogonal faces"
4187             // aVertex must be projected to the same point on Where and on What
4188             gp_Pnt pOnWhat  = aWhatDistance.PointOnShape2(1);
4189             gp_Pnt pOnWhere = aWhereDistance.PointOnShape2(1);
4190             isFound = ( pOnWhat.Distance(pOnWhere) <= Tol_1D );
4191             if ( isFound && iType == TopAbs_FACE )
4192             {
4193               // check normals at pOnWhat and pOnWhere
4194               const double angleTol = M_PI/180.;
4195               gp_Vec normToWhat  = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance);
4196               gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance);
4197               if ( normToWhat * normToWhere < 0 )
4198                 normToWhat.Reverse();
4199               isFound = ( normToWhat.Angle( normToWhere ) < angleTol );
4200             }
4201           }
4202         }
4203       }
4204       if ( isFound ) {
4205         aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current());
4206         aModifiedList.Append(aWhereIndex);
4207         //aWhere_Mass += tab_aWhere[3];
4208         isFound = false;
4209         break;
4210       }
4211     }
4212     //if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass )
4213       //break;
4214   }
4215
4216   if (aModifiedList.Extent() == 0) { // Not found any Results
4217     SetErrorCode(NOT_FOUND_ANY);
4218     return NULL;
4219   }
4220
4221   aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4222   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
4223   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
4224     aModifiedArray->SetValue(imod, anIterModif.Value());
4225
4226   //Add a new object
4227   aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4228   if (aResult.IsNull()) {
4229     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4230     return NULL;
4231   }
4232
4233   if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) {
4234     //Set a GROUP type
4235     aResult->SetType(GEOM_GROUP);
4236
4237     //Set a sub-shape type
4238     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4239     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4240
4241     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4242     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4243   }
4244
4245   //Make a Python command
4246   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4247
4248   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4249     << theShapeWhere << ", " << theShapeWhat << ", False)";
4250
4251   SetErrorCode(OK);
4252   return aResult;
4253 }
4254
4255 //=======================================================================
4256 //function : GetInPlaceByHistory
4257 //purpose  :
4258 //=======================================================================
4259 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
4260                                           (Handle(GEOM_Object) theShapeWhere,
4261                                            Handle(GEOM_Object) theShapeWhat)
4262 {
4263   SetErrorCode(KO);
4264
4265   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4266
4267   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4268   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4269
4270   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4271
4272   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4273   if (aWhereFunction.IsNull()) return NULL;
4274
4275   //Fill array of indices
4276   TopTools_IndexedMapOfShape aWhereIndices;
4277   TopExp::MapShapes(aWhere, aWhereIndices);
4278
4279   // process shape
4280   TColStd_ListOfInteger aModifiedList;
4281   bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
4282
4283   if (!isFound || aModifiedList.Extent() < 1) {
4284     SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
4285     return NULL;
4286   }
4287
4288   Standard_Integer nbFound = aModifiedList.Extent();
4289   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
4290   if ( nbFound > 1 )
4291   {
4292     // remove sub-shapes inappropriate for group creation
4293     TopAbs_ShapeEnum subType = TopAbs_SHAPE;
4294     while ( anIterModif.More() ) {
4295       TopAbs_ShapeEnum type = aWhereIndices( anIterModif.Value() ).ShapeType();
4296       bool okForGroup = ( type == TopAbs_VERTEX || type == TopAbs_EDGE ||
4297                           type == TopAbs_FACE   || type == TopAbs_SOLID );
4298       if ( okForGroup ) {
4299         if ( subType == TopAbs_SHAPE )
4300           subType = type;
4301         else
4302           okForGroup = ( subType == type );
4303       }
4304       if ( okForGroup )
4305         anIterModif.Next();
4306       else
4307         aModifiedList.Remove( anIterModif );
4308       nbFound -= ( !okForGroup );
4309     }
4310     if ( nbFound == 0 ) {
4311       SetErrorCode("Error: result found but it's type is inappropriate for group creation.");
4312       return NULL;
4313     }
4314   }
4315
4316   Handle(TColStd_HArray1OfInteger) aModifiedArray =
4317     new TColStd_HArray1OfInteger( 1, nbFound );
4318   anIterModif.Initialize(aModifiedList);
4319   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
4320     aModifiedArray->SetValue(imod, anIterModif.Value());
4321
4322   //Add a new object
4323   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4324   if (aResult.IsNull()) {
4325     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4326     return NULL;
4327   }
4328
4329   if (aModifiedArray->Length() > 1) {
4330     //Set a GROUP type
4331     aResult->SetType(GEOM_GROUP);
4332
4333     //Set a sub-shape type
4334     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4335     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4336
4337     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4338     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4339   }
4340
4341   //Make a Python command
4342   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4343
4344   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
4345                                << theShapeWhere << ", " << theShapeWhat << ")";
4346
4347   SetErrorCode(OK);
4348   return aResult;
4349 }
4350
4351 #define MAX_TOLERANCE 1.e-7
4352
4353 //=======================================================================
4354 //function : isSameEdge
4355 //purpose  : Returns True if two edges coincide
4356 //=======================================================================
4357 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4358 {
4359   TopoDS_Vertex V11, V12, V21, V22;
4360   TopExp::Vertices(theEdge1, V11, V12);
4361   TopExp::Vertices(theEdge2, V21, V22);
4362   gp_Pnt P11 = BRep_Tool::Pnt(V11);
4363   gp_Pnt P12 = BRep_Tool::Pnt(V12);
4364   gp_Pnt P21 = BRep_Tool::Pnt(V21);
4365   gp_Pnt P22 = BRep_Tool::Pnt(V22);
4366   bool coincide = false;
4367
4368   //Check that ends of edges coincide
4369   if(P11.Distance(P21) <= MAX_TOLERANCE) {
4370     if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
4371   }
4372   else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4373     if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4374   }
4375
4376   if(!coincide) return false;
4377
4378   if (BRep_Tool::Degenerated(theEdge1))
4379     if (BRep_Tool::Degenerated(theEdge2)) return true;
4380     else return false;
4381   else
4382     if (BRep_Tool::Degenerated(theEdge2)) return false;
4383
4384   double U11, U12, U21, U22;
4385   Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4386   Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4387   if(C1->DynamicType() == C2->DynamicType()) return true;
4388
4389   //Check that both edges has the same geometry
4390   double range = U12-U11;
4391   double U = U11+ range/3.0;
4392   gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
4393   U = U11+range*2.0/3.0;
4394   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
4395
4396   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
4397     return false;
4398
4399   if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4400
4401   if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4402     return false;
4403
4404   if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4405
4406   return true;
4407 }
4408
4409 #include <TopoDS_TShape.hxx>
4410 //=======================================================================
4411 //function : isSameFace
4412 //purpose  : Returns True if two faces coincide
4413 //=======================================================================
4414 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4415 {
4416   TopExp_Explorer E(theFace1, TopAbs_EDGE);
4417   TopTools_ListOfShape LS1, LS2;
4418   for(; E.More(); E.Next()) LS1.Append(E.Current());
4419
4420   E.Init(theFace2, TopAbs_EDGE);
4421   for(; E.More(); E.Next()) LS2.Append(E.Current());
4422
4423   //Compare the number of edges in the faces
4424   if(LS1.Extent() != LS2.Extent()) return false;
4425
4426   double aMin = RealFirst(), aMax = RealLast();
4427   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4428   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4429
4430   for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4431     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4432     if(P.X() < xminB1) xminB1 = P.X();
4433     if(P.Y() < yminB1) yminB1 = P.Y();
4434     if(P.Z() < zminB1) zminB1 = P.Z();
4435     if(P.X() > xmaxB1) xmaxB1 = P.X();
4436     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4437     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4438   }
4439
4440   for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4441     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4442     if(P.X() < xminB2) xminB2 = P.X();
4443     if(P.Y() < yminB2) yminB2 = P.Y();
4444     if(P.Z() < zminB2) zminB2 = P.Z();
4445     if(P.X() > xmaxB2) xmaxB2 = P.X();
4446     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4447     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4448   }
4449
4450   //Compare the bounding boxes of both faces
4451   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4452     return false;
4453
4454   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4455     return false;
4456
4457   Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4458   Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4459
4460   //Check if there a coincidence of two surfaces at least in two points
4461   double U11, U12, V11, V12, U21, U22, V21, V22;
4462   BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4463   BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4464
4465   double rangeU = U12-U11;
4466   double rangeV = V12-V11;
4467   double U = U11 + rangeU/3.0;
4468   double V = V11 + rangeV/3.0;
4469   gp_Pnt P1 = S1->Value(U, V);
4470   U = U11+rangeU*2.0/3.0;
4471   V = V11+rangeV*2.0/3.0;
4472   gp_Pnt P2 = S1->Value(U, V);
4473
4474   if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4475     return false;
4476
4477   if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4478
4479   if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4480     return false;
4481
4482   if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
4483
4484   //Check that each edge of the Face1 has a counterpart in the Face2
4485   TopTools_MapOfOrientedShape aMap;
4486   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4487   for(; LSI1.More(); LSI1.Next()) {
4488     TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
4489     bool isFound = false;
4490     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4491     for(; LSI2.More(); LSI2.Next()) {
4492       TopoDS_Shape aValue = LSI2.Value();
4493       if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
4494       if(isSameEdge(E, TopoDS::Edge(aValue))) {
4495         aMap.Add(aValue);
4496         isFound = true;
4497         break;
4498       }
4499     }
4500     if(!isFound) return false;
4501   }
4502
4503   return true;
4504 }
4505
4506 //=======================================================================
4507 //function : isSameSolid
4508 //purpose  : Returns True if two solids coincide
4509 //=======================================================================
4510 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
4511 {
4512   TopExp_Explorer E(theSolid1, TopAbs_FACE);
4513   TopTools_ListOfShape LS1, LS2;
4514   for(; E.More(); E.Next()) LS1.Append(E.Current());
4515   E.Init(theSolid2, TopAbs_FACE);
4516   for(; E.More(); E.Next()) LS2.Append(E.Current());
4517
4518   if(LS1.Extent() != LS2.Extent()) return false;
4519
4520   double aMin = RealFirst(), aMax = RealLast();
4521   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4522   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4523
4524   for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
4525     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4526     if(P.X() < xminB1) xminB1 = P.X();
4527     if(P.Y() < yminB1) yminB1 = P.Y();
4528     if(P.Z() < zminB1) zminB1 = P.Z();
4529     if(P.X() > xmaxB1) xmaxB1 = P.X();
4530     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4531     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4532   }
4533
4534   for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
4535     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4536     if(P.X() < xminB2) xminB2 = P.X();
4537     if(P.Y() < yminB2) yminB2 = P.Y();
4538     if(P.Z() < zminB2) zminB2 = P.Z();
4539     if(P.X() > xmaxB2) xmaxB2 = P.X();
4540     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4541     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4542   }
4543
4544   //Compare the bounding boxes of both solids
4545   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4546     return false;
4547
4548   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4549     return false;
4550
4551   //Check that each face of the Solid1 has a counterpart in the Solid2
4552   TopTools_MapOfOrientedShape aMap;
4553   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4554   for(; LSI1.More(); LSI1.Next()) {
4555     TopoDS_Face F = TopoDS::Face(LSI1.Value());
4556     bool isFound = false;
4557     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4558     for(; LSI2.More(); LSI2.Next()) {
4559       if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
4560       if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
4561         aMap.Add(LSI2.Value());
4562         isFound = true;
4563         break;
4564       }
4565     }
4566     if(!isFound) return false;
4567   }
4568
4569   return true;
4570 }
4571
4572 //=======================================================================
4573 //function : GetSame
4574 //purpose  :
4575 //=======================================================================
4576 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
4577                                                         const Handle(GEOM_Object)& theShapeWhat)
4578 {
4579   SetErrorCode(KO);
4580   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4581
4582   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4583   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4584
4585   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4586
4587   int anIndex = -1;
4588   bool isFound = false;
4589   TopoDS_Shape aSubShape;
4590   TopTools_MapOfShape aMap;
4591
4592   if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4593     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4594     if (It.More()) aWhat = It.Value();
4595     It.Next();
4596     if (It.More()) {
4597       SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4598       return NULL;
4599     }
4600   }
4601
4602   switch (aWhat.ShapeType()) {
4603     case TopAbs_VERTEX: {
4604       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
4605       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
4606       for(; E.More(); E.Next()) {
4607         if(!aMap.Add(E.Current())) continue;
4608         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4609         if(P.Distance(P2) <= MAX_TOLERANCE) {
4610           isFound = true;
4611           aSubShape = E.Current();
4612           break;
4613         }
4614       }
4615       break;
4616                         }
4617     case TopAbs_EDGE: {
4618       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4619       TopExp_Explorer E(aWhere, TopAbs_EDGE);
4620       for(; E.More(); E.Next()) {
4621         if(!aMap.Add(E.Current())) continue;
4622         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4623           aSubShape = E.Current();
4624           isFound = true;
4625           break;
4626         }
4627       }
4628       break;
4629                       }
4630     case TopAbs_FACE: {
4631       TopoDS_Face aFace = TopoDS::Face(aWhat);
4632       TopExp_Explorer E(aWhere, TopAbs_FACE);
4633       for(; E.More(); E.Next()) {
4634         if(!aMap.Add(E.Current())) continue;
4635         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
4636           aSubShape = E.Current();
4637           isFound = true;
4638           break;
4639         }
4640       }
4641       break;
4642                       }
4643     case TopAbs_SOLID: {
4644       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
4645       TopExp_Explorer E(aWhere, TopAbs_SOLID);
4646       for(; E.More(); E.Next()) {
4647         if(!aMap.Add(E.Current())) continue;
4648         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
4649           aSubShape = E.Current();
4650           isFound = true;
4651           break;
4652         }
4653       }
4654       break;
4655                        }
4656     default:
4657       return NULL;
4658   }
4659
4660   if (isFound) {
4661     TopTools_IndexedMapOfShape anIndices;
4662     TopExp::MapShapes(aWhere, anIndices);
4663     if (anIndices.Contains(aSubShape))
4664       anIndex = anIndices.FindIndex(aSubShape);
4665   }
4666
4667   if (anIndex < 0) return NULL;
4668
4669   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
4670
4671   anArray->SetValue(1, anIndex);
4672
4673   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
4674   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
4675
4676   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
4677     << theShapeWhere << ", " << theShapeWhat << ")";
4678
4679   SetErrorCode(OK);
4680
4681   return aResult;
4682 }
4683
4684
4685 //=======================================================================
4686 //function : GetSameIDs
4687 //purpose  :
4688 //=======================================================================
4689 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
4690                                                        (const Handle(GEOM_Object)& theShapeWhere,
4691                                                         const Handle(GEOM_Object)& theShapeWhat)
4692 {
4693   SetErrorCode(KO);
4694   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4695
4696   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4697   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4698
4699   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4700
4701   TopTools_ListOfShape listShape;
4702   TopTools_MapOfShape aMap;
4703
4704   if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4705     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4706     if (It.More()) aWhat = It.Value();
4707     It.Next();
4708     if (It.More()) {
4709       SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4710       return NULL;
4711     }
4712   }
4713
4714   switch (aWhat.ShapeType()) {
4715     case TopAbs_VERTEX: {
4716       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
4717       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
4718       for(; E.More(); E.Next()) {
4719         if(!aMap.Add(E.Current())) continue;
4720         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4721         if(P.Distance(P2) <= MAX_TOLERANCE) {
4722           listShape.Append(E.Current());
4723         }
4724       }
4725       break;
4726                         }
4727     case TopAbs_EDGE: {
4728       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4729       TopExp_Explorer E(aWhere, TopAbs_EDGE);
4730       for(; E.More(); E.Next()) {
4731         if(!aMap.Add(E.Current())) continue;
4732         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4733           listShape.Append(E.Current());
4734         }
4735       }
4736       break;
4737                       }
4738     case TopAbs_FACE: {
4739       TopoDS_Face aFace = TopoDS::Face(aWhat);
4740       TopExp_Explorer E(aWhere, TopAbs_FACE);
4741       for(; E.More(); E.Next()) {
4742         if(!aMap.Add(E.Current())) continue;
4743         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
4744           listShape.Append(E.Current());
4745         }
4746       }
4747       break;
4748                       }
4749     case TopAbs_SOLID: {
4750       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
4751       TopExp_Explorer E(aWhere, TopAbs_SOLID);
4752       for(; E.More(); E.Next()) {
4753         if(!aMap.Add(E.Current())) continue;
4754         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
4755           listShape.Append(E.Current());
4756         }
4757       }
4758       break;
4759                        }
4760     default:
4761       return NULL;
4762   }
4763
4764   if ( !listShape.IsEmpty() ) {
4765     TopTools_IndexedMapOfShape anIndices;
4766     TopExp::MapShapes(aWhere, anIndices);
4767     TopTools_ListIteratorOfListOfShape itSub (listShape);
4768     Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
4769     for (; itSub.More(); itSub.Next()) {
4770       if (anIndices.Contains(itSub.Value()))
4771         aSeq->Append(anIndices.FindIndex(itSub.Value()));
4772     }
4773     SetErrorCode(OK);
4774     // The GetSameIDs() doesn't change object so no new function is required.
4775     Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
4776
4777   // Make a Python command
4778   GEOM::TPythonDump(aFunction, /*append=*/true)
4779     << "listSameIDs = geompy.GetSameIDs("
4780     << theShapeWhere << ", "
4781     << theShapeWhat << ")";
4782     return aSeq;
4783   } else {
4784     SetErrorCode(NOT_FOUND_ANY);
4785     return NULL;
4786   }
4787 }