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