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