1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <GCPnts_UniformDeflection.hxx>
16
17 #include <CPnts_UniformDeflection.hxx>
18 #include <GCPnts_DeflectionType.hxx>
19 #include <GCPnts_TCurveTypes.hxx>
20 #include <gp_Pnt.hxx>
21 #include <gp_Pnt2d.hxx>
22 #include <Standard_ConstructionError.hxx>
23 #include <Standard_DomainError.hxx>
24 #include <Standard_NotImplemented.hxx>
25 #include <Standard_OutOfRange.hxx>
26 #include <StdFail_NotDone.hxx>
27
28 // mask the return of a Adaptor2d_Curve2d as a gp_Pnt
Value(const Adaptor3d_Curve & theC,const Standard_Real theParameter)29 static gp_Pnt Value (const Adaptor3d_Curve& theC,
30 const Standard_Real theParameter)
31 {
32 return theC.Value (theParameter);
33 }
34
Value(const Adaptor2d_Curve2d & theC,const Standard_Real theParameter)35 static gp_Pnt Value (const Adaptor2d_Curve2d& theC,
36 const Standard_Real theParameter)
37 {
38 const gp_Pnt2d a2dPoint = theC.Value (theParameter);
39 return gp_Pnt (a2dPoint.X(), a2dPoint.Y(), 0.0);
40 }
41
42 //=======================================================================
43 //function : GCPnts_UniformDeflection
44 //purpose :
45 //=======================================================================
GCPnts_UniformDeflection()46 GCPnts_UniformDeflection::GCPnts_UniformDeflection()
47 : myDone (Standard_False),
48 myDeflection (0.0)
49 {
50 //
51 }
52
53 //=======================================================================
54 //function : GCPnts_UniformDeflection
55 //purpose :
56 //=======================================================================
GCPnts_UniformDeflection(const Adaptor3d_Curve & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Boolean theWithControl)57 GCPnts_UniformDeflection::GCPnts_UniformDeflection (const Adaptor3d_Curve& theC,
58 const Standard_Real theDeflection,
59 const Standard_Real theU1,
60 const Standard_Real theU2,
61 const Standard_Boolean theWithControl)
62 : myDone (Standard_False),
63 myDeflection (theDeflection)
64 {
65 Initialize (theC, theDeflection, theU1, theU2, theWithControl);
66 }
67
68 //=======================================================================
69 //function : GCPnts_UniformDeflection
70 //purpose :
71 //=======================================================================
GCPnts_UniformDeflection(const Adaptor3d_Curve & theC,const Standard_Real theDeflection,const Standard_Boolean theWithControl)72 GCPnts_UniformDeflection::GCPnts_UniformDeflection (const Adaptor3d_Curve& theC,
73 const Standard_Real theDeflection,
74 const Standard_Boolean theWithControl)
75 : myDone (Standard_False),
76 myDeflection (theDeflection)
77 {
78 Initialize (theC, theDeflection, theWithControl);
79 }
80
81 //=======================================================================
82 //function : GCPnts_UniformDeflection
83 //purpose :
84 //=======================================================================
GCPnts_UniformDeflection(const Adaptor2d_Curve2d & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Boolean theWithControl)85 GCPnts_UniformDeflection::GCPnts_UniformDeflection (const Adaptor2d_Curve2d& theC,
86 const Standard_Real theDeflection,
87 const Standard_Real theU1,
88 const Standard_Real theU2,
89 const Standard_Boolean theWithControl)
90 : myDone (Standard_False),
91 myDeflection (theDeflection)
92 {
93 Initialize (theC, theDeflection, theU1, theU2, theWithControl);
94 }
95
96 //=======================================================================
97 //function : GCPnts_UniformDeflection
98 //purpose :
99 //=======================================================================
GCPnts_UniformDeflection(const Adaptor2d_Curve2d & theC,const Standard_Real theDeflection,const Standard_Boolean theWithControl)100 GCPnts_UniformDeflection::GCPnts_UniformDeflection (const Adaptor2d_Curve2d& theC,
101 const Standard_Real theDeflection,
102 const Standard_Boolean theWithControl)
103 : myDone (Standard_False),
104 myDeflection (theDeflection)
105 {
106 Initialize (theC, theDeflection, theWithControl);
107 }
108
109 //=======================================================================
110 //function : Initialize
111 //purpose :
112 //=======================================================================
Initialize(const Adaptor3d_Curve & theC,const Standard_Real theDeflection,const Standard_Boolean theWithControl)113 void GCPnts_UniformDeflection::Initialize (const Adaptor3d_Curve& theC,
114 const Standard_Real theDeflection,
115 const Standard_Boolean theWithControl)
116 {
117 Initialize (theC, theDeflection, theC.FirstParameter(), theC.LastParameter(), theWithControl);
118 }
119
120 //=======================================================================
121 //function : Initialize
122 //purpose :
123 //=======================================================================
Initialize(const Adaptor2d_Curve2d & theC,const Standard_Real theDeflection,const Standard_Boolean theWithControl)124 void GCPnts_UniformDeflection::Initialize (const Adaptor2d_Curve2d& theC,
125 const Standard_Real theDeflection,
126 const Standard_Boolean theWithControl)
127 {
128 Initialize (theC, theDeflection, theC.FirstParameter(), theC.LastParameter(), theWithControl);
129 }
130
131 //=======================================================================
132 //function : Initialize
133 //purpose :
134 //=======================================================================
Initialize(const Adaptor3d_Curve & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Boolean theWithControl)135 void GCPnts_UniformDeflection::Initialize (const Adaptor3d_Curve& theC,
136 const Standard_Real theDeflection,
137 const Standard_Real theU1,
138 const Standard_Real theU2,
139 const Standard_Boolean theWithControl)
140 {
141 initialize (theC, theDeflection, theU1, theU2, theWithControl);
142 }
143
144 //=======================================================================
145 //function : Initialize
146 //purpose :
147 //=======================================================================
Initialize(const Adaptor2d_Curve2d & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Boolean theWithControl)148 void GCPnts_UniformDeflection::Initialize (const Adaptor2d_Curve2d& theC,
149 const Standard_Real theDeflection,
150 const Standard_Real theU1,
151 const Standard_Real theU2,
152 const Standard_Boolean theWithControl)
153 {
154 initialize (theC, theDeflection, theU1, theU2, theWithControl);
155 }
156
157 //=======================================================================
158 //function : Value
159 //purpose :
160 //=======================================================================
Value(const Standard_Integer theIndex) const161 gp_Pnt GCPnts_UniformDeflection::Value (const Standard_Integer theIndex) const
162 {
163 StdFail_NotDone_Raise_if(!myDone, "GCPnts_UniformAbscissa::Parameter()");
164 return myPoints.Value (theIndex);
165 }
166
167 //! Control of the last points.
168 template<class TheCurve>
Controle(const TheCurve & theC,TColStd_SequenceOfReal & theParameters,TColgp_SequenceOfPnt & thePoints,const Standard_Real theU2)169 static void Controle (const TheCurve& theC,
170 TColStd_SequenceOfReal& theParameters,
171 TColgp_SequenceOfPnt& thePoints,
172 const Standard_Real theU2)
173 {
174 const Standard_Integer aNbPnts = thePoints.Length();
175 if (aNbPnts > 2)
176 {
177 const Standard_Real aUa = theParameters (aNbPnts - 2);
178 const Standard_Real aUb = theParameters (aNbPnts - 1);
179 if (theU2 - aUb < 0.33 * (theU2 - aUa))
180 {
181 const Standard_Real aUc = (theU2 + aUa) * 0.5;
182 theParameters (aNbPnts - 1) = aUc;
183 thePoints (aNbPnts - 1) = Value (theC, aUc);
184 }
185 }
186 }
187
188 //=======================================================================
189 //function : PerformLinear
190 //purpose :
191 //=======================================================================
192 template<class TheCurve>
PerformLinear(const TheCurve & theC,TColStd_SequenceOfReal & theParameters,TColgp_SequenceOfPnt & thePoints,const Standard_Real theU1,const Standard_Real theU2)193 static Standard_Boolean PerformLinear (const TheCurve& theC,
194 TColStd_SequenceOfReal& theParameters,
195 TColgp_SequenceOfPnt& thePoints,
196 const Standard_Real theU1,
197 const Standard_Real theU2)
198 {
199 theParameters.Append (theU1);
200 gp_Pnt aPoint = Value (theC, theU1);
201 thePoints.Append (aPoint);
202
203 theParameters.Append (theU2);
204 aPoint = Value (theC, theU2);
205 thePoints.Append (aPoint);
206 return Standard_True;
207 }
208
209 //=======================================================================
210 //function : PerformCircular
211 //purpose :
212 //=======================================================================
213 template<class TheCurve>
PerformCircular(const TheCurve & theC,TColStd_SequenceOfReal & theParameters,TColgp_SequenceOfPnt & thePoints,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2)214 static Standard_Boolean PerformCircular (const TheCurve& theC,
215 TColStd_SequenceOfReal& theParameters,
216 TColgp_SequenceOfPnt& thePoints,
217 const Standard_Real theDeflection,
218 const Standard_Real theU1,
219 const Standard_Real theU2)
220 {
221 gp_Pnt aPoint;
222 Standard_Real anAngle = Max (1.0 - (theDeflection / theC.Circle().Radius()), 0.0);
223 anAngle = 2.0e0 * ACos (anAngle);
224 Standard_Integer aNbPoints = (Standard_Integer )((theU2 - theU1) / anAngle);
225 aNbPoints += 2;
226 anAngle = (theU2 - theU1) / (Standard_Real) (aNbPoints - 1);
227 Standard_Real aU = theU1;
228 for (Standard_Integer i = 1; i <= aNbPoints; ++i)
229 {
230 theParameters.Append (aU);
231 aPoint = Value (theC, aU);
232 thePoints.Append (aPoint);
233 aU += anAngle;
234 }
235 return Standard_True;
236 }
237
238 //=======================================================================
239 //function : GetDefType
240 //purpose :
241 //=======================================================================
242 template<class TheCurve>
GetDefType(const TheCurve & theC)243 static GCPnts_DeflectionType GetDefType (const TheCurve& theC)
244 {
245 if (theC.NbIntervals (GeomAbs_C2) > 1)
246 {
247 return GCPnts_DefComposite;
248 }
249
250 switch (theC.GetType())
251 {
252 case GeomAbs_Line: return GCPnts_Linear;
253 case GeomAbs_Circle: return GCPnts_Circular;
254 case GeomAbs_BSplineCurve:
255 {
256 Handle(typename GCPnts_TCurveTypes<TheCurve>::BSplineCurve) aBSpline = theC.BSpline();
257 return (aBSpline->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved;
258 }
259 case GeomAbs_BezierCurve:
260 {
261 Handle(typename GCPnts_TCurveTypes<TheCurve>::BezierCurve) aBezier = theC.Bezier();
262 return (aBezier->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved;
263 }
264 default:
265 {
266 return GCPnts_Curved;
267 }
268 }
269 }
270
271 //=======================================================================
272 //function : PerformCurve
273 //purpose :
274 //=======================================================================
275 template<class TheCurve>
PerformCurve(TColStd_SequenceOfReal & theParameters,TColgp_SequenceOfPnt & thePoints,const TheCurve & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Real theEPSILON,const Standard_Boolean theWithControl)276 static Standard_Boolean PerformCurve (TColStd_SequenceOfReal& theParameters,
277 TColgp_SequenceOfPnt& thePoints,
278 const TheCurve& theC,
279 const Standard_Real theDeflection,
280 const Standard_Real theU1,
281 const Standard_Real theU2,
282 const Standard_Real theEPSILON,
283 const Standard_Boolean theWithControl)
284 {
285 CPnts_UniformDeflection anIterator (theC, theDeflection, theU1, theU2, theEPSILON, theWithControl);
286 for (; anIterator.More(); anIterator.Next())
287 {
288 theParameters.Append (anIterator.Value());
289 thePoints.Append (anIterator.Point());
290 }
291 return anIterator.IsAllDone();
292 }
293
294
295 //=======================================================================
296 //function : PerformComposite
297 //purpose :
298 //=======================================================================
299 template<class TheCurve>
PerformComposite(TColStd_SequenceOfReal & theParameters,TColgp_SequenceOfPnt & thePoints,const TheCurve & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Real theEPSILON,const Standard_Boolean theWithControl)300 static Standard_Boolean PerformComposite (TColStd_SequenceOfReal& theParameters,
301 TColgp_SequenceOfPnt& thePoints,
302 const TheCurve& theC,
303 const Standard_Real theDeflection,
304 const Standard_Real theU1,
305 const Standard_Real theU2,
306 const Standard_Real theEPSILON,
307 const Standard_Boolean theWithControl)
308 {
309 const Standard_Integer aNbIntervals = theC.NbIntervals (GeomAbs_C2);
310 Standard_Integer aPIndex = 0;
311
312 TColStd_Array1OfReal aTI (1, aNbIntervals + 1);
313 theC.Intervals (aTI, GeomAbs_C2);
314 BSplCLib::Hunt (aTI, theU1, aPIndex);
315
316 // iterate by continuous segments
317 Standard_Real aUa = theU1;
318 for (Standard_Integer anIndex = aPIndex;;)
319 {
320 Standard_Real aUb = anIndex + 1 <= aTI.Upper()
321 ? Min (theU2, aTI (anIndex + 1))
322 : theU2;
323 if (!PerformCurve (theParameters, thePoints, theC, theDeflection,
324 aUa, aUb, theEPSILON, theWithControl))
325 {
326 return Standard_False;
327 }
328 ++anIndex;
329 if (anIndex > aNbIntervals || theU2 < aTI (anIndex))
330 {
331 return Standard_True;
332 }
333
334 // remove last point to avoid duplication
335 theParameters.Remove (theParameters.Length());
336 thePoints.Remove (thePoints.Length());
337
338 aUa = aUb;
339 }
340 }
341
342 //=======================================================================
343 //function : initialize
344 //purpose :
345 //=======================================================================
346 template<class TheCurve>
initialize(const TheCurve & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Boolean theWithControl)347 void GCPnts_UniformDeflection::initialize (const TheCurve& theC,
348 const Standard_Real theDeflection,
349 const Standard_Real theU1,
350 const Standard_Real theU2,
351 const Standard_Boolean theWithControl)
352 {
353 const Standard_Real anEPSILON = theC.Resolution (Precision::Confusion());
354 myDeflection = theDeflection;
355 myDone = Standard_False;
356 myParams.Clear();
357 myPoints.Clear();
358
359 const Standard_Real aU1 = Min (theU1, theU2);
360 const Standard_Real aU2 = Max (theU1, theU2);
361 const GCPnts_DeflectionType aType = GetDefType (theC);
362 switch (aType)
363 {
364 case GCPnts_Linear:
365 myDone = PerformLinear (theC, myParams, myPoints, aU1, aU2);
366 break;
367 case GCPnts_Circular:
368 myDone = PerformCircular (theC, myParams, myPoints, theDeflection, aU1, aU2);
369 break;
370 case GCPnts_Curved:
371 myDone = PerformCurve (myParams, myPoints, theC, theDeflection,
372 aU1, aU2, anEPSILON, theWithControl);
373 break;
374 case GCPnts_DefComposite:
375 myDone = PerformComposite (myParams, myPoints, theC, theDeflection,
376 aU1, aU2, anEPSILON, theWithControl);
377 break;
378 }
379
380 // control of the last points
381 Controle (theC, myParams, myPoints, aU2);
382 }
383