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 = Index + 1 <= TI.Upper()
219 ? Min (U2, TI (Index + 1))
221 if (!PerformCurve (Parameters, Points, C, Deflection,
222 Ua, Ub, EPSILON, Continuity))
223 return Standard_False;
226 if (Index > NbIntervals || U2 < TI (Index))
227 return Standard_True;
229 // remove last point to avoid duplication
230 Parameters.Remove (Parameters.Length());
231 Points.Remove (Points.Length());
238 //=======================================================================
239 //function : GCPnts_QuasiUniformDeflection
241 //=======================================================================
242 GCPnts_QuasiUniformDeflection::GCPnts_QuasiUniformDeflection
244 const Standard_Real Deflection,
245 const Standard_Real U1,
246 const Standard_Real U2,
247 const GeomAbs_Shape Continuity)
249 Initialize (C, Deflection, U1, U2, Continuity);
253 //=======================================================================
254 //function : GCPnts_QuasiUniformDeflection
256 //=======================================================================
257 GCPnts_QuasiUniformDeflection::GCPnts_QuasiUniformDeflection
259 const Standard_Real Deflection,
260 const GeomAbs_Shape Continuity)
262 Initialize (C, Deflection, Continuity);
266 //=======================================================================
267 //function : Initialize
269 //=======================================================================
270 void GCPnts_QuasiUniformDeflection::Initialize (const TheCurve& C,
271 const Standard_Real Deflection,
272 const GeomAbs_Shape Continuity)
274 Initialize (C, Deflection, C.FirstParameter(),
275 C.LastParameter(), Continuity);
279 //=======================================================================
280 //function : Initialize
282 //=======================================================================
284 void GCPnts_QuasiUniformDeflection::Initialize
286 const Standard_Real Deflection,
287 const Standard_Real theU1,
288 const Standard_Real theU2,
289 const GeomAbs_Shape Continuity)
291 myCont = (Continuity > GeomAbs_G1) ? GeomAbs_C1 : GeomAbs_C0;
292 Standard_Real EPSILON = C.Resolution (Precision::Confusion());
293 EPSILON = Min (EPSILON, 1.e50);
294 myDeflection = Deflection;
295 myDone = Standard_False;
298 GCPnts_DeflectionType Type = GetDefType (C);
300 Standard_Real U1 = Min (theU1, theU2);
301 Standard_Real U2 = Max (theU1, theU2);
303 if (Type == GCPnts_Curved || Type == GCPnts_DefComposite)
305 if (C.GetType() == GeomAbs_BSplineCurve || C.GetType() == GeomAbs_BezierCurve)
307 Standard_Real maxpar = Max (Abs (C.FirstParameter()), Abs (C.LastParameter()));
308 if (EPSILON < Epsilon (maxpar)) return;
315 myDone = PerformLinear (C, myParams, myPoints, U1, U2);
317 case GCPnts_Circular:
318 myDone = PerformCircular (C, myParams, myPoints, Deflection, U1, U2);
321 myDone = PerformCurve (myParams, myPoints, C, Deflection,
322 U1, U2, EPSILON, myCont);
324 case GCPnts_DefComposite:
325 myDone = PerformComposite (myParams, myPoints, C, Deflection,
326 U1, U2, EPSILON, myCont);
332 //=======================================================================
333 //function : QuasiFleche
335 //=======================================================================
336 void QuasiFleche (const TheCurve& C,
337 const Standard_Real Deflection2,
338 const Standard_Real Udeb,
341 const Standard_Real Ufin,
344 const Standard_Integer Nbmin,
345 const Standard_Real Eps,
346 TColStd_SequenceOfReal& Parameters,
347 TColgp_SequenceOfPnt& Points,
348 Standard_Integer& theNbCalls)
351 if (theNbCalls >= MyMaxQuasiFleshe)
355 Standard_Integer Ptslength = Points.Length();
356 if (theNbCalls > 100 && Ptslength < 2)
360 Standard_Real Udelta = Ufin - Udeb;
365 Udelta /= (Nbmin - 1);
366 D1 (C, Udeb + Udelta, Pdelta, Vdelta);
374 Standard_Real Norme = gp_Vec (Pdeb, Pdelta).SquareMagnitude();
375 Standard_Real theFleche = 0;
376 Standard_Boolean flecheok = Standard_False;
379 // Evaluation de la fleche par interpolation . Voir IntWalk_IWalking_5.gxx
380 Standard_Real N1 = Vdeb.SquareMagnitude();
381 Standard_Real N2 = Vdelta.SquareMagnitude();
382 if (N1 > Eps && N2 > Eps)
384 Standard_Real Normediff = (Vdeb.Normalized().XYZ() - Vdelta.Normalized().XYZ()).SquareModulus();
387 theFleche = Normediff * Norme / 64.;
388 flecheok = Standard_True;
394 gp_Pnt Pmid ((Pdeb.XYZ() + Pdelta.XYZ()) * 0.5);
395 gp_Pnt Pverif (Value(C, Udeb + Udelta * 0.5));
396 theFleche = Pmid.SquareDistance (Pverif);
399 if (theFleche < Deflection2)
401 Parameters.Append (Udeb + Udelta);
402 Points.Append (Pdelta);
406 QuasiFleche (C, Deflection2, Udeb, Pdeb,
408 Udeb + Udelta, Pdelta,
412 Parameters, Points, theNbCalls);
417 QuasiFleche (C, Deflection2, Udeb + Udelta, Pdelta,
421 Nbmin - (Points.Length() - Ptslength),
423 Parameters, Points, theNbCalls);
429 //=======================================================================
430 //function : QuasiFleche
432 //=======================================================================
433 void QuasiFleche (const TheCurve& C,
434 const Standard_Real Deflection2,
435 const Standard_Real Udeb,
437 const Standard_Real Ufin,
439 const Standard_Integer Nbmin,
440 TColStd_SequenceOfReal& Parameters,
441 TColgp_SequenceOfPnt& Points,
442 Standard_Integer& theNbCalls)
445 if (theNbCalls >= MyMaxQuasiFleshe)
449 Standard_Integer Ptslength = Points.Length();
450 if (theNbCalls > 100 && Ptslength < 2)
454 Standard_Real Udelta = Ufin - Udeb;
459 Pdelta = Value (C, Udeb + Udelta);
466 gp_Pnt Pmid ((Pdeb.XYZ() + Pdelta.XYZ()) * 0.5);
467 gp_Pnt Pverif (Value (C, Udeb + Udelta * 0.5));
468 Standard_Real theFleche = Pmid.SquareDistance (Pverif);
470 if (theFleche < Deflection2)
472 Parameters.Append(Udeb + Udelta);
473 Points.Append (Pdelta);
477 QuasiFleche (C, Deflection2, Udeb, Pdeb,
478 Udeb + Udelta * 0.5, Pverif,
480 Parameters, Points, theNbCalls);
482 QuasiFleche (C, Deflection2, Udeb + Udelta * 0.5, Pverif,
483 Udeb + Udelta, Pdelta,
485 Parameters, Points, theNbCalls);
490 QuasiFleche (C, Deflection2, Udeb + Udelta, Pdelta,
492 Nbmin - (Points.Length() - Ptslength),
493 Parameters, Points, theNbCalls);