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