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