Salome HOME
67e8f436282b3354ed682780ec422987d3aa1114
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 #include <Standard_Stream.hxx>
21
22 #include "GEOMImpl_IShapesOperations.hxx"
23
24 #include "GEOMImpl_Types.hxx"
25
26 #include "GEOMImpl_VectorDriver.hxx"
27 #include "GEOMImpl_ShapeDriver.hxx"
28 #include "GEOMImpl_CopyDriver.hxx"
29 #include "GEOMImpl_GlueDriver.hxx"
30
31 #include "GEOMImpl_IVector.hxx"
32 #include "GEOMImpl_IShapes.hxx"
33 #include "GEOMImpl_IGlue.hxx"
34
35 #include "GEOMImpl_Block6Explorer.hxx"
36
37 #include "GEOM_Function.hxx"
38 #include "GEOM_PythonDump.hxx"
39
40 #include "GEOMAlgo_FinderShapeOn1.hxx"
41 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
42
43 #include "utilities.h"
44 #include "OpUtil.hxx"
45 #include "Utils_ExceptHandlers.hxx"
46
47 #include <TFunction_DriverTable.hxx>
48 #include <TFunction_Driver.hxx>
49 #include <TFunction_Logbook.hxx>
50 #include <TDataStd_Integer.hxx>
51 #include <TDataStd_IntegerArray.hxx>
52 #include <TDF_Tool.hxx>
53
54 #include <BRepExtrema_ExtCF.hxx>
55
56 #include <BRep_Tool.hxx>
57 #include <BRepGProp.hxx>
58 #include <BRepAdaptor_Curve.hxx>
59 #include <BRepAdaptor_Surface.hxx>
60 #include <BRepBndLib.hxx>
61 #include <BRepBuilderAPI_MakeFace.hxx>
62 #include <BRepMesh_IncrementalMesh.hxx>
63
64 #include <TopAbs.hxx>
65 #include <TopExp.hxx>
66 #include <TopoDS.hxx>
67 #include <TopoDS_Shape.hxx>
68 #include <TopoDS_Face.hxx>
69 #include <TopoDS_Edge.hxx>
70 #include <TopoDS_Vertex.hxx>
71 #include <TopoDS_Iterator.hxx>
72 #include <TopExp_Explorer.hxx>
73 #include <TopLoc_Location.hxx>
74 #include <TopTools_MapOfShape.hxx>
75 #include <TopTools_Array1OfShape.hxx>
76 #include <TopTools_ListIteratorOfListOfShape.hxx>
77 #include <TopTools_IndexedMapOfShape.hxx>
78
79 #include <Geom_Surface.hxx>
80 #include <Geom_Plane.hxx>
81 #include <Geom_SphericalSurface.hxx>
82 #include <Geom_CylindricalSurface.hxx>
83 #include <GeomAdaptor_Surface.hxx>
84
85 #include <Geom2d_Curve.hxx>
86
87 #include <Bnd_Box.hxx>
88 #include <GProp_GProps.hxx>
89 #include <gp_Pnt.hxx>
90 #include <gp_Lin.hxx>
91 #include <TColStd_ListOfInteger.hxx>
92 #include <TColStd_ListIteratorOfListOfInteger.hxx>
93 #include <TColStd_Array1OfReal.hxx>
94 #include <TColStd_HArray1OfInteger.hxx>
95
96 #include <vector>
97
98 #include <Standard_Failure.hxx>
99 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
100
101 //=============================================================================
102 /*!
103  *   constructor:
104  */
105 //=============================================================================
106 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
107 : GEOM_IOperations(theEngine, theDocID)
108 {
109   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
110 }
111
112 //=============================================================================
113 /*!
114  *  destructor
115  */
116 //=============================================================================
117 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
118 {
119   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
120 }
121
122
123 //=============================================================================
124 /*!
125  *  MakeEdge
126  */
127 //=============================================================================
128 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
129                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
130 {
131   SetErrorCode(KO);
132
133   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
134
135   //Add a new Edge object
136   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
137
138   //Add a new Vector function
139   Handle(GEOM_Function) aFunction =
140     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
141
142   //Check if the function is set correctly
143   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
144
145   GEOMImpl_IVector aPI (aFunction);
146
147   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
148   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
149   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
150
151   aPI.SetPoint1(aRef1);
152   aPI.SetPoint2(aRef2);
153
154   //Compute the Edge value
155   try {
156 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
157     OCC_CATCH_SIGNALS;
158 #endif
159     if (!GetSolver()->ComputeFunction(aFunction)) {
160       SetErrorCode("Vector driver failed");
161       return NULL;
162     }
163   }
164   catch (Standard_Failure) {
165     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
166     SetErrorCode(aFail->GetMessageString());
167     return NULL;
168   }
169
170   //Make a Python command
171   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
172                                << thePnt1 << ", " << thePnt2 << ")";
173
174   SetErrorCode(OK);
175   return anEdge;
176 }
177
178 //=============================================================================
179 /*!
180  *  MakeWire
181  */
182 //=============================================================================
183 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
184                              (list<Handle(GEOM_Object)> theShapes)
185 {
186   return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
187 }
188
189 //=============================================================================
190 /*!
191  *  MakeFace
192  */
193 //=============================================================================
194 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
195                                                           const bool isPlanarWanted)
196 {
197   SetErrorCode(KO);
198
199   if (theWire.IsNull()) return NULL;
200
201   //Add a new Face object
202   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
203
204   //Add a new Shape function for creation of a face from a wire
205   Handle(GEOM_Function) aFunction =
206     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
207   if (aFunction.IsNull()) return NULL;
208
209   //Check if the function is set correctly
210   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
211
212   GEOMImpl_IShapes aCI (aFunction);
213
214   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
215
216   if (aRefWire.IsNull()) return NULL;
217
218   aCI.SetBase(aRefWire);
219   aCI.SetIsPlanar(isPlanarWanted);
220
221   //Compute the Face value
222   try {
223 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
224     OCC_CATCH_SIGNALS;
225 #endif
226     if (!GetSolver()->ComputeFunction(aFunction)) {
227       SetErrorCode("Shape driver failed to compute a face");
228       return NULL;
229     }
230   }
231   catch (Standard_Failure) {
232     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
233     SetErrorCode(aFail->GetMessageString());
234     return NULL;
235   }
236
237   //Make a Python command
238   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
239     << theWire << ", " << (int)isPlanarWanted << ")";
240
241   SetErrorCode(OK);
242   return aFace;
243 }
244
245 //=============================================================================
246 /*!
247  *  MakeFaceWires
248  */
249 //=============================================================================
250 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
251                              (list<Handle(GEOM_Object)> theShapes,
252                               const bool isPlanarWanted)
253 {
254   SetErrorCode(KO);
255
256   //Add a new object
257   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
258
259   //Add a new function
260   Handle(GEOM_Function) aFunction =
261     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
262   if (aFunction.IsNull()) return NULL;
263
264   //Check if the function is set correctly
265   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
266
267   GEOMImpl_IShapes aCI (aFunction);
268
269   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
270
271   // Shapes
272   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
273   for (; it != theShapes.end(); it++) {
274     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
275     if (aRefSh.IsNull()) {
276       SetErrorCode("NULL argument shape for the face construction");
277       return NULL;
278     }
279     aShapesSeq->Append(aRefSh);
280   }
281   aCI.SetShapes(aShapesSeq);
282
283   aCI.SetIsPlanar(isPlanarWanted);
284
285   //Compute the shape
286   try {
287 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
288     OCC_CATCH_SIGNALS;
289 #endif
290     if (!GetSolver()->ComputeFunction(aFunction)) {
291       SetErrorCode("Shape driver failed");
292       return NULL;
293     }
294   }
295   catch (Standard_Failure) {
296     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
297     SetErrorCode(aFail->GetMessageString());
298     return NULL;
299   }
300
301   //Make a Python command
302   GEOM::TPythonDump pd (aFunction);
303   pd << aShape << " = geompy.MakeFaceWires([";
304
305   // Shapes
306   it = theShapes.begin();
307   if (it != theShapes.end()) {
308     pd << (*it++);
309     while (it != theShapes.end()) {
310       pd << ", " << (*it++);
311     }
312   }
313   pd << "], " << (int)isPlanarWanted << ")";
314
315   SetErrorCode(OK);
316   return aShape;
317 }
318
319 //=============================================================================
320 /*!
321  *  MakeShell
322  */
323 //=============================================================================
324 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
325                              (list<Handle(GEOM_Object)> theShapes)
326 {
327   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
328 }
329
330 //=============================================================================
331 /*!
332  *  MakeSolidShells
333  */
334 //=============================================================================
335 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
336                              (list<Handle(GEOM_Object)> theShapes)
337 {
338   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
339 }
340
341 //=============================================================================
342 /*!
343  *  MakeSolidShell
344  */
345 //=============================================================================
346 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
347 {
348   SetErrorCode(KO);
349
350   if (theShell.IsNull()) return NULL;
351
352   //Add a new Solid object
353   Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
354
355   //Add a new Solid function for creation of a solid from a shell
356   Handle(GEOM_Function) aFunction =
357     aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
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(GEOM_Function) aRefShell = theShell->GetLastFunction();
366
367   if (aRefShell.IsNull()) return NULL;
368
369   aCI.SetBase(aRefShell);
370
371   //Compute the Solid value
372   try {
373 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
374     OCC_CATCH_SIGNALS;
375 #endif
376     if (!GetSolver()->ComputeFunction(aFunction)) {
377       SetErrorCode("Solid driver failed");
378       return NULL;
379     }
380   }
381   catch (Standard_Failure) {
382     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
383     SetErrorCode(aFail->GetMessageString());
384     return NULL;
385   }
386
387   //Make a Python command
388   GEOM::TPythonDump(aFunction) << aSolid
389     << " = geompy.MakeSolid(" << theShell << ")";
390
391   SetErrorCode(OK);
392   return aSolid;
393 }
394
395 //=============================================================================
396 /*!
397  *  MakeCompound
398  */
399 //=============================================================================
400 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
401                              (list<Handle(GEOM_Object)> theShapes)
402 {
403   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
404 }
405
406 //=============================================================================
407 /*!
408  *  MakeShape
409  */
410 //=============================================================================
411 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
412                              (list<Handle(GEOM_Object)>      theShapes,
413                               const Standard_Integer         theObjectType,
414                               const Standard_Integer         theFunctionType,
415                               const TCollection_AsciiString& theMethodName)
416 {
417   SetErrorCode(KO);
418
419   //Add a new object
420   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
421
422   //Add a new function
423   Handle(GEOM_Function) aFunction =
424     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
425   if (aFunction.IsNull()) return NULL;
426
427   //Check if the function is set correctly
428   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
429
430   GEOMImpl_IShapes aCI (aFunction);
431
432   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
433
434   // Shapes
435   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
436   for (; it != theShapes.end(); it++) {
437     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
438     if (aRefSh.IsNull()) {
439       SetErrorCode("NULL argument shape for the shape construction");
440       return NULL;
441     }
442     aShapesSeq->Append(aRefSh);
443   }
444   aCI.SetShapes(aShapesSeq);
445
446   //Compute the shape
447   try {
448 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
449     OCC_CATCH_SIGNALS;
450 #endif
451     if (!GetSolver()->ComputeFunction(aFunction)) {
452       SetErrorCode("Shape driver failed");
453       return NULL;
454     }
455   }
456   catch (Standard_Failure) {
457     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
458     SetErrorCode(aFail->GetMessageString());
459     return NULL;
460   }
461
462   //Make a Python command
463   GEOM::TPythonDump pd (aFunction);
464   pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
465
466   // Shapes
467   it = theShapes.begin();
468   if (it != theShapes.end()) {
469     pd << (*it++);
470     while (it != theShapes.end()) {
471       pd << ", " << (*it++);
472     }
473   }
474   pd << "])";
475
476   SetErrorCode(OK);
477   return aShape;
478 }
479
480 //=============================================================================
481 /*!
482  *  MakeGlueFaces
483  */
484 //=============================================================================
485 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
486                                                 (Handle(GEOM_Object) theShape,
487                                                  const Standard_Real theTolerance)
488 {
489   SetErrorCode(KO);
490
491   if (theShape.IsNull()) return NULL;
492
493   //Add a new Glued object
494   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
495
496   //Add a new Glue function
497   Handle(GEOM_Function) aFunction;
498   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
499   if (aFunction.IsNull()) return NULL;
500
501   //Check if the function is set correctly
502   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
503
504   GEOMImpl_IGlue aCI (aFunction);
505
506   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
507   if (aRefShape.IsNull()) return NULL;
508
509   aCI.SetBase(aRefShape);
510   aCI.SetTolerance(theTolerance);
511
512   //Compute the sub-shape value
513   Standard_Boolean isWarning = Standard_False;
514   try {
515 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
516     OCC_CATCH_SIGNALS;
517 #endif
518     if (!GetSolver()->ComputeFunction(aFunction)) {
519       SetErrorCode("Shape driver failed to glue faces");
520       return NULL;
521     }
522   }
523   catch (Standard_Failure) {
524     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
525     SetErrorCode(aFail->GetMessageString());
526     // to provide warning
527     if (!aFunction->GetValue().IsNull()) {
528       isWarning = Standard_True;
529     } else {
530       return NULL;
531     }
532   }
533
534   //Make a Python command
535   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
536     << theShape << ", " << theTolerance << ")";
537
538   // to provide warning
539   if (!isWarning) SetErrorCode(OK);
540   return aGlued;
541 }
542
543 //=============================================================================
544 /*!
545  *  MakeExplode
546  */
547 //=============================================================================
548 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
549                                           (Handle(GEOM_Object)    theShape,
550                                            const Standard_Integer theShapeType,
551                                            const Standard_Boolean isSorted)
552 {
553   SetErrorCode(KO);
554
555   if (theShape.IsNull()) return NULL;
556   TopoDS_Shape aShape = theShape->GetValue();
557   if (aShape.IsNull()) return NULL;
558
559   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
560   Handle(GEOM_Object) anObj;
561   Handle(GEOM_Function) aFunction;
562   TopTools_MapOfShape mapShape;
563   TopTools_ListOfShape listShape;
564
565   if (aShape.ShapeType() == TopAbs_COMPOUND &&
566       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
567        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
568        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
569     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
570     for (; It.More(); It.Next()) {
571       if (mapShape.Add(It.Value())) {
572         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
573             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
574           listShape.Append(It.Value());
575         }
576       }
577     }
578   } else {
579     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
580     for (; exp.More(); exp.Next())
581       if (mapShape.Add(exp.Current()))
582         listShape.Append(exp.Current());
583   }
584
585   if (listShape.IsEmpty()) {
586     SetErrorCode("The given shape has no sub-shapes of the requested type");
587     return aSeq;
588   }
589
590   if (isSorted)
591     SortShapes(listShape);
592
593   TopTools_IndexedMapOfShape anIndices;
594   TopExp::MapShapes(aShape, anIndices);
595   Handle(TColStd_HArray1OfInteger) anArray;
596
597   TopTools_ListIteratorOfListOfShape itSub (listShape);
598   TCollection_AsciiString anAsciiList, anEntry;
599   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
600     TopoDS_Shape aValue = itSub.Value();
601     anArray = new TColStd_HArray1OfInteger(1,1);
602     anArray->SetValue(1, anIndices.FindIndex(aValue));
603     anObj = GetEngine()->AddSubShape(theShape, anArray);
604     aSeq->Append(anObj);
605
606     // for python command
607     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
608     anAsciiList += anEntry;
609     anAsciiList += ",";
610   }
611
612   //Make a Python command
613   anAsciiList.Trunc(anAsciiList.Length() - 1);
614
615   aFunction = theShape->GetLastFunction();
616
617   GEOM::TPythonDump pd (aFunction, /*append=*/true);
618   pd << "[" << anAsciiList.ToCString();
619   pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
620   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
621
622   SetErrorCode(OK);
623
624   return aSeq;
625 }
626
627 //=============================================================================
628 /*!
629  *  GetSubShapeAllIDs
630  */
631 //=============================================================================
632 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
633                                           (Handle(GEOM_Object)    theShape,
634                                            const Standard_Integer theShapeType,
635                                            const Standard_Boolean isSorted)
636 {
637   SetErrorCode(KO);
638
639   if (theShape.IsNull()) return NULL;
640   TopoDS_Shape aShape = theShape->GetValue();
641   if (aShape.IsNull()) return NULL;
642
643   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
644   TopTools_MapOfShape mapShape;
645   TopTools_ListOfShape listShape;
646
647   if (aShape.ShapeType() == TopAbs_COMPOUND &&
648       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
649        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
650        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
651     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
652     for (; It.More(); It.Next()) {
653       if (mapShape.Add(It.Value())) {
654         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
655             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
656           listShape.Append(It.Value());
657         }
658       }
659     }
660   } else {
661     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
662     for (; exp.More(); exp.Next())
663       if (mapShape.Add(exp.Current()))
664         listShape.Append(exp.Current());
665   }
666
667   if (listShape.IsEmpty()) {
668     SetErrorCode("The given shape has no sub-shapes of the requested type");
669     return aSeq;
670   }
671
672   if (isSorted)
673     SortShapes(listShape);
674
675   TopTools_IndexedMapOfShape anIndices;
676   TopExp::MapShapes(aShape, anIndices);
677   Handle(TColStd_HArray1OfInteger) anArray;
678
679   TopTools_ListIteratorOfListOfShape itSub (listShape);
680   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
681     TopoDS_Shape aValue = itSub.Value();
682     aSeq->Append(anIndices.FindIndex(aValue));
683   }
684
685   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
686
687   //Make a Python command
688   GEOM::TPythonDump pd (aFunction, /*append=*/true);
689   pd << "listSubShapeIDs = geompy.SubShapeAll";
690   pd << (isSorted ? "SortedIDs(" : "IDs(");
691   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
692
693   SetErrorCode(OK);
694   return aSeq;
695 }
696
697 //=============================================================================
698 /*!
699  *  GetSubShape
700  */
701 //=============================================================================
702 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
703                                           (Handle(GEOM_Object)    theMainShape,
704                                            const Standard_Integer theID)
705 {
706   SetErrorCode(KO);
707
708   if (theMainShape.IsNull()) return NULL;
709
710   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
711   anArray->SetValue(1, theID);
712   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
713   if (anObj.IsNull()) {
714     SetErrorCode("Can not get a sub-shape with the given ID");
715     return NULL;
716   }
717
718   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
719
720   //Make a Python command
721   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
722                                << theMainShape << ", [" << theID << "])";
723
724   SetErrorCode(OK);
725   return anObj;
726 }
727
728 //=============================================================================
729 /*!
730  *  GetSubShapeIndex
731  */
732 //=============================================================================
733 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
734                                                                Handle(GEOM_Object) theSubShape)
735 {
736   SetErrorCode(KO);
737
738   TopoDS_Shape aMainShape = theMainShape->GetValue();
739   TopoDS_Shape aSubShape = theSubShape->GetValue();
740
741   if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
742
743   TopTools_IndexedMapOfShape anIndices;
744   TopExp::MapShapes(aMainShape, anIndices);
745   if (anIndices.Contains(aSubShape)) {
746     SetErrorCode(OK);
747     return anIndices.FindIndex(aSubShape);
748   }
749
750   return -1;
751 }
752
753 //=============================================================================
754 /*!
755  *  GetTopologyIndex
756  */
757 //=============================================================================
758 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
759                                                                Handle(GEOM_Object) theSubShape)
760 {
761   SetErrorCode(OK);
762
763   TopoDS_Shape aMainShape = theMainShape->GetValue();
764   TopoDS_Shape aSubShape = theSubShape->GetValue();
765
766   if (aMainShape.IsNull() || aSubShape.IsNull()) {
767     SetErrorCode("Null argument shape given");
768     return -1;
769   }
770
771   int index = 1;
772   if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
773     TopoDS_Iterator it;
774     TopTools_ListOfShape CL;
775     CL.Append(aMainShape);
776     TopTools_ListIteratorOfListOfShape itC;
777     for (itC.Initialize(CL); itC.More(); itC.Next()) {
778       for (it.Initialize(itC.Value()); it.More(); it.Next()) {
779         if (it.Value().ShapeType() == TopAbs_COMPOUND) {
780           if (it.Value().IsSame(aSubShape))
781             return index;
782           else
783             index++;
784           CL.Append(it.Value());
785         }
786       }
787     }
788   } else {
789     TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
790     TopTools_MapOfShape M;
791     for (; anExp.More(); anExp.Next()) {
792       if (M.Add(anExp.Current())) {
793         if (anExp.Current().IsSame(aSubShape))
794           return index;
795         index++;
796       }
797     }
798   }
799
800   SetErrorCode("The sub-shape does not belong to the main shape");
801   return -1;
802 }
803
804 //=============================================================================
805 /*!
806  *  GetShapeTypeString
807  */
808 //=============================================================================
809 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
810 {
811   SetErrorCode(KO);
812
813   TCollection_AsciiString aTypeName ("Null Shape");
814
815   TopoDS_Shape aShape = theShape->GetValue();
816   if (aShape.IsNull())
817     return aTypeName;
818
819   switch (aShape.ShapeType() )
820   {
821   case TopAbs_COMPOUND:
822     aTypeName = "Compound";
823     break;
824   case  TopAbs_COMPSOLID:
825     aTypeName = "Compound Solid";
826     break;
827   case TopAbs_SOLID:
828     aTypeName = "Solid";
829     break;
830   case TopAbs_SHELL:
831     aTypeName = "Shell";
832     break;
833   case TopAbs_FACE:
834     {
835       BRepAdaptor_Surface surf (TopoDS::Face(aShape));
836       if (surf.GetType() == GeomAbs_Plane)
837         aTypeName = "Plane";
838       else if (surf.GetType() == GeomAbs_Cylinder)
839         aTypeName = "Cylindrical Face";
840       else if (surf.GetType() == GeomAbs_Sphere)
841         aTypeName = "Spherical Face";
842       else if (surf.GetType() == GeomAbs_Torus)
843         aTypeName = "Toroidal Face";
844       else if (surf.GetType() == GeomAbs_Cone)
845         aTypeName = "Conical Face";
846       else
847         aTypeName = "GEOM::FACE";
848     }
849     break;
850   case TopAbs_WIRE:
851     aTypeName = "Wire";
852     break;
853   case TopAbs_EDGE:
854     {
855       BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
856       if (curv.GetType() == GeomAbs_Line) {
857         if ((Abs(curv.FirstParameter()) >= 1E6) ||
858             (Abs(curv.LastParameter()) >= 1E6))
859           aTypeName = "Line";
860         else
861           aTypeName = "Edge" ;
862       } else if (curv.GetType() == GeomAbs_Circle) {
863         if (curv.IsClosed())
864           aTypeName = "Circle";
865         else
866           aTypeName = "Arc";
867       } else {
868         aTypeName = "Edge";
869       }
870     }
871     break;
872   case TopAbs_VERTEX:
873     aTypeName = "Vertex";
874     break;
875   case TopAbs_SHAPE:
876     aTypeName = "Shape";
877     break;
878   default:
879     aTypeName = "Shape of unknown type";
880   }
881
882   return aTypeName;
883 }
884
885
886 //=============================================================================
887 /*!
888  *  NumberOfFaces
889  */
890 //=============================================================================
891 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
892 {
893   SetErrorCode(KO);
894
895   Standard_Integer nb = 0;
896
897   if (theShape.IsNull()) return -1;
898   TopoDS_Shape aShape = theShape->GetValue();
899   if (aShape.IsNull()) return -1;
900
901   TopTools_MapOfShape mapShape;
902
903   TopExp_Explorer exp (aShape, TopAbs_FACE);
904   for (; exp.More(); exp.Next())
905     if (mapShape.Add(exp.Current()))
906       nb++;
907
908   SetErrorCode(OK);
909   return nb;
910 }
911
912 //=============================================================================
913 /*!
914  *  NumberOfEdges
915  */
916 //=============================================================================
917 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
918 {
919   SetErrorCode(KO);
920
921   Standard_Integer nb = 0;
922
923   if (theShape.IsNull()) return -1;
924   TopoDS_Shape aShape = theShape->GetValue();
925   if (aShape.IsNull()) return -1;
926
927   TopTools_MapOfShape mapShape;
928
929   TopExp_Explorer exp (aShape, TopAbs_EDGE);
930   for (; exp.More(); exp.Next())
931     if (mapShape.Add(exp.Current()))
932       nb++;
933
934   SetErrorCode(OK);
935   return nb;
936 }
937
938 //=============================================================================
939 /*!
940  *  ReverseShape
941  */
942 //=============================================================================
943 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
944 {
945   SetErrorCode(KO);
946
947   if (theShape.IsNull()) return NULL;
948
949   //Add a new reversed object
950   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
951
952   //Add a new Revese function
953   Handle(GEOM_Function) aFunction;
954   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
955   if (aFunction.IsNull()) return NULL;
956
957   //Check if the function is set correctly
958   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
959
960   GEOMImpl_IShapes aSI (aFunction);
961
962   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
963   if (aRefShape.IsNull()) return NULL;
964
965   aSI.SetBase(aRefShape);
966
967   //Compute the sub-shape value
968   try {
969 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
970     OCC_CATCH_SIGNALS;
971 #endif
972     if (!GetSolver()->ComputeFunction(aFunction)) {
973       SetErrorCode("Shape driver failed to reverse shape");
974       return NULL;
975     }
976   }
977   catch (Standard_Failure) {
978     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
979     SetErrorCode(aFail->GetMessageString());
980     return NULL;
981   }
982
983   //Make a Python command
984   GEOM::TPythonDump(aFunction) << aReversed
985     << " = geompy.ChangeOrientation(" << theShape << ")";
986
987   SetErrorCode(OK);
988   return aReversed;
989 }
990
991 //=============================================================================
992 /*!
993  *  GetFreeFacesIDs
994  */
995 //=============================================================================
996 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
997                                                  (Handle(GEOM_Object) theShape)
998 {
999   SetErrorCode(KO);
1000
1001   if (theShape.IsNull()) return NULL;
1002   TopoDS_Shape aShape = theShape->GetValue();
1003   if (aShape.IsNull()) return NULL;
1004
1005   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1006
1007   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1008   GEOMImpl_Block6Explorer::MapShapesAndAncestors
1009     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1010
1011   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1012
1013   if (nbFaces == 0) {
1014     SetErrorCode("The given shape has no faces");
1015     return aSeq;
1016   }
1017
1018   TopTools_IndexedMapOfShape anIndices;
1019   TopExp::MapShapes(aShape, anIndices);
1020
1021   Standard_Integer id;
1022   for (; ind <= nbFaces; ind++) {
1023     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1024       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1025       aSeq->Append(id);
1026     }
1027   }
1028
1029   //The explode doesn't change object so no new function is required.
1030   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1031
1032   //Make a Python command
1033   GEOM::TPythonDump(aFunction, /*append=*/true)
1034     << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
1035
1036   SetErrorCode(OK);
1037   return aSeq;
1038 }
1039
1040 //=======================================================================
1041 //function : GetSharedShapes
1042 //purpose  : 
1043 //=======================================================================
1044
1045 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1046                                                 (Handle(GEOM_Object)    theShape1,
1047                                                  Handle(GEOM_Object)    theShape2,
1048                                                  const Standard_Integer theShapeType)
1049 {
1050   SetErrorCode(KO);
1051
1052   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
1053
1054   TopoDS_Shape aShape1 = theShape1->GetValue();
1055   TopoDS_Shape aShape2 = theShape2->GetValue();
1056
1057   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
1058
1059   TopTools_IndexedMapOfShape anIndices;
1060   TopExp::MapShapes(aShape1, anIndices);
1061   Handle(TColStd_HArray1OfInteger) anArray;
1062
1063   TopTools_IndexedMapOfShape mapShape1;
1064   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
1065
1066   Handle(GEOM_Object) anObj;
1067   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1068   TCollection_AsciiString anAsciiList, anEntry;
1069
1070   TopTools_MapOfShape mapShape2;
1071   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
1072   for (; exp.More(); exp.Next()) {
1073     TopoDS_Shape aSS = exp.Current();
1074     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
1075       anArray = new TColStd_HArray1OfInteger(1,1);
1076       anArray->SetValue(1, anIndices.FindIndex(aSS));
1077       anObj = GetEngine()->AddSubShape(theShape1, anArray);
1078       aSeq->Append(anObj);
1079
1080       // for python command
1081       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1082       anAsciiList += anEntry;
1083       anAsciiList += ",";
1084     }
1085   }
1086
1087   if (aSeq->IsEmpty()) {
1088     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
1089     return aSeq;
1090   }
1091
1092   //Make a Python command
1093   anAsciiList.Trunc(anAsciiList.Length() - 1);
1094
1095   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1096
1097   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1098     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
1099       << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1100
1101   SetErrorCode(OK);
1102   return aSeq;
1103 }
1104
1105 //=============================================================================
1106 /*!
1107  *  
1108  */
1109 //=============================================================================
1110 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
1111                                       const GEOMAlgo_State theState)
1112 {
1113   switch (theState) {
1114   case GEOMAlgo_ST_IN:
1115     theDump << "geompy.GEOM.ST_IN";
1116     break;
1117   case GEOMAlgo_ST_OUT:
1118     theDump << "geompy.GEOM.ST_OUT";
1119     break;
1120   case GEOMAlgo_ST_ON:
1121     theDump << "geompy.GEOM.ST_ON";
1122     break;
1123   case GEOMAlgo_ST_ONIN:
1124     theDump << "geompy.GEOM.ST_ONIN";
1125     break;
1126   case GEOMAlgo_ST_ONOUT:
1127     theDump << "geompy.GEOM.ST_ONOUT";
1128     break;
1129   default:
1130     theDump << "geompy.GEOM.ST_UNKNOWN";
1131     break;
1132   }
1133   return theDump;
1134 }
1135
1136 //=======================================================================
1137 //function : checkTypeShapesOn
1138 /*!
1139  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
1140  * \param theShapeType - the shape type to check
1141  * \retval bool  - result of the check
1142  */
1143 //=======================================================================
1144
1145 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
1146 {
1147   if (theShapeType != TopAbs_VERTEX &&
1148       theShapeType != TopAbs_EDGE &&
1149       theShapeType != TopAbs_FACE &&
1150       theShapeType != TopAbs_SOLID) {
1151     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1152     return false;
1153   }
1154   return true;
1155 }
1156
1157 //=======================================================================
1158 //function : makePlane
1159   /*!
1160    * \brief Creates Geom_Plane
1161     * \param theAx1 - shape object defining plane parameters
1162     * \retval Handle(Geom_Surface) - resulting surface
1163    */
1164 //=======================================================================
1165
1166 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
1167 {
1168   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1169   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1170   TopoDS_Vertex V1, V2;
1171   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1172   if (V1.IsNull() || V2.IsNull()) {
1173     SetErrorCode("Bad edge given for the plane normal vector");
1174     return NULL;
1175   }
1176   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1177   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1178   if (aVec.Magnitude() < Precision::Confusion()) {
1179     SetErrorCode("Vector with null magnitude given");
1180     return NULL;
1181   }
1182   return new Geom_Plane(aLoc, aVec);
1183 }
1184
1185 //=======================================================================
1186 //function : makeCylinder
1187   /*!
1188    * \brief Creates Geom_CylindricalSurface
1189     * \param theAx1 - edge defining cylinder axis
1190     * \param theRadius - cylinder radius
1191     * \retval Handle(Geom_Surface) - resulting surface
1192    */
1193 //=======================================================================
1194
1195 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
1196                                                               const Standard_Real theRadius)
1197 {
1198   //Axis of the cylinder
1199   if (anAxis.ShapeType() != TopAbs_EDGE) {
1200     SetErrorCode("Not an edge given for the axis");
1201     return NULL;
1202   }
1203   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1204   TopoDS_Vertex V1, V2;
1205   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1206   if (V1.IsNull() || V2.IsNull()) {
1207     SetErrorCode("Bad edge given for the axis");
1208     return NULL;
1209   }
1210   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1211   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1212   if (aVec.Magnitude() < Precision::Confusion()) {
1213     SetErrorCode("Vector with null magnitude given");
1214     return NULL;
1215   }
1216
1217   gp_Ax3 anAx3 (aLoc, aVec);
1218   return new Geom_CylindricalSurface(anAx3, theRadius);
1219 }
1220
1221
1222 //=======================================================================
1223 //function : getShapesOnSurfaceIDs
1224   /*!
1225    * \brief Find IDs of subshapes complying with given status about surface
1226     * \param theSurface - the surface to check state of subshapes against
1227     * \param theShape - the shape to explore
1228     * \param theShapeType - type of subshape of theShape
1229     * \param theState - required state
1230     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1231    */
1232 //=======================================================================
1233
1234 Handle(TColStd_HSequenceOfInteger)
1235   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
1236                                                     const TopoDS_Shape&         theShape,
1237                                                     TopAbs_ShapeEnum            theShapeType,
1238                                                     GEOMAlgo_State              theState)
1239 {
1240   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1241
1242   // Check presence of triangulation, build if need
1243   if (!CheckTriangulation(theShape))
1244     return aSeqOfIDs;
1245
1246   // Call algo
1247   GEOMAlgo_FinderShapeOn1 aFinder;
1248   Standard_Real aTol = 0.0001; // default value
1249
1250   aFinder.SetShape(theShape);
1251   aFinder.SetTolerance(aTol);
1252   aFinder.SetSurface(theSurface);
1253   aFinder.SetShapeType(theShapeType);
1254   aFinder.SetState(theState);
1255
1256   // Sets the minimal number of inner points for the faces that do not have own
1257   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1258   // Default value=3
1259   aFinder.SetNbPntsMin(3);
1260   // Sets the maximal number of inner points for edges or faces.
1261   // It is usefull for the cases when this number is very big (e.g =2000) to improve
1262   // the performance. If this value =0, all inner points will be taken into account.
1263   // Default value=0
1264   aFinder.SetNbPntsMax(100);
1265
1266   aFinder.Perform();
1267
1268   // Interprete results
1269   Standard_Integer iErr = aFinder.ErrorStatus();
1270   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1271   if (iErr) {
1272     MESSAGE(" iErr : " << iErr);
1273     TCollection_AsciiString aMsg (" iErr : ");
1274     aMsg += TCollection_AsciiString(iErr);
1275     SetErrorCode(aMsg);
1276     return aSeqOfIDs;
1277   }
1278   Standard_Integer iWrn = aFinder.WarningStatus();
1279   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1280   if (iWrn) {
1281     MESSAGE(" *** iWrn : " << iWrn);
1282   }
1283
1284   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1285
1286   if (listSS.Extent() < 1) {
1287     SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1288     return aSeqOfIDs;
1289   }
1290
1291   // Fill sequence of object IDs
1292   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1293
1294   TopTools_IndexedMapOfShape anIndices;
1295   TopExp::MapShapes(theShape, anIndices);
1296
1297   TopTools_ListIteratorOfListOfShape itSub (listSS);
1298   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1299     int id = anIndices.FindIndex(itSub.Value());
1300     aSeqOfIDs->Append(id);
1301   }
1302
1303   return aSeqOfIDs;
1304 }
1305
1306 //=======================================================================
1307 //function : getObjectsShapesOn
1308 /*!
1309  * \brief Find shape objects and their entries by their ids
1310  * \param theShapeIDs - incoming shape ids
1311  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1312  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
1313  */
1314 //=======================================================================
1315
1316 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
1317  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
1318                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
1319                     TCollection_AsciiString &                 theShapeEntries)
1320 {
1321   Handle(TColStd_HSequenceOfTransient) aSeq;
1322
1323   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
1324   {
1325     aSeq = new TColStd_HSequenceOfTransient;
1326     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1327     TCollection_AsciiString anEntry;
1328     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
1329     {
1330       anArray->SetValue(1, theShapeIDs->Value( i ));
1331       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
1332       aSeq->Append( anObj );
1333
1334       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1335       if ( i != 1 ) theShapeEntries += ",";
1336       theShapeEntries += anEntry;
1337     }
1338   }
1339   return aSeq;
1340 }
1341
1342 //=======================================================================
1343 //function : getShapesOnSurface
1344 /*!
1345    * \brief Find subshapes complying with given status about surface
1346     * \param theSurface - the surface to check state of subshapes against
1347     * \param theShape - the shape to explore
1348     * \param theShapeType - type of subshape of theShape
1349     * \param theState - required state
1350     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1351     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1352  */
1353 //=======================================================================
1354
1355 Handle(TColStd_HSequenceOfTransient)
1356     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
1357                                                    const Handle(GEOM_Object)&  theShape,
1358                                                    TopAbs_ShapeEnum            theShapeType,
1359                                                    GEOMAlgo_State              theState,
1360                                                    TCollection_AsciiString &   theShapeEntries)
1361 {
1362   // Find subshapes ids
1363   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1364     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
1365   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1366     return NULL;
1367
1368   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
1369 }
1370
1371 //=============================================================================
1372 /*!
1373  *  GetShapesOnPlane
1374  */
1375 //=============================================================================
1376 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
1377                                         (const Handle(GEOM_Object)& theShape,
1378                                          const Standard_Integer     theShapeType,
1379                                          const Handle(GEOM_Object)& theAx1,
1380                                          const GEOMAlgo_State       theState)
1381 {
1382   SetErrorCode(KO);
1383
1384   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1385
1386   TopoDS_Shape aShape = theShape->GetValue();
1387   TopoDS_Shape anAx1  = theAx1->GetValue();
1388
1389   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1390
1391   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1392   if ( !checkTypeShapesOn( theShapeType ))
1393     return NULL;
1394
1395   // Create plane
1396   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1397   if ( aPlane.IsNull() )
1398     return NULL;
1399
1400   // Find objects
1401   TCollection_AsciiString anAsciiList;
1402   Handle(TColStd_HSequenceOfTransient) aSeq;
1403   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1404   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1405     return NULL;
1406
1407   // Make a Python command
1408
1409   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1410   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1411
1412   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1413     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
1414       << aShapeType << ", " << theAx1 << ", " << theState << ")";
1415
1416   SetErrorCode(OK);
1417   return aSeq;
1418 }
1419
1420 //=============================================================================
1421 /*!
1422  *  GetShapesOnPlaneWithLocation
1423  */
1424 //=============================================================================
1425 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
1426                                         (const Handle(GEOM_Object)& theShape,
1427                                          const Standard_Integer     theShapeType,
1428                                          const Handle(GEOM_Object)& theAx1,
1429                                          const Handle(GEOM_Object)& thePnt,
1430                                          const GEOMAlgo_State       theState)
1431 {
1432   SetErrorCode(KO);
1433
1434   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
1435
1436   TopoDS_Shape aShape = theShape->GetValue();
1437   TopoDS_Shape anAx1  = theAx1->GetValue();
1438   TopoDS_Shape anPnt = thePnt->GetValue();
1439
1440   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
1441
1442   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1443   if ( !checkTypeShapesOn( theShapeType ))
1444     return NULL;
1445
1446   // Create plane
1447   if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
1448   TopoDS_Vertex V1, V2, V3;
1449   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1450   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1451
1452   if (V1.IsNull() || V2.IsNull()) {
1453     SetErrorCode("Bad edge given for the plane normal vector");
1454     return NULL;
1455   }
1456   V3 = TopoDS::Vertex(anPnt);
1457
1458   if(V3.IsNull()) {
1459     SetErrorCode("Bad vertex given for the plane location");
1460       return NULL;
1461   }
1462   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
1463   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
1464
1465   if (aVec.Magnitude() < Precision::Confusion()) {
1466      SetErrorCode("Vector with null magnitude given");
1467     return NULL;
1468   }
1469   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
1470
1471   if ( aPlane.IsNull() )
1472     return NULL;
1473   
1474   // Find objects
1475   TCollection_AsciiString anAsciiList;
1476   Handle(TColStd_HSequenceOfTransient) aSeq;
1477   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1478   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1479     return NULL;
1480
1481   // Make a Python command
1482
1483   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1484   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1485
1486   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1487     << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
1488     << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
1489
1490   SetErrorCode(OK);
1491   return aSeq;
1492 }
1493
1494 //=============================================================================
1495 /*!
1496  *  GetShapesOnCylinder
1497  */
1498 //=============================================================================
1499 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
1500                                           (const Handle(GEOM_Object)& theShape,
1501                                            const Standard_Integer     theShapeType,
1502                                            const Handle(GEOM_Object)& theAxis,
1503                                            const Standard_Real        theRadius,
1504                                            const GEOMAlgo_State       theState)
1505 {
1506   SetErrorCode(KO);
1507
1508   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1509
1510   TopoDS_Shape aShape = theShape->GetValue();
1511   TopoDS_Shape anAxis = theAxis->GetValue();
1512
1513   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1514
1515   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1516   if ( !checkTypeShapesOn( aShapeType ))
1517     return NULL;
1518
1519   // Create a cylinder surface
1520   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1521   if ( aCylinder.IsNull() )
1522     return NULL;
1523
1524   // Find objects
1525   TCollection_AsciiString anAsciiList;
1526   Handle(TColStd_HSequenceOfTransient) aSeq;
1527   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
1528   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1529     return NULL;
1530   
1531   // Make a Python command
1532
1533   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1534   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1535
1536   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1537     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
1538       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
1539
1540   SetErrorCode(OK);
1541   return aSeq;
1542 }
1543
1544 //=============================================================================
1545 /*!
1546  *  GetShapesOnSphere
1547  */
1548 //=============================================================================
1549 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
1550                                           (const Handle(GEOM_Object)& theShape,
1551                                            const Standard_Integer     theShapeType,
1552                                            const Handle(GEOM_Object)& theCenter,
1553                                            const Standard_Real        theRadius,
1554                                            const GEOMAlgo_State       theState)
1555 {
1556   SetErrorCode(KO);
1557
1558   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1559
1560   TopoDS_Shape aShape  = theShape->GetValue();
1561   TopoDS_Shape aCenter = theCenter->GetValue();
1562
1563   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1564
1565   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1566   if ( !checkTypeShapesOn( aShapeType ))
1567     return NULL;
1568
1569   // Center of the sphere
1570   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1571   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1572
1573   gp_Ax3 anAx3 (aLoc, gp::DZ());
1574   Handle(Geom_SphericalSurface) aSphere =
1575     new Geom_SphericalSurface(anAx3, theRadius);
1576
1577   // Find objects
1578   TCollection_AsciiString anAsciiList;
1579   Handle(TColStd_HSequenceOfTransient) aSeq;
1580   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
1581   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1582     return NULL;
1583     
1584   // Make a Python command
1585
1586   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1587   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1588
1589   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1590     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
1591       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
1592
1593   SetErrorCode(OK);
1594   return aSeq;
1595 }
1596
1597 //=============================================================================
1598 /*!
1599  *  GetShapesOnPlaneIDs
1600  */
1601 //=============================================================================
1602 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
1603                                         (const Handle(GEOM_Object)& theShape,
1604                                          const Standard_Integer     theShapeType,
1605                                          const Handle(GEOM_Object)& theAx1,
1606                                          const GEOMAlgo_State       theState)
1607 {
1608   SetErrorCode(KO);
1609
1610   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1611
1612   TopoDS_Shape aShape = theShape->GetValue();
1613   TopoDS_Shape anAx1  = theAx1->GetValue();
1614
1615   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1616
1617   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1618   if ( !checkTypeShapesOn( aShapeType ))
1619     return NULL;
1620
1621   // Create plane
1622   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1623   if ( aPlane.IsNull() )
1624     return NULL;
1625
1626   // Find object IDs
1627   Handle(TColStd_HSequenceOfInteger) aSeq;
1628   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
1629
1630   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
1631   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
1632
1633   // Make a Python command
1634   GEOM::TPythonDump(aFunction, /*append=*/true)
1635     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
1636     << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
1637
1638   SetErrorCode(OK);
1639   return aSeq;
1640 }
1641
1642 //=============================================================================
1643 /*!
1644  *  GetShapesOnPlaneWithLocationIDs
1645  */
1646 //=============================================================================
1647 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
1648                                         (const Handle(GEOM_Object)& theShape,
1649                                          const Standard_Integer     theShapeType,
1650                                          const Handle(GEOM_Object)& theAx1,
1651                                          const Handle(GEOM_Object)& thePnt,
1652                                          const GEOMAlgo_State       theState)
1653 {
1654   SetErrorCode(KO);
1655
1656   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
1657
1658   TopoDS_Shape aShape = theShape->GetValue();
1659   TopoDS_Shape anAx1  = theAx1->GetValue();
1660   TopoDS_Shape anPnt  = thePnt->GetValue();
1661
1662   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
1663
1664   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1665   if ( !checkTypeShapesOn( aShapeType ))
1666     return NULL;
1667
1668   // Create plane
1669   if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
1670   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1671   TopoDS_Vertex V1, V2, V3;
1672   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1673   if (V1.IsNull() || V2.IsNull()) {
1674     SetErrorCode("Bad edge given for the plane normal vector");
1675     return NULL;
1676   }
1677   V3 = TopoDS::Vertex(anPnt);
1678   if(V3.IsNull()) {
1679     SetErrorCode("Bad vertex given for the plane location");
1680       return NULL;
1681   }
1682   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
1683   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
1684   if (aVec.Magnitude() < Precision::Confusion()) {
1685     SetErrorCode("Vector with null magnitude given");
1686     return NULL;
1687   }
1688   
1689   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);  
1690   if ( aPlane.IsNull() )
1691     return NULL;
1692
1693   // Find object IDs
1694   Handle(TColStd_HSequenceOfInteger) aSeq;
1695   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
1696
1697   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
1698   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
1699
1700   // Make a Python command
1701   GEOM::TPythonDump(aFunction, /*append=*/true)
1702     << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
1703     << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
1704
1705   SetErrorCode(OK);
1706   return aSeq;
1707 }
1708
1709 //=============================================================================
1710 /*!
1711  *  GetShapesOnCylinderIDs
1712  */
1713 //=============================================================================
1714 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
1715                                           (const Handle(GEOM_Object)& theShape,
1716                                            const Standard_Integer     theShapeType,
1717                                            const Handle(GEOM_Object)& theAxis,
1718                                            const Standard_Real        theRadius,
1719                                            const GEOMAlgo_State       theState)
1720 {
1721   SetErrorCode(KO);
1722
1723   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1724
1725   TopoDS_Shape aShape = theShape->GetValue();
1726   TopoDS_Shape anAxis = theAxis->GetValue();
1727
1728   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1729
1730   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1731   if ( !checkTypeShapesOn( aShapeType ))
1732     return NULL;
1733
1734   // Create a cylinder surface
1735   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1736   if ( aCylinder.IsNull() )
1737     return NULL;
1738   
1739   // Find object IDs
1740   Handle(TColStd_HSequenceOfInteger) aSeq;
1741   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
1742
1743   // The GetShapesOnCylinder() doesn't change object so no new function is required.
1744   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
1745
1746   // Make a Python command
1747   GEOM::TPythonDump(aFunction, /*append=*/true)
1748     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
1749     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
1750     << theRadius << ", " << theState << ")";
1751
1752   SetErrorCode(OK);
1753   return aSeq;
1754 }
1755
1756 //=============================================================================
1757 /*!
1758  *  GetShapesOnSphereIDs
1759  */
1760 //=============================================================================
1761 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
1762                                           (const Handle(GEOM_Object)& theShape,
1763                                            const Standard_Integer     theShapeType,
1764                                            const Handle(GEOM_Object)& theCenter,
1765                                            const Standard_Real        theRadius,
1766                                            const GEOMAlgo_State       theState)
1767 {
1768   SetErrorCode(KO);
1769
1770   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1771
1772   TopoDS_Shape aShape  = theShape->GetValue();
1773   TopoDS_Shape aCenter = theCenter->GetValue();
1774
1775   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1776
1777   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1778   if ( !checkTypeShapesOn( aShapeType ))
1779     return NULL;
1780
1781   // Center of the sphere
1782   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1783   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1784
1785   gp_Ax3 anAx3 (aLoc, gp::DZ());
1786   Handle(Geom_SphericalSurface) aSphere =
1787     new Geom_SphericalSurface(anAx3, theRadius);
1788
1789   // Find object IDs
1790   Handle(TColStd_HSequenceOfInteger) aSeq;
1791   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
1792   
1793   // The GetShapesOnSphere() doesn't change object so no new function is required.
1794   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
1795
1796   // Make a Python command
1797   GEOM::TPythonDump(aFunction, /*append=*/true)
1798     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
1799     << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
1800     << theRadius << ", " << theState << ")";
1801
1802   SetErrorCode(OK);
1803   return aSeq;
1804 }
1805
1806 //=======================================================================
1807 //function : getShapesOnQuadrangleIDs
1808   /*!
1809    * \brief Find IDs of subshapes complying with given status about quadrangle
1810     * \param theShape - the shape to explore
1811     * \param theShapeType - type of subshape of theShape
1812     * \param theTopLeftPoint - top left quadrangle corner
1813     * \param theTopRigthPoint - top right quadrangle corner
1814     * \param theBottomLeftPoint - bottom left quadrangle corner
1815     * \param theBottomRigthPoint - bottom right quadrangle corner
1816     * \param theState - required state
1817     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1818    */
1819 //=======================================================================
1820
1821 Handle(TColStd_HSequenceOfInteger)
1822   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
1823                                                         const Standard_Integer     theShapeType,
1824                                                         const Handle(GEOM_Object)& theTopLeftPoint,
1825                                                         const Handle(GEOM_Object)& theTopRigthPoint,
1826                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
1827                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
1828                                                         const GEOMAlgo_State       theState)
1829 {
1830   SetErrorCode(KO);
1831
1832   if ( theShape.IsNull() ||
1833        theTopLeftPoint.IsNull() ||
1834        theTopRigthPoint.IsNull() ||
1835        theBottomLeftPoint.IsNull() ||
1836        theBottomRigthPoint.IsNull() )
1837     return NULL;
1838
1839   TopoDS_Shape aShape = theShape->GetValue();
1840   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
1841   TopoDS_Shape aTR = theTopRigthPoint->GetValue();
1842   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
1843   TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
1844
1845   if (aShape.IsNull() ||
1846       aTL.IsNull() || 
1847       aTR.IsNull() || 
1848       aBL.IsNull() || 
1849       aBR.IsNull() ||
1850       aTL.ShapeType() != TopAbs_VERTEX || 
1851       aTR.ShapeType() != TopAbs_VERTEX || 
1852       aBL.ShapeType() != TopAbs_VERTEX || 
1853       aBR.ShapeType() != TopAbs_VERTEX )
1854     return NULL;
1855
1856   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1857   if ( !checkTypeShapesOn( aShapeType ))
1858     return NULL;
1859
1860   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1861
1862   // Check presence of triangulation, build if need
1863   if (!CheckTriangulation(aShape))
1864     return aSeqOfIDs;
1865
1866   // Call algo
1867   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
1868   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
1869   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
1870   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
1871
1872   GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
1873   Standard_Real aTol = 0.0001; // default value
1874
1875   aFinder.SetShape(aShape);
1876   aFinder.SetTolerance(aTol);
1877   //aFinder.SetSurface(theSurface);
1878   aFinder.SetShapeType(aShapeType);
1879   aFinder.SetState(theState);
1880
1881   // Sets the minimal number of inner points for the faces that do not have own
1882   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1883   // Default value=3
1884   aFinder.SetNbPntsMin(3);
1885   // Sets the maximal number of inner points for edges or faces.
1886   // It is usefull for the cases when this number is very big (e.g =2000) to improve
1887   // the performance. If this value =0, all inner points will be taken into account.
1888   // Default value=0
1889   aFinder.SetNbPntsMax(100);
1890
1891   aFinder.Perform();
1892
1893   // Interprete results
1894   Standard_Integer iErr = aFinder.ErrorStatus();
1895   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1896   if (iErr) {
1897     MESSAGE(" iErr : " << iErr);
1898     TCollection_AsciiString aMsg (" iErr : ");
1899     aMsg += TCollection_AsciiString(iErr);
1900     SetErrorCode(aMsg);
1901     return aSeqOfIDs;
1902   }
1903   Standard_Integer iWrn = aFinder.WarningStatus();
1904   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1905   if (iWrn) {
1906     MESSAGE(" *** iWrn : " << iWrn);
1907   }
1908
1909   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1910
1911   if (listSS.Extent() < 1) {
1912     SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1913     return aSeqOfIDs;
1914   }
1915
1916   // Fill sequence of object IDs
1917   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1918
1919   TopTools_IndexedMapOfShape anIndices;
1920   TopExp::MapShapes(aShape, anIndices);
1921
1922   TopTools_ListIteratorOfListOfShape itSub (listSS);
1923   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1924     int id = anIndices.FindIndex(itSub.Value());
1925     aSeqOfIDs->Append(id);
1926   }
1927   return aSeqOfIDs;
1928 }
1929
1930 //=======================================================================
1931 //function : GetShapesOnQuadrangle
1932   /*!
1933    * \brief Find subshapes complying with given status about quadrangle
1934     * \param theShape - the shape to explore
1935     * \param theShapeType - type of subshape of theShape
1936     * \param theTopLeftPoint - top left quadrangle corner
1937     * \param theTopRigthPoint - top right quadrangle corner
1938     * \param theBottomLeftPoint - bottom left quadrangle corner
1939     * \param theBottomRigthPoint - bottom right quadrangle corner
1940     * \param theState - required state
1941     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1942    */
1943 //=======================================================================
1944
1945 Handle(TColStd_HSequenceOfTransient)
1946     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
1947                                                        const Standard_Integer     theShapeType,
1948                                                        const Handle(GEOM_Object)& theTopLeftPoint,
1949                                                        const Handle(GEOM_Object)& theTopRigthPoint,
1950                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
1951                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
1952                                                        const GEOMAlgo_State       theState)
1953 {
1954   // Find indices
1955   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1956     getShapesOnQuadrangleIDs( theShape,
1957                               theShapeType,
1958                               theTopLeftPoint,
1959                               theTopRigthPoint,
1960                               theBottomLeftPoint,
1961                               theBottomRigthPoint,
1962                               theState);
1963   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
1964     return NULL;
1965
1966   // Find objects by indices
1967   TCollection_AsciiString anAsciiList;
1968   Handle(TColStd_HSequenceOfTransient) aSeq;
1969   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1970   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1971     return NULL;
1972
1973   // Make a Python command
1974
1975   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1976   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1977
1978   GEOM::TPythonDump(aFunction)
1979     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
1980     << theShape << ", "
1981     << TopAbs_ShapeEnum(theShapeType) << ", "
1982     << theTopLeftPoint << ", "
1983     << theTopRigthPoint << ", "
1984     << theBottomLeftPoint << ", "
1985     << theBottomRigthPoint << ", "
1986     << theState << ")";
1987
1988   SetErrorCode(OK);
1989   return aSeq;
1990 }
1991
1992 //=======================================================================
1993 //function : GetShapesOnQuadrangleIDs
1994   /*!
1995    * \brief Find IDs of subshapes complying with given status about quadrangle
1996     * \param theShape - the shape to explore
1997     * \param theShapeType - type of subshape of theShape
1998     * \param theTopLeftPoint - top left quadrangle corner
1999     * \param theTopRigthPoint - top right quadrangle corner
2000     * \param theBottomLeftPoint - bottom left quadrangle corner
2001     * \param theBottomRigthPoint - bottom right quadrangle corner
2002     * \param theState - required state
2003     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2004    */
2005 //=======================================================================
2006
2007 Handle(TColStd_HSequenceOfInteger)
2008   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2009                                                         const Standard_Integer     theShapeType,
2010                                                         const Handle(GEOM_Object)& theTopLeftPoint,
2011                                                         const Handle(GEOM_Object)& theTopRigthPoint,
2012                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
2013                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
2014                                                         const GEOMAlgo_State       theState)
2015 {
2016   // Find indices
2017   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2018     getShapesOnQuadrangleIDs( theShape,
2019                               theShapeType,
2020                               theTopLeftPoint,
2021                               theTopRigthPoint,
2022                               theBottomLeftPoint,
2023                               theBottomRigthPoint,
2024                               theState);
2025   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2026     return NULL;
2027
2028   // Make a Python command
2029
2030   // The GetShapesOnCylinder() doesn't change object so no new function is required.
2031   Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
2032   lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
2033   lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
2034   lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
2035   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
2036
2037   GEOM::TPythonDump(aFunction, /*append=*/true)
2038     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
2039     << theShape << ", "
2040     << TopAbs_ShapeEnum(theShapeType) << ", "
2041     << theTopLeftPoint << ", "
2042     << theTopRigthPoint << ", "
2043     << theBottomLeftPoint << ", "
2044     << theBottomRigthPoint << ", "
2045     << theState << ")";
2046
2047   SetErrorCode(OK);
2048   return aSeqOfIDs;
2049 }
2050
2051
2052 //=============================================================================
2053 /*!
2054  *  GetInPlace
2055  */
2056 //=============================================================================
2057 static void SimplifyWhat (TopoDS_Shape& theWhat,
2058                           TopTools_IndexedMapOfShape& theArgumentIndices,
2059                           TColStd_ListOfInteger& theSimpleSubWhat)
2060 {
2061   TopTools_MapOfShape mapShape;
2062   TopoDS_Iterator It (theWhat, Standard_True, Standard_True);
2063   for (; It.More(); It.Next()) {
2064     if (mapShape.Add(It.Value())) {
2065       TopoDS_Shape curSh = It.Value();
2066       if (curSh.ShapeType() == TopAbs_COMPOUND ||
2067           curSh.ShapeType() == TopAbs_COMPSOLID) {
2068         SimplifyWhat(curSh, theArgumentIndices, theSimpleSubWhat);
2069       } else {
2070         theSimpleSubWhat.Append(theArgumentIndices.FindIndex(curSh));
2071       }
2072     }
2073   }
2074 }
2075
2076 static bool GetInPlaceOfCompound (Handle(GEOM_Function)& theWhereFunction,
2077                                   TopoDS_Shape& theWhat,
2078                                   TColStd_ListOfInteger& theModifiedArray)
2079 {
2080   bool isFoundAny = false;
2081   TopTools_MapOfShape mapShape;
2082   TopoDS_Iterator It (theWhat, Standard_True, Standard_True);
2083   for (; It.More(); It.Next()) {
2084     if (mapShape.Add(It.Value())) {
2085       TopoDS_Shape curWhat = It.Value();
2086       if (curWhat.ShapeType() == TopAbs_COMPOUND ||
2087           curWhat.ShapeType() == TopAbs_COMPSOLID) {
2088         // Recursive call for compound or compsolid
2089         if (GetInPlaceOfCompound(theWhereFunction, curWhat, theModifiedArray))
2090           isFoundAny = true;
2091       } else {
2092         // Try to find for "simple" shape
2093         bool isFound = false;
2094
2095         TDF_LabelSequence aLabelSeq;
2096         theWhereFunction->GetDependency(aLabelSeq);
2097         Standard_Integer nbArg = aLabelSeq.Length();
2098
2099         for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
2100
2101           TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
2102
2103           Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
2104           TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
2105
2106           TopTools_IndexedMapOfShape anArgumentIndices;
2107           TopExp::MapShapes(anArgumentShape, anArgumentIndices);
2108
2109           if (anArgumentIndices.Contains(curWhat)) {
2110             isFound = Standard_True;
2111             Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(curWhat);
2112
2113             // Find corresponding label in history
2114             TDF_Label anArgumentHistoryLabel =
2115               theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
2116             if (!anArgumentHistoryLabel.IsNull()) {
2117               TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
2118               if (!aWhatHistoryLabel.IsNull()) {
2119                 Handle(TDataStd_IntegerArray) anIntegerArray;
2120                 if (aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2121                   Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
2122                   for (imod = 1; imod <= aModifLen; imod++) {
2123                     theModifiedArray.Append(anIntegerArray->Array()->Value(imod));
2124                   }
2125                 }
2126               }
2127             }
2128           }
2129         }
2130         if (isFound)
2131           isFoundAny = true;
2132       }
2133     }
2134   }
2135   return isFoundAny;
2136 }
2137
2138 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
2139                                           (Handle(GEOM_Object) theShapeWhere,
2140                                            Handle(GEOM_Object) theShapeWhat)
2141 {
2142   SetErrorCode(KO);
2143
2144   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2145
2146   TopoDS_Shape aWhere = theShapeWhere->GetValue();
2147   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
2148
2149   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
2150
2151   //Fill array of indices
2152   Handle(TColStd_HArray1OfInteger) aModifiedArray;
2153
2154   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
2155
2156   TopTools_IndexedMapOfShape aWhereIndices;
2157   TopExp::MapShapes(aWhere, aWhereIndices);
2158
2159   if (aWhereIndices.Contains(aWhat)) {
2160
2161     // entity was not changed by the operation
2162     Standard_Integer aWhatIndex = aWhereIndices.FindIndex(aWhat);
2163     aModifiedArray = new TColStd_HArray1OfInteger(1,1);
2164     aModifiedArray->SetValue(1, aWhatIndex);
2165
2166   } else {
2167
2168     TDF_Label aHistoryLabel = aWhereFunction->GetHistoryEntry(Standard_False);
2169     if (aHistoryLabel.IsNull()) {
2170       SetErrorCode("Modifications history does not exist for the shape under consideration.");
2171       return NULL;
2172     }
2173
2174     // search in history for all argument shapes
2175     Standard_Boolean isFound = Standard_False;
2176
2177     TDF_LabelSequence aLabelSeq;
2178     aWhereFunction->GetDependency(aLabelSeq);
2179     Standard_Integer nbArg = aLabelSeq.Length();
2180
2181     for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
2182
2183       TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
2184
2185       Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
2186       TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
2187
2188       TopTools_IndexedMapOfShape anArgumentIndices;
2189       TopExp::MapShapes(anArgumentShape, anArgumentIndices);
2190
2191       if (anArgumentIndices.Contains(aWhat)) {
2192         isFound = Standard_True;
2193         Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(aWhat);
2194
2195         // Find corresponding label in history
2196         TDF_Label anArgumentHistoryLabel =
2197           aWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
2198         if (anArgumentHistoryLabel.IsNull()) {
2199           // Lost History of operation argument. Possibly, all its entities was removed.
2200           SetErrorCode(OK);
2201           return NULL;
2202         }
2203
2204         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
2205         if (aWhatHistoryLabel.IsNull()) {
2206           // Check, if the sought shape is Compound or Compsolid.
2207           // In that case we will try to find history for its sub-shapes
2208           if (aWhat.ShapeType() == TopAbs_COMPOUND ||
2209               aWhat.ShapeType() == TopAbs_COMPSOLID) {
2210             TColStd_ListOfInteger aSimpleSubWhat, aModifiedList;
2211             SimplifyWhat(aWhat, anArgumentIndices, aSimpleSubWhat);
2212             TColStd_ListIteratorOfListOfInteger anIterSub (aSimpleSubWhat);
2213             for (; anIterSub.More(); anIterSub.Next()) {
2214               Standard_Integer aSubWhatIndex = anIterSub.Value();
2215               TDF_Label aSubWhatHistoryLabel =
2216                 anArgumentHistoryLabel.FindChild(aSubWhatIndex, Standard_False);
2217               if (!aSubWhatHistoryLabel.IsNull()) {
2218                 Handle(TDataStd_IntegerArray) anIntegerArray;
2219                 if (aSubWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2220                   for (Standard_Integer isub = 1; isub <= anIntegerArray->Length(); isub++) {
2221                     aModifiedList.Append(anIntegerArray->Value(isub));
2222                   }
2223                 }
2224               }
2225             }
2226             if (aModifiedList.Extent() > 0) {
2227               Handle(TColStd_HArray1OfInteger) aModifiedArraySub =
2228                 new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
2229               TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
2230               for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
2231                 aModifiedArraySub->SetValue(imod, anIterModif.Value());
2232               }
2233               aModifiedArray = aModifiedArraySub;
2234             } else {
2235               // Removed entity
2236               SetErrorCode(OK);
2237               return NULL;
2238             }
2239           } else {
2240             // Removed entity
2241             SetErrorCode(OK);
2242             return NULL;
2243           }
2244         } else {
2245           Handle(TDataStd_IntegerArray) anIntegerArray;
2246           if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2247             SetErrorCode("Error: Empty modifications history for the sought shape.");
2248             return NULL;
2249           }
2250
2251           aModifiedArray = anIntegerArray->Array();
2252           if (aModifiedArray->Length() == 0) {
2253             SetErrorCode("Error: Empty modifications history for the sought shape.");
2254             return NULL;
2255           }
2256         }
2257       }
2258     }
2259
2260     if (!isFound) {
2261       // try compound element by element
2262       if (aWhat.ShapeType() == TopAbs_COMPOUND ||
2263           aWhat.ShapeType() == TopAbs_COMPSOLID) {
2264         TColStd_ListOfInteger aModifiedList;
2265         isFound = GetInPlaceOfCompound(aWhereFunction, aWhat, aModifiedList);
2266         if (isFound) {
2267           aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
2268           TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
2269           for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
2270             aModifiedArray->SetValue(imod, anIterModif.Value());
2271           }
2272         }
2273       }
2274       if (!isFound) {
2275         SetErrorCode("The sought shape does not belong to any operation argument.");
2276         return NULL;
2277       }
2278     }
2279   }
2280
2281   //Add a new object
2282   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
2283
2284   if (aModifiedArray->Length() > 1) {
2285     //Set a GROUP type
2286     aResult->SetType(GEOM_GROUP);
2287
2288     //Set a sub shape type
2289     TDF_Label aFreeLabel = aResult->GetFreeLabel();
2290     TopAbs_ShapeEnum aShapeType = aWhat.ShapeType();
2291     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
2292   }
2293
2294   //Make a Python command
2295   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
2296
2297   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
2298     << theShapeWhere << ", " << theShapeWhat << ")";
2299
2300   SetErrorCode(OK);
2301   return aResult;
2302 }
2303
2304 //=======================================================================
2305 //function : SortShapes
2306 //purpose  :
2307 //=======================================================================
2308 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
2309 {
2310   Standard_Integer MaxShapes = SL.Extent();
2311   TopTools_Array1OfShape  aShapes (1,MaxShapes);
2312   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
2313   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
2314   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
2315
2316   // Computing of CentreOfMass
2317   Standard_Integer Index;
2318   GProp_GProps GPr;
2319   gp_Pnt GPoint;
2320   TopTools_ListIteratorOfListOfShape it(SL);
2321   for (Index=1;  it.More();  Index++)
2322   {
2323     TopoDS_Shape S = it.Value();
2324     SL.Remove( it ); // == it.Next()
2325     aShapes(Index) = S;
2326     OrderInd.SetValue (Index, Index);
2327     if (S.ShapeType() == TopAbs_VERTEX)
2328     {
2329       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
2330       Length.SetValue( Index, (Standard_Real) S.Orientation());
2331     }
2332     else
2333     {
2334       BRepGProp::LinearProperties (S, GPr);
2335       GPoint = GPr.CentreOfMass();
2336       Length.SetValue( Index, GPr.Mass() );
2337     }
2338     MidXYZ.SetValue(Index,
2339                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
2340   }
2341
2342   // Sorting
2343   Standard_Integer aTemp;
2344   Standard_Boolean exchange, Sort = Standard_True;
2345   while (Sort)
2346   {
2347     Sort = Standard_False;
2348     for (Index=1; Index < MaxShapes; Index++)
2349     {
2350       if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
2351         exchange = Standard_True;
2352       else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
2353                Length(OrderInd(Index)) >  Length(OrderInd(Index+1)) )
2354         exchange = Standard_True;
2355       else
2356         exchange = Standard_False;
2357       if (exchange)
2358       {
2359         aTemp = OrderInd(Index);
2360         OrderInd(Index) = OrderInd(Index+1);
2361         OrderInd(Index+1) = aTemp;
2362         Sort = Standard_True;
2363       }
2364     }
2365   }
2366   for (Index=1; Index <= MaxShapes; Index++)
2367     SL.Append( aShapes( OrderInd(Index) ));
2368 }
2369
2370 //=======================================================================
2371 //function : CheckTriangulation
2372 //purpose  :
2373 //=======================================================================
2374 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
2375 {
2376   TopExp_Explorer exp (aShape, TopAbs_FACE);
2377   if (!exp.More()) {
2378     SetErrorCode("Shape without faces given");
2379     return false;
2380   }
2381
2382   TopLoc_Location aTopLoc;
2383   Handle(Poly_Triangulation) aTRF;
2384   aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
2385   if (aTRF.IsNull()) {
2386     // calculate deflection
2387     Standard_Real aDeviationCoefficient = 0.001;
2388
2389     Bnd_Box B;
2390     BRepBndLib::Add(aShape, B);
2391     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
2392     B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
2393
2394     Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
2395     Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
2396     Standard_Real aHLRAngle = 0.349066;
2397
2398     BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
2399   }
2400
2401   return true;
2402 }