1 // Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : Sketcher_Utils.cxx
24 // Author : Sergey KHROMOV
28 #include "Sketcher_Utils.hxx"
30 #include <BRepBuilderAPI_MakeEdge.hxx>
31 #include <BRepBuilderAPI_MakeVertex.hxx>
32 #include <BRepBuilderAPI_MakeWire.hxx>
34 #include <GeomAPI_Interpolate.hxx>
35 #include <TColgp_Array1OfVec.hxx>
36 #include <TColgp_HArray1OfPnt.hxx>
37 #include <TColStd_HArray1OfBoolean.hxx>
38 #include <TopoDS_Wire.hxx>
40 const double POINT_CONFUSION_TOLERANCE = 0.0001;
43 //=======================================================================
44 // function : MakePolyline
46 //=======================================================================
47 TopoDS_Shape Sketcher_Utils::MakePolyline
48 (const std::list <double> &theCoords2D,
49 const Standard_Boolean IsClosed,
50 const gp_Ax3 &thePlane)
52 std::list <gp_Pnt> aPoints;
55 To3D(theCoords2D, thePlane, aPoints);
57 Standard_Integer aNbPnts = aPoints.size();
61 aPoints.front().IsEqual(aPoints.back(), POINT_CONFUSION_TOLERANCE)) {
62 // The polyline should be closed, first and last points are confused.
63 // Remove the last point.
70 // The result is vertex.
71 aResult = BRepBuilderAPI_MakeVertex(aPoints.front()).Vertex();
72 } else if (aNbPnts > 1) {
73 // There are several points. Make a polyline.
74 std::list <gp_Pnt>::const_iterator anIter = aPoints.begin();
75 TopoDS_Vertex aVtxFirst =
76 BRepBuilderAPI_MakeVertex(*anIter).Vertex();
77 TopoDS_Vertex aVtx[2];
79 BRepBuilderAPI_MakeWire aMkWire;
83 for (++anIter; anIter != aPoints.end(); ++anIter) {
84 aVtx[1] = BRepBuilderAPI_MakeVertex(*anIter).Vertex();
85 aSegment = BRepBuilderAPI_MakeEdge(aVtx[0], aVtx[1]).Edge();
86 aMkWire.Add(aSegment);
91 // Create a closing segment.
92 aSegment = BRepBuilderAPI_MakeEdge(aVtx[0], aVtxFirst).Edge();
93 aMkWire.Add(aSegment);
96 aResult = aMkWire.Wire();
102 //=======================================================================
103 // function : constructBSpline
104 // purpose : See function 'constructBSpline' in file 'CurveCreator_Utils.cxx'.
105 //=======================================================================
106 static bool constructBSpline(
107 const Handle(TColgp_HArray1OfPnt)& thePoints,
108 const Standard_Boolean theIsClosed,
109 Handle(Geom_BSplineCurve)& theBSpline)
111 const int aPointCount = thePoints->Length();
112 if (aPointCount <= 1)
117 // Calculate the tangents.
118 TColgp_Array1OfVec aTangents(1, aPointCount);
119 Handle(TColStd_HArray1OfBoolean) aTangentFlags =
120 new TColStd_HArray1OfBoolean(1, aPointCount);
121 GeomAPI_Interpolate aInterpolator(thePoints, theIsClosed, 0);
122 if (aPointCount == 2)
124 aTangentFlags->SetValue(1, Standard_False);
125 aTangentFlags->SetValue(2, Standard_False);
129 for (Standard_Integer aPN = 1; aPN <= aPointCount; ++aPN)
132 if (aPN != 1 || theIsClosed)
134 const Standard_Integer aPN1 = (aPN != 1) ? (aPN - 1) : aPointCount;
135 aTangent = gp_Vec(thePoints->Value(aPN1),
136 thePoints->Value(aPN)).Normalized();
138 if (aPN < aPointCount || theIsClosed)
140 const Standard_Integer aPN2 = (aPN != aPointCount) ? (aPN + 1) : 1;
141 const gp_Vec aTangent2 = aTangent +
142 gp_Vec(thePoints->Value(aPN), thePoints->Value(aPN2)).Normalized();
143 if (aTangent2.SquareMagnitude() >= Precision::SquareConfusion())
145 aTangent = aTangent2.Normalized();
149 aTangent = -aTangent;
152 aTangents.SetValue(aPN, aTangent);
153 aTangentFlags->SetValue(aPN, Standard_True);
158 aInterpolator.Load(aTangents, aTangentFlags, Standard_False);
159 aInterpolator.Perform();
160 const bool aResult = (aInterpolator.IsDone() == Standard_True);
163 theBSpline = aInterpolator.Curve();
168 //=======================================================================
169 // function : MakeInterpolation
171 //=======================================================================
172 TopoDS_Shape Sketcher_Utils::MakeInterpolation(
173 const std::list<double>& theCoords2D,
174 const Standard_Boolean theIsClosed,
175 const gp_Ax3& thePlane)
177 if (theCoords2D.size() == 0)
179 return TopoDS_Shape();
182 // Get the different points.
183 std::list<gp_Pnt> aTmpPoints;
184 To3D(theCoords2D, thePlane, aTmpPoints);
185 gp_Pnt aFirstPoint = aTmpPoints.front();
186 gp_Pnt aPoint = aFirstPoint;
187 std::list<gp_Pnt>::iterator aPIt = aTmpPoints.begin();
188 for (++aPIt; aPIt != aTmpPoints.end();)
190 const gp_Pnt aPoint2 = *aPIt;
191 if (!aPoint.IsEqual(aPoint2, POINT_CONFUSION_TOLERANCE))
198 aTmpPoints.erase(aPIt);
203 while (--aPIt != aTmpPoints.begin() &&
204 aFirstPoint.IsEqual(*aPIt, POINT_CONFUSION_TOLERANCE))
206 aTmpPoints.erase(aPIt);
210 // Process the single point case.
211 const int aPointCount = aTmpPoints.size();
212 if (aPointCount == 1)
214 return BRepBuilderAPI_MakeVertex(aTmpPoints.front());
217 // Process the other cases.
218 Handle(TColgp_HArray1OfPnt) aPoints =
219 new TColgp_HArray1OfPnt(1, aPointCount);
220 aPIt = aTmpPoints.begin();
221 for (Standard_Integer aPN = 1; aPIt != aTmpPoints.end(); ++aPIt, ++aPN)
223 aPoints->SetValue(aPN, *aPIt);
225 Handle(Geom_BSplineCurve) aBSpline;
226 if (constructBSpline(aPoints, theIsClosed, aBSpline))
228 return BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(aBSpline));
230 return TopoDS_Shape();
233 //=======================================================================
236 //=======================================================================
237 void Sketcher_Utils::To3D(const std::list <double> &theCoords2D,
238 const gp_Ax3 &thePlane,
239 std::list <gp_Pnt> &thePoints)
243 if (theCoords2D.empty() || theCoords2D.size() % 2 == 1) {
244 // Odd number of coordinates or empty list. Invalid case.
248 std::list <double>::const_iterator anIter = theCoords2D.begin();
249 Standard_Real aX = *anIter;
250 Standard_Real aY = *(++anIter);
251 gp_Pnt aPLast = ElSLib::PlaneValue (aX, aY, thePlane);
254 thePoints.push_back(aPLast);
256 for (++anIter; anIter != theCoords2D.end(); ++anIter) {
259 aPnt = ElSLib::PlaneValue (aX, aY, thePlane);
261 if (!aPLast.IsEqual(aPnt, POINT_CONFUSION_TOLERANCE)) {
262 thePoints.push_back(aPnt);