0026937: Eliminate NO_CXX_EXCEPTION macro support
[occt.git] / src / ShapeFix / ShapeFix_EdgeProjAux.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 //:r5 abv 06.04.99: ec_turbine-A.stp, #4313: protect against null curve
15 //    abv 09.04.99  S4136: add parameter preci (to eliminate BRepAPI::Precision)
16
17 #include <Adaptor3d_CurveOnSurface.hxx>
18 #include <BRep_Tool.hxx>
19 #include <ElCLib.hxx>
20 #include <Extrema_ExtPC.hxx>
21 #include <Geom2d_BoundedCurve.hxx>
22 #include <Geom2d_BSplineCurve.hxx>
23 #include <Geom2d_Curve.hxx>
24 #include <Geom2d_Line.hxx>
25 #include <Geom2dAdaptor_Curve.hxx>
26 #include <Geom2dAdaptor_HCurve.hxx>
27 #include <Geom_Curve.hxx>
28 #include <Geom_SphericalSurface.hxx>
29 #include <Geom_Surface.hxx>
30 #include <GeomAdaptor_HSurface.hxx>
31 #include <GeomAdaptor_Surface.hxx>
32 #include <gp_Pnt.hxx>
33 #include <Precision.hxx>
34 #include <ShapeAnalysis.hxx>
35 #include <ShapeAnalysis_Curve.hxx>
36 #include <ShapeAnalysis_Edge.hxx>
37 #include <ShapeAnalysis_Surface.hxx>
38 #include <ShapeFix_EdgeProjAux.hxx>
39 #include <Standard_ErrorHandler.hxx>
40 #include <Standard_Failure.hxx>
41 #include <Standard_Type.hxx>
42 #include <TopExp.hxx>
43 #include <TopoDS_Edge.hxx>
44 #include <TopoDS_Face.hxx>
45 #include <TopoDS_Vertex.hxx>
46 #include <Adaptor3d_HCurve.hxx>
47 #include <BSplCLib.hxx>
48
49 IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_EdgeProjAux,MMgt_TShared)
50
51 //=======================================================================
52 //function : ShapeFix_EdgeProjAux
53 //purpose  : 
54 //=======================================================================
55 ShapeFix_EdgeProjAux::ShapeFix_EdgeProjAux ()
56 {
57   myFirstDone = myLastDone = Standard_False;
58 }
59
60 //=======================================================================
61 //function : ShapeFix_EdgeProjAux
62 //purpose  : 
63 //=======================================================================
64
65 ShapeFix_EdgeProjAux::ShapeFix_EdgeProjAux (const TopoDS_Face& F,
66                                             const TopoDS_Edge& E)
67 {
68   Init (F, E);
69 }
70
71 //=======================================================================
72 //function : Init
73 //purpose  : 
74 //=======================================================================
75
76 void ShapeFix_EdgeProjAux::Init (const TopoDS_Face& F,
77                                  const TopoDS_Edge& E)
78 {
79   myFace = F;
80   myEdge = E;
81   myFirstParam = myLastParam = 0.;
82   myFirstDone = myLastDone = Standard_False;
83 }
84
85 //=======================================================================
86 //function : Compute
87 //purpose  : 
88 //=======================================================================
89
90 void ShapeFix_EdgeProjAux::Compute (const Standard_Real preci) 
91 {
92   myFirstDone = myLastDone = Standard_False;
93     
94   // Project Point3d on Surface
95   // TEMPORARY Call ShapeFix_EdgeProjAux
96   myFirstParam = 0.;
97   myLastParam = 0.;
98   Init2d(preci);
99   if (IsFirstDone() && IsLastDone()) {
100     Standard_Real U1 = FirstParam();
101     Standard_Real U2 = LastParam();
102     if (U1>=U2) {
103 #ifdef OCCT_DEBUG
104       cout << "Parametres inverses ... " << endl;
105 #endif
106       Standard_Real tmp = U1;
107       U1 = U2; U2 = tmp;
108     }
109     myFirstParam = U1;
110     myFirstDone  = Standard_True;
111     myLastParam  = U2;
112     myLastDone   = Standard_True;
113   }
114 }
115
116 //=======================================================================
117 //function : IsFirstDone
118 //purpose  : 
119 //=======================================================================
120
121 Standard_Boolean ShapeFix_EdgeProjAux::IsFirstDone() const
122 {
123   return myFirstDone;
124 }
125
126 //=======================================================================
127 //function : IsLastDone
128 //purpose  : 
129 //=======================================================================
130
131 Standard_Boolean ShapeFix_EdgeProjAux::IsLastDone() const
132 {
133   return myLastDone;
134 }
135
136 //=======================================================================
137 //function : FirstParam
138 //purpose  : 
139 //=======================================================================
140
141 Standard_Real ShapeFix_EdgeProjAux::FirstParam() const
142 {
143   return myFirstParam;
144 }
145
146 //=======================================================================
147 //function : LastParam
148 //purpose  : 
149 //=======================================================================
150
151 Standard_Real ShapeFix_EdgeProjAux::LastParam() const
152 {
153   return myLastParam;
154 }
155
156 //=======================================================================
157 //function : IsIso
158 //purpose  : 
159 //=======================================================================
160
161 Standard_Boolean ShapeFix_EdgeProjAux::IsIso (const Handle(Geom2d_Curve)& /*theCurve2d*/)
162 {
163   // Until an ISO is recognized by Adaptor3d_Curve
164 /*  
165   if (theCurve2d->IsKind(STANDARD_TYPE(Geom2d_Line))) {
166     Handle(Geom2d_Line) theLine2d = Handle(Geom2d_Line)::DownCast(theCurve2d);
167     gp_Dir2d theDir2d = theLine2d->Direction();
168     
169     gp_Dir2d dir1(0.,1.);
170     gp_Dir2d dir2(0.,-1.);
171     
172     return (theDir2d.IsEqual(dir1,Precision::Angular()) ||
173             theDir2d.IsEqual(dir2,Precision::Angular()) ||
174             theDir2d.IsNormal(dir1,Precision::Angular()) ||
175             theDir2d.IsNormal(dir2,Precision::Angular()) );
176   }
177 */
178   return Standard_False;
179 }
180
181 // ----------------------------------------------------------------------------
182 // static  : FindParameterWithExt
183 // Purpose : Computes the trimming parameter of Pt1 on COnS
184 // ----------------------------------------------------------------------------
185
186 static Standard_Boolean FindParameterWithExt (const gp_Pnt& Pt1, 
187                                               const Adaptor3d_CurveOnSurface& COnS,
188                                               const Standard_Real Uinf,
189                                               const Standard_Real Usup, 
190                                               const Standard_Real preci,
191                                               Standard_Real& w1)
192 {
193   try {  // et allez donc !
194     OCC_CATCH_SIGNALS
195     Extrema_ExtPC myExtPC (Pt1, COnS, Uinf, Usup, preci);
196
197     //ShapeFix_ExtPCOnS myExtPCOnS1 = 
198     //ShapeFix_ExtPCOnS(Pt1, COnS, Uinf, Usup, preci);
199   
200     if (myExtPC.IsDone()) {
201       Standard_Integer NbExt1 = myExtPC.NbExt();
202       for (Standard_Integer i=1; i<=NbExt1; i++) {
203         if (myExtPC.IsMin(i)) {
204           //Standard_Real dist = myExtPC.Value(i); //szv#4:S4163:12Mar99 debug mode only
205           w1   = myExtPC.Point(i).Parameter();
206         }
207       }
208       return Standard_True;
209     }
210     else return Standard_False;
211   }  // end try
212   catch(Standard_Failure const& anException) {
213 #ifdef OCCT_DEBUG
214 //:s5
215     cout << "Warning: ShapeFix_EdgeProjAux, FindParameterWithExt(): Exception: ";
216     anException.Print(cout); cout << endl;
217 #endif
218     (void)anException;
219     return Standard_False;
220   }
221 }
222
223 //=======================================================================
224 //function : Init2d
225 //purpose  : 
226 //=======================================================================
227
228 void ShapeFix_EdgeProjAux::Init2d (const Standard_Real preci) 
229 {
230   Standard_Real cl = 0., cf = 0.;
231     // Extract Geometries
232   myFirstDone = myLastDone = Standard_False;
233   Handle(Geom_Surface) theSurface = BRep_Tool::Surface(myFace);
234   Handle(Geom2d_Curve) theCurve2d = BRep_Tool::CurveOnSurface(myEdge, myFace, cf, cl);
235   if ( theCurve2d.IsNull() ) return; //:r5 abv 6 Apr 99:  ec_turbine-A.stp, #4313
236   myFirstParam = 0.;
237   myLastParam  = 0.;
238   TopoDS_Vertex V1,V2;
239   TopExp::Vertices(myEdge, V1, V2);
240   gp_Pnt Pt1,Pt2;
241   // pdn 28.12.98: r_39-db.stp #605: use ends of 3d curve instead of vertices 
242   ShapeAnalysis_Edge sae;
243   Standard_Real a,b;
244   Handle(Geom_Curve) C3d;
245   if(sae.Curve3d(myEdge,C3d,a,b,Standard_False)) {
246     Pt1 = C3d->Value(a);
247     Pt2 = C3d->Value(b);
248   } 
249   else {
250     Pt1 = BRep_Tool::Pnt(V1);
251     Pt2 = BRep_Tool::Pnt(V2);
252   }
253   //:S4136  Standard_Real preci = BRepAPI::Precision();
254   //pdn to manage degenerated case
255   if (V1.IsSame(V2)) {
256     Handle(ShapeAnalysis_Surface) stsu = new ShapeAnalysis_Surface (theSurface);
257     gp_Pnt2d aPt1,aPt2;
258     Standard_Real firstpar,lastpar;
259     if (stsu->DegeneratedValues(Pt1,preci,aPt1,aPt2,firstpar,lastpar)){
260
261       if(theCurve2d->IsKind(STANDARD_TYPE(Geom2d_Line))) {
262         if (aPt1.IsEqual(theCurve2d->Value(firstpar),preci) && 
263           aPt2.IsEqual(theCurve2d->Value(lastpar),preci)){
264             myFirstParam = firstpar;
265             myLastParam  = lastpar;
266             myFirstDone = myLastDone = Standard_True;
267             return;
268         }
269       } 
270 #ifdef OCCT_DEBUG
271       else cout <<"Other type of deg curve"<<endl;
272 #endif
273
274     }
275   }
276
277   Standard_Boolean parU = Standard_False, parV = Standard_False;
278   GeomAdaptor_Surface          SA     = GeomAdaptor_Surface(theSurface);
279   Handle(GeomAdaptor_HSurface) myHSur = new GeomAdaptor_HSurface(SA);
280
281   cf = theCurve2d->FirstParameter();
282   cl = theCurve2d->LastParameter();
283   //pdn cutting pcurve by suface bounds
284   if (Precision::IsInfinite(cf)||Precision::IsInfinite(cl)) {
285     if(theCurve2d->IsKind(STANDARD_TYPE(Geom2d_Line))) {
286       Standard_Real uf,ul,vf,vl;
287       theSurface->Bounds(uf,ul,vf,vl);
288       //Correct surface limits for extrusion/revolution surfaces based on hyperbola
289       //23 is ln(1.0e+10)
290       if(SA.GetType() == GeomAbs_SurfaceOfExtrusion)
291       {
292         if(SA.BasisCurve()->GetType() == GeomAbs_Hyperbola)
293         {
294           uf = Max(uf, -23.);
295           ul = Min(ul,  23.);
296         }
297       }
298       if(SA.GetType() == GeomAbs_SurfaceOfRevolution)
299       {
300         if(SA.BasisCurve()->GetType() == GeomAbs_Hyperbola)
301         {
302           vf = Max(vf, -23.);
303           vl = Min(vl,  23.);
304         }
305       }
306       if(!Precision::IsInfinite(uf)&&!Precision::IsInfinite(ul)&&
307          !Precision::IsInfinite(vf)&&!Precision::IsInfinite(vl)) {
308           Standard_Real cfi,cli;
309           Handle(Geom2d_Line) lin = Handle(Geom2d_Line)::DownCast(theCurve2d);
310           gp_Pnt2d pnt = lin->Location();
311           gp_Dir2d dir = lin->Direction();
312           if (dir.Y()==0) {
313             parU = Standard_True;
314             cfi = (uf-pnt.X())/dir.X();
315             cli = (ul-pnt.X())/dir.X();
316           } 
317           else if (dir.X()==0) {
318             parV = Standard_True;
319             cfi = (vf-pnt.Y())/dir.Y();
320             cli = (vl-pnt.Y())/dir.Y();
321           } 
322           else {//common case
323             Standard_Real xfi, xli, yfi, yli;
324             xfi = (uf-pnt.X())/dir.X();
325             xli = (ul-pnt.X())/dir.X();
326             yfi = (vf-pnt.Y())/dir.Y();
327             yli = (vl-pnt.Y())/dir.Y();
328             if (dir.X()*dir.Y() > 0) {
329               cfi = (Abs(xli-xfi) < Abs(xli-yfi)? xfi : yfi);
330               cli = (Abs(xfi-xli) < Abs(xfi-yli)? xli : yli);
331             } else {
332               cfi = (Abs(xli-xfi) < Abs(xli-yli)? xfi : yli);
333               cli = (Abs(yli-xli) < Abs(yli-yfi)? xli : yfi);
334             }
335           }
336           if (cfi < cli) { cf = cfi; cl = cli; }
337           else { cf = cli; cl = cfi; }
338       } 
339       else if(!Precision::IsInfinite(uf)&&!Precision::IsInfinite(ul)){
340         Handle(Geom2d_Line) lin = Handle(Geom2d_Line)::DownCast(theCurve2d);
341         gp_Dir2d dir = lin->Direction();
342         if (dir.X()!=0) {
343           if (dir.Y()==0) parU = Standard_True;
344           gp_Pnt2d pnt = lin->Location(); //szv#4:S4163:12Mar99 moved
345           Standard_Real cfi = (uf-pnt.X())/dir.X();
346           Standard_Real cli = (ul-pnt.X())/dir.X();
347           if (cfi < cli) { cf = cfi; cl = cli; }
348           else { cf = cli; cl = cfi; }
349         }
350         else {
351           cf=-10000;
352           cl= 10000;
353         }
354       }
355       else {
356         cf=-10000;
357         cl= 10000;
358         //pdn not cutted by bounds
359 #ifdef OCCT_DEBUG
360         cout<<"Infinite Surface"<<endl;
361 #endif  
362       }
363     }
364     else {
365       //pdn not linear case not managed
366       cf=-10000;
367       cl= 10000;
368       if(theCurve2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)))
369       {
370         //Try to reparametrize (CASE dxf read bug25899)
371         Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(theCurve2d->Copy());
372         TColStd_Array1OfReal aNewKnots(1, aBspl->NbKnots());  
373         aBspl->Knots(aNewKnots);
374         BSplCLib::Reparametrize(cf, cl, aNewKnots);
375         aBspl->SetKnots(aNewKnots);
376         theCurve2d = aBspl;
377       }
378
379 #ifdef OCCT_DEBUG
380       cout<<"Some infinite curve"<<endl;
381 #endif 
382     }
383   }
384
385   Geom2dAdaptor_Curve          CA     = Geom2dAdaptor_Curve(theCurve2d,cf,cl);
386   Handle(Geom2dAdaptor_HCurve) myHCur = new Geom2dAdaptor_HCurve(CA);
387
388   Adaptor3d_CurveOnSurface COnS = Adaptor3d_CurveOnSurface(myHCur, myHSur);
389
390   // ----------------------------------------------
391   // --- topological limit == geometric limit ? ---
392   // ----------------------------------------------
393   Standard_Real Uinf = COnS.FirstParameter();
394   Standard_Real Usup = COnS.LastParameter();
395  
396   Standard_Real w1 = 0., w2 = 0.;
397   ShapeAnalysis_Curve sac;
398   gp_Pnt pnt;
399   Standard_Real dist = sac.Project(COnS,Pt1,preci,pnt,w1,Standard_False);
400   //if distance is infinite then projection is not performed
401   if( Precision::IsInfinite(dist))
402     return;
403   
404   myFirstDone = Standard_True;
405   myFirstParam = w1;
406  
407   dist = sac.Project(COnS,Pt2,preci,pnt,w2,Standard_False);
408   
409   if( Precision::IsInfinite(dist))
410     return;
411   
412   myLastDone = Standard_True;
413   myLastParam  = w2;
414     
415   if(fabs(w1 - w2) < Precision::PConfusion())
416   {
417     if(!theSurface->IsUPeriodic() && !theSurface->IsVPeriodic())
418       return;
419   }
420     
421   if ( myFirstParam == Uinf && myLastParam == Usup ) return;
422   if ( myFirstParam == Usup && myLastParam == Uinf ) {
423     myFirstParam = theCurve2d->ReversedParameter(Usup);
424     myLastParam  = theCurve2d->ReversedParameter(Uinf);
425     theCurve2d->Reverse();
426 #ifdef OCCT_DEBUG
427     cout << "Warning: ShapeFix_EdgeProjAux: pcurve reversed" << endl;
428 #endif
429     return;
430   }
431   //:abv 29.08.01: SAT: fix for closed case
432   if ( COnS.Value(Uinf).Distance ( COnS.Value(Usup) ) < Precision::Confusion() ) {
433     // 18.11.2002 SKL OCC630 compare values with tolerance Precision::PConfusion() instead of "=="
434     if ( Abs(myFirstParam-Uinf) < ::Precision::PConfusion() &&
435       Abs(myLastParam-Uinf) < ::Precision::PConfusion() )
436       myLastParam = w2 = Usup;
437     // 18.11.2002 SKL OCC630 compare values with tolerance Precision::PConfusion() instead of "=="
438     else if ( Abs(myFirstParam-Usup) < ::Precision::PConfusion() && 
439       Abs(myLastParam-Usup) < ::Precision::PConfusion() )
440       myFirstParam = w1 = Uinf;
441   }
442
443   //pdn adjust parameters in periodic case
444   if(parU || parV) {
445     Standard_Real uf,ul,vf,vl;
446     theSurface->Bounds(uf,ul,vf,vl);
447     Standard_Real period = (parU ? ul-uf : vl-vf);
448     w1+=ShapeAnalysis::AdjustToPeriod(w1,0,period);
449     myFirstParam = w1;
450     w2+=ShapeAnalysis::AdjustToPeriod(w2,0,period);
451     myLastParam = w2;
452     Handle(Geom_Curve) C3d1;
453     if(!sae.Curve3d (myEdge, C3d1, cf, cl, Standard_False )) {
454       UpdateParam2d(theCurve2d);
455       return;
456     }
457     gp_Pnt mid = C3d1->Value((cf+cl)/2);
458     Standard_Real wmid;
459     sac.Project(COnS,mid,preci,pnt,wmid,Standard_False);
460     wmid+=ShapeAnalysis::AdjustToPeriod(wmid,0,period);
461     if(w1>=w2) {
462       if(w2 > wmid) myFirstParam -= period;
463       else if (w1 > wmid)
464         UpdateParam2d(theCurve2d);
465       else {
466         myLastParam+=period;
467 #ifdef OCCT_DEBUG
468         cout <<" Added"<<endl;
469 #endif  
470       }
471     }
472     else {
473       if(w1 > wmid) {
474         myLastParam -=period;
475         UpdateParam2d(theCurve2d);
476 #ifdef OCCT_DEBUG
477         cout <<" Added & Inverted"<<endl;
478 #endif  
479       } else if (w2 < wmid) {
480         myFirstParam += period;
481         UpdateParam2d(theCurve2d);
482       }
483     }
484   }
485   UpdateParam2d(theCurve2d);
486   return;
487 }
488
489 //=======================================================================
490 //function : Init3d
491 //purpose  : 
492 //=======================================================================
493
494 void ShapeFix_EdgeProjAux::Init3d (const Standard_Real preci) 
495 {
496   Standard_Real cl, cf;
497
498   // Extract Geometries
499   Handle(Geom_Surface) theSurface = BRep_Tool::Surface(myFace);
500   Handle(Geom2d_Curve) theCurve2d = BRep_Tool::CurveOnSurface(myEdge, myFace, cf, cl);
501   if ( theCurve2d.IsNull() ) return; //:r5 abv 6 Apr 99:  ec_turbine-A.stp, #4313
502   TopoDS_Vertex V1,V2;
503
504   V1 = TopExp::FirstVertex(myEdge);
505   V2 = TopExp::LastVertex(myEdge);
506   gp_Pnt Pt1 = BRep_Tool::Pnt(V1);
507   gp_Pnt Pt2 = BRep_Tool::Pnt(V2);
508
509
510   GeomAdaptor_Surface          SA     = GeomAdaptor_Surface(theSurface);  
511   Handle(GeomAdaptor_HSurface) myHSur = new GeomAdaptor_HSurface(SA);
512
513   Geom2dAdaptor_Curve          CA     = Geom2dAdaptor_Curve(theCurve2d);
514   Handle(Geom2dAdaptor_HCurve) myHCur = new Geom2dAdaptor_HCurve(CA);
515
516   Adaptor3d_CurveOnSurface COnS = Adaptor3d_CurveOnSurface(myHCur, myHSur);
517   
518 //:S4136  Standard_Real preci = BRepAPI::Precision();
519   Standard_Real Uinf = theCurve2d->FirstParameter();
520   Standard_Real Usup = theCurve2d->LastParameter();
521
522   // ----------------------------------------------
523   // --- topological limit == geometric limit ? ---
524   // ----------------------------------------------
525   
526   if (theCurve2d->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve))) {
527     
528     gp_Pnt Pdeb = COnS.Value(Uinf);
529     gp_Pnt Pfin = COnS.Value(Usup);
530     
531     //szv#4:S4163:12Mar99 optimized
532     if ( Pdeb.IsEqual(Pt1, preci) && Pfin.IsEqual(Pt2, preci) ) {
533       myFirstParam = Uinf;
534       myLastParam  = Usup;
535       myFirstDone = myLastDone = Standard_True;
536       return;
537     }
538   }
539
540   // ------------------------------------------
541   // --- The CurveOnSurface is not infinite ---
542   // ---          Try with Extrema          ---
543   // ------------------------------------------
544
545   Standard_Real w1 = COnS.FirstParameter();
546   Standard_Real w2 = COnS.LastParameter();
547
548   if ((!Precision::IsInfinite(w1) &&
549        !Precision::IsInfinite(w2) &&
550        theCurve2d->Continuity() != GeomAbs_C0) ||
551       IsIso(theCurve2d))  {
552
553     //szv#4:S4163:12Mar99 optimized
554     if ( FindParameterWithExt(Pt1, COnS, Uinf, Usup, preci, w1) &&
555          FindParameterWithExt(Pt2, COnS, Uinf, Usup, preci, w2) ) {
556       myFirstParam = w1;
557       myLastParam  = w2;
558       UpdateParam2d(theCurve2d);
559       myFirstDone = myLastDone = Standard_True;
560       return;
561     }
562   }
563   myFirstDone = myLastDone = Standard_True;
564 }
565
566 //=======================================================================
567 //function : UpdateParam2d
568 //purpose  : 
569 //=======================================================================
570
571 void ShapeFix_EdgeProjAux::UpdateParam2d (const Handle(Geom2d_Curve)& theCurve2d)
572 {
573   if (myFirstParam < myLastParam)  return;
574
575   Standard_Real cf = theCurve2d->FirstParameter();
576   Standard_Real cl = theCurve2d->LastParameter();
577 //:S4136  Standard_Real preci = BRepAPI::Precision();
578   Standard_Real preci2d = Precision::PConfusion(); //:S4136: Parametric(preci, 0.01);
579
580   // 15.11.2002 PTV OCC966
581   if (ShapeAnalysis_Curve::IsPeriodic(theCurve2d)) {
582     ElCLib::AdjustPeriodic(cf,cl,preci2d,myFirstParam,myLastParam);
583   }
584   else if (theCurve2d->IsClosed()) {
585     //szv#4:S4163:12Mar99 optimized
586     if      ( Abs ( myFirstParam - cl ) <= preci2d ) myFirstParam = cf;
587     else if ( Abs ( myLastParam  - cf ) <= preci2d ) myLastParam  = cl;
588     else {
589 #ifdef OCCT_DEBUG
590       cout << "Error : curve 2d range crossing non periodic curve origin";
591       cout <<  endl;
592 #endif
593       // add fail result;
594       return;
595     }
596   }
597   // the curve is closed within the 'file' 2D tolerance 
598   else if (theCurve2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
599     Handle(Geom2d_BSplineCurve) aBSpline2d =
600       Handle(Geom2d_BSplineCurve)::DownCast(theCurve2d);
601     if (aBSpline2d->StartPoint().Distance(aBSpline2d->EndPoint()) <= preci2d) {
602       if      ( Abs ( myFirstParam - cl ) <= preci2d ) myFirstParam = cf;
603       else if ( Abs ( myLastParam  - cf ) <= preci2d ) myLastParam  = cl;
604     }
605   }
606   else {
607 #ifdef OCCT_DEBUG
608     cout << "Warning : non increasing parameters for 2d curve." << endl;
609     cout << "          update parameter 2d uncertain." << endl;
610 #endif
611     Standard_Real tmp1 = myFirstParam, tmp2 = myLastParam;
612     myFirstParam = theCurve2d->ReversedParameter(tmp1);
613     myLastParam = theCurve2d->ReversedParameter(tmp2);
614     theCurve2d->Reverse();
615     //cout<<"Reversed case 2"<<endl;
616   }
617 }