Salome HOME
3d072c2225a7b16975eebaf2c4c0d560d4149d9b
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_ShapeTools.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        GeomAlgoAPI_ShapeTools.h
4 // Created:     3 August 2015
5 // Author:      Dmitry Bobylev
6
7 #include "GeomAlgoAPI_ShapeTools.h"
8
9 #include "GeomAlgoAPI_SketchBuilder.h"
10
11 #include <GeomAPI_Dir.h>
12 #include <GeomAPI_Face.h>
13 #include <GeomAPI_PlanarEdges.h>
14 #include <GeomAPI_Pln.h>
15 #include <GeomAPI_Pnt.h>
16
17 #include <Bnd_Box.hxx>
18 #include <BOPTools.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRepAdaptor_Curve.hxx>
21 #include <BRepAlgo_FaceRestrictor.hxx>
22 #include <BRepBndLib.hxx>
23 #include <BRepBuilderAPI_FindPlane.hxx>
24 #include <BRepBuilderAPI_MakeEdge.hxx>
25 #include <BRepBuilderAPI_MakeFace.hxx>
26 #include <BRepCheck_Analyzer.hxx>
27 #include <BRepExtrema_DistShapeShape.hxx>
28 #include <BRepExtrema_ExtCF.hxx>
29 #include <BRepGProp.hxx>
30 #include <BRepTools.hxx>
31 #include <BRepTopAdaptor_FClass2d.hxx>
32 #include <Geom_Curve.hxx>
33 #include <Geom2d_Curve.hxx>
34 #include <BRepLib_CheckCurveOnSurface.hxx>
35 #include <BRep_Tool.hxx>
36 #include <Geom_Plane.hxx>
37 #include <GeomLib_IsPlanarSurface.hxx>
38 #include <GeomLib_Tool.hxx>
39 #include <GeomProjLib.hxx>
40 #include <gp_Pln.hxx>
41 #include <GProp_GProps.hxx>
42 #include <IntAna_IntConicQuad.hxx>
43 #include <IntAna_Quadric.hxx>
44 #include <NCollection_Vector.hxx>
45 #include <ShapeAnalysis.hxx>
46 #include <ShapeAnalysis_Surface.hxx>
47 #include <TopoDS_Builder.hxx>
48 #include <TopoDS_Edge.hxx>
49 #include <TopoDS_Face.hxx>
50 #include <TopoDS_Shape.hxx>
51 #include <TopoDS_Shell.hxx>
52 #include <TopoDS_Vertex.hxx>
53 #include <TopoDS.hxx>
54 #include <TopExp_Explorer.hxx>
55
56 //==================================================================================================
57 double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr<GeomAPI_Shape> theShape)
58 {
59   GProp_GProps aGProps;
60   if(!theShape.get()) {
61     return 0.0;
62   }
63   const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
64   if(aShape.IsNull()) {
65     return 0.0;
66   }
67   const Standard_Real anEps = 1.e-6;
68   BRepGProp::VolumeProperties(aShape, aGProps, anEps);
69   return aGProps.Mass();
70 }
71
72 //==================================================================================================
73 std::shared_ptr<GeomAPI_Pnt> GeomAlgoAPI_ShapeTools::centreOfMass(const std::shared_ptr<GeomAPI_Shape> theShape)
74 {
75   GProp_GProps aGProps;
76   if(!theShape) {
77     return std::shared_ptr<GeomAPI_Pnt>();
78   }
79   const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
80   if(aShape.IsNull()) {
81     return std::shared_ptr<GeomAPI_Pnt>();
82   }
83   gp_Pnt aCentre;
84   if(aShape.ShapeType() == TopAbs_VERTEX) {
85     aCentre = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
86   } else if(aShape.ShapeType() == TopAbs_EDGE || aShape.ShapeType() == TopAbs_WIRE) {
87     BRepGProp::LinearProperties(aShape, aGProps);
88     aCentre = aGProps.CentreOfMass();
89   } else {
90     BRepGProp::SurfaceProperties(aShape, aGProps);
91     aCentre = aGProps.CentreOfMass();
92   }
93   return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(), aCentre.Z()));
94 }
95
96 //==================================================================================================
97 std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr<GeomAPI_Shape> theCompound,
98                                                                      const GeomAPI_Shape::ShapeType theType,
99                                                                      ListOfShape& theCombinedShapes,
100                                                                      ListOfShape& theFreeShapes)
101 {
102   GeomShapePtr aResult = theCompound;
103
104   if(!theCompound.get()) {
105     return aResult;
106   }
107
108   if(theType != GeomAPI_Shape::SHELL && theType != GeomAPI_Shape::COMPSOLID) {
109     return aResult;
110   }
111
112   TopAbs_ShapeEnum aTS = TopAbs_EDGE;
113   TopAbs_ShapeEnum aTA = TopAbs_FACE;
114   if(theType == GeomAPI_Shape::COMPSOLID) {
115     aTS = TopAbs_FACE;
116     aTA = TopAbs_SOLID;
117   }
118
119   theCombinedShapes.clear();
120   theFreeShapes.clear();
121
122   // Get free shapes.
123   const TopoDS_Shape& aShapesComp = theCompound->impl<TopoDS_Shape>();
124   for(TopoDS_Iterator anIter(aShapesComp); anIter.More(); anIter.Next() ) {
125     const TopoDS_Shape& aShape = anIter.Value();
126     if(aShape.ShapeType() > aTA) {
127       std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
128       aGeomShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aShape));
129       theFreeShapes.push_back(aGeomShape);
130     }
131   }
132
133   // Map subshapes and shapes.
134   BOPCol_IndexedDataMapOfShapeListOfShape aMapSA;
135   BOPTools::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapSA);
136   if(aMapSA.IsEmpty()) {
137     return aResult;
138   }
139
140   // Get all shapes with common subshapes and free shapes.
141   NCollection_Map<TopoDS_Shape> aFreeShapes;
142   NCollection_Vector<NCollection_Map<TopoDS_Shape>> aShapesWithCommonSubshapes;
143   for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapSA); anIter.More(); anIter.Next()) {
144     const TopoDS_Shape& aShape = anIter.Key();
145     BOPCol_ListOfShape& aListOfShape = anIter.ChangeValue();
146     if(aListOfShape.IsEmpty()) {
147       continue;
148     }
149     else if(aListOfShape.Size() == 1) {
150       const TopoDS_Shape& aF = aListOfShape.First();
151       aFreeShapes.Add(aF);
152       aListOfShape.Clear();
153     } else {
154       NCollection_List<TopoDS_Shape> aTempList;
155       NCollection_Map<TopoDS_Shape> aTempMap;
156       const TopoDS_Shape& aF = aListOfShape.First();
157       const TopoDS_Shape& aL = aListOfShape.Last();
158       aTempList.Append(aF);
159       aTempList.Append(aL);
160       aTempMap.Add(aF);
161       aTempMap.Add(aL);
162       aFreeShapes.Remove(aF);
163       aFreeShapes.Remove(aL);
164       aListOfShape.Clear();
165       for(NCollection_List<TopoDS_Shape>::Iterator aTempIter(aTempList); aTempIter.More(); aTempIter.Next()) {
166         const TopoDS_Shape& aTempShape = aTempIter.Value();
167         for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapSA); anIter.More(); anIter.Next()) {
168           BOPCol_ListOfShape& aTempListOfShape = anIter.ChangeValue();
169           if(aTempListOfShape.IsEmpty()) {
170             continue;
171           } else if(aTempListOfShape.Size() == 1 && aTempListOfShape.First() == aTempShape) {
172             aTempListOfShape.Clear();
173           } else if(aTempListOfShape.Size() > 1) {
174             if(aTempListOfShape.First() == aTempShape) {
175               const TopoDS_Shape& aTL = aTempListOfShape.Last();
176               if(aTempMap.Add(aTL)) {
177                 aTempList.Append(aTL);
178                 aFreeShapes.Remove(aTL);
179               }
180               aTempListOfShape.Clear();
181             } else if(aTempListOfShape.Last() == aTempShape) {
182               const TopoDS_Shape& aTF = aTempListOfShape.First();
183               if(aTempMap.Add(aTF)) {
184                 aTempList.Append(aTF);
185                 aFreeShapes.Remove(aTF);
186               }
187               aTempListOfShape.Clear();
188             }
189           }
190         }
191       }
192       aShapesWithCommonSubshapes.Append(aTempMap);
193     }
194   }
195
196   // Combine shapes with common subshapes.
197   for(NCollection_Vector<NCollection_Map<TopoDS_Shape>>::Iterator anIter(aShapesWithCommonSubshapes); anIter.More(); anIter.Next()) {
198     TopoDS_Shell aShell;
199     TopoDS_CompSolid aCSolid;
200     TopoDS_Builder aBuilder;
201     theType == GeomAPI_Shape::COMPSOLID ? aBuilder.MakeCompSolid(aCSolid) : aBuilder.MakeShell(aShell);
202     NCollection_Map<TopoDS_Shape>& aShapesMap = anIter.ChangeValue();
203     for(TopExp_Explorer anExp(aShapesComp, aTA); anExp.More(); anExp.Next()) {
204       const TopoDS_Shape& aShape = anExp.Current();
205       if(aShapesMap.Contains(aShape)) {
206         theType == GeomAPI_Shape::COMPSOLID ? aBuilder.Add(aCSolid, aShape) : aBuilder.Add(aShell, aShape);
207         aShapesMap.Remove(aShape);
208       }
209     }
210     std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
211     TopoDS_Shape* aSh = theType == GeomAPI_Shape::COMPSOLID ? new TopoDS_Shape(aCSolid) : new TopoDS_Shape(aShell);
212     aGeomShape->setImpl<TopoDS_Shape>(aSh);
213     theCombinedShapes.push_back(aGeomShape);
214   }
215
216   // Adding free shapes.
217   for(TopExp_Explorer anExp(aShapesComp, aTA); anExp.More(); anExp.Next()) {
218     const TopoDS_Shape& aShape = anExp.Current();
219     if(aFreeShapes.Contains(aShape)) {
220       std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
221       aGeomShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aShape));
222       theFreeShapes.push_back(aGeomShape);
223     }
224   }
225
226   if(theCombinedShapes.size() == 1 && theFreeShapes.size() == 0) {
227     aResult = theCombinedShapes.front();
228   } else if (theCombinedShapes.size() > 1 || (theCombinedShapes.size() >= 1 && theFreeShapes.size() >= 1)) {
229     TopoDS_Compound aResultComp;
230     TopoDS_Builder aBuilder;
231     aBuilder.MakeCompound(aResultComp);
232     for(ListOfShape::const_iterator anIter = theCombinedShapes.cbegin(); anIter != theCombinedShapes.cend(); anIter++) {
233       aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
234     }
235     for(ListOfShape::const_iterator anIter = theFreeShapes.cbegin(); anIter != theFreeShapes.cend(); anIter++) {
236       aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
237     }
238     aResult->setImpl(new TopoDS_Shape(aResultComp));
239   }
240
241   return aResult;
242 }
243
244 //==================================================================================================
245 static void addSimpleShapeToList(const TopoDS_Shape& theShape, NCollection_List<TopoDS_Shape>& theList)
246 {
247   if(theShape.IsNull()) {
248     return;
249   }
250
251   if(theShape.ShapeType() == TopAbs_COMPOUND) {
252     for(TopoDS_Iterator anIt(theShape); anIt.More(); anIt.Next()) {
253       addSimpleShapeToList(anIt.Value(), theList);
254     }
255   } else {
256     theList.Append(theShape);
257   }
258 }
259
260 //==================================================================================================
261 static TopoDS_Compound makeCompound(const NCollection_List<TopoDS_Shape> theShapes)
262 {
263   TopoDS_Compound aCompound;
264
265   BRep_Builder aBuilder;
266   aBuilder.MakeCompound(aCompound);
267
268   for(NCollection_List<TopoDS_Shape>::Iterator anIt(theShapes); anIt.More(); anIt.Next()) {
269     aBuilder.Add(aCompound, anIt.Value());
270   }
271
272   return aCompound;
273 }
274
275 //==================================================================================================
276 std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::groupSharedTopology(const std::shared_ptr<GeomAPI_Shape> theCompound)
277 {
278   GeomShapePtr aResult = theCompound;
279
280   if(!theCompound.get()) {
281     return aResult;
282   }
283
284   TopoDS_Shape anInShape = aResult->impl<TopoDS_Shape>();
285   NCollection_List<TopoDS_Shape> anUngroupedShapes;
286   addSimpleShapeToList(anInShape, anUngroupedShapes);
287
288   NCollection_Vector<NCollection_List<TopoDS_Shape>> aGroups;
289   while(!anUngroupedShapes.IsEmpty()) {
290     NCollection_List<TopoDS_Shape> aGroupedShapes;
291     aGroupedShapes.Append(anUngroupedShapes.First());
292     anUngroupedShapes.RemoveFirst();
293     for(NCollection_List<TopoDS_Shape>::Iterator aGroupIt(aGroupedShapes); aGroupIt.More(); aGroupIt.Next()) {
294       const TopoDS_Shape& aGroupShape = aGroupIt.Value();
295       for(NCollection_List<TopoDS_Shape>::Iterator anUngroupedIt(anUngroupedShapes); anUngroupedIt.More(); anUngroupedIt.Next()) {
296         const TopoDS_Shape& anUngroupedShape = anUngroupedIt.Value();
297         bool isFound = false;
298         for(TopExp_Explorer aGroupShapeExp(aGroupShape, TopAbs_VERTEX); aGroupShapeExp.More(); aGroupShapeExp.Next()) {
299           const TopoDS_Shape& aVertex1 = aGroupShapeExp.Current();
300           for(TopExp_Explorer anUngroupedShapeExp(anUngroupedShape, TopAbs_VERTEX); anUngroupedShapeExp.More(); anUngroupedShapeExp.Next()) {
301             const TopoDS_Shape& aVertex2 = anUngroupedShapeExp.Current();
302             if(aVertex1.IsSame(aVertex2)) {
303               aGroupedShapes.Append(anUngroupedShape);
304               anUngroupedShapes.Remove(anUngroupedIt);
305               isFound = true;
306               break;
307             }
308           }
309           if(isFound) {
310             break;
311           }
312         }
313         if(!anUngroupedIt.More()) {
314           break;
315         }
316       }
317     }
318     aGroups.Append(aGroupedShapes);
319   }
320
321   TopoDS_Compound aCompound;
322   BRep_Builder aBuilder;
323   aBuilder.MakeCompound(aCompound);
324   ListOfShape aCompSolids, aFreeSolids;
325   for(NCollection_Vector<NCollection_List<TopoDS_Shape>>::Iterator anIt(aGroups); anIt.More(); anIt.Next()) {
326     NCollection_List<TopoDS_Shape> aGroup = anIt.Value();
327     GeomShapePtr aGeomShape(new GeomAPI_Shape());
328     if(aGroup.Size() == 1) {
329       aGeomShape->setImpl(new TopoDS_Shape(aGroup.First()));
330     } else {
331       aGeomShape->setImpl(new TopoDS_Shape(makeCompound(anIt.Value())));
332       aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
333                                                          GeomAPI_Shape::COMPSOLID,
334                                                          aCompSolids,
335                                                          aFreeSolids);
336     }
337     aBuilder.Add(aCompound, aGeomShape->impl<TopoDS_Shape>());
338   }
339
340   if(!aCompound.IsNull()) {
341     aResult->setImpl(new TopoDS_Shape(aCompound));
342   }
343
344   return aResult;
345 }
346
347 //==================================================================================================
348 std::list<std::shared_ptr<GeomAPI_Pnt> > GeomAlgoAPI_ShapeTools::getBoundingBox(const ListOfShape& theShapes, const double theEnlarge)
349 {
350   // Bounding box of all objects.
351   Bnd_Box aBndBox;
352
353   // Getting box.
354   for (ListOfShape::const_iterator anObjectsIt = theShapes.begin(); anObjectsIt != theShapes.end(); anObjectsIt++) {
355     const TopoDS_Shape& aShape = (*anObjectsIt)->impl<TopoDS_Shape>();
356     BRepBndLib::Add(aShape, aBndBox);
357   }
358
359   if(theEnlarge != 0.0) {
360     // We enlarge bounding box just to be sure that plane will be large enough to cut all objects.
361     aBndBox.Enlarge(theEnlarge);
362   }
363
364   Standard_Real aXArr[2] = {aBndBox.CornerMin().X(), aBndBox.CornerMax().X()};
365   Standard_Real aYArr[2] = {aBndBox.CornerMin().Y(), aBndBox.CornerMax().Y()};
366   Standard_Real aZArr[2] = {aBndBox.CornerMin().Z(), aBndBox.CornerMax().Z()};
367   std::list<std::shared_ptr<GeomAPI_Pnt> > aResultPoints;
368   int aNum = 0;
369   for(int i = 0; i < 2; i++) {
370     for(int j = 0; j < 2; j++) {
371       for(int k = 0; k < 2; k++) {
372         std::shared_ptr<GeomAPI_Pnt> aPnt(new GeomAPI_Pnt(aXArr[i], aYArr[j], aZArr[k]));
373         aResultPoints.push_back(aPnt);
374       }
375     }
376   }
377
378   return aResultPoints;
379 }
380
381 //==================================================================================================
382 std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const std::shared_ptr<GeomAPI_Shape> theFace)
383 {
384   if (!theFace.get())
385     return std::shared_ptr<GeomAPI_Shape>();
386
387   TopoDS_Face aPlaneFace = TopoDS::Face(theFace->impl<TopoDS_Shape>());
388   if (aPlaneFace.IsNull())
389     return std::shared_ptr<GeomAPI_Shape>();
390
391   Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(aPlaneFace));
392   if (aPlane.IsNull())
393     return std::shared_ptr<GeomAPI_Shape>();
394
395   // make an infinity face on the plane
396   TopoDS_Shape anInfiniteFace = BRepBuilderAPI_MakeFace(aPlane->Pln()).Shape();
397
398   std::shared_ptr<GeomAPI_Shape> aResult(new GeomAPI_Shape);
399   aResult->setImpl(new TopoDS_Shape(anInfiniteFace));
400   return aResult;
401 }
402
403 //==================================================================================================
404 std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::fitPlaneToBox(const std::shared_ptr<GeomAPI_Shape> thePlane,
405                                                                      const std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints)
406 {
407   std::shared_ptr<GeomAPI_Shape> aResultShape;
408
409   if(!thePlane.get()) {
410     return aResultShape;
411   }
412
413   const TopoDS_Shape& aShape = thePlane->impl<TopoDS_Shape>();
414   if(aShape.ShapeType() != TopAbs_FACE) {
415     return aResultShape;
416   }
417
418   TopoDS_Face aFace = TopoDS::Face(aShape);
419   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
420   if(aSurf.IsNull()) {
421     return aResultShape;
422   }
423
424   GeomLib_IsPlanarSurface isPlanar(aSurf);
425   if(!isPlanar.IsPlanar()) {
426     return aResultShape;
427   }
428
429   if(thePoints.size() != 8) {
430     return aResultShape;
431   }
432
433   const gp_Pln& aFacePln = isPlanar.Plan();
434   Handle(Geom_Plane) aFacePlane = new Geom_Plane(aFacePln);
435   IntAna_Quadric aQuadric(aFacePln);
436   Standard_Real UMin, UMax, VMin, VMax;
437   UMin = UMax = VMin = VMax = 0;
438   for (std::list<std::shared_ptr<GeomAPI_Pnt> >::const_iterator aPointsIt = thePoints.begin(); aPointsIt != thePoints.end(); aPointsIt++) {
439     const gp_Pnt& aPnt = (*aPointsIt)->impl<gp_Pnt>();
440     gp_Lin aLin(aPnt, aFacePln.Axis().Direction());
441     IntAna_IntConicQuad anIntAna(aLin, aQuadric);
442     const gp_Pnt& aPntOnFace = anIntAna.Point(1);
443     Standard_Real aPntU(0), aPntV(0);
444     GeomLib_Tool::Parameters(aFacePlane, aPntOnFace, Precision::Confusion(), aPntU, aPntV);
445     if(aPntU < UMin) UMin = aPntU;
446     if(aPntU > UMax) UMax = aPntU;
447     if(aPntV < VMin) VMin = aPntV;
448     if(aPntV > VMax) VMax = aPntV;
449   }
450   aResultShape.reset(new GeomAPI_Shape);
451   aResultShape->setImpl(new TopoDS_Shape(BRepLib_MakeFace(aFacePln, UMin, UMax, VMin, VMax).Face()));
452
453   return aResultShape;
454 }
455
456 //==================================================================================================
457 void GeomAlgoAPI_ShapeTools::findBounds(const std::shared_ptr<GeomAPI_Shape> theShape,
458                                         std::shared_ptr<GeomAPI_Vertex>& theV1,
459                                         std::shared_ptr<GeomAPI_Vertex>& theV2)
460 {
461   if(!theShape.get()) {
462     std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex);
463     aVertex->setImpl(new TopoDS_Vertex());
464     theV1 = aVertex;
465     theV2 = aVertex;
466     return;
467   }
468
469   const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
470   TopoDS_Vertex aV1, aV2;
471   ShapeAnalysis::FindBounds(aShape, aV1, aV2);
472
473   std::shared_ptr<GeomAPI_Vertex> aGeomV1(new GeomAPI_Vertex()), aGeomV2(new GeomAPI_Vertex());
474   aGeomV1->setImpl(new TopoDS_Vertex(aV1));
475   aGeomV2->setImpl(new TopoDS_Vertex(aV2));
476   theV1 = aGeomV1;
477   theV2 = aGeomV2;
478 }
479
480 //==================================================================================================
481 void GeomAlgoAPI_ShapeTools::makeFacesWithHoles(const std::shared_ptr<GeomAPI_Pnt> theOrigin,
482                                                 const std::shared_ptr<GeomAPI_Dir> theDirection,
483                                                 const ListOfShape& theWires,
484                                                 ListOfShape& theFaces)
485 {
486   BRepBuilderAPI_MakeFace aMKFace(gp_Pln(theOrigin->impl<gp_Pnt>(),
487                                           theDirection->impl<gp_Dir>()));
488   TopoDS_Face aFace = aMKFace.Face();
489
490   BRepAlgo_FaceRestrictor aFRestrictor;
491   aFRestrictor.Init(aFace, Standard_False, Standard_True);
492   for(ListOfShape::const_iterator anIt = theWires.cbegin();
493       anIt != theWires.cend();
494       ++anIt) {
495     TopoDS_Wire aWire = TopoDS::Wire((*anIt)->impl<TopoDS_Shape>());
496     aFRestrictor.Add(aWire);
497   }
498
499   aFRestrictor.Perform();
500
501   if(!aFRestrictor.IsDone()) {
502     return;
503   }
504
505   for(; aFRestrictor.More(); aFRestrictor.Next()) {
506     GeomShapePtr aShape(new GeomAPI_Shape());
507     aShape->setImpl(new TopoDS_Shape(aFRestrictor.Current()));
508     theFaces.push_back(aShape);
509   }
510 }
511
512 //==================================================================================================
513 std::shared_ptr<GeomAPI_Pln> GeomAlgoAPI_ShapeTools::findPlane(const ListOfShape& theShapes)
514 {
515   TopoDS_Compound aCompound;
516   BRep_Builder aBuilder;
517   aBuilder.MakeCompound(aCompound);
518
519   for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
520     aBuilder.Add(aCompound, (*anIt)->impl<TopoDS_Shape>());
521   }
522   BRepBuilderAPI_FindPlane aFindPlane(aCompound);
523
524   if(aFindPlane.Found() != Standard_True) {
525     return std::shared_ptr<GeomAPI_Pln>();
526   }
527
528   Handle(Geom_Plane) aPlane = aFindPlane.Plane();
529   gp_Pnt aLoc = aPlane->Location();
530   gp_Dir aDir = aPlane->Axis().Direction();
531
532   std::shared_ptr<GeomAPI_Pnt> aGeomPnt(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z()));
533   std::shared_ptr<GeomAPI_Dir> aGeomDir(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z()));
534
535   std::shared_ptr<GeomAPI_Pln> aPln(new GeomAPI_Pln(aGeomPnt, aGeomDir));
536
537   return aPln;
538 }
539
540 //==================================================================================================
541 bool GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(const std::shared_ptr<GeomAPI_Shape> theSubShape,
542                                                    const std::shared_ptr<GeomAPI_Shape> theBaseShape)
543 {
544   if(!theSubShape.get() || !theBaseShape.get()) {
545     return false;
546   }
547
548   const TopoDS_Shape& aSubShape = theSubShape->impl<TopoDS_Shape>();
549   const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
550
551   if(aSubShape.ShapeType() == TopAbs_VERTEX) {
552     // If sub-shape is a vertex check distance to shape. If it is <= Precision::Confusion() then OK.
553     BRepExtrema_DistShapeShape aDist(aBaseShape, aSubShape);
554     aDist.Perform();
555     if(!aDist.IsDone() || aDist.Value() > Precision::Confusion()) {
556       return false;
557     }
558   } else if (aSubShape.ShapeType() == TopAbs_EDGE) {
559     if(aBaseShape.ShapeType() == TopAbs_FACE) {
560       // Check that edge is on face surface.
561       TopoDS_Face aFace = TopoDS::Face(aBaseShape);
562       TopoDS_Edge anEdge = TopoDS::Edge(aSubShape);
563       BRepLib_CheckCurveOnSurface aCheck(anEdge, aFace);
564       aCheck.Perform();
565       if(!aCheck.IsDone() || aCheck.MaxDistance() > Precision::Confusion()) {
566         return false;
567       }
568
569       // Check intersections.
570       TopoDS_Vertex aV1, aV2;
571       ShapeAnalysis::FindBounds(anEdge, aV1, aV2);
572       gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
573       gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
574       for(TopExp_Explorer anExp(aBaseShape, TopAbs_EDGE); anExp.More(); anExp.Next()) {
575         const TopoDS_Shape& anEdgeOnFace = anExp.Current();
576         BRepExtrema_DistShapeShape aDist(anEdgeOnFace, anEdge);
577         aDist.Perform();
578         if(aDist.IsDone() && aDist.Value() <= Precision::Confusion()) {
579           // Edge intersect face bound. Check that it is not on edge begin or end.
580           for(Standard_Integer anIndex = 1; anIndex <= aDist.NbSolution(); ++anIndex) {
581             gp_Pnt aPntOnSubShape = aDist.PointOnShape2(anIndex);
582             if(aPntOnSubShape.Distance(aPnt1) > Precision::Confusion()
583                 && aPntOnSubShape.Distance(aPnt2) > Precision::Confusion()) {
584               return false;
585             }
586           }
587         }
588       }
589
590       // No intersections found. Edge is inside or outside face. Check it.
591       BRepAdaptor_Curve aCurveAdaptor(anEdge);
592       gp_Pnt aPointToCheck = aCurveAdaptor.Value((aCurveAdaptor.FirstParameter() + aCurveAdaptor.LastParameter()) / 2.0);
593       Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);
594       ShapeAnalysis_Surface aSAS(aSurface);
595       gp_Pnt2d aPointOnFace = aSAS.ValueOfUV(aPointToCheck, Precision::Confusion());
596       BRepTopAdaptor_FClass2d aFClass2d(aFace, Precision::Confusion());
597       if(aFClass2d.Perform(aPointOnFace) == TopAbs_OUT) {
598         return false;
599       }
600
601     } else {
602       return false;
603     }
604   } else {
605     return false;
606   }
607
608   return true;
609 }
610
611 //==================================================================================================
612 bool GeomAlgoAPI_ShapeTools::isShapeValid(const std::shared_ptr<GeomAPI_Shape> theShape)
613 {
614   if(!theShape.get()) {
615     return false;
616   }
617
618   BRepCheck_Analyzer aChecker(theShape->impl<TopoDS_Shape>());
619   return (aChecker.IsValid() == Standard_True);
620 }
621
622 //==================================================================================================
623 std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::getFaceOuterWire(const std::shared_ptr<GeomAPI_Shape> theFace)
624 {
625   GeomShapePtr anOuterWire;
626
627   if(!theFace.get() || !theFace->isFace()) {
628     return anOuterWire;
629   }
630
631   TopoDS_Face aFace = TopoDS::Face(theFace->impl<TopoDS_Shape>());
632   TopoDS_Wire aWire = BRepTools::OuterWire(aFace);
633
634   anOuterWire.reset(new GeomAPI_Shape());
635   anOuterWire->setImpl(new TopoDS_Shape(aWire));
636
637   return anOuterWire;
638 }
639
640 //==================================================================================================
641 bool GeomAlgoAPI_ShapeTools::isParallel(const std::shared_ptr<GeomAPI_Edge> theEdge,
642                                         const std::shared_ptr<GeomAPI_Face> theFace)
643 {
644   if(!theEdge.get() || !theFace.get()) {
645     return false;
646   }
647
648   TopoDS_Edge anEdge = TopoDS::Edge(theEdge->impl<TopoDS_Shape>());
649   TopoDS_Face aFace  = TopoDS::Face(theFace->impl<TopoDS_Shape>());
650
651   BRepExtrema_ExtCF anExt(anEdge, aFace);
652   return anExt.IsParallel() == Standard_True;
653 }