]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
Salome HOME
bc09b41cff14e9c1081216cf3e6762d8a66ca6d6
[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 "GEOM_Function.hxx"
17
18 #include "utilities.h"
19 #include "OpUtil.hxx"
20 #include "Utils_ExceptHandlers.hxx"
21
22 #include <TFunction_DriverTable.hxx>
23 #include <TFunction_Driver.hxx>
24 #include <TFunction_Logbook.hxx>
25 #include <TDF_Tool.hxx>
26
27 #include <BRep_Tool.hxx>
28 #include <BRepGProp.hxx>
29
30 #include <TopAbs.hxx>
31 #include <TopExp.hxx>
32 #include <TopoDS.hxx>
33 #include <TopoDS_Shape.hxx>
34 #include <TopoDS_Iterator.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <TopTools_MapOfShape.hxx>
37 #include <TopTools_Array1OfShape.hxx>
38 #include <TopTools_ListIteratorOfListOfShape.hxx>
39 #include <TopTools_IndexedMapOfShape.hxx>
40
41 #include <GProp_GProps.hxx>
42 #include <gp_Pnt.hxx>
43 #include <TColStd_Array1OfReal.hxx>
44 #include <TColStd_HArray1OfInteger.hxx>
45
46 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
47
48 //=============================================================================
49 /*!
50  *   constructor:
51  */
52 //=============================================================================
53 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
54 : GEOM_IOperations(theEngine, theDocID)
55 {
56   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
57 }
58
59 //=============================================================================
60 /*!
61  *  destructor
62  */
63 //=============================================================================
64 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
65 {
66   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
67 }
68
69
70 //=============================================================================
71 /*!
72  *  MakeEdge
73  */
74 //=============================================================================
75 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
76                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
77 {
78   SetErrorCode(KO);
79
80   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
81
82   //Add a new Edge object
83   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
84
85   //Add a new Vector function
86   Handle(GEOM_Function) aFunction =
87     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
88
89   //Check if the function is set correctly
90   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
91
92   GEOMImpl_IVector aPI (aFunction);
93
94   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
95   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
96   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
97
98   aPI.SetPoint1(aRef1);
99   aPI.SetPoint2(aRef2);
100
101   //Compute the Edge value
102   try {
103     if (!GetSolver()->ComputeFunction(aFunction)) {
104       SetErrorCode("Vector driver failed");
105       return NULL;
106     }
107   }
108   catch (Standard_Failure) {
109     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
110     SetErrorCode(aFail->GetMessageString());
111     return NULL;
112   }
113
114   //Make a Python command
115   TCollection_AsciiString anEntry, aDescr;
116   TDF_Tool::Entry(anEdge->GetEntry(), anEntry);
117   aDescr += (anEntry+" = IShapesOperations.MakeEdge(");
118   TDF_Tool::Entry(thePnt1->GetEntry(), anEntry);
119   aDescr += (anEntry+", ");
120   TDF_Tool::Entry(thePnt2->GetEntry(), anEntry);
121   aDescr += (anEntry+")");
122
123   aFunction->SetDescription(aDescr);
124
125   SetErrorCode(OK);
126   return anEdge;
127 }
128
129 //=============================================================================
130 /*!
131  *  MakeWire
132  */
133 //=============================================================================
134 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
135                              (list<Handle(GEOM_Object)> theShapes)
136 {
137   return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
138 }
139
140 //=============================================================================
141 /*!
142  *  MakeFace
143  */
144 //=============================================================================
145 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
146                                                           const bool isPlanarWanted)
147 {
148   SetErrorCode(KO);
149
150   if (theWire.IsNull()) return NULL;
151
152   //Add a new Face object
153   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
154
155   //Add a new Shape function for creation of a face from a wire
156   Handle(GEOM_Function) aFunction =
157     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
158   if (aFunction.IsNull()) return NULL;
159
160   //Check if the function is set correctly
161   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
162
163   GEOMImpl_IShapes aCI (aFunction);
164
165   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
166
167   if (aRefWire.IsNull()) return NULL;
168
169   aCI.SetBase(aRefWire);
170   aCI.SetIsPlanar(isPlanarWanted);
171
172   //Compute the Face value
173   try {
174     if (!GetSolver()->ComputeFunction(aFunction)) {
175       SetErrorCode("Shape driver failed to compute a face");
176       return NULL;
177     }
178   }
179   catch (Standard_Failure) {
180     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
181     SetErrorCode(aFail->GetMessageString());
182     return NULL;
183   }
184
185   //Make a Python command
186   TCollection_AsciiString anEntry, aDescr;
187   TDF_Tool::Entry(aFace->GetEntry(), anEntry);
188   aDescr += anEntry;
189   aDescr += " = IShapesOperations.MakeFace(";
190   TDF_Tool::Entry(theWire->GetEntry(), anEntry);
191   aDescr += anEntry;
192   if (isPlanarWanted)
193     aDescr += ", 1)";
194
195   else
196     aDescr += ", 0)";
197
198   aFunction->SetDescription(aDescr);
199
200   SetErrorCode(OK);
201   return aFace;
202 }
203
204 //=============================================================================
205 /*!
206  *  MakeFaceWires
207  */
208 //=============================================================================
209 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
210                       (list<Handle(GEOM_Object)> theShapes, bool isPlanarWanted)
211 {
212   SetErrorCode(KO);
213
214   //Add a new object
215   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
216
217   //Add a new function
218   Handle(GEOM_Function) aFunction =
219     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
220   if (aFunction.IsNull()) return NULL;
221
222   //Check if the function is set correctly
223   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
224
225   GEOMImpl_IShapes aCI (aFunction);
226
227   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
228
229   // Shapes
230   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
231   for (; it != theShapes.end(); it++) {
232     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
233     if (aRefSh.IsNull()) {
234       SetErrorCode("NULL argument shape for the face construction");
235       return NULL;
236     }
237     aShapesSeq->Append(aRefSh);
238   }
239   aCI.SetShapes(aShapesSeq);
240
241   aCI.SetIsPlanar(isPlanarWanted);
242
243   //Compute the shape
244   try {
245     if (!GetSolver()->ComputeFunction(aFunction)) {
246       SetErrorCode("Shape driver failed");
247       return NULL;
248     }
249   }
250   catch (Standard_Failure) {
251     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
252     SetErrorCode(aFail->GetMessageString());
253     return NULL;
254   }
255
256   //Make a Python command
257   TCollection_AsciiString anEntry, aDescr;
258   TDF_Tool::Entry(aShape->GetEntry(), anEntry);
259   aDescr += (anEntry + " = IShapesOperations.MakeFaceWires([");
260   // Shapes
261   it = theShapes.begin();
262   if (it != theShapes.end()) {
263     TDF_Tool::Entry((*it)->GetEntry(), anEntry);
264     it++;
265     aDescr += (anEntry+", ");
266     for (; it != theShapes.end(); it++) {
267       aDescr += ", ";
268       TDF_Tool::Entry((*it)->GetEntry(), anEntry);
269       aDescr += anEntry;
270     }
271   }
272   if (isPlanarWanted)
273     aDescr += "], 1)";
274
275   else
276     aDescr += "], 0)";
277
278   aFunction->SetDescription(aDescr);
279
280   SetErrorCode(OK);
281   return aShape;
282 }
283
284 //=============================================================================
285 /*!
286  *  MakeShell
287  */
288 //=============================================================================
289 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
290                              (list<Handle(GEOM_Object)> theShapes)
291 {
292   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
293 }
294
295 //=============================================================================
296 /*!
297  *  MakeSolidShells
298  */
299 //=============================================================================
300 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
301                              (list<Handle(GEOM_Object)> theShapes)
302 {
303   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolidShells");
304 }
305
306 //=============================================================================
307 /*!
308  *  MakeSolidShell
309  */
310 //=============================================================================
311 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
312 {
313   SetErrorCode(KO);
314
315   if (theShell.IsNull()) return NULL;
316
317   //Add a new Solid object
318   Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
319
320   //Add a new Solid function for creation of a solid from a shell
321   Handle(GEOM_Function) aFunction =
322     aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
323   if (aFunction.IsNull()) return NULL;
324
325   //Check if the function is set correctly
326   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
327
328   GEOMImpl_IShapes aCI (aFunction);
329
330   Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
331
332   if (aRefShell.IsNull()) return NULL;
333
334   aCI.SetBase(aRefShell);
335
336   //Compute the Solid value
337   try {
338     if (!GetSolver()->ComputeFunction(aFunction)) {
339       SetErrorCode("Solid driver failed");
340       return NULL;
341     }
342   }
343   catch (Standard_Failure) {
344     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
345     SetErrorCode(aFail->GetMessageString());
346     return NULL;
347   }
348
349   //Make a Python command
350   TCollection_AsciiString anEntry, aDescr("");
351   TDF_Tool::Entry(aSolid->GetEntry(), anEntry);
352   aDescr += anEntry;
353   aDescr += " = IShapesOperations.MakeSolidShell(";
354   TDF_Tool::Entry(theShell->GetEntry(), anEntry);
355   aDescr += (anEntry+")");
356
357   aFunction->SetDescription(aDescr);
358
359   SetErrorCode(OK);
360   return aSolid;
361 }
362
363 //=============================================================================
364 /*!
365  *  MakeCompound
366  */
367 //=============================================================================
368 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound
369                              (list<Handle(GEOM_Object)> theShapes)
370 {
371   return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound");
372 }
373
374 //=============================================================================
375 /*!
376  *  MakeShape
377  */
378 //=============================================================================
379 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape
380                              (list<Handle(GEOM_Object)>     theShapes,
381                               const Standard_Integer        theObjectType,
382                               const Standard_Integer        theFunctionType,
383                               const TCollection_AsciiString theMethodName)
384 {
385   SetErrorCode(KO);
386
387   //Add a new object
388   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType);
389
390   //Add a new function
391   Handle(GEOM_Function) aFunction =
392     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), theFunctionType);
393   if (aFunction.IsNull()) return NULL;
394
395   //Check if the function is set correctly
396   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
397
398   GEOMImpl_IShapes aCI (aFunction);
399
400   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
401
402   // Shapes
403   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
404   for (; it != theShapes.end(); it++) {
405     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
406     if (aRefSh.IsNull()) {
407       SetErrorCode("NULL argument shape for the shape construction");
408       return NULL;
409     }
410     aShapesSeq->Append(aRefSh);
411   }
412   aCI.SetShapes(aShapesSeq);
413
414   //Compute the shape
415   try {
416     if (!GetSolver()->ComputeFunction(aFunction)) {
417       SetErrorCode("Shape driver failed");
418       return NULL;
419     }
420   }
421   catch (Standard_Failure) {
422     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
423     SetErrorCode(aFail->GetMessageString());
424     return NULL;
425   }
426
427   //Make a Python command
428   TCollection_AsciiString anEntry, aDescr("");
429   TDF_Tool::Entry(aShape->GetEntry(), anEntry);
430   aDescr += (anEntry + " = IShapesOperations.");
431   aDescr += (theMethodName + "([");
432   // Shapes
433   it = theShapes.begin();
434   if (it != theShapes.end()) {
435     TDF_Tool::Entry((*it)->GetEntry(), anEntry);
436     it++;
437     aDescr += (anEntry+", ");
438     for (; it != theShapes.end(); it++) {
439       aDescr += ", ";
440       TDF_Tool::Entry((*it)->GetEntry(), anEntry);
441       aDescr += anEntry;
442     }
443   }
444   aDescr += "])";
445
446   aFunction->SetDescription(aDescr);
447
448   SetErrorCode(OK);
449   return aShape;
450 }
451
452 //=============================================================================
453 /*!
454  *  MakeGlueFaces
455  */
456 //=============================================================================
457 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
458                                                 (Handle(GEOM_Object) theShape,
459                                                  const Standard_Real theTolerance)
460 {
461   SetErrorCode(KO);
462
463   if (theShape.IsNull()) return NULL;
464
465   //Add a new Glued object
466   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
467
468   //Add a new Glue function
469   Handle(GEOM_Function) aFunction;
470   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
471   if (aFunction.IsNull()) return NULL;
472
473   //Check if the function is set correctly
474   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
475
476   GEOMImpl_IGlue aCI (aFunction);
477
478   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
479   if (aRefShape.IsNull()) return NULL;
480
481   aCI.SetBase(aRefShape);
482   aCI.SetTolerance(theTolerance);
483
484   //Compute the sub-shape value
485   try {
486     if (!GetSolver()->ComputeFunction(aFunction)) {
487       SetErrorCode("Shape driver failed to glue faces");
488       return NULL;
489     }
490   }
491   catch (Standard_Failure) {
492     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
493     SetErrorCode(aFail->GetMessageString());
494     return NULL;
495   }
496
497   //Make a Python command
498   TCollection_AsciiString anEntry, aDescr;
499   TDF_Tool::Entry(aGlued->GetEntry(), anEntry);
500   aDescr += anEntry;
501   aDescr += " = IShapesOperations.MakeGlueFaces(";
502   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
503   aDescr += anEntry + ", ";
504   aDescr += TCollection_AsciiString(theTolerance) + ")";
505
506   aFunction->SetDescription(aDescr);
507
508   SetErrorCode(OK);
509   return aGlued;
510 }
511
512 //=============================================================================
513 /*!
514  *  MakeExplode
515  */
516 //=============================================================================
517 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
518                                           (Handle(GEOM_Object)    theShape,
519                                            const Standard_Integer theShapeType,
520                                            const Standard_Boolean isSorted)
521 {
522   SetErrorCode(KO);
523
524   if (theShape.IsNull()) return NULL;
525   TopoDS_Shape aShape = theShape->GetValue();
526   if (aShape.IsNull()) return NULL;
527
528   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
529   Handle(GEOM_Object) anObj;
530   Handle(GEOM_Function) aFunction;
531   TopTools_MapOfShape mapShape;
532   TopTools_ListOfShape listShape;
533
534   if (aShape.ShapeType() == TopAbs_COMPOUND &&
535       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
536        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
537        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
538     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
539     for (; It.More(); It.Next()) {
540       if (mapShape.Add(It.Value())) {
541         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
542             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
543           listShape.Append(It.Value());
544         }
545       }
546     }
547   } else {
548     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
549     for (; exp.More(); exp.Next())
550       if (mapShape.Add(exp.Current()))
551         listShape.Append(exp.Current());
552   }
553
554   if (listShape.IsEmpty()) {
555     SetErrorCode("The given shape has no sub-shapes of the requested type");
556     return aSeq;
557   }
558
559   if (isSorted)
560     SortShapes(listShape);
561
562   TopTools_IndexedMapOfShape anIndices;
563   TopExp::MapShapes(aShape, anIndices);
564   Handle(TColStd_HArray1OfInteger) anArray;
565
566   TopTools_ListIteratorOfListOfShape itSub (listShape);
567   TCollection_AsciiString anAsciiList="[", anEntry;
568   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
569     TopoDS_Shape aValue = itSub.Value();
570     anArray = new TColStd_HArray1OfInteger(1,1);
571     anArray->SetValue(1, anIndices.FindIndex(aValue));
572     anObj  = GetEngine()->AddSubShape(theShape, anArray);
573     aSeq->Append(anObj);
574
575     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
576     anAsciiList+=anEntry;
577     anAsciiList+=",";
578   }
579
580   anAsciiList.Trunc(anAsciiList.Length()-1);
581   anAsciiList+="]";
582
583   anAsciiList = (TCollection_AsciiString("\n")+anAsciiList);
584
585   //The explode doesn't change object so no new function is requiered.
586   aFunction = theShape->GetLastFunction();
587
588   //Make a Python command
589   TCollection_AsciiString aDescr(anAsciiList);
590   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
591   aDescr += " = IShapesOperations.MakeExplode(";
592   aDescr += (anEntry + ",");
593   if (isSorted)
594     aDescr += (TCollection_AsciiString(theShapeType) + ", 1)");
595   else
596     aDescr += (TCollection_AsciiString(theShapeType) + ", 0)");
597
598   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
599   anOldDescr = anOldDescr + aDescr;
600   aFunction->SetDescription(anOldDescr);
601
602   SetErrorCode(OK);
603
604   return aSeq;
605 }
606
607
608 //=============================================================================
609 /*!
610  *  NumberOfFaces
611  */
612 //=============================================================================
613 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
614 {
615   SetErrorCode(KO);
616
617   Standard_Integer nb = 0;
618
619   if (theShape.IsNull()) return -1;
620   TopoDS_Shape aShape = theShape->GetValue();
621   if (aShape.IsNull()) return -1;
622
623   TopTools_MapOfShape mapShape;
624
625   TopExp_Explorer exp (aShape, TopAbs_FACE);
626   for (; exp.More(); exp.Next())
627     if (mapShape.Add(exp.Current()))
628       nb++;
629
630   SetErrorCode(OK);
631   return nb;
632 }
633
634 //=============================================================================
635 /*!
636  *  NumberOfEdges
637  */
638 //=============================================================================
639 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
640 {
641   SetErrorCode(KO);
642
643   Standard_Integer nb = 0;
644
645   if (theShape.IsNull()) return -1;
646   TopoDS_Shape aShape = theShape->GetValue();
647   if (aShape.IsNull()) return -1;
648
649   TopTools_MapOfShape mapShape;
650
651   TopExp_Explorer exp (aShape, TopAbs_EDGE);
652   for (; exp.More(); exp.Next())
653     if (mapShape.Add(exp.Current()))
654       nb++;
655
656   SetErrorCode(OK);
657   return nb;
658 }
659
660 //=============================================================================
661 /*!
662  *  ReverseShape
663  */
664 //=============================================================================
665 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
666 {
667   SetErrorCode(KO);
668
669   if (theShape.IsNull()) return NULL;
670
671   //Add a new reversed object
672   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
673
674   //Add a new Revese function
675   Handle(GEOM_Function) aFunction;
676   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
677   if (aFunction.IsNull()) return NULL;
678
679   //Check if the function is set correctly
680   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
681
682   GEOMImpl_IShapes aSI (aFunction);
683
684   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
685   if (aRefShape.IsNull()) return NULL;
686
687   aSI.SetBase(aRefShape);
688
689   //Compute the sub-shape value
690   try {
691     if (!GetSolver()->ComputeFunction(aFunction)) {
692       SetErrorCode("Shape driver failed to reverse shape");
693       return NULL;
694     }
695   }
696   catch (Standard_Failure) {
697     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
698     SetErrorCode(aFail->GetMessageString());
699     return NULL;
700   }
701
702   //Make a Python command
703   TCollection_AsciiString anEntry, aDescr;
704   TDF_Tool::Entry(aReversed->GetEntry(), anEntry);
705   aDescr += anEntry;
706   aDescr += " = IShapesOperations.ReverseShape(";
707   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
708   aDescr += anEntry + ")";
709
710   aFunction->SetDescription(aDescr);
711
712   SetErrorCode(OK);
713   return aReversed;
714 }
715
716
717 //=======================================================================
718 //function : SortShapes
719 //purpose  :
720 //=======================================================================
721 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
722 {
723   Standard_Integer MaxShapes = SL.Extent();
724   TopTools_Array1OfShape  aShapes (1,MaxShapes);
725   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
726   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
727   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
728
729   // Computing of CentreOfMass
730   Standard_Integer Index;
731   GProp_GProps GPr;
732   gp_Pnt GPoint;
733   TopTools_ListIteratorOfListOfShape it(SL);
734   for (Index=1;  it.More();  Index++)
735   {
736     TopoDS_Shape S = it.Value();
737     SL.Remove( it ); // == it.Next()
738     aShapes(Index) = S;
739     OrderInd.SetValue (Index, Index);
740     if (S.ShapeType() == TopAbs_VERTEX)
741     {
742       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
743       Length.SetValue( Index, (Standard_Real) S.Orientation());
744     }
745     else
746     {
747       BRepGProp::LinearProperties (S, GPr);
748       GPoint = GPr.CentreOfMass();
749       Length.SetValue( Index, GPr.Mass() );
750     }
751     MidXYZ.SetValue(Index,
752                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
753   }
754   // Sorting
755   Standard_Integer aTemp;
756   Standard_Boolean exchange, Sort = Standard_True;
757   while (Sort)
758   {
759     Sort = Standard_False;
760     for (Index=1; Index < MaxShapes; Index++)
761     {
762       if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
763         exchange = Standard_True;
764       else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
765                Length(OrderInd(Index)) >  Length(OrderInd(Index+1)) )
766         exchange = Standard_True;
767       else
768         exchange = Standard_False;
769       if (exchange)
770       {
771         aTemp = OrderInd(Index);
772         OrderInd(Index) = OrderInd(Index+1);
773         OrderInd(Index+1) = aTemp;
774         Sort = Standard_True;
775       }
776     }
777   }
778   for (Index=1; Index <= MaxShapes; Index++)
779     SL.Append( aShapes( OrderInd(Index) ));
780 }