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