b311480e |
1 | // Copyright (c) 1995-1999 Matra Datavision |
973c2be1 |
2 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
3 | // |
973c2be1 |
4 | // This file is part of Open CASCADE Technology software library. |
b311480e |
5 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
11 | // |
973c2be1 |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
b311480e |
14 | |
7fd59977 |
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> |
27 | |
dcf0889f |
28 | |
7fd59977 |
29 | static void QuasiFleche(const TheCurve&, |
30 | const Standard_Real, |
31 | const Standard_Real, |
32 | const gp_Pnt&, |
33 | const gp_Vec&, |
34 | const Standard_Real, |
35 | const gp_Pnt&, |
36 | const gp_Vec&, |
37 | const Standard_Integer, |
38 | const Standard_Real, |
39 | TColStd_SequenceOfReal&, |
dcf0889f |
40 | TColgp_SequenceOfPnt&, |
41 | Standard_Integer&); |
7fd59977 |
42 | |
43 | static void QuasiFleche(const TheCurve&, |
44 | const Standard_Real, |
45 | const Standard_Real, |
46 | const gp_Pnt&, |
47 | const Standard_Real, |
48 | const gp_Pnt&, |
49 | const Standard_Integer, |
50 | TColStd_SequenceOfReal&, |
dcf0889f |
51 | TColgp_SequenceOfPnt&, |
52 | Standard_Integer&); |
7fd59977 |
53 | |
54 | |
55 | //======================================================================= |
56 | //function : PerformLinear |
57 | //purpose : |
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) |
64 | { |
65 | gp_Pnt aPoint; |
66 | Parameters.Append (U1); |
67 | aPoint = Value (C, U1); |
68 | Points.Append (aPoint); |
69 | |
70 | Parameters.Append (U2); |
71 | aPoint = Value (C, U2); |
72 | Points.Append (aPoint); |
73 | return Standard_True; |
74 | } |
75 | |
76 | |
77 | //======================================================================= |
78 | //function : PerformCircular |
79 | //purpose : |
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) |
87 | |
88 | { |
89 | gp_Pnt aPoint; |
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); |
93 | NbPoints += 2; |
94 | Angle = (U2 - U1) / (Standard_Real) (NbPoints - 1); |
95 | Standard_Real U = U1; |
96 | for (Standard_Integer i = 1; i <= NbPoints; ++i) |
97 | { |
98 | Parameters.Append (U); |
99 | aPoint = Value (C,U); |
100 | Points.Append (aPoint); |
101 | U += Angle; |
102 | } |
103 | return Standard_True; |
104 | } |
105 | |
106 | |
107 | //======================================================================= |
108 | //function : GetDefType |
109 | //purpose : |
110 | //======================================================================= |
37782ec2 |
111 | static GCPnts_DeflectionType GetDefType (const TheCurve& C) |
7fd59977 |
112 | { |
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... |
117 | |
118 | switch (C.GetType()) |
119 | { |
120 | case GeomAbs_Line: return GCPnts_Linear; |
121 | case GeomAbs_Circle: return GCPnts_Circular; |
122 | case GeomAbs_BSplineCurve: |
123 | { |
124 | Handle_TheBSplineCurve BS = C.BSpline(); |
125 | return (BS->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved; |
126 | } |
127 | case GeomAbs_BezierCurve: |
128 | { |
129 | Handle_TheBezierCurve BZ = C.Bezier(); |
130 | return (BZ->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved; |
131 | } |
132 | default: return GCPnts_Curved; |
133 | } |
134 | } |
135 | |
136 | |
137 | //======================================================================= |
138 | //function : PerformCurve |
139 | //purpose : |
140 | //======================================================================= |
141 | static Standard_Boolean PerformCurve (TColStd_SequenceOfReal& Parameters, |
142 | TColgp_SequenceOfPnt& Points, |
143 | const TheCurve& C, |
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) |
149 | { |
d8726c7c |
150 | Standard_Integer Nbmin = 2; |
dcf0889f |
151 | Standard_Integer aNbCallQF = 0; |
7fd59977 |
152 | |
153 | gp_Pnt Pdeb; |
154 | if (Continuity <= GeomAbs_G1) |
155 | { |
156 | |
157 | Pdeb = Value (C, U1); |
158 | Parameters.Append (U1); |
159 | Points.Append (Pdeb); |
160 | |
161 | gp_Pnt Pfin (Value (C, U2)); |
162 | QuasiFleche (C, Deflection * Deflection, |
163 | U1, Pdeb, |
164 | U2, Pfin, |
165 | Nbmin, |
dcf0889f |
166 | Parameters, Points, aNbCallQF); |
7fd59977 |
167 | } |
168 | else |
169 | { |
170 | gp_Pnt Pfin; |
171 | gp_Vec Ddeb, Dfin; |
172 | D1 (C, U1, Pdeb, Ddeb); |
173 | Parameters.Append (U1); |
174 | Points.Append (Pdeb); |
175 | |
bfd69b5f |
176 | Standard_Real aDecreasedU2 = U2 - Epsilon(U2) * 10.; |
177 | D1 (C, aDecreasedU2, Pfin, Dfin); |
7fd59977 |
178 | QuasiFleche (C, Deflection * Deflection, |
179 | U1, Pdeb, |
180 | Ddeb, |
181 | U2, Pfin, |
182 | Dfin, |
183 | Nbmin, |
184 | EPSILON * EPSILON, |
dcf0889f |
185 | Parameters, Points, aNbCallQF); |
7fd59977 |
186 | } |
187 | // cout << "Nb de pts: " << Points.Length()<< endl; |
188 | return Standard_True; |
189 | } |
190 | |
191 | |
192 | //======================================================================= |
193 | //function : PerformComposite |
194 | //purpose : |
195 | //======================================================================= |
196 | static Standard_Boolean PerformComposite (TColStd_SequenceOfReal& Parameters, |
197 | TColgp_SequenceOfPnt& Points, |
37782ec2 |
198 | const TheCurve& C, |
7fd59977 |
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) |
204 | { |
205 | // |
206 | // coherence avec Intervals |
207 | // |
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); |
213 | |
214 | // iterate by continuous segments |
215 | Standard_Real Ua = U1; |
216 | for (Standard_Integer Index = PIndex;;) |
217 | { |
437ef771 |
218 | Standard_Real Ub = Index + 1 <= TI.Upper() |
219 | ? Min (U2, TI (Index + 1)) |
220 | : U2; |
7fd59977 |
221 | if (!PerformCurve (Parameters, Points, C, Deflection, |
222 | Ua, Ub, EPSILON, Continuity)) |
223 | return Standard_False; |
224 | |
225 | ++Index; |
226 | if (Index > NbIntervals || U2 < TI (Index)) |
227 | return Standard_True; |
228 | |
229 | // remove last point to avoid duplication |
230 | Parameters.Remove (Parameters.Length()); |
231 | Points.Remove (Points.Length()); |
232 | |
233 | Ua = Ub; |
234 | } |
7fd59977 |
235 | } |
236 | |
237 | |
238 | //======================================================================= |
239 | //function : GCPnts_QuasiUniformDeflection |
240 | //purpose : |
241 | //======================================================================= |
242 | GCPnts_QuasiUniformDeflection::GCPnts_QuasiUniformDeflection |
37782ec2 |
243 | (const TheCurve& C, |
7fd59977 |
244 | const Standard_Real Deflection, |
245 | const Standard_Real U1, |
246 | const Standard_Real U2, |
247 | const GeomAbs_Shape Continuity) |
248 | { |
249 | Initialize (C, Deflection, U1, U2, Continuity); |
250 | } |
251 | |
252 | |
253 | //======================================================================= |
254 | //function : GCPnts_QuasiUniformDeflection |
255 | //purpose : |
256 | //======================================================================= |
257 | GCPnts_QuasiUniformDeflection::GCPnts_QuasiUniformDeflection |
37782ec2 |
258 | (const TheCurve& C, |
7fd59977 |
259 | const Standard_Real Deflection, |
260 | const GeomAbs_Shape Continuity) |
261 | { |
262 | Initialize (C, Deflection, Continuity); |
263 | } |
264 | |
265 | |
266 | //======================================================================= |
267 | //function : Initialize |
268 | //purpose : |
269 | //======================================================================= |
37782ec2 |
270 | void GCPnts_QuasiUniformDeflection::Initialize (const TheCurve& C, |
7fd59977 |
271 | const Standard_Real Deflection, |
272 | const GeomAbs_Shape Continuity) |
273 | { |
274 | Initialize (C, Deflection, C.FirstParameter(), |
275 | C.LastParameter(), Continuity); |
276 | } |
277 | |
278 | |
279 | //======================================================================= |
280 | //function : Initialize |
281 | //purpose : |
282 | //======================================================================= |
283 | |
284 | void GCPnts_QuasiUniformDeflection::Initialize |
37782ec2 |
285 | (const TheCurve& C, |
7fd59977 |
286 | const Standard_Real Deflection, |
287 | const Standard_Real theU1, |
288 | const Standard_Real theU2, |
289 | const GeomAbs_Shape Continuity) |
290 | { |
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; |
296 | myParams.Clear(); |
297 | myPoints.Clear(); |
298 | GCPnts_DeflectionType Type = GetDefType (C); |
299 | |
300 | Standard_Real U1 = Min (theU1, theU2); |
301 | Standard_Real U2 = Max (theU1, theU2); |
302 | |
303 | if (Type == GCPnts_Curved || Type == GCPnts_DefComposite) |
304 | { |
305 | if (C.GetType() == GeomAbs_BSplineCurve || C.GetType() == GeomAbs_BezierCurve) |
306 | { |
307 | Standard_Real maxpar = Max (Abs (C.FirstParameter()), Abs (C.LastParameter())); |
308 | if (EPSILON < Epsilon (maxpar)) return; |
309 | } |
310 | } |
311 | |
312 | switch (Type) |
313 | { |
314 | case GCPnts_Linear: |
315 | myDone = PerformLinear (C, myParams, myPoints, U1, U2); |
316 | break; |
317 | case GCPnts_Circular: |
318 | myDone = PerformCircular (C, myParams, myPoints, Deflection, U1, U2); |
319 | break; |
320 | case GCPnts_Curved: |
321 | myDone = PerformCurve (myParams, myPoints, C, Deflection, |
322 | U1, U2, EPSILON, myCont); |
323 | break; |
324 | case GCPnts_DefComposite: |
325 | myDone = PerformComposite (myParams, myPoints, C, Deflection, |
326 | U1, U2, EPSILON, myCont); |
327 | break; |
328 | } |
329 | } |
330 | |
331 | |
332 | //======================================================================= |
333 | //function : QuasiFleche |
334 | //purpose : |
335 | //======================================================================= |
336 | void QuasiFleche (const TheCurve& C, |
337 | const Standard_Real Deflection2, |
338 | const Standard_Real Udeb, |
339 | const gp_Pnt& Pdeb, |
340 | const gp_Vec& Vdeb, |
341 | const Standard_Real Ufin, |
342 | const gp_Pnt& Pfin, |
343 | const gp_Vec& Vfin, |
344 | const Standard_Integer Nbmin, |
345 | const Standard_Real Eps, |
346 | TColStd_SequenceOfReal& Parameters, |
dcf0889f |
347 | TColgp_SequenceOfPnt& Points, |
348 | Standard_Integer& theNbCalls) |
7fd59977 |
349 | { |
dcf0889f |
350 | theNbCalls++; |
351 | if (theNbCalls >= MyMaxQuasiFleshe) |
352 | { |
353 | return; |
354 | } |
7fd59977 |
355 | Standard_Integer Ptslength = Points.Length(); |
dcf0889f |
356 | if (theNbCalls > 100 && Ptslength < 2) |
357 | { |
358 | return; |
359 | } |
7fd59977 |
360 | Standard_Real Udelta = Ufin - Udeb; |
361 | gp_Pnt Pdelta; |
362 | gp_Vec Vdelta; |
363 | if (Nbmin > 2) |
364 | { |
365 | Udelta /= (Nbmin - 1); |
366 | D1 (C, Udeb + Udelta, Pdelta, Vdelta); |
367 | } |
368 | else |
369 | { |
370 | Pdelta = Pfin; |
371 | Vdelta = Vfin; |
372 | } |
373 | |
374 | Standard_Real Norme = gp_Vec (Pdeb, Pdelta).SquareMagnitude(); |
375 | Standard_Real theFleche = 0; |
376 | Standard_Boolean flecheok = Standard_False; |
377 | if (Norme > Eps) |
378 | { |
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) |
383 | { |
384 | Standard_Real Normediff = (Vdeb.Normalized().XYZ() - Vdelta.Normalized().XYZ()).SquareModulus(); |
385 | if (Normediff > Eps) |
386 | { |
387 | theFleche = Normediff * Norme / 64.; |
388 | flecheok = Standard_True; |
389 | } |
390 | } |
391 | } |
392 | if (!flecheok) |
393 | { |
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); |
397 | } |
398 | |
399 | if (theFleche < Deflection2) |
400 | { |
401 | Parameters.Append (Udeb + Udelta); |
402 | Points.Append (Pdelta); |
403 | } |
404 | else |
405 | { |
406 | QuasiFleche (C, Deflection2, Udeb, Pdeb, |
407 | Vdeb, |
408 | Udeb + Udelta, Pdelta, |
409 | Vdelta, |
410 | 3, |
411 | Eps, |
dcf0889f |
412 | Parameters, Points, theNbCalls); |
7fd59977 |
413 | } |
414 | |
415 | if (Nbmin > 2) |
416 | { |
417 | QuasiFleche (C, Deflection2, Udeb + Udelta, Pdelta, |
418 | Vdelta, |
419 | Ufin, Pfin, |
420 | Vfin, |
421 | Nbmin - (Points.Length() - Ptslength), |
422 | Eps, |
dcf0889f |
423 | Parameters, Points, theNbCalls); |
7fd59977 |
424 | } |
dcf0889f |
425 | theNbCalls--; |
7fd59977 |
426 | } |
427 | |
428 | |
429 | //======================================================================= |
430 | //function : QuasiFleche |
431 | //purpose : |
432 | //======================================================================= |
433 | void QuasiFleche (const TheCurve& C, |
434 | const Standard_Real Deflection2, |
435 | const Standard_Real Udeb, |
436 | const gp_Pnt& Pdeb, |
437 | const Standard_Real Ufin, |
438 | const gp_Pnt& Pfin, |
439 | const Standard_Integer Nbmin, |
440 | TColStd_SequenceOfReal& Parameters, |
dcf0889f |
441 | TColgp_SequenceOfPnt& Points, |
442 | Standard_Integer& theNbCalls) |
7fd59977 |
443 | { |
dcf0889f |
444 | theNbCalls++; |
445 | if (theNbCalls >= MyMaxQuasiFleshe) |
446 | { |
447 | return; |
448 | } |
7fd59977 |
449 | Standard_Integer Ptslength = Points.Length(); |
dcf0889f |
450 | if (theNbCalls > 100 && Ptslength < 2) |
451 | { |
452 | return; |
453 | } |
7fd59977 |
454 | Standard_Real Udelta = Ufin - Udeb; |
455 | gp_Pnt Pdelta; |
456 | if (Nbmin > 2) |
457 | { |
458 | Udelta /= (Nbmin-1); |
459 | Pdelta = Value (C, Udeb + Udelta); |
460 | } |
461 | else |
462 | { |
463 | Pdelta = Pfin; |
464 | } |
465 | |
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); |
469 | |
470 | if (theFleche < Deflection2) |
471 | { |
472 | Parameters.Append(Udeb + Udelta); |
473 | Points.Append (Pdelta); |
474 | } |
475 | else |
476 | { |
477 | QuasiFleche (C, Deflection2, Udeb, Pdeb, |
478 | Udeb + Udelta * 0.5, Pverif, |
479 | 2, |
dcf0889f |
480 | Parameters, Points, theNbCalls); |
7fd59977 |
481 | |
482 | QuasiFleche (C, Deflection2, Udeb + Udelta * 0.5, Pverif, |
483 | Udeb + Udelta, Pdelta, |
484 | 2, |
dcf0889f |
485 | Parameters, Points, theNbCalls); |
7fd59977 |
486 | } |
487 | |
488 | if (Nbmin > 2) |
489 | { |
490 | QuasiFleche (C, Deflection2, Udeb + Udelta, Pdelta, |
491 | Ufin, Pfin, |
492 | Nbmin - (Points.Length() - Ptslength), |
dcf0889f |
493 | Parameters, Points, theNbCalls); |
7fd59977 |
494 | } |
dcf0889f |
495 | theNbCalls--; |
7fd59977 |
496 | } |