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