]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
Salome HOME
PAL8395: Fix pb. with bug2extraEdges.py
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 using namespace std;
2
3 #include "GEOMImpl_IShapesOperations.hxx"
4
5 #include "GEOMImpl_Types.hxx"
6
7 #include "GEOMImpl_VectorDriver.hxx"
8 #include "GEOMImpl_ShapeDriver.hxx"
9 #include "GEOMImpl_CopyDriver.hxx"
10 #include "GEOMImpl_GlueDriver.hxx"
11
12 #include "GEOMImpl_IVector.hxx"
13 #include "GEOMImpl_IShapes.hxx"
14 #include "GEOMImpl_IGlue.hxx"
15
16 #include "GEOMImpl_Block6Explorer.hxx"
17
18 #include "GEOM_Function.hxx"
19
20 #include "GEOMAlgo_FinderShapeOn.hxx"
21
22 #include "utilities.h"
23 #include "OpUtil.hxx"
24 #include "Utils_ExceptHandlers.hxx"
25
26 #include <TFunction_DriverTable.hxx>
27 #include <TFunction_Driver.hxx>
28 #include <TFunction_Logbook.hxx>
29 #include <TDataStd_Integer.hxx>
30 #include <TDataStd_IntegerArray.hxx>
31 #include <TDF_Tool.hxx>
32
33 #include <BRepExtrema_ExtCF.hxx>
34
35 #include <BRep_Tool.hxx>
36 #include <BRepGProp.hxx>
37 #include <BRepAdaptor_Curve.hxx>
38 #include <BRepBuilderAPI_MakeFace.hxx>
39
40 #include <TopAbs.hxx>
41 #include <TopExp.hxx>
42 #include <TopoDS.hxx>
43 #include <TopoDS_Shape.hxx>
44 #include <TopoDS_Face.hxx>
45 #include <TopoDS_Edge.hxx>
46 #include <TopoDS_Vertex.hxx>
47 #include <TopoDS_Iterator.hxx>
48 #include <TopExp_Explorer.hxx>
49 #include <TopLoc_Location.hxx>
50 #include <TopTools_MapOfShape.hxx>
51 #include <TopTools_Array1OfShape.hxx>
52 #include <TopTools_ListIteratorOfListOfShape.hxx>
53 #include <TopTools_IndexedMapOfShape.hxx>
54
55 #include <Geom_Surface.hxx>
56 #include <Geom_Plane.hxx>
57 #include <Geom_SphericalSurface.hxx>
58 #include <Geom_CylindricalSurface.hxx>
59 #include <GeomAdaptor_Surface.hxx>
60
61 #include <Geom2d_Curve.hxx>
62
63 #include <GProp_GProps.hxx>
64 #include <gp_Pnt.hxx>
65 #include <gp_Lin.hxx>
66 #include <TColStd_Array1OfReal.hxx>
67 #include <TColStd_HArray1OfInteger.hxx>
68 #include <TColStd_ListOfInteger.hxx>
69 #include <TColStd_ListIteratorOfListOfInteger.hxx>
70
71 //#include <OSD_Timer.hxx>
72
73 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
74
75 //=============================================================================
76 /*!
77  *   constructor:
78  */
79 //=============================================================================
80 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
81 : GEOM_IOperations(theEngine, theDocID)
82 {
83   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
84 }
85
86 //=============================================================================
87 /*!
88  *  destructor
89  */
90 //=============================================================================
91 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
92 {
93   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
94 }
95
96
97 //=============================================================================
98 /*!
99  *  MakeEdge
100  */
101 //=============================================================================
102 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
103                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
104 {
105   SetErrorCode(KO);
106
107   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
108
109   //Add a new Edge object
110   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
111
112   //Add a new Vector function
113   Handle(GEOM_Function) aFunction =
114     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
115
116   //Check if the function is set correctly
117   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
118
119   GEOMImpl_IVector aPI (aFunction);
120
121   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
122   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
123   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
124
125   aPI.SetPoint1(aRef1);
126   aPI.SetPoint2(aRef2);
127
128   //Compute the Edge value
129   try {
130     if (!GetSolver()->ComputeFunction(aFunction)) {
131       SetErrorCode("Vector driver failed");
132       return NULL;
133     }
134   }
135   catch (Standard_Failure) {
136     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
137     SetErrorCode(aFail->GetMessageString());
138     return NULL;
139   }
140
141   //Make a Python command
142   TCollection_AsciiString anEntry, aDescr;
143   TDF_Tool::Entry(anEdge->GetEntry(), anEntry);
144   aDescr += (anEntry+" = IShapesOperations.MakeEdge(");
145   TDF_Tool::Entry(thePnt1->GetEntry(), anEntry);
146   aDescr += (anEntry+", ");
147   TDF_Tool::Entry(thePnt2->GetEntry(), anEntry);
148   aDescr += (anEntry+")");
149
150   aFunction->SetDescription(aDescr);
151
152   SetErrorCode(OK);
153   return anEdge;
154 }
155
156 //=============================================================================
157 /*!
158  *  MakeWire
159  */
160 //=============================================================================
161 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
162                              (list<Handle(GEOM_Object)> theShapes)
163 {
164   return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
165 }
166
167 //=============================================================================
168 /*!
169  *  MakeFace
170  */
171 //=============================================================================
172 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
173                                                           const bool isPlanarWanted)
174 {
175   SetErrorCode(KO);
176
177   if (theWire.IsNull()) return NULL;
178
179   //Add a new Face object
180   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
181
182   //Add a new Shape function for creation of a face from a wire
183   Handle(GEOM_Function) aFunction =
184     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
185   if (aFunction.IsNull()) return NULL;
186
187   //Check if the function is set correctly
188   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
189
190   GEOMImpl_IShapes aCI (aFunction);
191
192   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
193
194   if (aRefWire.IsNull()) return NULL;
195
196   aCI.SetBase(aRefWire);
197   aCI.SetIsPlanar(isPlanarWanted);
198
199   //Compute the Face value
200   try {
201     if (!GetSolver()->ComputeFunction(aFunction)) {
202       SetErrorCode("Shape driver failed to compute a face");
203       return NULL;
204     }
205   }
206   catch (Standard_Failure) {
207     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
208     SetErrorCode(aFail->GetMessageString());
209     return NULL;
210   }
211
212   //Make a Python command
213   TCollection_AsciiString anEntry, aDescr;
214   TDF_Tool::Entry(aFace->GetEntry(), anEntry);
215   aDescr += anEntry;
216   aDescr += " = IShapesOperations.MakeFace(";
217   TDF_Tool::Entry(theWire->GetEntry(), anEntry);
218   aDescr += anEntry;
219   if (isPlanarWanted)
220     aDescr += ", 1)";
221
222   else
223     aDescr += ", 0)";
224
225   aFunction->SetDescription(aDescr);
226
227   SetErrorCode(OK);
228   return aFace;
229 }
230
231 //=============================================================================
232 /*!
233  *  MakeFaceWires
234  */
235 //=============================================================================
236 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
237                              (list<Handle(GEOM_Object)> theShapes,
238                               const bool isPlanarWanted)
239 {
240   SetErrorCode(KO);
241
242   //Add a new object
243   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
244
245   //Add a new function
246   Handle(GEOM_Function) aFunction =
247     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
248   if (aFunction.IsNull()) return NULL;
249
250   //Check if the function is set correctly
251   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
252
253   GEOMImpl_IShapes aCI (aFunction);
254
255   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
256
257   // Shapes
258   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
259   for (; it != theShapes.end(); it++) {
260     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
261     if (aRefSh.IsNull()) {
262       SetErrorCode("NULL argument shape for the face construction");
263       return NULL;
264     }
265     aShapesSeq->Append(aRefSh);
266   }
267   aCI.SetShapes(aShapesSeq);
268
269   aCI.SetIsPlanar(isPlanarWanted);
270
271   //Compute the shape
272   try {
273     if (!GetSolver()->ComputeFunction(aFunction)) {
274       SetErrorCode("Shape driver failed");
275       return NULL;
276     }
277   }
278   catch (Standard_Failure) {
279     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
280     SetErrorCode(aFail->GetMessageString());
281     return NULL;
282   }
283
284   //Make a Python command
285   TCollection_AsciiString anEntry, aDescr;
286   TDF_Tool::Entry(aShape->GetEntry(), anEntry);
287   aDescr += (anEntry + " = IShapesOperations.MakeFaceWires([");
288   // Shapes
289   it = theShapes.begin();
290   if (it != theShapes.end()) {
291     TDF_Tool::Entry((*it)->GetEntry(), anEntry);
292     it++;
293     aDescr += (anEntry+", ");
294     for (; it != theShapes.end(); it++) {
295       aDescr += ", ";
296       TDF_Tool::Entry((*it)->GetEntry(), anEntry);
297       aDescr += anEntry;
298     }
299   }
300   if (isPlanarWanted)
301     aDescr += "], 1)";
302
303   else
304     aDescr += "], 0)";
305
306   aFunction->SetDescription(aDescr);
307
308   SetErrorCode(OK);
309   return aShape;
310 }
311
312 //=============================================================================
313 /*!
314  *  MakeShell
315  */
316 //=============================================================================
317 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
318                              (list<Handle(GEOM_Object)> theShapes)
319 {
320   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
321 }
322
323 //=============================================================================
324 /*!
325  *  MakeSolidShells
326  */
327 //=============================================================================
328 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
329                              (list<Handle(GEOM_Object)> theShapes)
330 {
331   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolidShells");
332 }
333
334 //=============================================================================
335 /*!
336  *  MakeSolidShell
337  */
338 //=============================================================================
339 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
340 {
341   SetErrorCode(KO);
342
343   if (theShell.IsNull()) return NULL;
344
345   //Add a new Solid object
346   Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
347
348   //Add a new Solid function for creation of a solid from a shell
349   Handle(GEOM_Function) aFunction =
350     aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
351   if (aFunction.IsNull()) return NULL;
352
353   //Check if the function is set correctly
354   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
355
356   GEOMImpl_IShapes aCI (aFunction);
357
358   Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
359
360   if (aRefShell.IsNull()) return NULL;
361
362   aCI.SetBase(aRefShell);
363
364   //Compute the Solid value
365   try {
366     if (!GetSolver()->ComputeFunction(aFunction)) {
367       SetErrorCode("Solid driver failed");
368       return NULL;
369     }
370   }
371   catch (Standard_Failure) {
372     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
373     SetErrorCode(aFail->GetMessageString());
374     return NULL;
375   }
376
377   //Make a Python command
378   TCollection_AsciiString anEntry, aDescr("");
379   TDF_Tool::Entry(aSolid->GetEntry(), anEntry);
380   aDescr += anEntry;
381   aDescr += " = IShapesOperations.MakeSolidShell(";
382   TDF_Tool::Entry(theShell->GetEntry(), anEntry);
383   aDescr += (anEntry+")");
384
385   aFunction->SetDescription(aDescr);
386
387   SetErrorCode(OK);
388   return aSolid;
389 }
390
391 //=============================================================================
392 /*!
393  *  MakeCompound
394  */
395 //=============================================================================
396 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
397                              (list<Handle(GEOM_Object)> theShapes)
398 {
399   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
400 }
401
402 //=============================================================================
403 /*!
404  *  MakeShape
405  */
406 //=============================================================================
407 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
408                              (list<Handle(GEOM_Object)>     theShapes,
409                               const Standard_Integer        theObjectType,
410                               const Standard_Integer        theFunctionType,
411                               const TCollection_AsciiString theMethodName)
412 {
413   SetErrorCode(KO);
414
415   //Add a new object
416   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
417
418   //Add a new function
419   Handle(GEOM_Function) aFunction =
420     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
421   if (aFunction.IsNull()) return NULL;
422
423   //Check if the function is set correctly
424   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
425
426   GEOMImpl_IShapes aCI (aFunction);
427
428   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
429
430   // Shapes
431   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
432   for (; it != theShapes.end(); it++) {
433     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
434     if (aRefSh.IsNull()) {
435       SetErrorCode("NULL argument shape for the shape construction");
436       return NULL;
437     }
438     aShapesSeq->Append(aRefSh);
439   }
440   aCI.SetShapes(aShapesSeq);
441
442   //Compute the shape
443   try {
444     if (!GetSolver()->ComputeFunction(aFunction)) {
445       SetErrorCode("Shape driver failed");
446       return NULL;
447     }
448   }
449   catch (Standard_Failure) {
450     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
451     SetErrorCode(aFail->GetMessageString());
452     return NULL;
453   }
454
455   //Make a Python command
456   TCollection_AsciiString anEntry, aDescr("");
457   TDF_Tool::Entry(aShape->GetEntry(), anEntry);
458   aDescr += (anEntry + " = IShapesOperations.");
459   aDescr += (theMethodName + "([");
460   // Shapes
461   it = theShapes.begin();
462   if (it != theShapes.end()) {
463     TDF_Tool::Entry((*it)->GetEntry(), anEntry);
464     it++;
465     aDescr += (anEntry+", ");
466     for (; it != theShapes.end(); it++) {
467       aDescr += ", ";
468       TDF_Tool::Entry((*it)->GetEntry(), anEntry);
469       aDescr += anEntry;
470     }
471   }
472   aDescr += "])";
473
474   aFunction->SetDescription(aDescr);
475
476   SetErrorCode(OK);
477   return aShape;
478 }
479
480 //=============================================================================
481 /*!
482  *  MakeGlueFaces
483  */
484 //=============================================================================
485 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
486                                                 (Handle(GEOM_Object) theShape,
487                                                  const Standard_Real theTolerance)
488 {
489   SetErrorCode(KO);
490
491   if (theShape.IsNull()) return NULL;
492
493   //Add a new Glued object
494   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
495
496   //Add a new Glue function
497   Handle(GEOM_Function) aFunction;
498   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
499   if (aFunction.IsNull()) return NULL;
500
501   //Check if the function is set correctly
502   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
503
504   GEOMImpl_IGlue aCI (aFunction);
505
506   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
507   if (aRefShape.IsNull()) return NULL;
508
509   aCI.SetBase(aRefShape);
510   aCI.SetTolerance(theTolerance);
511
512   //Compute the sub-shape value
513   Standard_Boolean isWarning = Standard_False;
514   try {
515     if (!GetSolver()->ComputeFunction(aFunction)) {
516       SetErrorCode("Shape driver failed to glue faces");
517       return NULL;
518     }
519   }
520   catch (Standard_Failure) {
521     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
522     SetErrorCode(aFail->GetMessageString());
523     // to provide warning
524     if (!aFunction->GetValue().IsNull()) {
525       isWarning = Standard_True;
526     } else {
527       return NULL;
528     }
529   }
530
531   //Make a Python command
532   TCollection_AsciiString anEntry, aDescr;
533   TDF_Tool::Entry(aGlued->GetEntry(), anEntry);
534   aDescr += anEntry;
535   aDescr += " = IShapesOperations.MakeGlueFaces(";
536   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
537   aDescr += anEntry + ", ";
538   aDescr += TCollection_AsciiString(theTolerance) + ")";
539
540   aFunction->SetDescription(aDescr);
541
542   // to provide warning
543   if (!isWarning) SetErrorCode(OK);
544   return aGlued;
545 }
546
547 //=============================================================================
548 /*!
549  *  MakeExplode
550  */
551 //=============================================================================
552 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
553                                           (Handle(GEOM_Object)    theShape,
554                                            const Standard_Integer theShapeType,
555                                            const Standard_Boolean isSorted)
556 {
557 //  OSD_Timer timer1, timer2, timer3, timer4;
558 //  timer1.Start();
559
560   SetErrorCode(KO);
561
562   if (theShape.IsNull()) return NULL;
563   TopoDS_Shape aShape = theShape->GetValue();
564   if (aShape.IsNull()) return NULL;
565
566   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
567   Handle(GEOM_Object) anObj;
568   Handle(GEOM_Function) aFunction;
569   TopTools_MapOfShape mapShape;
570   TopTools_ListOfShape listShape;
571
572   if (aShape.ShapeType() == TopAbs_COMPOUND &&
573       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
574        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
575        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
576     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
577     for (; It.More(); It.Next()) {
578       if (mapShape.Add(It.Value())) {
579         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
580             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
581           listShape.Append(It.Value());
582         }
583       }
584     }
585   } else {
586     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
587     for (; exp.More(); exp.Next())
588       if (mapShape.Add(exp.Current()))
589         listShape.Append(exp.Current());
590   }
591
592   if (listShape.IsEmpty()) {
593     SetErrorCode("The given shape has no sub-shapes of the requested type");
594     return aSeq;
595   }
596
597 //  timer1.Stop();
598 //  timer2.Start();
599
600   if (isSorted)
601     SortShapes(listShape);
602
603 //  timer2.Stop();
604 //  timer3.Start();
605
606   TopTools_IndexedMapOfShape anIndices;
607   TopExp::MapShapes(aShape, anIndices);
608   Handle(TColStd_HArray1OfInteger) anArray;
609
610   TopTools_ListIteratorOfListOfShape itSub (listShape);
611   TCollection_AsciiString anAsciiList = "[", anEntry;
612   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
613     TopoDS_Shape aValue = itSub.Value();
614     anArray = new TColStd_HArray1OfInteger(1,1);
615     anArray->SetValue(1, anIndices.FindIndex(aValue));
616     anObj = GetEngine()->AddSubShape(theShape, anArray);
617     aSeq->Append(anObj);
618
619     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
620     anAsciiList += anEntry;
621     anAsciiList += ",";
622   }
623
624 //  timer3.Stop();
625 //  timer4.Start();
626
627   anAsciiList.Trunc(anAsciiList.Length() - 1);
628   anAsciiList += "]";
629
630   anAsciiList = TCollection_AsciiString("\n") + anAsciiList;
631
632   //The explode doesn't change object so no new function is requiered.
633   aFunction = theShape->GetLastFunction();
634
635   //Make a Python command
636   TCollection_AsciiString aDescr(anAsciiList);
637   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
638   aDescr += " = IShapesOperations.MakeExplode(";
639   aDescr += (anEntry + ",");
640   if (isSorted)
641     aDescr += (TCollection_AsciiString(theShapeType) + ", 1)");
642   else
643     aDescr += (TCollection_AsciiString(theShapeType) + ", 0)");
644
645   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
646   anOldDescr = anOldDescr + aDescr;
647   aFunction->SetDescription(anOldDescr);
648
649   SetErrorCode(OK);
650
651 //  timer4.Stop();
652
653 //  cout << "Explosure takes:" << endl;
654 //  timer1.Show();
655 //  cout << "Sorting takes:" << endl;
656 //  timer2.Show();
657 //  cout << "Sub-shapes addition takes:" << endl;
658 //  timer3.Show();
659 //  cout << "Update Description takes:" << endl;
660 //  timer4.Show();
661
662   return aSeq;
663 }
664
665 //=============================================================================
666 /*!
667  *  GetSubShapeAllIDs
668  */
669 //=============================================================================
670 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
671                                           (Handle(GEOM_Object)    theShape,
672                                            const Standard_Integer theShapeType,
673                                            const Standard_Boolean isSorted)
674 {
675   SetErrorCode(KO);
676
677   if (theShape.IsNull()) return NULL;
678   TopoDS_Shape aShape = theShape->GetValue();
679   if (aShape.IsNull()) return NULL;
680
681   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
682   TopTools_MapOfShape mapShape;
683   TopTools_ListOfShape listShape;
684
685   if (aShape.ShapeType() == TopAbs_COMPOUND &&
686       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
687        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
688        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
689     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
690     for (; It.More(); It.Next()) {
691       if (mapShape.Add(It.Value())) {
692         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
693             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
694           listShape.Append(It.Value());
695         }
696       }
697     }
698   } else {
699     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
700     for (; exp.More(); exp.Next())
701       if (mapShape.Add(exp.Current()))
702         listShape.Append(exp.Current());
703   }
704
705   if (listShape.IsEmpty()) {
706     SetErrorCode("The given shape has no sub-shapes of the requested type");
707     return aSeq;
708   }
709
710   if (isSorted)
711     SortShapes(listShape);
712
713   TopTools_IndexedMapOfShape anIndices;
714   TopExp::MapShapes(aShape, anIndices);
715   Handle(TColStd_HArray1OfInteger) anArray;
716
717   TopTools_ListIteratorOfListOfShape itSub (listShape);
718   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
719     TopoDS_Shape aValue = itSub.Value();
720     aSeq->Append(anIndices.FindIndex(aValue));
721   }
722
723   //The explode doesn't change object so no new function is required.
724   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
725
726   //Make a Python command
727   TCollection_AsciiString aDescr
728     ("\nlistSubShapeAllIDs = IShapesOperations.SubShapeAllIDs(");
729   TCollection_AsciiString anEntry;
730   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
731   aDescr += (anEntry + ",");
732   if (isSorted)
733     aDescr += (TCollection_AsciiString(theShapeType) + ", 1)");
734   else
735     aDescr += (TCollection_AsciiString(theShapeType) + ", 0)");
736
737   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
738   anOldDescr = anOldDescr + aDescr;
739   aFunction->SetDescription(anOldDescr);
740
741   SetErrorCode(OK);
742   return aSeq;
743 }
744
745 //=============================================================================
746 /*!
747  *  GetSubShape
748  */
749 //=============================================================================
750 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
751                                           (Handle(GEOM_Object)    theMainShape,
752                                            const Standard_Integer theID)
753 {
754   SetErrorCode(KO);
755
756   if (theMainShape.IsNull()) return NULL;
757
758   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
759   anArray->SetValue(1, theID);
760   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray);
761   if (anObj.IsNull()) {
762     SetErrorCode("Can not get a sub-shape with the given ID");
763     return NULL;
764   }
765
766   //The GetSubShape() doesn't change object so no new function is requiered.
767   Handle(GEOM_Function) aFunction = theMainShape->GetLastFunction();
768
769   //Make a Python command
770   TCollection_AsciiString aDescr ("\n");
771   TCollection_AsciiString anEntry;
772   TDF_Tool::Entry(anObj->GetEntry(), anEntry);
773   aDescr += anEntry + " = IShapesOperations.GetSubShape(";
774   TDF_Tool::Entry(theMainShape->GetEntry(), anEntry);
775   aDescr += anEntry + ", ";
776   aDescr += TCollection_AsciiString(theID) + ")";
777
778   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
779   anOldDescr = anOldDescr + aDescr;
780   aFunction->SetDescription(anOldDescr);
781
782   SetErrorCode(OK);
783   return anObj;
784 }
785
786
787 //=============================================================================
788 /*!
789  *  NumberOfFaces
790  */
791 //=============================================================================
792 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
793 {
794   SetErrorCode(KO);
795
796   Standard_Integer nb = 0;
797
798   if (theShape.IsNull()) return -1;
799   TopoDS_Shape aShape = theShape->GetValue();
800   if (aShape.IsNull()) return -1;
801
802   TopTools_MapOfShape mapShape;
803
804   TopExp_Explorer exp (aShape, TopAbs_FACE);
805   for (; exp.More(); exp.Next())
806     if (mapShape.Add(exp.Current()))
807       nb++;
808
809   SetErrorCode(OK);
810   return nb;
811 }
812
813 //=============================================================================
814 /*!
815  *  NumberOfEdges
816  */
817 //=============================================================================
818 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
819 {
820   SetErrorCode(KO);
821
822   Standard_Integer nb = 0;
823
824   if (theShape.IsNull()) return -1;
825   TopoDS_Shape aShape = theShape->GetValue();
826   if (aShape.IsNull()) return -1;
827
828   TopTools_MapOfShape mapShape;
829
830   TopExp_Explorer exp (aShape, TopAbs_EDGE);
831   for (; exp.More(); exp.Next())
832     if (mapShape.Add(exp.Current()))
833       nb++;
834
835   SetErrorCode(OK);
836   return nb;
837 }
838
839 //=============================================================================
840 /*!
841  *  ReverseShape
842  */
843 //=============================================================================
844 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
845 {
846   SetErrorCode(KO);
847
848   if (theShape.IsNull()) return NULL;
849
850   //Add a new reversed object
851   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
852
853   //Add a new Revese function
854   Handle(GEOM_Function) aFunction;
855   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
856   if (aFunction.IsNull()) return NULL;
857
858   //Check if the function is set correctly
859   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
860
861   GEOMImpl_IShapes aSI (aFunction);
862
863   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
864   if (aRefShape.IsNull()) return NULL;
865
866   aSI.SetBase(aRefShape);
867
868   //Compute the sub-shape value
869   try {
870     if (!GetSolver()->ComputeFunction(aFunction)) {
871       SetErrorCode("Shape driver failed to reverse shape");
872       return NULL;
873     }
874   }
875   catch (Standard_Failure) {
876     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
877     SetErrorCode(aFail->GetMessageString());
878     return NULL;
879   }
880
881   //Make a Python command
882   TCollection_AsciiString anEntry, aDescr;
883   TDF_Tool::Entry(aReversed->GetEntry(), anEntry);
884   aDescr += anEntry;
885   aDescr += " = IShapesOperations.ReverseShape(";
886   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
887   aDescr += anEntry + ")";
888
889   aFunction->SetDescription(aDescr);
890
891   SetErrorCode(OK);
892   return aReversed;
893 }
894
895 //=============================================================================
896 /*!
897  *  GetFreeFacesIDs
898  */
899 //=============================================================================
900 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
901                                                  (Handle(GEOM_Object) theShape)
902 {
903   SetErrorCode(KO);
904
905   if (theShape.IsNull()) return NULL;
906   TopoDS_Shape aShape = theShape->GetValue();
907   if (aShape.IsNull()) return NULL;
908
909   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
910
911   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
912   GEOMImpl_Block6Explorer::MapShapesAndAncestors
913     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
914
915   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
916
917   if (nbFaces == 0) {
918     SetErrorCode("The given shape has no faces");
919     return aSeq;
920   }
921
922   TopTools_IndexedMapOfShape anIndices;
923   TopExp::MapShapes(aShape, anIndices);
924
925   Standard_Integer id;
926   for (; ind <= nbFaces; ind++) {
927     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
928       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
929       aSeq->Append(id);
930     }
931   }
932
933   //The explode doesn't change object so no new function is required.
934   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
935
936   //Make a Python command
937   TCollection_AsciiString aDescr ("\nlistFreeFacesIDs = IShapesOperations.GetFreeFacesIDs(");
938   TCollection_AsciiString anEntry;
939   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
940   aDescr += (anEntry + ")");
941
942   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
943   anOldDescr = anOldDescr + aDescr;
944   aFunction->SetDescription(anOldDescr);
945
946   SetErrorCode(OK);
947   return aSeq;
948 }
949
950 //=============================================================================
951 /*!
952  *  GetSharedShapes
953  */
954 //=============================================================================
955 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
956                                                 (Handle(GEOM_Object)    theShape1,
957                                                  Handle(GEOM_Object)    theShape2,
958                                                  const Standard_Integer theShapeType)
959 {
960   SetErrorCode(KO);
961
962   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
963
964   TopoDS_Shape aShape1 = theShape1->GetValue();
965   TopoDS_Shape aShape2 = theShape2->GetValue();
966
967   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
968
969   TopTools_IndexedMapOfShape anIndices;
970   TopExp::MapShapes(aShape1, anIndices);
971   Handle(TColStd_HArray1OfInteger) anArray;
972
973   TopTools_IndexedMapOfShape mapShape1;
974   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
975
976   Handle(GEOM_Object) anObj;
977   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
978
979   TopTools_MapOfShape mapShape2;
980   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
981   for (; exp.More(); exp.Next()) {
982     TopoDS_Shape aSS = exp.Current();
983     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
984       anArray = new TColStd_HArray1OfInteger(1,1);
985       anArray->SetValue(1, anIndices.FindIndex(aSS));
986       anObj = GetEngine()->AddSubShape(theShape1, anArray);
987       aSeq->Append(anObj);
988     }
989   }
990
991   if (aSeq->IsEmpty()) {
992     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
993     return aSeq;
994   }
995
996   //The explode doesn't change object so no new function is required.
997   Handle(GEOM_Function) aFunction = theShape1->GetLastFunction();
998
999   //Make a Python command
1000   TCollection_AsciiString aDescr
1001     ("\nlistSharedShapes = IShapesOperations.GetSharedShapes(");
1002   TCollection_AsciiString anEntry;
1003   TDF_Tool::Entry(theShape1->GetEntry(), anEntry);
1004   aDescr += (anEntry + ",");
1005   TDF_Tool::Entry(theShape2->GetEntry(), anEntry);
1006   aDescr += (anEntry + ",");
1007   aDescr += TCollection_AsciiString(theShapeType) + ")";
1008
1009   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1010   anOldDescr = anOldDescr + aDescr;
1011   aFunction->SetDescription(anOldDescr);
1012
1013   SetErrorCode(OK);
1014   return aSeq;
1015 }
1016
1017 //=============================================================================
1018 /*!
1019  *  GetShapesOnPlane
1020  */
1021 //=============================================================================
1022 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
1023                                         (const Handle(GEOM_Object)& theShape,
1024                                          const Standard_Integer     theShapeType,
1025                                          const Handle(GEOM_Object)& theAx1,
1026                                          const GEOMAlgo_State       theState)
1027 {
1028   SetErrorCode(KO);
1029
1030   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1031
1032   TopoDS_Shape aShape = theShape->GetValue();
1033   TopoDS_Shape anAx1  = theAx1->GetValue();
1034
1035   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1036
1037   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1038   if (aShapeType != TopAbs_VERTEX &&
1039       aShapeType != TopAbs_EDGE &&
1040       aShapeType != TopAbs_FACE &&
1041       aShapeType != TopAbs_SOLID) {
1042     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1043     return NULL;
1044   }
1045
1046   // Create plane
1047   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1048   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1049   TopoDS_Vertex V1, V2;
1050   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1051   if (V1.IsNull() || V2.IsNull()) {
1052     SetErrorCode("Bad edge given for the plane normal vector");
1053     return NULL;
1054   }
1055   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1056   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1057   if (aVec.Magnitude() < Precision::Confusion()) {
1058     SetErrorCode("Vector with null magnitude given");
1059     return NULL;
1060   }
1061
1062   Handle(Geom_Plane) aPlane = new Geom_Plane(aLoc, aVec);
1063
1064   // Call algo
1065   GEOMAlgo_FinderShapeOn aFinder;
1066   Standard_Real aTol = 0.0001; // default value
1067
1068   aFinder.SetShape(aShape);
1069   aFinder.SetTolerance(aTol);
1070   aFinder.SetSurface(aPlane);
1071   aFinder.SetShapeType(aShapeType);
1072   aFinder.SetState(theState);
1073
1074   aFinder.Perform();
1075
1076   // Interprete results
1077   Standard_Integer iErr = aFinder.ErrorStatus();
1078   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
1079   if (iErr) {
1080     MESSAGE(" iErr : " << iErr);
1081     TCollection_AsciiString aMsg (" iErr : ");
1082     aMsg += TCollection_AsciiString(iErr);
1083     SetErrorCode(aMsg);
1084     return NULL;
1085   }
1086   Standard_Integer iWrn = aFinder.WarningStatus();
1087   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
1088   if (iWrn) {
1089     MESSAGE(" *** iWrn : " << iWrn);
1090   }
1091
1092   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1093
1094   if (listSS.Extent() < 1) {
1095     SetErrorCode("Not a single sub-shape of the requested type found on the given plane");
1096     return NULL;
1097   }
1098
1099   // Fill sequence of objects
1100   TopTools_IndexedMapOfShape anIndices;
1101   TopExp::MapShapes(aShape, anIndices);
1102
1103   Handle(GEOM_Object) anObj;
1104   Handle(TColStd_HArray1OfInteger) anArray;
1105   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1106
1107   TopTools_ListIteratorOfListOfShape itSub (listSS);
1108   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1109     int id = anIndices.FindIndex(itSub.Value());
1110     anArray = new TColStd_HArray1OfInteger(1,1);
1111     anArray->SetValue(1, id);
1112     anObj = GetEngine()->AddSubShape(theShape, anArray);
1113     aSeq->Append(anObj);
1114   }
1115   
1116   // The GetShapesOnPlane() doesn't change object so no new function is required.
1117   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1118
1119   // Make a Python command
1120   TCollection_AsciiString anEntry, aDescr
1121     ("\nlistShapesOnPlane = IShapesOperations.GetShapesOnPlane(");
1122   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1123   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1124   TDF_Tool::Entry(theAx1->GetEntry(), anEntry);
1125   aDescr += anEntry + ",";
1126   aDescr += TCollection_AsciiString(theState) + ")";
1127
1128   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1129   anOldDescr += aDescr;
1130   aFunction->SetDescription(anOldDescr);
1131
1132   SetErrorCode(OK);
1133   return aSeq;
1134 }
1135
1136 //=============================================================================
1137 /*!
1138  *  GetShapesOnCylinder
1139  */
1140 //=============================================================================
1141 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
1142                                           (const Handle(GEOM_Object)& theShape,
1143                                            const Standard_Integer     theShapeType,
1144                                            const Handle(GEOM_Object)& theAxis,
1145                                            const Standard_Real        theRadius,
1146                                            const GEOMAlgo_State       theState)
1147 {
1148   SetErrorCode(KO);
1149
1150   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1151
1152   TopoDS_Shape aShape = theShape->GetValue();
1153   TopoDS_Shape anAxis = theAxis->GetValue();
1154
1155   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1156
1157   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1158   if (aShapeType != TopAbs_VERTEX &&
1159       aShapeType != TopAbs_EDGE &&
1160       aShapeType != TopAbs_FACE &&
1161       aShapeType != TopAbs_SOLID) {
1162     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1163     return NULL;
1164   }
1165
1166   //Axis of the cylinder
1167   if (anAxis.ShapeType() != TopAbs_EDGE) {
1168     SetErrorCode("Not an edge given for the axis");
1169     return NULL;
1170   }
1171   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1172   TopoDS_Vertex V1, V2;
1173   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1174   if (V1.IsNull() || V2.IsNull()) {
1175     SetErrorCode("Bad edge given for the axis");
1176     return NULL;
1177   }
1178   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1179   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1180   if (aVec.Magnitude() < Precision::Confusion()) {
1181     SetErrorCode("Vector with null magnitude given");
1182     return NULL;
1183   }
1184
1185   gp_Ax3 anAx3 (aLoc, aVec);
1186   Handle(Geom_CylindricalSurface) aCylinder =
1187     new Geom_CylindricalSurface(anAx3, theRadius);
1188
1189   // Call algo
1190   GEOMAlgo_FinderShapeOn aFinder;
1191   Standard_Real aTol = 0.0001; // default value
1192
1193   aFinder.SetShape(aShape);
1194   aFinder.SetTolerance(aTol);
1195   aFinder.SetSurface(aCylinder);
1196   aFinder.SetShapeType(aShapeType);
1197   aFinder.SetState(theState);
1198
1199   aFinder.Perform();
1200
1201   // Interprete results
1202   Standard_Integer iErr = aFinder.ErrorStatus();
1203   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
1204   if (iErr) {
1205     MESSAGE(" iErr : " << iErr);
1206     TCollection_AsciiString aMsg (" iErr : ");
1207     aMsg += TCollection_AsciiString(iErr);
1208     SetErrorCode(aMsg);
1209     return NULL;
1210   }
1211   Standard_Integer iWrn = aFinder.WarningStatus();
1212   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
1213   if (iWrn) {
1214     MESSAGE(" *** iWrn : " << iWrn);
1215   }
1216
1217   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1218
1219   if (listSS.Extent() < 1) {
1220     SetErrorCode("Not a single sub-shape of the requested type found on the given cylinder");
1221     return NULL;
1222   }
1223
1224   // Fill sequence of objects
1225   TopTools_IndexedMapOfShape anIndices;
1226   TopExp::MapShapes(aShape, anIndices);
1227
1228   Handle(GEOM_Object) anObj;
1229   Handle(TColStd_HArray1OfInteger) anArray;
1230   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1231
1232   TopTools_ListIteratorOfListOfShape itSub (listSS);
1233   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1234     int id = anIndices.FindIndex(itSub.Value());
1235     anArray = new TColStd_HArray1OfInteger(1,1);
1236     anArray->SetValue(1, id);
1237     anObj = GetEngine()->AddSubShape(theShape, anArray);
1238     aSeq->Append(anObj);
1239   }
1240   
1241   // The GetShapesOnCylinder() doesn't change object so no new function is required.
1242   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1243
1244   // Make a Python command
1245   TCollection_AsciiString anEntry, aDescr
1246     ("\nlistShapesOnCylinder = IShapesOperations.GetShapesOnCylinder(");
1247   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1248   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1249   TDF_Tool::Entry(theAxis->GetEntry(), anEntry);
1250   aDescr += anEntry + ",";
1251   aDescr += TCollection_AsciiString(theRadius) + ",";
1252   aDescr += TCollection_AsciiString(theState) + ")";
1253
1254   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1255   anOldDescr += aDescr;
1256   aFunction->SetDescription(anOldDescr);
1257
1258   SetErrorCode(OK);
1259   return aSeq;
1260 }
1261
1262 //=============================================================================
1263 /*!
1264  *  GetShapesOnSphere
1265  */
1266 //=============================================================================
1267 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
1268                                           (const Handle(GEOM_Object)& theShape,
1269                                            const Standard_Integer     theShapeType,
1270                                            const Handle(GEOM_Object)& theCenter,
1271                                            const Standard_Real        theRadius,
1272                                            const GEOMAlgo_State       theState)
1273 {
1274   SetErrorCode(KO);
1275
1276   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1277
1278   TopoDS_Shape aShape  = theShape->GetValue();
1279   TopoDS_Shape aCenter = theCenter->GetValue();
1280
1281   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1282
1283   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1284   if (aShapeType != TopAbs_VERTEX &&
1285       aShapeType != TopAbs_EDGE &&
1286       aShapeType != TopAbs_FACE &&
1287       aShapeType != TopAbs_SOLID) {
1288     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
1289     return NULL;
1290   }
1291
1292   // Center of the sphere
1293   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1294   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1295
1296   gp_Ax3 anAx3 (aLoc, gp::DZ());
1297   Handle(Geom_SphericalSurface) aSphere =
1298     new Geom_SphericalSurface(anAx3, theRadius);
1299
1300   // Call algo
1301   GEOMAlgo_FinderShapeOn aFinder;
1302   Standard_Real aTol = 0.0001; // default value
1303
1304   aFinder.SetShape(aShape);
1305   aFinder.SetTolerance(aTol);
1306   aFinder.SetSurface(aSphere);
1307   aFinder.SetShapeType(aShapeType);
1308   aFinder.SetState(theState);
1309
1310   aFinder.Perform();
1311
1312   // Interprete results
1313   Standard_Integer iErr = aFinder.ErrorStatus();
1314   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
1315   if (iErr) {
1316     MESSAGE(" iErr : " << iErr);
1317     TCollection_AsciiString aMsg (" iErr : ");
1318     aMsg += TCollection_AsciiString(iErr);
1319     SetErrorCode(aMsg);
1320     return NULL;
1321   }
1322   Standard_Integer iWrn = aFinder.WarningStatus();
1323   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
1324   if (iWrn) {
1325     MESSAGE(" *** iWrn : " << iWrn);
1326   }
1327
1328   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1329
1330   if (listSS.Extent() < 1) {
1331     SetErrorCode("Not a single sub-shape of the requested type found on the given sphere");
1332     return NULL;
1333   }
1334
1335   // Fill sequence of objects
1336   TopTools_IndexedMapOfShape anIndices;
1337   TopExp::MapShapes(aShape, anIndices);
1338
1339   Handle(GEOM_Object) anObj;
1340   Handle(TColStd_HArray1OfInteger) anArray;
1341   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1342
1343   TopTools_ListIteratorOfListOfShape itSub (listSS);
1344   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1345     int id = anIndices.FindIndex(itSub.Value());
1346     anArray = new TColStd_HArray1OfInteger(1,1);
1347     anArray->SetValue(1, id);
1348     anObj = GetEngine()->AddSubShape(theShape, anArray);
1349     aSeq->Append(anObj);
1350   }
1351   
1352   // The GetShapesOnSphere() doesn't change object so no new function is required.
1353   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1354
1355   // Make a Python command
1356   TCollection_AsciiString anEntry, aDescr
1357     ("\nlistShapesOnSphere = IShapesOperations.GetShapesOnSphere(");
1358   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1359   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1360   TDF_Tool::Entry(theCenter->GetEntry(), anEntry);
1361   aDescr += anEntry + ",";
1362   aDescr += TCollection_AsciiString(theRadius) + ",";
1363   aDescr += TCollection_AsciiString(theState) + ")";
1364
1365   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1366   anOldDescr += aDescr;
1367   aFunction->SetDescription(anOldDescr);
1368
1369   SetErrorCode(OK);
1370   return aSeq;
1371 }
1372
1373 //=============================================================================
1374 /*!
1375  *  GetInPlace
1376  */
1377 //=============================================================================
1378 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
1379                                           (Handle(GEOM_Object) theShapeWhere,
1380                                            Handle(GEOM_Object) theShapeWhat)
1381 {
1382   SetErrorCode(KO);
1383
1384   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
1385
1386   TopoDS_Shape aWhere = theShapeWhere->GetValue();
1387   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
1388
1389   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
1390
1391   //Fill array of indices
1392   Handle(TColStd_HArray1OfInteger) aModifiedArray;
1393
1394   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
1395
1396   TopTools_IndexedMapOfShape aWhereIndices;
1397   TopExp::MapShapes(aWhere, aWhereIndices);
1398
1399   if (aWhereIndices.Contains(aWhat)) {
1400
1401     // entity was not changed by the operation
1402     Standard_Integer aWhatIndex = aWhereIndices.FindIndex(aWhat);
1403     aModifiedArray = new TColStd_HArray1OfInteger(1,1);
1404     aModifiedArray->SetValue(1, aWhatIndex);
1405
1406   } else {
1407
1408     TDF_Label aHistoryLabel = aWhereFunction->GetHistoryEntry(Standard_False);
1409     if (aHistoryLabel.IsNull()) {
1410       SetErrorCode("Modifications history does not exist for the shape under consideration.");
1411       return NULL;
1412     }
1413
1414     // search in history for all argument shapes
1415     Standard_Boolean isFound = Standard_False;
1416
1417     TDF_LabelSequence aLabelSeq;
1418     aWhereFunction->GetDependency(aLabelSeq);
1419     Standard_Integer nbArg = aLabelSeq.Length();
1420
1421     for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
1422
1423       TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
1424
1425       Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
1426       TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
1427
1428       TopTools_IndexedMapOfShape anArgumentIndices;
1429       TopExp::MapShapes(anArgumentShape, anArgumentIndices);
1430
1431       if (anArgumentIndices.Contains(aWhat)) {
1432         isFound = Standard_True;
1433         Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(aWhat);
1434
1435         // Find corresponding label in history
1436         TDF_Label anArgumentHistoryLabel =
1437           aWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
1438         if (anArgumentHistoryLabel.IsNull()) {
1439           // Lost History of operation argument. Possibly, all its entities was removed.
1440           SetErrorCode(OK);
1441           return NULL;
1442         }
1443
1444         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
1445         if (aWhatHistoryLabel.IsNull()) {
1446           // Removed entity
1447           SetErrorCode(OK);
1448           return NULL;
1449         }
1450
1451         Handle(TDataStd_IntegerArray) anIntegerArray;
1452         if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
1453           SetErrorCode("Error: Empty modifications history for the sought shape.");
1454           return NULL;
1455         }
1456
1457         aModifiedArray = anIntegerArray->Array();
1458         if (aModifiedArray->Length() == 0) {
1459           SetErrorCode("Error: Empty modifications history for the sought shape.");
1460           return NULL;
1461         }
1462       }
1463     }
1464
1465     if (!isFound) {
1466       SetErrorCode("The sought shape does not belong to any operation argument.");
1467       return NULL;
1468     }
1469   }
1470
1471   //Add a new object
1472   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
1473
1474   if (aModifiedArray->Length() > 1) {
1475     //Set a GROUP type
1476     aResult->SetType(GEOM_GROUP);
1477
1478     //Set a sub shape type
1479     TDF_Label aFreeLabel = aResult->GetFreeLabel();
1480     TopAbs_ShapeEnum aShapeType = aWhat.ShapeType();
1481     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
1482   }
1483
1484   //Make a Python command
1485   TCollection_AsciiString anEntry, aDescr;
1486   TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1487   aDescr += anEntry;
1488   aDescr += " = IShapesOperations.GetInPlace(";
1489   TDF_Tool::Entry(theShapeWhere->GetEntry(), anEntry);
1490   aDescr += anEntry + ",";
1491   TDF_Tool::Entry(theShapeWhat->GetEntry(), anEntry);
1492   aDescr += anEntry + ")";
1493
1494   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
1495   aFunction->SetDescription(aDescr);
1496
1497   SetErrorCode(OK);
1498   return aResult;
1499 }
1500
1501 //=======================================================================
1502 //function : SortShapes
1503 //purpose  :
1504 //=======================================================================
1505 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
1506 {
1507   Standard_Integer MaxShapes = SL.Extent();
1508   TopTools_Array1OfShape  aShapes (1,MaxShapes);
1509   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
1510   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
1511   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
1512
1513   // Computing of CentreOfMass
1514   Standard_Integer Index;
1515   GProp_GProps GPr;
1516   gp_Pnt GPoint;
1517   TopTools_ListIteratorOfListOfShape it(SL);
1518   for (Index=1;  it.More();  Index++)
1519   {
1520     TopoDS_Shape S = it.Value();
1521     SL.Remove( it ); // == it.Next()
1522     aShapes(Index) = S;
1523     OrderInd.SetValue (Index, Index);
1524     if (S.ShapeType() == TopAbs_VERTEX)
1525     {
1526       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
1527       Length.SetValue( Index, (Standard_Real) S.Orientation());
1528     }
1529     else
1530     {
1531       BRepGProp::LinearProperties (S, GPr);
1532       GPoint = GPr.CentreOfMass();
1533       Length.SetValue( Index, GPr.Mass() );
1534     }
1535     MidXYZ.SetValue(Index,
1536                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
1537   }
1538   // Sorting
1539   Standard_Integer aTemp;
1540   Standard_Boolean exchange, Sort = Standard_True;
1541   while (Sort)
1542   {
1543     Sort = Standard_False;
1544     for (Index=1; Index < MaxShapes; Index++)
1545     {
1546       if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
1547         exchange = Standard_True;
1548       else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
1549                Length(OrderInd(Index)) >  Length(OrderInd(Index+1)) )
1550         exchange = Standard_True;
1551       else
1552         exchange = Standard_False;
1553       if (exchange)
1554       {
1555         aTemp = OrderInd(Index);
1556         OrderInd(Index) = OrderInd(Index+1);
1557         OrderInd(Index+1) = aTemp;
1558         Sort = Standard_True;
1559       }
1560     }
1561   }
1562   for (Index=1; Index <= MaxShapes; Index++)
1563     SL.Append( aShapes( OrderInd(Index) ));
1564 }