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