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