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