0025892: Wrong result obtained by projection algorithm.
[occt.git] / src / ProjLib / ProjLib_ProjectedCurve.cxx
1 // Created on: 1993-08-25
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 //  Modified by skv - Wed Aug 11 15:45:58 2004 OCC6272
18
19 #include <GeomAbs_SurfaceType.hxx>
20 #include <Standard_NoSuchObject.hxx>
21 #include <Standard_NotImplemented.hxx>
22 #include <ProjLib_ProjectedCurve.hxx>
23 #include <ProjLib_CompProjectedCurve.hxx>
24 #include <ProjLib_HCompProjectedCurve.hxx>
25 #include <ProjLib_ComputeApproxOnPolarSurface.hxx>
26 #include <ProjLib_ComputeApprox.hxx>
27 #include <ProjLib_Projector.hxx>
28 #include <Adaptor3d_HCurve.hxx>
29 #include <Adaptor3d_HSurface.hxx>
30 #include <Approx_CurveOnSurface.hxx>
31 #include <ProjLib_Plane.hxx>
32 #include <ProjLib_Cylinder.hxx>
33 #include <ProjLib_Cone.hxx>
34 #include <ProjLib_Sphere.hxx>
35 #include <ProjLib_Torus.hxx>
36 #include <Precision.hxx>
37 #include <Geom2d_BSplineCurve.hxx>
38 #include <Geom2d_BezierCurve.hxx>
39 #include <gp_Vec2d.hxx>
40 #include <StdFail_NotDone.hxx>
41 #include <gp_XY.hxx>
42 #include <TColgp_HArray1OfPnt2d.hxx>
43 #include <TColStd_HArray1OfReal.hxx>
44 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
45 #include <TColStd_Array1OfReal.hxx>
46 #include <TColStd_Array1OfInteger.hxx>
47 #include <TColgp_Array1OfPnt2d.hxx>
48 #include <TColgp_HArray1OfVec2d.hxx>
49 #include <TColStd_HArray1OfBoolean.hxx>
50 #include <BSplCLib.hxx>
51 #include <GeomAbs_IsoType.hxx>
52 #include <Geom2d_Line.hxx>
53 #include <Geom2d_TrimmedCurve.hxx>
54 #include <ElCLib.hxx>
55 #include <GeomLib.hxx>
56 #include <Extrema_ExtPC.hxx>
57
58 //=======================================================================
59 //function : IsoIsDeg
60 //purpose  : 
61 //=======================================================================
62
63 static Standard_Boolean IsoIsDeg  (const Adaptor3d_Surface& S,
64                                    const Standard_Real      Param,
65                                    const GeomAbs_IsoType    IT,
66                                    const Standard_Real      TolMin,
67                                    const Standard_Real      TolMax) 
68 {
69     Standard_Real U1=0.,U2=0.,V1=0.,V2=0.,T;
70     Standard_Boolean Along = Standard_True;
71     U1 = S.FirstUParameter();
72     U2 = S.LastUParameter();
73     V1 = S.FirstVParameter();
74     V2 = S.LastVParameter();
75     gp_Vec D1U,D1V;
76     gp_Pnt P;
77     Standard_Real Step,D1NormMax;
78     if (IT == GeomAbs_IsoV) 
79     {
80       Step = (U2 - U1)/10;
81       D1NormMax=0.;
82       for (T=U1;T<=U2;T=T+Step) 
83       {
84         S.D1(T,Param,P,D1U,D1V);
85         D1NormMax=Max(D1NormMax,D1U.Magnitude());
86       }
87
88       if (D1NormMax >TolMax || D1NormMax < TolMin ) 
89            Along = Standard_False;
90     }
91     else 
92     {
93       Step = (V2 - V1)/10;
94       D1NormMax=0.;
95       for (T=V1;T<=V2;T=T+Step) 
96       {
97         S.D1(Param,T,P,D1U,D1V);
98         D1NormMax=Max(D1NormMax,D1V.Magnitude());
99       }
100
101       if (D1NormMax >TolMax || D1NormMax < TolMin ) 
102            Along = Standard_False;
103
104
105     }
106     return Along;
107 }
108
109 //=======================================================================
110 //function : TrimC3d
111 //purpose  : 
112 //=======================================================================
113
114 static void TrimC3d(Handle(Adaptor3d_HCurve)& myCurve,
115                     Standard_Boolean* IsTrimmed,
116                     const Standard_Real dt,
117                     const gp_Pnt& Pole,
118                     Standard_Integer* SingularCase,
119                     const Standard_Integer NumberOfSingularCase)
120 {
121   Standard_Real f = myCurve->FirstParameter();
122   Standard_Real l = myCurve->LastParameter();
123
124   gp_Pnt P = myCurve->Value(f);
125
126   if(P.Distance(Pole) < Precision::Confusion()) {
127     IsTrimmed[0] = Standard_True;
128     f = f+dt;
129     myCurve = myCurve->Trim(f, l, Precision::Confusion());
130     SingularCase[0] = NumberOfSingularCase;
131   }
132   
133   P = myCurve->Value(l);
134   if(P.Distance(Pole) < Precision::Confusion()) {
135     IsTrimmed[1] = Standard_True;
136     l = l-dt;
137     myCurve = myCurve->Trim(f, l, Precision::Confusion());
138     SingularCase[1] = NumberOfSingularCase;
139   }
140 }
141
142 //=======================================================================
143 //function : ExtendC2d
144 //purpose  : 
145 //=======================================================================
146
147 static void ExtendC2d (Handle(Geom2d_BSplineCurve)& aRes,
148                        const Standard_Real /*t*/,
149                        const Standard_Real /*dt*/,
150                        const Standard_Real u1,
151                        const Standard_Real u2,
152                        const Standard_Real v1,
153                        const Standard_Real v2,
154                        const Standard_Integer FirstOrLast,
155                        const Standard_Integer NumberOfSingularCase)
156 {
157   Standard_Real theParam = (FirstOrLast == 0)? aRes->FirstParameter()
158     : aRes->LastParameter();
159
160   gp_Pnt2d                              aPBnd;
161   gp_Vec2d                              aVBnd;
162   gp_Dir2d                              aDBnd;
163   Handle(Geom2d_TrimmedCurve)           aSegment;
164   Geom2dConvert_CompCurveToBSplineCurve aCompCurve(aRes, Convert_RationalC1);
165   Standard_Real                         aTol = Precision::Confusion();
166
167   aRes->D1(theParam, aPBnd, aVBnd);
168   aDBnd.SetXY(aVBnd.XY());
169   gp_Lin2d aLin(aPBnd, aDBnd); //line in direction of derivative
170
171   gp_Pnt2d thePole;
172   gp_Dir2d theBoundDir;
173   switch (NumberOfSingularCase)
174   {
175   case 1:
176     {
177       thePole.SetCoord(u1, v1);
178       theBoundDir.SetCoord(0., 1.);
179       break;
180     }
181   case 2:
182     {
183       thePole.SetCoord(u2, v1);
184       theBoundDir.SetCoord(0., 1.);
185       break;
186     }
187   case 3:
188     {
189       thePole.SetCoord(u1, v1);
190       theBoundDir.SetCoord(1., 0.);
191       break;
192     }
193   case 4:
194     {
195       thePole.SetCoord(u1, v2);
196       theBoundDir.SetCoord(1., 0.);
197       break;
198     }
199   }
200   gp_Lin2d BoundLin(thePole, theBoundDir); //one of the bounds of rectangle
201
202   Standard_Real U1x = BoundLin.Direction().X();
203   Standard_Real U1y = BoundLin.Direction().Y();
204   Standard_Real U2x = aLin.Direction().X();
205   Standard_Real U2y = aLin.Direction().Y();
206   Standard_Real Uo21x = aLin.Location().X() - BoundLin.Location().X();
207   Standard_Real Uo21y = aLin.Location().Y() - BoundLin.Location().Y();
208   
209   Standard_Real D = U1y*U2x-U1x*U2y;
210   
211   Standard_Real ParOnLin = (Uo21y * U1x - Uo21x * U1y)/D; //parameter of intersection point
212   
213   Handle(Geom2d_Line) aSegLine = new Geom2d_Line(aLin);
214   aSegment = (FirstOrLast == 0)?
215     new Geom2d_TrimmedCurve(aSegLine, ParOnLin, 0.) :
216     new Geom2d_TrimmedCurve(aSegLine, 0., ParOnLin);
217
218   aCompCurve.Add(aSegment, aTol);
219   aRes = aCompCurve.BSplineCurve();
220 }
221
222 //=======================================================================
223 //function : Project
224 //purpose  : 
225 //=======================================================================
226
227 static void Project(ProjLib_Projector& P, Handle(Adaptor3d_HCurve)& C)
228 {
229   GeomAbs_CurveType CType = C->GetType();
230   switch (CType) {
231     case GeomAbs_Line:
232       P.Project(C->Line());
233       break;
234     case GeomAbs_Circle:
235       P.Project(C->Circle());
236       break;
237     case GeomAbs_Ellipse:
238       P.Project(C->Ellipse());
239       break;
240     case GeomAbs_Hyperbola:
241       P.Project(C->Hyperbola());
242       break;
243     case GeomAbs_Parabola:
244       P.Project(C->Parabola());
245       break;
246     case GeomAbs_BSplineCurve:
247     case GeomAbs_BezierCurve:
248     case GeomAbs_OtherCurve:    // try the approximation
249       break;
250     default:
251       Standard_NoSuchObject::Raise(" ");
252   }
253 }
254
255 //=======================================================================
256 //function : ProjLib_ProjectedCurve
257 //purpose  : 
258 //=======================================================================
259
260 ProjLib_ProjectedCurve::ProjLib_ProjectedCurve()
261
262 {
263   myTolerance = Precision::Confusion();
264 }
265
266
267 //=======================================================================
268 //function : ProjLib_ProjectedCurve
269 //purpose  : 
270 //=======================================================================
271
272 ProjLib_ProjectedCurve::ProjLib_ProjectedCurve
273 (const Handle(Adaptor3d_HSurface)& S)
274 {
275   myTolerance = Precision::Confusion();
276   Load(S);
277 }
278
279
280 //=======================================================================
281 //function : ProjLib_ProjectedCurve
282 //purpose  : 
283 //=======================================================================
284
285 ProjLib_ProjectedCurve::ProjLib_ProjectedCurve
286 (const Handle(Adaptor3d_HSurface)& S,
287  const Handle(Adaptor3d_HCurve)& C)
288 {
289   myTolerance = Precision::Confusion();
290   Load(S);
291   Load(C);
292 }
293
294
295 //=======================================================================
296 //function : ProjLib_ProjectedCurve
297 //purpose  : 
298 //=======================================================================
299
300 ProjLib_ProjectedCurve::ProjLib_ProjectedCurve
301 (const Handle(Adaptor3d_HSurface)& S,
302  const Handle(Adaptor3d_HCurve)&   C,
303  const Standard_Real             Tol)
304 {
305   myTolerance = Max(Tol, Precision::Confusion());
306   Load(S);
307   Load(C);
308 }
309
310
311 //=======================================================================
312 //function : Load
313 //purpose  : 
314 //=======================================================================
315
316 void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HSurface)& S)
317 {
318   mySurface = S ;
319 }
320
321
322 //=======================================================================
323 //function : Load
324 //purpose  : 
325 //=======================================================================
326
327 void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
328 {
329   myTolerance = Max(myTolerance, Precision::Confusion());
330   myCurve = C;
331   Standard_Real FirstPar = C->FirstParameter();
332   Standard_Real LastPar  = C->LastParameter();
333   GeomAbs_SurfaceType SType = mySurface->GetType();
334   GeomAbs_CurveType   CType = myCurve->GetType();
335   Standard_Boolean isAnalyticalSurf = Standard_True;
336
337   switch (SType)
338   {
339     case GeomAbs_Plane:
340       {
341         ProjLib_Plane P(mySurface->Plane());
342         Project(P,myCurve);
343         myResult = P;
344       }
345       break;
346
347     case GeomAbs_Cylinder:
348       {
349         ProjLib_Cylinder P(mySurface->Cylinder());
350         Project(P,myCurve);
351         myResult = P;
352       }
353       break;
354
355     case GeomAbs_Cone:
356       {
357         ProjLib_Cone P(mySurface->Cone());
358         Project(P,myCurve);
359         myResult = P;
360       }
361       break;
362
363     case GeomAbs_Sphere:
364       {
365         ProjLib_Sphere P(mySurface->Sphere());
366         Project(P,myCurve);
367         if ( P.IsDone())
368         {
369           // on met dans la pseudo-periode ( car Sphere n'est pas
370           // periodique en V !)
371           P.SetInBounds(myCurve->FirstParameter());
372         }
373         myResult = P;
374       }
375       break;
376
377     case GeomAbs_Torus:
378       {
379         ProjLib_Torus P(mySurface->Torus());
380         Project(P,myCurve);
381         myResult = P;
382       }
383       break;
384
385     case GeomAbs_BezierSurface:
386     case GeomAbs_BSplineSurface:
387       {
388         isAnalyticalSurf = Standard_False;
389         Standard_Boolean IsTrimmed[2] = {Standard_False, Standard_False};
390         Standard_Integer SingularCase[2];
391         Standard_Real f, l, dt;
392         const Standard_Real eps = 0.01;
393         f = myCurve->FirstParameter();
394         l = myCurve->LastParameter();
395         dt = (l - f) * eps;
396
397         Standard_Real U1 = 0.0, U2=0.0, V1=0.0, V2=0.0;
398         const Adaptor3d_Surface& S = mySurface->Surface();
399         U1 = S.FirstUParameter();
400         U2 = S.LastUParameter();
401         V1 = S.FirstVParameter();
402         V2 = S.LastVParameter();
403
404         if(IsoIsDeg(S, U1, GeomAbs_IsoU, 0., myTolerance))
405         {
406           //Surface has pole at U = Umin
407           gp_Pnt Pole = mySurface->Value(U1, V1);
408           TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 1);
409         }
410
411         if(IsoIsDeg(S, U2, GeomAbs_IsoU, 0., myTolerance))
412         {
413           //Surface has pole at U = Umax
414           gp_Pnt Pole = mySurface->Value(U2, V1);
415           TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 2);
416         }
417
418         if(IsoIsDeg(S, V1, GeomAbs_IsoV, 0., myTolerance))
419         {
420           //Surface has pole at V = Vmin
421           gp_Pnt Pole = mySurface->Value(U1, V1);
422           TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3);
423         }
424
425         if(IsoIsDeg(S, V2, GeomAbs_IsoV, 0., myTolerance))
426         {
427           //Surface has pole at V = Vmax
428           gp_Pnt Pole = mySurface->Value(U1, V2);
429           TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4);
430         }
431
432         ProjLib_ComputeApproxOnPolarSurface polar(myCurve, mySurface, myTolerance);
433
434         Handle(Geom2d_BSplineCurve) aRes = polar.BSpline();
435
436         if (!aRes.IsNull())
437         {
438           if( (IsTrimmed[0] || IsTrimmed[1]))
439           {
440             if(IsTrimmed[0])
441             {
442               //Add segment before start of curve
443               f = myCurve->FirstParameter();
444               ExtendC2d(aRes, f, -dt, U1, U2, V1, V2, 0, SingularCase[0]);
445             }
446             if(IsTrimmed[1])
447             {
448               //Add segment after end of curve
449               l = myCurve->LastParameter();
450               ExtendC2d(aRes, l,  dt, U1, U2, V1, V2, 1, SingularCase[1]);
451             }
452             Handle(Geom2d_Curve) NewCurve2d;
453             GeomLib::SameRange(Precision::PConfusion(), aRes,
454               aRes->FirstParameter(), aRes->LastParameter(),
455               FirstPar, LastPar, NewCurve2d);
456             aRes = Handle(Geom2d_BSplineCurve)::DownCast(NewCurve2d);
457           }
458           myResult.SetBSpline(aRes);
459           myResult.Done();
460           myResult.SetType(GeomAbs_BSplineCurve);
461         }
462       }
463       break;
464
465     default:
466       {
467         isAnalyticalSurf = Standard_False;
468         Standard_Boolean IsTrimmed[2] = {Standard_False, Standard_False};
469         Standard_Real Vsingular[2] = {0.0 , 0.0}; //for surfaces of revolution
470         Standard_Real f = 0.0, l = 0.0, dt = 0.0;
471         const Standard_Real eps = 0.01;
472
473         if(mySurface->GetType() == GeomAbs_SurfaceOfRevolution)
474         {
475           //Check possible singularity
476
477           gp_Pnt P = mySurface->AxeOfRevolution().Location();
478           gp_Dir N = mySurface->AxeOfRevolution().Direction();
479
480           gp_Lin L(P, N);
481
482           f = myCurve->FirstParameter();
483           l = myCurve->LastParameter();
484           dt = (l - f) * eps;
485
486           P = myCurve->Value(f);
487           if(L.Distance(P) < Precision::Confusion())
488           {
489             IsTrimmed[0] = Standard_True;
490             f = f + dt;
491             myCurve = myCurve->Trim(f, l, Precision::Confusion());
492             // Searching the parameter on the basis curve for surface of revolution
493             Extrema_ExtPC anExtr(P, mySurface->BasisCurve()->Curve(), myTolerance);
494             if (anExtr.IsDone())
495             {
496               Standard_Integer anIndex = 1;
497               while (!anExtr.IsMin(anIndex) && anIndex < anExtr.NbExt()) anIndex++;
498               Vsingular[0] = anExtr.Point(anIndex).Parameter();
499             }
500             else
501               Vsingular[0] = ElCLib::Parameter(L, P);
502             //SingularCase[0] = 3;
503           }
504
505           P = myCurve->Value(l);
506           if(L.Distance(P) < Precision::Confusion())
507           {
508             IsTrimmed[1] = Standard_True;
509             l = l - dt;
510             myCurve = myCurve->Trim(f, l, Precision::Confusion());
511             // Searching the parameter on the basis curve for surface of revolution
512             Extrema_ExtPC anExtr(P, mySurface->BasisCurve()->Curve(), myTolerance);
513             if (anExtr.IsDone())
514             {
515               Standard_Integer anIndex = 1;
516               while (!anExtr.IsMin(anIndex) && anIndex < anExtr.NbExt()) anIndex++;
517               Vsingular[1] = anExtr.Point(anIndex).Parameter();
518             }
519             else
520               Vsingular[1] = ElCLib::Parameter(L, P);
521             //SingularCase[1] = 4;
522           }
523         }
524
525         ProjLib_CompProjectedCurve Projector(mySurface,myCurve, myTolerance, myTolerance);
526         Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve();
527         HProjector->Set(Projector);
528
529         // Normalement, dans le cadre de ProjLib, le resultat 
530         // doit etre une et une seule courbe !!!
531         // De plus, cette courbe ne doit pas etre Single point
532         Standard_Integer NbCurves = Projector.NbCurves();
533         Standard_Real Udeb = 0.0,Ufin = 0.0;
534         if (NbCurves > 0)
535         {
536           Projector.Bounds(1, Udeb, Ufin);
537         }
538         else 
539         {
540           StdFail_NotDone::Raise("ProjLib CompProjectedCurve Not Done");
541         }
542         // Approximons cette courbe algorithmique.
543         Standard_Boolean Only3d = Standard_False;
544         Standard_Boolean Only2d = Standard_True;
545         GeomAbs_Shape Continuity = GeomAbs_C1;
546         Standard_Integer MaxDegree = 14;
547         Standard_Integer MaxSeg    = 16;
548
549         Approx_CurveOnSurface appr(HProjector, mySurface, Udeb, Ufin, 
550                                    myTolerance, Continuity, MaxDegree, MaxSeg, 
551                                    Only3d, Only2d);
552
553         Handle(Geom2d_BSplineCurve) aRes = appr.Curve2d();
554
555         if (!aRes.IsNull())
556         {
557           if(IsTrimmed[0] || IsTrimmed[1])
558           {
559             // Treatment only for surface of revolution
560             Standard_Real u1, u2, v1, v2;
561             u1 = mySurface->FirstUParameter();
562             u2 = mySurface->LastUParameter();
563             v1 = mySurface->FirstVParameter();
564             v2 = mySurface->LastVParameter();
565
566             if(IsTrimmed[0])
567             {
568               //Add segment before start of curve
569               ExtendC2d(aRes, f, -dt, u1, u2, Vsingular[0], v2, 0, 3);
570             }
571             if(IsTrimmed[1])
572             {
573               //Add segment after end of curve
574               ExtendC2d(aRes, l,  dt, u1, u2, v1, Vsingular[1], 1, 4);
575             }
576             Handle(Geom2d_Curve) NewCurve2d;
577             GeomLib::SameRange(Precision::PConfusion(), aRes,
578               aRes->FirstParameter(), aRes->LastParameter(),
579               FirstPar, LastPar, NewCurve2d);
580             aRes = Handle(Geom2d_BSplineCurve)::DownCast(NewCurve2d);
581           }
582
583           myResult.SetBSpline(aRes);
584           myResult.Done();
585           myResult.SetType(GeomAbs_BSplineCurve);
586         }
587       }
588   }
589
590   if ( !myResult.IsDone() && isAnalyticalSurf)
591   {
592     // Use advanced analytical projector if base analytical projection failed.
593     ProjLib_ComputeApprox Comp( myCurve, mySurface, myTolerance);
594     myResult.Done();
595
596     // set the type
597     if ( SType == GeomAbs_Plane && CType == GeomAbs_BezierCurve)
598     {
599       myResult.SetType(GeomAbs_BezierCurve);
600       myResult.SetBezier(Comp.Bezier()) ;
601     }
602     else
603     {
604       myResult.SetType(GeomAbs_BSplineCurve);
605       myResult.SetBSpline(Comp.BSpline()) ;
606     }
607     // set the periodicity flag
608     if (SType == GeomAbs_Plane        &&
609         CType == GeomAbs_BSplineCurve &&
610         myCurve->IsPeriodic()   )
611     {
612       myResult.SetPeriodic();
613     }
614     myTolerance = Comp.Tolerance();
615   }
616   else if (myResult.IsDone())
617   {
618     // On remet arbitrairement la tol atteinte a une valeur
619     // petite en attendant mieux. dub lbo 11/03/97
620     myTolerance = Min(myTolerance,Precision::Confusion());
621     
622     // Translate the projected curve to keep the first point
623     // In the canonical boundaries of periodic surfaces.
624     if (mySurface->IsUPeriodic())
625     {
626       // xf
627       Standard_Real aT1, aT2, aU1, aU2, aUPeriod, aUr, aUm, aUmid, dUm, dUr;
628       GeomAbs_CurveType aTypeR;
629       ProjLib_Projector aResult;
630       //
631       aT1 = myCurve->FirstParameter();
632       aT2 = myCurve->LastParameter();
633       aU1 = mySurface->FirstUParameter();
634       aU2 = mySurface->LastUParameter();
635       aUPeriod = mySurface->UPeriod();
636       //
637       aTypeR = myResult.GetType();
638       if ((aU2 - aU1) < (aUPeriod - myTolerance) && aTypeR == GeomAbs_Line)
639       {
640         aResult = myResult;
641         aResult.UFrame(aT1, aT2, aU1, aUPeriod);
642         //
643         gp_Lin2d &aLr = (gp_Lin2d &) aResult.Line();
644         aUr=aLr.Location().X();
645         gp_Lin2d &aLm = (gp_Lin2d &) myResult.Line();
646         aUm=aLm.Location().X();
647         //
648         aUmid = 0.5 * (aU2 + aU1);
649         dUm = fabs(aUm - aUmid);
650         dUr = fabs(aUr - aUmid);
651         if (dUr < dUm)
652         {
653           myResult = aResult;
654         }
655       }
656       else
657       {
658         myResult.UFrame(aT1, aT2, aU1, aUPeriod);
659       }
660       //
661       /*
662       myResult.UFrame(myCurve->FirstParameter(),
663       myCurve->LastParameter(),
664       mySurface->FirstUParameter(),
665       mySurface->UPeriod());
666       */
667       //xt
668       //  Modified by skv - Wed Aug 11 15:45:58 2004 OCC6272 Begin
669       //  Correct the U isoline in periodical surface
670       // to be inside restriction boundaries.
671       if (myResult.GetType() == GeomAbs_Line)
672       {
673         gp_Lin2d &aLine = (gp_Lin2d &) myResult.Line();
674
675         Standard_Real aPeriod = mySurface->UPeriod();
676         Standard_Real aFUPar  = mySurface->FirstUParameter();
677         Standard_Real aLUPar  = mySurface->LastUParameter();
678
679         // Check if the parametric range is lower then the period.
680         if (aLUPar - aFUPar < aPeriod - myTolerance)
681         {
682           Standard_Real aU = aLine.Location().X();
683
684           if (Abs(aU + aPeriod - aFUPar) < myTolerance ||
685               Abs(aU - aPeriod - aFUPar) < myTolerance)
686           {
687               gp_Pnt2d aNewLoc(aFUPar, aLine.Location().Y());
688
689               aLine.SetLocation(aNewLoc);
690           }
691           else if (Abs(aU + aPeriod - aLUPar) < myTolerance ||
692                    Abs(aU - aPeriod - aLUPar) < myTolerance)
693           {
694               gp_Pnt2d aNewLoc(aLUPar, aLine.Location().Y());
695               aLine.SetLocation(aNewLoc);
696           }
697         }
698       }
699     }
700     //  Modified by skv - Wed Aug 11 15:45:58 2004 OCC6272 End
701
702     if (mySurface->IsVPeriodic())
703     {
704       myResult.VFrame(myCurve->FirstParameter(), myCurve->LastParameter(),
705         mySurface->FirstVParameter(), mySurface->VPeriod());
706       //  Modified by skv - Wed Aug 11 15:45:58 2004 OCC6272 Begin
707       //  Correct the V isoline in a periodical surface
708       // to be inside restriction boundaries.
709       if (myResult.GetType() == GeomAbs_Line)
710       {
711         gp_Lin2d &aLine = (gp_Lin2d &) myResult.Line();
712
713         Standard_Real aPeriod = mySurface->VPeriod();
714         Standard_Real aFVPar  = mySurface->FirstVParameter();
715         Standard_Real aLVPar  = mySurface->LastVParameter();
716
717         // Check if the parametric range is lower then the period.
718         if (aLVPar - aFVPar < aPeriod - myTolerance)
719         {
720           Standard_Real aV = aLine.Location().Y();
721
722           if (Abs(aV + aPeriod - aFVPar) < myTolerance ||
723               Abs(aV - aPeriod - aFVPar) < myTolerance)
724           {
725             gp_Pnt2d aNewLoc(aLine.Location().X(), aFVPar);
726             aLine.SetLocation(aNewLoc);
727           }
728           else if (Abs(aV + aPeriod - aLVPar) < myTolerance ||
729                    Abs(aV - aPeriod - aLVPar) < myTolerance)
730           {
731             gp_Pnt2d aNewLoc(aLine.Location().X(), aLVPar);
732             aLine.SetLocation(aNewLoc);
733           }
734         }
735       }
736     }
737     //  Modified by skv - Wed Aug 11 15:45:58 2004 OCC6272 End
738   } 
739 }
740
741
742 //=======================================================================
743 //function : GetSurface
744 //purpose  : 
745 //=======================================================================
746
747 const Handle(Adaptor3d_HSurface)& ProjLib_ProjectedCurve::GetSurface() const
748 {
749   return mySurface;
750 }
751
752
753 //=======================================================================
754 //function : GetCurve
755 //purpose  : 
756 //=======================================================================
757
758 const Handle(Adaptor3d_HCurve)& ProjLib_ProjectedCurve::GetCurve() const
759 {
760   return myCurve;
761 }
762
763
764 //=======================================================================
765 //function : GetTolerance
766 //purpose  : 
767 //=======================================================================
768
769 Standard_Real ProjLib_ProjectedCurve::GetTolerance() const 
770 {
771   return myTolerance;
772 }
773
774
775 //=======================================================================
776 //function : FirstParameter
777 //purpose  : 
778 //=======================================================================
779
780 Standard_Real ProjLib_ProjectedCurve::FirstParameter() const 
781 {
782   return myCurve->FirstParameter();
783 }
784
785
786 //=======================================================================
787 //function : LastParameter
788 //purpose  : 
789 //=======================================================================
790
791 Standard_Real ProjLib_ProjectedCurve::LastParameter() const 
792 {
793   return myCurve->LastParameter();
794 }
795
796
797 //=======================================================================
798 //function : Continuity
799 //purpose  : 
800 //=======================================================================
801
802 GeomAbs_Shape ProjLib_ProjectedCurve::Continuity() const
803 {
804   Standard_NotImplemented::Raise("");
805   return GeomAbs_C0;
806 }
807
808
809 //=======================================================================
810 //function : NbIntervals
811 //purpose  : 
812 //=======================================================================
813
814 Standard_Integer ProjLib_ProjectedCurve::NbIntervals(const GeomAbs_Shape ) const 
815 {
816   Standard_NotImplemented::Raise("");
817   return 0;
818 }
819
820
821 //=======================================================================
822 //function : Intervals
823 //purpose  : 
824 //=======================================================================
825
826 //void ProjLib_ProjectedCurve::Intervals(TColStd_Array1OfReal&  T,
827 void ProjLib_ProjectedCurve::Intervals(TColStd_Array1OfReal&  ,
828                                        const GeomAbs_Shape ) const 
829 {
830   Standard_NotImplemented::Raise("");
831 }
832
833
834 //=======================================================================
835 //function : IsClosed
836 //purpose  : 
837 //=======================================================================
838
839 Standard_Boolean ProjLib_ProjectedCurve::IsClosed() const
840 {
841   Standard_NotImplemented::Raise("");
842   return Standard_True;
843 }
844
845
846 //=======================================================================
847 //function : IsPeriodic
848 //purpose  : 
849 //=======================================================================
850
851 Standard_Boolean ProjLib_ProjectedCurve::IsPeriodic() const
852 {
853   return myResult.IsPeriodic();
854 }
855
856
857 //=======================================================================
858 //function : Period
859 //purpose  : 
860 //=======================================================================
861
862 Standard_Real ProjLib_ProjectedCurve::Period() const
863 {
864   Standard_NotImplemented::Raise("");
865   return 0.;
866 }
867
868
869 //=======================================================================
870 //function : Value
871 //purpose  : 
872 //=======================================================================
873
874 gp_Pnt2d ProjLib_ProjectedCurve::Value(const Standard_Real ) const 
875 {
876   Standard_NotImplemented::Raise("");
877   return gp_Pnt2d(0.,0.);
878 }
879
880
881 //=======================================================================
882 //function : D0
883 //purpose  : 
884 //=======================================================================
885
886 void ProjLib_ProjectedCurve::D0(const Standard_Real , gp_Pnt2d& ) const
887 {
888   Standard_NotImplemented::Raise("");
889 }
890
891
892 //=======================================================================
893 //function : D1
894 //purpose  : 
895 //=======================================================================
896
897 void ProjLib_ProjectedCurve::D1(const Standard_Real ,
898                                       gp_Pnt2d&     , 
899                                       gp_Vec2d&     ) const 
900 {
901   Standard_NotImplemented::Raise("");
902 }
903
904
905 //=======================================================================
906 //function : D2
907 //purpose  : 
908 //=======================================================================
909
910 void ProjLib_ProjectedCurve::D2(const Standard_Real , 
911                                       gp_Pnt2d&     , 
912                                       gp_Vec2d&     , 
913                                       gp_Vec2d&     ) const 
914 {
915   Standard_NotImplemented::Raise("");
916 }
917
918
919 //=======================================================================
920 //function : D3
921 //purpose  : 
922 //=======================================================================
923
924 void ProjLib_ProjectedCurve::D3(const Standard_Real, 
925                                       gp_Pnt2d&, 
926                                       gp_Vec2d&, 
927                                       gp_Vec2d&, 
928                                       gp_Vec2d&) const 
929 {
930   Standard_NotImplemented::Raise("");
931 }
932
933
934 //=======================================================================
935 //function : DN
936 //purpose  : 
937 //=======================================================================
938
939 gp_Vec2d ProjLib_ProjectedCurve::DN(const Standard_Real, 
940                                     const Standard_Integer) const 
941 {
942   Standard_NotImplemented::Raise("");
943   return gp_Vec2d(0.,0.);
944 }
945
946
947 //=======================================================================
948 //function : Resolution
949 //purpose  : 
950 //=======================================================================
951
952 Standard_Real ProjLib_ProjectedCurve::Resolution(const Standard_Real) const 
953 {
954   Standard_NotImplemented::Raise("");
955   return 0.;
956 }
957     
958
959 //=======================================================================
960 //function : GetType
961 //purpose  : 
962 //=======================================================================
963
964 GeomAbs_CurveType ProjLib_ProjectedCurve::GetType() const
965 {
966   return myResult.GetType();
967 }
968
969
970 //=======================================================================
971 //function : Line
972 //purpose  : 
973 //=======================================================================
974
975 gp_Lin2d ProjLib_ProjectedCurve::Line() const
976 {
977   return myResult.Line();
978 }
979
980
981 //=======================================================================
982 //function : Circle
983 //purpose  : 
984 //=======================================================================
985
986 gp_Circ2d ProjLib_ProjectedCurve::Circle() const
987 {
988   return myResult.Circle();
989 }
990
991
992 //=======================================================================
993 //function : Ellipse
994 //purpose  : 
995 //=======================================================================
996
997 gp_Elips2d ProjLib_ProjectedCurve::Ellipse() const
998 {
999   return myResult.Ellipse();
1000 }
1001
1002
1003 //=======================================================================
1004 //function : Hyperbola
1005 //purpose  : 
1006 //=======================================================================
1007
1008 gp_Hypr2d ProjLib_ProjectedCurve::Hyperbola() const
1009 {
1010   return myResult.Hyperbola();
1011 }
1012
1013
1014 //=======================================================================
1015 //function : Parabola
1016 //purpose  : 
1017 //=======================================================================
1018
1019 gp_Parab2d ProjLib_ProjectedCurve::Parabola() const
1020 {
1021   return myResult.Parabola();
1022 }
1023
1024
1025
1026 //=======================================================================
1027 //function : Degree
1028 //purpose  : 
1029 //=======================================================================
1030
1031 Standard_Integer ProjLib_ProjectedCurve::Degree() const
1032 {
1033   Standard_NoSuchObject_Raise_if 
1034     ( (GetType() != GeomAbs_BSplineCurve) &&
1035       (GetType() != GeomAbs_BezierCurve),
1036      "ProjLib_ProjectedCurve:Degree");
1037   if (GetType() == GeomAbs_BSplineCurve) {
1038     return myResult.BSpline()->Degree();
1039   }
1040   else if (GetType() == GeomAbs_BezierCurve) {
1041     return myResult.Bezier()->Degree();
1042   }
1043
1044   // portage WNT
1045   return 0;
1046 }
1047
1048 //=======================================================================
1049 //function : IsRational
1050 //purpose  : 
1051 //=======================================================================
1052
1053 Standard_Boolean ProjLib_ProjectedCurve::IsRational() const 
1054 {
1055   Standard_NoSuchObject_Raise_if 
1056     ( (GetType() != GeomAbs_BSplineCurve) &&
1057       (GetType() != GeomAbs_BezierCurve),
1058      "ProjLib_ProjectedCurve:IsRational");
1059   if (GetType() == GeomAbs_BSplineCurve) {
1060     return myResult.BSpline()->IsRational();
1061   }
1062   else if (GetType() == GeomAbs_BezierCurve) {
1063     return myResult.Bezier()->IsRational();
1064   }
1065   // portage WNT
1066   return Standard_False;
1067 }
1068
1069 //=======================================================================
1070 //function : NbPoles
1071 //purpose  : 
1072 //=======================================================================
1073
1074 Standard_Integer ProjLib_ProjectedCurve::NbPoles() const
1075 {
1076   Standard_NoSuchObject_Raise_if 
1077     ( (GetType() != GeomAbs_BSplineCurve) &&
1078       (GetType() != GeomAbs_BezierCurve)   
1079      ,"ProjLib_ProjectedCurve:NbPoles"  );
1080   if (GetType() == GeomAbs_BSplineCurve) {
1081     return myResult.BSpline()->NbPoles();
1082   }
1083   else if (GetType() == GeomAbs_BezierCurve) {
1084     return myResult.Bezier()->NbPoles();
1085   }
1086
1087   // portage WNT
1088   return 0;
1089 }
1090
1091 //=======================================================================
1092 //function : NbKnots
1093 //purpose  : 
1094 //=======================================================================
1095
1096 Standard_Integer ProjLib_ProjectedCurve::NbKnots() const 
1097 {
1098   Standard_NoSuchObject_Raise_if ( GetType() != GeomAbs_BSplineCurve, 
1099                                   "ProjLib_ProjectedCurve:NbKnots");
1100   return myResult.BSpline()->NbKnots();
1101 }
1102
1103 //=======================================================================
1104 //function : Bezier
1105 //purpose  : 
1106 //=======================================================================
1107
1108 Handle(Geom2d_BezierCurve) ProjLib_ProjectedCurve::Bezier() const 
1109 {
1110  return myResult.Bezier() ;
1111 }
1112
1113 //=======================================================================
1114 //function : BSpline
1115 //purpose  : 
1116 //=======================================================================
1117
1118 Handle(Geom2d_BSplineCurve) ProjLib_ProjectedCurve::BSpline() const 
1119 {
1120  return myResult.BSpline() ;
1121 }
1122 //=======================================================================
1123 //function : Trim
1124 //purpose  : 
1125 //=======================================================================
1126
1127 Handle(Adaptor2d_HCurve2d) ProjLib_ProjectedCurve::Trim 
1128 //(const Standard_Real First,
1129 // const Standard_Real Last,
1130 // const Standard_Real Tolerance) const 
1131 (const Standard_Real ,
1132  const Standard_Real ,
1133  const Standard_Real ) const 
1134 {
1135   Standard_NotImplemented::Raise("");
1136   return NULL ;
1137 }
1138