Salome HOME
SMH: Merged GEOM (NEWGUI, HEAD, POLYWORK)
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 using namespace std;
2
3 #include "GEOMImpl_IShapesOperations.hxx"
4
5 #include "GEOMImpl_Types.hxx"
6
7 #include "GEOMImpl_VectorDriver.hxx"
8 #include "GEOMImpl_ShapeDriver.hxx"
9 #include "GEOMImpl_CopyDriver.hxx"
10 #include "GEOMImpl_GlueDriver.hxx"
11
12 #include "GEOMImpl_IVector.hxx"
13 #include "GEOMImpl_IShapes.hxx"
14 #include "GEOMImpl_IGlue.hxx"
15
16 #include "GEOMImpl_Block6Explorer.hxx"
17
18 #include "GEOM_Function.hxx"
19 #include "GEOM_PythonDump.hxx"
20
21 #include "GEOMAlgo_FinderShapeOn1.hxx"
22
23 #include "utilities.h"
24 #include "OpUtil.hxx"
25 #include "Utils_ExceptHandlers.hxx"
26
27 #include <TFunction_DriverTable.hxx>
28 #include <TFunction_Driver.hxx>
29 #include <TFunction_Logbook.hxx>
30 #include <TDataStd_Integer.hxx>
31 #include <TDataStd_IntegerArray.hxx>
32 #include <TDF_Tool.hxx>
33
34 #include <BRepExtrema_ExtCF.hxx>
35
36 #include <BRep_Tool.hxx>
37 #include <BRepGProp.hxx>
38 #include <BRepAdaptor_Curve.hxx>
39 #include <BRepBndLib.hxx>
40 #include <BRepBuilderAPI_MakeFace.hxx>
41 #include <BRepMesh_IncrementalMesh.hxx>
42
43 #include <TopAbs.hxx>
44 #include <TopExp.hxx>
45 #include <TopoDS.hxx>
46 #include <TopoDS_Shape.hxx>
47 #include <TopoDS_Face.hxx>
48 #include <TopoDS_Edge.hxx>
49 #include <TopoDS_Vertex.hxx>
50 #include <TopoDS_Iterator.hxx>
51 #include <TopExp_Explorer.hxx>
52 #include <TopLoc_Location.hxx>
53 #include <TopTools_MapOfShape.hxx>
54 #include <TopTools_Array1OfShape.hxx>
55 #include <TopTools_ListIteratorOfListOfShape.hxx>
56 #include <TopTools_IndexedMapOfShape.hxx>
57
58 #include <Geom_Surface.hxx>
59 #include <Geom_Plane.hxx>
60 #include <Geom_SphericalSurface.hxx>
61 #include <Geom_CylindricalSurface.hxx>
62 #include <GeomAdaptor_Surface.hxx>
63
64 #include <Geom2d_Curve.hxx>
65
66 #include <Bnd_Box.hxx>
67 #include <GProp_GProps.hxx>
68 #include <gp_Pnt.hxx>
69 #include <gp_Lin.hxx>
70 #include <TColStd_Array1OfReal.hxx>
71 #include <TColStd_HArray1OfInteger.hxx>
72 #include <TColStd_ListOfInteger.hxx>
73 #include <TColStd_ListIteratorOfListOfInteger.hxx>
74
75 //#include <OSD_Timer.hxx>
76
77 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
78
79 //=============================================================================
80 /*!
81  *   constructor:
82  */
83 //=============================================================================
84 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
85 : GEOM_IOperations(theEngine, theDocID)
86 {
87   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
88 }
89
90 //=============================================================================
91 /*!
92  *  destructor
93  */
94 //=============================================================================
95 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
96 {
97   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
98 }
99
100
101 //=============================================================================
102 /*!
103  *  MakeEdge
104  */
105 //=============================================================================
106 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
107                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
108 {
109   SetErrorCode(KO);
110
111   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
112
113   //Add a new Edge object
114   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
115
116   //Add a new Vector function
117   Handle(GEOM_Function) aFunction =
118     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
119
120   //Check if the function is set correctly
121   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
122
123   GEOMImpl_IVector aPI (aFunction);
124
125   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
126   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
127   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
128
129   aPI.SetPoint1(aRef1);
130   aPI.SetPoint2(aRef2);
131
132   //Compute the Edge value
133   try {
134     if (!GetSolver()->ComputeFunction(aFunction)) {
135       SetErrorCode("Vector driver failed");
136       return NULL;
137     }
138   }
139   catch (Standard_Failure) {
140     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
141     SetErrorCode(aFail->GetMessageString());
142     return NULL;
143   }
144
145   //Make a Python command
146   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
147                                << thePnt1 << ", " << thePnt2 << ")";
148
149   SetErrorCode(OK);
150   return anEdge;
151 }
152
153 //=============================================================================
154 /*!
155  *  MakeWire
156  */
157 //=============================================================================
158 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
159                              (list<Handle(GEOM_Object)> theShapes)
160 {
161   return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
162 }
163
164 //=============================================================================
165 /*!
166  *  MakeFace
167  */
168 //=============================================================================
169 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
170                                                           const bool isPlanarWanted)
171 {
172   SetErrorCode(KO);
173
174   if (theWire.IsNull()) return NULL;
175
176   //Add a new Face object
177   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
178
179   //Add a new Shape function for creation of a face from a wire
180   Handle(GEOM_Function) aFunction =
181     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
182   if (aFunction.IsNull()) return NULL;
183
184   //Check if the function is set correctly
185   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
186
187   GEOMImpl_IShapes aCI (aFunction);
188
189   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
190
191   if (aRefWire.IsNull()) return NULL;
192
193   aCI.SetBase(aRefWire);
194   aCI.SetIsPlanar(isPlanarWanted);
195
196   //Compute the Face value
197   try {
198     if (!GetSolver()->ComputeFunction(aFunction)) {
199       SetErrorCode("Shape driver failed to compute a face");
200       return NULL;
201     }
202   }
203   catch (Standard_Failure) {
204     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
205     SetErrorCode(aFail->GetMessageString());
206     return NULL;
207   }
208
209   //Make a Python command
210   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
211     << theWire << ", " << (int)isPlanarWanted << ")";
212
213   SetErrorCode(OK);
214   return aFace;
215 }
216
217 //=============================================================================
218 /*!
219  *  MakeFaceWires
220  */
221 //=============================================================================
222 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
223                              (list<Handle(GEOM_Object)> theShapes,
224                               const bool isPlanarWanted)
225 {
226   SetErrorCode(KO);
227
228   //Add a new object
229   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
230
231   //Add a new function
232   Handle(GEOM_Function) aFunction =
233     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
234   if (aFunction.IsNull()) return NULL;
235
236   //Check if the function is set correctly
237   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
238
239   GEOMImpl_IShapes aCI (aFunction);
240
241   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
242
243   // Shapes
244   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
245   for (; it != theShapes.end(); it++) {
246     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
247     if (aRefSh.IsNull()) {
248       SetErrorCode("NULL argument shape for the face construction");
249       return NULL;
250     }
251     aShapesSeq->Append(aRefSh);
252   }
253   aCI.SetShapes(aShapesSeq);
254
255   aCI.SetIsPlanar(isPlanarWanted);
256
257   //Compute the shape
258   try {
259     if (!GetSolver()->ComputeFunction(aFunction)) {
260       SetErrorCode("Shape driver failed");
261       return NULL;
262     }
263   }
264   catch (Standard_Failure) {
265     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
266     SetErrorCode(aFail->GetMessageString());
267     return NULL;
268   }
269
270   //Make a Python command
271   GEOM::TPythonDump pd (aFunction);
272   pd << aShape << " = geompy.MakeFaceWires([";
273
274   // Shapes
275   it = theShapes.begin();
276   if (it != theShapes.end()) {
277     pd << (*it++);
278     while (it != theShapes.end()) {
279       pd << ", " << (*it++);
280     }
281   }
282   pd << "], " << (int)isPlanarWanted << ")";
283
284   SetErrorCode(OK);
285   return aShape;
286 }
287
288 //=============================================================================
289 /*!
290  *  MakeShell
291  */
292 //=============================================================================
293 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
294                              (list<Handle(GEOM_Object)> theShapes)
295 {
296   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
297 }
298
299 //=============================================================================
300 /*!
301  *  MakeSolidShells
302  */
303 //=============================================================================
304 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
305                              (list<Handle(GEOM_Object)> theShapes)
306 {
307   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolidShells");
308 }
309
310 //=============================================================================
311 /*!
312  *  MakeSolidShell
313  */
314 //=============================================================================
315 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
316 {
317   SetErrorCode(KO);
318
319   if (theShell.IsNull()) return NULL;
320
321   //Add a new Solid object
322   Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
323
324   //Add a new Solid function for creation of a solid from a shell
325   Handle(GEOM_Function) aFunction =
326     aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
327   if (aFunction.IsNull()) return NULL;
328
329   //Check if the function is set correctly
330   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
331
332   GEOMImpl_IShapes aCI (aFunction);
333
334   Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
335
336   if (aRefShell.IsNull()) return NULL;
337
338   aCI.SetBase(aRefShell);
339
340   //Compute the Solid value
341   try {
342     if (!GetSolver()->ComputeFunction(aFunction)) {
343       SetErrorCode("Solid driver failed");
344       return NULL;
345     }
346   }
347   catch (Standard_Failure) {
348     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
349     SetErrorCode(aFail->GetMessageString());
350     return NULL;
351   }
352
353   //Make a Python command
354   GEOM::TPythonDump(aFunction) << aSolid
355     << " = geompy.MakeSolid(" << theShell << ")";
356
357   SetErrorCode(OK);
358   return aSolid;
359 }
360
361 //=============================================================================
362 /*!
363  *  MakeCompound
364  */
365 //=============================================================================
366 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
367                              (list<Handle(GEOM_Object)> theShapes)
368 {
369   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
370 }
371
372 //=============================================================================
373 /*!
374  *  MakeShape
375  */
376 //=============================================================================
377 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
378                              (list<Handle(GEOM_Object)>     theShapes,
379                               const Standard_Integer        theObjectType,
380                               const Standard_Integer        theFunctionType,
381                               const TCollection_AsciiString theMethodName)
382 {
383   SetErrorCode(KO);
384
385   //Add a new object
386   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
387
388   //Add a new function
389   Handle(GEOM_Function) aFunction =
390     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
391   if (aFunction.IsNull()) return NULL;
392
393   //Check if the function is set correctly
394   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
395
396   GEOMImpl_IShapes aCI (aFunction);
397
398   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
399
400   // Shapes
401   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
402   for (; it != theShapes.end(); it++) {
403     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
404     if (aRefSh.IsNull()) {
405       SetErrorCode("NULL argument shape for the shape construction");
406       return NULL;
407     }
408     aShapesSeq->Append(aRefSh);
409   }
410   aCI.SetShapes(aShapesSeq);
411
412   //Compute the shape
413   try {
414     if (!GetSolver()->ComputeFunction(aFunction)) {
415       SetErrorCode("Shape driver failed");
416       return NULL;
417     }
418   }
419   catch (Standard_Failure) {
420     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
421     SetErrorCode(aFail->GetMessageString());
422     return NULL;
423   }
424
425   //Make a Python command
426   GEOM::TPythonDump pd (aFunction);
427   pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
428
429   // Shapes
430   it = theShapes.begin();
431   if (it != theShapes.end()) {
432     pd << (*it++);
433     while (it != theShapes.end()) {
434       pd << ", " << (*it++);
435     }
436   }
437   pd << "])";
438
439   SetErrorCode(OK);
440   return aShape;
441 }
442
443 //=============================================================================
444 /*!
445  *  MakeGlueFaces
446  */
447 //=============================================================================
448 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
449                                                 (Handle(GEOM_Object) theShape,
450                                                  const Standard_Real theTolerance)
451 {
452   SetErrorCode(KO);
453
454   if (theShape.IsNull()) return NULL;
455
456   //Add a new Glued object
457   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
458
459   //Add a new Glue function
460   Handle(GEOM_Function) aFunction;
461   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
462   if (aFunction.IsNull()) return NULL;
463
464   //Check if the function is set correctly
465   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
466
467   GEOMImpl_IGlue aCI (aFunction);
468
469   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
470   if (aRefShape.IsNull()) return NULL;
471
472   aCI.SetBase(aRefShape);
473   aCI.SetTolerance(theTolerance);
474
475   //Compute the sub-shape value
476   Standard_Boolean isWarning = Standard_False;
477   try {
478     if (!GetSolver()->ComputeFunction(aFunction)) {
479       SetErrorCode("Shape driver failed to glue faces");
480       return NULL;
481     }
482   }
483   catch (Standard_Failure) {
484     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
485     SetErrorCode(aFail->GetMessageString());
486     // to provide warning
487     if (!aFunction->GetValue().IsNull()) {
488       isWarning = Standard_True;
489     } else {
490       return NULL;
491     }
492   }
493
494   //Make a Python command
495   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
496     << theShape << ", " << theTolerance << ")";
497
498   // to provide warning
499   if (!isWarning) SetErrorCode(OK);
500   return aGlued;
501 }
502
503 //=============================================================================
504 /*!
505  *  MakeExplode
506  */
507 //=============================================================================
508 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
509                                           (Handle(GEOM_Object)    theShape,
510                                            const Standard_Integer theShapeType,
511                                            const Standard_Boolean isSorted)
512 {
513 //  OSD_Timer timer1, timer2, timer3, timer4;
514 //  timer1.Start();
515
516   SetErrorCode(KO);
517
518   if (theShape.IsNull()) return NULL;
519   TopoDS_Shape aShape = theShape->GetValue();
520   if (aShape.IsNull()) return NULL;
521
522   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
523   Handle(GEOM_Object) anObj;
524   Handle(GEOM_Function) aFunction;
525   TopTools_MapOfShape mapShape;
526   TopTools_ListOfShape listShape;
527
528   if (aShape.ShapeType() == TopAbs_COMPOUND &&
529       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
530        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
531        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
532     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
533     for (; It.More(); It.Next()) {
534       if (mapShape.Add(It.Value())) {
535         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
536             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
537           listShape.Append(It.Value());
538         }
539       }
540     }
541   } else {
542     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
543     for (; exp.More(); exp.Next())
544       if (mapShape.Add(exp.Current()))
545         listShape.Append(exp.Current());
546   }
547
548   if (listShape.IsEmpty()) {
549     SetErrorCode("The given shape has no sub-shapes of the requested type");
550     return aSeq;
551   }
552
553 //  timer1.Stop();
554 //  timer2.Start();
555
556   if (isSorted)
557     SortShapes(listShape);
558
559 //  timer2.Stop();
560 //  timer3.Start();
561
562   TopTools_IndexedMapOfShape anIndices;
563   TopExp::MapShapes(aShape, anIndices);
564   Handle(TColStd_HArray1OfInteger) anArray;
565
566   TopTools_ListIteratorOfListOfShape itSub (listShape);
567   TCollection_AsciiString anAsciiList, anEntry;
568   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
569     TopoDS_Shape aValue = itSub.Value();
570     anArray = new TColStd_HArray1OfInteger(1,1);
571     anArray->SetValue(1, anIndices.FindIndex(aValue));
572     anObj = GetEngine()->AddSubShape(theShape, anArray);
573     aSeq->Append(anObj);
574
575     // for python command
576     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
577     anAsciiList += anEntry;
578     anAsciiList += ",";
579   }
580
581   //Make a Python command
582   anAsciiList.Trunc(anAsciiList.Length() - 1);
583
584   aFunction = theShape->GetLastFunction();
585   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
586
587   GEOM::TPythonDump pd (aFunction);
588   pd << anOldDescr.ToCString() << "\n\t[" << anAsciiList.ToCString();
589   pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
590   pd << theShape << ", " << theShapeType << ")";
591
592   SetErrorCode(OK);
593
594 //  timer4.Stop();
595
596 //  cout << "Explosure takes:" << endl;
597 //  timer1.Show();
598 //  cout << "Sorting takes:" << endl;
599 //  timer2.Show();
600 //  cout << "Sub-shapes addition takes:" << endl;
601 //  timer3.Show();
602 //  cout << "Update Description takes:" << endl;
603 //  timer4.Show();
604
605   return aSeq;
606 }
607
608 //=============================================================================
609 /*!
610  *  GetSubShapeAllIDs
611  */
612 //=============================================================================
613 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
614                                           (Handle(GEOM_Object)    theShape,
615                                            const Standard_Integer theShapeType,
616                                            const Standard_Boolean isSorted)
617 {
618   SetErrorCode(KO);
619
620   if (theShape.IsNull()) return NULL;
621   TopoDS_Shape aShape = theShape->GetValue();
622   if (aShape.IsNull()) return NULL;
623
624   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
625   TopTools_MapOfShape mapShape;
626   TopTools_ListOfShape listShape;
627
628   if (aShape.ShapeType() == TopAbs_COMPOUND &&
629       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
630        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
631        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
632     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
633     for (; It.More(); It.Next()) {
634       if (mapShape.Add(It.Value())) {
635         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
636             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
637           listShape.Append(It.Value());
638         }
639       }
640     }
641   } else {
642     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
643     for (; exp.More(); exp.Next())
644       if (mapShape.Add(exp.Current()))
645         listShape.Append(exp.Current());
646   }
647
648   if (listShape.IsEmpty()) {
649     SetErrorCode("The given shape has no sub-shapes of the requested type");
650     return aSeq;
651   }
652
653   if (isSorted)
654     SortShapes(listShape);
655
656   TopTools_IndexedMapOfShape anIndices;
657   TopExp::MapShapes(aShape, anIndices);
658   Handle(TColStd_HArray1OfInteger) anArray;
659
660   TopTools_ListIteratorOfListOfShape itSub (listShape);
661   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
662     TopoDS_Shape aValue = itSub.Value();
663     aSeq->Append(anIndices.FindIndex(aValue));
664   }
665
666   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
667   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
668
669   //Make a Python command
670   GEOM::TPythonDump pd (aFunction);
671   pd << anOldDescr.ToCString() << "\n\tlistSubShapeIDs = geompy.SubShapeAll";
672   pd << (isSorted ? "SortedIDs(" : "IDs(");
673   pd << theShape << ", " << theShapeType << ")";
674
675   SetErrorCode(OK);
676   return aSeq;
677 }
678
679 //=============================================================================
680 /*!
681  *  GetSubShape
682  */
683 //=============================================================================
684 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
685                                           (Handle(GEOM_Object)    theMainShape,
686                                            const Standard_Integer theID)
687 {
688   SetErrorCode(KO);
689
690   if (theMainShape.IsNull()) return NULL;
691
692   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
693   anArray->SetValue(1, theID);
694   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
695   if (anObj.IsNull()) {
696     SetErrorCode("Can not get a sub-shape with the given ID");
697     return NULL;
698   }
699
700   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
701
702   //Make a Python command
703   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
704                                << theMainShape << ", [" << theID << "])";
705
706   SetErrorCode(OK);
707   return anObj;
708 }
709
710
711 //=============================================================================
712 /*!
713  *  NumberOfFaces
714  */
715 //=============================================================================
716 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
717 {
718   SetErrorCode(KO);
719
720   Standard_Integer nb = 0;
721
722   if (theShape.IsNull()) return -1;
723   TopoDS_Shape aShape = theShape->GetValue();
724   if (aShape.IsNull()) return -1;
725
726   TopTools_MapOfShape mapShape;
727
728   TopExp_Explorer exp (aShape, TopAbs_FACE);
729   for (; exp.More(); exp.Next())
730     if (mapShape.Add(exp.Current()))
731       nb++;
732
733   SetErrorCode(OK);
734   return nb;
735 }
736
737 //=============================================================================
738 /*!
739  *  NumberOfEdges
740  */
741 //=============================================================================
742 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
743 {
744   SetErrorCode(KO);
745
746   Standard_Integer nb = 0;
747
748   if (theShape.IsNull()) return -1;
749   TopoDS_Shape aShape = theShape->GetValue();
750   if (aShape.IsNull()) return -1;
751
752   TopTools_MapOfShape mapShape;
753
754   TopExp_Explorer exp (aShape, TopAbs_EDGE);
755   for (; exp.More(); exp.Next())
756     if (mapShape.Add(exp.Current()))
757       nb++;
758
759   SetErrorCode(OK);
760   return nb;
761 }
762
763 //=============================================================================
764 /*!
765  *  ReverseShape
766  */
767 //=============================================================================
768 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
769 {
770   SetErrorCode(KO);
771
772   if (theShape.IsNull()) return NULL;
773
774   //Add a new reversed object
775   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
776
777   //Add a new Revese function
778   Handle(GEOM_Function) aFunction;
779   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
780   if (aFunction.IsNull()) return NULL;
781
782   //Check if the function is set correctly
783   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
784
785   GEOMImpl_IShapes aSI (aFunction);
786
787   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
788   if (aRefShape.IsNull()) return NULL;
789
790   aSI.SetBase(aRefShape);
791
792   //Compute the sub-shape value
793   try {
794     if (!GetSolver()->ComputeFunction(aFunction)) {
795       SetErrorCode("Shape driver failed to reverse shape");
796       return NULL;
797     }
798   }
799   catch (Standard_Failure) {
800     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
801     SetErrorCode(aFail->GetMessageString());
802     return NULL;
803   }
804
805   //Make a Python command
806   GEOM::TPythonDump(aFunction) << aReversed
807     << " = geompy.ChangeOrientation(" << theShape << ")";
808
809   SetErrorCode(OK);
810   return aReversed;
811 }
812
813 //=============================================================================
814 /*!
815  *  GetFreeFacesIDs
816  */
817 //=============================================================================
818 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
819                                                  (Handle(GEOM_Object) theShape)
820 {
821   SetErrorCode(KO);
822
823   if (theShape.IsNull()) return NULL;
824   TopoDS_Shape aShape = theShape->GetValue();
825   if (aShape.IsNull()) return NULL;
826
827   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
828
829   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
830   GEOMImpl_Block6Explorer::MapShapesAndAncestors
831     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
832
833   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
834
835   if (nbFaces == 0) {
836     SetErrorCode("The given shape has no faces");
837     return aSeq;
838   }
839
840   TopTools_IndexedMapOfShape anIndices;
841   TopExp::MapShapes(aShape, anIndices);
842
843   Standard_Integer id;
844   for (; ind <= nbFaces; ind++) {
845     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
846       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
847       aSeq->Append(id);
848     }
849   }
850
851   //The explode doesn't change object so no new function is required.
852   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
853   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
854
855   //Make a Python command
856   GEOM::TPythonDump(aFunction) << anOldDescr.ToCString()
857     << "\n\tlistFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
858
859   SetErrorCode(OK);
860   return aSeq;
861 }
862
863 //=============================================================================
864 /*!
865  *  GetSharedShapes
866  */
867 //=============================================================================
868 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
869                                                 (Handle(GEOM_Object)    theShape1,
870                                                  Handle(GEOM_Object)    theShape2,
871                                                  const Standard_Integer theShapeType)
872 {
873   SetErrorCode(KO);
874
875   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
876
877   TopoDS_Shape aShape1 = theShape1->GetValue();
878   TopoDS_Shape aShape2 = theShape2->GetValue();
879
880   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
881
882   TopTools_IndexedMapOfShape anIndices;
883   TopExp::MapShapes(aShape1, anIndices);
884   Handle(TColStd_HArray1OfInteger) anArray;
885
886   TopTools_IndexedMapOfShape mapShape1;
887   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
888
889   Handle(GEOM_Object) anObj;
890   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
891   TCollection_AsciiString anAsciiList, anEntry;
892
893   TopTools_MapOfShape mapShape2;
894   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
895   for (; exp.More(); exp.Next()) {
896     TopoDS_Shape aSS = exp.Current();
897     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
898       anArray = new TColStd_HArray1OfInteger(1,1);
899       anArray->SetValue(1, anIndices.FindIndex(aSS));
900       anObj = GetEngine()->AddSubShape(theShape1, anArray);
901       aSeq->Append(anObj);
902
903       // for python command
904       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
905       anAsciiList += anEntry;
906       anAsciiList += ",";
907     }
908   }
909
910   if (aSeq->IsEmpty()) {
911     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
912     return aSeq;
913   }
914
915   //Make a Python command
916   anAsciiList.Trunc(anAsciiList.Length() - 1);
917
918   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
919
920   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
921     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
922       << theShape2 << ", " << theShapeType << ")";
923
924   SetErrorCode(OK);
925   return aSeq;
926 }
927
928 //=============================================================================
929 /*!
930  *  
931  */
932 //=============================================================================
933 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
934                                       const GEOMAlgo_State theState)
935 {
936   switch (theState) {
937   case GEOMAlgo_ST_IN:
938     theDump << "geompy.GEOM.ST_IN";
939     break;
940   case GEOMAlgo_ST_OUT:
941     theDump << "geompy.GEOM.ST_OUT";
942     break;
943   case GEOMAlgo_ST_ON:
944     theDump << "geompy.GEOM.ST_ON";
945     break;
946   case GEOMAlgo_ST_ONIN:
947     theDump << "geompy.GEOM.ST_ONIN";
948     break;
949   case GEOMAlgo_ST_ONOUT:
950     theDump << "geompy.GEOM.ST_ONOUT";
951     break;
952   default:
953     theDump << "geompy.GEOM.ST_UNKNOWN";
954     break;
955   }
956   return theDump;
957 }
958
959 //=============================================================================
960 /*!
961  *  GetShapesOnPlane
962  */
963 //=============================================================================
964 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
965                                         (const Handle(GEOM_Object)& theShape,
966                                          const Standard_Integer     theShapeType,
967                                          const Handle(GEOM_Object)& theAx1,
968                                          const GEOMAlgo_State       theState)
969 {
970   SetErrorCode(KO);
971
972 //  MESSAGE("--------------------------- GetShapesOnPlane phase 1 takes:");
973 //  OSD_Timer timer1;
974 //  timer1.Start();
975
976   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
977
978   TopoDS_Shape aShape = theShape->GetValue();
979   TopoDS_Shape anAx1  = theAx1->GetValue();
980
981   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
982
983   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
984   if (aShapeType != TopAbs_VERTEX &&
985       aShapeType != TopAbs_EDGE &&
986       aShapeType != TopAbs_FACE &&
987       aShapeType != TopAbs_SOLID) {
988     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
989     return NULL;
990   }
991
992   // Create plane
993   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
994   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
995   TopoDS_Vertex V1, V2;
996   TopExp::Vertices(anEdge, V1, V2, Standard_True);
997   if (V1.IsNull() || V2.IsNull()) {
998     SetErrorCode("Bad edge given for the plane normal vector");
999     return NULL;
1000   }
1001   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1002   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1003   if (aVec.Magnitude() < Precision::Confusion()) {
1004     SetErrorCode("Vector with null magnitude given");
1005     return NULL;
1006   }
1007
1008   Handle(Geom_Plane) aPlane = new Geom_Plane(aLoc, aVec);
1009
1010   // Check presence of triangulation, build if need
1011   if (!CheckTriangulation(aShape))
1012     return NULL;
1013
1014   // Call algo
1015   GEOMAlgo_FinderShapeOn1 aFinder;
1016   Standard_Real aTol = 0.0001; // default value
1017
1018   aFinder.SetShape(aShape);
1019   aFinder.SetTolerance(aTol);
1020   aFinder.SetSurface(aPlane);
1021   aFinder.SetShapeType(aShapeType);
1022   aFinder.SetState(theState);
1023
1024   // Sets the minimal number of inner points for the faces that do not have own
1025   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1026   // Default value=3
1027   aFinder.SetNbPntsMin(3);
1028   // Sets the maximal number of inner points for edges or faces.
1029   // It is usefull for the cases when this number is very big (e.g =2000) to improve
1030   // the performance. If this value =0, all inner points will be taken into account.
1031   // Default value=0
1032   aFinder.SetNbPntsMax(100);
1033
1034 //  timer1.Stop();
1035 //  timer1.Show();
1036
1037 //  MESSAGE("--------------------------- Perform on Plane takes:");
1038 //  timer1.Reset();
1039 //  timer1.Start();
1040   aFinder.Perform();
1041 //  timer1.Stop();
1042 //  timer1.Show();
1043
1044 //  MESSAGE("--------------------------- GetShapesOnPlane phase 3 takes:");
1045 //  timer1.Reset();
1046 //  timer1.Start();
1047
1048   // Interprete results
1049   Standard_Integer iErr = aFinder.ErrorStatus();
1050   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1051   if (iErr) {
1052     MESSAGE(" iErr : " << iErr);
1053     TCollection_AsciiString aMsg (" iErr : ");
1054     aMsg += TCollection_AsciiString(iErr);
1055     SetErrorCode(aMsg);
1056     return NULL;
1057   }
1058   Standard_Integer iWrn = aFinder.WarningStatus();
1059   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1060   if (iWrn) {
1061     MESSAGE(" *** iWrn : " << iWrn);
1062   }
1063
1064   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1065
1066   if (listSS.Extent() < 1) {
1067     SetErrorCode("Not a single sub-shape of the requested type found on the given plane");
1068     return NULL;
1069   }
1070
1071 //  timer1.Stop();
1072 //  timer1.Show();
1073
1074 //  MESSAGE("--------------------------- GetShapesOnPlane phase 4 takes:");
1075 //  timer1.Reset();
1076 //  timer1.Start();
1077
1078   // Fill sequence of objects
1079   TopTools_IndexedMapOfShape anIndices;
1080   TopExp::MapShapes(aShape, anIndices);
1081
1082   Handle(GEOM_Object) anObj;
1083   Handle(TColStd_HArray1OfInteger) anArray;
1084   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1085   TCollection_AsciiString anAsciiList, anEntry;
1086
1087   TopTools_ListIteratorOfListOfShape itSub (listSS);
1088   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1089     int id = anIndices.FindIndex(itSub.Value());
1090     anArray = new TColStd_HArray1OfInteger(1,1);
1091     anArray->SetValue(1, id);
1092     anObj = GetEngine()->AddSubShape(theShape, anArray);
1093     aSeq->Append(anObj);
1094
1095     // for python command
1096     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1097     anAsciiList += anEntry;
1098     anAsciiList += ",";
1099   }
1100
1101 //  timer1.Stop();
1102 //  timer1.Show();
1103
1104 //  MESSAGE("--------------------------- GetShapesOnPlane phase 5 takes:");
1105 //  timer1.Reset();
1106 //  timer1.Start();
1107   
1108   // Make a Python command
1109   anAsciiList.Trunc(anAsciiList.Length() - 1);
1110
1111   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1112
1113   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1114     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
1115       << theShapeType << ", " << theAx1 << ", " << theState << ")";
1116
1117   SetErrorCode(OK);
1118   return aSeq;
1119 }
1120
1121 //=============================================================================
1122 /*!
1123  *  GetShapesOnCylinder
1124  */
1125 //=============================================================================
1126 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
1127                                           (const Handle(GEOM_Object)& theShape,
1128                                            const Standard_Integer     theShapeType,
1129                                            const Handle(GEOM_Object)& theAxis,
1130                                            const Standard_Real        theRadius,
1131                                            const GEOMAlgo_State       theState)
1132 {
1133   SetErrorCode(KO);
1134
1135   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1136
1137   TopoDS_Shape aShape = theShape->GetValue();
1138   TopoDS_Shape anAxis = theAxis->GetValue();
1139
1140   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1141
1142   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1143   if (aShapeType != TopAbs_VERTEX &&
1144       aShapeType != TopAbs_EDGE &&
1145       aShapeType != TopAbs_FACE &&
1146       aShapeType != TopAbs_SOLID) {
1147     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1148     return NULL;
1149   }
1150
1151   //Axis of the cylinder
1152   if (anAxis.ShapeType() != TopAbs_EDGE) {
1153     SetErrorCode("Not an edge given for the axis");
1154     return NULL;
1155   }
1156   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1157   TopoDS_Vertex V1, V2;
1158   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1159   if (V1.IsNull() || V2.IsNull()) {
1160     SetErrorCode("Bad edge given for the axis");
1161     return NULL;
1162   }
1163   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1164   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1165   if (aVec.Magnitude() < Precision::Confusion()) {
1166     SetErrorCode("Vector with null magnitude given");
1167     return NULL;
1168   }
1169
1170   gp_Ax3 anAx3 (aLoc, aVec);
1171   Handle(Geom_CylindricalSurface) aCylinder =
1172     new Geom_CylindricalSurface(anAx3, theRadius);
1173
1174   // Check presence of triangulation, build if need
1175   if (!CheckTriangulation(aShape))
1176     return NULL;
1177
1178   // Call algo
1179   GEOMAlgo_FinderShapeOn1 aFinder;
1180   Standard_Real aTol = 0.0001; // default value
1181
1182   aFinder.SetShape(aShape);
1183   aFinder.SetTolerance(aTol);
1184   aFinder.SetSurface(aCylinder);
1185   aFinder.SetShapeType(aShapeType);
1186   aFinder.SetState(theState);
1187
1188   aFinder.SetNbPntsMin(3);
1189   aFinder.SetNbPntsMax(100);
1190
1191   aFinder.Perform();
1192
1193   // Interprete results
1194   Standard_Integer iErr = aFinder.ErrorStatus();
1195   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1196   if (iErr) {
1197     MESSAGE(" iErr : " << iErr);
1198     TCollection_AsciiString aMsg (" iErr : ");
1199     aMsg += TCollection_AsciiString(iErr);
1200     SetErrorCode(aMsg);
1201     return NULL;
1202   }
1203   Standard_Integer iWrn = aFinder.WarningStatus();
1204   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1205   if (iWrn) {
1206     MESSAGE(" *** iWrn : " << iWrn);
1207   }
1208
1209   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1210
1211   if (listSS.Extent() < 1) {
1212     SetErrorCode("Not a single sub-shape of the requested type found on the given cylinder");
1213     return NULL;
1214   }
1215
1216   // Fill sequence of objects
1217   TopTools_IndexedMapOfShape anIndices;
1218   TopExp::MapShapes(aShape, anIndices);
1219
1220   Handle(GEOM_Object) anObj;
1221   Handle(TColStd_HArray1OfInteger) anArray;
1222   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1223   TCollection_AsciiString anAsciiList, anEntry;
1224
1225   TopTools_ListIteratorOfListOfShape itSub (listSS);
1226   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1227     int id = anIndices.FindIndex(itSub.Value());
1228     anArray = new TColStd_HArray1OfInteger(1,1);
1229     anArray->SetValue(1, id);
1230     anObj = GetEngine()->AddSubShape(theShape, anArray);
1231     aSeq->Append(anObj);
1232
1233     // for python command
1234     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1235     anAsciiList += anEntry;
1236     anAsciiList += ",";
1237   }
1238   
1239   // Make a Python command
1240   anAsciiList.Trunc(anAsciiList.Length() - 1);
1241
1242   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1243
1244   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1245     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << theShapeType
1246       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
1247
1248   SetErrorCode(OK);
1249   return aSeq;
1250 }
1251
1252 //=============================================================================
1253 /*!
1254  *  GetShapesOnSphere
1255  */
1256 //=============================================================================
1257 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
1258                                           (const Handle(GEOM_Object)& theShape,
1259                                            const Standard_Integer     theShapeType,
1260                                            const Handle(GEOM_Object)& theCenter,
1261                                            const Standard_Real        theRadius,
1262                                            const GEOMAlgo_State       theState)
1263 {
1264   SetErrorCode(KO);
1265
1266   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1267
1268   TopoDS_Shape aShape  = theShape->GetValue();
1269   TopoDS_Shape aCenter = theCenter->GetValue();
1270
1271   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1272
1273   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1274   if (aShapeType != TopAbs_VERTEX &&
1275       aShapeType != TopAbs_EDGE &&
1276       aShapeType != TopAbs_FACE &&
1277       aShapeType != TopAbs_SOLID) {
1278     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1279     return NULL;
1280   }
1281
1282   // Center of the sphere
1283   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1284   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1285
1286   gp_Ax3 anAx3 (aLoc, gp::DZ());
1287   Handle(Geom_SphericalSurface) aSphere =
1288     new Geom_SphericalSurface(anAx3, theRadius);
1289
1290   // Check presence of triangulation, build if need
1291   if (!CheckTriangulation(aShape))
1292     return NULL;
1293
1294   // Call algo
1295   GEOMAlgo_FinderShapeOn1 aFinder;
1296   Standard_Real aTol = 0.0001; // default value
1297
1298   aFinder.SetShape(aShape);
1299   aFinder.SetTolerance(aTol);
1300   aFinder.SetSurface(aSphere);
1301   aFinder.SetShapeType(aShapeType);
1302   aFinder.SetState(theState);
1303
1304   aFinder.SetNbPntsMin(3);
1305   aFinder.SetNbPntsMax(100);
1306
1307   aFinder.Perform();
1308
1309   // Interprete results
1310   Standard_Integer iErr = aFinder.ErrorStatus();
1311   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1312   if (iErr) {
1313     MESSAGE(" iErr : " << iErr);
1314     TCollection_AsciiString aMsg (" iErr : ");
1315     aMsg += TCollection_AsciiString(iErr);
1316     SetErrorCode(aMsg);
1317     return NULL;
1318   }
1319   Standard_Integer iWrn = aFinder.WarningStatus();
1320   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1321   if (iWrn) {
1322     MESSAGE(" *** iWrn : " << iWrn);
1323   }
1324
1325   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1326
1327   if (listSS.Extent() < 1) {
1328     SetErrorCode("Not a single sub-shape of the requested type found on the given sphere");
1329     return NULL;
1330   }
1331
1332   // Fill sequence of objects
1333   TopTools_IndexedMapOfShape anIndices;
1334   TopExp::MapShapes(aShape, anIndices);
1335
1336   Handle(GEOM_Object) anObj;
1337   Handle(TColStd_HArray1OfInteger) anArray;
1338   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1339   TCollection_AsciiString anAsciiList, anEntry;
1340
1341   TopTools_ListIteratorOfListOfShape itSub (listSS);
1342   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1343     int id = anIndices.FindIndex(itSub.Value());
1344     anArray = new TColStd_HArray1OfInteger(1,1);
1345     anArray->SetValue(1, id);
1346     anObj = GetEngine()->AddSubShape(theShape, anArray);
1347     aSeq->Append(anObj);
1348
1349     // for python command
1350     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1351     anAsciiList += anEntry;
1352     anAsciiList += ",";
1353   }
1354   
1355   // Make a Python command
1356   anAsciiList.Trunc(anAsciiList.Length() - 1);
1357
1358   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1359
1360   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1361     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << theShapeType
1362       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
1363
1364   SetErrorCode(OK);
1365   return aSeq;
1366 }
1367 //=============================================================================
1368 /*!
1369  *  GetShapesOnPlaneIDs
1370  */
1371 //=============================================================================
1372 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
1373                                         (const Handle(GEOM_Object)& theShape,
1374                                          const Standard_Integer     theShapeType,
1375                                          const Handle(GEOM_Object)& theAx1,
1376                                          const GEOMAlgo_State       theState)
1377 {
1378   SetErrorCode(KO);
1379
1380   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1381
1382   TopoDS_Shape aShape = theShape->GetValue();
1383   TopoDS_Shape anAx1  = theAx1->GetValue();
1384
1385   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1386
1387   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1388   if (aShapeType != TopAbs_VERTEX &&
1389       aShapeType != TopAbs_EDGE &&
1390       aShapeType != TopAbs_FACE &&
1391       aShapeType != TopAbs_SOLID) {
1392     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1393     return NULL;
1394   }
1395
1396   // Create plane
1397   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1398   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1399   TopoDS_Vertex V1, V2;
1400   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1401   if (V1.IsNull() || V2.IsNull()) {
1402     SetErrorCode("Bad edge given for the plane normal vector");
1403     return NULL;
1404   }
1405   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1406   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1407   if (aVec.Magnitude() < Precision::Confusion()) {
1408     SetErrorCode("Vector with null magnitude given");
1409     return NULL;
1410   }
1411
1412   Handle(Geom_Plane) aPlane = new Geom_Plane(aLoc, aVec);
1413
1414   // Check presence of triangulation, build if need
1415   if (!CheckTriangulation(aShape))
1416     return NULL;
1417
1418   // Call algo
1419   GEOMAlgo_FinderShapeOn1 aFinder;
1420   Standard_Real aTol = 0.0001; // default value
1421
1422   aFinder.SetShape(aShape);
1423   aFinder.SetTolerance(aTol);
1424   aFinder.SetSurface(aPlane);
1425   aFinder.SetShapeType(aShapeType);
1426   aFinder.SetState(theState);
1427
1428   aFinder.SetNbPntsMin(3);
1429   aFinder.SetNbPntsMax(100);
1430
1431   aFinder.Perform();
1432
1433   // Interprete results
1434   Standard_Integer iErr = aFinder.ErrorStatus();
1435   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1436   if (iErr) {
1437     MESSAGE(" iErr : " << iErr);
1438     TCollection_AsciiString aMsg (" iErr : ");
1439     aMsg += TCollection_AsciiString(iErr);
1440     SetErrorCode(aMsg);
1441     return NULL;
1442   }
1443   Standard_Integer iWrn = aFinder.WarningStatus();
1444   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1445   if (iWrn) {
1446     MESSAGE(" *** iWrn : " << iWrn);
1447   }
1448
1449   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1450
1451   if (listSS.Extent() < 1) {
1452     SetErrorCode("Not a single sub-shape of the requested type found on the given plane");
1453     return NULL;
1454   }
1455
1456   // Fill sequence of objects
1457   TopTools_IndexedMapOfShape anIndices;
1458   TopExp::MapShapes(aShape, anIndices);
1459
1460   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1461
1462   TopTools_ListIteratorOfListOfShape itSub (listSS);
1463   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1464     int id = anIndices.FindIndex(itSub.Value());
1465     aSeq->Append(id);
1466   }
1467
1468   // The GetShapesOnPlane() doesn't change object so no new function is required.
1469   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1470
1471   // Make a Python command
1472   TCollection_AsciiString anEntry, aDescr
1473     ("\nlistShapesOnPlane = IShapesOperations.GetShapesOnPlaneIDs(");
1474   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1475   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1476   TDF_Tool::Entry(theAx1->GetEntry(), anEntry);
1477   aDescr += anEntry + ",";
1478   aDescr += TCollection_AsciiString(theState) + ")";
1479
1480   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1481   anOldDescr += aDescr;
1482   aFunction->SetDescription(anOldDescr);
1483
1484   SetErrorCode(OK);
1485   return aSeq;
1486 }
1487
1488 //=============================================================================
1489 /*!
1490  *  GetShapesOnCylinderIDs
1491  */
1492 //=============================================================================
1493 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
1494                                           (const Handle(GEOM_Object)& theShape,
1495                                            const Standard_Integer     theShapeType,
1496                                            const Handle(GEOM_Object)& theAxis,
1497                                            const Standard_Real        theRadius,
1498                                            const GEOMAlgo_State       theState)
1499 {
1500   SetErrorCode(KO);
1501
1502   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1503
1504   TopoDS_Shape aShape = theShape->GetValue();
1505   TopoDS_Shape anAxis = theAxis->GetValue();
1506
1507   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1508
1509   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1510   if (aShapeType != TopAbs_VERTEX &&
1511       aShapeType != TopAbs_EDGE &&
1512       aShapeType != TopAbs_FACE &&
1513       aShapeType != TopAbs_SOLID) {
1514     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1515     return NULL;
1516   }
1517
1518   //Axis of the cylinder
1519   if (anAxis.ShapeType() != TopAbs_EDGE) {
1520     SetErrorCode("Not an edge given for the axis");
1521     return NULL;
1522   }
1523   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1524   TopoDS_Vertex V1, V2;
1525   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1526   if (V1.IsNull() || V2.IsNull()) {
1527     SetErrorCode("Bad edge given for the axis");
1528     return NULL;
1529   }
1530   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1531   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1532   if (aVec.Magnitude() < Precision::Confusion()) {
1533     SetErrorCode("Vector with null magnitude given");
1534     return NULL;
1535   }
1536
1537   gp_Ax3 anAx3 (aLoc, aVec);
1538   Handle(Geom_CylindricalSurface) aCylinder =
1539     new Geom_CylindricalSurface(anAx3, theRadius);
1540
1541   // Check presence of triangulation, build if need
1542   if (!CheckTriangulation(aShape))
1543     return NULL;
1544
1545   // Call algo
1546   GEOMAlgo_FinderShapeOn1 aFinder;
1547   Standard_Real aTol = 0.0001; // default value
1548
1549   aFinder.SetShape(aShape);
1550   aFinder.SetTolerance(aTol);
1551   aFinder.SetSurface(aCylinder);
1552   aFinder.SetShapeType(aShapeType);
1553   aFinder.SetState(theState);
1554
1555   aFinder.SetNbPntsMin(3);
1556   aFinder.SetNbPntsMax(100);
1557
1558   aFinder.Perform();
1559
1560   // Interprete results
1561   Standard_Integer iErr = aFinder.ErrorStatus();
1562   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1563   if (iErr) {
1564     MESSAGE(" iErr : " << iErr);
1565     TCollection_AsciiString aMsg (" iErr : ");
1566     aMsg += TCollection_AsciiString(iErr);
1567     SetErrorCode(aMsg);
1568     return NULL;
1569   }
1570   Standard_Integer iWrn = aFinder.WarningStatus();
1571   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1572   if (iWrn) {
1573     MESSAGE(" *** iWrn : " << iWrn);
1574   }
1575
1576   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1577
1578   if (listSS.Extent() < 1) {
1579     SetErrorCode("Not a single sub-shape of the requested type found on the given cylinder");
1580     return NULL;
1581   }
1582
1583   // Fill sequence of objects
1584   TopTools_IndexedMapOfShape anIndices;
1585   TopExp::MapShapes(aShape, anIndices);
1586
1587   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1588
1589   TopTools_ListIteratorOfListOfShape itSub (listSS);
1590   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1591     int id = anIndices.FindIndex(itSub.Value());
1592     aSeq->Append(id);
1593   }
1594   
1595   // The GetShapesOnCylinder() doesn't change object so no new function is required.
1596   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1597
1598   // Make a Python command
1599   TCollection_AsciiString anEntry, aDescr
1600     ("\nlistShapesOnCylinder = IShapesOperations.GetShapesOnCylinderIDs(");
1601   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1602   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1603   TDF_Tool::Entry(theAxis->GetEntry(), anEntry);
1604   aDescr += anEntry + ",";
1605   aDescr += TCollection_AsciiString(theRadius) + ",";
1606   aDescr += TCollection_AsciiString(theState) + ")";
1607
1608   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1609   anOldDescr += aDescr;
1610   aFunction->SetDescription(anOldDescr);
1611
1612   SetErrorCode(OK);
1613   return aSeq;
1614 }
1615
1616 //=============================================================================
1617 /*!
1618  *  GetShapesOnSphereIDs
1619  */
1620 //=============================================================================
1621 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
1622                                           (const Handle(GEOM_Object)& theShape,
1623                                            const Standard_Integer     theShapeType,
1624                                            const Handle(GEOM_Object)& theCenter,
1625                                            const Standard_Real        theRadius,
1626                                            const GEOMAlgo_State       theState)
1627 {
1628   SetErrorCode(KO);
1629
1630   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1631
1632   TopoDS_Shape aShape  = theShape->GetValue();
1633   TopoDS_Shape aCenter = theCenter->GetValue();
1634
1635   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1636
1637   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1638   if (aShapeType != TopAbs_VERTEX &&
1639       aShapeType != TopAbs_EDGE &&
1640       aShapeType != TopAbs_FACE &&
1641       aShapeType != TopAbs_SOLID) {
1642     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1643     return NULL;
1644   }
1645
1646   // Center of the sphere
1647   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1648   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1649
1650   gp_Ax3 anAx3 (aLoc, gp::DZ());
1651   Handle(Geom_SphericalSurface) aSphere =
1652     new Geom_SphericalSurface(anAx3, theRadius);
1653
1654   // Check presence of triangulation, build if need
1655   if (!CheckTriangulation(aShape))
1656     return NULL;
1657
1658   // Call algo
1659   GEOMAlgo_FinderShapeOn1 aFinder;
1660   Standard_Real aTol = 0.0001; // default value
1661
1662   aFinder.SetShape(aShape);
1663   aFinder.SetTolerance(aTol);
1664   aFinder.SetSurface(aSphere);
1665   aFinder.SetShapeType(aShapeType);
1666   aFinder.SetState(theState);
1667
1668   aFinder.SetNbPntsMin(3);
1669   aFinder.SetNbPntsMax(100);
1670
1671   aFinder.Perform();
1672
1673   // Interprete results
1674   Standard_Integer iErr = aFinder.ErrorStatus();
1675   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1676   if (iErr) {
1677     MESSAGE(" iErr : " << iErr);
1678     TCollection_AsciiString aMsg (" iErr : ");
1679     aMsg += TCollection_AsciiString(iErr);
1680     SetErrorCode(aMsg);
1681     return NULL;
1682   }
1683   Standard_Integer iWrn = aFinder.WarningStatus();
1684   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1685   if (iWrn) {
1686     MESSAGE(" *** iWrn : " << iWrn);
1687   }
1688
1689   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1690
1691   if (listSS.Extent() < 1) {
1692     SetErrorCode("Not a single sub-shape of the requested type found on the given sphere");
1693     return NULL;
1694   }
1695
1696   // Fill sequence of objects
1697   TopTools_IndexedMapOfShape anIndices;
1698   TopExp::MapShapes(aShape, anIndices);
1699
1700   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1701
1702   TopTools_ListIteratorOfListOfShape itSub (listSS);
1703   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1704     int id = anIndices.FindIndex(itSub.Value());
1705     aSeq->Append(id);
1706   }
1707   
1708   // The GetShapesOnSphere() doesn't change object so no new function is required.
1709   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1710
1711   // Make a Python command
1712   TCollection_AsciiString anEntry, aDescr
1713     ("\nlistShapesOnSphere = IShapesOperations.GetShapesOnSphereIDs(");
1714   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1715   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1716   TDF_Tool::Entry(theCenter->GetEntry(), anEntry);
1717   aDescr += anEntry + ",";
1718   aDescr += TCollection_AsciiString(theRadius) + ",";
1719   aDescr += TCollection_AsciiString(theState) + ")";
1720
1721   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1722   anOldDescr += aDescr;
1723   aFunction->SetDescription(anOldDescr);
1724
1725   SetErrorCode(OK);
1726   return aSeq;
1727 }
1728
1729 //=============================================================================
1730 /*!
1731  *  GetInPlace
1732  */
1733 //=============================================================================
1734 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
1735                                           (Handle(GEOM_Object) theShapeWhere,
1736                                            Handle(GEOM_Object) theShapeWhat)
1737 {
1738   SetErrorCode(KO);
1739
1740   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
1741
1742   TopoDS_Shape aWhere = theShapeWhere->GetValue();
1743   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
1744
1745   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
1746
1747   //Fill array of indices
1748   Handle(TColStd_HArray1OfInteger) aModifiedArray;
1749
1750   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
1751
1752   TopTools_IndexedMapOfShape aWhereIndices;
1753   TopExp::MapShapes(aWhere, aWhereIndices);
1754
1755   if (aWhereIndices.Contains(aWhat)) {
1756
1757     // entity was not changed by the operation
1758     Standard_Integer aWhatIndex = aWhereIndices.FindIndex(aWhat);
1759     aModifiedArray = new TColStd_HArray1OfInteger(1,1);
1760     aModifiedArray->SetValue(1, aWhatIndex);
1761
1762   } else {
1763
1764     TDF_Label aHistoryLabel = aWhereFunction->GetHistoryEntry(Standard_False);
1765     if (aHistoryLabel.IsNull()) {
1766       SetErrorCode("Modifications history does not exist for the shape under consideration.");
1767       return NULL;
1768     }
1769
1770     // search in history for all argument shapes
1771     Standard_Boolean isFound = Standard_False;
1772
1773     TDF_LabelSequence aLabelSeq;
1774     aWhereFunction->GetDependency(aLabelSeq);
1775     Standard_Integer nbArg = aLabelSeq.Length();
1776
1777     for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
1778
1779       TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
1780
1781       Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
1782       TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
1783
1784       TopTools_IndexedMapOfShape anArgumentIndices;
1785       TopExp::MapShapes(anArgumentShape, anArgumentIndices);
1786
1787       if (anArgumentIndices.Contains(aWhat)) {
1788         isFound = Standard_True;
1789         Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(aWhat);
1790
1791         // Find corresponding label in history
1792         TDF_Label anArgumentHistoryLabel =
1793           aWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
1794         if (anArgumentHistoryLabel.IsNull()) {
1795           // Lost History of operation argument. Possibly, all its entities was removed.
1796           SetErrorCode(OK);
1797           return NULL;
1798         }
1799
1800         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
1801         if (aWhatHistoryLabel.IsNull()) {
1802           // Removed entity
1803           SetErrorCode(OK);
1804           return NULL;
1805         }
1806
1807         Handle(TDataStd_IntegerArray) anIntegerArray;
1808         if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
1809           SetErrorCode("Error: Empty modifications history for the sought shape.");
1810           return NULL;
1811         }
1812
1813         aModifiedArray = anIntegerArray->Array();
1814         if (aModifiedArray->Length() == 0) {
1815           SetErrorCode("Error: Empty modifications history for the sought shape.");
1816           return NULL;
1817         }
1818       }
1819     }
1820
1821     if (!isFound) {
1822       SetErrorCode("The sought shape does not belong to any operation argument.");
1823       return NULL;
1824     }
1825   }
1826
1827   //Add a new object
1828   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
1829
1830   if (aModifiedArray->Length() > 1) {
1831     //Set a GROUP type
1832     aResult->SetType(GEOM_GROUP);
1833
1834     //Set a sub shape type
1835     TDF_Label aFreeLabel = aResult->GetFreeLabel();
1836     TopAbs_ShapeEnum aShapeType = aWhat.ShapeType();
1837     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
1838   }
1839
1840   //Make a Python command
1841   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
1842
1843   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
1844     << theShapeWhere << ", " << theShapeWhat << ")";
1845
1846   SetErrorCode(OK);
1847   return aResult;
1848 }
1849
1850 //=======================================================================
1851 //function : SortShapes
1852 //purpose  :
1853 //=======================================================================
1854 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
1855 {
1856   Standard_Integer MaxShapes = SL.Extent();
1857   TopTools_Array1OfShape  aShapes (1,MaxShapes);
1858   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
1859   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
1860   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
1861
1862   // Computing of CentreOfMass
1863   Standard_Integer Index;
1864   GProp_GProps GPr;
1865   gp_Pnt GPoint;
1866   TopTools_ListIteratorOfListOfShape it(SL);
1867   for (Index=1;  it.More();  Index++)
1868   {
1869     TopoDS_Shape S = it.Value();
1870     SL.Remove( it ); // == it.Next()
1871     aShapes(Index) = S;
1872     OrderInd.SetValue (Index, Index);
1873     if (S.ShapeType() == TopAbs_VERTEX)
1874     {
1875       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
1876       Length.SetValue( Index, (Standard_Real) S.Orientation());
1877     }
1878     else
1879     {
1880       BRepGProp::LinearProperties (S, GPr);
1881       GPoint = GPr.CentreOfMass();
1882       Length.SetValue( Index, GPr.Mass() );
1883     }
1884     MidXYZ.SetValue(Index,
1885                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
1886   }
1887   // Sorting
1888   Standard_Integer aTemp;
1889   Standard_Boolean exchange, Sort = Standard_True;
1890   while (Sort)
1891   {
1892     Sort = Standard_False;
1893     for (Index=1; Index < MaxShapes; Index++)
1894     {
1895       if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
1896         exchange = Standard_True;
1897       else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
1898                Length(OrderInd(Index)) >  Length(OrderInd(Index+1)) )
1899         exchange = Standard_True;
1900       else
1901         exchange = Standard_False;
1902       if (exchange)
1903       {
1904         aTemp = OrderInd(Index);
1905         OrderInd(Index) = OrderInd(Index+1);
1906         OrderInd(Index+1) = aTemp;
1907         Sort = Standard_True;
1908       }
1909     }
1910   }
1911   for (Index=1; Index <= MaxShapes; Index++)
1912     SL.Append( aShapes( OrderInd(Index) ));
1913 }
1914
1915 //=======================================================================
1916 //function : CheckTriangulation
1917 //purpose  :
1918 //=======================================================================
1919 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
1920 {
1921 //  MESSAGE("CheckTriangulation");
1922 //
1923 //  OSD_Timer timer1;
1924 //  timer1.Start();
1925
1926   TopExp_Explorer exp (aShape, TopAbs_FACE);
1927   if (!exp.More()) {
1928     SetErrorCode("Shape without faces given");
1929     return false;
1930   }
1931
1932   TopLoc_Location aTopLoc;
1933   Handle(Poly_Triangulation) aTRF;
1934   aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
1935   if (aTRF.IsNull()) {
1936     // calculate deflection
1937     Standard_Real aDeviationCoefficient = 0.001;
1938
1939     Bnd_Box B;
1940     BRepBndLib::Add(aShape, B);
1941     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
1942     B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
1943
1944     Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
1945     Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
1946
1947 //    MESSAGE("Deflection = " << aDeflection);
1948
1949     Standard_Real aHLRAngle = 0.349066;
1950
1951     BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
1952   }
1953 //  timer1.Stop();
1954 //  timer1.Show();
1955
1956   return true;
1957 }