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