]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
Salome HOME
0023043: EDF 10596 GEOM: GetShapesOnShape does not return all shapes expected
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File      : GEOMImpl_IShapesOperations.cxx
24 //  Created   :
25 //  Author    : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007
26 //  Project   : SALOME
27
28 //#include <Standard_Stream.hxx>
29
30 #include "GEOMImpl_IShapesOperations.hxx"
31
32 #include "GEOMImpl_Types.hxx"
33
34 #include "GEOMImpl_VectorDriver.hxx"
35 #include "GEOMImpl_ShapeDriver.hxx"
36 #include "GEOMImpl_GlueDriver.hxx"
37 #include "GEOMImpl_FillingDriver.hxx"
38
39 #include "GEOMImpl_IVector.hxx"
40 #include "GEOMImpl_IShapes.hxx"
41 #include "GEOMImpl_IShapeExtend.hxx"
42 #include "GEOMImpl_IGlue.hxx"
43 #include "GEOMImpl_IFilling.hxx"
44
45 #include "GEOMImpl_Block6Explorer.hxx"
46 #include "GEOMImpl_IHealingOperations.hxx"
47
48 #include "GEOMImpl_Gen.hxx"
49
50 #include "GEOM_Function.hxx"
51 #include "GEOM_ISubShape.hxx"
52 #include "GEOM_PythonDump.hxx"
53
54 #include "GEOMUtils.hxx"
55
56 #include "GEOMAlgo_ClsfBox.hxx"
57 #include "GEOMAlgo_ClsfQuad.hxx"
58 #include "GEOMAlgo_ClsfSolid.hxx"
59 #include "GEOMAlgo_ClsfSurf.hxx"
60 #include "GEOMAlgo_FinderShapeOn2.hxx"
61 #include "GEOMAlgo_GetInPlace.hxx"
62 #include "GEOMAlgo_GetInPlaceAPI.hxx"
63 #include "GEOMAlgo_GlueDetector.hxx"
64
65 #include <utilities.h>
66
67 #include <BRepAdaptor_Curve.hxx>
68 #include <BRepAdaptor_Surface.hxx>
69 #include <BRepTools.hxx>
70 #include <BRep_Builder.hxx>
71 #include <BRep_Tool.hxx>
72 #include <GeomLib_Tool.hxx>
73 #include <Geom_CylindricalSurface.hxx>
74 #include <Geom_Plane.hxx>
75 #include <Geom_SphericalSurface.hxx>
76 #include <Geom_Surface.hxx>
77 #include <Precision.hxx>
78 #include <TColStd_HArray1OfInteger.hxx>
79 #include <TDF_Tool.hxx>
80 #include <TDataStd_Integer.hxx>
81 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
82 #include <TopExp.hxx>
83 #include <TopExp_Explorer.hxx>
84 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
85 #include <TopTools_IndexedMapOfShape.hxx>
86 #include <TopTools_ListIteratorOfListOfShape.hxx>
87 #include <TopTools_MapOfOrientedShape.hxx>
88 #include <TopTools_MapOfShape.hxx>
89 #include <TopTools_SequenceOfShape.hxx>
90 #include <TopoDS.hxx>
91 #include <TopoDS_Compound.hxx>
92 #include <TopoDS_Edge.hxx>
93 #include <TopoDS_Face.hxx>
94 #include <TopoDS_Iterator.hxx>
95 #include <TopoDS_Shape.hxx>
96 #include <TopoDS_Solid.hxx>
97 #include <TopoDS_Vertex.hxx>
98 #include <gp_Cylinder.hxx>
99 #include <gp_Pnt.hxx>
100
101 #include <vector>
102
103 #include <Standard_Failure.hxx>
104 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
105
106 namespace {
107
108   void AddFlatSubShapes(const TopoDS_Shape& S, TopTools_ListOfShape& L, TopTools_MapOfShape& M)
109   {
110     if (S.ShapeType() != TopAbs_COMPOUND) {
111       L.Append(S);
112     }
113     else {
114       TopoDS_Iterator It(S, Standard_True, Standard_True);
115       for (; It.More(); It.Next()) {
116         TopoDS_Shape SS = It.Value();
117         if (M.Add(SS))
118           AddFlatSubShapes(SS, L, M);
119       }
120     }
121   }
122 }
123
124 namespace
125 {
126   const double MAX_TOLERANCE = 1.e-7;
127
128   /**
129    * \brief Returns the vertex from theWhere shape that is coincident with
130    * theVertex.
131    *
132    * \param theWhere the shape where the coinsident vertex is searched.
133    * \param theVertex the vertex to be searched.
134    * \return the coincident vertex if it is found. Otherwise null object.
135    */
136   static TopoDS_Vertex getSameVertex(const TopoDS_Shape  &theWhere,
137                                      const TopoDS_Vertex &theVertex)
138   {
139     TopoDS_Vertex       aResult;
140     gp_Pnt              aPoint = BRep_Tool::Pnt(theVertex);
141     TopExp_Explorer     anExp(theWhere, TopAbs_VERTEX);
142     TopTools_MapOfShape aMap;
143     
144     for(; anExp.More(); anExp.Next()) {
145       const TopoDS_Shape &aLocalShape = anExp.Current();
146
147       if(!aMap.Add(aLocalShape)) {
148         continue;
149       }
150
151       TopoDS_Vertex aVertex = TopoDS::Vertex(aLocalShape);
152       gp_Pnt        aPoint2 = BRep_Tool::Pnt(aVertex);
153
154       if(aPoint.Distance(aPoint2) <= MAX_TOLERANCE) {
155         aResult = aVertex;
156         break;
157       }
158     }
159
160     return aResult;
161   }
162 } // end of namespace
163
164 //=============================================================================
165 /*!
166  *   constructor:
167  */
168 //=============================================================================
169 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
170 : GEOM_IOperations(theEngine, theDocID)
171 {
172   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
173 }
174
175 //=============================================================================
176 /*!
177  *  destructor
178  */
179 //=============================================================================
180 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
181 {
182   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
183 }
184
185 //=============================================================================
186 /*!
187  *  MakeEdge
188  */
189 //=============================================================================
190 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
191                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
192 {
193   SetErrorCode(KO);
194
195   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
196
197   //Add a new Edge object
198   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
199
200   //Add a new Vector function
201   Handle(GEOM_Function) aFunction =
202     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
203
204   //Check if the function is set correctly
205   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
206
207   GEOMImpl_IVector aPI (aFunction);
208
209   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
210   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
211   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
212
213   aPI.SetPoint1(aRef1);
214   aPI.SetPoint2(aRef2);
215
216   //Compute the Edge value
217   try {
218     OCC_CATCH_SIGNALS;
219     if (!GetSolver()->ComputeFunction(aFunction)) {
220       SetErrorCode("Vector driver failed");
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) << anEdge << " = geompy.MakeEdge("
232                                << thePnt1 << ", " << thePnt2 << ")";
233
234   SetErrorCode(OK);
235   return anEdge;
236 }
237
238 //=============================================================================
239 /*!
240  *  MakeEdgeOnCurveByLength
241  */
242 //=============================================================================
243 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeOnCurveByLength
244                      (Handle(GEOM_Object) theRefCurve,
245                       const Standard_Real theLength,
246                       Handle(GEOM_Object) theStartPoint)
247 {
248   SetErrorCode(KO);
249
250   if (theRefCurve.IsNull()) return NULL;
251
252   //Add a new Edge object
253   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
254
255   //Add a new Vector function
256   Handle(GEOM_Function) aFunction =
257     anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_CURVE_LENGTH);
258
259   //Check if the function is set correctly
260   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
261
262   GEOMImpl_IVector aPI (aFunction);
263
264   Handle(GEOM_Function) aRef1 = theRefCurve->GetLastFunction();
265   if (aRef1.IsNull()) return NULL;
266   aPI.SetPoint1(aRef1);
267
268   if (!theStartPoint.IsNull()) {
269     Handle(GEOM_Function) aRef2 = theStartPoint->GetLastFunction();
270     aPI.SetPoint2(aRef2);
271   }
272
273   aPI.SetParameter(theLength);
274
275   //Compute the Edge value
276   try {
277     OCC_CATCH_SIGNALS;
278     if (!GetSolver()->ComputeFunction(aFunction)) {
279       SetErrorCode("Vector driver failed");
280       return NULL;
281     }
282   }
283   catch (Standard_Failure) {
284     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
285     SetErrorCode(aFail->GetMessageString());
286     return NULL;
287   }
288
289   //Make a Python command
290   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeOnCurveByLength("
291                                << theRefCurve << ", " << theLength << ", " << theStartPoint << ")";
292
293   SetErrorCode(OK);
294   return anEdge;
295 }
296
297 //=============================================================================
298 /*!
299  *  MakeEdgeWire
300  */
301 //=============================================================================
302 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire
303                     (Handle(GEOM_Object) theWire,
304                      const Standard_Real theLinearTolerance,
305                      const Standard_Real theAngularTolerance)
306 {
307   SetErrorCode(KO);
308
309   if (theWire.IsNull()) return NULL;
310
311   //Add a new Edge object
312   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
313
314   //Add a new Vector function
315   Handle(GEOM_Function) aFunction =
316     anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_WIRE);
317
318   //Check if the function is set correctly
319   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
320
321   GEOMImpl_IShapes aCI (aFunction);
322
323   Handle(GEOM_Function) aWire = theWire->GetLastFunction();
324
325   if (aWire.IsNull()) return NULL;
326
327   aCI.SetBase(aWire);
328   aCI.SetTolerance(theLinearTolerance);
329   aCI.SetAngularTolerance(theAngularTolerance);
330
331   //Compute the Edge value
332   try {
333     OCC_CATCH_SIGNALS;
334     if (!GetSolver()->ComputeFunction(aFunction)) {
335       SetErrorCode("Shape driver failed");
336       return NULL;
337     }
338   }
339   catch (Standard_Failure) {
340     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
341     SetErrorCode(aFail->GetMessageString());
342     return NULL;
343   }
344
345   const double DEF_LIN_TOL = Precision::Confusion();
346   const double DEF_ANG_TOL = Precision::Angular();
347   //Make a Python command
348   if ( theAngularTolerance == DEF_ANG_TOL ) {
349     if ( theLinearTolerance == DEF_LIN_TOL )
350       GEOM::TPythonDump(aFunction) << anEdge  << " = geompy.MakeEdgeWire("
351                                    << theWire << ")";
352     else
353       GEOM::TPythonDump(aFunction) << anEdge  << " = geompy.MakeEdgeWire("
354                                    << theWire << ", " << theLinearTolerance << ")";
355   }
356   else {
357     GEOM::TPythonDump(aFunction) << anEdge  << " = geompy.MakeEdgeWire("
358                                  << theWire << ", " << theLinearTolerance << ", "
359                                  << theAngularTolerance << ")";
360   }
361
362   SetErrorCode(OK);
363   return anEdge;
364 }
365
366 //=============================================================================
367 /*!
368  *  MakeWire
369  */
370 //=============================================================================
371 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
372                              (std::list<Handle(GEOM_Object)> theShapes,
373                               const Standard_Real            theTolerance)
374 {
375   SetErrorCode(KO);
376
377   //Add a new object
378   Handle(GEOM_Object) aWire = GetEngine()->AddObject(GetDocID(), GEOM_WIRE);
379
380   //Add a new function
381   Handle(GEOM_Function) aFunction =
382     aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES);
383   if (aFunction.IsNull()) return NULL;
384
385   //Check if the function is set correctly
386   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
387
388   GEOMImpl_IShapes aCI (aFunction);
389   aCI.SetTolerance(theTolerance);
390
391   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
392
393   // Shapes
394   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
395   for (; it != theShapes.end(); it++) {
396     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
397     if (aRefSh.IsNull()) {
398       SetErrorCode("NULL argument shape for the shape construction");
399       return NULL;
400     }
401     aShapesSeq->Append(aRefSh);
402   }
403   aCI.SetShapes(aShapesSeq);
404
405   //Compute the shape
406   try {
407     OCC_CATCH_SIGNALS;
408     if (!GetSolver()->ComputeFunction(aFunction)) {
409       SetErrorCode("Shape driver failed");
410       return NULL;
411     }
412   }
413   catch (Standard_Failure) {
414     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
415     SetErrorCode(aFail->GetMessageString());
416     return NULL;
417   }
418
419   //Make a Python command
420   GEOM::TPythonDump pd (aFunction);
421   pd << aWire << " = geompy.MakeWire([";
422
423   // Shapes
424   it = theShapes.begin();
425   if (it != theShapes.end()) {
426     pd << (*it++);
427     while (it != theShapes.end()) {
428       pd << ", " << (*it++);
429     }
430   }
431   pd << "], " << theTolerance << ")";
432
433   SetErrorCode(OK);
434   return aWire;
435 }
436
437 //=============================================================================
438 /*!
439  *  MakeFace
440  */
441 //=============================================================================
442 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
443                                                           const bool isPlanarWanted)
444 {
445   SetErrorCode(KO);
446
447   if (theWire.IsNull()) return NULL;
448
449   //Add a new Face object
450   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
451
452   //Add a new Shape function for creation of a face from a wire
453   Handle(GEOM_Function) aFunction =
454     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
455   if (aFunction.IsNull()) return NULL;
456
457   //Check if the function is set correctly
458   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
459
460   GEOMImpl_IShapes aCI (aFunction);
461
462   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
463
464   if (aRefWire.IsNull()) return NULL;
465
466   aCI.SetBase(aRefWire);
467   aCI.SetIsPlanar(isPlanarWanted);
468
469   //Compute the Face value
470   Standard_Boolean isWarning = Standard_False;
471   try {
472     OCC_CATCH_SIGNALS;
473     if (!GetSolver()->ComputeFunction(aFunction)) {
474       SetErrorCode("Shape driver failed to compute a face");
475       return NULL;
476     }
477   }
478   catch (Standard_Failure) {
479     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
480     SetErrorCode(aFail->GetMessageString());
481     // to provide warning
482     if (!aFunction->GetValue().IsNull()) {
483       isWarning = Standard_True;
484     } else {
485       return NULL;
486     }
487   }
488
489   //Make a Python command
490   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
491     << theWire << ", " << (int)isPlanarWanted << ")";
492
493   // to provide warning
494   if (!isWarning) SetErrorCode(OK);
495   return aFace;
496 }
497
498 //=============================================================================
499 /*!
500  *  MakeFaceWires
501  */
502 //=============================================================================
503 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
504                              (std::list<Handle(GEOM_Object)> theShapes,
505                               const bool isPlanarWanted)
506 {
507   SetErrorCode(KO);
508
509   //Add a new object
510   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
511
512   //Add a new function
513   Handle(GEOM_Function) aFunction =
514     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
515   if (aFunction.IsNull()) return NULL;
516
517   //Check if the function is set correctly
518   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
519
520   GEOMImpl_IShapes aCI (aFunction);
521
522   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
523
524   // Shapes
525   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
526   for (; it != theShapes.end(); it++) {
527     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
528     if (aRefSh.IsNull()) {
529       SetErrorCode("NULL argument shape for the face construction");
530       return NULL;
531     }
532     aShapesSeq->Append(aRefSh);
533   }
534   aCI.SetShapes(aShapesSeq);
535
536   aCI.SetIsPlanar(isPlanarWanted);
537
538   //Compute the shape
539   Standard_Boolean isWarning = Standard_False;
540   try {
541     OCC_CATCH_SIGNALS;
542     if (!GetSolver()->ComputeFunction(aFunction)) {
543       SetErrorCode("Shape driver failed");
544       return NULL;
545     }
546   }
547   catch (Standard_Failure) {
548     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
549     SetErrorCode(aFail->GetMessageString());
550     // to provide warning
551     if (!aFunction->GetValue().IsNull()) {
552       isWarning = Standard_True;
553     } else {
554       return NULL;
555     }
556   }
557
558   //Make a Python command
559   GEOM::TPythonDump pd (aFunction);
560   pd << aShape << " = geompy.MakeFaceWires([";
561
562   // Shapes
563   it = theShapes.begin();
564   if (it != theShapes.end()) {
565     pd << (*it++);
566     while (it != theShapes.end()) {
567       pd << ", " << (*it++);
568     }
569   }
570   pd << "], " << (int)isPlanarWanted << ")";
571
572   // to provide warning
573   if (!isWarning) SetErrorCode(OK);
574   return aShape;
575 }
576
577 //=============================================================================
578 /*!
579  *  MakeFaceFromSurface
580  */
581 //=============================================================================
582 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface
583                                               (Handle(GEOM_Object) theFace,
584                                                Handle(GEOM_Object) theWire)
585 {
586   SetErrorCode(KO);
587
588   //Add a new object
589   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
590
591   //Add a new function
592   Handle(GEOM_Function) aFunction =
593     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_FROM_SURFACE);
594
595   if (aFunction.IsNull()) {
596     return NULL;
597   }
598
599   //Check if the function is set correctly
600   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
601     return NULL;
602   }
603
604   GEOMImpl_IShapes aCI (aFunction);
605   Handle(TColStd_HSequenceOfTransient) aShapesSeq =
606     new TColStd_HSequenceOfTransient;
607   Handle(GEOM_Function) aRefFace = theFace->GetLastFunction();
608   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
609
610   if (aRefFace.IsNull()) {
611     SetErrorCode("NULL argument face for the face construction");
612     return NULL;
613   }
614
615   if (aRefWire.IsNull()) {
616     SetErrorCode("NULL argument wire for the face construction");
617     return NULL;
618   }
619
620   aShapesSeq->Append(aRefFace);
621   aShapesSeq->Append(aRefWire);
622
623   aCI.SetShapes(aShapesSeq);
624
625   //Compute the face
626   try {
627     OCC_CATCH_SIGNALS;
628     if (!GetSolver()->ComputeFunction(aFunction)) {
629       SetErrorCode("Shape driver failed");
630       return NULL;
631     }
632   }
633   catch (Standard_Failure) {
634     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
635     SetErrorCode(aFail->GetMessageString());
636     return NULL;
637   }
638
639   //Make a Python command
640   GEOM::TPythonDump (aFunction) << aShape
641     << " = geompy.MakeFaceFromSurface(" << theFace << ", " << theWire << ")";
642
643   SetErrorCode(OK);
644
645   return aShape;
646 }
647
648 //=============================================================================
649 /*!
650  *  MakeFaceWithConstraints
651  */
652 //=============================================================================
653 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWithConstraints
654                              (std::list<Handle(GEOM_Object)> theConstraints)
655 {
656   SetErrorCode(KO);
657
658   //Add a new object
659   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FILLING);
660
661   //Add a new function
662   Handle(GEOM_Function) aFunction =
663     aShape->AddFunction(GEOMImpl_FillingDriver::GetID(), FILLING_ON_CONSTRAINTS);
664   if (aFunction.IsNull()) return NULL;
665
666   //Check if the function is set correctly
667   if (aFunction->GetDriverGUID() != GEOMImpl_FillingDriver::GetID()) return NULL;
668
669   GEOMImpl_IFilling aCI (aFunction);
670   Handle(TColStd_HSequenceOfTransient) aConstraints = new TColStd_HSequenceOfTransient;
671
672   // Shapes
673   std::list<Handle(GEOM_Object)>::iterator it = theConstraints.begin();
674   while (it != theConstraints.end()) {
675     Handle(GEOM_Object) anObject = (*it);
676     if ( anObject.IsNull() || anObject->GetValue().ShapeType() != TopAbs_EDGE ) {
677       SetErrorCode("NULL argument edge for the face construction");
678       return NULL;
679     }
680     Handle(GEOM_Function) aRefSh = anObject->GetLastFunction();
681     aConstraints->Append(aRefSh);
682     it++;
683     if ( it != theConstraints.end() ) {
684       Handle(GEOM_Object) aFace = (*it);
685       if ( aFace.IsNull() ) {
686         // null constraint face - it is a valid case
687         it++;
688         continue;
689       }
690       if ( aFace->GetValue().ShapeType() != TopAbs_FACE )
691         // constraint face can be omitted - it is a valid case
692         continue;
693       if ( IsSubShapeBelongsTo( anObject, 0, aFace, 0 ) ) {
694         // valid constraint
695         aRefSh = aFace->GetLastFunction();
696         aConstraints->Append(aRefSh);
697         it++;
698       }
699       else {
700         // bad constraint
701         SetErrorCode("Face is NULL or not connected to the Edge");
702         return NULL;
703       }
704     }
705   }
706   aCI.SetShapes( aConstraints );
707
708   //Compute the shape
709   Standard_Boolean isWarning = Standard_False;
710   try {
711     OCC_CATCH_SIGNALS;
712     if (!GetSolver()->ComputeFunction(aFunction)) {
713       SetErrorCode("Shape driver failed");
714       return NULL;
715     }
716   }
717   catch (Standard_Failure) {
718     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
719     SetErrorCode(aFail->GetMessageString());
720     // to provide warning
721     if (!aFunction->GetValue().IsNull()) {
722       isWarning = Standard_True;
723     } else {
724       return NULL;
725     }
726   }
727
728   //Make a Python command
729   GEOM::TPythonDump pd (aFunction);
730   pd << aShape << " = geompy.MakeFaceWithConstraints([";
731
732   // Constraints
733   it = theConstraints.begin();
734   if (it != theConstraints.end() ) {
735     pd << (*it++);
736     while (it != theConstraints.end()) {
737       Handle(GEOM_Object) anObject = (*it++);
738       if( !anObject.IsNull() )
739         pd << ", " << anObject;
740     }
741   }
742   pd << "])";
743
744   // to provide warning
745   if (!isWarning) SetErrorCode(OK);
746   return aShape;
747 }
748
749 //=============================================================================
750 /*!
751  *  MakeShell
752  */
753 //=============================================================================
754 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
755                              (std::list<Handle(GEOM_Object)> theShapes)
756 {
757   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
758 }
759
760 //=============================================================================
761 /*!
762  *  MakeSolidShells
763  */
764 //=============================================================================
765 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
766                              (std::list<Handle(GEOM_Object)> theShapes)
767 {
768   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
769 }
770
771 //=============================================================================
772 /*!
773  *  MakeCompound
774  */
775 //=============================================================================
776 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
777                              (std::list<Handle(GEOM_Object)> theShapes)
778 {
779   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
780 }
781
782 //=============================================================================
783 /*!
784  *  MakeShape
785  */
786 //=============================================================================
787 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
788                              (std::list<Handle(GEOM_Object)> theShapes,
789                               const Standard_Integer         theObjectType,
790                               const Standard_Integer         theFunctionType,
791                               const TCollection_AsciiString& theMethodName)
792 {
793   SetErrorCode(KO);
794
795   //Add a new object
796   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
797
798   //Add a new function
799   Handle(GEOM_Function) aFunction =
800     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
801   if (aFunction.IsNull()) return NULL;
802
803   //Check if the function is set correctly
804   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
805
806   GEOMImpl_IShapes aCI (aFunction);
807
808   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
809
810   // Shapes
811   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
812   for (; it != theShapes.end(); it++) {
813     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
814     if (aRefSh.IsNull()) {
815       SetErrorCode("NULL argument shape for the shape construction");
816       return NULL;
817     }
818     aShapesSeq->Append(aRefSh);
819   }
820   aCI.SetShapes(aShapesSeq);
821
822   //Compute the shape
823   try {
824     OCC_CATCH_SIGNALS;
825     if (!GetSolver()->ComputeFunction(aFunction)) {
826       SetErrorCode("Shape driver failed");
827       return NULL;
828     }
829   }
830   catch (Standard_Failure) {
831     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
832     SetErrorCode(aFail->GetMessageString());
833     return NULL;
834   }
835
836   //Make a Python command
837   GEOM::TPythonDump pd (aFunction);
838   pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
839
840   // Shapes
841   it = theShapes.begin();
842   if (it != theShapes.end()) {
843     pd << (*it++);
844     while (it != theShapes.end()) {
845       pd << ", " << (*it++);
846     }
847   }
848   pd << "])";
849
850   SetErrorCode(OK);
851   return aShape;
852 }
853
854 //=============================================================================
855 /*!
856  *  MakeSolidFromConnectedFaces
857  */
858 //=============================================================================
859 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidFromConnectedFaces
860                              (std::list<Handle(GEOM_Object)> theFacesOrShells,
861                               const Standard_Boolean isIntersect)
862 {
863   SetErrorCode(KO);
864
865   //Add a new object
866   Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
867
868   //Add a new function
869   Handle(GEOM_Function) aFunction =
870     aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_FACES);
871   if (aFunction.IsNull()) return NULL;
872
873   //Check if the function is set correctly
874   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
875
876   GEOMImpl_IShapes aCI (aFunction);
877
878   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
879
880   // Shapes
881   std::list<Handle(GEOM_Object)>::iterator it = theFacesOrShells.begin();
882   for (; it != theFacesOrShells.end(); it++) {
883     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
884     if (aRefSh.IsNull()) {
885       SetErrorCode("NULL argument shape for the shape construction");
886       return NULL;
887     }
888     aShapesSeq->Append(aRefSh);
889   }
890   aCI.SetShapes(aShapesSeq);
891   aCI.SetIsIntersect(isIntersect);
892
893   //Compute the shape
894   try {
895     OCC_CATCH_SIGNALS;
896     if (!GetSolver()->ComputeFunction(aFunction)) {
897       SetErrorCode("Shape driver failed");
898       return NULL;
899     }
900   }
901   catch (Standard_Failure) {
902     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
903     SetErrorCode(aFail->GetMessageString());
904     return NULL;
905   }
906
907   //Make a Python command
908   GEOM::TPythonDump pd (aFunction);
909   pd << aSolid << " = geompy.MakeSolidFromConnectedFaces([";
910
911   // Shapes
912   it = theFacesOrShells.begin();
913   if (it != theFacesOrShells.end()) {
914     pd << (*it++);
915     while (it != theFacesOrShells.end()) {
916       pd << ", " << (*it++);
917     }
918   }
919   pd << "]," << (isIntersect ? "True" : "False") << ")";
920
921   SetErrorCode(OK);
922   return aSolid;
923 }
924
925 //=============================================================================
926 /*!
927  *  MakeGlueFaces
928  */
929 //=============================================================================
930 Handle(GEOM_Object)
931 GEOMImpl_IShapesOperations::MakeGlueFaces (std::list< Handle(GEOM_Object) >& theShapes,
932                                            const Standard_Real               theTolerance,
933                                            const Standard_Boolean            doKeepNonSolids)
934 {
935   SetErrorCode(KO);
936
937   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
938   if ( objects.IsNull() || objects->IsEmpty() ) {
939     SetErrorCode("NULL argument shape");
940     return NULL;
941   }
942
943   //Add a new Glued object
944   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
945
946   //Add a new Glue function
947   Handle(GEOM_Function) aFunction;
948   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
949   if (aFunction.IsNull()) return NULL;
950
951   //Check if the function is set correctly
952   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
953
954   GEOMImpl_IGlue aCI (aFunction);
955
956   aCI.SetBase( objects );
957   aCI.SetTolerance(theTolerance);
958   aCI.SetKeepNonSolids(doKeepNonSolids);
959
960   //Compute the sub-shape value
961   Standard_Boolean isWarning = Standard_False;
962   try {
963     OCC_CATCH_SIGNALS;
964     if (!GetSolver()->ComputeFunction(aFunction)) {
965       SetErrorCode("Shape driver failed to glue faces");
966       return NULL;
967     }
968   }
969   catch (Standard_Failure) {
970     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
971     SetErrorCode(aFail->GetMessageString());
972     // to provide warning
973     if (!aFunction->GetValue().IsNull()) {
974       isWarning = Standard_True;
975     } else {
976       return NULL;
977     }
978   }
979
980   //Make a Python command
981   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
982     << theShapes << ", " << theTolerance << ")";
983
984   // to provide warning
985   if (!isWarning) SetErrorCode(OK);
986   return aGlued;
987 }
988
989 //=============================================================================
990 /*!
991  *  GetGlueFaces
992  */
993 //=============================================================================
994 /*
995 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces
996                                                 (Handle(GEOM_Object) theShape,
997                                                  const Standard_Real theTolerance)
998 {
999   SetErrorCode(KO);
1000
1001   if (theShape.IsNull()) return NULL;
1002   TopoDS_Shape aShape = theShape->GetValue();
1003   if (aShape.IsNull()) return NULL;
1004
1005   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1006
1007   Standard_Integer iErr;
1008   TopoDS_Shape aS;
1009   GEOMAlgo_Gluer1 aGluer;
1010   GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS;
1011   GEOMAlgo_CoupleOfShapes aCS;
1012   GEOMAlgo_ListOfCoupleOfShapes aLCS;
1013
1014   //aGluer = new GEOMAlgo_Gluer1;
1015   aGluer.SetShape(aShape);
1016   aGluer.SetTolerance(theTolerance);
1017   aGluer.Perform();
1018   iErr = aGluer.ErrorStatus();
1019   if (iErr) return NULL;
1020
1021   TopTools_ListOfShape listShape;
1022   const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces();
1023   // Access to faces
1024   aItCS.Initialize(aLCSG);
1025   for (; aItCS.More(); aItCS.Next()) {
1026     const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value();
1027     listShape.Append(aCSG.Shape1());
1028   }
1029
1030   TopTools_ListIteratorOfListOfShape itSub (listShape);
1031   TCollection_AsciiString anAsciiList, anEntry;
1032   TopTools_IndexedMapOfShape anIndices;
1033   TopExp::MapShapes(aShape, anIndices);
1034   Handle(TColStd_HArray1OfInteger) anArray;
1035   Handle(GEOM_Object) anObj;
1036   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1037     TopoDS_Shape aValue = itSub.Value();
1038     anArray = new TColStd_HArray1OfInteger(1,1);
1039     anArray->SetValue(1, anIndices.FindIndex(aValue));
1040     anObj = GetEngine()->AddSubShape(theShape, anArray);
1041     if (!anObj.IsNull()) {
1042       aSeq->Append(anObj);
1043
1044       // for python command
1045       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1046       anAsciiList += anEntry;
1047       anAsciiList += ",";
1048     }
1049   }
1050
1051   //Make a Python command
1052   if( anAsciiList.Length() > 0 ) {
1053     anAsciiList.Trunc(anAsciiList.Length() - 1);
1054     Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1055     GEOM::TPythonDump pd (aFunction, true);
1056     pd << "[" << anAsciiList.ToCString();
1057     pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")";
1058   }
1059
1060   SetErrorCode(OK);
1061
1062   return aSeq;
1063 }
1064 */
1065
1066 //=============================================================================
1067 /*!
1068  *  MakeGlueFacesByList
1069  */
1070 //=============================================================================
1071 Handle(GEOM_Object)
1072 GEOMImpl_IShapesOperations::MakeGlueFacesByList(std::list< Handle(GEOM_Object) >& theShapes,
1073                                                 const Standard_Real               theTolerance,
1074                                                 std::list<Handle(GEOM_Object)> &  theFaces,
1075                                                 const Standard_Boolean            doKeepNonSolids,
1076                                                 const Standard_Boolean            doGlueAllEdges)
1077 {
1078   SetErrorCode(KO);
1079
1080   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1081   if ( objects.IsNull() || objects->IsEmpty() ) {
1082     SetErrorCode("NULL argument shape");
1083     return NULL;
1084   }
1085   Handle(TColStd_HSequenceOfTransient) aFaces = GEOM_Object::GetLastFunctions( theFaces );
1086   if ( aFaces.IsNull() ) {
1087     SetErrorCode("NULL argument shape for the shape construction");
1088     return NULL;
1089   }
1090
1091   //Add a new Glued object
1092   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
1093
1094   //Add a new Glue function
1095   Handle(GEOM_Function) aFunction;
1096   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST);
1097   if (aFunction.IsNull()) return NULL;
1098
1099   //Check if the function is set correctly
1100   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1101
1102   GEOMImpl_IGlue aCI (aFunction);
1103
1104   aCI.SetBase( objects );
1105   aCI.SetTolerance(theTolerance);
1106   aCI.SetKeepNonSolids(doKeepNonSolids);
1107   aCI.SetGlueAllEdges(doGlueAllEdges);
1108   aCI.SetFaces(aFaces);
1109
1110   //Compute the sub-shape value
1111   Standard_Boolean isWarning = Standard_False;
1112   try {
1113     OCC_CATCH_SIGNALS;
1114     if (!GetSolver()->ComputeFunction(aFunction)) {
1115       SetErrorCode("Shape driver failed to glue faces");
1116       return NULL;
1117     }
1118   }
1119   catch (Standard_Failure) {
1120     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1121     SetErrorCode(aFail->GetMessageString());
1122     // to provide warning
1123     if (!aFunction->GetValue().IsNull()) {
1124       isWarning = Standard_True;
1125     } else {
1126       return NULL;
1127     }
1128   }
1129
1130   //Make a Python command
1131
1132   GEOM::TPythonDump pd(aFunction);
1133   pd << aGlued << " = geompy.MakeGlueFacesByList("
1134      << theShapes << ", " << theTolerance << ", " << theFaces << ", "
1135      << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")";
1136
1137   // to provide warning
1138   if (!isWarning) SetErrorCode(OK);
1139   return aGlued;
1140 }
1141
1142 //=============================================================================
1143 /*!
1144  *  MakeGlueEdges
1145  */
1146 //=============================================================================
1147 Handle(GEOM_Object)
1148 GEOMImpl_IShapesOperations::MakeGlueEdges (std::list< Handle(GEOM_Object) >& theShapes,
1149                                            const Standard_Real               theTolerance)
1150 {
1151   SetErrorCode(KO);
1152
1153   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1154   if ( objects.IsNull() || objects->IsEmpty() ) {
1155     SetErrorCode("NULL argument shape");
1156     return NULL;
1157   }
1158
1159   //Add a new Glued object
1160   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
1161
1162   //Add a new Glue function
1163   Handle(GEOM_Function) aFunction;
1164   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES);
1165   if (aFunction.IsNull()) return NULL;
1166
1167   //Check if the function is set correctly
1168   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1169
1170   GEOMImpl_IGlue aCI (aFunction);
1171
1172   aCI.SetBase( objects );
1173   aCI.SetTolerance(theTolerance);
1174   aCI.SetKeepNonSolids(true);
1175
1176   //Compute the sub-shape value
1177   Standard_Boolean isWarning = Standard_False;
1178   try {
1179     OCC_CATCH_SIGNALS;
1180     if (!GetSolver()->ComputeFunction(aFunction)) {
1181       SetErrorCode("Shape driver failed to glue edges");
1182       return NULL;
1183     }
1184   }
1185   catch (Standard_Failure) {
1186     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1187     SetErrorCode(aFail->GetMessageString());
1188     // to provide warning
1189     if (!aFunction->GetValue().IsNull()) {
1190       isWarning = Standard_True;
1191     } else {
1192       return NULL;
1193     }
1194   }
1195
1196   //Make a Python command
1197   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueEdges("
1198     << theShapes << ", " << theTolerance << ")";
1199
1200   // to provide warning
1201   if (!isWarning) SetErrorCode(OK);
1202   return aGlued;
1203 }
1204
1205 //=============================================================================
1206 /*!
1207  *  GetGlueShapes
1208  */
1209 //=============================================================================
1210 Handle(TColStd_HSequenceOfTransient)
1211 GEOMImpl_IShapesOperations::GetGlueShapes (std::list< Handle(GEOM_Object) >& theShapes,
1212                                            const Standard_Real               theTolerance,
1213                                            const TopAbs_ShapeEnum            theType)
1214 {
1215   SetErrorCode(KO);
1216
1217   TopoDS_Shape aShape;
1218   TopTools_SequenceOfShape shapes;
1219   std::list< Handle(GEOM_Object) >::iterator s = theShapes.begin();
1220   Handle(GEOM_Object) lastCreatedGO;
1221   for ( ; s != theShapes.end(); ++s )
1222   {
1223     Handle(GEOM_Object) go = *s;
1224     if ( go.IsNull() ) return NULL;
1225     aShape = go->GetValue();
1226     if ( aShape.IsNull() ) return NULL;
1227     shapes.Append( aShape );
1228     lastCreatedGO = GEOM::GetCreatedLast( lastCreatedGO, go );
1229   }
1230   if ( shapes.Length() > 1 )
1231   {
1232     TopoDS_Compound compound;
1233     BRep_Builder builder;
1234     builder.MakeCompound( compound );
1235     for ( int i = 1; i <= shapes.Length(); ++i )
1236       builder.Add( compound, shapes( i ) );
1237
1238     aShape = compound;
1239   }
1240
1241   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1242
1243   GEOMAlgo_GlueDetector aGluer;
1244   aGluer.SetArgument(aShape);
1245   aGluer.SetTolerance(theTolerance);
1246   aGluer.Perform();
1247   Standard_Integer iErr = aGluer.ErrorStatus();
1248   if (iErr) return NULL;
1249
1250   std::vector< TopTools_IndexedMapOfShape* > anIndices( shapes.Length(), NULL );
1251   Handle(TColStd_HArray1OfInteger) anArray;
1252   Handle(GEOM_Object) anObj;
1253
1254   TopTools_ListOfShape listOnePerSet;
1255
1256   const TopTools_DataMapOfShapeListOfShape& aImages = aGluer.Images();
1257   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS (aImages);
1258   for (int index = 1; aItDMSLS.More(); aItDMSLS.Next(), ++index) {
1259     // some key shape
1260     //const TopoDS_Shape& aSkey = aItDMSLS.Key();
1261
1262     // list of shapes of the argument that can be glued
1263     const TopTools_ListOfShape& aLSD = aItDMSLS.Value();
1264
1265     //listShape.Append(aLSD.First());
1266     TopoDS_Shape aValue = aLSD.First();
1267
1268     if (aValue.ShapeType() == theType) {
1269       listOnePerSet.Append(aValue);
1270     }
1271   }
1272
1273   // for stable order of returned entities
1274   GEOMUtils::SortShapes(listOnePerSet, Standard_False);
1275
1276   TopTools_ListIteratorOfListOfShape aListIt (listOnePerSet);
1277   for (; aListIt.More(); aListIt.Next())
1278   {
1279     TopoDS_Shape aValue = aListIt.Value();
1280     // find a shape to add aValue as a sub-shape
1281     anObj.Nullify();
1282     s = theShapes.begin();
1283     for ( int i = 0; i < shapes.Length(); ++i, ++s )
1284     {
1285       Handle(GEOM_Object) object = *s;
1286       if ( !anIndices[i] ) {
1287         anIndices[i] = new TopTools_IndexedMapOfShape;
1288         TopExp::MapShapes( object->GetValue(), *anIndices[i]);
1289       }
1290       if (int index = anIndices[i]->FindIndex( aValue )) {
1291         anArray = new TColStd_HArray1OfInteger(1,1);
1292         anArray->SetValue(1, index);
1293         anObj = GetEngine()->AddSubShape( object, anArray);
1294         break;
1295       }
1296     }
1297     if (!anObj.IsNull())
1298       aSeq->Append(anObj);
1299   }
1300   for ( size_t i = 0 ; i < anIndices.size(); ++i )
1301     delete anIndices[i];
1302
1303   // Make a Python command
1304   if ( aSeq->Length() > 0)
1305   {
1306     Handle(GEOM_Function) aFunction = lastCreatedGO->GetLastFunction();
1307     GEOM::TPythonDump pd (aFunction, /*append=*/true);
1308     pd << aSeq
1309        << " = geompy." << (theType == TopAbs_FACE ? "GetGlueFaces" : "GetGlueEdges" )
1310        << "( " << theShapes << ", " << theTolerance << ")";
1311   }
1312
1313   SetErrorCode(OK);
1314
1315   return aSeq;
1316 }
1317
1318 //=============================================================================
1319 /*!
1320  *  MakeGlueEdgesByList
1321  */
1322 //=============================================================================
1323 Handle(GEOM_Object)
1324 GEOMImpl_IShapesOperations::MakeGlueEdgesByList (std::list< Handle(GEOM_Object) >& theShapes,
1325                                                  const Standard_Real               theTolerance,
1326                                                  std::list<Handle(GEOM_Object)>&   theEdges)
1327 {
1328   SetErrorCode(KO);
1329
1330   Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes );
1331   if ( objects.IsNull() || objects->IsEmpty() ) {
1332     SetErrorCode("NULL argument shape");
1333     return NULL;
1334   }
1335   Handle(TColStd_HSequenceOfTransient) anEdges = GEOM_Object::GetLastFunctions( theEdges );
1336   if ( anEdges.IsNull() ) {
1337     SetErrorCode("NULL argument shape for the shape construction");
1338     return NULL;
1339   }
1340   //Add a new Glued object
1341   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
1342
1343   //Add a new Glue function
1344   Handle(GEOM_Function) aFunction;
1345   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES_BY_LIST);
1346   if (aFunction.IsNull()) return NULL;
1347
1348   //Check if the function is set correctly
1349   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
1350
1351   GEOMImpl_IGlue aCI (aFunction);
1352
1353   aCI.SetBase( objects );
1354   aCI.SetTolerance(theTolerance);
1355   aCI.SetKeepNonSolids(true);
1356   aCI.SetFaces(anEdges);
1357
1358   //Compute the sub-shape value
1359   Standard_Boolean isWarning = Standard_False;
1360   try {
1361     OCC_CATCH_SIGNALS;
1362     if (!GetSolver()->ComputeFunction(aFunction)) {
1363       SetErrorCode("Shape driver failed to glue edges");
1364       return NULL;
1365     }
1366   }
1367   catch (Standard_Failure) {
1368     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1369     SetErrorCode(aFail->GetMessageString());
1370     // to provide warning
1371     if (!aFunction->GetValue().IsNull()) {
1372       isWarning = Standard_True;
1373     } else {
1374       return NULL;
1375     }
1376   }
1377
1378   //Make a Python command
1379
1380   GEOM::TPythonDump pd (aFunction);
1381   pd << aGlued << " = geompy.MakeGlueEdgesByList("
1382      << theShapes << ", " << theTolerance << ", " << theEdges << " )";
1383
1384   // to provide warning
1385   if (!isWarning) SetErrorCode(OK);
1386   return aGlued;
1387 }
1388
1389 //=============================================================================
1390 /*!
1391  *  GetExistingSubObjects
1392  */
1393 //=============================================================================
1394 Handle(TColStd_HSequenceOfTransient)
1395 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object)    theShape,
1396                                                   const Standard_Boolean theGroupsOnly)
1397 {
1398   // note: this method does not return fields
1399
1400   Standard_Integer types = theGroupsOnly ? Groups : Groups|SubShapes;
1401   Handle(TColStd_HSequenceOfTransient) results = GetExistingSubObjects(theShape, types);
1402
1403   if (results->Length() > 0) {
1404     //Make a Python command
1405     TCollection_AsciiString anAsciiList;
1406     for (int i = 1; i <= results->Length(); i++)
1407     {
1408       Handle(GEOM_BaseObject) obj = Handle(GEOM_BaseObject)::DownCast( results->Value(i));
1409       obj->GetEntryString();
1410       if ( i < results->Length() )
1411         anAsciiList += ",";
1412     }
1413     
1414     GEOM::TPythonDump pd (theShape->GetLastFunction(), /*append=*/true);
1415     pd << "[" << anAsciiList.ToCString();
1416     pd << "] = geompy.GetExistingSubObjects(";
1417     pd << theShape << ", " << (bool)theGroupsOnly << ")";
1418   }
1419
1420   return results;
1421 }
1422
1423 Handle(TColStd_HSequenceOfTransient)
1424 GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object)    theShape,
1425                                                   const Standard_Integer theTypes)
1426 {
1427   SetErrorCode(KO);
1428
1429   if (theShape.IsNull()) return NULL;
1430
1431   Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1432   if (aMainShape.IsNull()) return NULL;
1433
1434   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1435   SetErrorCode(NOT_FOUND_ANY);
1436
1437   if (!aMainShape->HasSubShapeReferences()) return aSeq;
1438   const TDataStd_ListOfExtendedString& aListEntries = aMainShape->GetSubShapeReferences();
1439   if (aListEntries.IsEmpty()) return aSeq;
1440
1441   SetErrorCode(KO);
1442
1443   TDataStd_ListIteratorOfListOfExtendedString anIt (aListEntries);
1444   for (; anIt.More(); anIt.Next()) {
1445     TCollection_ExtendedString anEntry = anIt.Value();
1446     Standard_Integer aStrLen = anEntry.LengthOfCString();
1447     char* anEntryStr = new char[aStrLen+1];
1448     anEntry.ToUTF8CString(anEntryStr);
1449     Handle(GEOM_BaseObject) anObj = GetEngine()->GetObject(GetDocID(), anEntryStr, false);
1450     if (!anObj.IsNull() ) {
1451       bool isGroup    = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() == GEOM_GROUP;
1452       bool isSubShape = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() != GEOM_GROUP;
1453       bool isField    = anObj->IsKind(STANDARD_TYPE(GEOM_Field));
1454       if (theTypes & Groups    && isGroup ||
1455           theTypes & SubShapes && isSubShape ||
1456           theTypes & Fields    && isField) {
1457         aSeq->Append(anObj);
1458       }
1459     }
1460     delete [] anEntryStr;
1461   }
1462
1463   if (aSeq->Length() == 0) {
1464     SetErrorCode(NOT_FOUND_ANY);
1465     return aSeq;
1466   }
1467
1468   SetErrorCode(OK);
1469
1470   return aSeq;
1471 }
1472
1473 //=============================================================================
1474 /*!
1475  *  MakeExplode
1476  */
1477 //=============================================================================
1478 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
1479                                           (Handle(GEOM_Object)    theShape,
1480                                            const Standard_Integer theShapeType,
1481                                            const Standard_Boolean isSorted,
1482                                            const ExplodeType      theExplodeType)
1483 {
1484   SetErrorCode(KO);
1485
1486   if (theShape.IsNull()) return NULL;
1487   TopoDS_Shape aShape = theShape->GetValue();
1488   if (aShape.IsNull()) return NULL;
1489
1490   Handle(GEOM_Function) aMainShape = theShape->GetLastFunction();
1491
1492   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1493   Handle(GEOM_Object) anObj;
1494   TopTools_MapOfShape mapShape;
1495   TopTools_ListOfShape listShape;
1496
1497   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1498       (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1499   {
1500     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1501     for (; It.More(); It.Next()) {
1502       TopoDS_Shape SS = It.Value();
1503       if (mapShape.Add(SS)) {
1504         if (theShapeType == TopAbs_FLAT) {
1505           AddFlatSubShapes(SS, listShape, mapShape);
1506         }
1507         else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1508           listShape.Append(SS);
1509         }
1510         // VSR: for EXPLODE_NEW_INCLUDE_MAIN and EXPLODE_OLD_INCLUDE_MAIN:
1511         // it seems it is necessary to add top-level shape if theShapeType == TopAbs_COMPOUND
1512       }
1513     }
1514   }
1515   else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1516   {
1517     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1518     for (; exp.More(); exp.Next())
1519       if (mapShape.Add(exp.Current()))
1520         listShape.Append(exp.Current());
1521   }
1522
1523   if (listShape.IsEmpty()){
1524     //SetErrorCode("The given shape has no sub-shapes of the requested type");
1525     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1526     return aSeq;
1527   }
1528
1529   if (isSorted) {
1530     bool isOldSorting = false;
1531     if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1532       isOldSorting = true;
1533     GEOMUtils::SortShapes(listShape, isOldSorting);
1534   }
1535
1536   TopTools_IndexedMapOfShape anIndices;
1537   TopExp::MapShapes(aShape, anIndices);
1538   Handle(TColStd_HArray1OfInteger) anArray;
1539
1540   TopTools_ListIteratorOfListOfShape itSub (listShape);
1541   TCollection_AsciiString anAsciiList, anEntry;
1542   for (int index = 1; itSub.More(); itSub.Next(), ++index)
1543   {
1544     TopoDS_Shape aValue = itSub.Value();
1545     anArray = new TColStd_HArray1OfInteger(1,1);
1546     anArray->SetValue(1, anIndices.FindIndex(aValue));
1547
1548     //anObj = GetEngine()->AddSubShape(theShape, anArray);
1549     {
1550       anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1551       Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1552       if (aFunction.IsNull()) return aSeq;
1553
1554       GEOM_ISubShape aSSI (aFunction);
1555       aSSI.SetMainShape(aMainShape);
1556       aSSI.SetIndices(anArray);
1557
1558       // Set function value directly, as we know it.
1559       // Usage of Solver here would lead to significant loss of time,
1560       // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1561       // on the main shape for each being calculated sub-shape separately.
1562       aFunction->SetValue(aValue);
1563
1564       // Put this subshape in the list of sub-shapes of theMainShape
1565       aMainShape->AddSubShapeReference(aFunction);
1566     }
1567     if (!anObj.IsNull()) {
1568           aSeq->Append(anObj);
1569
1570           // for python command
1571           TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1572           anAsciiList += anEntry;
1573           anAsciiList += ",";
1574         }
1575       }
1576
1577   //Make a Python command
1578   anAsciiList.Trunc(anAsciiList.Length() - 1);
1579
1580   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1581   pd << "[" << anAsciiList.ToCString() << "] = geompy.";
1582   switch (theExplodeType) {
1583   case EXPLODE_NEW_EXCLUDE_MAIN:
1584     pd << "ExtractShapes(" << theShape << ", "
1585        << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")";
1586     break;
1587   case EXPLODE_NEW_INCLUDE_MAIN:
1588     pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(")
1589        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1590     break;
1591   case EXPLODE_OLD_INCLUDE_MAIN:
1592     pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(")
1593        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1594     break;
1595   default: ;
1596   }
1597   SetErrorCode(OK);
1598
1599   return aSeq;
1600 }
1601
1602 //=============================================================================
1603 /*!
1604  *  SubShapeAllIDs
1605  */
1606 //=============================================================================
1607 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
1608                                           (Handle(GEOM_Object)    theShape,
1609                                            const Standard_Integer theShapeType,
1610                                            const Standard_Boolean isSorted,
1611                                            const ExplodeType      theExplodeType)
1612 {
1613   SetErrorCode(KO);
1614
1615   if (theShape.IsNull()) return NULL;
1616   TopoDS_Shape aShape = theShape->GetValue();
1617   if (aShape.IsNull()) return NULL;
1618
1619   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1620   TopTools_MapOfShape mapShape;
1621   TopTools_ListOfShape listShape;
1622
1623   if (aShape.ShapeType() == TopAbs_COMPOUND &&
1624       (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND))
1625   {
1626     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
1627     for (; It.More(); It.Next()) {
1628       TopoDS_Shape SS = It.Value();
1629       if (mapShape.Add(SS)) {
1630         if (theShapeType == TopAbs_FLAT) {
1631           AddFlatSubShapes(SS, listShape, mapShape);
1632         }
1633         else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) {
1634           listShape.Append(SS);
1635         }
1636       }
1637     }
1638   }
1639   else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079
1640   {
1641     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
1642     for (; exp.More(); exp.Next())
1643       if (mapShape.Add(exp.Current()))
1644         listShape.Append(exp.Current());
1645   }
1646
1647   if (listShape.IsEmpty()) {
1648     //SetErrorCode("The given shape has no sub-shapes of the requested type");
1649     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
1650     return aSeq;
1651   }
1652
1653   if (isSorted) {
1654     bool isOldSorting = false;
1655     if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN)
1656       isOldSorting = true;
1657     GEOMUtils::SortShapes(listShape, isOldSorting);
1658   }
1659
1660   TopTools_IndexedMapOfShape anIndices;
1661   TopExp::MapShapes(aShape, anIndices);
1662   Handle(TColStd_HArray1OfInteger) anArray;
1663
1664   TopTools_ListIteratorOfListOfShape itSub (listShape);
1665   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1666     TopoDS_Shape aValue = itSub.Value();
1667     aSeq->Append(anIndices.FindIndex(aValue));
1668   }
1669
1670   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1671
1672   //Make a Python command
1673   GEOM::TPythonDump pd (aFunction, /*append=*/true);
1674   pd << "listSubShapeIDs = geompy.SubShapeAll";
1675   switch (theExplodeType) {
1676   case EXPLODE_NEW_EXCLUDE_MAIN:
1677     break;
1678   case EXPLODE_NEW_INCLUDE_MAIN:
1679     pd << (isSorted ? "SortedCentresIDs(" : "IDs(")
1680        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1681     break;
1682   case EXPLODE_OLD_INCLUDE_MAIN:
1683     pd << (isSorted ? "SortedIDs(" : "IDs(")
1684        << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1685     break;
1686   default: ;
1687   }
1688
1689   SetErrorCode(OK);
1690   return aSeq;
1691 }
1692
1693 //=============================================================================
1694 /*!
1695  *  GetSubShape
1696  */
1697 //=============================================================================
1698 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
1699                                           (Handle(GEOM_Object)    theMainShape,
1700                                            const Standard_Integer theID)
1701 {
1702   SetErrorCode(KO);
1703
1704   if (theMainShape.IsNull()) return NULL;
1705
1706   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1707   anArray->SetValue(1, theID);
1708   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
1709   if (anObj.IsNull()) {
1710     SetErrorCode("Can not get a sub-shape with the given ID");
1711     return NULL;
1712   }
1713
1714   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1715
1716   //Make a Python command
1717   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
1718                                << theMainShape << ", [" << theID << "])";
1719
1720   SetErrorCode(OK);
1721   return anObj;
1722 }
1723
1724 //=============================================================================
1725 /*!
1726  *  MakeSubShapes
1727  */
1728 //=============================================================================
1729 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes
1730                                 (Handle(GEOM_Object)              theMainShape,
1731                                  Handle(TColStd_HArray1OfInteger) theIndices)
1732 {
1733   SetErrorCode(KO);
1734
1735   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1736
1737   if (!theIndices->Length()) {
1738     SetErrorCode(NOT_FOUND_ANY);
1739     return aSeq;
1740   }
1741
1742   if (theMainShape.IsNull()) return NULL;
1743   TopoDS_Shape aShape = theMainShape->GetValue();
1744   if (aShape.IsNull()) return NULL;
1745
1746   Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
1747
1748   TopTools_IndexedMapOfShape anIndices;
1749   TopExp::MapShapes(aShape, anIndices);
1750
1751   Handle(TColStd_HArray1OfInteger) anArray;
1752   Handle(GEOM_Object) anObj;
1753
1754   TCollection_AsciiString anAsciiList, anEntry;
1755   Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper();
1756   for (i = low; i <= up; i++) {
1757     int id = theIndices->Value(i);
1758     if (1 <= id && id <= anIndices.Extent()) {
1759       TopoDS_Shape aValue = anIndices.FindKey(id);
1760       anArray = new TColStd_HArray1OfInteger(1,1);
1761       anArray->SetValue(1, id);
1762
1763       anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
1764       if (!anObj.IsNull()) {
1765         Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1);
1766         if (aFunction.IsNull()) return aSeq;
1767
1768         GEOM_ISubShape aSSI (aFunction);
1769         aSSI.SetMainShape(aMainShape);
1770         aSSI.SetIndices(anArray);
1771
1772         // Set function value directly, as we know it.
1773         // Usage of Solver here would lead to significant loss of time,
1774         // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape
1775         // on the main shape for each being calculated sub-shape separately.
1776         aFunction->SetValue(aValue);
1777
1778         // Put this sub-shape in the list of sub-shapes of theMainShape
1779         aMainShape->AddSubShapeReference(aFunction);
1780
1781         aSeq->Append(anObj);
1782
1783         // for python command
1784         TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1785         anAsciiList += anEntry;
1786         anAsciiList += ",";
1787       }
1788     }
1789   }
1790
1791   //Make a Python command
1792   anAsciiList.Trunc(anAsciiList.Length() - 1);
1793
1794   GEOM::TPythonDump pd (aMainShape, /*append=*/true);
1795   pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes("
1796      << theMainShape << ", [" ;
1797   for (i = low; i <= up - 1; i++) {
1798     pd << theIndices->Value(i) << ", ";
1799   }
1800   pd << theIndices->Value(up) << "])";
1801
1802   SetErrorCode(OK);
1803
1804   return aSeq;
1805 }
1806
1807 //=============================================================================
1808 /*!
1809  *  GetSubShapeIndex
1810  */
1811 //=============================================================================
1812 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
1813                                                                Handle(GEOM_Object) theSubShape)
1814 {
1815   SetErrorCode(KO);
1816
1817   TopoDS_Shape aMainShape = theMainShape->GetValue();
1818   TopoDS_Shape aSubShape = theSubShape->GetValue();
1819
1820   if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
1821
1822   TopTools_IndexedMapOfShape anIndices;
1823   TopExp::MapShapes(aMainShape, anIndices);
1824 //   if (anIndices.Contains(aSubShape)) {
1825 //     SetErrorCode(OK);
1826 //     return anIndices.FindIndex(aSubShape);
1827 //   }
1828   int id = anIndices.FindIndex(aSubShape);
1829   if (id > 0)
1830   {
1831     SetErrorCode(OK);
1832     return id;
1833   }
1834   return -1;
1835 }
1836
1837
1838
1839 //=============================================================================
1840 /*!
1841  *  GetSubShapeIndices
1842  */
1843 //=============================================================================
1844 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSubShapesIndices (Handle(GEOM_Object) theMainShape,
1845                                                                                     std::list<Handle(GEOM_Object)> theSubShapes)
1846 {
1847   MESSAGE("GEOMImpl_IShapesOperations::GetSubShapesIndices")
1848   SetErrorCode(KO);
1849   
1850   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1851   
1852   TopoDS_Shape aMainShape = theMainShape->GetValue();
1853   if (aMainShape.IsNull())
1854   {
1855     MESSAGE("NULL main shape")
1856     return NULL;
1857   }
1858   
1859   TopTools_IndexedMapOfShape anIndices;
1860   TopExp::MapShapes(aMainShape, anIndices);
1861   
1862   std::list<Handle(GEOM_Object)>::iterator it;
1863   for (it=theSubShapes.begin(); it != theSubShapes.end(); ++it)
1864   {
1865     TopoDS_Shape aSubShape = (*it)->GetValue(); 
1866     if (aSubShape.IsNull())
1867     {
1868       MESSAGE("NULL subshape")
1869       return NULL;
1870     }
1871     int id = anIndices.FindIndex(aSubShape);
1872     aSeq->Append(id);
1873   }  
1874   
1875   SetErrorCode(OK);
1876   return aSeq;
1877 }
1878
1879
1880 //=============================================================================
1881 /*!
1882  *  GetTopologyIndex
1883  */
1884 //=============================================================================
1885 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
1886                                                                Handle(GEOM_Object) theSubShape)
1887 {
1888   SetErrorCode(OK);
1889
1890   TopoDS_Shape aMainShape = theMainShape->GetValue();
1891   TopoDS_Shape aSubShape = theSubShape->GetValue();
1892
1893   if (aMainShape.IsNull() || aSubShape.IsNull()) {
1894     SetErrorCode("Null argument shape given");
1895     return -1;
1896   }
1897
1898   int index = 1;
1899   if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
1900     TopoDS_Iterator it;
1901     TopTools_ListOfShape CL;
1902     CL.Append(aMainShape);
1903     TopTools_ListIteratorOfListOfShape itC;
1904     for (itC.Initialize(CL); itC.More(); itC.Next()) {
1905       for (it.Initialize(itC.Value()); it.More(); it.Next()) {
1906         if (it.Value().ShapeType() == TopAbs_COMPOUND) {
1907           if (it.Value().IsSame(aSubShape))
1908             return index;
1909           else
1910             index++;
1911           CL.Append(it.Value());
1912         }
1913       }
1914     }
1915   } else {
1916     TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
1917     TopTools_MapOfShape M;
1918     for (; anExp.More(); anExp.Next()) {
1919       if (M.Add(anExp.Current())) {
1920         if (anExp.Current().IsSame(aSubShape))
1921           return index;
1922         index++;
1923       }
1924     }
1925   }
1926
1927   SetErrorCode("The sub-shape does not belong to the main shape");
1928   return -1;
1929 }
1930
1931 //=============================================================================
1932 /*!
1933  *  GetShapeTypeString
1934  */
1935 //=============================================================================
1936 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
1937 {
1938   SetErrorCode(KO);
1939
1940   TCollection_AsciiString aTypeName ("Null Shape");
1941
1942   TopoDS_Shape aShape = theShape->GetValue();
1943   if (aShape.IsNull())
1944     return aTypeName;
1945
1946   switch (aShape.ShapeType() )
1947   {
1948   case TopAbs_COMPOUND:
1949     aTypeName = "Compound";
1950     break;
1951   case  TopAbs_COMPSOLID:
1952     aTypeName = "Compound Solid";
1953     break;
1954   case TopAbs_SOLID:
1955     aTypeName = "Solid";
1956     break;
1957   case TopAbs_SHELL:
1958     aTypeName = "Shell";
1959     break;
1960   case TopAbs_FACE:
1961     {
1962       BRepAdaptor_Surface surf (TopoDS::Face(aShape));
1963       if (surf.GetType() == GeomAbs_Plane)
1964         aTypeName = "Plane";
1965       else if (surf.GetType() == GeomAbs_Cylinder)
1966         aTypeName = "Cylindrical Face";
1967       else if (surf.GetType() == GeomAbs_Sphere)
1968         aTypeName = "Spherical Face";
1969       else if (surf.GetType() == GeomAbs_Torus)
1970         aTypeName = "Toroidal Face";
1971       else if (surf.GetType() == GeomAbs_Cone)
1972         aTypeName = "Conical Face";
1973       else
1974         aTypeName = "GEOM::FACE";
1975     }
1976     break;
1977   case TopAbs_WIRE:
1978     aTypeName = "Wire";
1979     break;
1980   case TopAbs_EDGE:
1981     {
1982       BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
1983       if (curv.GetType() == GeomAbs_Line) {
1984         if ((Abs(curv.FirstParameter()) >= 1E6) ||
1985             (Abs(curv.LastParameter()) >= 1E6))
1986           aTypeName = "Line";
1987         else
1988           aTypeName = "Edge";
1989       } else if (curv.GetType() == GeomAbs_Circle) {
1990         if (curv.IsClosed())
1991           aTypeName = "Circle";
1992         else
1993           aTypeName = "Arc";
1994       } else {
1995         aTypeName = "Edge";
1996       }
1997     }
1998     break;
1999   case TopAbs_VERTEX:
2000     aTypeName = "Vertex";
2001     break;
2002   case TopAbs_SHAPE:
2003     aTypeName = "Shape";
2004     break;
2005   default:
2006     aTypeName = "Shape of unknown type";
2007   }
2008
2009   return aTypeName;
2010 }
2011
2012 //=============================================================================
2013 /*!
2014  *  IsSubShapeBelongsTo
2015  */
2016 //=============================================================================
2017 Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject,
2018                                                                   const Standard_Integer theSubObjectIndex,
2019                                                                   Handle(GEOM_Object) theObject,
2020                                                                   const Standard_Integer theObjectIndex)
2021 {
2022   if ( theObject.IsNull() || theSubObject.IsNull() )
2023     return false;
2024
2025   TopoDS_Shape shape    = theObject->GetValue();
2026   TopoDS_Shape subShape = theSubObject->GetValue();
2027
2028   if ( shape.IsNull() || subShape.IsNull() )
2029     return false;
2030
2031   TopTools_IndexedMapOfShape anIndices;
2032   if ( theObjectIndex > 0 ) {
2033     TopExp::MapShapes( shape, anIndices );
2034     shape = anIndices.FindKey(theObjectIndex);
2035   }
2036   if ( theSubObjectIndex > 0 ) {
2037     TopExp::MapShapes( subShape, anIndices );
2038     subShape = anIndices.FindKey(theSubObjectIndex);
2039   }
2040
2041   TopExp::MapShapes( shape, anIndices );
2042   return anIndices.Contains( subShape );
2043 }
2044
2045 //=============================================================================
2046 /*!
2047  *  NumberOfSubShapes
2048  */
2049 //=============================================================================
2050 Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes
2051                                           (Handle(GEOM_Object)    theShape,
2052                                            const Standard_Integer theShapeType)
2053 {
2054   SetErrorCode(KO);
2055   Standard_Integer nbShapes = 0;
2056
2057   if (theShape.IsNull()) return -1;
2058   TopoDS_Shape aShape = theShape->GetValue();
2059   if (aShape.IsNull()) return -1;
2060
2061   /*
2062   TopTools_MapOfShape mapShape;
2063
2064   if (aShape.ShapeType() == TopAbs_COMPOUND &&
2065       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2066        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
2067        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
2068     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
2069     for (; It.More(); It.Next()) {
2070       if (mapShape.Add(It.Value())) {
2071         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
2072             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
2073           nbShapes++;
2074         }
2075       }
2076     }
2077   } else {
2078     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
2079     for (; exp.More(); exp.Next())
2080       if (mapShape.Add(exp.Current()))
2081         nbShapes++;
2082   }
2083   */
2084
2085   try {
2086     if (theShapeType == TopAbs_FLAT) {
2087       TopTools_MapOfShape aMapOfShape;
2088       TopTools_ListOfShape aListOfShape;
2089       AddFlatSubShapes(aShape, aListOfShape, aMapOfShape);
2090       nbShapes = aListOfShape.Extent();
2091     }
2092     else {
2093       OCC_CATCH_SIGNALS;
2094       int iType, nbTypes [TopAbs_SHAPE];
2095       for (iType = 0; iType < TopAbs_SHAPE; ++iType)
2096         nbTypes[iType] = 0;
2097       nbTypes[aShape.ShapeType()]++;
2098       
2099       TopTools_MapOfShape aMapOfShape;
2100       aMapOfShape.Add(aShape);
2101       TopTools_ListOfShape aListOfShape;
2102       aListOfShape.Append(aShape);
2103       
2104       TopTools_ListIteratorOfListOfShape itL (aListOfShape);
2105       for (; itL.More(); itL.Next()) {
2106         TopoDS_Iterator it (itL.Value());
2107         for (; it.More(); it.Next()) {
2108           TopoDS_Shape s = it.Value();
2109           if (aMapOfShape.Add(s)) {
2110             aListOfShape.Append(s);
2111             nbTypes[s.ShapeType()]++;
2112           }
2113         }
2114       }
2115       
2116       if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE)
2117         nbShapes = aMapOfShape.Extent();
2118       else
2119         nbShapes = nbTypes[theShapeType];
2120     }
2121   }
2122   catch (Standard_Failure) {
2123     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2124     SetErrorCode(aFail->GetMessageString());
2125     return -1;
2126   }
2127
2128   SetErrorCode(OK);
2129   return nbShapes;
2130 }
2131
2132 //=============================================================================
2133 /*!
2134  *  ReverseShape
2135  */
2136 //=============================================================================
2137 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
2138 {
2139   SetErrorCode(KO);
2140
2141   if (theShape.IsNull()) return NULL;
2142
2143   /*
2144   //Add a new reversed object
2145   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
2146
2147   //Add a new Revese function
2148   Handle(GEOM_Function) aFunction;
2149   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
2150   if (aFunction.IsNull()) return NULL;
2151
2152   //Check if the function is set correctly
2153   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
2154
2155   GEOMImpl_IShapes aSI (aFunction);
2156
2157   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
2158   if (aRefShape.IsNull()) return NULL;
2159
2160   aSI.SetBase(aRefShape);
2161
2162   //Compute the sub-shape value
2163   try {
2164     OCC_CATCH_SIGNALS;
2165     if (!GetSolver()->ComputeFunction(aFunction)) {
2166       SetErrorCode("Shape driver failed to reverse shape");
2167       return NULL;
2168     }
2169   }
2170   catch (Standard_Failure) {
2171     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2172     SetErrorCode(aFail->GetMessageString());
2173     return NULL;
2174   }
2175
2176   //Make a Python command
2177   GEOM::TPythonDump(aFunction) << aReversed
2178     << " = geompy.ChangeOrientation(" << theShape << ")";
2179
2180   SetErrorCode(OK);
2181   */
2182
2183   Handle(GEOM_Object) aReversed;
2184
2185   GEOM_Engine* anEngine = GetEngine();
2186   //GEOMImpl_Gen* aGen = dynamic_cast<GEOMImpl_Gen*>(anEngine);
2187   GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine;
2188
2189   if (aGen) {
2190     GEOMImpl_IHealingOperations* anIHealingOperations =
2191       aGen->GetIHealingOperations(GetDocID());
2192     aReversed = anIHealingOperations->ChangeOrientationCopy(theShape);
2193     SetErrorCode(anIHealingOperations->GetErrorCode());
2194   }
2195
2196   return aReversed;
2197 }
2198
2199 //=============================================================================
2200 /*!
2201  *  GetFreeFacesIDs
2202  */
2203 //=============================================================================
2204 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
2205                                                  (Handle(GEOM_Object) theShape)
2206 {
2207   SetErrorCode(KO);
2208
2209   if (theShape.IsNull()) return NULL;
2210   TopoDS_Shape aShape = theShape->GetValue();
2211   if (aShape.IsNull()) return NULL;
2212
2213   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
2214
2215   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
2216   GEOMImpl_Block6Explorer::MapShapesAndAncestors
2217     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
2218
2219   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
2220
2221   if (nbFaces == 0) {
2222     SetErrorCode("The given shape has no faces");
2223     return aSeq;
2224   }
2225
2226   TopTools_IndexedMapOfShape anIndices;
2227   TopExp::MapShapes(aShape, anIndices);
2228
2229   Standard_Integer id;
2230   for (; ind <= nbFaces; ind++) {
2231     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
2232       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
2233       aSeq->Append(id);
2234     }
2235   }
2236
2237   //The explode doesn't change object so no new function is required.
2238   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
2239
2240   //Make a Python command
2241   GEOM::TPythonDump(aFunction, /*append=*/true)
2242     << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
2243
2244   SetErrorCode(OK);
2245   return aSeq;
2246 }
2247
2248 //=======================================================================
2249 //function : GetSharedShapes
2250 //purpose  :
2251 //=======================================================================
2252 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2253                                                 (Handle(GEOM_Object)    theShape1,
2254                                                  Handle(GEOM_Object)    theShape2,
2255                                                  const Standard_Integer theShapeType)
2256 {
2257   SetErrorCode(KO);
2258
2259   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
2260
2261   TopoDS_Shape aShape1 = theShape1->GetValue();
2262   TopoDS_Shape aShape2 = theShape2->GetValue();
2263
2264   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
2265
2266   TopTools_IndexedMapOfShape anIndices;
2267   TopExp::MapShapes(aShape1, anIndices);
2268   Handle(TColStd_HArray1OfInteger) anArray;
2269
2270   TopTools_IndexedMapOfShape mapShape1;
2271   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
2272
2273   Handle(GEOM_Object) anObj;
2274   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2275   TCollection_AsciiString anAsciiList, anEntry;
2276
2277   TopTools_MapOfShape mapShape2;
2278   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2279   for (; exp.More(); exp.Next()) {
2280     TopoDS_Shape aSS = exp.Current();
2281     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
2282       anArray = new TColStd_HArray1OfInteger(1,1);
2283       anArray->SetValue(1, anIndices.FindIndex(aSS));
2284       anObj = GetEngine()->AddSubShape(theShape1, anArray);
2285       aSeq->Append(anObj);
2286
2287       // for python command
2288       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2289       anAsciiList += anEntry;
2290       anAsciiList += ",";
2291     }
2292   }
2293
2294   if (aSeq->IsEmpty()) {
2295     SetErrorCode(NOT_FOUND_ANY);
2296     return aSeq;
2297   }
2298
2299   //Make a Python command
2300   anAsciiList.Trunc(anAsciiList.Length() - 1);
2301
2302   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2303
2304   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
2305     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
2306       << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
2307
2308   SetErrorCode(OK);
2309   return aSeq;
2310 }
2311
2312 //=======================================================================
2313 //function : GetSharedShapes
2314 //purpose  :
2315 //
2316 // NOTE on the implementation
2317 // 
2318 // 1) Resulting sub-shapes are published as a children of the 1st input shape
2319 //    from theShapes list. Due to this reason only direct sub-shapes of the 1st
2320 //    shape can be contained in the result of the operation (i.e. shares between
2321 //    2nd/3rd, etc couples cannot be retrieved.
2322 // 2) An exception from above case is when a single compound is specified as an
2323 //    input. In this case we search shares between its top-level content, so we
2324 //    are able to search shares between all possible couples of shapes.
2325 // 3) Parameter theMultiShare controls what types of shares to search:
2326 //    - True: get sub-shapes that are shared between ALL input shapes;
2327 //    - False: get shares between couples of input sub-shapes (see points 1 and 2).
2328 //
2329 // Thus, we have the following cases:
2330 // [1] theShapes = N shapes (N>1), theMultiShare = True
2331 //     Result: sub-shapes that are shared by all theShapes
2332 // [2] theShapes = N shapes (N>1), theMultiShare = False
2333 //     Result: sub-shapes of 1st shape from theShapes that are shared with any shape
2334 //     from theShapes
2335 // [3] theShapes = 1 shape, theMultiShare = True
2336 //     Result: sub-shapes that are shared by all top-level sub-objects of theShapes[0]
2337 // [4] theShapes = 1 shape, theMultiShare = False
2338 //     Result: sub-shapes of all possible couples of all top-level sub-objects of
2339 //     theShapes[0].
2340 //=======================================================================
2341 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
2342                                      (std::list<Handle(GEOM_Object)> & theShapes,
2343                                       const Standard_Integer           theShapeType,
2344                                       const bool                       theMultiShare)
2345 {
2346   SetErrorCode(KO);
2347
2348   int aLen = theShapes.size();
2349   if (aLen < 1) return NULL;
2350
2351   std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
2352
2353   // main object is always first in the input list
2354   // it is the object from which sub-shapes indices are taken
2355   // and where results are published
2356   Handle(GEOM_Object) aMainObj = *it;
2357   Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
2358
2359   // collect all shapes from the input list (including first one) for processing
2360   TopTools_SequenceOfShape shapeSeq;
2361   for (; it != theShapes.end(); it++) {
2362     Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
2363     if (aRefShape.IsNull()) {
2364       SetErrorCode("NULL shape for GetSharedShapes");
2365       return NULL;
2366     }
2367     TopoDS_Shape aShape = aRefShape->GetValue();
2368     if (aShape.IsNull()) {
2369       SetErrorCode("NULL shape for GetSharedShapes");
2370       return NULL;
2371     }
2372     shapeSeq.Append( aShape );
2373   }
2374
2375   // if only single shape is specified as input
2376   // collect all ites top-level sub-shapes for processing
2377   if ( shapeSeq.Length() == 1 )
2378   {
2379     TopoDS_Shape aShape = shapeSeq.First();
2380     shapeSeq.Clear();
2381     for ( TopoDS_Iterator it( aShape ); it.More(); it.Next() )
2382       shapeSeq.Append( it.Value() );
2383   }
2384
2385   // map all sub-shapes in a main shape to their indices
2386   TopTools_IndexedMapOfShape anIndices;
2387   TopExp::MapShapes(aMainShape->GetValue(), anIndices);
2388   TopTools_MapOfShape mapShape;
2389
2390   // find shared shapes
2391
2392   // here we will collect all shares
2393   TopTools_ListOfShape aShared;
2394
2395   // number of iterations
2396   int nbIters  =  theMultiShare || theShapes.size() > 1 ? 1 : shapeSeq.Length()-1;
2397   // numShares factor to search (i.e. by what nb of shapes each found sub-shape should be shared)
2398   int nbShares =  theMultiShare ? shapeSeq.Length()-1 : 1;
2399     
2400   for ( int iter = 1; iter <= nbIters; iter++) {
2401     for ( int ind = iter+1; ind <= shapeSeq.Length(); ind++) {
2402       if ( ind-1+nbShares > shapeSeq.Length() ) break;
2403       TopoDS_Compound aCurrSelection;
2404       TopoDS_Shape aShape1 = shapeSeq.Value( iter );
2405       TopTools_IndexedMapOfShape mapSelected;
2406       TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
2407       for ( int s = 0; s < nbShares; s++ ) {
2408         BRep_Builder B;
2409         TopoDS_Compound aCompound;
2410         B.MakeCompound(aCompound);
2411         const TopoDS_Shape& aShape2 = shapeSeq.Value( ind+s );
2412         TopTools_MapOfShape mapShape2;
2413         TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
2414         for (; exp.More(); exp.Next()) {
2415           const TopoDS_Shape& aSS = exp.Current();
2416           if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
2417             B.Add(aCompound, aSS);
2418           }
2419         }
2420         mapSelected.Clear();
2421         aCurrSelection = aCompound;
2422         TopExp::MapShapes(aCurrSelection, TopAbs_ShapeEnum(theShapeType), mapSelected);
2423       }
2424       TopoDS_Iterator itSel(aCurrSelection, Standard_True, Standard_True);
2425       for (; itSel.More(); itSel.Next()) {
2426         const TopoDS_Shape& aSS = itSel.Value();
2427         if (mapShape.Add(aSS) )
2428           aShared.Append(aSS);
2429       }
2430     }
2431   }
2432
2433   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2434
2435   if (aShared.IsEmpty()){
2436     SetErrorCode(NOT_FOUND_ANY);
2437     return aSeq;
2438   }
2439
2440   // create GEOM_Object for each found shared shape (collected in aShared)
2441   TCollection_AsciiString anAsciiList;
2442   Handle(GEOM_Object) anObj;
2443   TopTools_ListIteratorOfListOfShape itSub (aShared);
2444   for (; itSub.More(); itSub.Next()) {
2445     TopoDS_Shape aValue = itSub.Value();
2446     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2447     anArray->SetValue(1, anIndices.FindIndex(aValue));
2448     anObj = GetEngine()->AddSubShape(aMainObj, anArray);
2449     aSeq->Append(anObj);
2450
2451     // for python command
2452     TCollection_AsciiString anEntry;
2453     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
2454     anAsciiList += anEntry;
2455     anAsciiList += ",";
2456   }
2457
2458   // make a Python command
2459   anAsciiList.Trunc(anAsciiList.Length() - 1);
2460
2461   GEOM::TPythonDump pd (anObj->GetLastFunction());
2462   pd << "[" << anAsciiList.ToCString()
2463      << "] = geompy.GetSharedShapesMulti(";
2464
2465   if ( aLen > 1 )
2466     pd << "[";
2467
2468   it = theShapes.begin();
2469   pd << (*it++);
2470   while (it != theShapes.end()) {
2471     pd << ", " << (*it++);
2472   }
2473   if ( aLen > 1 )
2474     pd << "]";
2475
2476   pd << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theMultiShare << ")";
2477
2478   SetErrorCode(OK);
2479   return aSeq;
2480 }
2481
2482 //=============================================================================
2483 /*!
2484  *
2485  */
2486 //=============================================================================
2487 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
2488                                       const GEOMAlgo_State theState)
2489 {
2490   switch (theState) {
2491   case GEOMAlgo_ST_IN:
2492     theDump << "GEOM.ST_IN";
2493     break;
2494   case GEOMAlgo_ST_OUT:
2495     theDump << "GEOM.ST_OUT";
2496     break;
2497   case GEOMAlgo_ST_ON:
2498     theDump << "GEOM.ST_ON";
2499     break;
2500   case GEOMAlgo_ST_ONIN:
2501     theDump << "GEOM.ST_ONIN";
2502     break;
2503   case GEOMAlgo_ST_ONOUT:
2504     theDump << "GEOM.ST_ONOUT";
2505     break;
2506   default:
2507     theDump << "GEOM.ST_UNKNOWN";
2508     break;
2509   }
2510   return theDump;
2511 }
2512
2513 //=======================================================================
2514 //function : checkTypeShapesOn
2515 /*!
2516  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
2517  * \param theShapeType - the shape type to check
2518  * \retval bool  - result of the check
2519  */
2520 //=======================================================================
2521 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
2522 {
2523   if (theShapeType != TopAbs_VERTEX &&
2524       theShapeType != TopAbs_EDGE &&
2525       theShapeType != TopAbs_FACE &&
2526       theShapeType != TopAbs_SOLID) {
2527     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
2528     return false;
2529   }
2530   return true;
2531 }
2532
2533 //=======================================================================
2534 //function : makePlane
2535   /*!
2536    * \brief Creates Geom_Plane
2537     * \param theAx1 - shape object defining plane parameters
2538     * \retval Handle(Geom_Surface) - resulting surface
2539    */
2540 //=======================================================================
2541 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
2542 {
2543   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
2544   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
2545   TopoDS_Vertex V1, V2;
2546   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2547   if (V1.IsNull() || V2.IsNull()) {
2548     SetErrorCode("Bad edge given for the plane normal vector");
2549     return NULL;
2550   }
2551   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2552   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2553   if (aVec.Magnitude() < Precision::Confusion()) {
2554     SetErrorCode("Vector with null magnitude given");
2555     return NULL;
2556   }
2557   return new Geom_Plane(aLoc, aVec);
2558 }
2559
2560 //=======================================================================
2561 //function : makeCylinder
2562   /*!
2563    * \brief Creates Geom_CylindricalSurface
2564     * \param theAx1 - edge defining cylinder axis
2565     * \param theRadius - cylinder radius
2566     * \retval Handle(Geom_Surface) - resulting surface
2567    */
2568 //=======================================================================
2569 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
2570                                                               const Standard_Real theRadius)
2571 {
2572   //Axis of the cylinder
2573   if (anAxis.ShapeType() != TopAbs_EDGE) {
2574     SetErrorCode("Not an edge given for the axis");
2575     return NULL;
2576   }
2577   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
2578   TopoDS_Vertex V1, V2;
2579   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2580   if (V1.IsNull() || V2.IsNull()) {
2581     SetErrorCode("Bad edge given for the axis");
2582     return NULL;
2583   }
2584   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
2585   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
2586   if (aVec.Magnitude() < Precision::Confusion()) {
2587     SetErrorCode("Vector with null magnitude given");
2588     return NULL;
2589   }
2590
2591   gp_Ax3 anAx3 (aLoc, aVec);
2592   return new Geom_CylindricalSurface(anAx3, theRadius);
2593 }
2594
2595 //=======================================================================
2596 //function : getShapesOnBoxIDs
2597   /*!
2598    * \brief Find IDs of sub-shapes complying with given status about surface
2599     * \param theBox - the box to check state of sub-shapes against
2600     * \param theShape - the shape to explore
2601     * \param theShapeType - type of sub-shape of theShape
2602     * \param theState - required state
2603     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2604    */
2605 //=======================================================================
2606 Handle(TColStd_HSequenceOfInteger)
2607   GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2608                                                 const Handle(GEOM_Object)& theShape,
2609                                                 const Standard_Integer theShapeType,
2610                                                 GEOMAlgo_State theState)
2611 {
2612   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2613
2614   TopoDS_Shape aBox = theBox->GetValue();
2615   TopoDS_Shape aShape = theShape->GetValue();
2616
2617   // Check presence of triangulation, build if need
2618   if (!GEOMUtils::CheckTriangulation(aShape)) {
2619     SetErrorCode("Cannot build triangulation on the shape");
2620     return aSeqOfIDs;
2621   }
2622
2623   // Call algo
2624   GEOMAlgo_FinderShapeOn2 aFinder;
2625   Standard_Real aTol = 0.0001; // default value
2626
2627   Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
2628   aClsfBox->SetBox(aBox);
2629
2630   aFinder.SetShape(aShape);
2631   aFinder.SetTolerance(aTol);
2632   aFinder.SetClsf(aClsfBox);
2633   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2634   aFinder.SetState(theState);
2635   aFinder.Perform();
2636
2637   // Interprete results
2638   Standard_Integer iErr = aFinder.ErrorStatus();
2639   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2640   if (iErr) {
2641     MESSAGE(" iErr : " << iErr);
2642     TCollection_AsciiString aMsg (" iErr : ");
2643     aMsg += TCollection_AsciiString(iErr);
2644     SetErrorCode(aMsg);
2645     return aSeqOfIDs;
2646   }
2647   Standard_Integer iWrn = aFinder.WarningStatus();
2648   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2649   if (iWrn) {
2650     MESSAGE(" *** iWrn : " << iWrn);
2651   }
2652
2653   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2654
2655   if (listSS.Extent() < 1) {
2656     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2657     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2658     return aSeqOfIDs;
2659   }
2660
2661   // Fill sequence of object IDs
2662   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2663
2664   TopTools_IndexedMapOfShape anIndices;
2665   TopExp::MapShapes(aShape, anIndices);
2666
2667   TopTools_ListIteratorOfListOfShape itSub (listSS);
2668   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2669     int id = anIndices.FindIndex(itSub.Value());
2670     aSeqOfIDs->Append(id);
2671   }
2672
2673   return aSeqOfIDs;
2674 }
2675
2676 //=======================================================================
2677 //function : GetShapesOnBoxIDs
2678 /*!
2679    * \brief Find sub-shapes complying with given status about surface
2680     * \param theBox - the box to check state of sub-shapes against
2681     * \param theShape - the shape to explore
2682     * \param theShapeType - type of sub-shape of theShape
2683     * \param theState - required state
2684     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2685  */
2686 //=======================================================================
2687 Handle(TColStd_HSequenceOfInteger)
2688     GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
2689                                                   const Handle(GEOM_Object)& theShape,
2690                                                   const Standard_Integer theShapeType,
2691                                                   GEOMAlgo_State theState)
2692 {
2693   // Find sub-shapes ids
2694   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2695     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2696   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2697     return NULL;
2698
2699   // The GetShapesOnBox() doesn't change object so no new function is required.
2700   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
2701
2702   // Make a Python command
2703   GEOM::TPythonDump(aFunction, /*append=*/true)
2704     << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
2705     << theBox << ", "
2706     << theShape << ", "
2707     << TopAbs_ShapeEnum(theShapeType) << ", "
2708     << theState << ")";
2709
2710   SetErrorCode(OK);
2711   return aSeqOfIDs;
2712 }
2713
2714 //=======================================================================
2715 //function : GetShapesOnBox
2716 /*!
2717    * \brief Find sub-shapes complying with given status about surface
2718     * \param theBox - the box to check state of sub-shapes against
2719     * \param theShape - the shape to explore
2720     * \param theShapeType - type of sub-shape of theShape
2721     * \param theState - required state
2722     * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2723  */
2724 //=======================================================================
2725 Handle(TColStd_HSequenceOfTransient)
2726     GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
2727                                                const Handle(GEOM_Object)&  theShape,
2728                                                const Standard_Integer theShapeType,
2729                                                GEOMAlgo_State theState)
2730 {
2731   // Find sub-shapes ids
2732   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2733     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
2734   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2735     return NULL;
2736
2737   // Find objects by indices
2738   TCollection_AsciiString anAsciiList;
2739   Handle(TColStd_HSequenceOfTransient) aSeq;
2740   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2741   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2742     return NULL;
2743
2744   // Make a Python command
2745
2746   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2747   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2748
2749   GEOM::TPythonDump(aFunction)
2750     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
2751     << theBox << ", "
2752     << theShape << ", "
2753     << TopAbs_ShapeEnum(theShapeType) << ", "
2754     << theState << ")";
2755
2756   SetErrorCode(OK);
2757   return aSeq;
2758 }
2759
2760 //=======================================================================
2761 //function : getShapesOnShapeIDs
2762 /*!
2763  * \brief Find IDs of sub-shapes complying with given status about surface
2764  * \param theCheckShape - the shape to check state of sub-shapes against
2765  * \param theShape - the shape to explore
2766  * \param theShapeType - type of sub-shape of theShape
2767  * \param theState - required state
2768  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2769  */
2770 //=======================================================================
2771 Handle(TColStd_HSequenceOfInteger)
2772   GEOMImpl_IShapesOperations::getShapesOnShapeIDs
2773                                  (const Handle(GEOM_Object)& theCheckShape,
2774                                   const Handle(GEOM_Object)& theShape,
2775                                   const Standard_Integer theShapeType,
2776                                   GEOMAlgo_State theState)
2777 {
2778   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2779
2780   TopoDS_Shape aCheckShape = theCheckShape->GetValue();
2781   TopoDS_Shape aShape = theShape->GetValue();
2782   TopTools_ListOfShape res;
2783
2784   // Check presence of triangulation, build if need
2785   if (!GEOMUtils::CheckTriangulation(aShape)) {
2786     SetErrorCode("Cannot build triangulation on the shape");
2787     return aSeqOfIDs;
2788   }
2789
2790   // Compute classification tolerance.
2791   TopTools_IndexedMapOfShape aMapVtx;
2792   Standard_Real              aTol = Precision::Confusion();
2793
2794   TopExp::MapShapes(aShape, TopAbs_VERTEX, aMapVtx);
2795
2796   Standard_Integer i;
2797   Standard_Integer aNbVtx = aMapVtx.Extent();
2798
2799   for (i = 1; i <= aNbVtx; ++i) {
2800     const TopoDS_Vertex aVtx    = TopoDS::Vertex(aMapVtx.FindKey(i));
2801     const Standard_Real aVtxTol = BRep_Tool::Tolerance(aVtx);
2802
2803     if (aTol < aVtxTol) {
2804       aTol = aVtxTol;
2805     }
2806   }
2807
2808   // Bound the tolerance value.
2809   if (aTol > 0.0001) {
2810     aTol = 0.0001;
2811   }
2812
2813   // Call algo
2814   GEOMAlgo_FinderShapeOn2 aFinder;
2815
2816   Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
2817   aClsfSolid->SetShape(aCheckShape);
2818
2819   aFinder.SetShape(aShape);
2820   aFinder.SetTolerance(aTol);
2821   aFinder.SetClsf(aClsfSolid);
2822   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
2823   aFinder.SetState(theState);
2824   aFinder.Perform();
2825
2826   // Interprete results
2827   Standard_Integer iErr = aFinder.ErrorStatus();
2828   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
2829   if (iErr) {
2830     if (iErr == 41) {
2831       SetErrorCode("theCheckShape must be a solid");
2832     }
2833     else {
2834       MESSAGE(" iErr : " << iErr);
2835       TCollection_AsciiString aMsg (" iErr : ");
2836       aMsg += TCollection_AsciiString(iErr);
2837       SetErrorCode(aMsg);
2838     }
2839     return aSeqOfIDs;
2840   }
2841   Standard_Integer iWrn = aFinder.WarningStatus();
2842   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
2843   if (iWrn) {
2844     MESSAGE(" *** iWrn : " << iWrn);
2845   }
2846
2847   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2848
2849   if (listSS.Extent() < 1) {
2850     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2851     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
2852   }
2853
2854   // Fill sequence of object IDs
2855   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2856
2857   TopTools_IndexedMapOfShape anIndices;
2858   TopExp::MapShapes(aShape, anIndices);
2859
2860   TopTools_ListIteratorOfListOfShape itSub (listSS);
2861   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2862     int id = anIndices.FindIndex(itSub.Value());
2863     aSeqOfIDs->Append(id);
2864   }
2865
2866   return aSeqOfIDs;
2867 }
2868
2869 //=======================================================================
2870 //function : GetShapesOnShapeIDs
2871 /*!
2872  * \brief Find sub-shapes complying with given status about surface
2873  * \param theCheckShape - the shape to check state of sub-shapes against
2874  * \param theShape - the shape to explore
2875  * \param theShapeType - type of sub-shape of theShape
2876  * \param theState - required state
2877  * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
2878  */
2879 //=======================================================================
2880 Handle(TColStd_HSequenceOfInteger)
2881     GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
2882                             (const Handle(GEOM_Object)& theCheckShape,
2883                              const Handle(GEOM_Object)& theShape,
2884                              const Standard_Integer theShapeType,
2885                              GEOMAlgo_State theState)
2886 {
2887   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2888     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2889
2890   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2891     return NULL;
2892
2893   // The GetShapesOnShape() doesn't change object so no new function is required.
2894   Handle(GEOM_Function) aFunction =
2895     GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
2896
2897   // Make a Python command
2898   GEOM::TPythonDump(aFunction, /*append=*/true)
2899     << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs("
2900     << theCheckShape << ", "
2901     << theShape << ", "
2902     << TopAbs_ShapeEnum(theShapeType) << ", "
2903     << theState << ")";
2904
2905   SetErrorCode(OK);
2906   return aSeqOfIDs;
2907 }
2908
2909 //=======================================================================
2910 //function : GetShapesOnShape
2911 /*!
2912  * \brief Find sub-shapes complying with given status about surface
2913  * \param theCheckShape - the shape to check state of sub-shapes against
2914  * \param theShape - the shape to explore
2915  * \param theShapeType - type of sub-shape of theShape
2916  * \param theState - required state
2917  * \retval Handle(TColStd_HSequenceOfTransient) - found sub-shapes
2918  */
2919 //=======================================================================
2920 Handle(TColStd_HSequenceOfTransient)
2921   GEOMImpl_IShapesOperations::GetShapesOnShape
2922                              (const Handle(GEOM_Object)& theCheckShape,
2923                               const Handle(GEOM_Object)&  theShape,
2924                               const Standard_Integer theShapeType,
2925                               GEOMAlgo_State theState)
2926 {
2927   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2928     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2929   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2930     return NULL;
2931
2932   // Find objects by indices
2933   TCollection_AsciiString anAsciiList;
2934   Handle(TColStd_HSequenceOfTransient) aSeq;
2935   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2936
2937   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2938     return NULL;
2939
2940   // Make a Python command
2941
2942   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2943   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2944
2945   GEOM::TPythonDump(aFunction)
2946     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
2947     << theCheckShape << ", "
2948     << theShape << ", "
2949     << TopAbs_ShapeEnum(theShapeType) << ", "
2950     << theState << ")";
2951
2952   SetErrorCode(OK);
2953   return aSeq;
2954 }
2955
2956 //=======================================================================
2957 //function : GetShapesOnShapeAsCompound
2958 //=======================================================================
2959 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
2960                              (const Handle(GEOM_Object)& theCheckShape,
2961                               const Handle(GEOM_Object)&  theShape,
2962                               const Standard_Integer theShapeType,
2963                               GEOMAlgo_State theState)
2964 {
2965   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2966     getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
2967
2968   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
2969     return NULL;
2970
2971   // Find objects by indices
2972   TCollection_AsciiString anAsciiList;
2973   Handle(TColStd_HSequenceOfTransient) aSeq;
2974   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2975
2976   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2977     return NULL;
2978
2979   TopoDS_Compound aCompound;
2980   BRep_Builder B;
2981   B.MakeCompound(aCompound);
2982   int i = 1;
2983   for(; i<=aSeq->Length(); i++) {
2984     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
2985     TopoDS_Shape aShape_i = anObj->GetValue();
2986     B.Add(aCompound,aShape_i);
2987   }
2988
2989   //Add a new result object
2990   Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
2991   Handle(GEOM_Function) aFunction =
2992     aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
2993   aFunction->SetValue(aCompound);
2994
2995   aSeq->Clear();
2996   aSeq->Append( theCheckShape->GetLastFunction() );
2997   aSeq->Append( theShape->GetLastFunction() );
2998
2999   GEOMImpl_IShapes aCI( aFunction );
3000   aCI.SetShapes( aSeq );
3001   aCI.SetSubShapeType( theShapeType );
3002   aCI.SetTolerance( theState );
3003
3004   GEOM::TPythonDump(aFunction)
3005     << aRes << " = geompy.GetShapesOnShapeAsCompound("
3006     << theCheckShape << ", "
3007     << theShape << ", "
3008     << TopAbs_ShapeEnum(theShapeType) << ", "
3009     << theState << ")";
3010
3011   SetErrorCode(OK);
3012
3013   return aRes;
3014 }
3015
3016 //=============================================================================
3017 /*!
3018  *  GetSubShapeEdgeSorted
3019  */
3020 //=============================================================================
3021 Handle(TColStd_HSequenceOfTransient)
3022     GEOMImpl_IShapesOperations::GetSubShapeEdgeSorted
3023                           (const Handle(GEOM_Object) &theShape,
3024                            const Handle(GEOM_Object) &theStartPoint)
3025 {
3026   // Get the sorted edges indices.
3027   Handle(TColStd_HSequenceOfInteger) aSortedIDs =
3028     getSubShapeEdgeSortedIDs(theShape, theStartPoint);
3029
3030   // Get object by indices.
3031   TCollection_AsciiString              anAsciiList;
3032   Handle(TColStd_HSequenceOfTransient) aSeq =
3033     getObjectsShapesOn(theShape, aSortedIDs, anAsciiList);
3034
3035   if (aSeq.IsNull() || aSeq->IsEmpty()) {
3036     SetErrorCode("Empty sequence of edges");
3037     return NULL;
3038   }
3039
3040   // Make a Python command
3041   Handle(GEOM_Object)   anObj     =
3042     Handle(GEOM_Object)::DownCast(aSeq->Value(1));
3043   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3044
3045   GEOM::TPythonDump(aFunction)
3046     << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapeEdgeSorted("
3047     << theShape << ", " << theStartPoint << ")";
3048
3049   SetErrorCode(OK);
3050
3051   return aSeq;
3052 }
3053
3054 //=======================================================================
3055 //function : getShapesOnSurfaceIDs
3056   /*!
3057    * \brief Find IDs of sub-shapes complying with given status about surface
3058     * \param theSurface - the surface to check state of sub-shapes against
3059     * \param theShape - the shape to explore
3060     * \param theShapeType - type of sub-shape of theShape
3061     * \param theState - required state
3062     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3063    */
3064 //=======================================================================
3065 Handle(TColStd_HSequenceOfInteger)
3066   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
3067                                                     const TopoDS_Shape&         theShape,
3068                                                     TopAbs_ShapeEnum            theShapeType,
3069                                                     GEOMAlgo_State              theState)
3070 {
3071   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3072
3073   // Check presence of triangulation, build if need
3074   if (!GEOMUtils::CheckTriangulation(theShape)) {
3075     SetErrorCode("Cannot build triangulation on the shape");
3076     return aSeqOfIDs;
3077   }
3078
3079   // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape
3080   // Compute tolerance
3081   Standard_Real T, VertMax = -RealLast();
3082   try {
3083     OCC_CATCH_SIGNALS;
3084     for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
3085       TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
3086       T = BRep_Tool::Tolerance(Vertex);
3087       if (T > VertMax)
3088         VertMax = T;
3089     }
3090   }
3091   catch (Standard_Failure) {
3092     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3093     SetErrorCode(aFail->GetMessageString());
3094     return aSeqOfIDs;
3095   }
3096   // END: Mantis issue 0020961
3097
3098   // Call algo
3099   GEOMAlgo_FinderShapeOn2   aFinder;
3100   Handle(GEOMAlgo_ClsfSurf) aClsfSurf = new GEOMAlgo_ClsfSurf;
3101   Standard_Real             aTol      = VertMax; // Mantis issue 0020961
3102
3103   aClsfSurf->SetSurface(theSurface);
3104   aFinder.SetShape(theShape);
3105   aFinder.SetTolerance(aTol);
3106   aFinder.SetClsf(aClsfSurf);
3107   aFinder.SetShapeType(theShapeType);
3108   aFinder.SetState(theState);
3109
3110   // Sets the minimal number of inner points for the faces that do not have own
3111   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
3112   // Default value=3
3113   aFinder.SetNbPntsMin(3);
3114   // Sets the maximal number of inner points for edges or faces.
3115   // It is usefull for the cases when this number is very big (e.g =2000) to improve
3116   // the performance. If this value =0, all inner points will be taken into account.
3117   // Default value=0
3118   aFinder.SetNbPntsMax(100);
3119
3120   aFinder.Perform();
3121
3122   // Interprete results
3123   Standard_Integer iErr = aFinder.ErrorStatus();
3124   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
3125   if (iErr) {
3126     MESSAGE(" iErr : " << iErr);
3127     TCollection_AsciiString aMsg (" iErr : ");
3128     aMsg += TCollection_AsciiString(iErr);
3129     SetErrorCode(aMsg);
3130     return aSeqOfIDs;
3131   }
3132   Standard_Integer iWrn = aFinder.WarningStatus();
3133   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
3134   if (iWrn) {
3135     MESSAGE(" *** iWrn : " << iWrn);
3136   }
3137
3138   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
3139
3140   if (listSS.Extent() < 1) {
3141     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
3142     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
3143     return aSeqOfIDs;
3144   }
3145
3146   // Fill sequence of object IDs
3147   aSeqOfIDs = new TColStd_HSequenceOfInteger;
3148
3149   TopTools_IndexedMapOfShape anIndices;
3150   TopExp::MapShapes(theShape, anIndices);
3151
3152   TopTools_ListIteratorOfListOfShape itSub (listSS);
3153   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
3154     int id = anIndices.FindIndex(itSub.Value());
3155     aSeqOfIDs->Append(id);
3156   }
3157
3158   return aSeqOfIDs;
3159 }
3160
3161 //=======================================================================
3162 //function : getObjectsShapesOn
3163 /*!
3164  * \brief Find shape objects and their entries by their ids
3165  * \param theShapeIDs - incoming shape ids
3166  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3167  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
3168  */
3169 //=======================================================================
3170 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
3171  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
3172                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
3173                     TCollection_AsciiString &                 theShapeEntries)
3174 {
3175   Handle(TColStd_HSequenceOfTransient) aSeq;
3176
3177   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
3178   {
3179     aSeq = new TColStd_HSequenceOfTransient;
3180     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
3181     TCollection_AsciiString anEntry;
3182     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
3183     {
3184       anArray->SetValue(1, theShapeIDs->Value( i ));
3185       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
3186       aSeq->Append( anObj );
3187
3188       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
3189       if ( i != 1 ) theShapeEntries += ",";
3190       theShapeEntries += anEntry;
3191     }
3192   }
3193   return aSeq;
3194 }
3195
3196 //=============================================================================
3197 /*!
3198  *  getSubShapeEdgeSortedIDs
3199  */
3200 //=============================================================================
3201 Handle(TColStd_HSequenceOfInteger)
3202     GEOMImpl_IShapesOperations::getSubShapeEdgeSortedIDs
3203                                (const Handle(GEOM_Object) &theShape,
3204                                 const Handle(GEOM_Object) &theStartPoint)
3205 {
3206   Handle(TColStd_HSequenceOfInteger) aResult;
3207
3208   if (theShape.IsNull() || theStartPoint.IsNull()) {
3209     SetErrorCode("NULL GEOM object");
3210     return aResult;
3211   }
3212
3213   const TopoDS_Shape aShape      = theShape->GetValue();
3214   const TopoDS_Shape aStartPoint = theStartPoint->GetValue();
3215
3216   if (aShape.IsNull() || aStartPoint.IsNull()) {
3217     SetErrorCode("NULL Shape");
3218     return aResult;
3219   }
3220
3221   if (aStartPoint.ShapeType() != TopAbs_VERTEX) {
3222     SetErrorCode("Starting point is not a vertex");
3223     return aResult;
3224   }
3225
3226   TopExp_Explorer      anExp(aShape, TopAbs_EDGE);
3227   TopTools_MapOfShape  aMapFence;
3228   TopTools_ListOfShape anEdges;
3229
3230   for (; anExp.More(); anExp.Next()) {
3231     const TopoDS_Shape &anEdge = anExp.Current();
3232
3233     if (aMapFence.Add(anEdge)) {
3234       anEdges.Append(anEdge);
3235     }
3236   }
3237
3238   if (anEdges.IsEmpty()) {
3239     SetErrorCode("Shape doesn't contain edges");
3240     return aResult;
3241   }
3242
3243   // Step 1: Sort edges
3244   GEOMUtils::SortShapes(anEdges, Standard_False);
3245
3246   TopTools_ListIteratorOfListOfShape anIter(anEdges);
3247   TopoDS_Vertex                      aV[2];
3248   TopTools_DataMapOfShapeListOfShape aMapVE;
3249
3250   // Step 2: Fill the map vertex - list of edges.
3251   for (; anIter.More(); anIter.Next()) {
3252     TopoDS_Edge anEdge = TopoDS::Edge(anIter.Value());
3253
3254     TopExp::Vertices(anEdge, aV[0], aV[1]);
3255
3256     const Standard_Integer aNbV = aV[0].IsSame(aV[1]) ? 1 : 2;
3257     Standard_Integer       i;
3258
3259     for (i = 0; i < aNbV; ++i) {
3260       if (aV[i].IsNull() == Standard_False) {
3261         if (!aMapVE.IsBound(aV[i])) {
3262           // There is no this vertex in the map.
3263           aMapVE.Bind(aV[i], TopTools_ListOfShape());
3264         }
3265
3266         // Add the edge to the list bound with the vertex aV[i].
3267         TopTools_ListOfShape &aLEdges = aMapVE.ChangeFind(aV[i]);
3268
3269         aLEdges.Append(anEdge);
3270       }
3271     }
3272   }
3273
3274   // Step 3: Find starting point in aMapVE.
3275   TopoDS_Vertex aStartVtx = TopoDS::Vertex(aStartPoint);
3276
3277   if (!aMapVE.IsBound(aStartVtx)) {
3278     aStartVtx = getSameVertex(aShape, aStartVtx);
3279
3280     if (aStartVtx.IsNull()) {
3281       SetErrorCode("Invalid Starting point");
3282       return aResult;
3283     }
3284   }
3285
3286   TopTools_IndexedMapOfShape anIndices;
3287   TopTools_MapOfShape        aMapVFence;
3288   TopoDS_Shape               aCurVtx  = aStartVtx;
3289   TopoDS_Edge                aCurEdge =
3290     TopoDS::Edge(aMapVE.Find(aCurVtx).First());
3291
3292   aResult = new TColStd_HSequenceOfInteger;
3293   TopExp::MapShapes(aShape, anIndices);
3294
3295   // Step 4: Fill the list of sorted edges.
3296   while (aMapVFence.Add(aCurVtx)) {
3297     // Append the ID of the current edge to the list of sorted.
3298     aResult->Append(anIndices.FindIndex(aCurEdge));
3299     TopExp::Vertices(aCurEdge, aV[0], aV[1]);
3300
3301     // Get the next vertex.
3302     if (aCurVtx.IsSame(aV[0])) {
3303       if (aCurVtx.IsSame(aV[1])) {
3304         // There is no next vertex.
3305         break;
3306       } else {
3307         aCurVtx = aV[1];
3308       }
3309     } else {
3310       aCurVtx = aV[0];
3311     }
3312
3313     if (aCurVtx.IsNull()) {
3314       // There is no next vertex.
3315       break;
3316     }
3317
3318     // Get the next edge.
3319     const TopTools_ListOfShape         &aLEdges = aMapVE.Find(aCurVtx);
3320     TopTools_ListIteratorOfListOfShape  anEIter(aLEdges);
3321
3322     for (; anEIter.More(); anEIter.Next()) {
3323       const TopoDS_Shape &aLocalEdge = anEIter.Value();
3324
3325       if (aLocalEdge.IsNull() == Standard_False) {
3326         if (!aCurEdge.IsSame(aLocalEdge)) {
3327           aCurEdge = TopoDS::Edge(aLocalEdge);
3328           break;
3329         }
3330       }
3331     }
3332
3333     if (!anEIter.More()) {
3334       // There is no next edge.
3335       break;
3336     }
3337   }
3338
3339   return aResult;
3340 }
3341
3342 //=======================================================================
3343 //function : getShapesOnSurface
3344 /*!
3345    * \brief Find sub-shapes complying with given status about surface
3346     * \param theSurface - the surface to check state of sub-shapes against
3347     * \param theShape - the shape to explore
3348     * \param theShapeType - type of sub-shape of theShape
3349     * \param theState - required state
3350     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
3351     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3352  */
3353 //=======================================================================
3354 Handle(TColStd_HSequenceOfTransient)
3355     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
3356                                                    const Handle(GEOM_Object)&  theShape,
3357                                                    TopAbs_ShapeEnum            theShapeType,
3358                                                    GEOMAlgo_State              theState,
3359                                                    TCollection_AsciiString &   theShapeEntries)
3360 {
3361   // Find sub-shapes ids
3362   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
3363     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
3364   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
3365     return NULL;
3366
3367   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
3368 }
3369
3370 //=============================================================================
3371 /*!
3372  *  GetShapesOnPlane
3373  */
3374 //=============================================================================
3375 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
3376                                         (const Handle(GEOM_Object)& theShape,
3377                                          const Standard_Integer     theShapeType,
3378                                          const Handle(GEOM_Object)& theAx1,
3379                                          const GEOMAlgo_State       theState)
3380 {
3381   SetErrorCode(KO);
3382
3383   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3384
3385   TopoDS_Shape aShape = theShape->GetValue();
3386   TopoDS_Shape anAx1  = theAx1->GetValue();
3387
3388   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3389
3390   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3391   if ( !checkTypeShapesOn( theShapeType ))
3392     return NULL;
3393
3394   // Create plane
3395   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3396   if ( aPlane.IsNull() )
3397     return NULL;
3398
3399   // Find objects
3400   TCollection_AsciiString anAsciiList;
3401   Handle(TColStd_HSequenceOfTransient) aSeq;
3402   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3403   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3404     return NULL;
3405
3406   // Make a Python command
3407
3408   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3409   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3410
3411   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3412     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
3413       << aShapeType << ", " << theAx1 << ", " << theState << ")";
3414
3415   SetErrorCode(OK);
3416   return aSeq;
3417 }
3418
3419 //=============================================================================
3420 /*!
3421  *  GetShapesOnPlaneWithLocation
3422  */
3423 //=============================================================================
3424 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
3425                                         (const Handle(GEOM_Object)& theShape,
3426                                          const Standard_Integer     theShapeType,
3427                                          const Handle(GEOM_Object)& theAx1,
3428                                          const Handle(GEOM_Object)& thePnt,
3429                                          const GEOMAlgo_State       theState)
3430 {
3431   SetErrorCode(KO);
3432
3433   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3434
3435   TopoDS_Shape aShape = theShape->GetValue();
3436   TopoDS_Shape anAx1  = theAx1->GetValue();
3437   TopoDS_Shape anPnt = thePnt->GetValue();
3438
3439   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3440
3441   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3442   if ( !checkTypeShapesOn( theShapeType ))
3443     return NULL;
3444
3445   // Create plane
3446   if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
3447   TopoDS_Vertex V1, V2, V3;
3448   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3449   TopExp::Vertices(anEdge, V1, V2, Standard_True);
3450
3451   if (V1.IsNull() || V2.IsNull()) {
3452     SetErrorCode("Bad edge given for the plane normal vector");
3453     return NULL;
3454   }
3455   V3 = TopoDS::Vertex(anPnt);
3456
3457   if(V3.IsNull()) {
3458     SetErrorCode("Bad vertex given for the plane location");
3459       return NULL;
3460   }
3461   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3462   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3463
3464   if (aVec.Magnitude() < Precision::Confusion()) {
3465     SetErrorCode("Vector with null magnitude given");
3466     return NULL;
3467   }
3468   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3469
3470   if ( aPlane.IsNull() )
3471     return NULL;
3472
3473   // Find objects
3474   TCollection_AsciiString anAsciiList;
3475   Handle(TColStd_HSequenceOfTransient) aSeq;
3476   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
3477   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3478     return NULL;
3479
3480   // Make a Python command
3481
3482   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3483   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3484
3485   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3486     << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
3487     << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
3488
3489   SetErrorCode(OK);
3490   return aSeq;
3491 }
3492
3493 //=============================================================================
3494 /*!
3495  *  GetShapesOnCylinder
3496  */
3497 //=============================================================================
3498 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
3499                                           (const Handle(GEOM_Object)& theShape,
3500                                            const Standard_Integer     theShapeType,
3501                                            const Handle(GEOM_Object)& theAxis,
3502                                            const Standard_Real        theRadius,
3503                                            const GEOMAlgo_State       theState)
3504 {
3505   SetErrorCode(KO);
3506
3507   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3508
3509   TopoDS_Shape aShape = theShape->GetValue();
3510   TopoDS_Shape anAxis = theAxis->GetValue();
3511
3512   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3513
3514   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3515   if ( !checkTypeShapesOn( aShapeType ))
3516     return NULL;
3517
3518   // Create a cylinder surface
3519   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3520   if ( aCylinder.IsNull() )
3521     return NULL;
3522
3523   // Find objects
3524   TCollection_AsciiString anAsciiList;
3525   Handle(TColStd_HSequenceOfTransient) aSeq;
3526   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3527   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3528     return NULL;
3529
3530   // Make a Python command
3531
3532   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3533   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3534
3535   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3536     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
3537       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
3538
3539   SetErrorCode(OK);
3540   return aSeq;
3541 }
3542
3543 //=============================================================================
3544 /*!
3545  *  GetShapesOnCylinderWithLocation
3546  */
3547 //=============================================================================
3548 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation
3549                                           (const Handle(GEOM_Object)& theShape,
3550                                            const Standard_Integer     theShapeType,
3551                                            const Handle(GEOM_Object)& theAxis,
3552                                            const Handle(GEOM_Object)& thePnt,
3553                                            const Standard_Real        theRadius,
3554                                            const GEOMAlgo_State       theState)
3555 {
3556   SetErrorCode(KO);
3557
3558   if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3559
3560   TopoDS_Shape aShape = theShape->GetValue();
3561   TopoDS_Shape anAxis = theAxis->GetValue();
3562   TopoDS_Shape aPnt   = thePnt->GetValue();
3563
3564   if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3565
3566   if (aPnt.ShapeType() != TopAbs_VERTEX )
3567   {
3568     SetErrorCode("Bottom location point must be vertex");
3569     return NULL;
3570   }
3571
3572   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3573   if ( !checkTypeShapesOn( aShapeType ))
3574     return NULL;
3575
3576   // Create a cylinder surface
3577   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3578   if ( aCylinder.IsNull() )
3579     return NULL;
3580
3581   // translate the surface
3582   Handle(Geom_CylindricalSurface) aCylSurface =
3583     Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3584   if ( aCylSurface.IsNull() )
3585   {
3586     SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3587     return NULL;
3588   }
3589   gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3590   gp_Pnt toLoc   = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3591   aCylinder->Translate( fromLoc, toLoc );
3592
3593   // Find objects
3594   TCollection_AsciiString anAsciiList;
3595   Handle(TColStd_HSequenceOfTransient) aSeq;
3596   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
3597   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3598     return NULL;
3599
3600   // Make a Python command
3601
3602   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3603   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3604
3605   GEOM::TPythonDump(aFunction)
3606     << "[" << anAsciiList.ToCString()
3607     << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", "
3608     << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")";
3609
3610   SetErrorCode(OK);
3611   return aSeq;
3612 }
3613
3614 //=============================================================================
3615 /*!
3616  *  GetShapesOnSphere
3617  */
3618 //=============================================================================
3619 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
3620                                           (const Handle(GEOM_Object)& theShape,
3621                                            const Standard_Integer     theShapeType,
3622                                            const Handle(GEOM_Object)& theCenter,
3623                                            const Standard_Real        theRadius,
3624                                            const GEOMAlgo_State       theState)
3625 {
3626   SetErrorCode(KO);
3627
3628   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3629
3630   TopoDS_Shape aShape  = theShape->GetValue();
3631   TopoDS_Shape aCenter = theCenter->GetValue();
3632
3633   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3634
3635   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3636   if ( !checkTypeShapesOn( aShapeType ))
3637     return NULL;
3638
3639   // Center of the sphere
3640   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3641   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3642
3643   gp_Ax3 anAx3 (aLoc, gp::DZ());
3644   Handle(Geom_SphericalSurface) aSphere =
3645     new Geom_SphericalSurface(anAx3, theRadius);
3646
3647   // Find objects
3648   TCollection_AsciiString anAsciiList;
3649   Handle(TColStd_HSequenceOfTransient) aSeq;
3650   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
3651   if ( aSeq.IsNull() || aSeq->Length() == 0 )
3652     return NULL;
3653
3654   // Make a Python command
3655
3656   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
3657   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
3658
3659   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
3660     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
3661       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
3662
3663   SetErrorCode(OK);
3664   return aSeq;
3665 }
3666
3667 //=============================================================================
3668 /*!
3669  *  GetShapesOnPlaneIDs
3670  */
3671 //=============================================================================
3672 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
3673                                         (const Handle(GEOM_Object)& theShape,
3674                                          const Standard_Integer     theShapeType,
3675                                          const Handle(GEOM_Object)& theAx1,
3676                                          const GEOMAlgo_State       theState)
3677 {
3678   SetErrorCode(KO);
3679
3680   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
3681
3682   TopoDS_Shape aShape = theShape->GetValue();
3683   TopoDS_Shape anAx1  = theAx1->GetValue();
3684
3685   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
3686
3687   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3688   if ( !checkTypeShapesOn( aShapeType ))
3689     return NULL;
3690
3691   // Create plane
3692   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
3693   if ( aPlane.IsNull() )
3694     return NULL;
3695
3696   // Find object IDs
3697   Handle(TColStd_HSequenceOfInteger) aSeq;
3698   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3699
3700   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3701   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3702
3703   // Make a Python command
3704   GEOM::TPythonDump(aFunction, /*append=*/true)
3705     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
3706     << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
3707
3708   SetErrorCode(OK);
3709   return aSeq;
3710 }
3711
3712 //=============================================================================
3713 /*!
3714  *  GetShapesOnPlaneWithLocationIDs
3715  */
3716 //=============================================================================
3717 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
3718                                         (const Handle(GEOM_Object)& theShape,
3719                                          const Standard_Integer     theShapeType,
3720                                          const Handle(GEOM_Object)& theAx1,
3721                                          const Handle(GEOM_Object)& thePnt,
3722                                          const GEOMAlgo_State       theState)
3723 {
3724   SetErrorCode(KO);
3725
3726   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
3727
3728   TopoDS_Shape aShape = theShape->GetValue();
3729   TopoDS_Shape anAx1  = theAx1->GetValue();
3730   TopoDS_Shape anPnt  = thePnt->GetValue();
3731
3732   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
3733
3734   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3735   if ( !checkTypeShapesOn( aShapeType ))
3736     return NULL;
3737
3738   // Create plane
3739   if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
3740   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
3741   TopoDS_Vertex V1, V2, V3;
3742   TopExp::Vertices(anEdge, V1, V2, Standard_True);
3743   if (V1.IsNull() || V2.IsNull()) {
3744     SetErrorCode("Bad edge given for the plane normal vector");
3745     return NULL;
3746   }
3747   V3 = TopoDS::Vertex(anPnt);
3748   if(V3.IsNull()) {
3749     SetErrorCode("Bad vertex given for the plane location");
3750       return NULL;
3751   }
3752   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
3753   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
3754   if (aVec.Magnitude() < Precision::Confusion()) {
3755     SetErrorCode("Vector with null magnitude given");
3756     return NULL;
3757   }
3758
3759   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
3760   if ( aPlane.IsNull() )
3761     return NULL;
3762
3763   // Find object IDs
3764   Handle(TColStd_HSequenceOfInteger) aSeq;
3765   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
3766
3767   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
3768   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
3769
3770   // Make a Python command
3771   GEOM::TPythonDump(aFunction, /*append=*/true)
3772     << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
3773     << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
3774
3775   SetErrorCode(OK);
3776   return aSeq;
3777 }
3778
3779 //=============================================================================
3780 /*!
3781  *  GetShapesOnCylinderIDs
3782  */
3783 //=============================================================================
3784 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
3785                                           (const Handle(GEOM_Object)& theShape,
3786                                            const Standard_Integer     theShapeType,
3787                                            const Handle(GEOM_Object)& theAxis,
3788                                            const Standard_Real        theRadius,
3789                                            const GEOMAlgo_State       theState)
3790 {
3791   SetErrorCode(KO);
3792
3793   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
3794
3795   TopoDS_Shape aShape = theShape->GetValue();
3796   TopoDS_Shape anAxis = theAxis->GetValue();
3797
3798   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
3799
3800   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3801   if ( !checkTypeShapesOn( aShapeType ))
3802     return NULL;
3803
3804   // Create a cylinder surface
3805   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3806   if ( aCylinder.IsNull() )
3807     return NULL;
3808
3809   // Find object IDs
3810   Handle(TColStd_HSequenceOfInteger) aSeq;
3811   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
3812
3813   // The GetShapesOnCylinder() doesn't change object so no new function is required.
3814   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
3815
3816   // Make a Python command
3817   GEOM::TPythonDump(aFunction, /*append=*/true)
3818     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
3819     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
3820     << theRadius << ", " << theState << ")";
3821
3822   SetErrorCode(OK);
3823   return aSeq;
3824 }
3825
3826 //=============================================================================
3827 /*!
3828  *  GetShapesOnCylinderWithLocationIDs
3829  */
3830 //=============================================================================
3831 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs
3832                                           (const Handle(GEOM_Object)& theShape,
3833                                            const Standard_Integer     theShapeType,
3834                                            const Handle(GEOM_Object)& theAxis,
3835                                            const Handle(GEOM_Object)& thePnt,
3836                                            const Standard_Real        theRadius,
3837                                            const GEOMAlgo_State       theState)
3838 {
3839   SetErrorCode(KO);
3840
3841   if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL;
3842
3843   TopoDS_Shape aShape = theShape->GetValue();
3844   TopoDS_Shape anAxis = theAxis->GetValue();
3845   TopoDS_Shape aPnt   = thePnt->GetValue();
3846
3847   if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL;
3848
3849   if (aPnt.ShapeType() != TopAbs_VERTEX )
3850   {
3851     SetErrorCode("Bottom location point must be vertex");
3852     return NULL;
3853   }
3854
3855   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3856   if ( !checkTypeShapesOn( aShapeType ))
3857     return NULL;
3858
3859   // Create a cylinder surface
3860   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
3861   if ( aCylinder.IsNull() )
3862     return NULL;
3863
3864   // translate the surface
3865   Handle(Geom_CylindricalSurface) aCylSurface =
3866     Handle(Geom_CylindricalSurface)::DownCast( aCylinder );
3867   if ( aCylSurface.IsNull() )
3868   {
3869     SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface");
3870     return NULL;
3871   }
3872   gp_Pnt fromLoc = aCylSurface->Cylinder().Location();
3873   gp_Pnt toLoc   = BRep_Tool::Pnt( TopoDS::Vertex( aPnt ));
3874   aCylinder->Translate( fromLoc, toLoc );
3875
3876   // Find object IDs
3877   Handle(TColStd_HSequenceOfInteger) aSeq;
3878   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
3879
3880   // The GetShapesOnCylinder() doesn't change object so no new function is required.
3881   Handle(GEOM_Function) aFunction =
3882     GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction();
3883
3884   // Make a Python command
3885   GEOM::TPythonDump(aFunction, /*append=*/true)
3886     << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs"
3887     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
3888     << thePnt << ", " << theRadius << ", " << theState << ")";
3889
3890   SetErrorCode(OK);
3891   return aSeq;
3892 }
3893
3894 //=============================================================================
3895 /*!
3896  *  GetShapesOnSphereIDs
3897  */
3898 //=============================================================================
3899 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
3900                                           (const Handle(GEOM_Object)& theShape,
3901                                            const Standard_Integer     theShapeType,
3902                                            const Handle(GEOM_Object)& theCenter,
3903                                            const Standard_Real        theRadius,
3904                                            const GEOMAlgo_State       theState)
3905 {
3906   SetErrorCode(KO);
3907
3908   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
3909
3910   TopoDS_Shape aShape  = theShape->GetValue();
3911   TopoDS_Shape aCenter = theCenter->GetValue();
3912
3913   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
3914
3915   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3916   if ( !checkTypeShapesOn( aShapeType ))
3917     return NULL;
3918
3919   // Center of the sphere
3920   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
3921   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
3922
3923   gp_Ax3 anAx3 (aLoc, gp::DZ());
3924   Handle(Geom_SphericalSurface) aSphere =
3925     new Geom_SphericalSurface(anAx3, theRadius);
3926
3927   // Find object IDs
3928   Handle(TColStd_HSequenceOfInteger) aSeq;
3929   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
3930
3931   // The GetShapesOnSphere() doesn't change object so no new function is required.
3932   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
3933
3934   // Make a Python command
3935   GEOM::TPythonDump(aFunction, /*append=*/true)
3936     << "listShapesOnCylinder = geompy.GetShapesOnSphereIDs"
3937     << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
3938     << theRadius << ", " << theState << ")";
3939
3940   SetErrorCode(OK);
3941   return aSeq;
3942 }
3943
3944 //=======================================================================
3945 //function : getShapesOnQuadrangleIDs
3946   /*!
3947    * \brief Find IDs of sub-shapes complying with given status about quadrangle
3948     * \param theShape - the shape to explore
3949     * \param theShapeType - type of sub-shape of theShape
3950     * \param theTopLeftPoint - top left quadrangle corner
3951     * \param theTopRigthPoint - top right quadrangle corner
3952     * \param theBottomLeftPoint - bottom left quadrangle corner
3953     * \param theBottomRigthPoint - bottom right quadrangle corner
3954     * \param theState - required state
3955     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
3956    */
3957 //=======================================================================
3958 Handle(TColStd_HSequenceOfInteger)
3959   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
3960                                                         const Standard_Integer     theShapeType,
3961                                                         const Handle(GEOM_Object)& theTopLeftPoint,
3962                                                         const Handle(GEOM_Object)& theTopRigthPoint,
3963                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
3964                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
3965                                                         const GEOMAlgo_State       theState)
3966 {
3967   SetErrorCode(KO);
3968
3969   if ( theShape.IsNull() ||
3970        theTopLeftPoint.IsNull() ||
3971        theTopRigthPoint.IsNull() ||
3972        theBottomLeftPoint.IsNull() ||
3973        theBottomRigthPoint.IsNull() )
3974     return NULL;
3975
3976   TopoDS_Shape aShape = theShape->GetValue();
3977   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
3978   TopoDS_Shape aTR = theTopRigthPoint->GetValue();
3979   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
3980   TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
3981
3982   if (aShape.IsNull() ||
3983       aTL.IsNull() ||
3984       aTR.IsNull() ||
3985       aBL.IsNull() ||
3986       aBR.IsNull() ||
3987       aTL.ShapeType() != TopAbs_VERTEX ||
3988       aTR.ShapeType() != TopAbs_VERTEX ||
3989       aBL.ShapeType() != TopAbs_VERTEX ||
3990       aBR.ShapeType() != TopAbs_VERTEX )
3991     return NULL;
3992
3993   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
3994   if ( !checkTypeShapesOn( aShapeType ))
3995     return NULL;
3996
3997   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
3998
3999   // Check presence of triangulation, build if need
4000   if (!GEOMUtils::CheckTriangulation(aShape)) {
4001     SetErrorCode("Cannot build triangulation on the shape");
4002     return aSeqOfIDs;
4003   }
4004
4005   // Call algo
4006   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
4007   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
4008   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
4009   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
4010
4011   GEOMAlgo_FinderShapeOn2  aFinder;
4012   Handle(GEOMAlgo_ClsfQuad) aClsfQuad = new GEOMAlgo_ClsfQuad;
4013
4014   Standard_Real aTol = 0.0001; // default value
4015
4016   aClsfQuad->SetCorners(aPntTL, aPntTR, aPntBL, aPntBR);
4017   aFinder.SetShape(aShape);
4018   aFinder.SetTolerance(aTol);
4019   aFinder.SetClsf(aClsfQuad);
4020   aFinder.SetShapeType(aShapeType);
4021   aFinder.SetState(theState);
4022
4023   // Sets the minimal number of inner points for the faces that do not have own
4024   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
4025   // Default value=3
4026   aFinder.SetNbPntsMin(3);
4027   // Sets the maximal number of inner points for edges or faces.
4028   // It is usefull for the cases when this number is very big (e.g =2000) to improve
4029   // the performance. If this value =0, all inner points will be taken into account.
4030   // Default value=0
4031   aFinder.SetNbPntsMax(100);
4032
4033   aFinder.Perform();
4034
4035   // Interprete results
4036   Standard_Integer iErr = aFinder.ErrorStatus();
4037   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
4038   if (iErr) {
4039     MESSAGE(" iErr : " << iErr);
4040     TCollection_AsciiString aMsg (" iErr : ");
4041     aMsg += TCollection_AsciiString(iErr);
4042     SetErrorCode(aMsg);
4043     return aSeqOfIDs;
4044   }
4045   Standard_Integer iWrn = aFinder.WarningStatus();
4046   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
4047   if (iWrn) {
4048     MESSAGE(" *** iWrn : " << iWrn);
4049   }
4050
4051   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
4052
4053   if (listSS.Extent() < 1) {
4054     //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
4055     SetErrorCode(NOT_FOUND_ANY); // NPAL18017
4056     return aSeqOfIDs;
4057   }
4058
4059   // Fill sequence of object IDs
4060   aSeqOfIDs = new TColStd_HSequenceOfInteger;
4061
4062   TopTools_IndexedMapOfShape anIndices;
4063   TopExp::MapShapes(aShape, anIndices);
4064
4065   TopTools_ListIteratorOfListOfShape itSub (listSS);
4066   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
4067     int id = anIndices.FindIndex(itSub.Value());
4068     aSeqOfIDs->Append(id);
4069   }
4070   return aSeqOfIDs;
4071 }
4072
4073 //=======================================================================
4074 //function : GetShapesOnQuadrangle
4075   /*!
4076    * \brief Find sub-shapes complying with given status about quadrangle
4077     * \param theShape - the shape to explore
4078     * \param theShapeType - type of sub-shape of theShape
4079     * \param theTopLeftPoint - top left quadrangle corner
4080     * \param theTopRigthPoint - top right quadrangle corner
4081     * \param theBottomLeftPoint - bottom left quadrangle corner
4082     * \param theBottomRigthPoint - bottom right quadrangle corner
4083     * \param theState - required state
4084     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4085    */
4086 //=======================================================================
4087 Handle(TColStd_HSequenceOfTransient)
4088     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
4089                                                        const Standard_Integer     theShapeType,
4090                                                        const Handle(GEOM_Object)& theTopLeftPoint,
4091                                                        const Handle(GEOM_Object)& theTopRigthPoint,
4092                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
4093                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
4094                                                        const GEOMAlgo_State       theState)
4095 {
4096   // Find indices
4097   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4098     getShapesOnQuadrangleIDs( theShape,
4099                               theShapeType,
4100                               theTopLeftPoint,
4101                               theTopRigthPoint,
4102                               theBottomLeftPoint,
4103                               theBottomRigthPoint,
4104                               theState);
4105   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4106     return NULL;
4107
4108   // Find objects by indices
4109   TCollection_AsciiString anAsciiList;
4110   Handle(TColStd_HSequenceOfTransient) aSeq;
4111   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
4112   if ( aSeq.IsNull() || aSeq->IsEmpty() )
4113     return NULL;
4114
4115   // Make a Python command
4116
4117   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
4118   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
4119
4120   GEOM::TPythonDump(aFunction)
4121     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
4122     << theShape << ", "
4123     << TopAbs_ShapeEnum(theShapeType) << ", "
4124     << theTopLeftPoint << ", "
4125     << theTopRigthPoint << ", "
4126     << theBottomLeftPoint << ", "
4127     << theBottomRigthPoint << ", "
4128     << theState << ")";
4129
4130   SetErrorCode(OK);
4131   return aSeq;
4132 }
4133
4134 //=======================================================================
4135 //function : GetShapesOnQuadrangleIDs
4136   /*!
4137    * \brief Find IDs of sub-shapes complying with given status about quadrangle
4138     * \param theShape - the shape to explore
4139     * \param theShapeType - type of sub-shape of theShape
4140     * \param theTopLeftPoint - top left quadrangle corner
4141     * \param theTopRigthPoint - top right quadrangle corner
4142     * \param theBottomLeftPoint - bottom left quadrangle corner
4143     * \param theBottomRigthPoint - bottom right quadrangle corner
4144     * \param theState - required state
4145     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes
4146    */
4147 //=======================================================================
4148 Handle(TColStd_HSequenceOfInteger)
4149   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
4150                                                         const Standard_Integer     theShapeType,
4151                                                         const Handle(GEOM_Object)& theTopLeftPoint,
4152                                                         const Handle(GEOM_Object)& theTopRigthPoint,
4153                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
4154                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
4155                                                         const GEOMAlgo_State       theState)
4156 {
4157   // Find indices
4158   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
4159     getShapesOnQuadrangleIDs( theShape,
4160                               theShapeType,
4161                               theTopLeftPoint,
4162                               theTopRigthPoint,
4163                               theBottomLeftPoint,
4164                               theBottomRigthPoint,
4165                               theState);
4166   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
4167     return NULL;
4168
4169   // Make a Python command
4170
4171   // The GetShapesOnCylinder() doesn't change object so no new function is required.
4172   Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
4173   lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
4174   lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
4175   lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
4176   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
4177
4178   GEOM::TPythonDump(aFunction, /*append=*/true)
4179     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
4180     << theShape << ", "
4181     << TopAbs_ShapeEnum(theShapeType) << ", "
4182     << theTopLeftPoint << ", "
4183     << theTopRigthPoint << ", "
4184     << theBottomLeftPoint << ", "
4185     << theBottomRigthPoint << ", "
4186     << theState << ")";
4187
4188   SetErrorCode(OK);
4189   return aSeqOfIDs;
4190 }
4191
4192 //=============================================================================
4193 /*!
4194  *  case GetInPlace:
4195  *  default:
4196  */
4197 //=============================================================================
4198 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
4199                                                             Handle(GEOM_Object) theShapeWhat)
4200 {
4201   SetErrorCode(KO);
4202
4203   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4204
4205   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4206   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4207
4208   if (aWhere.IsNull() || aWhat.IsNull()) {
4209     SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4210     return NULL;
4211   }
4212
4213   // Searching for the sub-shapes inside the ShapeWhere shape
4214   GEOMAlgo_GetInPlace aGIP;
4215
4216   if (!GEOMAlgo_GetInPlaceAPI::GetInPlace(aWhere, aWhat, aGIP)) {
4217     SetErrorCode("Error in GEOMAlgo_GetInPlace");
4218     return NULL;
4219   }
4220
4221   // Add direct result.
4222   TopTools_ListOfShape        aLSA;
4223   const TopoDS_Shape         &aShapeResult = aGIP.Result();
4224   TopTools_MapOfShape         aMFence;
4225   TopTools_IndexedMapOfShape  aWhereIndices;
4226
4227   TopExp::MapShapes(aWhere, aWhereIndices);
4228
4229   if (aShapeResult.IsNull() == Standard_False) {
4230     TopoDS_Iterator anIt(aShapeResult);
4231
4232     for (; anIt.More(); anIt.Next()) {
4233       const TopoDS_Shape &aPart = anIt.Value();
4234
4235       if(aWhereIndices.Contains(aPart) && aMFence.Add(aPart)) {
4236         aLSA.Append(aPart);
4237       }
4238     }
4239   }
4240
4241   if (aLSA.Extent() == 0) {
4242     SetErrorCode(NOT_FOUND_ANY); // Not found any Results
4243     return NULL;
4244   }
4245
4246   Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent());
4247   TopTools_ListIteratorOfListOfShape anIterModif (aLSA);
4248   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4249     if (aWhereIndices.Contains(anIterModif.Value())) {
4250       aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value()));
4251     }
4252     else {
4253       SetErrorCode("Error: wrong sub-shape returned");
4254       return NULL;
4255     }
4256   }
4257
4258   //Add a new object
4259   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4260   if (aResult.IsNull()) {
4261     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4262     return NULL;
4263   }
4264
4265   if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) {
4266     //Set a GROUP type
4267     aResult->SetType(GEOM_GROUP);
4268
4269     //Set a sub-shape type
4270     TopoDS_Shape aFirstFound = aLSA.First();
4271     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4272
4273     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4274     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4275   }
4276
4277   //Make a Python command
4278   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4279
4280   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4281     << theShapeWhere << ", " << theShapeWhat << ", True)";
4282
4283   SetErrorCode(OK);
4284   return aResult;
4285 }
4286
4287 //=============================================================================
4288 /*!
4289  *  case GetInPlaceOld:
4290  *  default:
4291  */
4292 //=============================================================================
4293 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld
4294                             (Handle(GEOM_Object) theShapeWhere,
4295                              Handle(GEOM_Object) theShapeWhat)
4296 {
4297   SetErrorCode(KO);
4298
4299   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4300
4301   TopoDS_Shape           aWhere = theShapeWhere->GetValue();
4302   TopoDS_Shape           aWhat  = theShapeWhat->GetValue();
4303   TopTools_ListOfShape   aModifiedList;
4304   const Standard_Integer iErr   =
4305     GEOMAlgo_GetInPlaceAPI::GetInPlaceOld(aWhere, aWhat, aModifiedList);
4306
4307   if (iErr) {
4308     switch (iErr) {
4309       case 1:
4310         SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
4311         break;
4312       case 2:
4313         SetErrorCode
4314           ("Error: An attempt to extract a shape of not supported type.");
4315         break;
4316       case 3:
4317         SetErrorCode(NOT_FOUND_ANY);
4318         break;
4319       default:
4320         SetErrorCode("Shape driver failed");
4321         break;
4322     }
4323
4324     return NULL;
4325   }
4326
4327   TopTools_IndexedMapOfShape aWhereIndices;
4328   TopExp::MapShapes(aWhere, aWhereIndices);
4329
4330   Handle(TColStd_HArray1OfInteger)   aModifiedArray =
4331     new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
4332   TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4333   Standard_Integer                   imod;
4334
4335   for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
4336     const Standard_Integer anIndex =
4337       aWhereIndices.FindIndex(anIterModif.Value());
4338
4339     aModifiedArray->SetValue(imod, anIndex);
4340   }
4341
4342   //Add a new object
4343   Handle(GEOM_Object) aResult =
4344     GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4345
4346   if (aResult.IsNull()) {
4347     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4348     return NULL;
4349   }
4350
4351   if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) {
4352     //Set a GROUP type
4353     aResult->SetType(GEOM_GROUP);
4354
4355     //Set a sub-shape type
4356     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4357     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4358
4359     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4360     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4361   }
4362
4363   //Make a Python command
4364   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4365
4366   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
4367     << theShapeWhere << ", " << theShapeWhat << ", False)";
4368
4369   SetErrorCode(OK);
4370
4371   return aResult;
4372 }
4373
4374 //=======================================================================
4375 //function : GetInPlaceByHistory
4376 //purpose  :
4377 //=======================================================================
4378 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
4379                                           (Handle(GEOM_Object) theShapeWhere,
4380                                            Handle(GEOM_Object) theShapeWhat)
4381 {
4382   SetErrorCode(KO);
4383
4384   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4385
4386   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4387   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4388
4389   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4390
4391   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
4392   if (aWhereFunction.IsNull()) return NULL;
4393
4394   //Fill array of indices
4395   TopTools_IndexedMapOfShape aWhereIndices;
4396
4397   TopExp::MapShapes(aWhere, aWhereIndices);
4398
4399   // process shape
4400   TopTools_ListOfShape aModifiedList;
4401   bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceByHistory
4402     (aWhereFunction, aWhereIndices, aWhat, aModifiedList);
4403
4404   if (!isFound || aModifiedList.Extent() < 1) {
4405     SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
4406     return NULL;
4407   }
4408
4409   Standard_Integer nbFound = aModifiedList.Extent();
4410   TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList);
4411   if ( nbFound > 1 )
4412   {
4413     // remove sub-shapes inappropriate for group creation
4414     TopAbs_ShapeEnum subType = TopAbs_SHAPE;
4415     while ( anIterModif.More() ) {
4416       TopAbs_ShapeEnum type = anIterModif.Value().ShapeType();
4417       bool okForGroup = ( type == TopAbs_VERTEX || type == TopAbs_EDGE ||
4418                           type == TopAbs_FACE   || type == TopAbs_SOLID );
4419       if ( okForGroup ) {
4420         if ( subType == TopAbs_SHAPE )
4421           subType = type;
4422         else
4423           okForGroup = ( subType == type );
4424       }
4425       if ( okForGroup )
4426         anIterModif.Next();
4427       else
4428         aModifiedList.Remove( anIterModif );
4429       nbFound -= ( !okForGroup );
4430     }
4431     if ( nbFound == 0 ) {
4432       SetErrorCode("Error: result found but it's type is inappropriate for group creation.");
4433       return NULL;
4434     }
4435   }
4436
4437   Handle(TColStd_HArray1OfInteger) aModifiedArray =
4438     new TColStd_HArray1OfInteger( 1, nbFound );
4439   anIterModif.Initialize(aModifiedList);
4440   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
4441     aModifiedArray->SetValue
4442         (imod, aWhereIndices.FindIndex(anIterModif.Value()));
4443
4444   //Add a new object
4445   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
4446   if (aResult.IsNull()) {
4447     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
4448     return NULL;
4449   }
4450
4451   if (aModifiedArray->Length() > 1) {
4452     //Set a GROUP type
4453     aResult->SetType(GEOM_GROUP);
4454
4455     //Set a sub-shape type
4456     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
4457     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
4458
4459     TDF_Label aFreeLabel = aResult->GetFreeLabel();
4460     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
4461   }
4462
4463   //Make a Python command
4464   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
4465
4466   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
4467                                << theShapeWhere << ", " << theShapeWhat << ")";
4468
4469   SetErrorCode(OK);
4470   return aResult;
4471 }
4472
4473 //=======================================================================
4474 //function : isSameEdge
4475 //purpose  : Returns True if two edges coincide
4476 //=======================================================================
4477 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
4478 {
4479   TopoDS_Vertex V11, V12, V21, V22;
4480   TopExp::Vertices(theEdge1, V11, V12);
4481   TopExp::Vertices(theEdge2, V21, V22);
4482   gp_Pnt P11 = BRep_Tool::Pnt(V11);
4483   gp_Pnt P12 = BRep_Tool::Pnt(V12);
4484   gp_Pnt P21 = BRep_Tool::Pnt(V21);
4485   gp_Pnt P22 = BRep_Tool::Pnt(V22);
4486   bool coincide = false;
4487
4488   //Check that ends of edges coincide
4489   if(P11.Distance(P21) <= MAX_TOLERANCE) {
4490     if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
4491   }
4492   else if(P11.Distance(P22) <= MAX_TOLERANCE) {
4493     if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
4494   }
4495
4496   if(!coincide) return false;
4497
4498   if (BRep_Tool::Degenerated(theEdge1))
4499     if (BRep_Tool::Degenerated(theEdge2)) return true;
4500     else return false;
4501   else
4502     if (BRep_Tool::Degenerated(theEdge2)) return false;
4503
4504   double U11, U12, U21, U22;
4505   Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
4506   Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
4507
4508   //Check that both edges has the same geometry
4509   double range = U12-U11;
4510   double U = U11+ range/3.0;
4511   gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
4512   U = U11+range*2.0/3.0;
4513   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
4514
4515   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
4516     return false;
4517
4518   if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4519
4520   if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
4521     return false;
4522
4523   if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
4524
4525   return true;
4526 }
4527
4528 #include <TopoDS_TShape.hxx>
4529 //=======================================================================
4530 //function : isSameFace
4531 //purpose  : Returns True if two faces coincide
4532 //=======================================================================
4533 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
4534 {
4535   TopExp_Explorer E(theFace1, TopAbs_EDGE);
4536   TopTools_ListOfShape LS1, LS2;
4537   for(; E.More(); E.Next()) LS1.Append(E.Current());
4538
4539   E.Init(theFace2, TopAbs_EDGE);
4540   for(; E.More(); E.Next()) LS2.Append(E.Current());
4541
4542   //Compare the number of edges in the faces
4543   if(LS1.Extent() != LS2.Extent()) return false;
4544
4545   double aMin = RealFirst(), aMax = RealLast();
4546   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4547   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4548
4549   for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
4550     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4551     if(P.X() < xminB1) xminB1 = P.X();
4552     if(P.Y() < yminB1) yminB1 = P.Y();
4553     if(P.Z() < zminB1) zminB1 = P.Z();
4554     if(P.X() > xmaxB1) xmaxB1 = P.X();
4555     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4556     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4557   }
4558
4559   for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
4560     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4561     if(P.X() < xminB2) xminB2 = P.X();
4562     if(P.Y() < yminB2) yminB2 = P.Y();
4563     if(P.Z() < zminB2) zminB2 = P.Z();
4564     if(P.X() > xmaxB2) xmaxB2 = P.X();
4565     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4566     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4567   }
4568
4569   //Compare the bounding boxes of both faces
4570   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4571     return false;
4572
4573   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4574     return false;
4575
4576   Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
4577   Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
4578
4579   //Check if there a coincidence of two surfaces at least in two points
4580   double U11, U12, V11, V12, U21, U22, V21, V22;
4581   BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
4582   BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
4583
4584   double rangeU = U12-U11;
4585   double rangeV = V12-V11;
4586   double U = U11 + rangeU/3.0;
4587   double V = V11 + rangeV/3.0;
4588   gp_Pnt P1 = S1->Value(U, V);
4589   U = U11+rangeU*2.0/3.0;
4590   V = V11+rangeV*2.0/3.0;
4591   gp_Pnt P2 = S1->Value(U, V);
4592
4593   if (!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4594     return false;
4595
4596   if (P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
4597
4598   if (!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
4599     return false;
4600
4601   if (P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
4602
4603   //Check that each edge of the Face1 has a counterpart in the Face2
4604   TopTools_MapOfOrientedShape aMap;
4605   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4606   for(; LSI1.More(); LSI1.Next()) {
4607     TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
4608     bool isFound = false;
4609     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4610     for(; LSI2.More(); LSI2.Next()) {
4611       TopoDS_Shape aValue = LSI2.Value();
4612       if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
4613       if(isSameEdge(E, TopoDS::Edge(aValue))) {
4614         aMap.Add(aValue);
4615         isFound = true;
4616         break;
4617       }
4618     }
4619     if(!isFound) return false;
4620   }
4621
4622   return true;
4623 }
4624
4625 //=======================================================================
4626 //function : isSameSolid
4627 //purpose  : Returns True if two solids coincide
4628 //=======================================================================
4629 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
4630 {
4631   TopExp_Explorer E(theSolid1, TopAbs_FACE);
4632   TopTools_ListOfShape LS1, LS2;
4633   for(; E.More(); E.Next()) LS1.Append(E.Current());
4634   E.Init(theSolid2, TopAbs_FACE);
4635   for(; E.More(); E.Next()) LS2.Append(E.Current());
4636
4637   if(LS1.Extent() != LS2.Extent()) return false;
4638
4639   double aMin = RealFirst(), aMax = RealLast();
4640   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
4641   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
4642
4643   for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
4644     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4645     if(P.X() < xminB1) xminB1 = P.X();
4646     if(P.Y() < yminB1) yminB1 = P.Y();
4647     if(P.Z() < zminB1) zminB1 = P.Z();
4648     if(P.X() > xmaxB1) xmaxB1 = P.X();
4649     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
4650     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
4651   }
4652
4653   for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
4654     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4655     if(P.X() < xminB2) xminB2 = P.X();
4656     if(P.Y() < yminB2) yminB2 = P.Y();
4657     if(P.Z() < zminB2) zminB2 = P.Z();
4658     if(P.X() > xmaxB2) xmaxB2 = P.X();
4659     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
4660     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
4661   }
4662
4663   //Compare the bounding boxes of both solids
4664   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
4665     return false;
4666
4667   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
4668     return false;
4669
4670   //Check that each face of the Solid1 has a counterpart in the Solid2
4671   TopTools_MapOfOrientedShape aMap;
4672   TopTools_ListIteratorOfListOfShape LSI1(LS1);
4673   for(; LSI1.More(); LSI1.Next()) {
4674     TopoDS_Face F = TopoDS::Face(LSI1.Value());
4675     bool isFound = false;
4676     TopTools_ListIteratorOfListOfShape LSI2(LS2);
4677     for(; LSI2.More(); LSI2.Next()) {
4678       if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
4679       if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
4680         aMap.Add(LSI2.Value());
4681         isFound = true;
4682         break;
4683       }
4684     }
4685     if(!isFound) return false;
4686   }
4687
4688   return true;
4689 }
4690
4691 //=======================================================================
4692 //function : GetSame
4693 //purpose  :
4694 //=======================================================================
4695 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
4696                                                         const Handle(GEOM_Object)& theShapeWhat)
4697 {
4698   SetErrorCode(KO);
4699   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4700
4701   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4702   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4703
4704   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4705
4706   int anIndex = -1;
4707   bool isFound = false;
4708   TopoDS_Shape aSubShape;
4709   TopTools_MapOfShape aMap;
4710
4711   if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4712     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4713     if (It.More()) aWhat = It.Value();
4714     It.Next();
4715     if (It.More()) {
4716       SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4717       return NULL;
4718     }
4719   }
4720
4721   switch (aWhat.ShapeType()) {
4722     case TopAbs_VERTEX: {
4723       aSubShape = getSameVertex(aWhere, TopoDS::Vertex(aWhat));
4724       isFound   = !aSubShape.IsNull();
4725       break;
4726                         }
4727     case TopAbs_EDGE: {
4728       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4729       TopExp_Explorer E(aWhere, TopAbs_EDGE);
4730       for(; E.More(); E.Next()) {
4731         if(!aMap.Add(E.Current())) continue;
4732         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4733           aSubShape = E.Current();
4734           isFound = true;
4735           break;
4736         }
4737       }
4738       break;
4739                       }
4740     case TopAbs_FACE: {
4741       TopoDS_Face aFace = TopoDS::Face(aWhat);
4742       TopExp_Explorer E(aWhere, TopAbs_FACE);
4743       for(; E.More(); E.Next()) {
4744         if(!aMap.Add(E.Current())) continue;
4745         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
4746           aSubShape = E.Current();
4747           isFound = true;
4748           break;
4749         }
4750       }
4751       break;
4752                       }
4753     case TopAbs_SOLID: {
4754       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
4755       TopExp_Explorer E(aWhere, TopAbs_SOLID);
4756       for(; E.More(); E.Next()) {
4757         if(!aMap.Add(E.Current())) continue;
4758         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
4759           aSubShape = E.Current();
4760           isFound = true;
4761           break;
4762         }
4763       }
4764       break;
4765                        }
4766     default:
4767       return NULL;
4768   }
4769
4770   if (isFound) {
4771     TopTools_IndexedMapOfShape anIndices;
4772     TopExp::MapShapes(aWhere, anIndices);
4773     if (anIndices.Contains(aSubShape))
4774       anIndex = anIndices.FindIndex(aSubShape);
4775   }
4776
4777   if (anIndex < 0) return NULL;
4778
4779   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
4780
4781   anArray->SetValue(1, anIndex);
4782
4783   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
4784   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
4785
4786   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
4787     << theShapeWhere << ", " << theShapeWhat << ")";
4788
4789   SetErrorCode(OK);
4790
4791   return aResult;
4792 }
4793
4794
4795 //=======================================================================
4796 //function : GetSameIDs
4797 //purpose  :
4798 //=======================================================================
4799 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs
4800                                                        (const Handle(GEOM_Object)& theShapeWhere,
4801                                                         const Handle(GEOM_Object)& theShapeWhat)
4802 {
4803   SetErrorCode(KO);
4804   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
4805
4806   TopoDS_Shape aWhere = theShapeWhere->GetValue();
4807   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
4808
4809   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
4810
4811   TopTools_ListOfShape listShape;
4812   TopTools_MapOfShape aMap;
4813
4814   if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) {
4815     TopoDS_Iterator It (aWhat, Standard_True, Standard_True);
4816     if (It.More()) aWhat = It.Value();
4817     It.Next();
4818     if (It.More()) {
4819       SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument");
4820       return NULL;
4821     }
4822   }
4823
4824   switch (aWhat.ShapeType()) {
4825     case TopAbs_VERTEX: {
4826       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
4827       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
4828       for(; E.More(); E.Next()) {
4829         if(!aMap.Add(E.Current())) continue;
4830         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
4831         if(P.Distance(P2) <= MAX_TOLERANCE) {
4832           listShape.Append(E.Current());
4833         }
4834       }
4835       break;
4836                         }
4837     case TopAbs_EDGE: {
4838       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
4839       TopExp_Explorer E(aWhere, TopAbs_EDGE);
4840       for(; E.More(); E.Next()) {
4841         if(!aMap.Add(E.Current())) continue;
4842         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
4843           listShape.Append(E.Current());
4844         }
4845       }
4846       break;
4847                       }
4848     case TopAbs_FACE: {
4849       TopoDS_Face aFace = TopoDS::Face(aWhat);
4850       TopExp_Explorer E(aWhere, TopAbs_FACE);
4851       for(; E.More(); E.Next()) {
4852         if(!aMap.Add(E.Current())) continue;
4853         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
4854           listShape.Append(E.Current());
4855         }
4856       }
4857       break;
4858                       }
4859     case TopAbs_SOLID: {
4860       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
4861       TopExp_Explorer E(aWhere, TopAbs_SOLID);
4862       for(; E.More(); E.Next()) {
4863         if(!aMap.Add(E.Current())) continue;
4864         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
4865           listShape.Append(E.Current());
4866         }
4867       }
4868       break;
4869                        }
4870     default:
4871       return NULL;
4872   }
4873
4874   if ( !listShape.IsEmpty() ) {
4875     TopTools_IndexedMapOfShape anIndices;
4876     TopExp::MapShapes(aWhere, anIndices);
4877     TopTools_ListIteratorOfListOfShape itSub (listShape);
4878     Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
4879     for (; itSub.More(); itSub.Next()) {
4880       if (anIndices.Contains(itSub.Value()))
4881         aSeq->Append(anIndices.FindIndex(itSub.Value()));
4882     }
4883     SetErrorCode(OK);
4884     // The GetSameIDs() doesn't change object so no new function is required.
4885     Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction();
4886
4887   // Make a Python command
4888   GEOM::TPythonDump(aFunction, /*append=*/true)
4889     << "listSameIDs = geompy.GetSameIDs("
4890     << theShapeWhere << ", "
4891     << theShapeWhat << ")";
4892     return aSeq;
4893   } else {
4894     SetErrorCode(NOT_FOUND_ANY);
4895     return NULL;
4896   }
4897 }
4898
4899 //=======================================================================
4900 //function : ExtendEdge
4901 //purpose  :
4902 //=======================================================================
4903 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendEdge
4904                                       (const Handle(GEOM_Object) &theEdge,
4905                                        const Standard_Real        theMin,
4906                                        const Standard_Real        theMax)
4907 {
4908   SetErrorCode(KO);
4909
4910   if (theEdge.IsNull()) {
4911     return NULL;
4912   }
4913
4914   //Add a new Edge object
4915   Handle(GEOM_Object) aResEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
4916
4917   //Add a new Vector function
4918   Handle(GEOM_Function) aFunction =
4919     aResEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_UV);
4920
4921   //Check if the function is set correctly
4922   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
4923     return NULL;
4924   }
4925
4926   GEOMImpl_IShapeExtend aCI (aFunction);
4927
4928   Handle(GEOM_Function) anEdge = theEdge->GetLastFunction();
4929
4930   if (anEdge.IsNull()) {
4931     return NULL;
4932   }
4933
4934   aCI.SetShape(anEdge);
4935   aCI.SetUMin(theMin);
4936   aCI.SetUMax(theMax);
4937
4938   //Compute the Edge value
4939   try {
4940     OCC_CATCH_SIGNALS;
4941     if (!GetSolver()->ComputeFunction(aFunction)) {
4942       SetErrorCode("Shape driver failed");
4943
4944       return NULL;
4945     }
4946   }
4947   catch (Standard_Failure) {
4948     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
4949     SetErrorCode(aFail->GetMessageString());
4950
4951     return NULL;
4952   }
4953
4954   //Make a Python command
4955   GEOM::TPythonDump(aFunction)
4956              << aResEdge  << " = geompy.ExtendEdge("
4957              << theEdge << ", " << theMin << ", " << theMax << ")";
4958
4959   SetErrorCode(OK);
4960
4961   return aResEdge;
4962 }
4963
4964 //=======================================================================
4965 //function : ExtendFace
4966 //purpose  :
4967 //=======================================================================
4968 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendFace
4969                                       (const Handle(GEOM_Object) &theFace,
4970                                        const Standard_Real        theUMin,
4971                                        const Standard_Real        theUMax,
4972                                        const Standard_Real        theVMin,
4973                                        const Standard_Real        theVMax)
4974 {
4975   SetErrorCode(KO);
4976
4977   if (theFace.IsNull()) {
4978     return NULL;
4979   }
4980
4981   //Add a new Face object
4982   Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
4983
4984   //Add a new Vector function
4985   Handle(GEOM_Function) aFunction =
4986     aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_UV);
4987
4988   //Check if the function is set correctly
4989   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
4990     return NULL;
4991   }
4992
4993   GEOMImpl_IShapeExtend aCI (aFunction);
4994
4995   Handle(GEOM_Function) aFace = theFace->GetLastFunction();
4996
4997   if (aFace.IsNull()) {
4998     return NULL;
4999   }
5000
5001   aCI.SetShape(aFace);
5002   aCI.SetUMin(theUMin);
5003   aCI.SetUMax(theUMax);
5004   aCI.SetVMin(theVMin);
5005   aCI.SetVMax(theVMax);
5006
5007   //Compute the Face value
5008   try {
5009     OCC_CATCH_SIGNALS;
5010     if (!GetSolver()->ComputeFunction(aFunction)) {
5011       SetErrorCode("Shape driver failed");
5012
5013       return NULL;
5014     }
5015   }
5016   catch (Standard_Failure) {
5017     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
5018     SetErrorCode(aFail->GetMessageString());
5019
5020     return NULL;
5021   }
5022
5023   //Make a Python command
5024   GEOM::TPythonDump(aFunction)
5025              << aResFace  << " = geompy.ExtendFace("
5026              << theFace << ", " << theUMin << ", " << theUMax << ", "
5027              << theVMin << ", " << theVMax << ")";
5028
5029   SetErrorCode(OK);
5030
5031   return aResFace;
5032 }
5033
5034 //=======================================================================
5035 //function : MakeSurfaceFromFace
5036 //purpose  :
5037 //=======================================================================
5038 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSurfaceFromFace
5039                                       (const Handle(GEOM_Object) &theFace)
5040 {
5041   SetErrorCode(KO);
5042
5043   if (theFace.IsNull()) {
5044     return NULL;
5045   }
5046
5047   //Add a new Face object
5048   Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
5049
5050   //Add a new Vector function
5051   Handle(GEOM_Function) aFunction =
5052     aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), SURFACE_FROM_FACE);
5053
5054   //Check if the function is set correctly
5055   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
5056     return NULL;
5057   }
5058
5059   GEOMImpl_IShapeExtend aCI (aFunction);
5060
5061   Handle(GEOM_Function) aFace = theFace->GetLastFunction();
5062
5063   if (aFace.IsNull()) {
5064     return NULL;
5065   }
5066
5067   aCI.SetShape(aFace);
5068
5069   //Compute the Face value
5070   try {
5071     OCC_CATCH_SIGNALS;
5072     if (!GetSolver()->ComputeFunction(aFunction)) {
5073       SetErrorCode("Shape driver failed");
5074
5075       return NULL;
5076     }
5077   }
5078   catch (Standard_Failure) {
5079     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
5080     SetErrorCode(aFail->GetMessageString());
5081
5082     return NULL;
5083   }
5084
5085   //Make a Python command
5086   GEOM::TPythonDump(aFunction)
5087              << aResFace  << " = geompy.MakeSurfaceFromFace("
5088              << theFace << ")";
5089
5090   SetErrorCode(OK);
5091
5092   return aResFace;
5093 }