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>
28 static void QuasiFleche(const TheCurve&,
36 const Standard_Integer,
38 TColStd_SequenceOfReal&,
39 TColgp_SequenceOfPnt&);
41 static void QuasiFleche(const TheCurve&,
47 const Standard_Integer,
48 TColStd_SequenceOfReal&,
49 TColgp_SequenceOfPnt&);
52 //=======================================================================
53 //function : PerformLinear
55 //=======================================================================
56 static Standard_Boolean PerformLinear (const TheCurve& C,
57 TColStd_SequenceOfReal& Parameters,
58 TColgp_SequenceOfPnt& Points,
59 const Standard_Real U1,
60 const Standard_Real U2)
63 Parameters.Append (U1);
64 aPoint = Value (C, U1);
65 Points.Append (aPoint);
67 Parameters.Append (U2);
68 aPoint = Value (C, U2);
69 Points.Append (aPoint);
74 //=======================================================================
75 //function : PerformCircular
77 //=======================================================================
78 static Standard_Boolean PerformCircular (const TheCurve& C,
79 TColStd_SequenceOfReal& Parameters,
80 TColgp_SequenceOfPnt& Points,
81 const Standard_Real Deflection,
82 const Standard_Real U1,
83 const Standard_Real U2)
87 Standard_Real Angle = Max (1.0e0 - (Deflection / C.Circle().Radius()), 0.0e0);
88 Angle = 2.0e0 * ACos (Angle);
89 Standard_Integer NbPoints = (Standard_Integer )((U2 - U1) / Angle);
91 Angle = (U2 - U1) / (Standard_Real) (NbPoints - 1);
93 for (Standard_Integer i = 1; i <= NbPoints; ++i)
95 Parameters.Append (U);
97 Points.Append (aPoint);
100 return Standard_True;
104 //=======================================================================
105 //function : GetDefType
107 //=======================================================================
108 static GCPnts_DeflectionType GetDefType (const TheCurve& C)
110 if (C.NbIntervals(GeomAbs_C1) > 1)
111 return GCPnts_DefComposite;
112 // pour forcer les decoupages aux cassures. G1 devrait marcher,
113 // mais donne des exceptions...
117 case GeomAbs_Line: return GCPnts_Linear;
118 case GeomAbs_Circle: return GCPnts_Circular;
119 case GeomAbs_BSplineCurve:
121 Handle_TheBSplineCurve BS = C.BSpline();
122 return (BS->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved;
124 case GeomAbs_BezierCurve:
126 Handle_TheBezierCurve BZ = C.Bezier();
127 return (BZ->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved;
129 default: return GCPnts_Curved;
134 //=======================================================================
135 //function : PerformCurve
137 //=======================================================================
138 static Standard_Boolean PerformCurve (TColStd_SequenceOfReal& Parameters,
139 TColgp_SequenceOfPnt& Points,
141 const Standard_Real Deflection,
142 const Standard_Real U1,
143 const Standard_Real U2,
144 const Standard_Real EPSILON,
145 const GeomAbs_Shape Continuity)
147 Standard_Integer Nbmin = 2;
150 if (Continuity <= GeomAbs_G1)
153 Pdeb = Value (C, U1);
154 Parameters.Append (U1);
155 Points.Append (Pdeb);
157 gp_Pnt Pfin (Value (C, U2));
158 QuasiFleche (C, Deflection * Deflection,
168 D1 (C, U1, Pdeb, Ddeb);
169 Parameters.Append (U1);
170 Points.Append (Pdeb);
172 D1 (C, U2, Pfin, Dfin);
173 QuasiFleche (C, Deflection * Deflection,
182 // cout << "Nb de pts: " << Points.Length()<< endl;
183 return Standard_True;
187 //=======================================================================
188 //function : PerformComposite
190 //=======================================================================
191 static Standard_Boolean PerformComposite (TColStd_SequenceOfReal& Parameters,
192 TColgp_SequenceOfPnt& Points,
194 const Standard_Real Deflection,
195 const Standard_Real U1,
196 const Standard_Real U2,
197 const Standard_Real EPSILON,
198 const GeomAbs_Shape Continuity)
201 // coherence avec Intervals
203 Standard_Integer NbIntervals = C.NbIntervals (GeomAbs_C2);
204 Standard_Integer PIndex;
205 TColStd_Array1OfReal TI (1, NbIntervals + 1);
206 C.Intervals (TI, GeomAbs_C2);
207 BSplCLib::Hunt (TI, U1, PIndex);
209 // iterate by continuous segments
210 Standard_Real Ua = U1;
211 for (Standard_Integer Index = PIndex;;)
213 Standard_Real Ub = Min (U2, TI (Index + 1));
214 if (!PerformCurve (Parameters, Points, C, Deflection,
215 Ua, Ub, EPSILON, Continuity))
216 return Standard_False;
219 if (Index > NbIntervals || U2 < TI (Index))
220 return Standard_True;
222 // remove last point to avoid duplication
223 Parameters.Remove (Parameters.Length());
224 Points.Remove (Points.Length());
231 //=======================================================================
232 //function : GCPnts_QuasiUniformDeflection
234 //=======================================================================
235 GCPnts_QuasiUniformDeflection::GCPnts_QuasiUniformDeflection
237 const Standard_Real Deflection,
238 const Standard_Real U1,
239 const Standard_Real U2,
240 const GeomAbs_Shape Continuity)
242 Initialize (C, Deflection, U1, U2, Continuity);
246 //=======================================================================
247 //function : GCPnts_QuasiUniformDeflection
249 //=======================================================================
250 GCPnts_QuasiUniformDeflection::GCPnts_QuasiUniformDeflection
252 const Standard_Real Deflection,
253 const GeomAbs_Shape Continuity)
255 Initialize (C, Deflection, Continuity);
259 //=======================================================================
260 //function : Initialize
262 //=======================================================================
263 void GCPnts_QuasiUniformDeflection::Initialize (const TheCurve& C,
264 const Standard_Real Deflection,
265 const GeomAbs_Shape Continuity)
267 Initialize (C, Deflection, C.FirstParameter(),
268 C.LastParameter(), Continuity);
272 //=======================================================================
273 //function : Initialize
275 //=======================================================================
277 void GCPnts_QuasiUniformDeflection::Initialize
279 const Standard_Real Deflection,
280 const Standard_Real theU1,
281 const Standard_Real theU2,
282 const GeomAbs_Shape Continuity)
284 myCont = (Continuity > GeomAbs_G1) ? GeomAbs_C1 : GeomAbs_C0;
285 Standard_Real EPSILON = C.Resolution (Precision::Confusion());
286 EPSILON = Min (EPSILON, 1.e50);
287 myDeflection = Deflection;
288 myDone = Standard_False;
291 GCPnts_DeflectionType Type = GetDefType (C);
293 Standard_Real U1 = Min (theU1, theU2);
294 Standard_Real U2 = Max (theU1, theU2);
296 if (Type == GCPnts_Curved || Type == GCPnts_DefComposite)
298 if (C.GetType() == GeomAbs_BSplineCurve || C.GetType() == GeomAbs_BezierCurve)
300 Standard_Real maxpar = Max (Abs (C.FirstParameter()), Abs (C.LastParameter()));
301 if (EPSILON < Epsilon (maxpar)) return;
308 myDone = PerformLinear (C, myParams, myPoints, U1, U2);
310 case GCPnts_Circular:
311 myDone = PerformCircular (C, myParams, myPoints, Deflection, U1, U2);
314 myDone = PerformCurve (myParams, myPoints, C, Deflection,
315 U1, U2, EPSILON, myCont);
317 case GCPnts_DefComposite:
318 myDone = PerformComposite (myParams, myPoints, C, Deflection,
319 U1, U2, EPSILON, myCont);
325 //=======================================================================
326 //function : QuasiFleche
328 //=======================================================================
329 void QuasiFleche (const TheCurve& C,
330 const Standard_Real Deflection2,
331 const Standard_Real Udeb,
334 const Standard_Real Ufin,
337 const Standard_Integer Nbmin,
338 const Standard_Real Eps,
339 TColStd_SequenceOfReal& Parameters,
340 TColgp_SequenceOfPnt& Points)
342 Standard_Integer Ptslength = Points.Length();
343 Standard_Real Udelta = Ufin - Udeb;
348 Udelta /= (Nbmin - 1);
349 D1 (C, Udeb + Udelta, Pdelta, Vdelta);
357 Standard_Real Norme = gp_Vec (Pdeb, Pdelta).SquareMagnitude();
358 Standard_Real theFleche = 0;
359 Standard_Boolean flecheok = Standard_False;
362 // Evaluation de la fleche par interpolation . Voir IntWalk_IWalking_5.gxx
363 Standard_Real N1 = Vdeb.SquareMagnitude();
364 Standard_Real N2 = Vdelta.SquareMagnitude();
365 if (N1 > Eps && N2 > Eps)
367 Standard_Real Normediff = (Vdeb.Normalized().XYZ() - Vdelta.Normalized().XYZ()).SquareModulus();
370 theFleche = Normediff * Norme / 64.;
371 flecheok = Standard_True;
377 gp_Pnt Pmid ((Pdeb.XYZ() + Pdelta.XYZ()) * 0.5);
378 gp_Pnt Pverif (Value(C, Udeb + Udelta * 0.5));
379 theFleche = Pmid.SquareDistance (Pverif);
382 if (theFleche < Deflection2)
384 Parameters.Append (Udeb + Udelta);
385 Points.Append (Pdelta);
389 QuasiFleche (C, Deflection2, Udeb, Pdeb,
391 Udeb + Udelta, Pdelta,
400 QuasiFleche (C, Deflection2, Udeb + Udelta, Pdelta,
404 Nbmin - (Points.Length() - Ptslength),
411 //=======================================================================
412 //function : QuasiFleche
414 //=======================================================================
415 void QuasiFleche (const TheCurve& C,
416 const Standard_Real Deflection2,
417 const Standard_Real Udeb,
419 const Standard_Real Ufin,
421 const Standard_Integer Nbmin,
422 TColStd_SequenceOfReal& Parameters,
423 TColgp_SequenceOfPnt& Points)
425 Standard_Integer Ptslength = Points.Length();
426 Standard_Real Udelta = Ufin - Udeb;
431 Pdelta = Value (C, Udeb + Udelta);
438 gp_Pnt Pmid ((Pdeb.XYZ() + Pdelta.XYZ()) * 0.5);
439 gp_Pnt Pverif (Value (C, Udeb + Udelta * 0.5));
440 Standard_Real theFleche = Pmid.SquareDistance (Pverif);
442 if (theFleche < Deflection2)
444 Parameters.Append(Udeb + Udelta);
445 Points.Append (Pdelta);
449 QuasiFleche (C, Deflection2, Udeb, Pdeb,
450 Udeb + Udelta * 0.5, Pverif,
454 QuasiFleche (C, Deflection2, Udeb + Udelta * 0.5, Pverif,
455 Udeb + Udelta, Pdelta,
462 QuasiFleche (C, Deflection2, Udeb + Udelta, Pdelta,
464 Nbmin - (Points.Length() - Ptslength),