Salome HOME
Merge with version on tag OCC-V2_1_0d
[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  *  GetSubShape
610  */
611 //=============================================================================
612 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
613                                           (Handle(GEOM_Object)    theMainShape,
614                                            const Standard_Integer theID)
615 {
616   SetErrorCode(KO);
617
618   if (theMainShape.IsNull()) return NULL;
619
620   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
621   anArray->SetValue(1, theID);
622   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray);
623   if (anObj.IsNull()) {
624     SetErrorCode("Can not get a sub-shape with the given ID");
625     return NULL;
626   }
627
628   //The GetSubShape() doesn't change object so no new function is requiered.
629   Handle(GEOM_Function) aFunction = theMainShape->GetLastFunction();
630
631   //Make a Python command
632   TCollection_AsciiString aDescr ("\n");
633   TCollection_AsciiString anEntry;
634   TDF_Tool::Entry(anObj->GetEntry(), anEntry);
635   aDescr += anEntry + " = IShapesOperations.GetSubShape(";
636   TDF_Tool::Entry(theMainShape->GetEntry(), anEntry);
637   aDescr += anEntry + ", ";
638   aDescr += TCollection_AsciiString(theID) + ")";
639
640   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
641   anOldDescr = anOldDescr + aDescr;
642   aFunction->SetDescription(anOldDescr);
643
644   SetErrorCode(OK);
645   return anObj;
646 }
647
648
649 //=============================================================================
650 /*!
651  *  NumberOfFaces
652  */
653 //=============================================================================
654 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
655 {
656   SetErrorCode(KO);
657
658   Standard_Integer nb = 0;
659
660   if (theShape.IsNull()) return -1;
661   TopoDS_Shape aShape = theShape->GetValue();
662   if (aShape.IsNull()) return -1;
663
664   TopTools_MapOfShape mapShape;
665
666   TopExp_Explorer exp (aShape, TopAbs_FACE);
667   for (; exp.More(); exp.Next())
668     if (mapShape.Add(exp.Current()))
669       nb++;
670
671   SetErrorCode(OK);
672   return nb;
673 }
674
675 //=============================================================================
676 /*!
677  *  NumberOfEdges
678  */
679 //=============================================================================
680 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
681 {
682   SetErrorCode(KO);
683
684   Standard_Integer nb = 0;
685
686   if (theShape.IsNull()) return -1;
687   TopoDS_Shape aShape = theShape->GetValue();
688   if (aShape.IsNull()) return -1;
689
690   TopTools_MapOfShape mapShape;
691
692   TopExp_Explorer exp (aShape, TopAbs_EDGE);
693   for (; exp.More(); exp.Next())
694     if (mapShape.Add(exp.Current()))
695       nb++;
696
697   SetErrorCode(OK);
698   return nb;
699 }
700
701 //=============================================================================
702 /*!
703  *  ReverseShape
704  */
705 //=============================================================================
706 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
707 {
708   SetErrorCode(KO);
709
710   if (theShape.IsNull()) return NULL;
711
712   //Add a new reversed object
713   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
714
715   //Add a new Revese function
716   Handle(GEOM_Function) aFunction;
717   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
718   if (aFunction.IsNull()) return NULL;
719
720   //Check if the function is set correctly
721   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
722
723   GEOMImpl_IShapes aSI (aFunction);
724
725   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
726   if (aRefShape.IsNull()) return NULL;
727
728   aSI.SetBase(aRefShape);
729
730   //Compute the sub-shape value
731   try {
732     if (!GetSolver()->ComputeFunction(aFunction)) {
733       SetErrorCode("Shape driver failed to reverse shape");
734       return NULL;
735     }
736   }
737   catch (Standard_Failure) {
738     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
739     SetErrorCode(aFail->GetMessageString());
740     return NULL;
741   }
742
743   //Make a Python command
744   TCollection_AsciiString anEntry, aDescr;
745   TDF_Tool::Entry(aReversed->GetEntry(), anEntry);
746   aDescr += anEntry;
747   aDescr += " = IShapesOperations.ReverseShape(";
748   TDF_Tool::Entry(theShape->GetEntry(), anEntry);
749   aDescr += anEntry + ")";
750
751   aFunction->SetDescription(aDescr);
752
753   SetErrorCode(OK);
754   return aReversed;
755 }
756
757
758 //=======================================================================
759 //function : SortShapes
760 //purpose  :
761 //=======================================================================
762 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
763 {
764   Standard_Integer MaxShapes = SL.Extent();
765   TopTools_Array1OfShape  aShapes (1,MaxShapes);
766   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
767   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
768   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
769
770   // Computing of CentreOfMass
771   Standard_Integer Index;
772   GProp_GProps GPr;
773   gp_Pnt GPoint;
774   TopTools_ListIteratorOfListOfShape it(SL);
775   for (Index=1;  it.More();  Index++)
776   {
777     TopoDS_Shape S = it.Value();
778     SL.Remove( it ); // == it.Next()
779     aShapes(Index) = S;
780     OrderInd.SetValue (Index, Index);
781     if (S.ShapeType() == TopAbs_VERTEX)
782     {
783       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
784       Length.SetValue( Index, (Standard_Real) S.Orientation());
785     }
786     else
787     {
788       BRepGProp::LinearProperties (S, GPr);
789       GPoint = GPr.CentreOfMass();
790       Length.SetValue( Index, GPr.Mass() );
791     }
792     MidXYZ.SetValue(Index,
793                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
794   }
795   // Sorting
796   Standard_Integer aTemp;
797   Standard_Boolean exchange, Sort = Standard_True;
798   while (Sort)
799   {
800     Sort = Standard_False;
801     for (Index=1; Index < MaxShapes; Index++)
802     {
803       if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
804         exchange = Standard_True;
805       else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
806                Length(OrderInd(Index)) >  Length(OrderInd(Index+1)) )
807         exchange = Standard_True;
808       else
809         exchange = Standard_False;
810       if (exchange)
811       {
812         aTemp = OrderInd(Index);
813         OrderInd(Index) = OrderInd(Index+1);
814         OrderInd(Index+1) = aTemp;
815         Sort = Standard_True;
816       }
817     }
818   }
819   for (Index=1; Index <= MaxShapes; Index++)
820     SL.Append( aShapes( OrderInd(Index) ));
821 }