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