Integration of OCCT 6.5.0 from SVN
[occt.git] / src / ShapeAnalysis / ShapeAnalysis_Curve.cxx
CommitLineData
7fd59977 1// pdn 04.12.98 Add method using Adaptor_Curve
2//:j8 abv 10.12.98 TR10 r0501_db.stp #9423
3//pdn 25.12.98 private method ProjectAct
4//szv#4 S4163
5//:s5 abv 22.04.99 Adding debug printouts in catch {} blocks
6// abv 14.05.99 S4174: Adding method for exact computing of the boundary box
7// gka 21.06.99 S4208: adding method NextProject(Adaptor_Curve)
8// msv 30.05.00 correct IsPlanar for a conic curve
9#include <ShapeAnalysis_Curve.ixx>
10
11#include <ElCLib.hxx>
12
13#include <Geom2d_BoundedCurve.hxx>
14#include <Geom2d_Line.hxx>
15#include <Geom_BSplineCurve.hxx>
16#include <GeomAdaptor_Curve.hxx>
17
18#include <Precision.hxx>
19
20#include <Standard_ErrorHandler.hxx>
21#include <Standard_Failure.hxx>
22#include <Adaptor3d_Curve.hxx>
23#include <Extrema_ExtPC.hxx>
24#include <ShapeAnalysis.hxx>
25#include <TColgp_SequenceOfPnt.hxx>
26#include <Geom_Line.hxx>
27#include <Geom_Conic.hxx>
28#include <Geom_TrimmedCurve.hxx>
29#include <Geom_OffsetCurve.hxx>
30#include <Geom_BezierCurve.hxx>
31#include <ShapeExtend_ComplexCurve.hxx>
32#include <Geom2d_Conic.hxx>
33#include <Geom2d_TrimmedCurve.hxx>
34#include <Geom2d_BSplineCurve.hxx>
35#include <Geom2d_BezierCurve.hxx>
36
37#include <Geom2d_OffsetCurve.hxx>
38#include <Geom2dInt_Geom2dCurveTool.hxx>
39#include <Geom2dAdaptor_Curve.hxx>
40#include <Geom_Circle.hxx>
41
42
43//=======================================================================
44//function : ProjectOnSegments
45//purpose :
46//=======================================================================
47
48static void ProjectOnSegments (const Adaptor3d_Curve& AC, const gp_Pnt& P3D,
49 const Standard_Integer nbseg,
50 Standard_Real& uMin, Standard_Real& uMax,
51 Standard_Real& distmin, gp_Pnt& proj, Standard_Real& param)
52{
53 // On considere <nbseg> points sur [uMin,uMax]
54 // Quel est le plus proche. Et quel est le nouvel intervalle
55 // (il ne peut pas deborder l ancien)
56 Standard_Real u, dist, delta = (nbseg == 0)? 0 : (uMax-uMin)/nbseg; //szv#4:S4163:12Mar99 anti-exception
57 for (Standard_Integer i = 0; i <= nbseg; i ++) {
58 u = uMin + (delta * i);
59 gp_Pnt PU = AC.Value (u);
60 dist = PU.Distance (P3D);
61 if (dist < distmin) { distmin = dist; proj = PU; param = u; }
62 }
63
64#ifdef DEBUG
65 cout<<"ShapeAnalysis_Geom:Project, param="<<param<<" -> distmin="<<distmin<<endl;
66#endif
67
68 uMax = Min (uMax, param+delta);
69 uMin = Max (uMin, param-delta);
70}
71
72
73//=======================================================================
74//function : CurveNewton
75//purpose : Newton algo on curve (study S4030)
76//=======================================================================
77
78static Standard_Boolean CurveNewton(const Standard_Real paramPrev,
79 const Adaptor3d_Curve& Ad,
80 const gp_Pnt& P3D,
81 const Standard_Real /*preci*/,
82 Standard_Real& param,
83 const Standard_Real cf,
84 const Standard_Real cl)
85{
86 //szv#4:S4163:12Mar99 optimized
87 Standard_Real uMin = cf, uMax = cl;
88
89 Standard_Real Tol = Precision::Confusion();
90 Standard_Real Tol2 = Tol*Tol, rs2p = 1.e+10;
91 Standard_Real X = paramPrev;
92
93 for ( Standard_Integer i=0; i<20; i++) {
94 gp_Vec v1, v2;
95 gp_Pnt pnt;
96 Ad.D2 (X, pnt, v1, v2);
97 Standard_Real nv1 = v1.SquareMagnitude();
98 if (nv1 < 1e-10) break;
99
100 gp_Vec rs (P3D, pnt);
101 Standard_Real D = nv1 + (rs * v2);
102 if ( fabs( D ) <1e-10) break;
103
104 Standard_Real dX = -(rs *v1)/D;
105 X += dX;
106
107 Standard_Real rs2 = rs.SquareMagnitude();
108 if (rs2 > 4.*rs2p) break;
109 rs2p = rs2;
110
111 if ( fabs(dX) > 1e-12) continue;
112
113 if (X < uMin || X > uMax) break;
114
115 Standard_Real rsn = rs * v1;
116 if (rsn*rsn/nv1 > Tol2) break;
117 param = X;
118 return Standard_True;
119 }
120
121 // cout <<"NewtonC: failed after " << i+1 << " iterations (fail " << fail << " )" << endl;
122 return Standard_False;
123}
124
125//=======================================================================
126//function : Project
127//purpose :
128//=======================================================================
129
130Standard_Real ShapeAnalysis_Curve::Project(const Handle(Geom_Curve)& C3D,
131 const gp_Pnt& P3D,
132 const Standard_Real preci,
133 gp_Pnt& proj,
134 Standard_Real& param,
135 const Standard_Boolean AdjustToEnds) const
136{
137 Standard_Real uMin = C3D->FirstParameter();
138 Standard_Real uMax = C3D->LastParameter();
139 if (uMin < uMax) return Project (C3D,P3D,preci,proj,param,uMin,uMax,AdjustToEnds);
140 else return Project (C3D,P3D,preci,proj,param,uMax,uMin,AdjustToEnds);
141}
142
143//=======================================================================
144//function : Project
145//purpose :
146//=======================================================================
147
148Standard_Real ShapeAnalysis_Curve::Project(const Handle(Geom_Curve)& C3D,
149 const gp_Pnt& P3D,
150 const Standard_Real preci,
151 gp_Pnt& proj,
152 Standard_Real& param,
153 const Standard_Real cf,
154 const Standard_Real cl,
155 const Standard_Boolean AdjustToEnds) const
156{
157 Standard_Real distmin;
158 Standard_Real uMin = (cf < cl ? cf : cl);
159 Standard_Real uMax = (cf < cl ? cl : cf);
160
161 if (C3D->IsKind(STANDARD_TYPE(Geom_BoundedCurve))) {
162 Standard_Real prec = ( AdjustToEnds ? preci : Precision::Confusion() ); //:j8 abv 10 Dec 98: tr10_r0501_db.stp #9423: protection against densing of points near one end
163 gp_Pnt LowBound = C3D->Value(uMin);
164 gp_Pnt HigBound = C3D->Value(uMax);
165 distmin = LowBound.Distance(P3D);
166 if (distmin <= prec) {
167 param = uMin;
168 proj = LowBound;
169 return distmin;
170 }
171 distmin = HigBound.Distance(P3D);
172 if (distmin <= prec) {
173 param = uMax;
174 proj = HigBound;
175 return distmin;
176 }
177 }
178
179 GeomAdaptor_Curve GAC(C3D, uMin, uMax);
180 if (!C3D->IsClosed()) {
181 //modified by rln on 16/12/97 after CSR# PRO11641 entity 20767
182 //the VIso was not closed (according to C3D->IsClosed()) while it "almost"
183 //was (the distance between ends of the curve was a little bit more than
184 //Precision::Confusion())
185 //in that case value 0.1 was too much and this method returned not correct parameter
186 //uMin = uMin - 0.1;
187 //uMax = uMax + 0.1;
188 // modified by pdn on 01.07.98 after BUC60195 entity 1952 (Min() added)
189 Standard_Real delta = Min (GAC.Resolution (preci), (uMax - uMin) * 0.1);
190 uMin -= delta;
191 uMax += delta;
192 GAC.Load(C3D, uMin, uMax);
193 }
194
195 return ProjectAct(GAC, P3D, preci, proj, param);
196}
197
198//=======================================================================
199//function : Project
200//purpose :
201//=======================================================================
202
203Standard_Real ShapeAnalysis_Curve::Project(const Adaptor3d_Curve& C3D,
204 const gp_Pnt& P3D,
205 const Standard_Real preci,
206 gp_Pnt& proj,
207 Standard_Real& param,
208 const Standard_Boolean AdjustToEnds) const
209
210{
211 Standard_Real uMin = C3D.FirstParameter();
212 Standard_Real uMax = C3D.LastParameter();
213 Standard_Real distmin;
214 if (!Precision::IsInfinite(uMin)||!Precision::IsInfinite(uMax)) {
215 Standard_Real prec = ( AdjustToEnds ? preci : Precision::Confusion() ); //:j8 abv 10 Dec 98: tr10_r0501_db.stp #9423: protection against densing of points near one end
216 gp_Pnt LowBound = C3D.Value(uMin);
217 gp_Pnt HigBound = C3D.Value(uMax);
218 distmin = LowBound.Distance(P3D);
219 if (distmin <= prec) {
220 param = uMin;
221 proj = LowBound;
222 return distmin;
223 }
224 distmin = HigBound.Distance(P3D);
225 if (distmin <= prec) {
226 param = uMax;
227 proj = HigBound;
228 return distmin;
229 }
230 }
231 return ProjectAct(C3D, P3D, preci, proj, param);
232}
233
234//=======================================================================
235//function : ProjectAct
236//purpose :
237//=======================================================================
238
239Standard_Real ShapeAnalysis_Curve::ProjectAct(const Adaptor3d_Curve& C3D,
240 const gp_Pnt& P3D,
241 const Standard_Real preci,
242 gp_Pnt& proj,
243 Standard_Real& param) const
244
245{
246 Standard_Boolean useExtrema = Standard_True; //:i5
247
248#ifdef WNT
249 //:i5 abv 11 Sep 98: UKI60195.igs on NT: hanging on null-length bsplines
250 if (C3D.IsClosed() && C3D.GetType()==GeomAbs_BSplineCurve) {
251 Handle(Geom_BSplineCurve) bspl = C3D.BSpline();
252 Standard_Real prec2 = gp::Resolution();
253 prec2 *= prec2;
254 gp_Pnt p0 = bspl->Pole(1), p1;
255 for ( Standard_Integer i=2; i <= bspl->NbPoles(); i++, p0 = p1 ) {
256 p1 = bspl->Pole(i);
257 if ( p0.SquareDistance ( p1 ) <= prec2 ) {
258 useExtrema = Standard_False;
259 break;
260 }
261 }
262 }
263#endif
264
265 Standard_Boolean OK = Standard_False;
266 if ( useExtrema ) { //:i5 //szv#4:S4163:12Mar99 try moved into if
267 try {
268 OCC_CATCH_SIGNALS
269 Extrema_ExtPC myExtPC(P3D,C3D);
270 //Standard_Boolean done = myExtPC.IsDone() && ( myExtPC.NbExt() > 0); //szv#4:S4163:12Mar99 not needed
271 if ( myExtPC.IsDone() && ( myExtPC.NbExt() > 0) ) {
272 Standard_Real dist2, dist2Min = myExtPC.SquareDistance(1);
273 Standard_Integer index = 1;
274 for ( Standard_Integer i = 2; i <= myExtPC.NbExt(); i++) {
275 dist2 = myExtPC.SquareDistance(i);
276 if ( dist2 < dist2Min) { dist2Min = dist2; index = i; }
277 }
278 param = (myExtPC.Point(index)).Parameter();
279 proj = (myExtPC.Point(index)).Value();
280 OK = Standard_True;
281 }
282 }
283 catch(Standard_Failure) {
284 OK = Standard_False;
285#ifdef DEB //:s5
286 cout << "\nWarning: ShapeAnalysis_Curve::ProjectAct(): Exception in Extrema_ExtPC: ";
287 Standard_Failure::Caught()->Print(cout); cout << endl;
288#endif
289 }
290 }
291
292 //szv#4:S4163:12Mar99 moved
293 Standard_Real uMin = C3D.FirstParameter(), uMax = C3D.LastParameter();
294 Standard_Boolean closed = Standard_False; // si on franchit les bornes ...
295 Standard_Real distmin = RealLast(), valclosed = 0.;
296 Standard_Real aModParam = param;
297 Standard_Real aModMin = distmin;
298
299 // PTV 29.05.2002 remember the old solution, cause it could be better
300 Standard_Real anOldParam =0.;
301 Standard_Boolean IsHaveOldSol = Standard_False;
302 gp_Pnt anOldProj;
303 if (OK) {
304 IsHaveOldSol = Standard_True;
305 anOldProj = proj;
306 anOldParam = param;
307 distmin = proj.Distance (P3D);
308 aModMin = distmin;
309 if (distmin > preci) OK = Standard_False;
310 // Cas TrimmedCurve a cheval. Voir la courbe de base.
311 // Si fermee, passer une periode
312 if (C3D.IsClosed()) {
313 closed = Standard_True;
314 valclosed = uMax - uMin; //szv#4:S4163:12Mar99 optimized
315 }
316 }
317
318 if (!OK) {
319 // BUG NICOLAS - Si le point est sur la courbe 0 Solutions
320 // Cela fonctionne avec ElCLib
321
322 // D une facon generale, on essaie de TOUJOURS retourner un resultat
323 // MEME PAS BIEN BON. L appelant pourra decider alors quoi faire
324 param = 0.;
325
326 switch(C3D.GetType()) {
327 case GeomAbs_Circle:
328 {
329 const gp_Circ& aCirc = C3D.Circle();
330 proj = aCirc.Position().Location();
331 if(aCirc.Radius() <= gp::Resolution() ||
332 P3D.SquareDistance(proj) <= gp::Resolution() ) {
333 param = C3D.FirstParameter();
334 proj = proj.XYZ() + aCirc.XAxis().Direction().XYZ() * aCirc.Radius();
335 }
336 else {
337 param = ElCLib::Parameter(aCirc, P3D);
338 proj = ElCLib::Value(param, aCirc);
339 }
340 closed = Standard_True;
341 valclosed = 2.*PI;
342 }
343 break;
344 case GeomAbs_Hyperbola:
345 {
346 param = ElCLib::Parameter(C3D.Hyperbola(), P3D);
347 proj = ElCLib::Value(param, C3D.Hyperbola());
348 }
349 break;
350 case GeomAbs_Parabola:
351 {
352 param = ElCLib::Parameter(C3D.Parabola(), P3D);
353 proj = ElCLib::Value(param, C3D.Parabola());
354 }
355 break;
356 case GeomAbs_Line:
357 {
358 param = ElCLib::Parameter(C3D.Line(), P3D);
359 proj = ElCLib::Value(param, C3D.Line());
360 }
361 break;
362 case GeomAbs_Ellipse:
363 {
364 param = ElCLib::Parameter(C3D.Ellipse(), P3D);
365 proj = ElCLib::Value(param, C3D.Ellipse());
366 closed = Standard_True;
367 valclosed = 2.*PI;
368
369 }
370 break;
371 default:
372 {
373 // on ne va quand meme pas se laisser abattre ... ???
374 // on tente ceci : 21 points sur la courbe, quel est le plus proche
375 distmin = Precision::Infinite();
376 ProjectOnSegments (C3D,P3D,25,uMin,uMax,distmin,proj,param);
377 if (distmin <= preci) return distmin;
378 if (CurveNewton(param, C3D, P3D, preci, param, uMin, uMax)) { //:S4030
379 C3D.D0(param, proj);
380 Standard_Real aDistNewton = P3D.Distance(proj);
381 if(aDistNewton < aModMin)
382 return aDistNewton;
383 }
384 // cout <<"newton failed"<<endl;
385 ProjectOnSegments (C3D,P3D,40,uMin,uMax,distmin,proj,param);
386 if (distmin <= preci) return distmin;
387 ProjectOnSegments (C3D,P3D,20,uMin,uMax,distmin,proj,param);
388 if (distmin <= preci) return distmin;
389 ProjectOnSegments (C3D,P3D,25,uMin,uMax,distmin,proj,param);
390 if (distmin <= preci) return distmin;
391 ProjectOnSegments (C3D,P3D,40,uMin,uMax,distmin,proj,param);
392 if (distmin <= preci) return distmin;
393 // soyons raisonnable ...
394 if(distmin > aModMin) {
395 distmin = aModMin;
396 param = aModParam;
397 }
398
399 return distmin;
400 }
401 }
402 }
403
404 // p = PPOC.LowerDistanceParameter(); cf try
405 if ( closed && ( param < uMin || param > uMax ) )
406 param += ShapeAnalysis::AdjustByPeriod ( param, 0.5 * ( uMin + uMax ), valclosed );
407
408 if (IsHaveOldSol) {
409 // PTV 29.05.2002 Compare old solution and new;
410 Standard_Real adist1, adist2;
411 adist1 = anOldProj.SquareDistance(P3D);
412 adist2 = proj.SquareDistance (P3D);
413 if (adist1 < adist2) {
414 proj = anOldProj;
415 param = anOldParam;
416 }
417 }
418 return proj.Distance (P3D);
419}
420
421
422//=======================================================================
423//function : NextProject
424//purpose : Newton algo for projecting point on curve (S4030)
425//=======================================================================
426
427Standard_Real ShapeAnalysis_Curve::NextProject(const Standard_Real paramPrev,
428 const Handle(Geom_Curve)& C3D,
429 const gp_Pnt& P3D,
430 const Standard_Real preci,
431 gp_Pnt& proj,
432 Standard_Real& param,
433 const Standard_Real cf,
434 const Standard_Real cl,
435 const Standard_Boolean AdjustToEnds) const
436{
437 Standard_Real uMin = (cf < cl ? cf : cl);
438 Standard_Real uMax = (cf < cl ? cl : cf);
439 Standard_Real distmin;
440 if (C3D->IsKind(STANDARD_TYPE(Geom_BoundedCurve))) {
441 Standard_Real prec = ( AdjustToEnds ? preci : Precision::Confusion() ); //:j8 abv 10 Dec 98: tr10_r0501_db.stp #9423: protection against densing of points near one end
442 gp_Pnt LowBound = C3D->Value(uMin);
443 gp_Pnt HigBound = C3D->Value(uMax);
444 distmin = LowBound.Distance(P3D);
445 if (distmin <= prec) {
446 param = uMin;
447 proj = LowBound;
448 return distmin;
449 }
450 distmin = HigBound.Distance(P3D);
451 if (distmin <= prec) {
452 param = uMax;
453 proj = HigBound;
454 return distmin;
455 }
456 }
457
458 GeomAdaptor_Curve GAC(C3D, uMin, uMax);
459 if (!C3D->IsClosed()) {
460 //modified by rln on 16/12/97 after CSR# PRO11641 entity 20767
461 //the VIso was not closed (according to C3D->IsClosed()) while it "almost"
462 //was (the distance between ends of the curve was a little bit more than
463 //Precision::Confusion())
464 //in that case value 0.1 was too much and this method returned not correct parameter
465 //uMin = uMin - 0.1;
466 //uMax = uMax + 0.1;
467 // modified by pdn on 01.07.98 after BUC60195 entity 1952 (Min() added)
468 Standard_Real delta = Min (GAC.Resolution (preci), (uMax - uMin) * 0.1);
469 uMin -= delta;
470 uMax += delta;
471 GAC.Load(C3D, uMin, uMax);
472 }
473 return NextProject ( paramPrev, GAC, P3D, preci, proj, param );
474}
475
476//=======================================================================
477//function : NextProject
478//purpose :
479//=======================================================================
480
481Standard_Real ShapeAnalysis_Curve::NextProject(const Standard_Real paramPrev,
482 const Adaptor3d_Curve& C3D,
483 const gp_Pnt& P3D,
484 const Standard_Real preci,
485 gp_Pnt& proj,
486 Standard_Real& param) const
487{
488 Standard_Real uMin = C3D.FirstParameter();
489 Standard_Real uMax = C3D.LastParameter();
490
491 if (CurveNewton(paramPrev, C3D, P3D, preci, param, uMin, uMax)) {
492 C3D.D0(param, proj);
493 return P3D.Distance(proj);
494 }
495
496 return Project(C3D, P3D, preci, proj, param);
497}
498
499//=======================================================================
500//function : AdjustParameters
501//purpose : Copied from StepToTopoDS_GeometricTuul::UpdateParam3d (Aug 2001)
502//=======================================================================
503
504Standard_Boolean ShapeAnalysis_Curve::ValidateRange (const Handle(Geom_Curve)& theCurve,
505 Standard_Real& First, Standard_Real& Last,
506 const Standard_Real preci) const
507{
508 // First et/ou Last peuvent etre en dehors des bornes naturelles de la courbe.
509 // On donnera alors la valeur en bout a First et/ou Last
510
511 Standard_Real cf = theCurve->FirstParameter();
512 Standard_Real cl = theCurve->LastParameter();
513// Standard_Real preci = BRepAPI::Precision();
514
515 if (theCurve->IsKind(STANDARD_TYPE(Geom_BoundedCurve)) && !theCurve->IsClosed()) {
516 if (First < cf) {
517#ifdef DEBUG
518 cout << "Update Edge First Parameter to Curve First Parameter" << endl;
519#endif
520 First = cf;
521 }
522 else if (First > cl) {
523#ifdef DEBUG
524 cout << "Update Edge First Parameter to Curve Last Parameter" << endl;
525#endif
526 First = cl;
527 }
528 if (Last < cf) {
529#ifdef DEBUG
530 cout << "Update Edge Last Parameter to Curve First Parameter" << endl;
531#endif
532 Last = cf;
533 }
534 else if (Last > cl) {
535#ifdef DEBUG
536 cout << "Update Edge Last Parameter to Curve Last Parameter" << endl;
537#endif
538 Last = cl;
539 }
540 }
541
542 if (First < Last) return Standard_True;
543
544 // 15.11.2002 PTV OCC966
545 if (ShapeAnalysis_Curve::IsPeriodic(theCurve))
546 ElCLib::AdjustPeriodic(cf,cl,Precision::PConfusion(),First,Last); //:a7 abv 11 Feb 98: preci -> PConfusion()
547 else if (theCurve->IsClosed()) {
548 // l'un des points projecte se trouve sur l'origine du parametrage
549 // de la courbe 3D. L algo a donne cl +- preci au lieu de cf ou vice-versa
550 // DANGER precision 3d applique a une espace 1d
551
552 // Last = cf au lieu de Last = cl
553 if (Abs(Last - cf) < Precision::PConfusion() /*preci*/) Last = cl ;
554 // First = cl au lieu de First = cf
555 else if (Abs(First - cl) < Precision::PConfusion() /*preci*/) First = cf;
556
557 // on se trouve dans un cas ou l origine est traversee
558 // illegal sur une courbe fermee non periodique
559 // on inverse quand meme les parametres !!!!!!
560 else {
561 //:S4136 abv 20 Apr 99: r0701_ug.stp #6230: add check in 3d
562 if ( theCurve->Value(First).Distance(theCurve->Value(cf)) < preci ) First = cf;
563 if ( theCurve->Value(Last).Distance(theCurve->Value(cl)) < preci ) Last = cl;
564 if ( First > Last ) {
565#ifdef DEBUG
566 cout << "Warning : parameter range of edge crossing non periodic curve origin" << endl;
567#endif
568 Standard_Real tmp = First;
569 First = Last;
570 Last = tmp;
571 }
572 }
573 }
574 // The curve is closed within the 3D tolerance
575 else if (theCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
576 Handle(Geom_BSplineCurve) aBSpline =
577 Handle(Geom_BSplineCurve)::DownCast(theCurve);
578 if (aBSpline->StartPoint().Distance(aBSpline->EndPoint()) <= preci ) {
579//:S4136 <= BRepAPI::Precision()) {
580 // l'un des points projecte se trouve sur l'origine du parametrage
581 // de la courbe 3D. L algo a donne cl +- preci au lieu de cf ou vice-versa
582 // DANGER precision 3d applique a une espace 1d
583
584 // Last = cf au lieu de Last = cl
585 if (Abs(Last - cf) < Precision::PConfusion() /*preci*/) Last = cl ;
586 // First = cl au lieu de First = cf
587 else if (Abs(First - cl) < Precision::PConfusion() /*preci*/) First = cf;
588
589 // on se trouve dans un cas ou l origine est traversee
590 // illegal sur une courbe fermee non periodique
591 // on inverse quand meme les parametres !!!!!!
592 else {
593#ifdef DEBUG
594 cout << "Warning : parameter range of edge crossing non periodic curve origin" << endl;
595#endif
596 Standard_Real tmp = First;
597 First = Last;
598 Last = tmp;
599 }
600 }
601 //abv 15.03.00 #72 bm1_pe_t4 protection of exceptions in draw
602 else if ( First > Last ) {
603#ifdef DEBUG
604 cout << "Warning: parameter range is bad; curve reversed" << endl;
605#endif
606 First = theCurve->ReversedParameter ( First );
607 Last = theCurve->ReversedParameter ( Last );
608 theCurve->Reverse();
609 }
610//:j9 abv 11 Dec 98: PRO7747 #4875, after :j8: else
611 if (First == Last) { //gka 10.07.1998 file PRO7656 entity 33334
612 First = cf; Last = cl;
613 return Standard_False;
614 }
615 }
616 else {
617#ifdef DEBUG
618 cout << "UpdateParam3d Failed" << endl;
619 cout << " - Curve Type : " << theCurve->DynamicType() << endl;
620 cout << " - Param 1 : " << First << endl;
621 cout << " - Param 2 : " << Last << endl;
622#endif
623 //abv 15.03.00 #72 bm1_pe_t4 protection of exceptions in draw
624 if ( First > Last ) {
625#ifdef DEBUG
626 cout << "Warning: parameter range is bad; curve reversed" << endl;
627#endif
628 First = theCurve->ReversedParameter ( First );
629 Last = theCurve->ReversedParameter ( Last );
630 theCurve->Reverse();
631 }
632 //pdn 11.01.99 #144 bm1_pe_t4 protection of exceptions in draw
633 if (First == Last) {
634 First -= Precision::PConfusion();
635 Last += Precision::PConfusion();
636 }
637 return Standard_False;
638 }
639 return Standard_True;
640}
641
642//=======================================================================
643//function : FillBndBox
644//purpose : WORK-AROUND for methods brom BndLib which give not exact bounds
645//=======================================================================
646
647// search for extremum using Newton
648static Standard_Integer SearchForExtremum (const Handle(Geom2d_Curve)& C2d,
649 const Standard_Real First,
650 const Standard_Real Last,
651 const gp_Vec2d &dir,
652 Standard_Real &par,
653 gp_Pnt2d &res)
654{
655 Standard_Real prevpar;
656 for ( Standard_Integer i=0; i <10; i++ ) {
657 prevpar = par;
658
659 gp_Vec2d D1, D2;
660 C2d->D2 ( par, res, D1, D2 );
661 Standard_Real Det = ( D2 * dir );
662 if ( Abs ( Det ) < 1e-10 ) return Standard_True;
663
664 par -= ( D1 * dir ) / Det;
665 if ( Abs ( par - prevpar ) < Precision::PConfusion() ) return Standard_True;
666
667 if ( First - par >= Precision::PConfusion() ||
668 par - Last >= Precision::PConfusion() ) return Standard_False;
669 }
670 return Standard_True;
671}
672
673void ShapeAnalysis_Curve::FillBndBox (const Handle(Geom2d_Curve)& C2d,
674 const Standard_Real First,
675 const Standard_Real Last,
676 const Standard_Integer NPoints,
677 const Standard_Boolean Exact,
678 Bnd_Box2d &Box) const
679{
680 Standard_Integer nseg = ( NPoints <2 ? 1 : NPoints-1 );
681 Standard_Real step = ( Last - First ) / nseg;
682 for ( Standard_Integer i=0; i <= nseg; i++ ) {
683 Standard_Real par = First + i * step;
684 gp_Pnt2d pnt = C2d->Value ( par );
685 Box.Add ( pnt );
686 if ( ! Exact ) continue;
687
688 gp_Pnt2d pextr;
689 Standard_Real parextr = par;
690 if ( SearchForExtremum ( C2d, Max(First,par-2.*step), Min(Last,par+2.*step),
691 gp_Vec2d(1,0), parextr, pextr ) ) {
692 Box.Add ( pextr );
693 }
694 parextr = par;
695 if ( SearchForExtremum ( C2d, Max(First,par-2.*step), Min(Last,par+2.*step),
696 gp_Vec2d(0,1), parextr, pextr ) ) {
697 Box.Add ( pextr );
698 }
699 }
700}
701
702//=======================================================================
703//function : SelectForwardSeam
704//purpose :
705//=======================================================================
706
707Standard_Integer ShapeAnalysis_Curve::SelectForwardSeam(const Handle(Geom2d_Curve)& C1,
708 const Handle(Geom2d_Curve)& C2) const
709{
710 // SelectForward est destine a devenir un outil distinct
711 // Il est sans doute optimisable !
712
713 Standard_Integer theCurveIndice = 0;
714
715 Handle(Geom2d_Line) L1 = Handle(Geom2d_Line)::DownCast(C1);
716 if (L1.IsNull()) {
717 // if we have BoundedCurve, create a line from C1
718 Handle(Geom2d_BoundedCurve) BC1 = Handle(Geom2d_BoundedCurve)::DownCast(C1);
719 if (BC1.IsNull()) return theCurveIndice;
720 gp_Pnt2d StartBC1 = BC1->StartPoint();
721 gp_Pnt2d EndBC1 = BC1->EndPoint();
722 gp_Vec2d VecBC1(StartBC1, EndBC1);
723 L1 = new Geom2d_Line(StartBC1, VecBC1);
724 }
725
726 Handle(Geom2d_Line) L2 = Handle(Geom2d_Line)::DownCast(C2);
727 if (L2.IsNull()) {
728 // if we have BoundedCurve, creates a line from C2
729 Handle(Geom2d_BoundedCurve) BC2 = Handle(Geom2d_BoundedCurve)::DownCast(C2);
730 if (BC2.IsNull()) return theCurveIndice;
731 gp_Pnt2d StartBC2 = BC2->StartPoint();
732 gp_Pnt2d EndBC2 = BC2->EndPoint();
733 gp_Vec2d VecBC2(StartBC2, EndBC2);
734 L2 = new Geom2d_Line(StartBC2, VecBC2);
735 }
736
737 Standard_Boolean UdirPos, UdirNeg, VdirPos, VdirNeg;
738 UdirPos = UdirNeg = VdirPos = VdirNeg = Standard_False;
739
740 gp_Dir2d theDir = L1->Direction();
741 gp_Pnt2d theLoc1 = L1->Location();
742 gp_Pnt2d theLoc2 = L2->Location();
743
744 if (theDir.X() > 0.) {
745 UdirPos = Standard_True; //szv#4:S4163:12Mar99 Udir unused
746 } else if (theDir.X() < 0.) {
747 UdirNeg = Standard_True; //szv#4:S4163:12Mar99 Udir unused
748 } else if (theDir.Y() > 0.) {
749 VdirPos = Standard_True; //szv#4:S4163:12Mar99 Vdir unused
750 } else if (theDir.Y() < 0.) {
751 VdirNeg = Standard_True; //szv#4:S4163:12Mar99 Vdir unused
752 }
753
754 if (VdirPos) {
755 // max of Loc1.X() Loc2.X()
756 if (theLoc1.X() > theLoc2.X()) theCurveIndice = 1;
757 else theCurveIndice = 2;
758 } else if (VdirNeg) {
759 if (theLoc1.X() > theLoc2.X()) theCurveIndice = 2;
760 else theCurveIndice = 1;
761 } else if (UdirPos) {
762 // min of Loc1.X() Loc2.X()
763 if (theLoc1.Y() < theLoc2.Y()) theCurveIndice = 1;
764 else theCurveIndice = 2;
765 } else if (UdirNeg) {
766 if (theLoc1.Y() < theLoc2.Y()) theCurveIndice = 2;
767 else theCurveIndice = 1;
768 }
769
770 return theCurveIndice;
771}
772
773//%11 pdn 12.01.98
774//=============================================================================
775// Static methods for IsPlanar
776// IsPlanar
777//=============================================================================
778
779static gp_XYZ GetAnyNormal ( gp_XYZ orig )
780{
781 gp_XYZ Norm;
782 if ( Abs ( orig.Z() ) < Precision::Confusion() )
783 Norm.SetCoord ( 0, 0, 1 );
784 else {
785 Norm.SetCoord ( orig.Z(), 0, -orig.X() );
786 Standard_Real nrm = Norm.Modulus();
787 if ( nrm < Precision::Confusion() ) Norm.SetCoord ( 0, 0, 1 );
788 else Norm = Norm / nrm;
789 }
790 return Norm;
791}
792
793//=======================================================================
794//function : GetSamplePoints
795//purpose :
796//=======================================================================
797static void AppendControlPoles (TColgp_SequenceOfPnt& seq,
798 const Handle(Geom_Curve) curve)
799{
800 if ( curve->IsKind(STANDARD_TYPE(Geom_Line))) {
801 seq.Append(curve->Value(0));
802 seq.Append(curve->Value(1));
803 } else if ( curve->IsKind(STANDARD_TYPE(Geom_Conic))) {
804 seq.Append(curve->Value(0));
805 seq.Append(curve->Value(PI/2));
806 seq.Append(curve->Value(PI));
807 } else if ( curve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
808 //DeclareAndCast(Geom_TrimmedCurve, Trimmed, curve);
809 Handle(Geom_TrimmedCurve) Trimmed = *((Handle(Geom_TrimmedCurve) *) &curve);
810// AppendControlPoles(seq,Trimmed->BasisCurve());
811 Handle(Geom_Curve) aBaseCrv = Trimmed->BasisCurve();
812 Standard_Boolean done = Standard_False;
813 if ( aBaseCrv->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
814 try {
815 OCC_CATCH_SIGNALS
816 Handle(Geom_Geometry) Ctmp = aBaseCrv->Copy();
817 Handle(Geom_BSplineCurve) bslp = Handle(Geom_BSplineCurve)::DownCast(Ctmp);
818 bslp->Segment(curve->FirstParameter(), curve->LastParameter());
819 AppendControlPoles(seq,bslp);
820 done = Standard_True;
821 }
822 catch (Standard_Failure) {
823 }
824 }
825 else if ( aBaseCrv->IsKind(STANDARD_TYPE(Geom_BezierCurve))) {
826 try {
827 OCC_CATCH_SIGNALS
828 Handle(Geom_Geometry) Ctmp = aBaseCrv->Copy();
829 Handle(Geom_BezierCurve) bz = Handle(Geom_BezierCurve)::DownCast(Ctmp);
830 bz->Segment(curve->FirstParameter(), curve->LastParameter());
831 AppendControlPoles(seq,bz);
832 done = Standard_True;
833 }
834 catch (Standard_Failure) {
835 }
836 }
837 if (!done) {
838 seq.Append(curve->Value(curve->FirstParameter()));
839 seq.Append(curve->Value((curve->FirstParameter() + curve->LastParameter())/2.));
840 seq.Append(curve->Value(curve->LastParameter()));
841 }
842 } else if ( curve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) {
843 //DeclareAndCast(Geom_OffsetCurve, OffsetC, curve);
844 Handle(Geom_OffsetCurve) OffsetC = *((Handle(Geom_OffsetCurve) *) &curve);
845// AppendControlPoles(seq,OffsetC->BasisCurve());
846 seq.Append(curve->Value(curve->FirstParameter()));
847 seq.Append(curve->Value((curve->FirstParameter() + curve->LastParameter())/2.));
848 seq.Append(curve->Value(curve->LastParameter()));
849 } else if ( curve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
850 //DeclareAndCast(Geom_BSplineCurve, BSpline, curve);
851 Handle(Geom_BSplineCurve) BSpline = *((Handle(Geom_BSplineCurve) *) &curve);
852 TColgp_Array1OfPnt Poles(1,BSpline->NbPoles());
853 BSpline->Poles(Poles);
854 for(Standard_Integer i = 1; i <= BSpline->NbPoles(); i++)
855 seq.Append(Poles(i));
856 } else if ( curve->IsKind(STANDARD_TYPE(Geom_BezierCurve))) {
857 //DeclareAndCast(Geom_BezierCurve, Bezier, curve);
858 //Handle(Geom_BezierCurve) Bezier = Handle(Geom_BezierCurve)::DownCast(curve);
859 Handle(Geom_BezierCurve) Bezier = *((Handle(Geom_BezierCurve) *) &curve);
860 TColgp_Array1OfPnt Poles(1,Bezier->NbPoles());
861 Bezier->Poles(Poles);
862 for(Standard_Integer i = 1; i <= Bezier->NbPoles(); i++)
863 seq.Append(Poles(i));
864 }
865}
866
867//%11 pdn 12.01.98
868//szv modified
869//=======================================================================
870//function : IsPlanar
871//purpose : Detects if points lie in some plane and returns normal
872//=======================================================================
873
874Standard_Boolean ShapeAnalysis_Curve::IsPlanar (const TColgp_Array1OfPnt& pnts,
875 gp_XYZ& Normal,
876 const Standard_Real preci)
877{
878 Standard_Real precision = (preci > 0.0)? preci : Precision::Confusion();
879 Standard_Boolean noNorm = (Normal.SquareModulus() == 0);
880
881 if (pnts.Length() < 3) {
882 gp_XYZ N1 = pnts(1).XYZ()-pnts(2).XYZ();
883 if (noNorm) {
884 Normal = GetAnyNormal(N1);
885 return Standard_True;
886 }
887 return Abs(N1*Normal) < Precision::Confusion();
888 }
889
890 gp_XYZ aMaxDir;
891 if (noNorm) {
892 //define a center point
893 gp_XYZ aCenter(0,0,0);
894 Standard_Integer i = 1;
895 for (; i <= pnts.Length(); i++)
896 aCenter += pnts(i).XYZ();
897 aCenter/=pnts.Length();
898
899
900 aMaxDir = pnts(1).XYZ() - aCenter;
901 Normal = (pnts(pnts.Length()).XYZ() - aCenter) ^ aMaxDir;
902
903 for ( i = 1; i < pnts.Length(); i++) {
904 gp_XYZ aTmpDir = pnts(i+1).XYZ() - aCenter;
905 if(aTmpDir.SquareModulus() > aMaxDir.SquareModulus())
906 aMaxDir = aTmpDir;
907
908 gp_XYZ aDelta = (pnts(i).XYZ() - aCenter) ^ (pnts(i+1).XYZ() - aCenter);
909 if(Normal*aDelta < 0)
910 aDelta*=-1;
911 Normal += aDelta;
912 }
913 }
914
915 // check if points are linear
916 Standard_Real nrm = Normal.Modulus();
917 if ( nrm < Precision::Confusion() ) {
918 Normal = GetAnyNormal(aMaxDir);
919 return Standard_True;
920 }
921 Normal = Normal / nrm;
922
923 Standard_Real mind = RealLast(), maxd = -RealLast(), dev;
924 for (Standard_Integer i = 1; i <= pnts.Length(); i++) {
925 dev = pnts(i).XYZ() * Normal;
926 if (dev < mind) mind = dev;
927 if (dev > maxd) maxd = dev;
928 }
929
930 return ((maxd - mind) <= precision);
931}
932
933
934//=======================================================================
935//function : IsPlanar
936//purpose :
937//=======================================================================
938
939 Standard_Boolean ShapeAnalysis_Curve::IsPlanar (const Handle(Geom_Curve)& curve,
940 gp_XYZ& Normal,
941 const Standard_Real preci)
942{
943 Standard_Real precision = (preci > 0.0)? preci : Precision::Confusion();
944 Standard_Boolean noNorm = (Normal.SquareModulus() == 0);
945
946 if (curve->IsKind(STANDARD_TYPE(Geom_Line))) {
947 //DeclareAndCast(Geom_Line, Line, curve);
948 Handle(Geom_Line) Line = *((Handle(Geom_Line) *) &curve);
949 gp_XYZ N1 = Line->Position().Direction().XYZ();
950 if (noNorm) {
951 Normal = GetAnyNormal(N1);
952 return Standard_True;
953 }
954 return Abs(N1*Normal) < Precision::Confusion();
955 }
956
957 if (curve->IsKind(STANDARD_TYPE(Geom_Conic))) {
958 //DeclareAndCast(Geom_Conic, Conic, curve);
959 Handle(Geom_Conic) Conic = *((Handle(Geom_Conic) *) &curve);
960 gp_XYZ N1 = Conic->Axis().Direction().XYZ();
961 if (noNorm) {
962 Normal = N1;
963 return Standard_True;
964 }
965 gp_XYZ aVecMul = N1^Normal;
966 return aVecMul.SquareModulus() < Precision::Confusion()*Precision::Confusion();
967 }
968
969 if (curve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
970 //DeclareAndCast(Geom_TrimmedCurve, Trimmed, curve);
971 Handle(Geom_TrimmedCurve) Trimmed = *((Handle(Geom_TrimmedCurve) *) &curve);
972 return IsPlanar(Trimmed->BasisCurve(),Normal,precision);
973 }
974
975 if (curve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) {
976 //DeclareAndCast(Geom_OffsetCurve, OffsetC, curve);
977 Handle(Geom_OffsetCurve) OffsetC = *((Handle(Geom_OffsetCurve) *) &curve);
978 return IsPlanar(OffsetC->BasisCurve(),Normal,precision);
979 }
980
981 if (curve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
982 //DeclareAndCast(Geom_BSplineCurve, BSpline, curve);
983 Handle(Geom_BSplineCurve) BSpline = *((Handle(Geom_BSplineCurve) *) &curve);
984 TColgp_Array1OfPnt Poles(1,BSpline->NbPoles());
985 BSpline->Poles(Poles);
986 return IsPlanar(Poles,Normal,precision);
987 }
988
989 if (curve->IsKind(STANDARD_TYPE(Geom_BezierCurve))) {
990 //DeclareAndCast(Geom_BezierCurve, Bezier, curve);
991 Handle(Geom_BezierCurve) Bezier = *((Handle(Geom_BezierCurve) *) &curve);
992 TColgp_Array1OfPnt Poles(1,Bezier->NbPoles());
993 Bezier->Poles(Poles);
994 return IsPlanar(Poles,Normal,precision);
995 }
996
997 if (curve->IsKind(STANDARD_TYPE(ShapeExtend_ComplexCurve))) {
998 //DeclareAndCast(ShapeExtend_ComplexCurve, Complex, curve);
999 Handle(ShapeExtend_ComplexCurve) Complex = *((Handle(ShapeExtend_ComplexCurve) *) &curve);
1000 TColgp_SequenceOfPnt sequence;
1001 Standard_Integer i; // svv Jan11 2000 : porting on DEC
1002 for (i = 1; i <= Complex->NbCurves(); i++)
1003 AppendControlPoles(sequence,Complex->Curve(i));
1004 TColgp_Array1OfPnt Poles(1,sequence.Length());
1005 for (i=1; i <= sequence.Length(); i++) Poles(i) = sequence(i);
1006 return IsPlanar(Poles,Normal,precision);
1007 }
1008
1009 return Standard_False;
1010}
1011
1012//=======================================================================
1013//function : GetSamplePoints
1014//purpose :
1015//=======================================================================
1016
1017Standard_Boolean ShapeAnalysis_Curve::GetSamplePoints (const Handle(Geom_Curve)& curve,
1018 const Standard_Real first,
1019 const Standard_Real last,
1020 TColgp_SequenceOfPnt& seq)
1021{
1022 Standard_Real adelta = curve->LastParameter() - curve->FirstParameter();
1023 if(!adelta )
1024 return Standard_False;
1025
1026 Standard_Integer aK = (Standard_Integer)ceil ((last - first) / adelta);
1027 Standard_Integer nbp =100*aK;
1028 if(curve->IsKind(STANDARD_TYPE(Geom_Line)))
1029 nbp =2;
1030 else if(curve->IsKind(STANDARD_TYPE(Geom_Circle)))
1031 nbp =360*aK;
1032
1033 else if (curve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
1034 Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(curve);
1035
1036 nbp = aBspl->NbKnots() * aBspl->Degree()*aK;
1037 if(nbp < 2.0) nbp=2;
1038 }
1039 else if (curve->IsKind(STANDARD_TYPE(Geom_BezierCurve))) {
1040 Handle(Geom_BezierCurve) aB = Handle(Geom_BezierCurve)::DownCast(curve);
1041 nbp = 3 + aB->NbPoles();
1042 }
1043 else if(curve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) {
1044 Handle(Geom_OffsetCurve) aC = Handle(Geom_OffsetCurve)::DownCast(curve);
1045 return GetSamplePoints(aC->BasisCurve(),first,last,seq);
1046 }
1047 else if(curve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
1048 Handle(Geom_TrimmedCurve) aC = Handle(Geom_TrimmedCurve)::DownCast(curve);
1049 return GetSamplePoints(aC->BasisCurve(),first,last,seq);
1050 }
1051 Standard_Real step = ( last - first ) / (Standard_Real)( nbp - 1 );
1052 Standard_Real par = first, stop = last - 0.5 * step;
1053 for ( ; par < stop; par += step )
1054 seq.Append(curve->Value(par));
1055 seq.Append(curve->Value(last));
1056 return Standard_True;
1057}
1058//=======================================================================
1059//function : GetSamplePoints
1060//purpose :
1061//=======================================================================
1062
1063Standard_Boolean ShapeAnalysis_Curve::GetSamplePoints (const Handle(Geom2d_Curve)& curve,
1064 const Standard_Real first,
1065 const Standard_Real last,
1066 TColgp_SequenceOfPnt2d& seq)
1067{
1068 //:abv 05.06.02: TUBE.stp
1069 // Use the same distribution of points as BRepTopAdaptor_FClass2d for consistency
1070 Geom2dAdaptor_Curve C ( curve, first, last );
1071 Standard_Integer nbs = Geom2dInt_Geom2dCurveTool::NbSamples(C);
1072 //-- Attention aux bsplines rationnelles de degree 3. (bouts de cercles entre autres)
1073 if (nbs > 2) nbs*=4;
1074 Standard_Real step = ( last - first ) / (Standard_Real)( nbs - 1 );
1075 Standard_Real par = first, stop = last - 0.5 * step;
1076 for ( ; par < stop; par += step )
1077 seq.Append(curve->Value(par));
1078 seq.Append(curve->Value(last));
1079 return Standard_True;
1080/*
1081 Standard_Integer i;
1082 Standard_Real step;
1083 gp_Pnt2d Ptmp;
1084 if ( curve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
1085 seq.Append(curve->Value(first));
1086 seq.Append(curve->Value(last));
1087 return Standard_True;
1088 }
1089 else if(curve->IsKind(STANDARD_TYPE(Geom2d_Conic))) {
1090 step = Min ( PI, last-first ) / 19; //:abv 05.06.02 TUBE.stp #19209...: PI/16
1091// if( step>(last-first) ) {
1092// seq.Append(curve->Value(first));
1093// seq.Append(curve->Value((last+first)/2));
1094// seq.Append(curve->Value(last));
1095// return Standard_True;
1096// }
1097// else {
1098 Standard_Real par=first;
1099 for(i=0; par<last; i++) {
1100 seq.Append(curve->Value(par));
1101 par += step;
1102 }
1103 seq.Append(curve->Value(last));
1104 return Standard_True;
1105// }
1106 }
1107 else if ( curve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
1108 DeclareAndCast(Geom2d_TrimmedCurve, Trimmed, curve);
1109 return GetControlPoints(Trimmed->BasisCurve(), seq, first, last);
1110 }
1111 else if ( curve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
1112 DeclareAndCast(Geom2d_BSplineCurve, aBs, curve);
1113 TColStd_SequenceOfReal aSeqParam;
1114 if(!aBs.IsNull()) {
1115 aSeqParam.Append(first);
1116 for(i=1; i<=aBs->NbKnots(); i++) {
1117 if( aBs->Knot(i)>first && aBs->Knot(i)<last )
1118 aSeqParam.Append(aBs->Knot(i));
1119 }
1120 aSeqParam.Append(last);
1121 Standard_Integer NbPoints=aBs->Degree();
1122 if( (aSeqParam.Length()-1)*NbPoints>10 ) {
1123 for(i=1; i<aSeqParam.Length(); i++) {
1124 Standard_Real FirstPar = aSeqParam.Value(i);
1125 Standard_Real LastPar = aSeqParam.Value(i+1);
1126 step = (LastPar-FirstPar)/NbPoints;
1127 for(Standard_Integer k=0; k<NbPoints; k++ ) {
1128 aBs->D0(FirstPar+step*k, Ptmp);
1129 seq.Append(Ptmp);
1130 }
1131 }
1132 aBs->D0(last, Ptmp);
1133 seq.Append(Ptmp);
1134 return Standard_True;
1135 }
1136 else {
1137 step = (last-first)/10;
1138 for(Standard_Integer k=0; k<=10; k++ ) {
1139 aBs->D0(first+step*k, Ptmp);
1140 seq.Append(Ptmp);
1141 }
1142 return Standard_True;
1143 }
1144 }
1145 }
1146 else if ( curve->IsKind(STANDARD_TYPE(Geom2d_BezierCurve))) {
1147 DeclareAndCast(Geom2d_BezierCurve, aBz, curve);
1148 if(!aBz.IsNull()) {
1149 Standard_Integer NbPoints=aBz->Degree();
1150 step = (last-first)/NbPoints;
1151 for(Standard_Integer k=0; k<NbPoints; k++ ) {
1152 aBz->D0(first+step*k, Ptmp);
1153 seq.Append(Ptmp);
1154 }
1155 aBz->D0(last, Ptmp);
1156 seq.Append(Ptmp);
1157 return Standard_True;
1158 }
1159 }
1160 return Standard_False;
1161*/
1162}
1163
1164//=======================================================================
1165//function : IsClosed
1166//purpose :
1167//=======================================================================
1168
1169Standard_Boolean ShapeAnalysis_Curve::IsClosed(const Handle(Geom_Curve)& theCurve,
1170 const Standard_Real preci)
1171{
1172 if (theCurve->IsClosed())
1173 return Standard_True;
1174
1175 Standard_Real prec = Max (preci, Precision::Confusion());
1176
1177 Standard_Real f, l;
1178 f = theCurve->FirstParameter();
1179 l = theCurve->LastParameter();
1180
1181 if (Precision::IsInfinite (f) || Precision::IsInfinite (l))
1182 return Standard_False;
1183
1184 Standard_Real aClosedVal = theCurve->Value(f).SquareDistance(theCurve->Value(l));
1185 Standard_Real preci2 = prec*prec;
1186
1187 return (aClosedVal <= preci2);
1188}
1189//=======================================================================
1190//function : IsPeriodic
1191//purpose : OCC996
1192//=======================================================================
1193
1194Standard_Boolean ShapeAnalysis_Curve::IsPeriodic(const Handle(Geom_Curve)& theCurve)
1195{
1196 // 15.11.2002 PTV OCC966
1197 // remove regressions in DE tests (diva, divb, divc, toe3) in KAS:dev
1198 // ask IsPeriodic on BasisCurve
1199 Handle(Geom_Curve) aTmpCurve = theCurve;
1200 while ( (aTmpCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) ||
1201 (aTmpCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) ) {
1202 if (aTmpCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
1203 aTmpCurve = Handle(Geom_OffsetCurve)::DownCast(aTmpCurve)->BasisCurve();
1204 if (aTmpCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
1205 aTmpCurve = Handle(Geom_TrimmedCurve)::DownCast(aTmpCurve)->BasisCurve();
1206 }
1207 return aTmpCurve->IsPeriodic();
1208}
1209
1210Standard_Boolean ShapeAnalysis_Curve::IsPeriodic(const Handle(Geom2d_Curve)& theCurve)
1211{
1212 // 15.11.2002 PTV OCC966
1213 // remove regressions in DE tests (diva, divb, divc, toe3) in KAS:dev
1214 // ask IsPeriodic on BasisCurve
1215 Handle(Geom2d_Curve) aTmpCurve = theCurve;
1216 while ( (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))) ||
1217 (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) ) {
1218 if (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
1219 aTmpCurve = Handle(Geom2d_OffsetCurve)::DownCast(aTmpCurve)->BasisCurve();
1220 if (aTmpCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1221 aTmpCurve = Handle(Geom2d_TrimmedCurve)::DownCast(aTmpCurve)->BasisCurve();
1222 }
1223 return aTmpCurve->IsPeriodic();
1224}