Salome HOME
PAL7508: Development of GetInPlace() functionality
[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     SetErrorCode("Only vertices, edges or faces can be found by this method");
1042     return NULL;
1043   }
1044
1045   // Create plane
1046   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
1047   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
1048   TopoDS_Vertex V1, V2;
1049   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1050   if (V1.IsNull() || V2.IsNull()) {
1051     SetErrorCode("Bad edge given for the plane normal vector");
1052     return NULL;
1053   }
1054   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1055   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1056   if (aVec.Magnitude() < Precision::Confusion()) {
1057     SetErrorCode("Vector with null magnitude given");
1058     return NULL;
1059   }
1060
1061   Handle(Geom_Plane) aPlane = new Geom_Plane(aLoc, aVec);
1062
1063   // Call algo
1064   GEOMAlgo_FinderShapeOn aFinder;
1065   Standard_Real aTol = 0.0001; // default value
1066
1067   aFinder.SetShape(aShape);
1068   aFinder.SetTolerance(aTol);
1069   aFinder.SetSurface(aPlane);
1070   aFinder.SetShapeType(aShapeType);
1071   aFinder.SetState(theState);
1072
1073   aFinder.Perform();
1074
1075   // Interprete results
1076   Standard_Integer iErr = aFinder.ErrorStatus();
1077   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
1078   if (iErr) {
1079     MESSAGE(" iErr : " << iErr);
1080     TCollection_AsciiString aMsg (" iErr : ");
1081     aMsg += TCollection_AsciiString(iErr);
1082     SetErrorCode(aMsg);
1083     return NULL;
1084   }
1085   Standard_Integer iWrn = aFinder.WarningStatus();
1086   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
1087   if (iWrn) {
1088     MESSAGE(" *** iWrn : " << iWrn);
1089   }
1090
1091   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1092
1093   if (listSS.Extent() < 1) {
1094     SetErrorCode("Not a single sub-shape of the requested type found on the given plane");
1095     return NULL;
1096   }
1097
1098   // Fill sequence of objects
1099   TopTools_IndexedMapOfShape anIndices;
1100   TopExp::MapShapes(aShape, anIndices);
1101
1102   Handle(GEOM_Object) anObj;
1103   Handle(TColStd_HArray1OfInteger) anArray;
1104   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1105
1106   TopTools_ListIteratorOfListOfShape itSub (listSS);
1107   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1108     int id = anIndices.FindIndex(itSub.Value());
1109     anArray = new TColStd_HArray1OfInteger(1,1);
1110     anArray->SetValue(1, id);
1111     anObj = GetEngine()->AddSubShape(theShape, anArray);
1112     aSeq->Append(anObj);
1113   }
1114   
1115   // The GetShapesOnPlane() doesn't change object so no new function is required.
1116   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1117
1118   // Make a Python command
1119   TCollection_AsciiString anEntry, aDescr
1120     ("\nlistShapesOnPlane = IShapesOperations.GetShapesOnPlane(");
1121   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1122   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1123   TDF_Tool::Entry(theAx1->GetEntry(), anEntry);
1124   aDescr += anEntry + ",";
1125   aDescr += TCollection_AsciiString(theState) + ")";
1126
1127   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1128   anOldDescr += aDescr;
1129   aFunction->SetDescription(anOldDescr);
1130
1131   SetErrorCode(OK);
1132   return aSeq;
1133 }
1134
1135 //=============================================================================
1136 /*!
1137  *  GetShapesOnCylinder
1138  */
1139 //=============================================================================
1140 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
1141                                           (const Handle(GEOM_Object)& theShape,
1142                                            const Standard_Integer     theShapeType,
1143                                            const Handle(GEOM_Object)& theAxis,
1144                                            const Standard_Real        theRadius,
1145                                            const GEOMAlgo_State       theState)
1146 {
1147   SetErrorCode(KO);
1148
1149   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1150
1151   TopoDS_Shape aShape = theShape->GetValue();
1152   TopoDS_Shape anAxis = theAxis->GetValue();
1153
1154   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1155
1156   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1157   if (aShapeType != TopAbs_VERTEX &&
1158       aShapeType != TopAbs_EDGE &&
1159       aShapeType != TopAbs_FACE) {
1160     SetErrorCode("Only vertices, edges or faces can be found by this method");
1161     return NULL;
1162   }
1163
1164   //Axis of the cylinder
1165   if (anAxis.ShapeType() != TopAbs_EDGE) {
1166     SetErrorCode("Not an edge given for the axis");
1167     return NULL;
1168   }
1169   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1170   TopoDS_Vertex V1, V2;
1171   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1172   if (V1.IsNull() || V2.IsNull()) {
1173     SetErrorCode("Bad edge given for the axis");
1174     return NULL;
1175   }
1176   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1177   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1178   if (aVec.Magnitude() < Precision::Confusion()) {
1179     SetErrorCode("Vector with null magnitude given");
1180     return NULL;
1181   }
1182
1183   gp_Ax3 anAx3 (aLoc, aVec);
1184   Handle(Geom_CylindricalSurface) aCylinder =
1185     new Geom_CylindricalSurface(anAx3, theRadius);
1186
1187   // Call algo
1188   GEOMAlgo_FinderShapeOn aFinder;
1189   Standard_Real aTol = 0.0001; // default value
1190
1191   aFinder.SetShape(aShape);
1192   aFinder.SetTolerance(aTol);
1193   aFinder.SetSurface(aCylinder);
1194   aFinder.SetShapeType(aShapeType);
1195   aFinder.SetState(theState);
1196
1197   aFinder.Perform();
1198
1199   // Interprete results
1200   Standard_Integer iErr = aFinder.ErrorStatus();
1201   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
1202   if (iErr) {
1203     MESSAGE(" iErr : " << iErr);
1204     TCollection_AsciiString aMsg (" iErr : ");
1205     aMsg += TCollection_AsciiString(iErr);
1206     SetErrorCode(aMsg);
1207     return NULL;
1208   }
1209   Standard_Integer iWrn = aFinder.WarningStatus();
1210   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
1211   if (iWrn) {
1212     MESSAGE(" *** iWrn : " << iWrn);
1213   }
1214
1215   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1216
1217   if (listSS.Extent() < 1) {
1218     SetErrorCode("Not a single sub-shape of the requested type found on the given cylinder");
1219     return NULL;
1220   }
1221
1222   // Fill sequence of objects
1223   TopTools_IndexedMapOfShape anIndices;
1224   TopExp::MapShapes(aShape, anIndices);
1225
1226   Handle(GEOM_Object) anObj;
1227   Handle(TColStd_HArray1OfInteger) anArray;
1228   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1229
1230   TopTools_ListIteratorOfListOfShape itSub (listSS);
1231   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1232     int id = anIndices.FindIndex(itSub.Value());
1233     anArray = new TColStd_HArray1OfInteger(1,1);
1234     anArray->SetValue(1, id);
1235     anObj = GetEngine()->AddSubShape(theShape, anArray);
1236     aSeq->Append(anObj);
1237   }
1238   
1239   // The GetShapesOnCylinder() doesn't change object so no new function is required.
1240   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1241
1242   // Make a Python command
1243   TCollection_AsciiString anEntry, aDescr
1244     ("\nlistShapesOnCylinder = IShapesOperations.GetShapesOnCylinder(");
1245   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1246   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1247   TDF_Tool::Entry(theAxis->GetEntry(), anEntry);
1248   aDescr += anEntry + ",";
1249   aDescr += TCollection_AsciiString(theRadius) + ",";
1250   aDescr += TCollection_AsciiString(theState) + ")";
1251
1252   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1253   anOldDescr += aDescr;
1254   aFunction->SetDescription(anOldDescr);
1255
1256   SetErrorCode(OK);
1257   return aSeq;
1258 }
1259
1260 //=============================================================================
1261 /*!
1262  *  GetShapesOnSphere
1263  */
1264 //=============================================================================
1265 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
1266                                           (const Handle(GEOM_Object)& theShape,
1267                                            const Standard_Integer     theShapeType,
1268                                            const Handle(GEOM_Object)& theCenter,
1269                                            const Standard_Real        theRadius,
1270                                            const GEOMAlgo_State       theState)
1271 {
1272   SetErrorCode(KO);
1273
1274   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1275
1276   TopoDS_Shape aShape  = theShape->GetValue();
1277   TopoDS_Shape aCenter = theCenter->GetValue();
1278
1279   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1280
1281   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1282   if (aShapeType != TopAbs_VERTEX &&
1283       aShapeType != TopAbs_EDGE &&
1284       aShapeType != TopAbs_FACE) {
1285     SetErrorCode("Only vertices, edges or faces can be found by this method");
1286     return NULL;
1287   }
1288
1289   // Center of the sphere
1290   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1291   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1292
1293   gp_Ax3 anAx3 (aLoc, gp::DZ());
1294   Handle(Geom_SphericalSurface) aSphere =
1295     new Geom_SphericalSurface(anAx3, theRadius);
1296
1297   // Call algo
1298   GEOMAlgo_FinderShapeOn aFinder;
1299   Standard_Real aTol = 0.0001; // default value
1300
1301   aFinder.SetShape(aShape);
1302   aFinder.SetTolerance(aTol);
1303   aFinder.SetSurface(aSphere);
1304   aFinder.SetShapeType(aShapeType);
1305   aFinder.SetState(theState);
1306
1307   aFinder.Perform();
1308
1309   // Interprete results
1310   Standard_Integer iErr = aFinder.ErrorStatus();
1311   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
1312   if (iErr) {
1313     MESSAGE(" iErr : " << iErr);
1314     TCollection_AsciiString aMsg (" iErr : ");
1315     aMsg += TCollection_AsciiString(iErr);
1316     SetErrorCode(aMsg);
1317     return NULL;
1318   }
1319   Standard_Integer iWrn = aFinder.WarningStatus();
1320   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
1321   if (iWrn) {
1322     MESSAGE(" *** iWrn : " << iWrn);
1323   }
1324
1325   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1326
1327   if (listSS.Extent() < 1) {
1328     SetErrorCode("Not a single sub-shape of the requested type found on the given sphere");
1329     return NULL;
1330   }
1331
1332   // Fill sequence of objects
1333   TopTools_IndexedMapOfShape anIndices;
1334   TopExp::MapShapes(aShape, anIndices);
1335
1336   Handle(GEOM_Object) anObj;
1337   Handle(TColStd_HArray1OfInteger) anArray;
1338   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1339
1340   TopTools_ListIteratorOfListOfShape itSub (listSS);
1341   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1342     int id = anIndices.FindIndex(itSub.Value());
1343     anArray = new TColStd_HArray1OfInteger(1,1);
1344     anArray->SetValue(1, id);
1345     anObj = GetEngine()->AddSubShape(theShape, anArray);
1346     aSeq->Append(anObj);
1347   }
1348   
1349   // The GetShapesOnSphere() doesn't change object so no new function is required.
1350   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1351
1352   // Make a Python command
1353   TCollection_AsciiString anEntry, aDescr
1354     ("\nlistShapesOnSphere = IShapesOperations.GetShapesOnSphere(");
1355   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1356   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1357   TDF_Tool::Entry(theCenter->GetEntry(), anEntry);
1358   aDescr += anEntry + ",";
1359   aDescr += TCollection_AsciiString(theRadius) + ",";
1360   aDescr += TCollection_AsciiString(theState) + ")";
1361
1362   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1363   anOldDescr += aDescr;
1364   aFunction->SetDescription(anOldDescr);
1365
1366   SetErrorCode(OK);
1367   return aSeq;
1368 }
1369
1370 //=============================================================================
1371 /*!
1372  *  GetInPlace
1373  */
1374 //=============================================================================
1375 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
1376                                           (Handle(GEOM_Object) theShapeWhere,
1377                                            Handle(GEOM_Object) theShapeWhat)
1378 {
1379   SetErrorCode(KO);
1380
1381   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
1382
1383   TopoDS_Shape aWhere = theShapeWhere->GetValue();
1384   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
1385
1386   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
1387
1388   //Fill array of indices
1389   Handle(TColStd_HArray1OfInteger) aModifiedArray;
1390
1391   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
1392
1393   TopTools_IndexedMapOfShape aWhereIndices;
1394   TopExp::MapShapes(aWhere, aWhereIndices);
1395
1396   if (aWhereIndices.Contains(aWhat)) {
1397
1398     // entity was not changed by the operation
1399     Standard_Integer aWhatIndex = aWhereIndices.FindIndex(aWhat);
1400     aModifiedArray = new TColStd_HArray1OfInteger(1,1);
1401     aModifiedArray->SetValue(1, aWhatIndex);
1402
1403   } else {
1404
1405     TDF_Label aHistoryLabel = aWhereFunction->GetHistoryEntry(Standard_False);
1406     if (aHistoryLabel.IsNull()) {
1407       SetErrorCode("History for an operation, produced the shape, does not exist.");
1408       return NULL;
1409     }
1410
1411     // search in history for all argument shapes
1412     Standard_Boolean isFound = Standard_False;
1413
1414     TDF_LabelSequence aLabelSeq;
1415     aWhereFunction->GetDependency(aLabelSeq);
1416     Standard_Integer nbArg = aLabelSeq.Length();
1417
1418     for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
1419
1420       TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
1421
1422       Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
1423       TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
1424
1425       TopTools_IndexedMapOfShape anArgumentIndices;
1426       TopExp::MapShapes(anArgumentShape, anArgumentIndices);
1427
1428       if (anArgumentIndices.Contains(aWhat)) {
1429         isFound = Standard_True;
1430         Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(aWhat);
1431
1432         // Find corresponding label in history
1433         TDF_Label anArgumentHistoryLabel =
1434           aWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
1435         if (anArgumentHistoryLabel.IsNull()) {
1436           SetErrorCode("History for this entity does not exist.");
1437           return NULL;
1438         }
1439
1440         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
1441         if (aWhatHistoryLabel.IsNull()) {
1442           SetErrorCode("History for this entity does not exist.");
1443           return NULL;
1444         }
1445
1446         Handle(TDataStd_IntegerArray) anIntegerArray;
1447         if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
1448           SetErrorCode("Empty history. Possibly, this entity is absent in result.");
1449           return NULL;
1450         }
1451
1452         aModifiedArray = anIntegerArray->Array();
1453         if (aModifiedArray->Length() == 0) {
1454           SetErrorCode("This entity is absent in result.");
1455           return NULL;
1456         }
1457       }
1458     }
1459
1460     if (!isFound) {
1461       SetErrorCode("Not found in arguments.");
1462       return NULL;
1463     }
1464   }
1465
1466   //Add a new object
1467   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
1468
1469   if (aModifiedArray->Length() > 1) {
1470     //Set a GROUP type
1471     aResult->SetType(GEOM_GROUP);
1472
1473     //Set a sub shape type
1474     TDF_Label aFreeLabel = aResult->GetFreeLabel();
1475     TopAbs_ShapeEnum aShapeType = aWhat.ShapeType();
1476     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
1477   }
1478
1479   //Make a Python command
1480   TCollection_AsciiString anEntry, aDescr;
1481   TDF_Tool::Entry(aResult->GetEntry(), anEntry);
1482   aDescr += anEntry;
1483   aDescr += " = IShapesOperations.GetInPlace(";
1484   TDF_Tool::Entry(theShapeWhere->GetEntry(), anEntry);
1485   aDescr += anEntry + ",";
1486   TDF_Tool::Entry(theShapeWhat->GetEntry(), anEntry);
1487   aDescr += anEntry + ")";
1488
1489   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
1490   aFunction->SetDescription(aDescr);
1491
1492   SetErrorCode(OK);
1493   return aResult;
1494 }
1495
1496 //=======================================================================
1497 //function : SortShapes
1498 //purpose  :
1499 //=======================================================================
1500 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
1501 {
1502   Standard_Integer MaxShapes = SL.Extent();
1503   TopTools_Array1OfShape  aShapes (1,MaxShapes);
1504   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
1505   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
1506   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
1507
1508   // Computing of CentreOfMass
1509   Standard_Integer Index;
1510   GProp_GProps GPr;
1511   gp_Pnt GPoint;
1512   TopTools_ListIteratorOfListOfShape it(SL);
1513   for (Index=1;  it.More();  Index++)
1514   {
1515     TopoDS_Shape S = it.Value();
1516     SL.Remove( it ); // == it.Next()
1517     aShapes(Index) = S;
1518     OrderInd.SetValue (Index, Index);
1519     if (S.ShapeType() == TopAbs_VERTEX)
1520     {
1521       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
1522       Length.SetValue( Index, (Standard_Real) S.Orientation());
1523     }
1524     else
1525     {
1526       BRepGProp::LinearProperties (S, GPr);
1527       GPoint = GPr.CentreOfMass();
1528       Length.SetValue( Index, GPr.Mass() );
1529     }
1530     MidXYZ.SetValue(Index,
1531                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
1532   }
1533   // Sorting
1534   Standard_Integer aTemp;
1535   Standard_Boolean exchange, Sort = Standard_True;
1536   while (Sort)
1537   {
1538     Sort = Standard_False;
1539     for (Index=1; Index < MaxShapes; Index++)
1540     {
1541       if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
1542         exchange = Standard_True;
1543       else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
1544                Length(OrderInd(Index)) >  Length(OrderInd(Index+1)) )
1545         exchange = Standard_True;
1546       else
1547         exchange = Standard_False;
1548       if (exchange)
1549       {
1550         aTemp = OrderInd(Index);
1551         OrderInd(Index) = OrderInd(Index+1);
1552         OrderInd(Index+1) = aTemp;
1553         Sort = Standard_True;
1554       }
1555     }
1556   }
1557   for (Index=1; Index <= MaxShapes; Index++)
1558     SL.Append( aShapes( OrderInd(Index) ));
1559 }