Salome HOME
Task 2.1. Creation of ellipses and arcs of ellipse.
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_EdgeBuilder.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        GeomAlgoAPI_EdgeBuilder.cpp
4 // Created:     23 Apr 2014
5 // Author:      Mikhail PONIKAROV
6
7 #include <GeomAlgoAPI_EdgeBuilder.h>
8
9 #include <Bnd_Box.hxx>
10 #include <BRep_Tool.hxx>
11 #include <BRepBndLib.hxx>
12 #include <BRepBuilderAPI_MakeEdge.hxx>
13 #include <gp_Ax2.hxx>
14 #include <gp_Circ.hxx>
15 #include <gp_Elips.hxx>
16 #include <gp_Pln.hxx>
17 #include <Geom_CylindricalSurface.hxx>
18 #include <Geom_Plane.hxx>
19 #include <Geom_RectangularTrimmedSurface.hxx>
20 #include <TopoDS.hxx>
21 #include <TopoDS_Edge.hxx>
22 #include <TopoDS_Face.hxx>
23
24 std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::line(
25     std::shared_ptr<GeomAPI_Pnt> theStart, std::shared_ptr<GeomAPI_Pnt> theEnd)
26 {
27   const gp_Pnt& aStart = theStart->impl<gp_Pnt>();
28   const gp_Pnt& anEnd = theEnd->impl<gp_Pnt>();
29
30   if (aStart.IsEqual(anEnd, Precision::Confusion()))
31     return std::shared_ptr<GeomAPI_Edge>();
32   if (Abs(aStart.SquareDistance(anEnd)) > 1.e+100)
33     return std::shared_ptr<GeomAPI_Edge>();
34   BRepBuilderAPI_MakeEdge anEdgeBuilder(aStart, anEnd);
35   std::shared_ptr<GeomAPI_Edge> aRes(new GeomAPI_Edge);
36   TopoDS_Edge anEdge = anEdgeBuilder.Edge();
37   aRes->setImpl(new TopoDS_Shape(anEdge));
38   return aRes;
39 }
40 std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::line(
41     double theDX, double theDY, double theDZ)
42 {
43
44   const gp_Pnt& aStart = gp_Pnt(0, 0, 0);
45   const gp_Pnt& anEnd = gp_Pnt(theDX, theDY, theDZ);
46
47   if (aStart.IsEqual(anEnd, Precision::Confusion()))
48     return std::shared_ptr<GeomAPI_Edge>();
49   if (Abs(aStart.SquareDistance(anEnd)) > 1.e+100)
50     return std::shared_ptr<GeomAPI_Edge>();
51   BRepBuilderAPI_MakeEdge anEdgeBuilder(aStart, anEnd);
52   std::shared_ptr<GeomAPI_Edge> aRes(new GeomAPI_Edge);
53   TopoDS_Edge anEdge = anEdgeBuilder.Edge();
54   aRes->setImpl(new TopoDS_Shape(anEdge));
55   return aRes;
56 }
57
58 std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::line(
59     const std::shared_ptr<GeomAPI_Lin> theLin)
60 {
61   if(!theLin.get()) {
62     return std::shared_ptr<GeomAPI_Edge>();
63   }
64
65   const gp_Lin& aLin = theLin->impl<gp_Lin>();
66   BRepBuilderAPI_MakeEdge anEdgeBuilder(aLin);
67   std::shared_ptr<GeomAPI_Edge> aRes(new GeomAPI_Edge());
68   TopoDS_Edge anEdge = anEdgeBuilder.Edge();
69   aRes->setImpl(new TopoDS_Shape(anEdge));
70   return aRes;
71 }
72
73 std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::cylinderAxis(
74     std::shared_ptr<GeomAPI_Shape> theCylindricalFace)
75 {
76   std::shared_ptr<GeomAPI_Edge> aResult;
77   const TopoDS_Shape& aShape = theCylindricalFace->impl<TopoDS_Shape>();
78   if (aShape.IsNull())
79     return aResult;
80   TopoDS_Face aFace = TopoDS::Face(aShape);
81   if (aFace.IsNull())
82     return aResult;
83   TopLoc_Location aLoc;
84   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc);
85   if (aSurf.IsNull())
86     return aResult;
87   Handle(Geom_RectangularTrimmedSurface) aTrimmed =
88     Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf);
89   if (!aTrimmed.IsNull())
90     aSurf = aTrimmed->BasisSurface();
91   Handle(Geom_CylindricalSurface) aCyl = Handle(Geom_CylindricalSurface)::DownCast(aSurf);
92   if (aCyl.IsNull())
93     return aResult;
94   gp_Ax1 anAxis = aCyl->Axis();
95   // compute the start and the end points of the resulting edge by the bounding box of the face
96   // (vertices projected to the axis) plus 10%
97   Bnd_Box aFaceBnd;
98   BRepBndLib::Add(aFace, aFaceBnd);
99   gp_Pnt aBoxMin(aFaceBnd.CornerMin()), aBoxMax(aFaceBnd.CornerMax());
100   bool isFirst = true;
101   double aParamMin = 0, aParamMax = 0;
102   for(int aX = 0; aX < 2; aX++) {
103     for(int aY = 0; aY < 2; aY++) {
104       for(int aZ = 0; aZ < 2; aZ++) {
105         gp_XYZ aBoxVertex(aX == 0 ? aBoxMin.X() : aBoxMax.X(),
106           aY == 0 ? aBoxMin.Y() : aBoxMax.Y(), aZ == 0 ? aBoxMin.Z() : aBoxMax.Z());
107         gp_XYZ aVec(aBoxVertex - anAxis.Location().XYZ());
108         double aProjParam = aVec.Dot(anAxis.Direction().XYZ());
109         if (isFirst) {
110           isFirst = false;
111           aParamMin = aProjParam;
112           aParamMax = aProjParam;
113         } else {
114           if (aParamMin > aProjParam)
115             aParamMin = aProjParam;
116           else if (aParamMax < aProjParam)
117             aParamMax = aProjParam;
118         }
119       }
120     }
121   }
122   // add 10%
123   double aDelta = aParamMax - aParamMin;
124   if (aDelta < 1.e-4) aDelta = 1.e-4;
125   aParamMin -= aDelta * 0.1;
126   aParamMax += aDelta * 0.1;
127
128   gp_Pnt aStart(aParamMin * anAxis.Direction().XYZ() + anAxis.Location().XYZ());
129   gp_Pnt anEnd(aParamMax * anAxis.Direction().XYZ() + anAxis.Location().XYZ());
130   /*
131   gp_Pnt aStart(anAxis.Location().Transformed(aLoc.Transformation()));
132   // edge length is 100, "-" because cylinder of extrusion has negative direction with the cylinder
133   gp_Pnt anEnd(anAxis.Location().XYZ() - anAxis.Direction().XYZ() * 100.);
134   anEnd.Transform(aLoc.Transformation());
135   */
136
137   BRepBuilderAPI_MakeEdge anEdgeBuilder(aStart, anEnd);
138   std::shared_ptr<GeomAPI_Edge> aRes(new GeomAPI_Edge);
139   TopoDS_Edge anEdge = anEdgeBuilder.Edge();
140   // an axis is an infinite object
141   anEdge.Infinite(Standard_True);
142   aRes->setImpl(new TopoDS_Shape(anEdge));
143   return aRes;
144 }
145
146 std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::lineCircle(
147     std::shared_ptr<GeomAPI_Pnt> theCenter, std::shared_ptr<GeomAPI_Dir> theNormal,
148     double theRadius)
149 {
150   const gp_Pnt& aCenter = theCenter->impl<gp_Pnt>();
151   const gp_Dir& aDir = theNormal->impl<gp_Dir>();
152
153   gp_Circ aCircle(gp_Ax2(aCenter, aDir), theRadius);
154
155   BRepBuilderAPI_MakeEdge anEdgeBuilder(aCircle);
156   std::shared_ptr<GeomAPI_Edge> aRes(new GeomAPI_Edge);
157   TopoDS_Edge anEdge = anEdgeBuilder.Edge();
158   aRes->setImpl(new TopoDS_Shape(anEdge));
159   return aRes;
160 }
161
162 std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::lineCircle(
163     std::shared_ptr<GeomAPI_Circ> theCircle)
164 {
165   if(!theCircle.get()) {
166     return std::shared_ptr<GeomAPI_Edge>();
167   }
168
169   const gp_Circ& aCirc = theCircle->impl<gp_Circ>();
170   BRepBuilderAPI_MakeEdge anEdgeBuilder(aCirc);
171   std::shared_ptr<GeomAPI_Edge> aRes(new GeomAPI_Edge());
172   TopoDS_Edge anEdge = anEdgeBuilder.Edge();
173   aRes->setImpl(new TopoDS_Shape(anEdge));
174   return aRes;
175 }
176
177 std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::lineCircleArc(
178     std::shared_ptr<GeomAPI_Pnt> theCenter, std::shared_ptr<GeomAPI_Pnt> theStartPoint,
179     std::shared_ptr<GeomAPI_Pnt> theEndPoint, std::shared_ptr<GeomAPI_Dir> theNormal)
180 {
181   std::shared_ptr<GeomAPI_Edge> aRes;
182
183   const gp_Pnt& aCenter = theCenter->impl<gp_Pnt>();
184   const gp_Dir& aDir = theNormal->impl<gp_Dir>();
185
186   /// OCCT creates an edge on a circle with empty radius, but visualization
187   /// is not able to process it
188   if (theCenter->isEqual(theStartPoint))
189     return aRes;
190
191   double aRadius = theCenter->distance(theStartPoint);
192   gp_Circ aCircle(gp_Ax2(aCenter, aDir), aRadius);
193
194   const gp_Pnt& aStart = theStartPoint->impl<gp_Pnt>();
195   const gp_Pnt& anEndInter = theEndPoint->impl<gp_Pnt>();
196
197   // project end point to a circle
198   gp_XYZ aEndDir = anEndInter.XYZ() - aCenter.XYZ();
199   gp_Pnt anEnd(aCenter.XYZ() + aEndDir.Normalized() * aRadius);
200
201   BRepBuilderAPI_MakeEdge anEdgeBuilder;
202   anEdgeBuilder = BRepBuilderAPI_MakeEdge(aCircle, aStart, anEnd);
203
204   anEdgeBuilder.Build();
205
206   if (anEdgeBuilder.IsDone()) {
207     aRes = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge);
208     aRes->setImpl(new TopoDS_Shape(anEdgeBuilder.Edge()));
209   }
210   return aRes;
211 }
212
213 std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::ellipse(
214     const std::shared_ptr<GeomAPI_Pnt>& theCenter,
215     const std::shared_ptr<GeomAPI_Dir>& theNormal,
216     const std::shared_ptr<GeomAPI_Dir>& theMajorAxis,
217     const double                        theMajorRadius,
218     const double                        theMinorRadius)
219 {
220   const gp_Pnt& aCenter = theCenter->impl<gp_Pnt>();
221   const gp_Dir& aNormal = theNormal->impl<gp_Dir>();
222   const gp_Dir& aMajorAxis = theMajorAxis->impl<gp_Dir>();
223
224   gp_Elips anEllipse(gp_Ax2(aCenter, aNormal, aMajorAxis), theMajorRadius, theMinorRadius);
225
226   BRepBuilderAPI_MakeEdge anEdgeBuilder(anEllipse);
227   std::shared_ptr<GeomAPI_Edge> aRes(new GeomAPI_Edge);
228   TopoDS_Edge anEdge = anEdgeBuilder.Edge();
229   aRes->setImpl(new TopoDS_Shape(anEdge));
230   return aRes;
231 }