1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <StdFail_NotDone.hxx>
16 #include <Standard_DomainError.hxx>
17 #include <Standard_OutOfRange.hxx>
18 #include <Standard_ConstructionError.hxx>
19 #include <Standard_NotImplemented.hxx>
20 #include <GCPnts_DeflectionType.hxx>
21 #include <TColStd_Array1OfReal.hxx>
22 #include <TColStd_SequenceOfReal.hxx>
23 #include <BSplCLib.hxx>
24 #include <gp_Circ.hxx>
25 #include <gp_Circ2d.hxx>
26 #include <Precision.hxx>
29 static void QuasiFleche(const TheCurve&,
37 const Standard_Integer,
39 TColStd_SequenceOfReal&,
40 TColgp_SequenceOfPnt&,
43 static void QuasiFleche(const TheCurve&,
49 const Standard_Integer,
50 TColStd_SequenceOfReal&,
51 TColgp_SequenceOfPnt&,
55 //=======================================================================
56 //function : PerformLinear
58 //=======================================================================
59 static Standard_Boolean PerformLinear (const TheCurve& C,
60 TColStd_SequenceOfReal& Parameters,
61 TColgp_SequenceOfPnt& Points,
62 const Standard_Real U1,
63 const Standard_Real U2)
66 Parameters.Append (U1);
67 aPoint = Value (C, U1);
68 Points.Append (aPoint);
70 Parameters.Append (U2);
71 aPoint = Value (C, U2);
72 Points.Append (aPoint);
77 //=======================================================================
78 //function : PerformCircular
80 //=======================================================================
81 static Standard_Boolean PerformCircular (const TheCurve& C,
82 TColStd_SequenceOfReal& Parameters,
83 TColgp_SequenceOfPnt& Points,
84 const Standard_Real Deflection,
85 const Standard_Real U1,
86 const Standard_Real U2)
90 Standard_Real Angle = Max (1.0e0 - (Deflection / C.Circle().Radius()), 0.0e0);
91 Angle = 2.0e0 * ACos (Angle);
92 Standard_Integer NbPoints = (Standard_Integer )((U2 - U1) / Angle);
94 Angle = (U2 - U1) / (Standard_Real) (NbPoints - 1);
96 for (Standard_Integer i = 1; i <= NbPoints; ++i)
98 Parameters.Append (U);
100 Points.Append (aPoint);
103 return Standard_True;
107 //=======================================================================
108 //function : GetDefType
110 //=======================================================================
111 static GCPnts_DeflectionType GetDefType (const TheCurve& C)
113 if (C.NbIntervals(GeomAbs_C1) > 1)
114 return GCPnts_DefComposite;
115 // pour forcer les decoupages aux cassures. G1 devrait marcher,
116 // mais donne des exceptions...
120 case GeomAbs_Line: return GCPnts_Linear;
121 case GeomAbs_Circle: return GCPnts_Circular;
122 case GeomAbs_BSplineCurve:
124 Handle_TheBSplineCurve BS = C.BSpline();
125 return (BS->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved;
127 case GeomAbs_BezierCurve:
129 Handle_TheBezierCurve BZ = C.Bezier();
130 return (BZ->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved;
132 default: return GCPnts_Curved;
137 //=======================================================================
138 //function : PerformCurve
140 //=======================================================================
141 static Standard_Boolean PerformCurve (TColStd_SequenceOfReal& Parameters,
142 TColgp_SequenceOfPnt& Points,
144 const Standard_Real Deflection,
145 const Standard_Real U1,
146 const Standard_Real U2,
147 const Standard_Real EPSILON,
148 const GeomAbs_Shape Continuity)
150 Standard_Integer Nbmin = 2;
151 Standard_Integer aNbCallQF = 0;
154 if (Continuity <= GeomAbs_G1)
157 Pdeb = Value (C, U1);
158 Parameters.Append (U1);
159 Points.Append (Pdeb);
161 gp_Pnt Pfin (Value (C, U2));
162 QuasiFleche (C, Deflection * Deflection,
166 Parameters, Points, aNbCallQF);
172 D1 (C, U1, Pdeb, Ddeb);
173 Parameters.Append (U1);
174 Points.Append (Pdeb);
176 Standard_Real aDecreasedU2 = U2 - Epsilon(U2) * 10.;
177 D1 (C, aDecreasedU2, Pfin, Dfin);
178 QuasiFleche (C, Deflection * Deflection,
185 Parameters, Points, aNbCallQF);
187 // cout << "Nb de pts: " << Points.Length()<< endl;
188 return Standard_True;
192 //=======================================================================
193 //function : PerformComposite
195 //=======================================================================
196 static Standard_Boolean PerformComposite (TColStd_SequenceOfReal& Parameters,
197 TColgp_SequenceOfPnt& Points,
199 const Standard_Real Deflection,
200 const Standard_Real U1,
201 const Standard_Real U2,
202 const Standard_Real EPSILON,
203 const GeomAbs_Shape Continuity)
206 // coherence avec Intervals
208 Standard_Integer NbIntervals = C.NbIntervals (GeomAbs_C2);
209 Standard_Integer PIndex;
210 TColStd_Array1OfReal TI (1, NbIntervals + 1);
211 C.Intervals (TI, GeomAbs_C2);
212 BSplCLib::Hunt (TI, U1, PIndex);
214 // iterate by continuous segments
215 Standard_Real Ua = U1;
216 for (Standard_Integer Index = PIndex;;)
218 Standard_Real Ub = Min (U2, TI (Index + 1));
219 if (!PerformCurve (Parameters, Points, C, Deflection,
220 Ua, Ub, EPSILON, Continuity))
221 return Standard_False;
224 if (Index > NbIntervals || U2 < TI (Index))
225 return Standard_True;
227 // remove last point to avoid duplication
228 Parameters.Remove (Parameters.Length());
229 Points.Remove (Points.Length());
236 //=======================================================================
237 //function : GCPnts_QuasiUniformDeflection
239 //=======================================================================
240 GCPnts_QuasiUniformDeflection::GCPnts_QuasiUniformDeflection
242 const Standard_Real Deflection,
243 const Standard_Real U1,
244 const Standard_Real U2,
245 const GeomAbs_Shape Continuity)
247 Initialize (C, Deflection, U1, U2, Continuity);
251 //=======================================================================
252 //function : GCPnts_QuasiUniformDeflection
254 //=======================================================================
255 GCPnts_QuasiUniformDeflection::GCPnts_QuasiUniformDeflection
257 const Standard_Real Deflection,
258 const GeomAbs_Shape Continuity)
260 Initialize (C, Deflection, Continuity);
264 //=======================================================================
265 //function : Initialize
267 //=======================================================================
268 void GCPnts_QuasiUniformDeflection::Initialize (const TheCurve& C,
269 const Standard_Real Deflection,
270 const GeomAbs_Shape Continuity)
272 Initialize (C, Deflection, C.FirstParameter(),
273 C.LastParameter(), Continuity);
277 //=======================================================================
278 //function : Initialize
280 //=======================================================================
282 void GCPnts_QuasiUniformDeflection::Initialize
284 const Standard_Real Deflection,
285 const Standard_Real theU1,
286 const Standard_Real theU2,
287 const GeomAbs_Shape Continuity)
289 myCont = (Continuity > GeomAbs_G1) ? GeomAbs_C1 : GeomAbs_C0;
290 Standard_Real EPSILON = C.Resolution (Precision::Confusion());
291 EPSILON = Min (EPSILON, 1.e50);
292 myDeflection = Deflection;
293 myDone = Standard_False;
296 GCPnts_DeflectionType Type = GetDefType (C);
298 Standard_Real U1 = Min (theU1, theU2);
299 Standard_Real U2 = Max (theU1, theU2);
301 if (Type == GCPnts_Curved || Type == GCPnts_DefComposite)
303 if (C.GetType() == GeomAbs_BSplineCurve || C.GetType() == GeomAbs_BezierCurve)
305 Standard_Real maxpar = Max (Abs (C.FirstParameter()), Abs (C.LastParameter()));
306 if (EPSILON < Epsilon (maxpar)) return;
313 myDone = PerformLinear (C, myParams, myPoints, U1, U2);
315 case GCPnts_Circular:
316 myDone = PerformCircular (C, myParams, myPoints, Deflection, U1, U2);
319 myDone = PerformCurve (myParams, myPoints, C, Deflection,
320 U1, U2, EPSILON, myCont);
322 case GCPnts_DefComposite:
323 myDone = PerformComposite (myParams, myPoints, C, Deflection,
324 U1, U2, EPSILON, myCont);
330 //=======================================================================
331 //function : QuasiFleche
333 //=======================================================================
334 void QuasiFleche (const TheCurve& C,
335 const Standard_Real Deflection2,
336 const Standard_Real Udeb,
339 const Standard_Real Ufin,
342 const Standard_Integer Nbmin,
343 const Standard_Real Eps,
344 TColStd_SequenceOfReal& Parameters,
345 TColgp_SequenceOfPnt& Points,
346 Standard_Integer& theNbCalls)
349 if (theNbCalls >= MyMaxQuasiFleshe)
353 Standard_Integer Ptslength = Points.Length();
354 if (theNbCalls > 100 && Ptslength < 2)
358 Standard_Real Udelta = Ufin - Udeb;
363 Udelta /= (Nbmin - 1);
364 D1 (C, Udeb + Udelta, Pdelta, Vdelta);
372 Standard_Real Norme = gp_Vec (Pdeb, Pdelta).SquareMagnitude();
373 Standard_Real theFleche = 0;
374 Standard_Boolean flecheok = Standard_False;
377 // Evaluation de la fleche par interpolation . Voir IntWalk_IWalking_5.gxx
378 Standard_Real N1 = Vdeb.SquareMagnitude();
379 Standard_Real N2 = Vdelta.SquareMagnitude();
380 if (N1 > Eps && N2 > Eps)
382 Standard_Real Normediff = (Vdeb.Normalized().XYZ() - Vdelta.Normalized().XYZ()).SquareModulus();
385 theFleche = Normediff * Norme / 64.;
386 flecheok = Standard_True;
392 gp_Pnt Pmid ((Pdeb.XYZ() + Pdelta.XYZ()) * 0.5);
393 gp_Pnt Pverif (Value(C, Udeb + Udelta * 0.5));
394 theFleche = Pmid.SquareDistance (Pverif);
397 if (theFleche < Deflection2)
399 Parameters.Append (Udeb + Udelta);
400 Points.Append (Pdelta);
404 QuasiFleche (C, Deflection2, Udeb, Pdeb,
406 Udeb + Udelta, Pdelta,
410 Parameters, Points, theNbCalls);
415 QuasiFleche (C, Deflection2, Udeb + Udelta, Pdelta,
419 Nbmin - (Points.Length() - Ptslength),
421 Parameters, Points, theNbCalls);
427 //=======================================================================
428 //function : QuasiFleche
430 //=======================================================================
431 void QuasiFleche (const TheCurve& C,
432 const Standard_Real Deflection2,
433 const Standard_Real Udeb,
435 const Standard_Real Ufin,
437 const Standard_Integer Nbmin,
438 TColStd_SequenceOfReal& Parameters,
439 TColgp_SequenceOfPnt& Points,
440 Standard_Integer& theNbCalls)
443 if (theNbCalls >= MyMaxQuasiFleshe)
447 Standard_Integer Ptslength = Points.Length();
448 if (theNbCalls > 100 && Ptslength < 2)
452 Standard_Real Udelta = Ufin - Udeb;
457 Pdelta = Value (C, Udeb + Udelta);
464 gp_Pnt Pmid ((Pdeb.XYZ() + Pdelta.XYZ()) * 0.5);
465 gp_Pnt Pverif (Value (C, Udeb + Udelta * 0.5));
466 Standard_Real theFleche = Pmid.SquareDistance (Pverif);
468 if (theFleche < Deflection2)
470 Parameters.Append(Udeb + Udelta);
471 Points.Append (Pdelta);
475 QuasiFleche (C, Deflection2, Udeb, Pdeb,
476 Udeb + Udelta * 0.5, Pverif,
478 Parameters, Points, theNbCalls);
480 QuasiFleche (C, Deflection2, Udeb + Udelta * 0.5, Pverif,
481 Udeb + Udelta, Pdelta,
483 Parameters, Points, theNbCalls);
488 QuasiFleche (C, Deflection2, Udeb + Udelta, Pdelta,
490 Nbmin - (Points.Length() - Ptslength),
491 Parameters, Points, theNbCalls);