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