Salome HOME
Merging with WPdev
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
8 //
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20
21 #include <Standard_Stream.hxx>
22
23 #include "GEOMImpl_IShapesOperations.hxx"
24
25 #include "GEOMImpl_Types.hxx"
26
27 #include "GEOMImpl_VectorDriver.hxx"
28 #include "GEOMImpl_ShapeDriver.hxx"
29 #include "GEOMImpl_CopyDriver.hxx"
30 #include "GEOMImpl_GlueDriver.hxx"
31
32 #include "GEOMImpl_IVector.hxx"
33 #include "GEOMImpl_IShapes.hxx"
34 #include "GEOMImpl_IGlue.hxx"
35
36 #include "GEOMImpl_Block6Explorer.hxx"
37
38 #include "GEOM_Function.hxx"
39 #include "GEOM_PythonDump.hxx"
40
41 #include "GEOMAlgo_FinderShapeOn1.hxx"
42 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
43 #include "GEOMAlgo_FinderShapeOn2.hxx"
44 #include "GEOMAlgo_ClsfBox.hxx"
45 //#include "GEOMAlgo_ClsfSurf.hxx"
46
47 #include "utilities.h"
48 #include "OpUtil.hxx"
49 #include "Utils_ExceptHandlers.hxx"
50
51 #include <TFunction_DriverTable.hxx>
52 #include <TFunction_Driver.hxx>
53 #include <TFunction_Logbook.hxx>
54 #include <TDataStd_Integer.hxx>
55 #include <TDataStd_IntegerArray.hxx>
56 #include <TDF_Tool.hxx>
57
58 #include <BRepExtrema_ExtCF.hxx>
59
60 #include <BRep_Tool.hxx>
61 #include <BRepTools.hxx>
62 #include <BRepGProp.hxx>
63 #include <BRepAdaptor_Curve.hxx>
64 #include <BRepAdaptor_Surface.hxx>
65 #include <BRepBndLib.hxx>
66 #include <BRepBuilderAPI_MakeFace.hxx>
67 #include <BRepMesh_IncrementalMesh.hxx>
68
69 #include <TopAbs.hxx>
70 #include <TopExp.hxx>
71 #include <TopoDS.hxx>
72 #include <TopoDS_Shape.hxx>
73 #include <TopoDS_Solid.hxx>
74 #include <TopoDS_Face.hxx>
75 #include <TopoDS_Edge.hxx>
76 #include <TopoDS_Vertex.hxx>
77 #include <TopoDS_Iterator.hxx>
78 #include <TopExp_Explorer.hxx>
79 #include <TopLoc_Location.hxx>
80 #include <TopTools_MapOfShape.hxx>
81 #include <TopTools_MapOfOrientedShape.hxx>
82 #include <TopTools_Array1OfShape.hxx>
83 #include <TopTools_ListIteratorOfListOfShape.hxx>
84 #include <TopTools_IndexedMapOfShape.hxx>
85
86 #include <Geom_Surface.hxx>
87 #include <Geom_Plane.hxx>
88 #include <Geom_SphericalSurface.hxx>
89 #include <Geom_CylindricalSurface.hxx>
90 #include <GeomAdaptor_Surface.hxx>
91
92 #include <GeomLib_Tool.hxx>
93 #include <Geom2d_Curve.hxx>
94
95 #include <Bnd_Box.hxx>
96 #include <GProp_GProps.hxx>
97 #include <gp_Pnt.hxx>
98 #include <gp_Lin.hxx>
99 #include <TColStd_ListOfInteger.hxx>
100 #include <TColStd_ListIteratorOfListOfInteger.hxx>
101 #include <TColStd_Array1OfReal.hxx>
102 #include <TColStd_HArray1OfInteger.hxx>
103
104 #include <vector>
105
106 #include <Standard_Failure.hxx>
107 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
108
109 //=============================================================================
110 /*!
111  *   constructor:
112  */
113 //=============================================================================
114 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
115 : GEOM_IOperations(theEngine, theDocID)
116 {
117   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
118 }
119
120 //=============================================================================
121 /*!
122  *  destructor
123  */
124 //=============================================================================
125 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
126 {
127   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
128 }
129
130
131 //=============================================================================
132 /*!
133  *  MakeEdge
134  */
135 //=============================================================================
136 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
137                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
138 {
139   SetErrorCode(KO);
140
141   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
142
143   //Add a new Edge object
144   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
145
146   //Add a new Vector function
147   Handle(GEOM_Function) aFunction =
148     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
149
150   //Check if the function is set correctly
151   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
152
153   GEOMImpl_IVector aPI (aFunction);
154
155   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
156   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
157   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
158
159   aPI.SetPoint1(aRef1);
160   aPI.SetPoint2(aRef2);
161
162   //Compute the Edge value
163   try {
164 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
165     OCC_CATCH_SIGNALS;
166 #endif
167     if (!GetSolver()->ComputeFunction(aFunction)) {
168       SetErrorCode("Vector driver failed");
169       return NULL;
170     }
171   }
172   catch (Standard_Failure) {
173     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
174     SetErrorCode(aFail->GetMessageString());
175     return NULL;
176   }
177
178   //Make a Python command
179   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
180                                << thePnt1 << ", " << thePnt2 << ")";
181
182   SetErrorCode(OK);
183   return anEdge;
184 }
185
186 //=============================================================================
187 /*!
188  *  MakeWire
189  */
190 //=============================================================================
191 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
192                              (list<Handle(GEOM_Object)> theShapes)
193 {
194   return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
195 }
196
197 //=============================================================================
198 /*!
199  *  MakeFace
200  */
201 //=============================================================================
202 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
203                                                           const bool isPlanarWanted)
204 {
205   SetErrorCode(KO);
206
207   if (theWire.IsNull()) return NULL;
208
209   //Add a new Face object
210   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
211
212   //Add a new Shape function for creation of a face from a wire
213   Handle(GEOM_Function) aFunction =
214     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
215   if (aFunction.IsNull()) return NULL;
216
217   //Check if the function is set correctly
218   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
219
220   GEOMImpl_IShapes aCI (aFunction);
221
222   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
223
224   if (aRefWire.IsNull()) return NULL;
225
226   aCI.SetBase(aRefWire);
227   aCI.SetIsPlanar(isPlanarWanted);
228
229   //Compute the Face value
230   try {
231 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
232     OCC_CATCH_SIGNALS;
233 #endif
234     if (!GetSolver()->ComputeFunction(aFunction)) {
235       SetErrorCode("Shape driver failed to compute a face");
236       return NULL;
237     }
238   }
239   catch (Standard_Failure) {
240     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
241     SetErrorCode(aFail->GetMessageString());
242     return NULL;
243   }
244
245   //Make a Python command
246   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
247     << theWire << ", " << (int)isPlanarWanted << ")";
248
249   SetErrorCode(OK);
250   return aFace;
251 }
252
253 //=============================================================================
254 /*!
255  *  MakeFaceWires
256  */
257 //=============================================================================
258 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
259                              (list<Handle(GEOM_Object)> theShapes,
260                               const bool isPlanarWanted)
261 {
262   SetErrorCode(KO);
263
264   //Add a new object
265   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
266
267   //Add a new function
268   Handle(GEOM_Function) aFunction =
269     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
270   if (aFunction.IsNull()) return NULL;
271
272   //Check if the function is set correctly
273   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
274
275   GEOMImpl_IShapes aCI (aFunction);
276
277   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
278
279   // Shapes
280   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
281   for (; it != theShapes.end(); it++) {
282     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
283     if (aRefSh.IsNull()) {
284       SetErrorCode("NULL argument shape for the face construction");
285       return NULL;
286     }
287     aShapesSeq->Append(aRefSh);
288   }
289   aCI.SetShapes(aShapesSeq);
290
291   aCI.SetIsPlanar(isPlanarWanted);
292
293   //Compute the shape
294   try {
295 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
296     OCC_CATCH_SIGNALS;
297 #endif
298     if (!GetSolver()->ComputeFunction(aFunction)) {
299       SetErrorCode("Shape driver failed");
300       return NULL;
301     }
302   }
303   catch (Standard_Failure) {
304     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
305     SetErrorCode(aFail->GetMessageString());
306     return NULL;
307   }
308
309   //Make a Python command
310   GEOM::TPythonDump pd (aFunction);
311   pd << aShape << " = geompy.MakeFaceWires([";
312
313   // Shapes
314   it = theShapes.begin();
315   if (it != theShapes.end()) {
316     pd << (*it++);
317     while (it != theShapes.end()) {
318       pd << ", " << (*it++);
319     }
320   }
321   pd << "], " << (int)isPlanarWanted << ")";
322
323   SetErrorCode(OK);
324   return aShape;
325 }
326
327 //=============================================================================
328 /*!
329  *  MakeShell
330  */
331 //=============================================================================
332 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
333                              (list<Handle(GEOM_Object)> theShapes)
334 {
335   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
336 }
337
338 //=============================================================================
339 /*!
340  *  MakeSolidShells
341  */
342 //=============================================================================
343 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
344                              (list<Handle(GEOM_Object)> theShapes)
345 {
346   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid");
347 }
348
349 //=============================================================================
350 /*!
351  *  MakeSolidShell
352  */
353 //=============================================================================
354 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
355 {
356   SetErrorCode(KO);
357
358   if (theShell.IsNull()) return NULL;
359
360   //Add a new Solid object
361   Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
362
363   //Add a new Solid function for creation of a solid from a shell
364   Handle(GEOM_Function) aFunction =
365     aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
366   if (aFunction.IsNull()) return NULL;
367
368   //Check if the function is set correctly
369   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
370
371   GEOMImpl_IShapes aCI (aFunction);
372
373   Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
374
375   if (aRefShell.IsNull()) return NULL;
376
377   aCI.SetBase(aRefShell);
378
379   //Compute the Solid value
380   try {
381 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
382     OCC_CATCH_SIGNALS;
383 #endif
384     if (!GetSolver()->ComputeFunction(aFunction)) {
385       SetErrorCode("Solid driver failed");
386       return NULL;
387     }
388   }
389   catch (Standard_Failure) {
390     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
391     SetErrorCode(aFail->GetMessageString());
392     return NULL;
393   }
394
395   //Make a Python command
396   GEOM::TPythonDump(aFunction) << aSolid
397     << " = geompy.MakeSolid(" << theShell << ")";
398
399   SetErrorCode(OK);
400   return aSolid;
401 }
402
403 //=============================================================================
404 /*!
405  *  MakeCompound
406  */
407 //=============================================================================
408 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
409                              (list<Handle(GEOM_Object)> theShapes)
410 {
411   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
412 }
413
414 //=============================================================================
415 /*!
416  *  MakeShape
417  */
418 //=============================================================================
419 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
420                              (list<Handle(GEOM_Object)>      theShapes,
421                               const Standard_Integer         theObjectType,
422                               const Standard_Integer         theFunctionType,
423                               const TCollection_AsciiString& theMethodName)
424 {
425   SetErrorCode(KO);
426
427   //Add a new object
428   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
429
430   //Add a new function
431   Handle(GEOM_Function) aFunction =
432     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
433   if (aFunction.IsNull()) return NULL;
434
435   //Check if the function is set correctly
436   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
437
438   GEOMImpl_IShapes aCI (aFunction);
439
440   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
441
442   // Shapes
443   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
444   for (; it != theShapes.end(); it++) {
445     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
446     if (aRefSh.IsNull()) {
447       SetErrorCode("NULL argument shape for the shape construction");
448       return NULL;
449     }
450     aShapesSeq->Append(aRefSh);
451   }
452   aCI.SetShapes(aShapesSeq);
453
454   //Compute the shape
455   try {
456 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
457     OCC_CATCH_SIGNALS;
458 #endif
459     if (!GetSolver()->ComputeFunction(aFunction)) {
460       SetErrorCode("Shape driver failed");
461       return NULL;
462     }
463   }
464   catch (Standard_Failure) {
465     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
466     SetErrorCode(aFail->GetMessageString());
467     return NULL;
468   }
469
470   //Make a Python command
471   GEOM::TPythonDump pd (aFunction);
472   pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
473
474   // Shapes
475   it = theShapes.begin();
476   if (it != theShapes.end()) {
477     pd << (*it++);
478     while (it != theShapes.end()) {
479       pd << ", " << (*it++);
480     }
481   }
482   pd << "])";
483
484   SetErrorCode(OK);
485   return aShape;
486 }
487
488 //=============================================================================
489 /*!
490  *  MakeGlueFaces
491  */
492 //=============================================================================
493 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
494                                                 (Handle(GEOM_Object) theShape,
495                                                  const Standard_Real theTolerance)
496 {
497   SetErrorCode(KO);
498
499   if (theShape.IsNull()) return NULL;
500
501   //Add a new Glued object
502   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
503
504   //Add a new Glue function
505   Handle(GEOM_Function) aFunction;
506   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
507   if (aFunction.IsNull()) return NULL;
508
509   //Check if the function is set correctly
510   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
511
512   GEOMImpl_IGlue aCI (aFunction);
513
514   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
515   if (aRefShape.IsNull()) return NULL;
516
517   aCI.SetBase(aRefShape);
518   aCI.SetTolerance(theTolerance);
519
520   //Compute the sub-shape value
521   Standard_Boolean isWarning = Standard_False;
522   try {
523 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
524     OCC_CATCH_SIGNALS;
525 #endif
526     if (!GetSolver()->ComputeFunction(aFunction)) {
527       SetErrorCode("Shape driver failed to glue faces");
528       return NULL;
529     }
530   }
531   catch (Standard_Failure) {
532     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
533     SetErrorCode(aFail->GetMessageString());
534     // to provide warning
535     if (!aFunction->GetValue().IsNull()) {
536       isWarning = Standard_True;
537     } else {
538       return NULL;
539     }
540   }
541
542   //Make a Python command
543   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
544     << theShape << ", " << theTolerance << ")";
545
546   // to provide warning
547   if (!isWarning) SetErrorCode(OK);
548   return aGlued;
549 }
550
551 //=============================================================================
552 /*!
553  *  MakeExplode
554  */
555 //=============================================================================
556 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
557                                           (Handle(GEOM_Object)    theShape,
558                                            const Standard_Integer theShapeType,
559                                            const Standard_Boolean isSorted)
560 {
561   SetErrorCode(KO);
562
563   if (theShape.IsNull()) return NULL;
564   TopoDS_Shape aShape = theShape->GetValue();
565   if (aShape.IsNull()) return NULL;
566
567   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
568   Handle(GEOM_Object) anObj;
569   Handle(GEOM_Function) aFunction;
570   TopTools_MapOfShape mapShape;
571   TopTools_ListOfShape listShape;
572
573   if (aShape.ShapeType() == TopAbs_COMPOUND &&
574       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
575        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
576        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
577     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
578     for (; It.More(); It.Next()) {
579       if (mapShape.Add(It.Value())) {
580         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
581             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
582           listShape.Append(It.Value());
583         }
584       }
585     }
586   } else {
587     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
588     for (; exp.More(); exp.Next())
589       if (mapShape.Add(exp.Current()))
590         listShape.Append(exp.Current());
591   }
592
593   if (listShape.IsEmpty()) {
594     SetErrorCode("The given shape has no sub-shapes of the requested type");
595     return aSeq;
596   }
597
598   if (isSorted)
599     SortShapes(listShape);
600
601   TopTools_IndexedMapOfShape anIndices;
602   TopExp::MapShapes(aShape, anIndices);
603   Handle(TColStd_HArray1OfInteger) anArray;
604
605   TopTools_ListIteratorOfListOfShape itSub (listShape);
606   TCollection_AsciiString anAsciiList, anEntry;
607   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
608     TopoDS_Shape aValue = itSub.Value();
609     anArray = new TColStd_HArray1OfInteger(1,1);
610     anArray->SetValue(1, anIndices.FindIndex(aValue));
611     anObj = GetEngine()->AddSubShape(theShape, anArray);
612     if (!anObj.IsNull()) {
613       aSeq->Append(anObj);
614
615       // for python command
616       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
617       anAsciiList += anEntry;
618       anAsciiList += ",";
619     }
620   }
621
622   //Make a Python command
623   anAsciiList.Trunc(anAsciiList.Length() - 1);
624
625   aFunction = theShape->GetLastFunction();
626
627   GEOM::TPythonDump pd (aFunction, /*append=*/true);
628   pd << "[" << anAsciiList.ToCString();
629   pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
630   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
631
632   SetErrorCode(OK);
633
634   return aSeq;
635 }
636
637 //=============================================================================
638 /*!
639  *  GetSubShapeAllIDs
640  */
641 //=============================================================================
642 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
643                                           (Handle(GEOM_Object)    theShape,
644                                            const Standard_Integer theShapeType,
645                                            const Standard_Boolean isSorted)
646 {
647   SetErrorCode(KO);
648
649   if (theShape.IsNull()) return NULL;
650   TopoDS_Shape aShape = theShape->GetValue();
651   if (aShape.IsNull()) return NULL;
652
653   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
654   TopTools_MapOfShape mapShape;
655   TopTools_ListOfShape listShape;
656
657   if (aShape.ShapeType() == TopAbs_COMPOUND &&
658       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
659        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
660        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
661     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
662     for (; It.More(); It.Next()) {
663       if (mapShape.Add(It.Value())) {
664         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
665             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
666           listShape.Append(It.Value());
667         }
668       }
669     }
670   } else {
671     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
672     for (; exp.More(); exp.Next())
673       if (mapShape.Add(exp.Current()))
674         listShape.Append(exp.Current());
675   }
676
677   if (listShape.IsEmpty()) {
678     SetErrorCode("The given shape has no sub-shapes of the requested type");
679     return aSeq;
680   }
681
682   if (isSorted)
683     SortShapes(listShape);
684
685   TopTools_IndexedMapOfShape anIndices;
686   TopExp::MapShapes(aShape, anIndices);
687   Handle(TColStd_HArray1OfInteger) anArray;
688
689   TopTools_ListIteratorOfListOfShape itSub (listShape);
690   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
691     TopoDS_Shape aValue = itSub.Value();
692     aSeq->Append(anIndices.FindIndex(aValue));
693   }
694
695   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
696
697   //Make a Python command
698   GEOM::TPythonDump pd (aFunction, /*append=*/true);
699   pd << "listSubShapeIDs = geompy.SubShapeAll";
700   pd << (isSorted ? "SortedIDs(" : "IDs(");
701   pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
702
703   SetErrorCode(OK);
704   return aSeq;
705 }
706
707 //=============================================================================
708 /*!
709  *  GetSubShape
710  */
711 //=============================================================================
712 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
713                                           (Handle(GEOM_Object)    theMainShape,
714                                            const Standard_Integer theID)
715 {
716   SetErrorCode(KO);
717
718   if (theMainShape.IsNull()) return NULL;
719
720   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
721   anArray->SetValue(1, theID);
722   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
723   if (anObj.IsNull()) {
724     SetErrorCode("Can not get a sub-shape with the given ID");
725     return NULL;
726   }
727
728   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
729
730   //Make a Python command
731   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
732                                << theMainShape << ", [" << theID << "])";
733
734   SetErrorCode(OK);
735   return anObj;
736 }
737
738 //=============================================================================
739 /*!
740  *  GetSubShapeIndex
741  */
742 //=============================================================================
743 Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape,
744                                                                Handle(GEOM_Object) theSubShape)
745 {
746   SetErrorCode(KO);
747
748   TopoDS_Shape aMainShape = theMainShape->GetValue();
749   TopoDS_Shape aSubShape = theSubShape->GetValue();
750
751   if (aMainShape.IsNull() || aSubShape.IsNull()) return -1;
752
753   TopTools_IndexedMapOfShape anIndices;
754   TopExp::MapShapes(aMainShape, anIndices);
755   if (anIndices.Contains(aSubShape)) {
756     SetErrorCode(OK);
757     return anIndices.FindIndex(aSubShape);
758   }
759
760   return -1;
761 }
762
763 //=============================================================================
764 /*!
765  *  GetTopologyIndex
766  */
767 //=============================================================================
768 Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape,
769                                                                Handle(GEOM_Object) theSubShape)
770 {
771   SetErrorCode(OK);
772
773   TopoDS_Shape aMainShape = theMainShape->GetValue();
774   TopoDS_Shape aSubShape = theSubShape->GetValue();
775
776   if (aMainShape.IsNull() || aSubShape.IsNull()) {
777     SetErrorCode("Null argument shape given");
778     return -1;
779   }
780
781   int index = 1;
782   if (aSubShape.ShapeType() == TopAbs_COMPOUND) {
783     TopoDS_Iterator it;
784     TopTools_ListOfShape CL;
785     CL.Append(aMainShape);
786     TopTools_ListIteratorOfListOfShape itC;
787     for (itC.Initialize(CL); itC.More(); itC.Next()) {
788       for (it.Initialize(itC.Value()); it.More(); it.Next()) {
789         if (it.Value().ShapeType() == TopAbs_COMPOUND) {
790           if (it.Value().IsSame(aSubShape))
791             return index;
792           else
793             index++;
794           CL.Append(it.Value());
795         }
796       }
797     }
798   } else {
799     TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType());
800     TopTools_MapOfShape M;
801     for (; anExp.More(); anExp.Next()) {
802       if (M.Add(anExp.Current())) {
803         if (anExp.Current().IsSame(aSubShape))
804           return index;
805         index++;
806       }
807     }
808   }
809
810   SetErrorCode("The sub-shape does not belong to the main shape");
811   return -1;
812 }
813
814 //=============================================================================
815 /*!
816  *  GetShapeTypeString
817  */
818 //=============================================================================
819 TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape)
820 {
821   SetErrorCode(KO);
822
823   TCollection_AsciiString aTypeName ("Null Shape");
824
825   TopoDS_Shape aShape = theShape->GetValue();
826   if (aShape.IsNull())
827     return aTypeName;
828
829   switch (aShape.ShapeType() )
830   {
831   case TopAbs_COMPOUND:
832     aTypeName = "Compound";
833     break;
834   case  TopAbs_COMPSOLID:
835     aTypeName = "Compound Solid";
836     break;
837   case TopAbs_SOLID:
838     aTypeName = "Solid";
839     break;
840   case TopAbs_SHELL:
841     aTypeName = "Shell";
842     break;
843   case TopAbs_FACE:
844     {
845       BRepAdaptor_Surface surf (TopoDS::Face(aShape));
846       if (surf.GetType() == GeomAbs_Plane)
847         aTypeName = "Plane";
848       else if (surf.GetType() == GeomAbs_Cylinder)
849         aTypeName = "Cylindrical Face";
850       else if (surf.GetType() == GeomAbs_Sphere)
851         aTypeName = "Spherical Face";
852       else if (surf.GetType() == GeomAbs_Torus)
853         aTypeName = "Toroidal Face";
854       else if (surf.GetType() == GeomAbs_Cone)
855         aTypeName = "Conical Face";
856       else
857         aTypeName = "GEOM::FACE";
858     }
859     break;
860   case TopAbs_WIRE:
861     aTypeName = "Wire";
862     break;
863   case TopAbs_EDGE:
864     {
865       BRepAdaptor_Curve curv (TopoDS::Edge(aShape));
866       if (curv.GetType() == GeomAbs_Line) {
867         if ((Abs(curv.FirstParameter()) >= 1E6) ||
868             (Abs(curv.LastParameter()) >= 1E6))
869           aTypeName = "Line";
870         else
871           aTypeName = "Edge" ;
872       } else if (curv.GetType() == GeomAbs_Circle) {
873         if (curv.IsClosed())
874           aTypeName = "Circle";
875         else
876           aTypeName = "Arc";
877       } else {
878         aTypeName = "Edge";
879       }
880     }
881     break;
882   case TopAbs_VERTEX:
883     aTypeName = "Vertex";
884     break;
885   case TopAbs_SHAPE:
886     aTypeName = "Shape";
887     break;
888   default:
889     aTypeName = "Shape of unknown type";
890   }
891
892   return aTypeName;
893 }
894
895
896 //=============================================================================
897 /*!
898  *  NumberOfFaces
899  */
900 //=============================================================================
901 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
902 {
903   SetErrorCode(KO);
904
905   Standard_Integer nb = 0;
906
907   if (theShape.IsNull()) return -1;
908   TopoDS_Shape aShape = theShape->GetValue();
909   if (aShape.IsNull()) return -1;
910
911   TopTools_MapOfShape mapShape;
912
913   TopExp_Explorer exp (aShape, TopAbs_FACE);
914   for (; exp.More(); exp.Next())
915     if (mapShape.Add(exp.Current()))
916       nb++;
917
918   SetErrorCode(OK);
919   return nb;
920 }
921
922 //=============================================================================
923 /*!
924  *  NumberOfEdges
925  */
926 //=============================================================================
927 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
928 {
929   SetErrorCode(KO);
930
931   Standard_Integer nb = 0;
932
933   if (theShape.IsNull()) return -1;
934   TopoDS_Shape aShape = theShape->GetValue();
935   if (aShape.IsNull()) return -1;
936
937   TopTools_MapOfShape mapShape;
938
939   TopExp_Explorer exp (aShape, TopAbs_EDGE);
940   for (; exp.More(); exp.Next())
941     if (mapShape.Add(exp.Current()))
942       nb++;
943
944   SetErrorCode(OK);
945   return nb;
946 }
947
948 //=============================================================================
949 /*!
950  *  ReverseShape
951  */
952 //=============================================================================
953 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
954 {
955   SetErrorCode(KO);
956
957   if (theShape.IsNull()) return NULL;
958
959   //Add a new reversed object
960   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
961
962   //Add a new Revese function
963   Handle(GEOM_Function) aFunction;
964   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
965   if (aFunction.IsNull()) return NULL;
966
967   //Check if the function is set correctly
968   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
969
970   GEOMImpl_IShapes aSI (aFunction);
971
972   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
973   if (aRefShape.IsNull()) return NULL;
974
975   aSI.SetBase(aRefShape);
976
977   //Compute the sub-shape value
978   try {
979 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
980     OCC_CATCH_SIGNALS;
981 #endif
982     if (!GetSolver()->ComputeFunction(aFunction)) {
983       SetErrorCode("Shape driver failed to reverse shape");
984       return NULL;
985     }
986   }
987   catch (Standard_Failure) {
988     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
989     SetErrorCode(aFail->GetMessageString());
990     return NULL;
991   }
992
993   //Make a Python command
994   GEOM::TPythonDump(aFunction) << aReversed
995     << " = geompy.ChangeOrientation(" << theShape << ")";
996
997   SetErrorCode(OK);
998   return aReversed;
999 }
1000
1001 //=============================================================================
1002 /*!
1003  *  GetFreeFacesIDs
1004  */
1005 //=============================================================================
1006 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
1007                                                  (Handle(GEOM_Object) theShape)
1008 {
1009   SetErrorCode(KO);
1010
1011   if (theShape.IsNull()) return NULL;
1012   TopoDS_Shape aShape = theShape->GetValue();
1013   if (aShape.IsNull()) return NULL;
1014
1015   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
1016
1017   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
1018   GEOMImpl_Block6Explorer::MapShapesAndAncestors
1019     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
1020
1021   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
1022
1023   if (nbFaces == 0) {
1024     SetErrorCode("The given shape has no faces");
1025     return aSeq;
1026   }
1027
1028   TopTools_IndexedMapOfShape anIndices;
1029   TopExp::MapShapes(aShape, anIndices);
1030
1031   Standard_Integer id;
1032   for (; ind <= nbFaces; ind++) {
1033     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
1034       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
1035       aSeq->Append(id);
1036     }
1037   }
1038
1039   //The explode doesn't change object so no new function is required.
1040   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1041
1042   //Make a Python command
1043   GEOM::TPythonDump(aFunction, /*append=*/true)
1044     << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
1045
1046   SetErrorCode(OK);
1047   return aSeq;
1048 }
1049
1050 //=======================================================================
1051 //function : GetSharedShapes
1052 //purpose  :
1053 //=======================================================================
1054
1055 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
1056                                                 (Handle(GEOM_Object)    theShape1,
1057                                                  Handle(GEOM_Object)    theShape2,
1058                                                  const Standard_Integer theShapeType)
1059 {
1060   SetErrorCode(KO);
1061
1062   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
1063
1064   TopoDS_Shape aShape1 = theShape1->GetValue();
1065   TopoDS_Shape aShape2 = theShape2->GetValue();
1066
1067   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
1068
1069   TopTools_IndexedMapOfShape anIndices;
1070   TopExp::MapShapes(aShape1, anIndices);
1071   Handle(TColStd_HArray1OfInteger) anArray;
1072
1073   TopTools_IndexedMapOfShape mapShape1;
1074   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
1075
1076   Handle(GEOM_Object) anObj;
1077   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1078   TCollection_AsciiString anAsciiList, anEntry;
1079
1080   TopTools_MapOfShape mapShape2;
1081   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
1082   for (; exp.More(); exp.Next()) {
1083     TopoDS_Shape aSS = exp.Current();
1084     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
1085       anArray = new TColStd_HArray1OfInteger(1,1);
1086       anArray->SetValue(1, anIndices.FindIndex(aSS));
1087       anObj = GetEngine()->AddSubShape(theShape1, anArray);
1088       aSeq->Append(anObj);
1089
1090       // for python command
1091       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1092       anAsciiList += anEntry;
1093       anAsciiList += ",";
1094     }
1095   }
1096
1097   if (aSeq->IsEmpty()) {
1098     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
1099     return aSeq;
1100   }
1101
1102   //Make a Python command
1103   anAsciiList.Trunc(anAsciiList.Length() - 1);
1104
1105   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1106
1107   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1108     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
1109       << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
1110
1111   SetErrorCode(OK);
1112   return aSeq;
1113 }
1114
1115 //=============================================================================
1116 /*!
1117  *
1118  */
1119 //=============================================================================
1120 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
1121                                       const GEOMAlgo_State theState)
1122 {
1123   switch (theState) {
1124   case GEOMAlgo_ST_IN:
1125     theDump << "geompy.GEOM.ST_IN";
1126     break;
1127   case GEOMAlgo_ST_OUT:
1128     theDump << "geompy.GEOM.ST_OUT";
1129     break;
1130   case GEOMAlgo_ST_ON:
1131     theDump << "geompy.GEOM.ST_ON";
1132     break;
1133   case GEOMAlgo_ST_ONIN:
1134     theDump << "geompy.GEOM.ST_ONIN";
1135     break;
1136   case GEOMAlgo_ST_ONOUT:
1137     theDump << "geompy.GEOM.ST_ONOUT";
1138     break;
1139   default:
1140     theDump << "geompy.GEOM.ST_UNKNOWN";
1141     break;
1142   }
1143   return theDump;
1144 }
1145
1146 //=======================================================================
1147 //function : checkTypeShapesOn
1148 /*!
1149  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
1150  * \param theShapeType - the shape type to check
1151  * \retval bool  - result of the check
1152  */
1153 //=======================================================================
1154
1155 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
1156 {
1157   if (theShapeType != TopAbs_VERTEX &&
1158       theShapeType != TopAbs_EDGE &&
1159       theShapeType != TopAbs_FACE &&
1160       theShapeType != TopAbs_SOLID) {
1161     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1162     return false;
1163   }
1164   return true;
1165 }
1166
1167 //=======================================================================
1168 //function : makePlane
1169   /*!
1170    * \brief Creates Geom_Plane
1171     * \param theAx1 - shape object defining plane parameters
1172     * \retval Handle(Geom_Surface) - resulting surface
1173    */
1174 //=======================================================================
1175
1176 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
1177 {
1178   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1179   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1180   TopoDS_Vertex V1, V2;
1181   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1182   if (V1.IsNull() || V2.IsNull()) {
1183     SetErrorCode("Bad edge given for the plane normal vector");
1184     return NULL;
1185   }
1186   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1187   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1188   if (aVec.Magnitude() < Precision::Confusion()) {
1189     SetErrorCode("Vector with null magnitude given");
1190     return NULL;
1191   }
1192   return new Geom_Plane(aLoc, aVec);
1193 }
1194
1195 //=======================================================================
1196 //function : makeCylinder
1197   /*!
1198    * \brief Creates Geom_CylindricalSurface
1199     * \param theAx1 - edge defining cylinder axis
1200     * \param theRadius - cylinder radius
1201     * \retval Handle(Geom_Surface) - resulting surface
1202    */
1203 //=======================================================================
1204
1205 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
1206                                                               const Standard_Real theRadius)
1207 {
1208   //Axis of the cylinder
1209   if (anAxis.ShapeType() != TopAbs_EDGE) {
1210     SetErrorCode("Not an edge given for the axis");
1211     return NULL;
1212   }
1213   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1214   TopoDS_Vertex V1, V2;
1215   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1216   if (V1.IsNull() || V2.IsNull()) {
1217     SetErrorCode("Bad edge given for the axis");
1218     return NULL;
1219   }
1220   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1221   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1222   if (aVec.Magnitude() < Precision::Confusion()) {
1223     SetErrorCode("Vector with null magnitude given");
1224     return NULL;
1225   }
1226
1227   gp_Ax3 anAx3 (aLoc, aVec);
1228   return new Geom_CylindricalSurface(anAx3, theRadius);
1229 }
1230
1231
1232 //=======================================================================
1233 //function : getShapesOnBoxIDs
1234   /*!
1235    * \brief Find IDs of subshapes complying with given status about surface
1236     * \param theBox - the box to check state of subshapes against
1237     * \param theShape - the shape to explore
1238     * \param theShapeType - type of subshape of theShape
1239     * \param theState - required state
1240     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1241    */
1242 //=======================================================================
1243
1244 Handle(TColStd_HSequenceOfInteger)
1245   GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1246                                                 const Handle(GEOM_Object)& theShape,
1247                                                 const Standard_Integer theShapeType,
1248                                                 GEOMAlgo_State theState)
1249 {
1250   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1251
1252   TopoDS_Shape aBox = theBox->GetValue();
1253   TopoDS_Shape aShape = theShape->GetValue();
1254
1255   // Call algo
1256   GEOMAlgo_FinderShapeOn2 aFinder;
1257   Standard_Real aTol = 0.0001; // default value
1258
1259   Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
1260   aClsfBox->SetBox(aBox);
1261
1262   aFinder.SetShape(aShape);
1263   aFinder.SetTolerance(aTol);
1264   aFinder.SetClsf(aClsfBox);
1265   aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
1266   aFinder.SetState(theState);
1267   aFinder.Perform();
1268
1269   // Interprete results
1270   Standard_Integer iErr = aFinder.ErrorStatus();
1271   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1272   if (iErr) {
1273     MESSAGE(" iErr : " << iErr);
1274     TCollection_AsciiString aMsg (" iErr : ");
1275     aMsg += TCollection_AsciiString(iErr);
1276     SetErrorCode(aMsg);
1277     return aSeqOfIDs;
1278   }
1279   Standard_Integer iWrn = aFinder.WarningStatus();
1280   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1281   if (iWrn) {
1282     MESSAGE(" *** iWrn : " << iWrn);
1283   }
1284
1285   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1286
1287   if (listSS.Extent() < 1) {
1288     SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1289     return aSeqOfIDs;
1290   }
1291
1292   // Fill sequence of object IDs
1293   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1294
1295   TopTools_IndexedMapOfShape anIndices;
1296   TopExp::MapShapes(aShape, anIndices);
1297
1298   TopTools_ListIteratorOfListOfShape itSub (listSS);
1299   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1300     int id = anIndices.FindIndex(itSub.Value());
1301     aSeqOfIDs->Append(id);
1302   }
1303
1304   return aSeqOfIDs;
1305 }
1306
1307
1308 //=======================================================================
1309 //function : GetShapesOnBoxIDs
1310 /*!
1311    * \brief Find subshapes complying with given status about surface
1312     * \param theBox - the box to check state of subshapes against
1313     * \param theShape - the shape to explore
1314     * \param theShapeType - type of subshape of theShape
1315     * \param theState - required state
1316     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1317  */
1318 //=======================================================================
1319
1320 Handle(TColStd_HSequenceOfInteger)
1321     GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
1322                                                   const Handle(GEOM_Object)& theShape,
1323                                                   const Standard_Integer theShapeType,
1324                                                   GEOMAlgo_State theState)
1325 {
1326   // Find subshapes ids
1327   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1328     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1329   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1330     return NULL;
1331
1332   // The GetShapesOnBox() doesn't change object so no new function is required.
1333   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
1334
1335   // Make a Python command
1336   GEOM::TPythonDump(aFunction)
1337     << "listShapesOnBoxIDs = geompy.GetShapesOnQuadrangleIDs("
1338     << theBox << ", "
1339     << theShape << ", "
1340     << TopAbs_ShapeEnum(theShapeType) << ", "
1341     << theState << ")";
1342
1343   SetErrorCode(OK);
1344   return aSeqOfIDs;
1345 }
1346
1347 //=======================================================================
1348 //function : GetShapesOnBox
1349 /*!
1350    * \brief Find subshapes complying with given status about surface
1351     * \param theBox - the box to check state of subshapes against
1352     * \param theShape - the shape to explore
1353     * \param theShapeType - type of subshape of theShape
1354     * \param theState - required state
1355     * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
1356  */
1357 //=======================================================================
1358
1359 Handle(TColStd_HSequenceOfTransient)
1360     GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
1361                                                const Handle(GEOM_Object)&  theShape,
1362                                                const Standard_Integer theShapeType,
1363                                                GEOMAlgo_State theState)
1364 {
1365   // Find subshapes ids
1366   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1367     getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
1368   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1369     return NULL;
1370
1371   // Find objects by indices
1372   TCollection_AsciiString anAsciiList;
1373   Handle(TColStd_HSequenceOfTransient) aSeq;
1374   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1375   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1376     return NULL;
1377
1378   // Make a Python command
1379
1380   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1381   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1382
1383   GEOM::TPythonDump(aFunction)
1384     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
1385     << theBox << ", "
1386     << theShape << ", "
1387     << TopAbs_ShapeEnum(theShapeType) << ", "
1388     << theState << ")";
1389
1390   SetErrorCode(OK);
1391   return aSeq;
1392 }
1393
1394
1395 //=======================================================================
1396 //function : getShapesOnSurfaceIDs
1397   /*!
1398    * \brief Find IDs of subshapes complying with given status about surface
1399     * \param theSurface - the surface to check state of subshapes against
1400     * \param theShape - the shape to explore
1401     * \param theShapeType - type of subshape of theShape
1402     * \param theState - required state
1403     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1404    */
1405 //=======================================================================
1406
1407 Handle(TColStd_HSequenceOfInteger)
1408   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
1409                                                     const TopoDS_Shape&         theShape,
1410                                                     TopAbs_ShapeEnum            theShapeType,
1411                                                     GEOMAlgo_State              theState)
1412 {
1413   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1414
1415   // Check presence of triangulation, build if need
1416   if (!CheckTriangulation(theShape))
1417     return aSeqOfIDs;
1418
1419   // Call algo
1420   GEOMAlgo_FinderShapeOn1 aFinder;
1421   Standard_Real aTol = 0.0001; // default value
1422
1423   aFinder.SetShape(theShape);
1424   aFinder.SetTolerance(aTol);
1425   aFinder.SetSurface(theSurface);
1426   aFinder.SetShapeType(theShapeType);
1427   aFinder.SetState(theState);
1428
1429   // Sets the minimal number of inner points for the faces that do not have own
1430   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1431   // Default value=3
1432   aFinder.SetNbPntsMin(3);
1433   // Sets the maximal number of inner points for edges or faces.
1434   // It is usefull for the cases when this number is very big (e.g =2000) to improve
1435   // the performance. If this value =0, all inner points will be taken into account.
1436   // Default value=0
1437   aFinder.SetNbPntsMax(100);
1438
1439   aFinder.Perform();
1440
1441   // Interprete results
1442   Standard_Integer iErr = aFinder.ErrorStatus();
1443   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1444   if (iErr) {
1445     MESSAGE(" iErr : " << iErr);
1446     TCollection_AsciiString aMsg (" iErr : ");
1447     aMsg += TCollection_AsciiString(iErr);
1448     SetErrorCode(aMsg);
1449     return aSeqOfIDs;
1450   }
1451   Standard_Integer iWrn = aFinder.WarningStatus();
1452   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1453   if (iWrn) {
1454     MESSAGE(" *** iWrn : " << iWrn);
1455   }
1456
1457   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1458
1459   if (listSS.Extent() < 1) {
1460     SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1461     return aSeqOfIDs;
1462   }
1463
1464   // Fill sequence of object IDs
1465   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1466
1467   TopTools_IndexedMapOfShape anIndices;
1468   TopExp::MapShapes(theShape, anIndices);
1469
1470   TopTools_ListIteratorOfListOfShape itSub (listSS);
1471   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1472     int id = anIndices.FindIndex(itSub.Value());
1473     aSeqOfIDs->Append(id);
1474   }
1475
1476   return aSeqOfIDs;
1477 }
1478
1479 //=======================================================================
1480 //function : getObjectsShapesOn
1481 /*!
1482  * \brief Find shape objects and their entries by their ids
1483  * \param theShapeIDs - incoming shape ids
1484  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1485  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
1486  */
1487 //=======================================================================
1488
1489 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
1490  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
1491                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
1492                     TCollection_AsciiString &                 theShapeEntries)
1493 {
1494   Handle(TColStd_HSequenceOfTransient) aSeq;
1495
1496   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
1497   {
1498     aSeq = new TColStd_HSequenceOfTransient;
1499     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1500     TCollection_AsciiString anEntry;
1501     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
1502     {
1503       anArray->SetValue(1, theShapeIDs->Value( i ));
1504       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
1505       aSeq->Append( anObj );
1506
1507       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1508       if ( i != 1 ) theShapeEntries += ",";
1509       theShapeEntries += anEntry;
1510     }
1511   }
1512   return aSeq;
1513 }
1514
1515 //=======================================================================
1516 //function : getShapesOnSurface
1517 /*!
1518    * \brief Find subshapes complying with given status about surface
1519     * \param theSurface - the surface to check state of subshapes against
1520     * \param theShape - the shape to explore
1521     * \param theShapeType - type of subshape of theShape
1522     * \param theState - required state
1523     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1524     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1525  */
1526 //=======================================================================
1527
1528 Handle(TColStd_HSequenceOfTransient)
1529     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
1530                                                    const Handle(GEOM_Object)&  theShape,
1531                                                    TopAbs_ShapeEnum            theShapeType,
1532                                                    GEOMAlgo_State              theState,
1533                                                    TCollection_AsciiString &   theShapeEntries)
1534 {
1535   // Find subshapes ids
1536   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1537     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
1538   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1539     return NULL;
1540
1541   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
1542 }
1543
1544 //=============================================================================
1545 /*!
1546  *  GetShapesOnPlane
1547  */
1548 //=============================================================================
1549 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
1550                                         (const Handle(GEOM_Object)& theShape,
1551                                          const Standard_Integer     theShapeType,
1552                                          const Handle(GEOM_Object)& theAx1,
1553                                          const GEOMAlgo_State       theState)
1554 {
1555   SetErrorCode(KO);
1556
1557   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1558
1559   TopoDS_Shape aShape = theShape->GetValue();
1560   TopoDS_Shape anAx1  = theAx1->GetValue();
1561
1562   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1563
1564   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1565   if ( !checkTypeShapesOn( theShapeType ))
1566     return NULL;
1567
1568   // Create plane
1569   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1570   if ( aPlane.IsNull() )
1571     return NULL;
1572
1573   // Find objects
1574   TCollection_AsciiString anAsciiList;
1575   Handle(TColStd_HSequenceOfTransient) aSeq;
1576   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1577   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1578     return NULL;
1579
1580   // Make a Python command
1581
1582   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1583   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1584
1585   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1586     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
1587       << aShapeType << ", " << theAx1 << ", " << theState << ")";
1588
1589   SetErrorCode(OK);
1590   return aSeq;
1591 }
1592
1593 //=============================================================================
1594 /*!
1595  *  GetShapesOnPlaneWithLocation
1596  */
1597 //=============================================================================
1598 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
1599                                         (const Handle(GEOM_Object)& theShape,
1600                                          const Standard_Integer     theShapeType,
1601                                          const Handle(GEOM_Object)& theAx1,
1602                                          const Handle(GEOM_Object)& thePnt,
1603                                          const GEOMAlgo_State       theState)
1604 {
1605   SetErrorCode(KO);
1606
1607   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
1608
1609   TopoDS_Shape aShape = theShape->GetValue();
1610   TopoDS_Shape anAx1  = theAx1->GetValue();
1611   TopoDS_Shape anPnt = thePnt->GetValue();
1612
1613   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
1614
1615   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1616   if ( !checkTypeShapesOn( theShapeType ))
1617     return NULL;
1618
1619   // Create plane
1620   if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
1621   TopoDS_Vertex V1, V2, V3;
1622   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1623   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1624
1625   if (V1.IsNull() || V2.IsNull()) {
1626     SetErrorCode("Bad edge given for the plane normal vector");
1627     return NULL;
1628   }
1629   V3 = TopoDS::Vertex(anPnt);
1630
1631   if(V3.IsNull()) {
1632     SetErrorCode("Bad vertex given for the plane location");
1633       return NULL;
1634   }
1635   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
1636   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
1637
1638   if (aVec.Magnitude() < Precision::Confusion()) {
1639      SetErrorCode("Vector with null magnitude given");
1640     return NULL;
1641   }
1642   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
1643
1644   if ( aPlane.IsNull() )
1645     return NULL;
1646
1647   // Find objects
1648   TCollection_AsciiString anAsciiList;
1649   Handle(TColStd_HSequenceOfTransient) aSeq;
1650   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1651   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1652     return NULL;
1653
1654   // Make a Python command
1655
1656   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1657   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1658
1659   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1660     << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
1661     << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
1662
1663   SetErrorCode(OK);
1664   return aSeq;
1665 }
1666
1667 //=============================================================================
1668 /*!
1669  *  GetShapesOnCylinder
1670  */
1671 //=============================================================================
1672 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
1673                                           (const Handle(GEOM_Object)& theShape,
1674                                            const Standard_Integer     theShapeType,
1675                                            const Handle(GEOM_Object)& theAxis,
1676                                            const Standard_Real        theRadius,
1677                                            const GEOMAlgo_State       theState)
1678 {
1679   SetErrorCode(KO);
1680
1681   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1682
1683   TopoDS_Shape aShape = theShape->GetValue();
1684   TopoDS_Shape anAxis = theAxis->GetValue();
1685
1686   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1687
1688   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1689   if ( !checkTypeShapesOn( aShapeType ))
1690     return NULL;
1691
1692   // Create a cylinder surface
1693   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1694   if ( aCylinder.IsNull() )
1695     return NULL;
1696
1697   // Find objects
1698   TCollection_AsciiString anAsciiList;
1699   Handle(TColStd_HSequenceOfTransient) aSeq;
1700   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
1701   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1702     return NULL;
1703
1704   // Make a Python command
1705
1706   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1707   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1708
1709   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1710     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
1711       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
1712
1713   SetErrorCode(OK);
1714   return aSeq;
1715 }
1716
1717 //=============================================================================
1718 /*!
1719  *  GetShapesOnSphere
1720  */
1721 //=============================================================================
1722 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
1723                                           (const Handle(GEOM_Object)& theShape,
1724                                            const Standard_Integer     theShapeType,
1725                                            const Handle(GEOM_Object)& theCenter,
1726                                            const Standard_Real        theRadius,
1727                                            const GEOMAlgo_State       theState)
1728 {
1729   SetErrorCode(KO);
1730
1731   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1732
1733   TopoDS_Shape aShape  = theShape->GetValue();
1734   TopoDS_Shape aCenter = theCenter->GetValue();
1735
1736   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1737
1738   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1739   if ( !checkTypeShapesOn( aShapeType ))
1740     return NULL;
1741
1742   // Center of the sphere
1743   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1744   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1745
1746   gp_Ax3 anAx3 (aLoc, gp::DZ());
1747   Handle(Geom_SphericalSurface) aSphere =
1748     new Geom_SphericalSurface(anAx3, theRadius);
1749
1750   // Find objects
1751   TCollection_AsciiString anAsciiList;
1752   Handle(TColStd_HSequenceOfTransient) aSeq;
1753   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
1754   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1755     return NULL;
1756
1757   // Make a Python command
1758
1759   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1760   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1761
1762   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1763     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
1764       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
1765
1766   SetErrorCode(OK);
1767   return aSeq;
1768 }
1769
1770 //=============================================================================
1771 /*!
1772  *  GetShapesOnPlaneIDs
1773  */
1774 //=============================================================================
1775 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
1776                                         (const Handle(GEOM_Object)& theShape,
1777                                          const Standard_Integer     theShapeType,
1778                                          const Handle(GEOM_Object)& theAx1,
1779                                          const GEOMAlgo_State       theState)
1780 {
1781   SetErrorCode(KO);
1782
1783   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1784
1785   TopoDS_Shape aShape = theShape->GetValue();
1786   TopoDS_Shape anAx1  = theAx1->GetValue();
1787
1788   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1789
1790   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1791   if ( !checkTypeShapesOn( aShapeType ))
1792     return NULL;
1793
1794   // Create plane
1795   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1796   if ( aPlane.IsNull() )
1797     return NULL;
1798
1799   // Find object IDs
1800   Handle(TColStd_HSequenceOfInteger) aSeq;
1801   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
1802
1803   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
1804   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
1805
1806   // Make a Python command
1807   GEOM::TPythonDump(aFunction, /*append=*/true)
1808     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
1809     << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
1810
1811   SetErrorCode(OK);
1812   return aSeq;
1813 }
1814
1815 //=============================================================================
1816 /*!
1817  *  GetShapesOnPlaneWithLocationIDs
1818  */
1819 //=============================================================================
1820 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
1821                                         (const Handle(GEOM_Object)& theShape,
1822                                          const Standard_Integer     theShapeType,
1823                                          const Handle(GEOM_Object)& theAx1,
1824                                          const Handle(GEOM_Object)& thePnt,
1825                                          const GEOMAlgo_State       theState)
1826 {
1827   SetErrorCode(KO);
1828
1829   if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
1830
1831   TopoDS_Shape aShape = theShape->GetValue();
1832   TopoDS_Shape anAx1  = theAx1->GetValue();
1833   TopoDS_Shape anPnt  = thePnt->GetValue();
1834
1835   if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
1836
1837   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1838   if ( !checkTypeShapesOn( aShapeType ))
1839     return NULL;
1840
1841   // Create plane
1842   if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
1843   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1844   TopoDS_Vertex V1, V2, V3;
1845   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1846   if (V1.IsNull() || V2.IsNull()) {
1847     SetErrorCode("Bad edge given for the plane normal vector");
1848     return NULL;
1849   }
1850   V3 = TopoDS::Vertex(anPnt);
1851   if(V3.IsNull()) {
1852     SetErrorCode("Bad vertex given for the plane location");
1853       return NULL;
1854   }
1855   gp_Pnt aLoc = BRep_Tool::Pnt(V3);
1856   gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
1857   if (aVec.Magnitude() < Precision::Confusion()) {
1858     SetErrorCode("Vector with null magnitude given");
1859     return NULL;
1860   }
1861
1862   Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
1863   if ( aPlane.IsNull() )
1864     return NULL;
1865
1866   // Find object IDs
1867   Handle(TColStd_HSequenceOfInteger) aSeq;
1868   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
1869
1870   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
1871   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
1872
1873   // Make a Python command
1874   GEOM::TPythonDump(aFunction, /*append=*/true)
1875     << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
1876     << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", "  << theState << ")";
1877
1878   SetErrorCode(OK);
1879   return aSeq;
1880 }
1881
1882 //=============================================================================
1883 /*!
1884  *  GetShapesOnCylinderIDs
1885  */
1886 //=============================================================================
1887 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
1888                                           (const Handle(GEOM_Object)& theShape,
1889                                            const Standard_Integer     theShapeType,
1890                                            const Handle(GEOM_Object)& theAxis,
1891                                            const Standard_Real        theRadius,
1892                                            const GEOMAlgo_State       theState)
1893 {
1894   SetErrorCode(KO);
1895
1896   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1897
1898   TopoDS_Shape aShape = theShape->GetValue();
1899   TopoDS_Shape anAxis = theAxis->GetValue();
1900
1901   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1902
1903   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1904   if ( !checkTypeShapesOn( aShapeType ))
1905     return NULL;
1906
1907   // Create a cylinder surface
1908   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1909   if ( aCylinder.IsNull() )
1910     return NULL;
1911
1912   // Find object IDs
1913   Handle(TColStd_HSequenceOfInteger) aSeq;
1914   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
1915
1916   // The GetShapesOnCylinder() doesn't change object so no new function is required.
1917   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
1918
1919   // Make a Python command
1920   GEOM::TPythonDump(aFunction, /*append=*/true)
1921     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
1922     << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
1923     << theRadius << ", " << theState << ")";
1924
1925   SetErrorCode(OK);
1926   return aSeq;
1927 }
1928
1929 //=============================================================================
1930 /*!
1931  *  GetShapesOnSphereIDs
1932  */
1933 //=============================================================================
1934 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
1935                                           (const Handle(GEOM_Object)& theShape,
1936                                            const Standard_Integer     theShapeType,
1937                                            const Handle(GEOM_Object)& theCenter,
1938                                            const Standard_Real        theRadius,
1939                                            const GEOMAlgo_State       theState)
1940 {
1941   SetErrorCode(KO);
1942
1943   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1944
1945   TopoDS_Shape aShape  = theShape->GetValue();
1946   TopoDS_Shape aCenter = theCenter->GetValue();
1947
1948   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1949
1950   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1951   if ( !checkTypeShapesOn( aShapeType ))
1952     return NULL;
1953
1954   // Center of the sphere
1955   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1956   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1957
1958   gp_Ax3 anAx3 (aLoc, gp::DZ());
1959   Handle(Geom_SphericalSurface) aSphere =
1960     new Geom_SphericalSurface(anAx3, theRadius);
1961
1962   // Find object IDs
1963   Handle(TColStd_HSequenceOfInteger) aSeq;
1964   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
1965
1966   // The GetShapesOnSphere() doesn't change object so no new function is required.
1967   Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
1968
1969   // Make a Python command
1970   GEOM::TPythonDump(aFunction, /*append=*/true)
1971     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
1972     << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
1973     << theRadius << ", " << theState << ")";
1974
1975   SetErrorCode(OK);
1976   return aSeq;
1977 }
1978
1979 //=======================================================================
1980 //function : getShapesOnQuadrangleIDs
1981   /*!
1982    * \brief Find IDs of subshapes complying with given status about quadrangle
1983     * \param theShape - the shape to explore
1984     * \param theShapeType - type of subshape of theShape
1985     * \param theTopLeftPoint - top left quadrangle corner
1986     * \param theTopRigthPoint - top right quadrangle corner
1987     * \param theBottomLeftPoint - bottom left quadrangle corner
1988     * \param theBottomRigthPoint - bottom right quadrangle corner
1989     * \param theState - required state
1990     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1991    */
1992 //=======================================================================
1993
1994 Handle(TColStd_HSequenceOfInteger)
1995   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
1996                                                         const Standard_Integer     theShapeType,
1997                                                         const Handle(GEOM_Object)& theTopLeftPoint,
1998                                                         const Handle(GEOM_Object)& theTopRigthPoint,
1999                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
2000                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
2001                                                         const GEOMAlgo_State       theState)
2002 {
2003   SetErrorCode(KO);
2004
2005   if ( theShape.IsNull() ||
2006        theTopLeftPoint.IsNull() ||
2007        theTopRigthPoint.IsNull() ||
2008        theBottomLeftPoint.IsNull() ||
2009        theBottomRigthPoint.IsNull() )
2010     return NULL;
2011
2012   TopoDS_Shape aShape = theShape->GetValue();
2013   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
2014   TopoDS_Shape aTR = theTopRigthPoint->GetValue();
2015   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
2016   TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
2017
2018   if (aShape.IsNull() ||
2019       aTL.IsNull() ||
2020       aTR.IsNull() ||
2021       aBL.IsNull() ||
2022       aBR.IsNull() ||
2023       aTL.ShapeType() != TopAbs_VERTEX ||
2024       aTR.ShapeType() != TopAbs_VERTEX ||
2025       aBL.ShapeType() != TopAbs_VERTEX ||
2026       aBR.ShapeType() != TopAbs_VERTEX )
2027     return NULL;
2028
2029   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
2030   if ( !checkTypeShapesOn( aShapeType ))
2031     return NULL;
2032
2033   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
2034
2035   // Check presence of triangulation, build if need
2036   if (!CheckTriangulation(aShape))
2037     return aSeqOfIDs;
2038
2039   // Call algo
2040   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
2041   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
2042   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
2043   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
2044
2045   GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
2046   Standard_Real aTol = 0.0001; // default value
2047
2048   aFinder.SetShape(aShape);
2049   aFinder.SetTolerance(aTol);
2050   //aFinder.SetSurface(theSurface);
2051   aFinder.SetShapeType(aShapeType);
2052   aFinder.SetState(theState);
2053
2054   // Sets the minimal number of inner points for the faces that do not have own
2055   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
2056   // Default value=3
2057   aFinder.SetNbPntsMin(3);
2058   // Sets the maximal number of inner points for edges or faces.
2059   // It is usefull for the cases when this number is very big (e.g =2000) to improve
2060   // the performance. If this value =0, all inner points will be taken into account.
2061   // Default value=0
2062   aFinder.SetNbPntsMax(100);
2063
2064   aFinder.Perform();
2065
2066   // Interprete results
2067   Standard_Integer iErr = aFinder.ErrorStatus();
2068   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
2069   if (iErr) {
2070     MESSAGE(" iErr : " << iErr);
2071     TCollection_AsciiString aMsg (" iErr : ");
2072     aMsg += TCollection_AsciiString(iErr);
2073     SetErrorCode(aMsg);
2074     return aSeqOfIDs;
2075   }
2076   Standard_Integer iWrn = aFinder.WarningStatus();
2077   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
2078   if (iWrn) {
2079     MESSAGE(" *** iWrn : " << iWrn);
2080   }
2081
2082   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
2083
2084   if (listSS.Extent() < 1) {
2085     SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
2086     return aSeqOfIDs;
2087   }
2088
2089   // Fill sequence of object IDs
2090   aSeqOfIDs = new TColStd_HSequenceOfInteger;
2091
2092   TopTools_IndexedMapOfShape anIndices;
2093   TopExp::MapShapes(aShape, anIndices);
2094
2095   TopTools_ListIteratorOfListOfShape itSub (listSS);
2096   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
2097     int id = anIndices.FindIndex(itSub.Value());
2098     aSeqOfIDs->Append(id);
2099   }
2100   return aSeqOfIDs;
2101 }
2102
2103 //=======================================================================
2104 //function : GetShapesOnQuadrangle
2105   /*!
2106    * \brief Find subshapes complying with given status about quadrangle
2107     * \param theShape - the shape to explore
2108     * \param theShapeType - type of subshape of theShape
2109     * \param theTopLeftPoint - top left quadrangle corner
2110     * \param theTopRigthPoint - top right quadrangle corner
2111     * \param theBottomLeftPoint - bottom left quadrangle corner
2112     * \param theBottomRigthPoint - bottom right quadrangle corner
2113     * \param theState - required state
2114     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2115    */
2116 //=======================================================================
2117
2118 Handle(TColStd_HSequenceOfTransient)
2119     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
2120                                                        const Standard_Integer     theShapeType,
2121                                                        const Handle(GEOM_Object)& theTopLeftPoint,
2122                                                        const Handle(GEOM_Object)& theTopRigthPoint,
2123                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
2124                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
2125                                                        const GEOMAlgo_State       theState)
2126 {
2127   // Find indices
2128   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2129     getShapesOnQuadrangleIDs( theShape,
2130                               theShapeType,
2131                               theTopLeftPoint,
2132                               theTopRigthPoint,
2133                               theBottomLeftPoint,
2134                               theBottomRigthPoint,
2135                               theState);
2136   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2137     return NULL;
2138
2139   // Find objects by indices
2140   TCollection_AsciiString anAsciiList;
2141   Handle(TColStd_HSequenceOfTransient) aSeq;
2142   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
2143   if ( aSeq.IsNull() || aSeq->IsEmpty() )
2144     return NULL;
2145
2146   // Make a Python command
2147
2148   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
2149   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
2150
2151   GEOM::TPythonDump(aFunction)
2152     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
2153     << theShape << ", "
2154     << TopAbs_ShapeEnum(theShapeType) << ", "
2155     << theTopLeftPoint << ", "
2156     << theTopRigthPoint << ", "
2157     << theBottomLeftPoint << ", "
2158     << theBottomRigthPoint << ", "
2159     << theState << ")";
2160
2161   SetErrorCode(OK);
2162   return aSeq;
2163 }
2164
2165 //=======================================================================
2166 //function : GetShapesOnQuadrangleIDs
2167   /*!
2168    * \brief Find IDs of subshapes complying with given status about quadrangle
2169     * \param theShape - the shape to explore
2170     * \param theShapeType - type of subshape of theShape
2171     * \param theTopLeftPoint - top left quadrangle corner
2172     * \param theTopRigthPoint - top right quadrangle corner
2173     * \param theBottomLeftPoint - bottom left quadrangle corner
2174     * \param theBottomRigthPoint - bottom right quadrangle corner
2175     * \param theState - required state
2176     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
2177    */
2178 //=======================================================================
2179
2180 Handle(TColStd_HSequenceOfInteger)
2181   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
2182                                                         const Standard_Integer     theShapeType,
2183                                                         const Handle(GEOM_Object)& theTopLeftPoint,
2184                                                         const Handle(GEOM_Object)& theTopRigthPoint,
2185                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
2186                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
2187                                                         const GEOMAlgo_State       theState)
2188 {
2189   // Find indices
2190   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
2191     getShapesOnQuadrangleIDs( theShape,
2192                               theShapeType,
2193                               theTopLeftPoint,
2194                               theTopRigthPoint,
2195                               theBottomLeftPoint,
2196                               theBottomRigthPoint,
2197                               theState);
2198   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
2199     return NULL;
2200
2201   // Make a Python command
2202
2203   // The GetShapesOnCylinder() doesn't change object so no new function is required.
2204   Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
2205   lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
2206   lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
2207   lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
2208   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
2209
2210   GEOM::TPythonDump(aFunction, /*append=*/true)
2211     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
2212     << theShape << ", "
2213     << TopAbs_ShapeEnum(theShapeType) << ", "
2214     << theTopLeftPoint << ", "
2215     << theTopRigthPoint << ", "
2216     << theBottomLeftPoint << ", "
2217     << theBottomRigthPoint << ", "
2218     << theState << ")";
2219
2220   SetErrorCode(OK);
2221   return aSeqOfIDs;
2222 }
2223
2224
2225 //=============================================================================
2226 /*!
2227  *  GetInPlace
2228  */
2229 //=============================================================================
2230 static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
2231                                const TopTools_IndexedMapOfShape& theWhereIndices,
2232                                const TopoDS_Shape& theWhat,
2233                                TColStd_ListOfInteger& theModifiedList)
2234 {
2235   if (theWhereFunction.IsNull() || theWhat.IsNull()) return false;
2236
2237   if (theWhereIndices.Contains(theWhat)) {
2238     // entity was not changed by the operation
2239     Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
2240     theModifiedList.Append(aWhatIndex);
2241     return true;
2242   }
2243
2244   // try to find in history
2245   TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
2246
2247   // search in history for all argument shapes
2248   Standard_Boolean isFound = Standard_False;
2249   Standard_Boolean isGood = Standard_False;
2250
2251   TDF_LabelSequence aLabelSeq;
2252   theWhereFunction->GetDependency(aLabelSeq);
2253   Standard_Integer nbArg = aLabelSeq.Length();
2254
2255   for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
2256
2257     TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
2258
2259     Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
2260     TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
2261
2262     TopTools_IndexedMapOfShape anArgumentIndices;
2263     TopExp::MapShapes(anArgumentShape, anArgumentIndices);
2264
2265     if (anArgumentIndices.Contains(theWhat)) {
2266       isFound = Standard_True;
2267       Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
2268
2269       // Find corresponding label in history
2270       TDF_Label anArgumentHistoryLabel =
2271         theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
2272       if (anArgumentHistoryLabel.IsNull()) {
2273         // Lost History of operation argument. Possibly, all its entities was removed.
2274         isGood = Standard_True;
2275       }
2276       else {
2277         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
2278
2279         if (aWhatHistoryLabel.IsNull()) {
2280           // Removed entity ? Compound ? Compsolid ? Shell ? Wire
2281           isGood = Standard_False;
2282         } else {
2283           Handle(TDataStd_IntegerArray) anIntegerArray;
2284           if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
2285             //Error: Empty modifications history for the sought shape.
2286             isGood = Standard_False;
2287           }
2288           else {
2289             isGood = Standard_True;
2290             Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
2291             for (imod = 1; imod <= aModifLen; imod++) {
2292               theModifiedList.Append(anIntegerArray->Array()->Value(imod));
2293             }
2294           }
2295         }
2296       }
2297     }
2298   }
2299
2300   isFound = isGood;
2301
2302   if (!isFound) {
2303     // try compound/compsolid/shell/wire element by element
2304     bool isFoundAny = false;
2305     TopTools_MapOfShape mapShape;
2306
2307     if (theWhat.ShapeType() == TopAbs_COMPOUND ||
2308         theWhat.ShapeType() == TopAbs_COMPSOLID) {
2309       // recursive processing of compound/compsolid
2310       TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
2311       for (; anIt.More(); anIt.Next()) {
2312         if (mapShape.Add(anIt.Value())) {
2313           TopoDS_Shape curWhat = anIt.Value();
2314           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2315           if (isFoundAny) isFound = Standard_True;
2316         }
2317       }
2318     }
2319     else if (theWhat.ShapeType() == TopAbs_SHELL) {
2320       // try to replace a shell by its faces images
2321       TopExp_Explorer anExp (theWhat, TopAbs_FACE);
2322       for (; anExp.More(); anExp.Next()) {
2323         if (mapShape.Add(anExp.Current())) {
2324           TopoDS_Shape curWhat = anExp.Current();
2325           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2326           if (isFoundAny) isFound = Standard_True;
2327         }
2328       }
2329     }
2330     else if (theWhat.ShapeType() == TopAbs_WIRE) {
2331       // try to replace a wire by its edges images
2332       TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
2333       for (; anExp.More(); anExp.Next()) {
2334         if (mapShape.Add(anExp.Current())) {
2335           TopoDS_Shape curWhat = anExp.Current();
2336           isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
2337           if (isFoundAny) isFound = Standard_True;
2338         }
2339       }
2340     }
2341     else {
2342       // Removed entity
2343     }
2344   }
2345
2346   return isFound;
2347 }
2348
2349 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
2350                                           (Handle(GEOM_Object) theShapeWhere,
2351                                            Handle(GEOM_Object) theShapeWhat)
2352 {
2353   SetErrorCode(KO);
2354
2355   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2356
2357   TopoDS_Shape aWhere = theShapeWhere->GetValue();
2358   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
2359
2360   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
2361
2362   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
2363   if (aWhereFunction.IsNull()) return NULL;
2364
2365   //Fill array of indices
2366   TopTools_IndexedMapOfShape aWhereIndices;
2367   TopExp::MapShapes(aWhere, aWhereIndices);
2368
2369   // process shape
2370   TColStd_ListOfInteger aModifiedList;
2371   bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
2372
2373   if (!isFound || aModifiedList.Extent() < 1) {
2374     SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
2375     return NULL;
2376   }
2377
2378   Handle(TColStd_HArray1OfInteger) aModifiedArray =
2379     new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
2380   TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
2381   for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
2382     aModifiedArray->SetValue(imod, anIterModif.Value());
2383   }
2384
2385   //Add a new object
2386   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
2387   if (aResult.IsNull()) {
2388     SetErrorCode("Error in algorithm: result found, but cannot be returned.");
2389     return NULL;
2390   }
2391
2392   if (aModifiedArray->Length() > 1) {
2393     //Set a GROUP type
2394     aResult->SetType(GEOM_GROUP);
2395
2396     //Set a sub shape type
2397     TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
2398     TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
2399
2400     TDF_Label aFreeLabel = aResult->GetFreeLabel();
2401     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
2402   }
2403
2404   //Make a Python command
2405   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
2406
2407   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
2408     << theShapeWhere << ", " << theShapeWhat << ")";
2409
2410   SetErrorCode(OK);
2411   return aResult;
2412 }
2413
2414 //=======================================================================
2415 //function : SortShapes
2416 //purpose  :
2417 //=======================================================================
2418 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
2419 {
2420   Standard_Integer MaxShapes = SL.Extent();
2421   TopTools_Array1OfShape  aShapes (1,MaxShapes);
2422   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
2423   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
2424   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
2425
2426   // Computing of CentreOfMass
2427   Standard_Integer Index;
2428   GProp_GProps GPr;
2429   gp_Pnt GPoint;
2430   TopTools_ListIteratorOfListOfShape it(SL);
2431   for (Index=1;  it.More();  Index++)
2432   {
2433     TopoDS_Shape S = it.Value();
2434     SL.Remove( it ); // == it.Next()
2435     aShapes(Index) = S;
2436     OrderInd.SetValue (Index, Index);
2437     if (S.ShapeType() == TopAbs_VERTEX)
2438     {
2439       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
2440       Length.SetValue( Index, (Standard_Real) S.Orientation());
2441     }
2442     else
2443     {
2444       BRepGProp::LinearProperties (S, GPr);
2445       GPoint = GPr.CentreOfMass();
2446       Length.SetValue( Index, GPr.Mass() );
2447     }
2448     MidXYZ.SetValue(Index,
2449                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
2450   }
2451
2452   // Sorting
2453   Standard_Integer aTemp;
2454   Standard_Boolean exchange, Sort = Standard_True;
2455   while (Sort)
2456   {
2457     Sort = Standard_False;
2458     for (Index=1; Index < MaxShapes; Index++)
2459     {
2460       if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
2461         exchange = Standard_True;
2462       else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
2463                Length(OrderInd(Index)) >  Length(OrderInd(Index+1)) )
2464         exchange = Standard_True;
2465       else
2466         exchange = Standard_False;
2467       if (exchange)
2468       {
2469         aTemp = OrderInd(Index);
2470         OrderInd(Index) = OrderInd(Index+1);
2471         OrderInd(Index+1) = aTemp;
2472         Sort = Standard_True;
2473       }
2474     }
2475   }
2476   for (Index=1; Index <= MaxShapes; Index++)
2477     SL.Append( aShapes( OrderInd(Index) ));
2478 }
2479
2480 //=======================================================================
2481 //function : CheckTriangulation
2482 //purpose  :
2483 //=======================================================================
2484 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
2485 {
2486   TopExp_Explorer exp (aShape, TopAbs_FACE);
2487   if (!exp.More()) {
2488     SetErrorCode("Shape without faces given");
2489     return false;
2490   }
2491
2492   TopLoc_Location aTopLoc;
2493   Handle(Poly_Triangulation) aTRF;
2494   aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
2495   if (aTRF.IsNull()) {
2496     // calculate deflection
2497     Standard_Real aDeviationCoefficient = 0.001;
2498
2499     Bnd_Box B;
2500     BRepBndLib::Add(aShape, B);
2501     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
2502     B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
2503
2504     Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
2505     Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
2506     Standard_Real aHLRAngle = 0.349066;
2507
2508     BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
2509   }
2510
2511   return true;
2512 }
2513
2514 #define MAX_TOLERANCE 1.e-7
2515
2516
2517 //=======================================================================
2518 //function : isSameEdge
2519 //purpose  : Returns True if two edges coincide
2520 //=======================================================================
2521 static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
2522 {
2523   TopoDS_Vertex V11, V12, V21, V22;
2524   TopExp::Vertices(theEdge1, V11, V12);
2525   TopExp::Vertices(theEdge2, V21, V22);
2526   gp_Pnt P11 = BRep_Tool::Pnt(V11);
2527   gp_Pnt P12 = BRep_Tool::Pnt(V12);
2528   gp_Pnt P21 = BRep_Tool::Pnt(V21);
2529   gp_Pnt P22 = BRep_Tool::Pnt(V22);
2530   bool coincide = false;
2531
2532   //Check that ends of edges coincide
2533   if(P11.Distance(P21) <= MAX_TOLERANCE) {
2534     if(P12.Distance(P22) <= MAX_TOLERANCE) coincide =  true;
2535   }
2536   else if(P11.Distance(P22) <= MAX_TOLERANCE) {
2537     if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true;
2538   }
2539
2540   if(!coincide) return false;
2541
2542   double U11, U12, U21, U22;
2543   Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12);
2544   Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22);
2545   if(C1->DynamicType() == C2->DynamicType()) return true;
2546
2547   //Check that both edges has the same geometry
2548   double range = U12-U11;
2549   double U = U11+ range/3.0;
2550   gp_Pnt P1 = C1->Value(U);     //Compute a point on one third of the edge's length
2551   U = U11+range*2.0/3.0;
2552   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
2553
2554   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
2555     return false;
2556
2557   if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
2558
2559   if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22)
2560     return false;
2561
2562   if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false;
2563
2564   return true;
2565 }
2566
2567 #include <TopoDS_TShape.hxx>
2568 //=======================================================================
2569 //function : isSameFace
2570 //purpose  : Returns True if two faces coincide
2571 //=======================================================================
2572 static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2)
2573 {
2574   TopExp_Explorer E(theFace1, TopAbs_EDGE);
2575   TopTools_ListOfShape LS1, LS2;
2576   for(; E.More(); E.Next()) LS1.Append(E.Current());
2577
2578   E.Init(theFace2, TopAbs_EDGE);
2579   for(; E.More(); E.Next()) LS2.Append(E.Current());
2580
2581   //Compare the number of edges in the faces
2582   if(LS1.Extent() != LS2.Extent()) return false;
2583
2584   double aMin = RealFirst(), aMax = RealLast();
2585   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
2586   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
2587
2588   for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) {
2589     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2590     if(P.X() < xminB1) xminB1 = P.X();
2591     if(P.Y() < yminB1) yminB1 = P.Y();
2592     if(P.Z() < zminB1) zminB1 = P.Z();
2593     if(P.X() > xmaxB1) xmaxB1 = P.X();
2594     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
2595     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
2596   }
2597
2598   for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) {
2599     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2600     if(P.X() < xminB2) xminB2 = P.X();
2601     if(P.Y() < yminB2) yminB2 = P.Y();
2602     if(P.Z() < zminB2) zminB2 = P.Z();
2603     if(P.X() > xmaxB2) xmaxB2 = P.X();
2604     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
2605     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
2606   }
2607
2608   //Compare the bounding boxes of both faces
2609   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
2610     return false;
2611
2612   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
2613     return false;
2614
2615   //Check that each edge of the Face1 has a counterpart in the Face2
2616   TopTools_MapOfOrientedShape aMap;
2617   TopTools_ListIteratorOfListOfShape LSI1(LS1);
2618   for(; LSI1.More(); LSI1.Next()) {
2619     TopoDS_Edge E = TopoDS::Edge(LSI1.Value());
2620     bool isFound = false;
2621     TopTools_ListIteratorOfListOfShape LSI2(LS2);
2622     for(; LSI2.More(); LSI2.Next()) {
2623       TopoDS_Shape aValue = LSI2.Value();
2624       if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times
2625       if(isSameEdge(E, TopoDS::Edge(aValue))) {
2626         aMap.Add(aValue);
2627         isFound = true;
2628         break;
2629       }
2630     }
2631     if(!isFound) return false;
2632   }
2633
2634   Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1);
2635   Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2);
2636   if(S1->DynamicType() == S2->DynamicType()) {
2637     return true;
2638   }
2639   else {   //Check if there a coincidence of two surfaces at least in two points
2640     double U11, U12, V11, V12, U21, U22, V21, V22;
2641     BRepTools::UVBounds(theFace1, U11, U12, V11, V12);
2642     BRepTools::UVBounds(theFace2, U21, U22, V21, V22);
2643
2644     double rangeU = U12-U11;
2645     double rangeV = V12-V11;
2646     double U = U11 + rangeU/3.0;
2647     double V = V11 + rangeV/3.0;
2648     gp_Pnt P1 = S1->Value(U, V);
2649     U = U11+rangeU*2.0/3.0;
2650     V = V11+rangeV*2.0/3.0;
2651     gp_Pnt P2 = S1->Value(U, V);
2652
2653     if(!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
2654       return false;
2655
2656     if(P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false;
2657
2658     if(!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22)
2659       return false;
2660
2661     if(P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false;
2662   }
2663
2664   return true;
2665 }
2666
2667 //=======================================================================
2668 //function : isSameSolid
2669 //purpose  : Returns True if two solids coincide
2670 //=======================================================================
2671 bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2)
2672 {
2673   TopExp_Explorer E(theSolid1, TopAbs_FACE);
2674   TopTools_ListOfShape LS1, LS2;
2675   for(; E.More(); E.Next()) LS1.Append(E.Current());
2676   E.Init(theSolid2, TopAbs_FACE);
2677   for(; E.More(); E.Next()) LS2.Append(E.Current());
2678
2679   if(LS1.Extent() != LS2.Extent()) return false;
2680
2681   double aMin = RealFirst(), aMax = RealLast();
2682   double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax;
2683   double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin;
2684
2685   for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) {
2686     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2687     if(P.X() < xminB1) xminB1 = P.X();
2688     if(P.Y() < yminB1) yminB1 = P.Y();
2689     if(P.Z() < zminB1) zminB1 = P.Z();
2690     if(P.X() > xmaxB1) xmaxB1 = P.X();
2691     if(P.Y() > ymaxB1) ymaxB1 = P.Y();
2692     if(P.Z() > zmaxB1) zmaxB1 = P.Z();
2693   }
2694
2695   for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) {
2696     gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2697     if(P.X() < xminB2) xminB2 = P.X();
2698     if(P.Y() < yminB2) yminB2 = P.Y();
2699     if(P.Z() < zminB2) zminB2 = P.Z();
2700     if(P.X() > xmaxB2) xmaxB2 = P.X();
2701     if(P.Y() > ymaxB2) ymaxB2 = P.Y();
2702     if(P.Z() > zmaxB2) zmaxB2 = P.Z();
2703   }
2704
2705   //Compare the bounding boxes of both solids
2706   if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE)
2707     return false;
2708
2709   if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE)
2710     return false;
2711
2712   //Check that each face of the Solid1 has a counterpart in the Solid2
2713   TopTools_MapOfOrientedShape aMap;
2714   TopTools_ListIteratorOfListOfShape LSI1(LS1);
2715   for(; LSI1.More(); LSI1.Next()) {
2716     TopoDS_Face F = TopoDS::Face(LSI1.Value());
2717     bool isFound = false;
2718     TopTools_ListIteratorOfListOfShape LSI2(LS2);
2719     for(; LSI2.More(); LSI2.Next()) {
2720       if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times
2721       if(isSameFace(F, TopoDS::Face(LSI2.Value()))) {
2722         aMap.Add(LSI2.Value());
2723         isFound = true;
2724         break;
2725       }
2726     }
2727     if(!isFound) return false;
2728   }
2729
2730   return true;
2731 }
2732
2733 //=======================================================================
2734 //function : GetSame
2735 //purpose  :
2736 //=======================================================================
2737 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere,
2738                                                         const Handle(GEOM_Object)& theShapeWhat)
2739 {
2740   SetErrorCode(KO);
2741   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
2742
2743   TopoDS_Shape aWhere = theShapeWhere->GetValue();
2744   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
2745
2746   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
2747
2748   int anIndex = -1;
2749   bool isFound = false;
2750   TopoDS_Shape aSubShape;
2751   TopTools_MapOfShape aMap;
2752
2753   switch(aWhat.ShapeType()) {
2754     case TopAbs_VERTEX: {
2755       gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
2756       TopExp_Explorer E(aWhere, TopAbs_VERTEX);
2757       for(; E.More(); E.Next()) {
2758         if(!aMap.Add(E.Current())) continue;
2759         gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
2760         if(P.Distance(P2) <= MAX_TOLERANCE) {
2761           isFound = true;
2762           aSubShape = E.Current();
2763           break;
2764         }
2765       }
2766       break;
2767                         }
2768     case TopAbs_FACE: {
2769       TopoDS_Face aFace = TopoDS::Face(aWhat);
2770       TopExp_Explorer E(aWhere, TopAbs_FACE);
2771       for(; E.More(); E.Next()) {
2772         if(!aMap.Add(E.Current())) continue;
2773         if(isSameFace(aFace, TopoDS::Face(E.Current()))) {
2774           aSubShape = E.Current();
2775           isFound = true;
2776           break;
2777         }
2778       }
2779       break;
2780                       }
2781     case TopAbs_EDGE: {
2782       TopoDS_Edge anEdge = TopoDS::Edge(aWhat);
2783       TopExp_Explorer E(aWhere, TopAbs_EDGE);
2784       for(; E.More(); E.Next()) {
2785         if(!aMap.Add(E.Current())) continue;
2786         if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) {
2787           aSubShape = E.Current();
2788           isFound = true;
2789           break;
2790         }
2791       }
2792       break;
2793                       }
2794     case TopAbs_SOLID: {
2795       TopoDS_Solid aSolid = TopoDS::Solid(aWhat);
2796       TopExp_Explorer E(aWhere, TopAbs_SOLID);
2797       for(; E.More(); E.Next()) {
2798         if(!aMap.Add(E.Current())) continue;
2799         if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) {
2800           aSubShape = E.Current();
2801           isFound = true;
2802           break;
2803         }
2804       }
2805       break;
2806                        }
2807     default:
2808       return NULL;
2809   }
2810
2811   if(isFound) {
2812     TopTools_IndexedMapOfShape anIndices;
2813     TopExp::MapShapes(aWhere, anIndices);
2814     if (anIndices.Contains(aSubShape))
2815       anIndex = anIndices.FindIndex(aSubShape);
2816   }
2817
2818   if(anIndex < 0) return NULL;
2819
2820   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
2821
2822   anArray->SetValue(1, anIndex);
2823
2824   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray);
2825   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
2826
2827   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame("
2828     << theShapeWhere << ", " << theShapeWhat << ")";
2829
2830   SetErrorCode(OK);
2831
2832   return aResult;
2833 }