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