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