]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
Salome HOME
PAL10015. Use GEOMAlgo_FinderShapeOnQuad for GetShapesOnQuad(). Fix
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IShapesOperations.cxx
1 #include <Standard_Stream.hxx>
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 #include "GEOM_PythonDump.hxx"
20
21 #include "GEOMAlgo_FinderShapeOn1.hxx"
22 #include "GEOMAlgo_FinderShapeOnQuad.hxx"
23
24 #include "utilities.h"
25 #include "OpUtil.hxx"
26 #include "Utils_ExceptHandlers.hxx"
27
28 #include <TFunction_DriverTable.hxx>
29 #include <TFunction_Driver.hxx>
30 #include <TFunction_Logbook.hxx>
31 #include <TDataStd_Integer.hxx>
32 #include <TDataStd_IntegerArray.hxx>
33 #include <TDF_Tool.hxx>
34
35 #include <BRepExtrema_ExtCF.hxx>
36
37 #include <BRep_Tool.hxx>
38 #include <BRepGProp.hxx>
39 #include <BRepAdaptor_Curve.hxx>
40 #include <BRepBndLib.hxx>
41 #include <BRepBuilderAPI_MakeFace.hxx>
42 #include <BRepMesh_IncrementalMesh.hxx>
43
44 #include <TopAbs.hxx>
45 #include <TopExp.hxx>
46 #include <TopoDS.hxx>
47 #include <TopoDS_Shape.hxx>
48 #include <TopoDS_Face.hxx>
49 #include <TopoDS_Edge.hxx>
50 #include <TopoDS_Vertex.hxx>
51 #include <TopoDS_Iterator.hxx>
52 #include <TopExp_Explorer.hxx>
53 #include <TopLoc_Location.hxx>
54 #include <TopTools_MapOfShape.hxx>
55 #include <TopTools_Array1OfShape.hxx>
56 #include <TopTools_ListIteratorOfListOfShape.hxx>
57 #include <TopTools_IndexedMapOfShape.hxx>
58
59 #include <Geom_Surface.hxx>
60 #include <Geom_Plane.hxx>
61 #include <Geom_SphericalSurface.hxx>
62 #include <Geom_CylindricalSurface.hxx>
63 #include <GeomAdaptor_Surface.hxx>
64
65 #include <Geom2d_Curve.hxx>
66
67 #include <Bnd_Box.hxx>
68 #include <GProp_GProps.hxx>
69 #include <gp_Pnt.hxx>
70 #include <gp_Lin.hxx>
71 #include <TColStd_Array1OfReal.hxx>
72 #include <TColStd_HArray1OfInteger.hxx>
73
74 #include <vector>
75 //#include <iostream>
76
77 //#include <OSD_Timer.hxx>
78
79 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
80
81 //=============================================================================
82 /*!
83  *   constructor:
84  */
85 //=============================================================================
86 GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID)
87 : GEOM_IOperations(theEngine, theDocID)
88 {
89   MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations");
90 }
91
92 //=============================================================================
93 /*!
94  *  destructor
95  */
96 //=============================================================================
97 GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations()
98 {
99   MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations");
100 }
101
102
103 //=============================================================================
104 /*!
105  *  MakeEdge
106  */
107 //=============================================================================
108 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge
109                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2)
110 {
111   SetErrorCode(KO);
112
113   if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL;
114
115   //Add a new Edge object
116   Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE);
117
118   //Add a new Vector function
119   Handle(GEOM_Function) aFunction =
120     anEdge->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_TWO_PNT);
121
122   //Check if the function is set correctly
123   if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
124
125   GEOMImpl_IVector aPI (aFunction);
126
127   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
128   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
129   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
130
131   aPI.SetPoint1(aRef1);
132   aPI.SetPoint2(aRef2);
133
134   //Compute the Edge value
135   try {
136     if (!GetSolver()->ComputeFunction(aFunction)) {
137       SetErrorCode("Vector driver failed");
138       return NULL;
139     }
140   }
141   catch (Standard_Failure) {
142     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
143     SetErrorCode(aFail->GetMessageString());
144     return NULL;
145   }
146
147   //Make a Python command
148   GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdge("
149                                << thePnt1 << ", " << thePnt2 << ")";
150
151   SetErrorCode(OK);
152   return anEdge;
153 }
154
155 //=============================================================================
156 /*!
157  *  MakeWire
158  */
159 //=============================================================================
160 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire
161                              (list<Handle(GEOM_Object)> theShapes)
162 {
163   return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire");
164 }
165
166 //=============================================================================
167 /*!
168  *  MakeFace
169  */
170 //=============================================================================
171 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) theWire,
172                                                           const bool isPlanarWanted)
173 {
174   SetErrorCode(KO);
175
176   if (theWire.IsNull()) return NULL;
177
178   //Add a new Face object
179   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
180
181   //Add a new Shape function for creation of a face from a wire
182   Handle(GEOM_Function) aFunction =
183     aFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRE);
184   if (aFunction.IsNull()) return NULL;
185
186   //Check if the function is set correctly
187   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
188
189   GEOMImpl_IShapes aCI (aFunction);
190
191   Handle(GEOM_Function) aRefWire = theWire->GetLastFunction();
192
193   if (aRefWire.IsNull()) return NULL;
194
195   aCI.SetBase(aRefWire);
196   aCI.SetIsPlanar(isPlanarWanted);
197
198   //Compute the Face value
199   try {
200     if (!GetSolver()->ComputeFunction(aFunction)) {
201       SetErrorCode("Shape driver failed to compute a face");
202       return NULL;
203     }
204   }
205   catch (Standard_Failure) {
206     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
207     SetErrorCode(aFail->GetMessageString());
208     return NULL;
209   }
210
211   //Make a Python command
212   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace("
213     << theWire << ", " << (int)isPlanarWanted << ")";
214
215   SetErrorCode(OK);
216   return aFace;
217 }
218
219 //=============================================================================
220 /*!
221  *  MakeFaceWires
222  */
223 //=============================================================================
224 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires
225                              (list<Handle(GEOM_Object)> theShapes,
226                               const bool isPlanarWanted)
227 {
228   SetErrorCode(KO);
229
230   //Add a new object
231   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
232
233   //Add a new function
234   Handle(GEOM_Function) aFunction =
235     aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_WIRES);
236   if (aFunction.IsNull()) return NULL;
237
238   //Check if the function is set correctly
239   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
240
241   GEOMImpl_IShapes aCI (aFunction);
242
243   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
244
245   // Shapes
246   list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
247   for (; it != theShapes.end(); it++) {
248     Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
249     if (aRefSh.IsNull()) {
250       SetErrorCode("NULL argument shape for the face construction");
251       return NULL;
252     }
253     aShapesSeq->Append(aRefSh);
254   }
255   aCI.SetShapes(aShapesSeq);
256
257   aCI.SetIsPlanar(isPlanarWanted);
258
259   //Compute the shape
260   try {
261     if (!GetSolver()->ComputeFunction(aFunction)) {
262       SetErrorCode("Shape driver failed");
263       return NULL;
264     }
265   }
266   catch (Standard_Failure) {
267     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
268     SetErrorCode(aFail->GetMessageString());
269     return NULL;
270   }
271
272   //Make a Python command
273   GEOM::TPythonDump pd (aFunction);
274   pd << aShape << " = geompy.MakeFaceWires([";
275
276   // Shapes
277   it = theShapes.begin();
278   if (it != theShapes.end()) {
279     pd << (*it++);
280     while (it != theShapes.end()) {
281       pd << ", " << (*it++);
282     }
283   }
284   pd << "], " << (int)isPlanarWanted << ")";
285
286   SetErrorCode(OK);
287   return aShape;
288 }
289
290 //=============================================================================
291 /*!
292  *  MakeShell
293  */
294 //=============================================================================
295 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell
296                              (list<Handle(GEOM_Object)> theShapes)
297 {
298   return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell");
299 }
300
301 //=============================================================================
302 /*!
303  *  MakeSolidShells
304  */
305 //=============================================================================
306 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells
307                              (list<Handle(GEOM_Object)> theShapes)
308 {
309   return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolidShells");
310 }
311
312 //=============================================================================
313 /*!
314  *  MakeSolidShell
315  */
316 //=============================================================================
317 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell)
318 {
319   SetErrorCode(KO);
320
321   if (theShell.IsNull()) return NULL;
322
323   //Add a new Solid object
324   Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID);
325
326   //Add a new Solid function for creation of a solid from a shell
327   Handle(GEOM_Function) aFunction =
328     aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL);
329   if (aFunction.IsNull()) return NULL;
330
331   //Check if the function is set correctly
332   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
333
334   GEOMImpl_IShapes aCI (aFunction);
335
336   Handle(GEOM_Function) aRefShell = theShell->GetLastFunction();
337
338   if (aRefShell.IsNull()) return NULL;
339
340   aCI.SetBase(aRefShell);
341
342   //Compute the Solid value
343   try {
344     if (!GetSolver()->ComputeFunction(aFunction)) {
345       SetErrorCode("Solid driver failed");
346       return NULL;
347     }
348   }
349   catch (Standard_Failure) {
350     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
351     SetErrorCode(aFail->GetMessageString());
352     return NULL;
353   }
354
355   //Make a Python command
356   GEOM::TPythonDump(aFunction) << aSolid
357     << " = geompy.MakeSolid(" << theShell << ")";
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   GEOM::TPythonDump pd (aFunction);
429   pd << aShape << " = geompy." << theMethodName.ToCString() << "([";
430
431   // Shapes
432   it = theShapes.begin();
433   if (it != theShapes.end()) {
434     pd << (*it++);
435     while (it != theShapes.end()) {
436       pd << ", " << (*it++);
437     }
438   }
439   pd << "])";
440
441   SetErrorCode(OK);
442   return aShape;
443 }
444
445 //=============================================================================
446 /*!
447  *  MakeGlueFaces
448  */
449 //=============================================================================
450 Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces
451                                                 (Handle(GEOM_Object) theShape,
452                                                  const Standard_Real theTolerance)
453 {
454   SetErrorCode(KO);
455
456   if (theShape.IsNull()) return NULL;
457
458   //Add a new Glued object
459   Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED);
460
461   //Add a new Glue function
462   Handle(GEOM_Function) aFunction;
463   aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES);
464   if (aFunction.IsNull()) return NULL;
465
466   //Check if the function is set correctly
467   if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL;
468
469   GEOMImpl_IGlue aCI (aFunction);
470
471   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
472   if (aRefShape.IsNull()) return NULL;
473
474   aCI.SetBase(aRefShape);
475   aCI.SetTolerance(theTolerance);
476
477   //Compute the sub-shape value
478   Standard_Boolean isWarning = Standard_False;
479   try {
480     if (!GetSolver()->ComputeFunction(aFunction)) {
481       SetErrorCode("Shape driver failed to glue faces");
482       return NULL;
483     }
484   }
485   catch (Standard_Failure) {
486     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
487     SetErrorCode(aFail->GetMessageString());
488     // to provide warning
489     if (!aFunction->GetValue().IsNull()) {
490       isWarning = Standard_True;
491     } else {
492       return NULL;
493     }
494   }
495
496   //Make a Python command
497   GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces("
498     << theShape << ", " << theTolerance << ")";
499
500   // to provide warning
501   if (!isWarning) SetErrorCode(OK);
502   return aGlued;
503 }
504
505 //=============================================================================
506 /*!
507  *  MakeExplode
508  */
509 //=============================================================================
510 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode
511                                           (Handle(GEOM_Object)    theShape,
512                                            const Standard_Integer theShapeType,
513                                            const Standard_Boolean isSorted)
514 {
515 //  OSD_Timer timer1, timer2, timer3, timer4;
516 //  timer1.Start();
517
518   SetErrorCode(KO);
519
520   if (theShape.IsNull()) return NULL;
521   TopoDS_Shape aShape = theShape->GetValue();
522   if (aShape.IsNull()) return NULL;
523
524   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
525   Handle(GEOM_Object) anObj;
526   Handle(GEOM_Function) aFunction;
527   TopTools_MapOfShape mapShape;
528   TopTools_ListOfShape listShape;
529
530   if (aShape.ShapeType() == TopAbs_COMPOUND &&
531       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
532        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
533        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
534     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
535     for (; It.More(); It.Next()) {
536       if (mapShape.Add(It.Value())) {
537         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
538             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
539           listShape.Append(It.Value());
540         }
541       }
542     }
543   } else {
544     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
545     for (; exp.More(); exp.Next())
546       if (mapShape.Add(exp.Current()))
547         listShape.Append(exp.Current());
548   }
549
550   if (listShape.IsEmpty()) {
551     SetErrorCode("The given shape has no sub-shapes of the requested type");
552     return aSeq;
553   }
554
555 //  timer1.Stop();
556 //  timer2.Start();
557
558   if (isSorted)
559     SortShapes(listShape);
560
561 //  timer2.Stop();
562 //  timer3.Start();
563
564   TopTools_IndexedMapOfShape anIndices;
565   TopExp::MapShapes(aShape, anIndices);
566   Handle(TColStd_HArray1OfInteger) anArray;
567
568   TopTools_ListIteratorOfListOfShape itSub (listShape);
569   TCollection_AsciiString anAsciiList, anEntry;
570   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
571     TopoDS_Shape aValue = itSub.Value();
572     anArray = new TColStd_HArray1OfInteger(1,1);
573     anArray->SetValue(1, anIndices.FindIndex(aValue));
574     anObj = GetEngine()->AddSubShape(theShape, anArray);
575     aSeq->Append(anObj);
576
577     // for python command
578     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
579     anAsciiList += anEntry;
580     anAsciiList += ",";
581   }
582
583   //Make a Python command
584   anAsciiList.Trunc(anAsciiList.Length() - 1);
585
586   aFunction = theShape->GetLastFunction();
587   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
588
589   GEOM::TPythonDump pd (aFunction);
590   pd << anOldDescr.ToCString() << "\n\t[" << anAsciiList.ToCString();
591   pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "(");
592   pd << theShape << ", " << theShapeType << ")";
593
594   SetErrorCode(OK);
595
596 //  timer4.Stop();
597
598 //  cout << "Explosure takes:" << endl;
599 //  timer1.Show();
600 //  cout << "Sorting takes:" << endl;
601 //  timer2.Show();
602 //  cout << "Sub-shapes addition takes:" << endl;
603 //  timer3.Show();
604 //  cout << "Update Description takes:" << endl;
605 //  timer4.Show();
606
607   return aSeq;
608 }
609
610 //=============================================================================
611 /*!
612  *  GetSubShapeAllIDs
613  */
614 //=============================================================================
615 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs
616                                           (Handle(GEOM_Object)    theShape,
617                                            const Standard_Integer theShapeType,
618                                            const Standard_Boolean isSorted)
619 {
620   SetErrorCode(KO);
621
622   if (theShape.IsNull()) return NULL;
623   TopoDS_Shape aShape = theShape->GetValue();
624   if (aShape.IsNull()) return NULL;
625
626   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
627   TopTools_MapOfShape mapShape;
628   TopTools_ListOfShape listShape;
629
630   if (aShape.ShapeType() == TopAbs_COMPOUND &&
631       (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
632        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID ||
633        TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) {
634     TopoDS_Iterator It (aShape, Standard_True, Standard_True);
635     for (; It.More(); It.Next()) {
636       if (mapShape.Add(It.Value())) {
637         if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE ||
638             TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) {
639           listShape.Append(It.Value());
640         }
641       }
642     }
643   } else {
644     TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType));
645     for (; exp.More(); exp.Next())
646       if (mapShape.Add(exp.Current()))
647         listShape.Append(exp.Current());
648   }
649
650   if (listShape.IsEmpty()) {
651     SetErrorCode("The given shape has no sub-shapes of the requested type");
652     return aSeq;
653   }
654
655   if (isSorted)
656     SortShapes(listShape);
657
658   TopTools_IndexedMapOfShape anIndices;
659   TopExp::MapShapes(aShape, anIndices);
660   Handle(TColStd_HArray1OfInteger) anArray;
661
662   TopTools_ListIteratorOfListOfShape itSub (listShape);
663   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
664     TopoDS_Shape aValue = itSub.Value();
665     aSeq->Append(anIndices.FindIndex(aValue));
666   }
667
668   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
669   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
670
671   //Make a Python command
672   GEOM::TPythonDump pd (aFunction);
673   pd << anOldDescr.ToCString() << "\n\tlistSubShapeIDs = geompy.SubShapeAll";
674   pd << (isSorted ? "SortedIDs(" : "IDs(");
675   pd << theShape << ", " << theShapeType << ")";
676
677   SetErrorCode(OK);
678   return aSeq;
679 }
680
681 //=============================================================================
682 /*!
683  *  GetSubShape
684  */
685 //=============================================================================
686 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape
687                                           (Handle(GEOM_Object)    theMainShape,
688                                            const Standard_Integer theID)
689 {
690   SetErrorCode(KO);
691
692   if (theMainShape.IsNull()) return NULL;
693
694   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
695   anArray->SetValue(1, theID);
696   Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true);
697   if (anObj.IsNull()) {
698     SetErrorCode("Can not get a sub-shape with the given ID");
699     return NULL;
700   }
701
702   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
703
704   //Make a Python command
705   GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape("
706                                << theMainShape << ", [" << theID << "])";
707
708   SetErrorCode(OK);
709   return anObj;
710 }
711
712
713 //=============================================================================
714 /*!
715  *  NumberOfFaces
716  */
717 //=============================================================================
718 Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape)
719 {
720   SetErrorCode(KO);
721
722   Standard_Integer nb = 0;
723
724   if (theShape.IsNull()) return -1;
725   TopoDS_Shape aShape = theShape->GetValue();
726   if (aShape.IsNull()) return -1;
727
728   TopTools_MapOfShape mapShape;
729
730   TopExp_Explorer exp (aShape, TopAbs_FACE);
731   for (; exp.More(); exp.Next())
732     if (mapShape.Add(exp.Current()))
733       nb++;
734
735   SetErrorCode(OK);
736   return nb;
737 }
738
739 //=============================================================================
740 /*!
741  *  NumberOfEdges
742  */
743 //=============================================================================
744 Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape)
745 {
746   SetErrorCode(KO);
747
748   Standard_Integer nb = 0;
749
750   if (theShape.IsNull()) return -1;
751   TopoDS_Shape aShape = theShape->GetValue();
752   if (aShape.IsNull()) return -1;
753
754   TopTools_MapOfShape mapShape;
755
756   TopExp_Explorer exp (aShape, TopAbs_EDGE);
757   for (; exp.More(); exp.Next())
758     if (mapShape.Add(exp.Current()))
759       nb++;
760
761   SetErrorCode(OK);
762   return nb;
763 }
764
765 //=============================================================================
766 /*!
767  *  ReverseShape
768  */
769 //=============================================================================
770 Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape)
771 {
772   SetErrorCode(KO);
773
774   if (theShape.IsNull()) return NULL;
775
776   //Add a new reversed object
777   Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType());
778
779   //Add a new Revese function
780   Handle(GEOM_Function) aFunction;
781   aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION);
782   if (aFunction.IsNull()) return NULL;
783
784   //Check if the function is set correctly
785   if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL;
786
787   GEOMImpl_IShapes aSI (aFunction);
788
789   Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
790   if (aRefShape.IsNull()) return NULL;
791
792   aSI.SetBase(aRefShape);
793
794   //Compute the sub-shape value
795   try {
796     if (!GetSolver()->ComputeFunction(aFunction)) {
797       SetErrorCode("Shape driver failed to reverse shape");
798       return NULL;
799     }
800   }
801   catch (Standard_Failure) {
802     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
803     SetErrorCode(aFail->GetMessageString());
804     return NULL;
805   }
806
807   //Make a Python command
808   GEOM::TPythonDump(aFunction) << aReversed
809     << " = geompy.ChangeOrientation(" << theShape << ")";
810
811   SetErrorCode(OK);
812   return aReversed;
813 }
814
815 //=============================================================================
816 /*!
817  *  GetFreeFacesIDs
818  */
819 //=============================================================================
820 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
821                                                  (Handle(GEOM_Object) theShape)
822 {
823   SetErrorCode(KO);
824
825   if (theShape.IsNull()) return NULL;
826   TopoDS_Shape aShape = theShape->GetValue();
827   if (aShape.IsNull()) return NULL;
828
829   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
830
831   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
832   GEOMImpl_Block6Explorer::MapShapesAndAncestors
833     (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
834
835   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
836
837   if (nbFaces == 0) {
838     SetErrorCode("The given shape has no faces");
839     return aSeq;
840   }
841
842   TopTools_IndexedMapOfShape anIndices;
843   TopExp::MapShapes(aShape, anIndices);
844
845   Standard_Integer id;
846   for (; ind <= nbFaces; ind++) {
847     if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
848       id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
849       aSeq->Append(id);
850     }
851   }
852
853   //The explode doesn't change object so no new function is required.
854   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
855   TCollection_AsciiString anOldDescr = aFunction->GetDescription();
856
857   //Make a Python command
858   GEOM::TPythonDump(aFunction) << anOldDescr.ToCString()
859     << "\n\tlistFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
860
861   SetErrorCode(OK);
862   return aSeq;
863 }
864
865 //=======================================================================
866 //function : GetSharedShapes
867 //purpose  : 
868 //=======================================================================
869
870 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
871                                                 (Handle(GEOM_Object)    theShape1,
872                                                  Handle(GEOM_Object)    theShape2,
873                                                  const Standard_Integer theShapeType)
874 {
875   SetErrorCode(KO);
876
877   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
878
879   TopoDS_Shape aShape1 = theShape1->GetValue();
880   TopoDS_Shape aShape2 = theShape2->GetValue();
881
882   if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
883
884   TopTools_IndexedMapOfShape anIndices;
885   TopExp::MapShapes(aShape1, anIndices);
886   Handle(TColStd_HArray1OfInteger) anArray;
887
888   TopTools_IndexedMapOfShape mapShape1;
889   TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
890
891   Handle(GEOM_Object) anObj;
892   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
893   TCollection_AsciiString anAsciiList, anEntry;
894
895   TopTools_MapOfShape mapShape2;
896   TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
897   for (; exp.More(); exp.Next()) {
898     TopoDS_Shape aSS = exp.Current();
899     if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
900       anArray = new TColStd_HArray1OfInteger(1,1);
901       anArray->SetValue(1, anIndices.FindIndex(aSS));
902       anObj = GetEngine()->AddSubShape(theShape1, anArray);
903       aSeq->Append(anObj);
904
905       // for python command
906       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
907       anAsciiList += anEntry;
908       anAsciiList += ",";
909     }
910   }
911
912   if (aSeq->IsEmpty()) {
913     SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
914     return aSeq;
915   }
916
917   //Make a Python command
918   anAsciiList.Trunc(anAsciiList.Length() - 1);
919
920   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
921
922   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
923     << "] = geompy.GetSharedShapes(" << theShape1 << ", "
924       << theShape2 << ", " << theShapeType << ")";
925
926   SetErrorCode(OK);
927   return aSeq;
928 }
929
930 //=============================================================================
931 /*!
932  *  
933  */
934 //=============================================================================
935 static GEOM::TPythonDump& operator<< (GEOM::TPythonDump&   theDump,
936                                       const GEOMAlgo_State theState)
937 {
938   switch (theState) {
939   case GEOMAlgo_ST_IN:
940     theDump << "geompy.GEOM.ST_IN";
941     break;
942   case GEOMAlgo_ST_OUT:
943     theDump << "geompy.GEOM.ST_OUT";
944     break;
945   case GEOMAlgo_ST_ON:
946     theDump << "geompy.GEOM.ST_ON";
947     break;
948   case GEOMAlgo_ST_ONIN:
949     theDump << "geompy.GEOM.ST_ONIN";
950     break;
951   case GEOMAlgo_ST_ONOUT:
952     theDump << "geompy.GEOM.ST_ONOUT";
953     break;
954   default:
955     theDump << "geompy.GEOM.ST_UNKNOWN";
956     break;
957   }
958   return theDump;
959 }
960
961 //=======================================================================
962 //function : checkTypeShapesOn
963 /*!
964  * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
965  * \param theShapeType - the shape type to check
966  * \retval bool  - result of the check
967  */
968 //=======================================================================
969
970 bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
971 {
972   if (theShapeType != TopAbs_VERTEX &&
973       theShapeType != TopAbs_EDGE &&
974       theShapeType != TopAbs_FACE &&
975       theShapeType != TopAbs_SOLID) {
976     SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
977     return false;
978   }
979   return true;
980 }
981
982 //=======================================================================
983 //function : makePlane
984   /*!
985    * \brief Creates Geom_Plane
986     * \param theAx1 - shape object defining plane parameters
987     * \retval Handle(Geom_Surface) - resulting surface
988    */
989 //=======================================================================
990
991 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
992 {
993   if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
994   TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
995   TopoDS_Vertex V1, V2;
996   TopExp::Vertices(anEdge, V1, V2, Standard_True);
997   if (V1.IsNull() || V2.IsNull()) {
998     SetErrorCode("Bad edge given for the plane normal vector");
999     return NULL;
1000   }
1001   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1002   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1003   if (aVec.Magnitude() < Precision::Confusion()) {
1004     SetErrorCode("Vector with null magnitude given");
1005     return NULL;
1006   }
1007   return new Geom_Plane(aLoc, aVec);
1008 }
1009
1010 //=======================================================================
1011 //function : makeCylinder
1012   /*!
1013    * \brief Creates Geom_CylindricalSurface
1014     * \param theAx1 - edge defining cylinder axis
1015     * \param theRadius - cylinder radius
1016     * \retval Handle(Geom_Surface) - resulting surface
1017    */
1018 //=======================================================================
1019
1020 Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
1021                                                               const Standard_Real theRadius)
1022 {
1023   //Axis of the cylinder
1024   if (anAxis.ShapeType() != TopAbs_EDGE) {
1025     SetErrorCode("Not an edge given for the axis");
1026     return NULL;
1027   }
1028   TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
1029   TopoDS_Vertex V1, V2;
1030   TopExp::Vertices(anEdge, V1, V2, Standard_True);
1031   if (V1.IsNull() || V2.IsNull()) {
1032     SetErrorCode("Bad edge given for the axis");
1033     return NULL;
1034   }
1035   gp_Pnt aLoc = BRep_Tool::Pnt(V1);
1036   gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
1037   if (aVec.Magnitude() < Precision::Confusion()) {
1038     SetErrorCode("Vector with null magnitude given");
1039     return NULL;
1040   }
1041
1042   gp_Ax3 anAx3 (aLoc, aVec);
1043   return new Geom_CylindricalSurface(anAx3, theRadius);
1044 }
1045
1046
1047 //=======================================================================
1048 //function : getShapesOnSurfaceIDs
1049   /*!
1050    * \brief Find IDs of subshapes complying with given status about surface
1051     * \param theSurface - the surface to check state of subshapes against
1052     * \param theShape - the shape to explore
1053     * \param theShapeType - type of subshape of theShape
1054     * \param theState - required state
1055     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1056    */
1057 //=======================================================================
1058
1059 Handle(TColStd_HSequenceOfInteger)
1060   GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
1061                                                     const TopoDS_Shape&         theShape,
1062                                                     TopAbs_ShapeEnum            theShapeType,
1063                                                     GEOMAlgo_State              theState)
1064 {
1065   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1066 //  MESSAGE("--------------------------- GetShapesOnPlane phase 1 takes:");
1067 //  OSD_Timer timer1;
1068 //  timer1.Start();
1069
1070   // Check presence of triangulation, build if need
1071   if (!CheckTriangulation(theShape))
1072     return aSeqOfIDs;
1073
1074   // Call algo
1075   GEOMAlgo_FinderShapeOn1 aFinder;
1076   Standard_Real aTol = 0.0001; // default value
1077
1078   aFinder.SetShape(theShape);
1079   aFinder.SetTolerance(aTol);
1080   aFinder.SetSurface(theSurface);
1081   aFinder.SetShapeType(theShapeType);
1082   aFinder.SetState(theState);
1083
1084   // Sets the minimal number of inner points for the faces that do not have own
1085   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1086   // Default value=3
1087   aFinder.SetNbPntsMin(3);
1088   // Sets the maximal number of inner points for edges or faces.
1089   // It is usefull for the cases when this number is very big (e.g =2000) to improve
1090   // the performance. If this value =0, all inner points will be taken into account.
1091   // Default value=0
1092   aFinder.SetNbPntsMax(100);
1093
1094 //  timer1.Stop();
1095 //  timer1.Show();
1096
1097 //  MESSAGE("--------------------------- Perform on Plane takes:");
1098 //  timer1.Reset();
1099 //  timer1.Start();
1100   aFinder.Perform();
1101 //  timer1.Stop();
1102 //  timer1.Show();
1103
1104 //  MESSAGE("--------------------------- GetShapesOnPlane phase 3 takes:");
1105 //  timer1.Reset();
1106 //  timer1.Start();
1107
1108   // Interprete results
1109   Standard_Integer iErr = aFinder.ErrorStatus();
1110   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1111   if (iErr) {
1112     MESSAGE(" iErr : " << iErr);
1113     TCollection_AsciiString aMsg (" iErr : ");
1114     aMsg += TCollection_AsciiString(iErr);
1115     SetErrorCode(aMsg);
1116     return aSeqOfIDs;
1117   }
1118   Standard_Integer iWrn = aFinder.WarningStatus();
1119   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1120   if (iWrn) {
1121     MESSAGE(" *** iWrn : " << iWrn);
1122   }
1123
1124   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1125
1126   if (listSS.Extent() < 1) {
1127     SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1128     return aSeqOfIDs;
1129   }
1130
1131 //  timer1.Stop();
1132 //  timer1.Show();
1133
1134 //  MESSAGE("--------------------------- GetShapesOnPlane phase 4 takes:");
1135 //  timer1.Reset();
1136 //  timer1.Start();
1137
1138   // Fill sequence of object IDs
1139   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1140
1141   TopTools_IndexedMapOfShape anIndices;
1142   TopExp::MapShapes(theShape, anIndices);
1143
1144   TopTools_ListIteratorOfListOfShape itSub (listSS);
1145   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1146     int id = anIndices.FindIndex(itSub.Value());
1147     aSeqOfIDs->Append(id);
1148   }
1149 //  timer1.Stop();
1150 //  timer1.Show();
1151   return aSeqOfIDs;
1152 }
1153
1154 //=======================================================================
1155 //function : getObjectsShapesOn
1156 /*!
1157  * \brief Find shape objects and their entries by their ids
1158  * \param theShapeIDs - incoming shape ids
1159  * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1160  * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
1161  */
1162 //=======================================================================
1163
1164 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
1165  getObjectsShapesOn(const Handle(GEOM_Object)&                theShape,
1166                     const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
1167                     TCollection_AsciiString &                 theShapeEntries)
1168 {
1169   Handle(TColStd_HSequenceOfTransient) aSeq;
1170
1171   if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
1172   {
1173     aSeq = new TColStd_HSequenceOfTransient;
1174     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
1175     TCollection_AsciiString anEntry;
1176     for ( int i = 1; i <= theShapeIDs->Length(); ++i )
1177     {
1178       anArray->SetValue(1, theShapeIDs->Value( i ));
1179       Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
1180       aSeq->Append( anObj );
1181
1182       TDF_Tool::Entry(anObj->GetEntry(), anEntry);
1183       if ( i != 1 ) theShapeEntries += ",";
1184       theShapeEntries += anEntry;
1185     }
1186   }
1187   return aSeq;
1188 }
1189
1190 //=======================================================================
1191 //function : getShapesOnSurface
1192 /*!
1193    * \brief Find subshapes complying with given status about surface
1194     * \param theSurface - the surface to check state of subshapes against
1195     * \param theShape - the shape to explore
1196     * \param theShapeType - type of subshape of theShape
1197     * \param theState - required state
1198     * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
1199     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1200  */
1201 //=======================================================================
1202
1203 Handle(TColStd_HSequenceOfTransient)
1204     GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
1205                                                    const Handle(GEOM_Object)&  theShape,
1206                                                    TopAbs_ShapeEnum            theShapeType,
1207                                                    GEOMAlgo_State              theState,
1208                                                    TCollection_AsciiString &   theShapeEntries)
1209 {
1210   // Find subshapes ids
1211   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1212     getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
1213   if ( aSeqOfIDs.IsNull()  || aSeqOfIDs->Length() == 0 )
1214     return NULL;
1215
1216   return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
1217 }
1218
1219 //=============================================================================
1220 /*!
1221  *  GetShapesOnPlane
1222  */
1223 //=============================================================================
1224 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
1225                                         (const Handle(GEOM_Object)& theShape,
1226                                          const Standard_Integer     theShapeType,
1227                                          const Handle(GEOM_Object)& theAx1,
1228                                          const GEOMAlgo_State       theState)
1229 {
1230   SetErrorCode(KO);
1231
1232 //  MESSAGE("--------------------------- GetShapesOnPlane phase 1 takes:");
1233 //  OSD_Timer timer1;
1234 //  timer1.Start();
1235
1236   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1237
1238   TopoDS_Shape aShape = theShape->GetValue();
1239   TopoDS_Shape anAx1  = theAx1->GetValue();
1240
1241   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1242
1243   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1244   if ( !checkTypeShapesOn( theShapeType ))
1245     return NULL;
1246
1247   // Create plane
1248   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1249   if ( aPlane.IsNull() )
1250     return NULL;
1251
1252   // Find objects
1253   TCollection_AsciiString anAsciiList;
1254   Handle(TColStd_HSequenceOfTransient) aSeq;
1255   aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
1256   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1257     return NULL;
1258
1259 //  timer1.Stop();
1260 //  timer1.Show();
1261
1262 //  MESSAGE("--------------------------- GetShapesOnPlane phase 5 takes:");
1263 //  timer1.Reset();
1264 //  timer1.Start();
1265
1266   // Make a Python command
1267
1268   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1269   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1270
1271   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1272     << "] = geompy.GetShapesOnPlane(" << theShape << ", "
1273       << theShapeType << ", " << theAx1 << ", " << theState << ")";
1274
1275   SetErrorCode(OK);
1276   return aSeq;
1277 }
1278
1279 //=============================================================================
1280 /*!
1281  *  GetShapesOnCylinder
1282  */
1283 //=============================================================================
1284 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
1285                                           (const Handle(GEOM_Object)& theShape,
1286                                            const Standard_Integer     theShapeType,
1287                                            const Handle(GEOM_Object)& theAxis,
1288                                            const Standard_Real        theRadius,
1289                                            const GEOMAlgo_State       theState)
1290 {
1291   SetErrorCode(KO);
1292
1293   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1294
1295   TopoDS_Shape aShape = theShape->GetValue();
1296   TopoDS_Shape anAxis = theAxis->GetValue();
1297
1298   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1299
1300   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1301   if ( !checkTypeShapesOn( aShapeType ))
1302     return NULL;
1303
1304   // Create a cylinder surface
1305   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1306   if ( aCylinder.IsNull() )
1307     return NULL;
1308
1309   // Find objects
1310   TCollection_AsciiString anAsciiList;
1311   Handle(TColStd_HSequenceOfTransient) aSeq;
1312   aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
1313   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1314     return NULL;
1315   
1316   // Make a Python command
1317
1318   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1319   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1320
1321   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1322     << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << theShapeType
1323       << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
1324
1325   SetErrorCode(OK);
1326   return aSeq;
1327 }
1328
1329 //=============================================================================
1330 /*!
1331  *  GetShapesOnSphere
1332  */
1333 //=============================================================================
1334 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
1335                                           (const Handle(GEOM_Object)& theShape,
1336                                            const Standard_Integer     theShapeType,
1337                                            const Handle(GEOM_Object)& theCenter,
1338                                            const Standard_Real        theRadius,
1339                                            const GEOMAlgo_State       theState)
1340 {
1341   SetErrorCode(KO);
1342
1343   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1344
1345   TopoDS_Shape aShape  = theShape->GetValue();
1346   TopoDS_Shape aCenter = theCenter->GetValue();
1347
1348   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1349
1350   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1351   if ( !checkTypeShapesOn( aShapeType ))
1352     return NULL;
1353
1354   // Center of the sphere
1355   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1356   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1357
1358   gp_Ax3 anAx3 (aLoc, gp::DZ());
1359   Handle(Geom_SphericalSurface) aSphere =
1360     new Geom_SphericalSurface(anAx3, theRadius);
1361
1362   // Find objects
1363   TCollection_AsciiString anAsciiList;
1364   Handle(TColStd_HSequenceOfTransient) aSeq;
1365   aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
1366   if ( aSeq.IsNull() || aSeq->Length() == 0 )
1367     return NULL;
1368     
1369   // Make a Python command
1370
1371   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1372   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1373
1374   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
1375     << "] = geompy.GetShapesOnSphere(" << theShape << ", " << theShapeType
1376       << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
1377
1378   SetErrorCode(OK);
1379   return aSeq;
1380 }
1381
1382 //=======================================================================
1383 //function : getCreatedLast
1384   /*!
1385    * \brief Select the object created last
1386     * \param theObj1 - Object 1
1387     * \param theObj2 - Object 2
1388     * \retval Handle(GEOM_Object) - selected object
1389    */
1390 //=======================================================================
1391
1392 Handle(GEOM_Object) GEOMImpl_IShapesOperations::getCreatedLast(const Handle(GEOM_Object)& theObj1,
1393                                                                const Handle(GEOM_Object)& theObj2)
1394 {
1395   if ( theObj1.IsNull() ) return theObj2;
1396   if ( theObj2.IsNull() ) return theObj1;
1397   return ( theObj1->GetEntry().Tag() > theObj2->GetEntry().Tag() ) ? theObj1 : theObj2;
1398 }
1399
1400 //=============================================================================
1401 /*!
1402  *  GetShapesOnPlaneIDs
1403  */
1404 //=============================================================================
1405 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
1406                                         (const Handle(GEOM_Object)& theShape,
1407                                          const Standard_Integer     theShapeType,
1408                                          const Handle(GEOM_Object)& theAx1,
1409                                          const GEOMAlgo_State       theState)
1410 {
1411   SetErrorCode(KO);
1412
1413   if (theShape.IsNull() || theAx1.IsNull()) return NULL;
1414
1415   TopoDS_Shape aShape = theShape->GetValue();
1416   TopoDS_Shape anAx1  = theAx1->GetValue();
1417
1418   if (aShape.IsNull() || anAx1.IsNull()) return NULL;
1419
1420   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1421   if ( !checkTypeShapesOn( aShapeType ))
1422     return NULL;
1423
1424   // Create plane
1425   Handle(Geom_Surface) aPlane = makePlane( anAx1 );
1426   if ( aPlane.IsNull() )
1427     return NULL;
1428
1429   // Find object IDs
1430   Handle(TColStd_HSequenceOfInteger) aSeq;
1431   aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
1432
1433   // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
1434   Handle(GEOM_Function) aFunction = getCreatedLast(theShape,theAx1)->GetLastFunction();
1435
1436   // Make a Python command
1437   const bool append = true;
1438   GEOM::TPythonDump(aFunction,append)
1439     << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
1440     << "(" << theShape << "," << theShapeType << "," << theAx1 << "," << theState << ")";
1441
1442   SetErrorCode(OK);
1443   return aSeq;
1444 }
1445
1446 //=============================================================================
1447 /*!
1448  *  GetShapesOnCylinderIDs
1449  */
1450 //=============================================================================
1451 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
1452                                           (const Handle(GEOM_Object)& theShape,
1453                                            const Standard_Integer     theShapeType,
1454                                            const Handle(GEOM_Object)& theAxis,
1455                                            const Standard_Real        theRadius,
1456                                            const GEOMAlgo_State       theState)
1457 {
1458   SetErrorCode(KO);
1459
1460   if (theShape.IsNull() || theAxis.IsNull()) return NULL;
1461
1462   TopoDS_Shape aShape = theShape->GetValue();
1463   TopoDS_Shape anAxis = theAxis->GetValue();
1464
1465   if (aShape.IsNull() || anAxis.IsNull()) return NULL;
1466
1467   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1468   if ( !checkTypeShapesOn( aShapeType ))
1469     return NULL;
1470
1471   // Create a cylinder surface
1472   Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
1473   if ( aCylinder.IsNull() )
1474     return NULL;
1475   
1476   // Find object IDs
1477   Handle(TColStd_HSequenceOfInteger) aSeq;
1478   aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
1479
1480   // The GetShapesOnCylinder() doesn't change object so no new function is required.
1481   Handle(GEOM_Function) aFunction = getCreatedLast(theShape,theAxis)->GetLastFunction();
1482
1483   // Make a Python command
1484   const bool append = true;
1485   GEOM::TPythonDump(aFunction,append)
1486     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
1487     << "(" << theShape << ", " << theShapeType << ", " << theAxis << ", "
1488     << theRadius << ", " << theState << ")";
1489
1490   SetErrorCode(OK);
1491   return aSeq;
1492 }
1493
1494 //=============================================================================
1495 /*!
1496  *  GetShapesOnSphereIDs
1497  */
1498 //=============================================================================
1499 Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
1500                                           (const Handle(GEOM_Object)& theShape,
1501                                            const Standard_Integer     theShapeType,
1502                                            const Handle(GEOM_Object)& theCenter,
1503                                            const Standard_Real        theRadius,
1504                                            const GEOMAlgo_State       theState)
1505 {
1506   SetErrorCode(KO);
1507
1508   if (theShape.IsNull() || theCenter.IsNull()) return NULL;
1509
1510   TopoDS_Shape aShape  = theShape->GetValue();
1511   TopoDS_Shape aCenter = theCenter->GetValue();
1512
1513   if (aShape.IsNull() || aCenter.IsNull()) return NULL;
1514
1515   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1516   if ( !checkTypeShapesOn( aShapeType ))
1517     return NULL;
1518
1519   // Center of the sphere
1520   if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
1521   gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
1522
1523   gp_Ax3 anAx3 (aLoc, gp::DZ());
1524   Handle(Geom_SphericalSurface) aSphere =
1525     new Geom_SphericalSurface(anAx3, theRadius);
1526
1527   // Find object IDs
1528   Handle(TColStd_HSequenceOfInteger) aSeq;
1529   aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
1530   
1531   // The GetShapesOnSphere() doesn't change object so no new function is required.
1532   Handle(GEOM_Function) aFunction = getCreatedLast(theShape,theCenter)->GetLastFunction();
1533
1534   // Make a Python command
1535   const bool append = true;
1536   GEOM::TPythonDump(aFunction,append)
1537     << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
1538     << "(" << theShape << ", " << theShapeType << ", " << theCenter << ", "
1539     << theRadius << ", " << theState << ")";
1540
1541   SetErrorCode(OK);
1542   return aSeq;
1543 }
1544
1545 //=======================================================================
1546 //function : getShapesOnQuadrangleIDs
1547   /*!
1548    * \brief Find IDs of subshapes complying with given status about quadrangle
1549     * \param theShape - the shape to explore
1550     * \param theShapeType - type of subshape of theShape
1551     * \param theTopLeftPoint - top left quadrangle corner
1552     * \param theTopRigthPoint - top right quadrangle corner
1553     * \param theBottomLeftPoint - bottom left quadrangle corner
1554     * \param theBottomRigthPoint - bottom right quadrangle corner
1555     * \param theState - required state
1556     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1557    */
1558 //=======================================================================
1559
1560 Handle(TColStd_HSequenceOfInteger)
1561   GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
1562                                                         const Standard_Integer     theShapeType,
1563                                                         const Handle(GEOM_Object)& theTopLeftPoint,
1564                                                         const Handle(GEOM_Object)& theTopRigthPoint,
1565                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
1566                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
1567                                                         const GEOMAlgo_State       theState)
1568 {
1569   SetErrorCode(KO);
1570
1571   if ( theShape.IsNull() ||
1572        theTopLeftPoint.IsNull() ||
1573        theTopRigthPoint.IsNull() ||
1574        theBottomLeftPoint.IsNull() ||
1575        theBottomRigthPoint.IsNull() )
1576     return NULL;
1577
1578   TopoDS_Shape aShape = theShape->GetValue();
1579   TopoDS_Shape aTL = theTopLeftPoint->GetValue();
1580   TopoDS_Shape aTR = theTopRigthPoint->GetValue();
1581   TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
1582   TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
1583
1584   if (aShape.IsNull() ||
1585       aTL.IsNull() || 
1586       aTR.IsNull() || 
1587       aBL.IsNull() || 
1588       aBR.IsNull() ||
1589       aTL.ShapeType() != TopAbs_VERTEX || 
1590       aTR.ShapeType() != TopAbs_VERTEX || 
1591       aBL.ShapeType() != TopAbs_VERTEX || 
1592       aBR.ShapeType() != TopAbs_VERTEX )
1593     return NULL;
1594
1595   TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
1596   if ( !checkTypeShapesOn( aShapeType ))
1597     return NULL;
1598
1599   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
1600
1601   // Check presence of triangulation, build if need
1602   if (!CheckTriangulation(aShape))
1603     return aSeqOfIDs;
1604
1605   // Call algo
1606   gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
1607   gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
1608   gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
1609   gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
1610
1611   GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
1612   Standard_Real aTol = 0.0001; // default value
1613
1614   aFinder.SetShape(aShape);
1615   aFinder.SetTolerance(aTol);
1616   //aFinder.SetSurface(theSurface);
1617   aFinder.SetShapeType(aShapeType);
1618   aFinder.SetState(theState);
1619
1620   // Sets the minimal number of inner points for the faces that do not have own
1621   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
1622   // Default value=3
1623   aFinder.SetNbPntsMin(3);
1624   // Sets the maximal number of inner points for edges or faces.
1625   // It is usefull for the cases when this number is very big (e.g =2000) to improve
1626   // the performance. If this value =0, all inner points will be taken into account.
1627   // Default value=0
1628   aFinder.SetNbPntsMax(100);
1629
1630   aFinder.Perform();
1631
1632   // Interprete results
1633   Standard_Integer iErr = aFinder.ErrorStatus();
1634   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
1635   if (iErr) {
1636     MESSAGE(" iErr : " << iErr);
1637     TCollection_AsciiString aMsg (" iErr : ");
1638     aMsg += TCollection_AsciiString(iErr);
1639     SetErrorCode(aMsg);
1640     return aSeqOfIDs;
1641   }
1642   Standard_Integer iWrn = aFinder.WarningStatus();
1643   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
1644   if (iWrn) {
1645     MESSAGE(" *** iWrn : " << iWrn);
1646   }
1647
1648   const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
1649
1650   if (listSS.Extent() < 1) {
1651     SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
1652     return aSeqOfIDs;
1653   }
1654
1655   // Fill sequence of object IDs
1656   aSeqOfIDs = new TColStd_HSequenceOfInteger;
1657
1658   TopTools_IndexedMapOfShape anIndices;
1659   TopExp::MapShapes(aShape, anIndices);
1660
1661   TopTools_ListIteratorOfListOfShape itSub (listSS);
1662   for (int index = 1; itSub.More(); itSub.Next(), ++index) {
1663     int id = anIndices.FindIndex(itSub.Value());
1664     aSeqOfIDs->Append(id);
1665   }
1666   return aSeqOfIDs;
1667 }
1668
1669 //=======================================================================
1670 //function : GetShapesOnQuadrangle
1671   /*!
1672    * \brief Find subshapes complying with given status about quadrangle
1673     * \param theShape - the shape to explore
1674     * \param theShapeType - type of subshape of theShape
1675     * \param theTopLeftPoint - top left quadrangle corner
1676     * \param theTopRigthPoint - top right quadrangle corner
1677     * \param theBottomLeftPoint - bottom left quadrangle corner
1678     * \param theBottomRigthPoint - bottom right quadrangle corner
1679     * \param theState - required state
1680     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1681    */
1682 //=======================================================================
1683
1684 Handle(TColStd_HSequenceOfTransient)
1685     GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
1686                                                        const Standard_Integer     theShapeType,
1687                                                        const Handle(GEOM_Object)& theTopLeftPoint,
1688                                                        const Handle(GEOM_Object)& theTopRigthPoint,
1689                                                        const Handle(GEOM_Object)& theBottomLeftPoint,
1690                                                        const Handle(GEOM_Object)& theBottomRigthPoint,
1691                                                        const GEOMAlgo_State       theState)
1692 {
1693   // Find indices
1694   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1695     getShapesOnQuadrangleIDs( theShape,
1696                               theShapeType,
1697                               theTopLeftPoint,
1698                               theTopRigthPoint,
1699                               theBottomLeftPoint,
1700                               theBottomRigthPoint,
1701                               theState);
1702   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
1703     return NULL;
1704
1705   // Find objects by indices
1706   TCollection_AsciiString anAsciiList;
1707   Handle(TColStd_HSequenceOfTransient) aSeq;
1708   aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
1709   if ( aSeq.IsNull() || aSeq->IsEmpty() )
1710     return NULL;
1711
1712   // Make a Python command
1713
1714   Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
1715   Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
1716
1717   GEOM::TPythonDump(aFunction)
1718     << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
1719     << theShape << ", "
1720     << theShapeType << ", "
1721     << theTopLeftPoint << ", "
1722     << theTopRigthPoint << ", "
1723     << theBottomLeftPoint << ", "
1724     << theBottomRigthPoint << ", "
1725     << theState << ")";
1726
1727   SetErrorCode(OK);
1728   return aSeq;
1729 }
1730
1731 //=======================================================================
1732 //function : GetShapesOnQuadrangleIDs
1733   /*!
1734    * \brief Find IDs of subshapes complying with given status about quadrangle
1735     * \param theShape - the shape to explore
1736     * \param theShapeType - type of subshape of theShape
1737     * \param theTopLeftPoint - top left quadrangle corner
1738     * \param theTopRigthPoint - top right quadrangle corner
1739     * \param theBottomLeftPoint - bottom left quadrangle corner
1740     * \param theBottomRigthPoint - bottom right quadrangle corner
1741     * \param theState - required state
1742     * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
1743    */
1744 //=======================================================================
1745
1746 Handle(TColStd_HSequenceOfInteger)
1747   GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
1748                                                         const Standard_Integer     theShapeType,
1749                                                         const Handle(GEOM_Object)& theTopLeftPoint,
1750                                                         const Handle(GEOM_Object)& theTopRigthPoint,
1751                                                         const Handle(GEOM_Object)& theBottomLeftPoint,
1752                                                         const Handle(GEOM_Object)& theBottomRigthPoint,
1753                                                         const GEOMAlgo_State       theState)
1754 {
1755   // Find indices
1756   Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
1757     getShapesOnQuadrangleIDs( theShape,
1758                               theShapeType,
1759                               theTopLeftPoint,
1760                               theTopRigthPoint,
1761                               theBottomLeftPoint,
1762                               theBottomRigthPoint,
1763                               theState);
1764   if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
1765     return NULL;
1766
1767   // Make a Python command
1768
1769   // The GetShapesOnCylinder() doesn't change object so no new function is required.
1770   Handle(GEOM_Object) lastObj = getCreatedLast(theShape,theTopLeftPoint);
1771   lastObj = getCreatedLast(lastObj,theTopRigthPoint);
1772   lastObj = getCreatedLast(lastObj,theBottomRigthPoint);
1773   lastObj = getCreatedLast(lastObj,theBottomLeftPoint);
1774   Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
1775
1776   const bool append = true;
1777   GEOM::TPythonDump(aFunction,append)
1778     << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
1779     << theShape << ", "
1780     << theShapeType << ", "
1781     << theTopLeftPoint << ", "
1782     << theTopRigthPoint << ", "
1783     << theBottomLeftPoint << ", "
1784     << theBottomRigthPoint << ", "
1785     << theState << ")";
1786
1787   SetErrorCode(OK);
1788   return aSeqOfIDs;
1789 }
1790
1791
1792 //=============================================================================
1793 /*!
1794  *  GetInPlace
1795  */
1796 //=============================================================================
1797 Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace
1798                                           (Handle(GEOM_Object) theShapeWhere,
1799                                            Handle(GEOM_Object) theShapeWhat)
1800 {
1801   SetErrorCode(KO);
1802
1803   if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
1804
1805   TopoDS_Shape aWhere = theShapeWhere->GetValue();
1806   TopoDS_Shape aWhat  = theShapeWhat->GetValue();
1807
1808   if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
1809
1810   //Fill array of indices
1811   Handle(TColStd_HArray1OfInteger) aModifiedArray;
1812
1813   Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
1814
1815   TopTools_IndexedMapOfShape aWhereIndices;
1816   TopExp::MapShapes(aWhere, aWhereIndices);
1817
1818   if (aWhereIndices.Contains(aWhat)) {
1819
1820     // entity was not changed by the operation
1821     Standard_Integer aWhatIndex = aWhereIndices.FindIndex(aWhat);
1822     aModifiedArray = new TColStd_HArray1OfInteger(1,1);
1823     aModifiedArray->SetValue(1, aWhatIndex);
1824
1825   } else {
1826
1827     TDF_Label aHistoryLabel = aWhereFunction->GetHistoryEntry(Standard_False);
1828     if (aHistoryLabel.IsNull()) {
1829       SetErrorCode("Modifications history does not exist for the shape under consideration.");
1830       return NULL;
1831     }
1832
1833     // search in history for all argument shapes
1834     Standard_Boolean isFound = Standard_False;
1835
1836     TDF_LabelSequence aLabelSeq;
1837     aWhereFunction->GetDependency(aLabelSeq);
1838     Standard_Integer nbArg = aLabelSeq.Length();
1839
1840     for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
1841
1842       TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
1843
1844       Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
1845       TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
1846
1847       TopTools_IndexedMapOfShape anArgumentIndices;
1848       TopExp::MapShapes(anArgumentShape, anArgumentIndices);
1849
1850       if (anArgumentIndices.Contains(aWhat)) {
1851         isFound = Standard_True;
1852         Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(aWhat);
1853
1854         // Find corresponding label in history
1855         TDF_Label anArgumentHistoryLabel =
1856           aWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
1857         if (anArgumentHistoryLabel.IsNull()) {
1858           // Lost History of operation argument. Possibly, all its entities was removed.
1859           SetErrorCode(OK);
1860           return NULL;
1861         }
1862
1863         TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
1864         if (aWhatHistoryLabel.IsNull()) {
1865           // Removed entity
1866           SetErrorCode(OK);
1867           return NULL;
1868         }
1869
1870         Handle(TDataStd_IntegerArray) anIntegerArray;
1871         if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
1872           SetErrorCode("Error: Empty modifications history for the sought shape.");
1873           return NULL;
1874         }
1875
1876         aModifiedArray = anIntegerArray->Array();
1877         if (aModifiedArray->Length() == 0) {
1878           SetErrorCode("Error: Empty modifications history for the sought shape.");
1879           return NULL;
1880         }
1881       }
1882     }
1883
1884     if (!isFound) {
1885       SetErrorCode("The sought shape does not belong to any operation argument.");
1886       return NULL;
1887     }
1888   }
1889
1890   //Add a new object
1891   Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
1892
1893   if (aModifiedArray->Length() > 1) {
1894     //Set a GROUP type
1895     aResult->SetType(GEOM_GROUP);
1896
1897     //Set a sub shape type
1898     TDF_Label aFreeLabel = aResult->GetFreeLabel();
1899     TopAbs_ShapeEnum aShapeType = aWhat.ShapeType();
1900     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
1901   }
1902
1903   //Make a Python command
1904   Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
1905
1906   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
1907     << theShapeWhere << ", " << theShapeWhat << ")";
1908
1909   SetErrorCode(OK);
1910   return aResult;
1911 }
1912
1913 //=======================================================================
1914 //function : SortShapes
1915 //purpose  :
1916 //=======================================================================
1917 void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)
1918 {
1919   Standard_Integer MaxShapes = SL.Extent();
1920   TopTools_Array1OfShape  aShapes (1,MaxShapes);
1921   TColStd_Array1OfInteger OrderInd(1,MaxShapes);
1922   TColStd_Array1OfReal    MidXYZ  (1,MaxShapes); //X,Y,Z;
1923   TColStd_Array1OfReal    Length  (1,MaxShapes); //X,Y,Z;
1924
1925   // Computing of CentreOfMass
1926   Standard_Integer Index;
1927   GProp_GProps GPr;
1928   gp_Pnt GPoint;
1929   TopTools_ListIteratorOfListOfShape it(SL);
1930   for (Index=1;  it.More();  Index++)
1931   {
1932     TopoDS_Shape S = it.Value();
1933     SL.Remove( it ); // == it.Next()
1934     aShapes(Index) = S;
1935     OrderInd.SetValue (Index, Index);
1936     if (S.ShapeType() == TopAbs_VERTEX)
1937     {
1938       GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
1939       Length.SetValue( Index, (Standard_Real) S.Orientation());
1940     }
1941     else
1942     {
1943       BRepGProp::LinearProperties (S, GPr);
1944       GPoint = GPr.CentreOfMass();
1945       Length.SetValue( Index, GPr.Mass() );
1946     }
1947     MidXYZ.SetValue(Index,
1948                     GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9);
1949   }
1950   // Sorting
1951   Standard_Integer aTemp;
1952   Standard_Boolean exchange, Sort = Standard_True;
1953   while (Sort)
1954   {
1955     Sort = Standard_False;
1956     for (Index=1; Index < MaxShapes; Index++)
1957     {
1958       if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1)))
1959         exchange = Standard_True;
1960       else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) &&
1961                Length(OrderInd(Index)) >  Length(OrderInd(Index+1)) )
1962         exchange = Standard_True;
1963       else
1964         exchange = Standard_False;
1965       if (exchange)
1966       {
1967         aTemp = OrderInd(Index);
1968         OrderInd(Index) = OrderInd(Index+1);
1969         OrderInd(Index+1) = aTemp;
1970         Sort = Standard_True;
1971       }
1972     }
1973   }
1974   for (Index=1; Index <= MaxShapes; Index++)
1975     SL.Append( aShapes( OrderInd(Index) ));
1976 }
1977
1978 //=======================================================================
1979 //function : CheckTriangulation
1980 //purpose  :
1981 //=======================================================================
1982 bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape)
1983 {
1984 //  MESSAGE("CheckTriangulation");
1985 //
1986 //  OSD_Timer timer1;
1987 //  timer1.Start();
1988
1989   TopExp_Explorer exp (aShape, TopAbs_FACE);
1990   if (!exp.More()) {
1991     SetErrorCode("Shape without faces given");
1992     return false;
1993   }
1994
1995   TopLoc_Location aTopLoc;
1996   Handle(Poly_Triangulation) aTRF;
1997   aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
1998   if (aTRF.IsNull()) {
1999     // calculate deflection
2000     Standard_Real aDeviationCoefficient = 0.001;
2001
2002     Bnd_Box B;
2003     BRepBndLib::Add(aShape, B);
2004     Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
2005     B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
2006
2007     Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
2008     Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
2009
2010 //    MESSAGE("Deflection = " << aDeflection);
2011
2012     Standard_Real aHLRAngle = 0.349066;
2013
2014     BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
2015   }
2016 //  timer1.Stop();
2017 //  timer1.Show();
2018
2019   return true;
2020 }