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