Salome HOME
Several improvement of the filters functionality, correct work with shapes types...
[modules/shaper.git] / src / GeomAPI / GeomAPI_Shape.cpp
1 // Copyright (C) 2014-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "GeomAPI_Shape.h"
21
22 #include <GeomAPI_Pnt.h>
23 #include <GeomAPI_Vertex.h>
24 #include <GeomAPI_Edge.h>
25 #include <GeomAPI_Wire.h>
26 #include <GeomAPI_Face.h>
27 #include <GeomAPI_Shell.h>
28 #include <GeomAPI_Solid.h>
29
30 #include <BRep_Tool.hxx>
31 #include <BRepAlgoAPI_Section.hxx>
32 #include <BRepBndLib.hxx>
33 #include <BRepBuilderAPI_FindPlane.hxx>
34 #include <BRepExtrema_DistShapeShape.hxx>
35 #include <BRepTools.hxx>
36 #include <Bnd_Box.hxx>
37 #include <Geom_Circle.hxx>
38 #include <Geom_Conic.hxx>
39 #include <Geom_Curve.hxx>
40 #include <Geom_Ellipse.hxx>
41 #include <Geom_Hyperbola.hxx>
42 #include <Geom_Line.hxx>
43 #include <Geom_Parabola.hxx>
44 #include <Geom_Plane.hxx>
45 #include <Geom_RectangularTrimmedSurface.hxx>
46 #include <Geom_TrimmedCurve.hxx>
47 #include <TopExp_Explorer.hxx>
48 #include <TopoDS.hxx>
49 #include <TopoDS_Iterator.hxx>
50 #include <TopoDS_Shape.hxx>
51 #include <NCollection_List.hxx>
52
53 #include <BOPAlgo_CheckerSI.hxx>
54 #include <BOPDS_DS.hxx>
55
56 #include <sstream>
57 #include <algorithm> // for std::transform
58
59 #include <BRepTools.hxx>
60
61 #define MY_SHAPE implPtr<TopoDS_Shape>()
62
63 GeomAPI_Shape::GeomAPI_Shape()
64     : GeomAPI_Interface(new TopoDS_Shape())
65 {
66 }
67
68 std::shared_ptr<GeomAPI_Shape> GeomAPI_Shape::emptyCopied() const
69 {
70   GeomShapePtr aShape(new GeomAPI_Shape());
71   aShape->setImpl(new TopoDS_Shape(MY_SHAPE->EmptyCopied()));
72   return aShape;
73 }
74
75 bool GeomAPI_Shape::isNull() const
76 {
77   return MY_SHAPE->IsNull() == Standard_True;
78 }
79
80 bool GeomAPI_Shape::isEqual(const std::shared_ptr<GeomAPI_Shape> theShape) const
81 {
82   if (!theShape.get())
83     return false;
84   if (isNull())
85     return theShape->isNull();
86   if (theShape->isNull())
87     return false;
88
89   return MY_SHAPE->IsEqual(theShape->impl<TopoDS_Shape>()) == Standard_True;
90 }
91
92 bool GeomAPI_Shape::isSame(const std::shared_ptr<GeomAPI_Shape> theShape) const
93 {
94   if (!theShape.get())
95     return false;
96   if (isNull())
97     return theShape->isNull();
98   if (theShape->isNull())
99     return false;
100
101   return MY_SHAPE->IsSame(theShape->impl<TopoDS_Shape>()) == Standard_True;
102 }
103
104 bool GeomAPI_Shape::isVertex() const
105 {
106   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
107   return !aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX;
108 }
109
110 bool GeomAPI_Shape::isEdge() const
111 {
112   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
113   return !aShape.IsNull() && aShape.ShapeType() == TopAbs_EDGE;
114 }
115
116 bool GeomAPI_Shape::isWire() const
117 {
118   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
119   return !aShape.IsNull() && aShape.ShapeType() == TopAbs_WIRE;
120 }
121
122 bool GeomAPI_Shape::isFace() const
123 {
124   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
125   return !aShape.IsNull() && aShape.ShapeType() == TopAbs_FACE;
126 }
127
128 bool GeomAPI_Shape::isShell() const
129 {
130   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
131   return !aShape.IsNull() && aShape.ShapeType() == TopAbs_SHELL;
132 }
133
134 bool GeomAPI_Shape::isCompound() const
135 {
136   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
137   return !aShape.IsNull() && aShape.ShapeType() == TopAbs_COMPOUND;
138 }
139
140 bool GeomAPI_Shape::isCompoundOfSolids() const
141 {
142   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
143   if (aShape.IsNull() || aShape.ShapeType() != TopAbs_COMPOUND)
144     return false;
145   bool isAtLeastOne = false;
146   for(TopoDS_Iterator aSubs(aShape); aSubs.More(); aSubs.Next()) {
147     if (aSubs.Value().IsNull() || aSubs.Value().ShapeType() != TopAbs_SOLID)
148       return false;
149     isAtLeastOne = true;
150   }
151   return isAtLeastOne;
152 }
153
154 // LCOV_EXCL_START
155 GeomAPI_Shape::ShapeType GeomAPI_Shape::typeOfCompoundShapes() const
156 {
157   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
158   if (aShape.IsNull() || aShape.ShapeType() != TopAbs_COMPOUND)
159     return SHAPE;
160   int aType = -1;
161   for(TopoDS_Iterator aSubs(aShape); aSubs.More(); aSubs.Next()) {
162     if (!aSubs.Value().IsNull()) {
163       if (aType == -1)
164         aType = aSubs.Value().ShapeType();
165       else if (aSubs.Value().ShapeType() != aType)
166         return SHAPE;
167     }
168   }
169   return (GeomAPI_Shape::ShapeType) aType;
170 }
171 // LCOV_EXCL_STOP
172
173 // adds the nopt-compound elements recursively to the list
174 static void addSimpleToList(const TopoDS_Shape& theShape, NCollection_List<TopoDS_Shape>& theList)
175 {
176   if (!theShape.IsNull()) {
177     if (theShape.ShapeType() == TopAbs_COMPOUND) {
178       for(TopoDS_Iterator aSubs(theShape); aSubs.More(); aSubs.Next()) {
179         addSimpleToList(aSubs.Value(), theList);
180       }
181     } else {
182       theList.Append(theShape);
183     }
184   }
185 }
186
187 bool GeomAPI_Shape::isConnectedTopology() const
188 {
189   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
190   if (aShape.IsNull() || aShape.ShapeType() != TopAbs_COMPOUND)
191     return false;
192   // list of simple elements that are not detected in connection to others
193   NCollection_List<TopoDS_Shape> aNotConnected;
194   addSimpleToList(aShape, aNotConnected);
195   if (aNotConnected.IsEmpty()) // an empty compound
196     return false;
197
198   // collect here the group of connected subs, starting with one first element
199   NCollection_List<TopoDS_Shape> aNewConnected;
200   aNewConnected.Append(aNotConnected.First());
201   aNotConnected.RemoveFirst();
202   // iterate until some new element become connected
203   while(!aNewConnected.IsEmpty() && !aNotConnected.IsEmpty()) {
204     NCollection_List<TopoDS_Shape> aNew; // very new connected to new connected
205     NCollection_List<TopoDS_Shape>::Iterator aNotIter(aNotConnected);
206     while(aNotIter.More()) {
207       // optimization to avoid TopExp_Explorer double-cycle, collect all vertices in the list first
208       NCollection_List<TopoDS_Shape> aNotVertices;
209       for(TopExp_Explorer anExp1(aNotIter.Value(), TopAbs_VERTEX); anExp1.More(); anExp1.Next()) {
210         aNotVertices.Append(anExp1.Current());
211       }
212
213       bool aConnected =  false;
214       NCollection_List<TopoDS_Shape>::Iterator aNewIter(aNewConnected);
215       for(; !aConnected && aNewIter.More(); aNewIter.Next()) {
216         // checking topological connecion of aNotIter and aNewIter
217         // (if shapes are connected, vertices are connected for sure)
218         TopExp_Explorer anExp2(aNewIter.Value(), TopAbs_VERTEX);
219         for(; !aConnected && anExp2.More(); anExp2.Next()) {
220           NCollection_List<TopoDS_Shape>::Iterator aNotIter(aNotVertices);
221           for(; aNotIter.More(); aNotIter.Next()) {
222             if (aNotIter.Value().IsSame(anExp2.Current())) {
223               aConnected = true;
224               break;
225             }
226           }
227         }
228       }
229       if (aConnected) {
230         aNew.Append(aNotIter.Value());
231         aNotConnected.Remove(aNotIter);
232       } else {
233         aNotIter.Next();
234       }
235     }
236     // remove all new connected and put to this list very new connected
237     aNewConnected.Clear();
238     aNewConnected.Append(aNew);
239   }
240   return aNotConnected.IsEmpty() == Standard_True;
241 }
242
243 bool GeomAPI_Shape::isSolid() const
244 {
245   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
246   return !aShape.IsNull() && aShape.ShapeType() == TopAbs_SOLID;
247 }
248
249 bool GeomAPI_Shape::isCompSolid() const
250 {
251   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
252   return !aShape.IsNull() && aShape.ShapeType() == TopAbs_COMPSOLID;
253 }
254
255 bool GeomAPI_Shape::isPlanar() const
256 {
257   TopoDS_Shape aShape = impl<TopoDS_Shape>();
258
259   if(aShape.IsNull()) {
260     return false;
261   }
262
263   TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
264   if(aShapeType == TopAbs_COMPOUND) {
265     TopoDS_Iterator anIt(aShape);
266     int aShNum = 0;
267     for(; anIt.More(); anIt.Next()) {
268       ++aShNum;
269     }
270     if(aShNum == 1) {
271       anIt.Initialize(aShape);
272       aShape = anIt.Value();
273     }
274   }
275
276   aShapeType = aShape.ShapeType();
277   if(aShapeType == TopAbs_VERTEX) {
278     return true;
279   } else if(aShapeType == TopAbs_FACE) {
280     const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
281     Handle(Standard_Type) aType = aSurface->DynamicType();
282
283     if(aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
284       Handle(Geom_RectangularTrimmedSurface) aTrimSurface =
285         Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
286       aType = aTrimSurface->BasisSurface()->DynamicType();
287     }
288     return (aType == STANDARD_TYPE(Geom_Plane)) == Standard_True;
289   } else {
290     BRepBuilderAPI_FindPlane aFindPlane(aShape);
291     bool isFound = aFindPlane.Found() == Standard_True;
292
293     if(!isFound && aShapeType == TopAbs_EDGE) {
294       Standard_Real aFirst, aLast;
295       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFirst, aLast);
296       Handle(Standard_Type) aType = aCurve->DynamicType();
297
298       if(aType == STANDARD_TYPE(Geom_TrimmedCurve)) {
299         Handle(Geom_TrimmedCurve) aTrimCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve);
300         aType = aTrimCurve->BasisCurve()->DynamicType();
301       }
302
303       if(aType == STANDARD_TYPE(Geom_Line)
304           || aType == STANDARD_TYPE(Geom_Conic)
305           || aType == STANDARD_TYPE(Geom_Circle)
306           || aType == STANDARD_TYPE(Geom_Ellipse)
307           || aType == STANDARD_TYPE(Geom_Hyperbola)
308           || aType == STANDARD_TYPE(Geom_Parabola)) {
309         isFound = true;
310       }
311     }
312
313     return isFound;
314   }
315
316   return false;
317 }
318
319 std::shared_ptr<GeomAPI_Vertex> GeomAPI_Shape::vertex() const
320 {
321   GeomVertexPtr aVertex;
322   if (isVertex()) {
323     const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
324     aVertex = GeomVertexPtr(new GeomAPI_Vertex);
325     aVertex->setImpl(new TopoDS_Shape(aShape));
326   }
327   return aVertex;
328 }
329
330 std::shared_ptr<GeomAPI_Edge> GeomAPI_Shape::edge() const
331 {
332   GeomEdgePtr anEdge;
333   if (isEdge()) {
334     const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
335     anEdge = GeomEdgePtr(new GeomAPI_Edge);
336     anEdge->setImpl(new TopoDS_Shape(aShape));
337   }
338   return anEdge;
339 }
340
341 std::shared_ptr<GeomAPI_Wire> GeomAPI_Shape::wire() const
342 {
343   GeomWirePtr aWire;
344   if (isWire()) {
345     const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
346     aWire = GeomWirePtr(new GeomAPI_Wire);
347     aWire->setImpl(new TopoDS_Shape(aShape));
348   }
349   return aWire;
350 }
351
352 std::shared_ptr<GeomAPI_Face> GeomAPI_Shape::face() const
353 {
354   GeomFacePtr aFace;
355   if (isFace()) {
356     const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
357     aFace = GeomFacePtr(new GeomAPI_Face);
358     aFace->setImpl(new TopoDS_Shape(aShape));
359   }
360   return aFace;
361 }
362
363 std::shared_ptr<GeomAPI_Shell> GeomAPI_Shape::shell() const
364 {
365   GeomShellPtr aShell;
366   if (isShell()) {
367     const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
368     aShell = GeomShellPtr(new GeomAPI_Shell);
369     aShell->setImpl(new TopoDS_Shape(aShape));
370   }
371   return aShell;
372 }
373
374 std::shared_ptr<GeomAPI_Solid> GeomAPI_Shape::solid() const
375 {
376   GeomSolidPtr aSolid;
377   if (isSolid()) {
378     const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
379     aSolid = GeomSolidPtr(new GeomAPI_Solid);
380     aSolid->setImpl(new TopoDS_Shape(aShape));
381   }
382   return aSolid;
383 }
384
385 std::list<std::shared_ptr<GeomAPI_Shape> >
386 GeomAPI_Shape::subShapes(ShapeType theSubShapeType) const
387 {
388   ListOfShape aSubs;
389   const TopoDS_Shape& aShape = impl<TopoDS_Shape>();
390   if (aShape.IsNull())
391     return aSubs;
392
393   // process multi-level compounds
394   if (shapeType() == COMPOUND && theSubShapeType == COMPOUND) {
395     for (TopoDS_Iterator anIt(aShape); anIt.More(); anIt.Next()) {
396       const TopoDS_Shape& aCurrent = anIt.Value();
397       if (aCurrent.ShapeType() == TopAbs_COMPOUND) {
398         GeomShapePtr aSub(new GeomAPI_Shape);
399         aSub->setImpl(new TopoDS_Shape(aCurrent));
400         aSubs.push_back(aSub);
401       }
402     }
403     // add self
404     GeomShapePtr aSub(new GeomAPI_Shape);
405     aSub->setImpl(new TopoDS_Shape(aShape));
406     aSubs.push_back(aSub);
407   }
408   else {
409     for (TopExp_Explorer anExp(aShape, (TopAbs_ShapeEnum)theSubShapeType);
410          anExp.More(); anExp.Next()) {
411       GeomShapePtr aSub(new GeomAPI_Shape);
412       aSub->setImpl(new TopoDS_Shape(anExp.Current()));
413       aSubs.push_back(aSub);
414     }
415   }
416   return aSubs;
417 }
418
419 GeomAPI_Shape::ShapeType GeomAPI_Shape::shapeType() const
420 {
421   const TopoDS_Shape& aShape = impl<TopoDS_Shape>();
422   if (aShape.IsNull())
423     return GeomAPI_Shape::SHAPE;
424
425   ShapeType aST = GeomAPI_Shape::SHAPE;
426
427   switch(aShape.ShapeType()) {
428   case TopAbs_COMPOUND:
429     aST = GeomAPI_Shape::COMPOUND;
430     break;
431   case TopAbs_COMPSOLID:
432     aST = GeomAPI_Shape::COMPSOLID;
433     break;
434   case TopAbs_SOLID:
435     aST = GeomAPI_Shape::SOLID;
436     break;
437   case TopAbs_SHELL:
438     aST = GeomAPI_Shape::SHELL;
439     break;
440   case TopAbs_FACE:
441     aST = GeomAPI_Shape::FACE;
442     break;
443   case TopAbs_WIRE:
444     aST = GeomAPI_Shape::WIRE;
445     break;
446   case TopAbs_EDGE:
447     aST = GeomAPI_Shape::EDGE;
448     break;
449   case TopAbs_VERTEX:
450     aST = GeomAPI_Shape::VERTEX;
451     break;
452   case TopAbs_SHAPE:
453     aST = GeomAPI_Shape::SHAPE;
454     break;
455   }
456
457   return aST;
458 }
459
460 GeomAPI_Shape::ShapeType GeomAPI_Shape::shapeTypeByStr(std::string theType)
461 {
462   std::transform(theType.begin(), theType.end(), theType.begin(), ::toupper);
463   if (theType == "COMPOUND" || theType == "COMPOUNDS")
464     return COMPOUND;
465   if (theType == "COMPSOLID" || theType == "COMPSOLIDS")
466     return COMPSOLID;
467   if (theType == "SOLID" || theType == "SOLIDS")
468     return SOLID;
469   if (theType == "SHELL" || theType == "SHELLS")
470     return SHELL;
471   if (theType == "FACE" || theType == "FACES")
472     return FACE;
473   if (theType == "WIRE" || theType == "WIRES")
474     return WIRE;
475   if (theType == "EDGE" || theType == "EDGES")
476     return EDGE;
477   if (theType == "VERTEX" || theType == "VERTICES")
478     return VERTEX;
479   return SHAPE; // default
480 }
481
482 std::string GeomAPI_Shape::shapeTypeStr() const
483 {
484   ShapeType aShapeType = shapeType();
485   std::string aShapeTypeStr;
486
487   switch(aShapeType) {
488     case COMPOUND: {
489       aShapeTypeStr = "COMPOUND";
490       break;
491     }
492     case COMPSOLID: {
493       aShapeTypeStr = "COMPSOLID";
494       break;
495     }
496     case SOLID: {
497       aShapeTypeStr = "SOLID";
498       break;
499     }
500     case SHELL: {
501       aShapeTypeStr = "SHELL";
502       break;
503     }
504     case FACE: {
505       aShapeTypeStr = "FACE";
506       break;
507     }
508     case WIRE: {
509       aShapeTypeStr = "WIRE";
510       break;
511     }
512     case EDGE: {
513       aShapeTypeStr = "EDGE";
514       break;
515     }
516     case VERTEX: {
517       aShapeTypeStr = "VERTEX";
518       break;
519     }
520     case SHAPE: {
521       aShapeTypeStr = "SHAPE";
522       break;
523     }
524   }
525
526   return aShapeTypeStr;
527 }
528
529 GeomAPI_Shape::Orientation GeomAPI_Shape::orientation() const
530 {
531   TopAbs_Orientation anOrientation = MY_SHAPE->Orientation();
532
533   switch(anOrientation) {
534     case TopAbs_FORWARD:  return FORWARD;
535     case TopAbs_REVERSED: return REVERSED;
536     case TopAbs_INTERNAL: return INTERNAL;
537     case TopAbs_EXTERNAL: return EXTERNAL;
538     default:              return FORWARD;
539   }
540 }
541
542 void GeomAPI_Shape::setOrientation(const GeomAPI_Shape::Orientation theOrientation)
543 {
544   TopAbs_Orientation anOrientation = MY_SHAPE->Orientation();
545
546   switch(theOrientation) {
547     case FORWARD:  MY_SHAPE->Orientation(TopAbs_FORWARD);  break;
548     case REVERSED: MY_SHAPE->Orientation(TopAbs_REVERSED); break;
549     case INTERNAL: MY_SHAPE->Orientation(TopAbs_INTERNAL); break;
550     case EXTERNAL: MY_SHAPE->Orientation(TopAbs_EXTERNAL); break;
551   }
552 }
553
554 void GeomAPI_Shape::reverse()
555 {
556   MY_SHAPE->Reverse();
557 }
558
559 bool GeomAPI_Shape::isSubShape(const std::shared_ptr<GeomAPI_Shape> theShape,
560                                const bool theCheckOrientation) const
561 {
562   if(!theShape.get()) {
563     return false;
564   }
565
566   const TopoDS_Shape& aShapeToSearch = theShape->impl<TopoDS_Shape>();
567   if(aShapeToSearch.IsNull()) {
568     return false;
569   }
570
571   for(TopExp_Explorer anExp(*MY_SHAPE, aShapeToSearch.ShapeType()); anExp.More(); anExp.Next()) {
572     if(theCheckOrientation ?
573        aShapeToSearch.IsEqual(anExp.Current()) : aShapeToSearch.IsSame(anExp.Current())) {
574       return true;
575     }
576   }
577
578   return false;
579 }
580
581 bool GeomAPI_Shape::computeSize(double& theXmin, double& theYmin, double& theZmin,
582                                 double& theXmax, double& theYmax, double& theZmax) const
583 {
584   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
585   if (aShape.IsNull())
586     return false;
587   Bnd_Box aBndBox;
588   BRepBndLib::Add(aShape, aBndBox, false);
589   if (aBndBox.IsVoid())
590     return false;
591   aBndBox.Get(theXmin, theYmin, theZmin, theXmax, theYmax, theZmax);
592   return true;
593 }
594
595 GeomPointPtr GeomAPI_Shape::middlePoint() const
596 {
597   GeomPointPtr aMiddlePoint;
598
599   switch (shapeType()) {
600   case VERTEX:
601     aMiddlePoint = vertex()->point();
602     break;
603   case EDGE:
604     aMiddlePoint = edge()->middlePoint();
605     break;
606   case WIRE:
607     aMiddlePoint = wire()->middlePoint();
608     break;
609   case FACE:
610     aMiddlePoint = face()->middlePoint();
611     break;
612   case SHELL:
613     aMiddlePoint = shell()->middlePoint();
614     break;
615   case SOLID:
616     aMiddlePoint = solid()->middlePoint();
617     break;
618   default: {
619       // get middle point as center of the bounding box
620       double aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ;
621       computeSize(aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ);
622       aMiddlePoint = GeomPointPtr(new GeomAPI_Pnt(
623           (aMinX + aMaxX) * 0.5, (aMinY + aMaxY) * 0.5, (aMinZ + aMaxZ) * 0.5));
624     }
625   }
626
627   return aMiddlePoint;
628 }
629
630 // LCOV_EXCL_START
631 std::string GeomAPI_Shape::getShapeStream() const
632 {
633   std::ostringstream aStream;
634   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
635   BRepTools::Write(aShape, aStream);
636   return aStream.str();
637 }
638 // LCOV_EXCL_STOP
639
640 GeomShapePtr GeomAPI_Shape::intersect(const GeomShapePtr theShape) const
641 {
642   const TopoDS_Shape& aShape1 = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
643   const TopoDS_Shape& aShape2 = theShape->impl<TopoDS_Shape>();
644
645   BRepAlgoAPI_Section aCommon(aShape1, aShape2);
646   if (!aCommon.IsDone())
647     return GeomShapePtr();
648
649   TopoDS_Shape aResult = aCommon.Shape();
650   if (aResult.ShapeType() == TopAbs_COMPOUND) {
651     NCollection_List<TopoDS_Shape> aSubs;
652     addSimpleToList(aResult, aSubs);
653     if(aSubs.Size() == 1) {
654       aResult = aSubs.First();
655     } else if(aSubs.Size() == 0) {
656       return GeomShapePtr();
657     }
658   }
659
660   GeomShapePtr aResShape(new GeomAPI_Shape);
661   aResShape->setImpl(new TopoDS_Shape(aResult));
662   return aResShape;
663 }
664
665 bool GeomAPI_Shape::isIntersect(const GeomShapePtr theShape) const
666 {
667   if(!theShape.get()) {
668     return false;
669   }
670
671   const TopoDS_Shape& aShape1 = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
672   const TopoDS_Shape& aShape2 = theShape->impl<TopoDS_Shape>();
673
674   BRepExtrema_DistShapeShape aDist(aShape1, aShape2);
675   aDist.Perform();
676   if(aDist.IsDone() && aDist.Value() < Precision::Confusion()) {
677     return true;
678   }
679
680   return false;
681 }
682
683 void GeomAPI_Shape::translate(const std::shared_ptr<GeomAPI_Dir> theDir, const double theOffset)
684 {
685   gp_Dir aDir = theDir->impl<gp_Dir>();
686   gp_Vec aTrsfVec(aDir.XYZ() * theOffset);
687   gp_Trsf aTranslation;
688   aTranslation.SetTranslation(aTrsfVec);
689   TopoDS_Shape aResult = MY_SHAPE->Moved(aTranslation);
690   setImpl(new TopoDS_Shape(aResult));
691 }
692
693 bool GeomAPI_Shape::isSelfIntersected(const int theLevelOfCheck) const
694 {
695   BOPAlgo_CheckerSI aCSI;  // checker of self-interferences
696   aCSI.SetLevelOfCheck(theLevelOfCheck);
697   TopTools_ListOfShape aList;
698   const TopoDS_Shape& aThisShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
699   aList.Append(aThisShape);
700   aCSI.SetArguments(aList);
701   aCSI.Perform();
702   if (aCSI.HasErrors() || aCSI.DS().Interferences().Extent() > 0) {
703     return true;
704   }
705
706   return false;
707 }
708
709 bool GeomAPI_Shape::Comparator::operator()(const std::shared_ptr<GeomAPI_Shape>& theShape1,
710                                            const std::shared_ptr<GeomAPI_Shape>& theShape2) const
711 {
712   return theShape1->impl<TopoDS_Shape>().TShape() < theShape2->impl<TopoDS_Shape>().TShape();
713 }