Salome HOME
60ef003672c766723fe7b33d2032d5ee8b461143
[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("Not implemented for the given sub-shape type");
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   // The "-" is because interpretation of normale differs
1060   // between interface and algorithm for the case of plane
1061
1062   // Call algo
1063   GEOMAlgo_FinderShapeOn aFinder;
1064   Standard_Real aTol = 0.0001; // default value
1065
1066   aFinder.SetShape(aShape);
1067   aFinder.SetTolerance(aTol);
1068   aFinder.SetSurface(aPlane);
1069   aFinder.SetShapeType(aShapeType);
1070   aFinder.SetState(theState);
1071
1072   aFinder.Perform();
1073
1074   // Interprete results
1075   Standard_Integer iErr = aFinder.ErrorStatus();
1076   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
1077   if (iErr) {
1078     MESSAGE(" iErr : " << iErr);
1079     TCollection_AsciiString aMsg (" iErr : ");
1080     aMsg += TCollection_AsciiString(iErr);
1081     SetErrorCode(aMsg);
1082     return NULL;
1083   }
1084   Standard_Integer iWrn = aFinder.WarningStatus();
1085   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
1086   if (iWrn) {
1087     MESSAGE(" *** iWrn : " << iWrn);
1088   }
1089
1090   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1091
1092   if (listSS.Extent() < 1) {
1093     SetErrorCode("Not a single sub-shape of the requested type found on the given plane");
1094     return NULL;
1095   }
1096
1097   // Fill sequence of objects
1098   TopTools_IndexedMapOfShape anIndices;
1099   TopExp::MapShapes(aShape, anIndices);
1100
1101   Handle(GEOM_Object) anObj;
1102   Handle(TColStd_HArray1OfInteger) anArray;
1103   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1104
1105   TopTools_ListIteratorOfListOfShape itSub (listSS);
1106   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1107     int id = anIndices.FindIndex(itSub.Value());
1108     anArray = new TColStd_HArray1OfInteger(1,1);
1109     anArray->SetValue(1, id);
1110     anObj = GetEngine()->AddSubShape(theShape, anArray);
1111     aSeq->Append(anObj);
1112   }
1113   
1114   // The GetShapesOnPlane() doesn't change object so no new function is required.
1115   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1116
1117   // Make a Python command
1118   TCollection_AsciiString anEntry, aDescr
1119     ("\nlistShapesOnPlane = IShapesOperations.GetShapesOnPlane(");
1120   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1121   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1122   TDF_Tool::Entry(theAx1->GetEntry(), anEntry);
1123   aDescr += anEntry + ",";
1124   aDescr += TCollection_AsciiString(theState) + ")";
1125
1126   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1127   anOldDescr += aDescr;
1128   aFunction->SetDescription(anOldDescr);
1129
1130   SetErrorCode(OK);
1131   return aSeq;
1132 }
1133
1134 //=============================================================================
1135 /*!
1136  *  GetShapesOnCylinder
1137  */
1138 //=============================================================================
1139 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
1140                                           (const Handle(GEOM_Object)& theShape,
1141                                            const Standard_Integer     theShapeType,
1142                                            const Handle(GEOM_Object)& theAxis,
1143                                            const Standard_Real        theRadius,
1144                                            const GEOMAlgo_State       theState)
1145 {
1146   SetErrorCode(KO);
1147
1148   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1149
1150   TopoDS_Shape aShape = theShape->GetValue();
1151   TopoDS_Shape anAxis = theAxis->GetValue();
1152
1153   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1154
1155   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1156   if (aShapeType != TopAbs_VERTEX &&
1157       aShapeType != TopAbs_EDGE &&
1158       aShapeType != TopAbs_FACE) {
1159     SetErrorCode("Not implemented for the given sub-shape type");
1160     return NULL;
1161   }
1162
1163   //Axis of the cylinder
1164   if (anAxis.ShapeType() != TopAbs_EDGE) {
1165     SetErrorCode("Not an edge given for the axis");
1166     return NULL;
1167   }
1168   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1169   TopoDS_Vertex V1, V2;
1170   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1171   if (V1.IsNull() || V2.IsNull()) {
1172     SetErrorCode("Bad edge given for the axis");
1173     return NULL;
1174   }
1175   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1176   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1177   if (aVec.Magnitude() < Precision::Confusion()) {
1178     SetErrorCode("Vector with null magnitude given");
1179     return NULL;
1180   }
1181
1182   gp_Ax3 anAx3 (aLoc, aVec);
1183   Handle(Geom_CylindricalSurface) aCylinder =
1184     new Geom_CylindricalSurface(anAx3, theRadius);
1185
1186   // Call algo
1187   GEOMAlgo_FinderShapeOn aFinder;
1188   Standard_Real aTol = 0.0001; // default value
1189
1190   aFinder.SetShape(aShape);
1191   aFinder.SetTolerance(aTol);
1192   aFinder.SetSurface(aCylinder);
1193   aFinder.SetShapeType(aShapeType);
1194   aFinder.SetState(theState);
1195
1196   aFinder.Perform();
1197
1198   // Interprete results
1199   Standard_Integer iErr = aFinder.ErrorStatus();
1200   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
1201   if (iErr) {
1202     MESSAGE(" iErr : " << iErr);
1203     TCollection_AsciiString aMsg (" iErr : ");
1204     aMsg += TCollection_AsciiString(iErr);
1205     SetErrorCode(aMsg);
1206     return NULL;
1207   }
1208   Standard_Integer iWrn = aFinder.WarningStatus();
1209   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
1210   if (iWrn) {
1211     MESSAGE(" *** iWrn : " << iWrn);
1212   }
1213
1214   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1215
1216   if (listSS.Extent() < 1) {
1217     SetErrorCode("Not a single sub-shape of the requested type found on the given cylinder");
1218     return NULL;
1219   }
1220
1221   // Fill sequence of objects
1222   TopTools_IndexedMapOfShape anIndices;
1223   TopExp::MapShapes(aShape, anIndices);
1224
1225   Handle(GEOM_Object) anObj;
1226   Handle(TColStd_HArray1OfInteger) anArray;
1227   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1228
1229   TopTools_ListIteratorOfListOfShape itSub (listSS);
1230   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1231     int id = anIndices.FindIndex(itSub.Value());
1232     anArray = new TColStd_HArray1OfInteger(1,1);
1233     anArray->SetValue(1, id);
1234     anObj = GetEngine()->AddSubShape(theShape, anArray);
1235     aSeq->Append(anObj);
1236   }
1237   
1238   // The GetShapesOnCylinder() doesn't change object so no new function is required.
1239   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1240
1241   // Make a Python command
1242   TCollection_AsciiString anEntry, aDescr
1243     ("\nlistShapesOnCylinder = IShapesOperations.GetShapesOnCylinder(");
1244   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1245   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1246   TDF_Tool::Entry(theAxis->GetEntry(), anEntry);
1247   aDescr += anEntry + ",";
1248   aDescr += TCollection_AsciiString(theRadius) + ",";
1249   aDescr += TCollection_AsciiString(theState) + ")";
1250
1251   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1252   anOldDescr += aDescr;
1253   aFunction->SetDescription(anOldDescr);
1254
1255   SetErrorCode(OK);
1256   return aSeq;
1257 }
1258
1259 //=============================================================================
1260 /*!
1261  *  GetShapesOnSphere
1262  */
1263 //=============================================================================
1264 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
1265                                           (const Handle(GEOM_Object)& theShape,
1266                                            const Standard_Integer     theShapeType,
1267                                            const Handle(GEOM_Object)& theCenter,
1268                                            const Standard_Real        theRadius,
1269                                            const GEOMAlgo_State       theState)
1270 {
1271   SetErrorCode(KO);
1272
1273   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1274
1275   TopoDS_Shape aShape  = theShape->GetValue();
1276   TopoDS_Shape aCenter = theCenter->GetValue();
1277
1278   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1279
1280   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1281   if (aShapeType != TopAbs_VERTEX &&
1282       aShapeType != TopAbs_EDGE &&
1283       aShapeType != TopAbs_FACE) {
1284     SetErrorCode("Not implemented for the given sub-shape type");
1285     return NULL;
1286   }
1287
1288   // Center of the sphere
1289   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1290   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1291
1292   gp_Ax3 anAx3 (aLoc, gp::DZ());
1293   Handle(Geom_SphericalSurface) aSphere =
1294     new Geom_SphericalSurface(anAx3, theRadius);
1295
1296   // Call algo
1297   GEOMAlgo_FinderShapeOn aFinder;
1298   Standard_Real aTol = 0.0001; // default value
1299
1300   aFinder.SetShape(aShape);
1301   aFinder.SetTolerance(aTol);
1302   aFinder.SetSurface(aSphere);
1303   aFinder.SetShapeType(aShapeType);
1304   aFinder.SetState(theState);
1305
1306   aFinder.Perform();
1307
1308   // Interprete results
1309   Standard_Integer iErr = aFinder.ErrorStatus();
1310   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn.cxx
1311   if (iErr) {
1312     MESSAGE(" iErr : " << iErr);
1313     TCollection_AsciiString aMsg (" iErr : ");
1314     aMsg += TCollection_AsciiString(iErr);
1315     SetErrorCode(aMsg);
1316     return NULL;
1317   }
1318   Standard_Integer iWrn = aFinder.WarningStatus();
1319   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn.cxx
1320   if (iWrn) {
1321     MESSAGE(" *** iWrn : " << iWrn);
1322   }
1323
1324   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1325
1326   if (listSS.Extent() < 1) {
1327     SetErrorCode("Not a single sub-shape of the requested type found on the given sphere");
1328     return NULL;
1329   }
1330
1331   // Fill sequence of objects
1332   TopTools_IndexedMapOfShape anIndices;
1333   TopExp::MapShapes(aShape, anIndices);
1334
1335   Handle(GEOM_Object) anObj;
1336   Handle(TColStd_HArray1OfInteger) anArray;
1337   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1338
1339   TopTools_ListIteratorOfListOfShape itSub (listSS);
1340   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1341     int id = anIndices.FindIndex(itSub.Value());
1342     anArray = new TColStd_HArray1OfInteger(1,1);
1343     anArray->SetValue(1, id);
1344     anObj = GetEngine()->AddSubShape(theShape, anArray);
1345     aSeq->Append(anObj);
1346   }
1347   
1348   // The GetShapesOnSphere() doesn't change object so no new function is required.
1349   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1350
1351   // Make a Python command
1352   TCollection_AsciiString anEntry, aDescr
1353     ("\nlistShapesOnSphere = IShapesOperations.GetShapesOnSphere(");
1354   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1355   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1356   TDF_Tool::Entry(theCenter->GetEntry(), anEntry);
1357   aDescr += anEntry + ",";
1358   aDescr += TCollection_AsciiString(theRadius) + ",";
1359   aDescr += TCollection_AsciiString(theState) + ")";
1360
1361   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
1362   anOldDescr += aDescr;
1363   aFunction->SetDescription(anOldDescr);
1364
1365   SetErrorCode(OK);
1366   return aSeq;
1367 }
1368
1369 //=============================================================================
1370 /*!
1371  *  GetShapesOnCylinderOld
1372  */
1373 //=============================================================================
1374 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnCylinderOld
1375                                           (Handle(GEOM_Object)    theShape,
1376                                            const Standard_Integer theShapeType,
1377                                            Handle(GEOM_Object)    theAxis,
1378                                            const Standard_Real    theRadius)
1379 {
1380   SetErrorCode(KO);
1381
1382   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1383
1384   TopoDS_Shape aShape = theShape->GetValue();
1385   TopoDS_Shape anAxis = theAxis->GetValue();
1386
1387   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1388
1389   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1390   if (aShapeType != TopAbs_VERTEX &&
1391       aShapeType != TopAbs_EDGE &&
1392       aShapeType != TopAbs_FACE) {
1393     SetErrorCode("Not implemented for the given sub-shape type");
1394     return NULL;
1395   }
1396
1397   //Axis of the cylinder
1398   if (anAxis.ShapeType() != TopAbs_EDGE) {
1399     SetErrorCode("Not an edge given for the axis");
1400     return NULL;
1401   }
1402   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1403   TopoDS_Vertex V1, V2;
1404   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1405   if (V1.IsNull() || V2.IsNull()) {
1406     SetErrorCode("Bad edge given for the axis");
1407     return NULL;
1408   }
1409   gp_Pnt loc = BRep_Tool::Pnt(V1);
1410   gp_Vec aVec (loc, BRep_Tool::Pnt(V2));
1411   gp_Dir dir (aVec);
1412   gp_Lin aLin (loc, aVec);
1413
1414   //Find sub-shapes on the cylinder
1415   TopTools_ListOfShape listSS;
1416   TopTools_MapOfShape mapShapes;
1417   TopExp_Explorer exp (aShape, aShapeType);
1418   for (; exp.More(); exp.Next()) {
1419     TopoDS_Shape aSS = exp.Current();
1420     if (mapShapes.Add(aSS)) {
1421       switch (aShapeType) {
1422       case TopAbs_VERTEX:
1423         {
1424           TopoDS_Vertex aV = TopoDS::Vertex(aSS);
1425           gp_Pnt aP = BRep_Tool::Pnt(aV);
1426           if (Abs(aLin.Distance(aP) - theRadius) < Precision::Confusion()) {
1427             listSS.Append(aSS);
1428           }
1429         }
1430         break;
1431       case TopAbs_EDGE:
1432         {
1433           TopoDS_Edge anEdge = TopoDS::Edge(aSS);
1434           Standard_Real f, l;
1435           Handle(Geom2d_Curve) PC;
1436           Handle(Geom_Surface) cur_surf;
1437           TopLoc_Location L;
1438           Standard_Integer i = 0;
1439
1440           // iterate on the surfaces of the edge
1441           while (Standard_True) {
1442             i++;
1443             BRep_Tool::CurveOnSurface(anEdge, PC , cur_surf, L, f, l, i);
1444             if (cur_surf.IsNull()) break;
1445
1446             Handle(Geom_CylindricalSurface) cur_cyl =
1447               Handle(Geom_CylindricalSurface)::DownCast(cur_surf);
1448             if (!cur_cyl.IsNull()) {
1449               const gp_Ax3 cur_pos = cur_cyl->Position();
1450               const gp_Pnt cur_loc = cur_pos.Location();
1451               const gp_Dir cur_dir = cur_pos.Direction();
1452               const Standard_Real cur_rad = cur_cyl->Radius();
1453               gp_Vec vecToLoc (cur_loc, loc);
1454               if (vecToLoc.IsParallel(dir, Precision::Angular()) &&
1455                   cur_dir.IsParallel(dir, Precision::Angular()) &&
1456                   Abs(cur_rad - theRadius) < Precision::Confusion()) {
1457                 listSS.Append(aSS);
1458               }
1459             }
1460           }
1461         }
1462         break;
1463       case TopAbs_FACE:
1464         {
1465           TopoDS_Face aF = TopoDS::Face(aSS);
1466           Handle(Geom_Surface) cur_surf = BRep_Tool::Surface(aF);
1467           Handle(Geom_CylindricalSurface) cur_cyl =
1468             Handle(Geom_CylindricalSurface)::DownCast(cur_surf);
1469           if (!cur_cyl.IsNull()) {
1470             const gp_Ax3 cur_pos = cur_cyl->Position();
1471             const gp_Pnt cur_loc = cur_pos.Location();
1472             const gp_Dir cur_dir = cur_pos.Direction();
1473             const Standard_Real cur_rad = cur_cyl->Radius();
1474             gp_Vec vecToLoc (cur_loc, loc);
1475             if (vecToLoc.IsParallel(dir, Precision::Angular()) &&
1476                 cur_dir.IsParallel(dir, Precision::Angular()) &&
1477                 Abs(cur_rad - theRadius) < Precision::Confusion()) {
1478               listSS.Append(aSS);
1479             }
1480           }
1481         }
1482         break;
1483       default:
1484         break;
1485       }
1486     }
1487   }
1488
1489   if (listSS.Extent() < 1) {
1490     SetErrorCode("Not a single sub-shape of the requested type found on the given cylinder");
1491     return NULL;
1492   }
1493
1494   //Fill array of indices
1495   TopTools_IndexedMapOfShape anIndices;
1496   TopExp::MapShapes(aShape, anIndices);
1497
1498   Handle(TColStd_HArray1OfInteger) anArray =
1499     new TColStd_HArray1OfInteger (1, listSS.Extent());
1500   TopTools_ListIteratorOfListOfShape itSub (listSS);
1501   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1502     int id = anIndices.FindIndex(itSub.Value());
1503     anArray->SetValue(index, id);
1504   }
1505   
1506   //Add a new group object
1507   Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(theShape, anArray);
1508
1509   //Set a GROUP type
1510   aGroup->SetType(GEOM_GROUP);
1511
1512   //Set a sub shape type
1513   TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1514   TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)theShapeType);
1515  
1516   //Make a Python command
1517   TCollection_AsciiString anEntry, aDescr;
1518   TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1519   aDescr += anEntry;
1520   aDescr += " = IShapesOperations.GetShapesOnCylinder(";
1521   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1522   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1523   TDF_Tool::Entry(theAxis->GetEntry(), anEntry);
1524   aDescr += anEntry + TCollection_AsciiString(theRadius) + ")";
1525
1526   Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1527   aFunction->SetDescription(aDescr);
1528
1529   SetErrorCode(OK);
1530   return aGroup;
1531 }
1532
1533 //=============================================================================
1534 /*!
1535  *  GetShapesOnSphereOld
1536  */
1537 //=============================================================================
1538 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnSphereOld
1539                                           (Handle(GEOM_Object)    theShape,
1540                                            const Standard_Integer theShapeType,
1541                                            Handle(GEOM_Object)    theCenter,
1542                                            const Standard_Real    theRadius)
1543 {
1544   SetErrorCode(KO);
1545
1546   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1547
1548   TopoDS_Shape aShape  = theShape->GetValue();
1549   TopoDS_Shape aCenter = theCenter->GetValue();
1550
1551   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1552
1553   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1554   if (aShapeType != TopAbs_VERTEX &&
1555       aShapeType != TopAbs_EDGE &&
1556       aShapeType != TopAbs_FACE) {
1557     SetErrorCode("Not implemented for the given sub-shape type");
1558     return NULL;
1559   }
1560
1561   //Center of the sphere
1562   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1563   gp_Pnt aC = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1564
1565   //Find sub-shapes on the sphere
1566   TopTools_ListOfShape listSS;
1567   TopTools_MapOfShape mapShapes;
1568   TopExp_Explorer exp (aShape, aShapeType);
1569   for (; exp.More(); exp.Next()) {
1570     TopoDS_Shape aSS = exp.Current();
1571     if (mapShapes.Add(aSS)) {
1572       switch (aShapeType) {
1573       case TopAbs_VERTEX:
1574         {
1575           TopoDS_Vertex aV = TopoDS::Vertex(aSS);
1576           gp_Pnt aP = BRep_Tool::Pnt(aV);
1577           if (Abs(aP.Distance(aC) - theRadius) < Precision::Confusion()) {
1578             listSS.Append(aSS);
1579           }
1580         }
1581         break;
1582       case TopAbs_EDGE:
1583         {
1584           TopoDS_Edge anEdge = TopoDS::Edge(aSS);
1585           Standard_Real f, l;
1586           Handle(Geom2d_Curve) PC;
1587           Handle(Geom_Surface) cur_surf;
1588           TopLoc_Location L;
1589           Standard_Integer i = 0;
1590
1591           // iterate on the surfaces of the edge
1592           while (Standard_True) {
1593             i++;
1594             BRep_Tool::CurveOnSurface(anEdge, PC , cur_surf, L, f, l, i);
1595             if (cur_surf.IsNull()) break;
1596
1597             Handle(Geom_SphericalSurface) cur_sph =
1598               Handle(Geom_SphericalSurface)::DownCast(cur_surf);
1599             if (!cur_sph.IsNull()) {
1600               const gp_Ax3 cur_pos = cur_sph->Position();
1601               const gp_Pnt cur_loc = cur_pos.Location();
1602               const Standard_Real cur_rad = cur_sph->Radius();
1603               if (cur_loc.Distance(aC) < Precision::Confusion() &&
1604                   Abs(cur_rad - theRadius) < Precision::Confusion()) {
1605                 listSS.Append(aSS);
1606               }
1607             }
1608           }
1609         }
1610         break;
1611       case TopAbs_FACE:
1612         {
1613           TopoDS_Face aF = TopoDS::Face(aSS);
1614           Handle(Geom_Surface) cur_surf = BRep_Tool::Surface(aF);
1615           Handle(Geom_SphericalSurface) cur_sph =
1616             Handle(Geom_SphericalSurface)::DownCast(cur_surf);
1617           if (!cur_sph.IsNull()) {
1618             const gp_Ax3 cur_pos = cur_sph->Position();
1619             const gp_Pnt cur_loc = cur_pos.Location();
1620             const Standard_Real cur_rad = cur_sph->Radius();
1621             if (cur_loc.Distance(aC) < Precision::Confusion() &&
1622                 Abs(cur_rad - theRadius) < Precision::Confusion()) {
1623               listSS.Append(aSS);
1624             }
1625           }
1626         }
1627         break;
1628       default:
1629         break;
1630       }
1631     }
1632   }
1633
1634   if (listSS.Extent() < 1) {
1635     SetErrorCode("Not a single sub-shape of the requested type found on the given sphere");
1636     return NULL;
1637   }
1638
1639   //Fill array of indices
1640   TopTools_IndexedMapOfShape anIndices;
1641   TopExp::MapShapes(aShape, anIndices);
1642
1643   Handle(TColStd_HArray1OfInteger) anArray =
1644     new TColStd_HArray1OfInteger (1, listSS.Extent());
1645   TopTools_ListIteratorOfListOfShape itSub (listSS);
1646   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1647     int id = anIndices.FindIndex(itSub.Value());
1648     anArray->SetValue(index, id);
1649   }
1650   
1651   //Add a new group object
1652   Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(theShape, anArray);
1653
1654   //Set a GROUP type
1655   aGroup->SetType(GEOM_GROUP);
1656
1657   //Set a sub shape type
1658   TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1659   TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)theShapeType);
1660  
1661   //Make a Python command
1662   TCollection_AsciiString anEntry, aDescr;
1663   TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1664   aDescr += anEntry;
1665   aDescr += " = IShapesOperations.GetShapesOnSphere(";
1666   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
1667   aDescr += anEntry + TCollection_AsciiString(theShapeType) + ",";
1668   TDF_Tool::Entry(theCenter->GetEntry(), anEntry);
1669   aDescr += anEntry + TCollection_AsciiString(theRadius) + ")";
1670
1671   Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1672   aFunction->SetDescription(aDescr);
1673
1674   SetErrorCode(OK);
1675   return aGroup;
1676 }
1677
1678 //=============================================================================
1679 /*!
1680  *  GetInPlace
1681  */
1682 //=============================================================================
1683 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
1684                                           (Handle(GEOM_Object) theShapeWhere,
1685                                            Handle(GEOM_Object) theShapeWhat)
1686 {
1687   SetErrorCode(KO);
1688
1689   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
1690
1691   TopoDS_Shape aWhere = theShapeWhere->GetValue();
1692   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
1693
1694   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
1695
1696   //Fill array of indices
1697   TopTools_IndexedMapOfShape anIndices;
1698   TopExp::MapShapes(aWhere, anIndices);
1699
1700 //  Handle(TColStd_HArray1OfInteger) anArray =
1701 //    new TColStd_HArray1OfInteger (1, listSS.Extent());
1702 //  TopTools_ListIteratorOfListOfShape itSub (listSS);
1703 //  for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1704 //    int id = anIndices.FindIndex(itSub.Value());
1705 //    anArray->SetValue(index, id);
1706 //  }
1707 //  
1708 //  //Add a new group object
1709 //  Handle(GEOM_Object) aGroup = GetEngine()->AddSubShape(theShape, anArray);
1710 //
1711 //  //Set a GROUP type
1712 //  aGroup->SetType(GEOM_GROUP);
1713 //
1714 //  //Set a sub shape type
1715 //  TDF_Label aFreeLabel = aGroup->GetFreeLabel();
1716 //  TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)theShapeType);
1717 // 
1718 //  //Make a Python command
1719 //  TCollection_AsciiString anEntry, aDescr;
1720 //  TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1721 //  aDescr += anEntry;
1722 //  aDescr += " = IShapesOperations.GetInPlace(";
1723 //  TDF_Tool::Entry(theShapeWhere->GetEntry(), anEntry);
1724 //  aDescr += anEntry + ",";
1725 //  TDF_Tool::Entry(theShapeWhat->GetEntry(), anEntry);
1726 //  aDescr += anEntry + ")";
1727 //
1728 //  Handle(GEOM_Function) aFunction = aGroup->GetFunction(1);
1729 //  aFunction->SetDescription(aDescr);
1730
1731 //  SetErrorCode(OK);
1732 //  return aGroup;
1733   SetErrorCode("Not implemented");
1734   return NULL;
1735 }
1736
1737
1738 //=======================================================================
1739 //function : SortShapes
1740 //purpose  :
1741 //=======================================================================
1742 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
1743 {
1744   Standard_Integer MaxShapes = SL.Extent();
1745   TopTools_Array1OfShape  aShapes (1,MaxShapes);
1746   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
1747   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
1748   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
1749
1750   // Computing of CentreOfMass
1751   Standard_Integer Index;
1752   GProp_GProps GPr;
1753   gp_Pnt GPoint;
1754   TopTools_ListIteratorOfListOfShape it(SL);
1755   for (Index=1;  it.More();  Index++)
1756   {
1757     TopoDS_Shape S = it.Value();
1758     SL.Remove( it ); // == it.Next()
1759     aShapes(Index) = S;
1760     OrderInd.SetValue (Index, Index);
1761     if (S.ShapeType() == TopAbs_VERTEX)
1762     {
1763       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
1764       Length.SetValue( Index, (Standard_Real) S.Orientation());
1765     }
1766     else
1767     {
1768       BRepGProp::LinearProperties (S, GPr);
1769       GPoint = GPr.CentreOfMass();
1770       Length.SetValue( Index, GPr.Mass() );
1771     }
1772     MidXYZ.SetValue(Index,
1773                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
1774   }
1775   // Sorting
1776   Standard_Integer aTemp;
1777   Standard_Boolean exchange, Sort = Standard_True;
1778   while (Sort)
1779   {
1780     Sort = Standard_False;
1781     for (Index=1; Index < MaxShapes; Index++)
1782     {
1783       if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
1784         exchange = Standard_True;
1785       else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
1786                Length(OrderInd(Index)) >  Length(OrderInd(Index+1)) )
1787         exchange = Standard_True;
1788       else
1789         exchange = Standard_False;
1790       if (exchange)
1791       {
1792         aTemp = OrderInd(Index);
1793         OrderInd(Index) = OrderInd(Index+1);
1794         OrderInd(Index+1) = aTemp;
1795         Sort = Standard_True;
1796       }
1797     }
1798   }
1799   for (Index=1; Index <= MaxShapes; Index++)
1800     SL.Append( aShapes( OrderInd(Index) ));
1801 }