0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[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 <Standard_NoSuchObject.hxx>
20 #include <Standard_NotImplemented.hxx>
21 #include <ProjLib_ProjectedCurve.hxx>
22 #include <ProjLib_HCompProjectedCurve.hxx>
23 #include <ProjLib_ComputeApproxOnPolarSurface.hxx>
24 #include <ProjLib_ComputeApprox.hxx>
25 #include <ProjLib_Projector.hxx>
26 #include <Adaptor3d_Curve.hxx>
27 #include <Adaptor3d_Surface.hxx>
28 #include <Approx_CurveOnSurface.hxx>
29 #include <ProjLib_Plane.hxx>
30 #include <ProjLib_Cylinder.hxx>
31 #include <ProjLib_Cone.hxx>
32 #include <ProjLib_Sphere.hxx>
33 #include <ProjLib_Torus.hxx>
34 #include <Precision.hxx>
35 #include <Geom2d_BezierCurve.hxx>
36 #include <gp_Vec2d.hxx>
37 #include <StdFail_NotDone.hxx>
38 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
39 #include <Geom2dConvert.hxx>
40 #include <TColStd_Array1OfReal.hxx>
41 #include <GeomAbs_IsoType.hxx>
42 #include <Geom2d_Line.hxx>
43 #include <Geom2d_TrimmedCurve.hxx>
44 #include <GeomLib.hxx>
45 #include <Extrema_ExtPC.hxx>
46 #include <NCollection_DataMap.hxx>
47 #include <ElSLib.hxx>
48 #include <ElCLib.hxx>
49
50 IMPLEMENT_STANDARD_RTTIEXT(ProjLib_ProjectedCurve, Adaptor2d_Curve2d)
51
52 //=======================================================================
53 //function : ComputeTolU
54 //purpose  : 
55 //=======================================================================
56
57 static Standard_Real ComputeTolU(const Handle(Adaptor3d_Surface)& theSurf,
58                                  const Standard_Real theTolerance)
59 {
60   Standard_Real aTolU = theSurf->UResolution(theTolerance);
61   if (theSurf->IsUPeriodic())
62   {
63     aTolU = Min(aTolU, 0.01*theSurf->UPeriod());
64   }
65
66   return aTolU;
67 }
68
69 //=======================================================================
70 //function : ComputeTolV
71 //purpose  : 
72 //=======================================================================
73
74 static Standard_Real ComputeTolV(const Handle(Adaptor3d_Surface)& theSurf,
75                                  const Standard_Real theTolerance)
76 {
77   Standard_Real aTolV = theSurf->VResolution(theTolerance);
78   if (theSurf->IsVPeriodic())
79   {
80     aTolV = Min(aTolV, 0.01*theSurf->VPeriod());
81   }
82
83   return aTolV;
84 }
85
86 //=======================================================================
87 //function : IsoIsDeg
88 //purpose  : 
89 //=======================================================================
90
91 static Standard_Boolean IsoIsDeg  (const Adaptor3d_Surface& S,
92                                    const Standard_Real      Param,
93                                    const GeomAbs_IsoType    IT,
94                                    const Standard_Real      TolMin,
95                                    const Standard_Real      TolMax) 
96 {
97     Standard_Real U1=0.,U2=0.,V1=0.,V2=0.,T;
98     Standard_Boolean Along = Standard_True;
99     U1 = S.FirstUParameter();
100     U2 = S.LastUParameter();
101     V1 = S.FirstVParameter();
102     V2 = S.LastVParameter();
103     gp_Vec D1U,D1V;
104     gp_Pnt P;
105     Standard_Real Step,D1NormMax;
106     if (IT == GeomAbs_IsoV) 
107     {
108       Step = (U2 - U1)/10;
109       D1NormMax=0.;
110       for (T=U1;T<=U2;T=T+Step) 
111       {
112         S.D1(T,Param,P,D1U,D1V);
113         D1NormMax=Max(D1NormMax,D1U.Magnitude());
114       }
115
116       if (D1NormMax >TolMax || D1NormMax < TolMin ) 
117            Along = Standard_False;
118     }
119     else 
120     {
121       Step = (V2 - V1)/10;
122       D1NormMax=0.;
123       for (T=V1;T<=V2;T=T+Step) 
124       {
125         S.D1(Param,T,P,D1U,D1V);
126         D1NormMax=Max(D1NormMax,D1V.Magnitude());
127       }
128
129       if (D1NormMax >TolMax || D1NormMax < TolMin ) 
130            Along = Standard_False;
131
132
133     }
134     return Along;
135 }
136
137 //=======================================================================
138 //function : TrimC3d
139 //purpose  : 
140 //=======================================================================
141
142 static void TrimC3d(Handle(Adaptor3d_Curve)& myCurve,
143                     Standard_Boolean* IsTrimmed,
144                     const Standard_Real dt,
145                     const gp_Pnt& Pole,
146                     Standard_Integer* SingularCase,
147                     const Standard_Integer NumberOfSingularCase,
148                     const Standard_Real TolConf)
149 {
150   Standard_Real f = myCurve->FirstParameter();
151   Standard_Real l = myCurve->LastParameter();
152
153   gp_Pnt P = myCurve->Value(f);
154
155   if(P.Distance(Pole) <= TolConf) {
156     IsTrimmed[0] = Standard_True;
157     f = f+dt;
158     myCurve = myCurve->Trim(f, l, Precision::Confusion());
159     SingularCase[0] = NumberOfSingularCase;
160   }
161   
162   P = myCurve->Value(l);
163   if(P.Distance(Pole) <= TolConf) {
164     IsTrimmed[1] = Standard_True;
165     l = l-dt;
166     myCurve = myCurve->Trim(f, l, Precision::Confusion());
167     SingularCase[1] = NumberOfSingularCase;
168   }
169 }
170
171 //=======================================================================
172 //function : ExtendC2d
173 //purpose  : 
174 //=======================================================================
175
176 static void ExtendC2d (Handle(Geom2d_BSplineCurve)& aRes,
177                        const Standard_Real /*t*/,
178                        const Standard_Real /*dt*/,
179                        const Standard_Real u1,
180                        const Standard_Real u2,
181                        const Standard_Real v1,
182                        const Standard_Real v2,
183                        const Standard_Integer FirstOrLast,
184                        const Standard_Integer NumberOfSingularCase)
185 {
186   Standard_Real theParam = (FirstOrLast == 0)? aRes->FirstParameter()
187     : aRes->LastParameter();
188
189   gp_Pnt2d                              aPBnd;
190   gp_Vec2d                              aVBnd;
191   gp_Dir2d                              aDBnd;
192   Handle(Geom2d_TrimmedCurve)           aSegment;
193   Geom2dConvert_CompCurveToBSplineCurve aCompCurve(aRes, Convert_RationalC1);
194   Standard_Real                         aTol = Precision::Confusion();
195
196   aRes->D1(theParam, aPBnd, aVBnd);
197   aDBnd.SetXY(aVBnd.XY());
198   gp_Lin2d aLin(aPBnd, aDBnd); //line in direction of derivative
199
200   gp_Pnt2d thePole;
201   gp_Dir2d theBoundDir;
202   switch (NumberOfSingularCase)
203   {
204   case 1:
205     {
206       thePole.SetCoord(u1, v1);
207       theBoundDir.SetCoord(0., 1.);
208       break;
209     }
210   case 2:
211     {
212       thePole.SetCoord(u2, v1);
213       theBoundDir.SetCoord(0., 1.);
214       break;
215     }
216   case 3:
217     {
218       thePole.SetCoord(u1, v1);
219       theBoundDir.SetCoord(1., 0.);
220       break;
221     }
222   case 4:
223     {
224       thePole.SetCoord(u1, v2);
225       theBoundDir.SetCoord(1., 0.);
226       break;
227     }
228   }
229   gp_Lin2d BoundLin(thePole, theBoundDir); //one of the bounds of rectangle
230   Standard_Real ParOnLin = 0.;
231   if (theBoundDir.IsParallel(aDBnd, 100.*Precision::Angular()))
232   {
233     ParOnLin = ElCLib::Parameter(aLin, thePole);
234   }
235   else
236   {
237     Standard_Real U1x = BoundLin.Direction().X();
238     Standard_Real U1y = BoundLin.Direction().Y();
239     Standard_Real U2x = aLin.Direction().X();
240     Standard_Real U2y = aLin.Direction().Y();
241     Standard_Real Uo21x = aLin.Location().X() - BoundLin.Location().X();
242     Standard_Real Uo21y = aLin.Location().Y() - BoundLin.Location().Y();
243
244     Standard_Real D = U1y*U2x - U1x*U2y;
245
246     ParOnLin = (Uo21y * U1x - Uo21x * U1y) / D; //parameter of intersection point
247   }
248   
249   Handle(Geom2d_Line) aSegLine = new Geom2d_Line(aLin);
250   aSegment = (FirstOrLast == 0)?
251     new Geom2d_TrimmedCurve(aSegLine, ParOnLin, 0.) :
252     new Geom2d_TrimmedCurve(aSegLine, 0., ParOnLin);
253   
254   Standard_Boolean anAfter = FirstOrLast != 0;
255   aCompCurve.Add(aSegment, aTol, anAfter);
256   aRes = aCompCurve.BSplineCurve();
257 }
258
259 //=======================================================================
260 //function : Project
261 //purpose  : 
262 //=======================================================================
263
264 static void Project(ProjLib_Projector& P, Handle(Adaptor3d_Curve)& C)
265 {
266   GeomAbs_CurveType CType = C->GetType();
267   switch (CType) {
268     case GeomAbs_Line:
269       P.Project(C->Line());
270       break;
271     case GeomAbs_Circle:
272       P.Project(C->Circle());
273       break;
274     case GeomAbs_Ellipse:
275       P.Project(C->Ellipse());
276       break;
277     case GeomAbs_Hyperbola:
278       P.Project(C->Hyperbola());
279       break;
280     case GeomAbs_Parabola:
281       P.Project(C->Parabola());
282       break;
283     case GeomAbs_BSplineCurve:
284     case GeomAbs_BezierCurve:
285     case GeomAbs_OffsetCurve:
286     case GeomAbs_OtherCurve:    // try the approximation
287       break;
288     default:
289       throw Standard_NoSuchObject(" ");
290   }
291 }
292
293 //=======================================================================
294 //function : ProjLib_ProjectedCurve
295 //purpose  : 
296 //=======================================================================
297
298 ProjLib_ProjectedCurve::ProjLib_ProjectedCurve() :
299   myTolerance(Precision::Confusion()),
300   myDegMin(-1), myDegMax(-1),
301   myMaxSegments(-1),
302   myMaxDist(-1.),
303   myBndPnt(AppParCurves_TangencyPoint)
304 {
305 }
306
307
308 //=======================================================================
309 //function : ProjLib_ProjectedCurve
310 //purpose  : 
311 //=======================================================================
312
313 ProjLib_ProjectedCurve::ProjLib_ProjectedCurve
314 (const Handle(Adaptor3d_Surface)& S) :
315   myTolerance(Precision::Confusion()),
316   myDegMin(-1), myDegMax(-1),
317   myMaxSegments(-1),
318   myMaxDist(-1.),
319   myBndPnt(AppParCurves_TangencyPoint)
320 {
321   Load(S);
322 }
323
324
325 //=======================================================================
326 //function : ProjLib_ProjectedCurve
327 //purpose  : 
328 //=======================================================================
329
330 ProjLib_ProjectedCurve::ProjLib_ProjectedCurve
331 (const Handle(Adaptor3d_Surface)& S,
332  const Handle(Adaptor3d_Curve)& C) :
333   myTolerance(Precision::Confusion()),
334   myDegMin(-1), myDegMax(-1),
335   myMaxSegments(-1),
336   myMaxDist(-1.),
337   myBndPnt(AppParCurves_TangencyPoint)
338 {
339   Load(S);
340   Perform(C);
341 }
342
343
344 //=======================================================================
345 //function : ProjLib_ProjectedCurve
346 //purpose  : 
347 //=======================================================================
348
349 ProjLib_ProjectedCurve::ProjLib_ProjectedCurve
350 (const Handle(Adaptor3d_Surface)& S,
351  const Handle(Adaptor3d_Curve)&   C,
352  const Standard_Real             Tol) :
353   myTolerance(Max(Tol, Precision::Confusion())),
354   myDegMin(-1), myDegMax(-1),
355   myMaxSegments(-1),
356   myMaxDist(-1.),
357   myBndPnt(AppParCurves_TangencyPoint)
358 {
359   Load(S);
360   Perform(C);
361 }
362
363 //=======================================================================
364 //function : ShallowCopy
365 //purpose  : 
366 //=======================================================================
367
368 Handle(Adaptor2d_Curve2d) ProjLib_ProjectedCurve::ShallowCopy() const
369 {
370   Handle(ProjLib_ProjectedCurve) aCopy = new ProjLib_ProjectedCurve();
371
372   aCopy->myTolerance   = myTolerance;
373   if (!mySurface.IsNull())
374   {
375     aCopy->mySurface = mySurface->ShallowCopy();
376   }
377   if (!myCurve.IsNull())
378   {
379     aCopy->myCurve = myCurve->ShallowCopy();
380   }
381   aCopy->myResult      = myResult;
382   aCopy->myDegMin      = myDegMin;
383   aCopy->myDegMax      = myDegMax;
384   aCopy->myMaxSegments = myMaxSegments;
385   aCopy->myMaxDist     = myMaxDist;
386   aCopy->myBndPnt      = myBndPnt;
387
388   return aCopy;
389 }
390
391 //=======================================================================
392 //function : Load
393 //purpose  : 
394 //=======================================================================
395
396 void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_Surface)& S)
397 {
398   mySurface = S ;
399 }
400
401 //=======================================================================
402 //function : Load
403 //purpose  : 
404 //=======================================================================
405
406 void ProjLib_ProjectedCurve::Load(const Standard_Real theTol)
407 {
408   myTolerance = theTol;
409 }
410
411 //=======================================================================
412 //function : Perform
413 //purpose  : 
414 //=======================================================================
415
416 void ProjLib_ProjectedCurve::Perform(const Handle(Adaptor3d_Curve)& C)
417 {
418   myTolerance = Max(myTolerance, Precision::Confusion());
419   myCurve = C;
420   Standard_Real FirstPar = C->FirstParameter();
421   Standard_Real LastPar  = C->LastParameter();
422   GeomAbs_SurfaceType SType = mySurface->GetType();
423   GeomAbs_CurveType   CType = myCurve->GetType();
424   Standard_Boolean isAnalyticalSurf = Standard_True;
425   Standard_Boolean IsTrimmed[2] = { Standard_False, Standard_False };
426   Standard_Integer SingularCase[2];
427   const Standard_Real eps = 0.01;
428   Standard_Real TolConf = Precision::Confusion();
429   Standard_Real dt = (LastPar - FirstPar) * eps;
430   Standard_Real U1 = 0.0, U2 = 0.0, V1 = 0.0, V2 = 0.0;
431   U1 = mySurface->FirstUParameter();
432   U2 = mySurface->LastUParameter();
433   V1 = mySurface->FirstVParameter();
434   V2 = mySurface->LastVParameter();
435
436   switch (SType)
437   {
438     case GeomAbs_Plane:
439       {
440         ProjLib_Plane P(mySurface->Plane());
441         Project(P,myCurve);
442         myResult = P;
443       }
444       break;
445
446     case GeomAbs_Cylinder:
447       {
448         ProjLib_Cylinder P(mySurface->Cylinder());
449         Project(P,myCurve);
450         myResult = P;
451       }
452       break;
453
454     case GeomAbs_Cone:
455       {
456         ProjLib_Cone P(mySurface->Cone());
457         Project(P,myCurve);
458         myResult = P;
459       }
460       break;
461
462     case GeomAbs_Sphere:
463       {
464         ProjLib_Sphere P(mySurface->Sphere());
465         Project(P,myCurve);
466         if ( P.IsDone())
467         {
468           // on met dans la pseudo-periode ( car Sphere n'est pas
469           // periodique en V !)
470           P.SetInBounds(myCurve->FirstParameter());
471         }
472         else
473         {
474           const Standard_Real Vmax = M_PI / 2.;
475           const Standard_Real Vmin = -Vmax;
476           const Standard_Real minang = 1.e-5 * M_PI;
477           gp_Sphere aSph = mySurface->Sphere();
478           Standard_Real anR = aSph.Radius();
479           Standard_Real f = myCurve->FirstParameter();
480           Standard_Real l = myCurve->LastParameter();
481
482           gp_Pnt Pf = myCurve->Value(f);
483           gp_Pnt Pl = myCurve->Value(l);
484           gp_Pnt aLoc = aSph.Position().Location();
485           Standard_Real maxdist = Max(Pf.Distance(aLoc), Pl.Distance(aLoc));
486           TolConf = Max(anR * minang, Abs(anR - maxdist));
487
488           //Surface has pole at V = Vmin and Vmax
489           gp_Pnt Pole = mySurface->Value(U1, Vmin);
490           TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3, TolConf);
491           Pole = mySurface->Value(U1, Vmax);
492           TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4, TolConf);
493         }
494         myResult = P;
495       }
496       break;
497
498     case GeomAbs_Torus:
499       {
500         ProjLib_Torus P(mySurface->Torus());
501         Project(P,myCurve);
502         myResult = P;
503       }
504       break;
505
506     case GeomAbs_BezierSurface:
507     case GeomAbs_BSplineSurface:
508       {
509         isAnalyticalSurf = Standard_False;
510         Standard_Real f, l;
511         f = myCurve->FirstParameter();
512         l = myCurve->LastParameter();
513         dt = (l - f) * eps;
514
515         const Adaptor3d_Surface& S = *mySurface;
516         U1 = S.FirstUParameter();
517         U2 = S.LastUParameter();
518         V1 = S.FirstVParameter();
519         V2 = S.LastVParameter();
520
521         if(IsoIsDeg(S, U1, GeomAbs_IsoU, 0., myTolerance))
522         {
523           //Surface has pole at U = Umin
524           gp_Pnt Pole = mySurface->Value(U1, V1);
525           TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 1, TolConf);
526         }
527
528         if(IsoIsDeg(S, U2, GeomAbs_IsoU, 0., myTolerance))
529         {
530           //Surface has pole at U = Umax
531           gp_Pnt Pole = mySurface->Value(U2, V1);
532           TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 2, TolConf);
533         }
534
535         if(IsoIsDeg(S, V1, GeomAbs_IsoV, 0., myTolerance))
536         {
537           //Surface has pole at V = Vmin
538           gp_Pnt Pole = mySurface->Value(U1, V1);
539           TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3, TolConf);
540         }
541
542         if(IsoIsDeg(S, V2, GeomAbs_IsoV, 0., myTolerance))
543         {
544           //Surface has pole at V = Vmax
545           gp_Pnt Pole = mySurface->Value(U1, V2);
546           TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4, TolConf);
547         }
548
549         ProjLib_ComputeApproxOnPolarSurface polar;
550         polar.SetTolerance(myTolerance);
551         polar.SetDegree(myDegMin, myDegMax);
552         polar.SetMaxSegments(myMaxSegments);
553         polar.SetBndPnt(myBndPnt);
554         polar.SetMaxDist(myMaxDist);
555         polar.Perform(myCurve, mySurface); 
556
557         Handle(Geom2d_BSplineCurve) aRes = polar.BSpline();
558
559         if (!aRes.IsNull())
560         {
561           myTolerance = polar.Tolerance();
562           if( (IsTrimmed[0] || IsTrimmed[1]))
563           {
564             if(IsTrimmed[0])
565             {
566               //Add segment before start of curve
567               f = myCurve->FirstParameter();
568               ExtendC2d(aRes, f, -dt, U1, U2, V1, V2, 0, SingularCase[0]);
569             }
570             if(IsTrimmed[1])
571             {
572               //Add segment after end of curve
573               l = myCurve->LastParameter();
574               ExtendC2d(aRes, l,  dt, U1, U2, V1, V2, 1, SingularCase[1]);
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           myResult.SetBSpline(aRes);
583           myResult.Done();
584           myResult.SetType(GeomAbs_BSplineCurve);
585         }
586       }
587       break;
588
589     default:
590       {
591         isAnalyticalSurf = Standard_False;
592         Standard_Real Vsingular[2] = {0.0 , 0.0}; //for surfaces of revolution
593         Standard_Real f = 0.0, l = 0.0;
594         dt = 0.0;
595
596         if(mySurface->GetType() == GeomAbs_SurfaceOfRevolution)
597         {
598           //Check possible singularity
599
600           gp_Pnt P = mySurface->AxeOfRevolution().Location();
601           gp_Dir N = mySurface->AxeOfRevolution().Direction();
602
603           gp_Lin L(P, N);
604
605           f = myCurve->FirstParameter();
606           l = myCurve->LastParameter();
607           dt = (l - f) * eps;
608
609           P = myCurve->Value(f);
610           if(L.Distance(P) < Precision::Confusion())
611           {
612             IsTrimmed[0] = Standard_True;
613             f = f + dt;
614             myCurve = myCurve->Trim(f, l, Precision::Confusion());
615             // Searching the parameter on the basis curve for surface of revolution
616             Extrema_ExtPC anExtr(P, *mySurface->BasisCurve(), myTolerance);
617             if (anExtr.IsDone())
618             {
619               Standard_Real aMinDist = RealLast();
620               for(Standard_Integer anIdx = 1; anIdx <= anExtr.NbExt(); anIdx++)
621               {
622                 if (anExtr.IsMin(anIdx) &&
623                     anExtr.SquareDistance(anIdx) < aMinDist)
624                 {
625                   aMinDist = anExtr.SquareDistance(anIdx);
626                   Vsingular[0] = anExtr.Point(anIdx).Parameter();
627                 }
628               }
629             }
630             else
631               Vsingular[0] = ElCLib::Parameter(L, P);
632             //SingularCase[0] = 3;
633           }
634
635           P = myCurve->Value(l);
636           if(L.Distance(P) < Precision::Confusion())
637           {
638             IsTrimmed[1] = Standard_True;
639             l = l - dt;
640             myCurve = myCurve->Trim(f, l, Precision::Confusion());
641             // Searching the parameter on the basis curve for surface of revolution
642             Extrema_ExtPC anExtr(P, *mySurface->BasisCurve(), myTolerance);
643             if (anExtr.IsDone())
644             {
645               Standard_Real aMinDist = RealLast();
646               for(Standard_Integer anIdx = 1; anIdx <= anExtr.NbExt(); anIdx++)
647               {
648                 if (anExtr.IsMin(anIdx) &&
649                     anExtr.SquareDistance(anIdx) < aMinDist)
650                 {
651                   aMinDist = anExtr.SquareDistance(anIdx);
652                   Vsingular[1] = anExtr.Point(anIdx).Parameter();
653                 }
654               }
655             }
656             else
657               Vsingular[1] = ElCLib::Parameter(L, P);
658             //SingularCase[1] = 4;
659           }
660         }
661
662         Standard_Real aTolU = Max(ComputeTolU(mySurface, myTolerance), Precision::Confusion());
663         Standard_Real aTolV = Max(ComputeTolV(mySurface, myTolerance), Precision::Confusion());
664         Standard_Real aTol2d = Sqrt(aTolU*aTolU + aTolV*aTolV);
665
666         Standard_Real aMaxDist = 100. * myTolerance;
667         if(myMaxDist > 0.)
668         {
669           aMaxDist = myMaxDist;
670         }
671         Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve (mySurface,myCurve, aTolU, aTolV, aMaxDist);
672
673         // Normalement, dans le cadre de ProjLib, le resultat 
674         // doit etre une et une seule courbe !!!
675         // De plus, cette courbe ne doit pas etre Single point
676         Standard_Integer NbCurves = HProjector->NbCurves();
677         Standard_Real Udeb = 0.0,Ufin = 0.0;
678         if (NbCurves > 0)
679         {
680           HProjector->Bounds(1, Udeb, Ufin);
681         }
682         else 
683         {
684           return;
685         }
686         // Approximons cette courbe algorithmique.
687         Standard_Boolean Only3d = Standard_False;
688         Standard_Boolean Only2d = Standard_True;
689         GeomAbs_Shape Continuity = GeomAbs_C1;
690         if(myBndPnt == AppParCurves_PassPoint)
691         {
692           Continuity = GeomAbs_C0;
693         }
694         Standard_Integer MaxDegree = 14;
695         if(myDegMax > 0)
696         {
697           MaxDegree = myDegMax;
698         }
699         Standard_Integer MaxSeg    = 16;
700         if(myMaxSegments > 0)
701         {
702           MaxSeg = myMaxSegments;
703         }
704
705         Approx_CurveOnSurface appr(HProjector, mySurface, Udeb, Ufin, myTolerance);
706         appr.Perform(MaxSeg, MaxDegree, Continuity, Only3d, Only2d);
707
708         Handle(Geom2d_BSplineCurve) aRes = appr.Curve2d();
709
710         if (!aRes.IsNull())
711         {
712           aTolU = appr.MaxError2dU();
713           aTolV = appr.MaxError2dV();
714           Standard_Real aNewTol2d = Sqrt(aTolU*aTolU + aTolV*aTolV);
715           myTolerance *= (aNewTol2d / aTol2d);
716           if(IsTrimmed[0] || IsTrimmed[1])
717           {
718             // Treatment only for surface of revolution
719             Standard_Real u1, u2, v1, v2;
720             u1 = mySurface->FirstUParameter();
721             u2 = mySurface->LastUParameter();
722             v1 = mySurface->FirstVParameter();
723             v2 = mySurface->LastVParameter();
724
725             if(IsTrimmed[0])
726             {
727               //Add segment before start of curve
728               ExtendC2d(aRes, f, -dt, u1, u2, Vsingular[0], v2, 0, 3);
729             }
730             if(IsTrimmed[1])
731             {
732               //Add segment after end of curve
733               ExtendC2d(aRes, l,  dt, u1, u2, v1, Vsingular[1], 1, 4);
734             }
735             Handle(Geom2d_Curve) NewCurve2d;
736             GeomLib::SameRange(Precision::PConfusion(), aRes,
737               aRes->FirstParameter(), aRes->LastParameter(),
738               FirstPar, LastPar, NewCurve2d);
739             aRes = Handle(Geom2d_BSplineCurve)::DownCast(NewCurve2d);
740             if(Continuity == GeomAbs_C0)
741             {
742               // try to smoother the Curve GeomAbs_C1.
743               Standard_Integer aDeg = aRes->Degree();
744               Standard_Boolean OK = Standard_True;
745               Standard_Real aSmoothTol = Max(Precision::Confusion(), aNewTol2d);
746               for (Standard_Integer ij = 2; ij < aRes->NbKnots(); ij++) {
747                 OK = OK && aRes->RemoveKnot(ij, aDeg-1, aSmoothTol);  
748               }
749             }
750           }
751
752           myResult.SetBSpline(aRes);
753           myResult.Done();
754           myResult.SetType(GeomAbs_BSplineCurve);
755         }
756       }
757   }
758
759   if ( !myResult.IsDone() && isAnalyticalSurf)
760   {
761     // Use advanced analytical projector if base analytical projection failed.
762     ProjLib_ComputeApprox Comp;
763     Comp.SetTolerance(myTolerance);
764     Comp.SetDegree(myDegMin, myDegMax);
765     Comp.SetMaxSegments(myMaxSegments);
766     Comp.SetBndPnt(myBndPnt);
767     Comp.Perform(myCurve, mySurface);
768     if (Comp.Bezier().IsNull() && Comp.BSpline().IsNull())
769       return; // advanced projector has been failed too
770     myResult.Done();
771     Handle(Geom2d_BSplineCurve) aRes;
772     if (Comp.BSpline().IsNull())
773     {
774       aRes = Geom2dConvert::CurveToBSplineCurve(Comp.Bezier());
775     }
776     else
777     {
778       aRes = Comp.BSpline();
779     }
780     if ((IsTrimmed[0] || IsTrimmed[1]))
781     {
782       if (IsTrimmed[0])
783       {
784         //Add segment before start of curve
785         Standard_Real f = myCurve->FirstParameter();
786         ExtendC2d(aRes, f, -dt, U1, U2, V1, V2, 0, SingularCase[0]);
787       }
788       if (IsTrimmed[1])
789       {
790         //Add segment after end of curve
791         Standard_Real l = myCurve->LastParameter();
792         ExtendC2d(aRes, l, dt, U1, U2, V1, V2, 1, SingularCase[1]);
793       }
794       Handle(Geom2d_Curve) NewCurve2d;
795       GeomLib::SameRange(Precision::PConfusion(), aRes,
796         aRes->FirstParameter(), aRes->LastParameter(),
797         FirstPar, LastPar, NewCurve2d);
798       aRes = Handle(Geom2d_BSplineCurve)::DownCast(NewCurve2d);
799       myResult.SetBSpline(aRes);
800       myResult.SetType(GeomAbs_BSplineCurve);
801     }
802     else
803     {
804       // set the type
805       if (SType == GeomAbs_Plane && CType == GeomAbs_BezierCurve)
806       {
807         myResult.SetType(GeomAbs_BezierCurve);
808         myResult.SetBezier(Comp.Bezier());
809       }
810       else
811       {
812         myResult.SetType(GeomAbs_BSplineCurve);
813         myResult.SetBSpline(Comp.BSpline());
814       }
815     }
816     // set the periodicity flag
817     if (SType == GeomAbs_Plane        &&
818       CType == GeomAbs_BSplineCurve &&
819       myCurve->IsPeriodic())
820     {
821       myResult.SetPeriodic();
822     }
823     myTolerance = Comp.Tolerance();
824   }
825
826   Standard_Boolean isPeriodic[] = {mySurface->IsUPeriodic(),
827                                    mySurface->IsVPeriodic()};
828   if (myResult.IsDone() &&
829      (isPeriodic[0] || isPeriodic[1]))
830   {
831     // Check result curve to be in params space.
832
833     // U and V parameters space correspondingly.
834     const Standard_Real aSurfFirstPar[2] = {mySurface->FirstUParameter(),
835                                             mySurface->FirstVParameter()};
836     Standard_Real aSurfPeriod[2] = {0.0, 0.0};
837     if (isPeriodic[0])
838       aSurfPeriod[0] = mySurface->UPeriod();
839     if (isPeriodic[1])
840       aSurfPeriod[1] = mySurface->VPeriod();
841
842     for(Standard_Integer anIdx = 1; anIdx <= 2; anIdx++)
843     {
844       if (!isPeriodic[anIdx - 1])
845         continue;
846
847       if (myResult.GetType() == GeomAbs_BSplineCurve)
848       {
849         NCollection_DataMap<Standard_Integer, Standard_Integer> aMap; 
850         Handle(Geom2d_BSplineCurve) aRes = myResult.BSpline();
851         const Standard_Integer aDeg = aRes->Degree();
852
853         for(Standard_Integer aKnotIdx = aRes->FirstUKnotIndex();
854                              aKnotIdx < aRes->LastUKnotIndex();
855                              aKnotIdx++)
856         {
857           const Standard_Real aFirstParam = aRes->Knot(aKnotIdx);
858           const Standard_Real aLastParam  = aRes->Knot(aKnotIdx + 1);
859
860           for(Standard_Integer anIntIdx = 0; anIntIdx <= aDeg; anIntIdx++)
861           {
862             const Standard_Real aCurrParam = aFirstParam + (aLastParam - aFirstParam) * anIntIdx / (aDeg + 1.0);
863             gp_Pnt2d aPnt2d;
864             aRes->D0(aCurrParam, aPnt2d);
865
866             Standard_Integer aMapKey = Standard_Integer ((aPnt2d.Coord(anIdx) - aSurfFirstPar[anIdx - 1]) / aSurfPeriod[anIdx - 1]);
867
868             if (aPnt2d.Coord(anIdx) - aSurfFirstPar[anIdx - 1] < 0.0)
869               aMapKey--;
870
871             if (aMap.IsBound(aMapKey))
872               aMap.ChangeFind(aMapKey)++;
873             else
874               aMap.Bind(aMapKey, 1);
875           }
876         }
877
878         Standard_Integer aMaxPoints = 0, aMaxIdx = 0;
879         NCollection_DataMap<Standard_Integer, Standard_Integer>::Iterator aMapIter(aMap);
880         for( ; aMapIter.More(); aMapIter.Next())
881         {
882           if (aMapIter.Value() > aMaxPoints)
883           {
884             aMaxPoints = aMapIter.Value();
885             aMaxIdx = aMapIter.Key();
886           }
887         }
888         if (aMaxIdx != 0)
889         {
890           gp_Pnt2d aFirstPnt = aRes->Value(aRes->FirstParameter());
891           gp_Pnt2d aSecondPnt = aFirstPnt;
892           aSecondPnt.SetCoord(anIdx, aFirstPnt.Coord(anIdx) - aSurfPeriod[anIdx - 1] * aMaxIdx);
893           aRes->Translate(gp_Vec2d(aFirstPnt, aSecondPnt));
894         }
895       }
896
897       if (myResult.GetType() == GeomAbs_Line)
898       {
899         Standard_Real aT1 = myCurve->FirstParameter();
900         Standard_Real aT2 = myCurve->LastParameter();
901
902         if (anIdx == 1)
903         {
904           // U param space.
905           myResult.UFrame(aT1, aT2, aSurfFirstPar[anIdx - 1], aSurfPeriod[anIdx - 1]);
906         }
907         else
908         {
909           // V param space.
910           myResult.VFrame(aT1, aT2, aSurfFirstPar[anIdx - 1], aSurfPeriod[anIdx - 1]);
911         }
912       }
913     }
914   }
915 }
916
917 //=======================================================================
918 //function : SetDegree
919 //purpose  : 
920 //=======================================================================
921 void ProjLib_ProjectedCurve::SetDegree(const Standard_Integer theDegMin, 
922                                        const Standard_Integer theDegMax)
923 {
924   myDegMin = theDegMin;
925   myDegMax = theDegMax;
926 }
927 //=======================================================================
928 //function : SetMaxSegments
929 //purpose  : 
930 //=======================================================================
931 void ProjLib_ProjectedCurve::SetMaxSegments(const Standard_Integer theMaxSegments)
932 {
933   myMaxSegments = theMaxSegments;
934 }
935
936 //=======================================================================
937 //function : SetBndPnt
938 //purpose  : 
939 //=======================================================================
940 void ProjLib_ProjectedCurve::SetBndPnt(const AppParCurves_Constraint theBndPnt)
941 {
942   myBndPnt = theBndPnt;
943 }
944
945 //=======================================================================
946 //function : SetMaxDist
947 //purpose  : 
948 //=======================================================================
949 void ProjLib_ProjectedCurve::SetMaxDist(const Standard_Real theMaxDist)
950 {
951   myMaxDist = theMaxDist;
952 }
953
954 //=======================================================================
955 //function : GetSurface
956 //purpose  : 
957 //=======================================================================
958
959 const Handle(Adaptor3d_Surface)& ProjLib_ProjectedCurve::GetSurface() const
960 {
961   return mySurface;
962 }
963
964
965 //=======================================================================
966 //function : GetCurve
967 //purpose  : 
968 //=======================================================================
969
970 const Handle(Adaptor3d_Curve)& ProjLib_ProjectedCurve::GetCurve() const
971 {
972   return myCurve;
973 }
974
975
976 //=======================================================================
977 //function : GetTolerance
978 //purpose  : 
979 //=======================================================================
980
981 Standard_Real ProjLib_ProjectedCurve::GetTolerance() const 
982 {
983   return myTolerance;
984 }
985
986
987 //=======================================================================
988 //function : FirstParameter
989 //purpose  : 
990 //=======================================================================
991
992 Standard_Real ProjLib_ProjectedCurve::FirstParameter() const 
993 {
994   return myCurve->FirstParameter();
995 }
996
997
998 //=======================================================================
999 //function : LastParameter
1000 //purpose  : 
1001 //=======================================================================
1002
1003 Standard_Real ProjLib_ProjectedCurve::LastParameter() const 
1004 {
1005   return myCurve->LastParameter();
1006 }
1007
1008
1009 //=======================================================================
1010 //function : Continuity
1011 //purpose  : 
1012 //=======================================================================
1013
1014 GeomAbs_Shape ProjLib_ProjectedCurve::Continuity() const
1015 {
1016   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Continuity() - method is not implemented");
1017 }
1018
1019
1020 //=======================================================================
1021 //function : NbIntervals
1022 //purpose  : 
1023 //=======================================================================
1024
1025 Standard_Integer ProjLib_ProjectedCurve::NbIntervals(const GeomAbs_Shape ) const 
1026 {
1027   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::NbIntervals() - method is not implemented");
1028 }
1029
1030
1031 //=======================================================================
1032 //function : Intervals
1033 //purpose  : 
1034 //=======================================================================
1035
1036 //void ProjLib_ProjectedCurve::Intervals(TColStd_Array1OfReal&  T,
1037 void ProjLib_ProjectedCurve::Intervals(TColStd_Array1OfReal&  ,
1038                                        const GeomAbs_Shape ) const 
1039 {
1040   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Intervals() - method is not implemented");
1041 }
1042
1043
1044 //=======================================================================
1045 //function : IsClosed
1046 //purpose  : 
1047 //=======================================================================
1048
1049 Standard_Boolean ProjLib_ProjectedCurve::IsClosed() const
1050 {
1051   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::IsClosed() - method is not implemented");
1052 }
1053
1054
1055 //=======================================================================
1056 //function : IsPeriodic
1057 //purpose  : 
1058 //=======================================================================
1059
1060 Standard_Boolean ProjLib_ProjectedCurve::IsPeriodic() const
1061 {
1062   return myResult.IsPeriodic();
1063 }
1064
1065
1066 //=======================================================================
1067 //function : Period
1068 //purpose  : 
1069 //=======================================================================
1070
1071 Standard_Real ProjLib_ProjectedCurve::Period() const
1072 {
1073   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Period() - method is not implemented");
1074 }
1075
1076
1077 //=======================================================================
1078 //function : Value
1079 //purpose  : 
1080 //=======================================================================
1081
1082 gp_Pnt2d ProjLib_ProjectedCurve::Value(const Standard_Real ) const 
1083 {
1084   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Value() - method is not implemented");
1085 }
1086
1087
1088 //=======================================================================
1089 //function : D0
1090 //purpose  : 
1091 //=======================================================================
1092
1093 void ProjLib_ProjectedCurve::D0(const Standard_Real , gp_Pnt2d& ) const
1094 {
1095   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D0() - method is not implemented");
1096 }
1097
1098
1099 //=======================================================================
1100 //function : D1
1101 //purpose  : 
1102 //=======================================================================
1103
1104 void ProjLib_ProjectedCurve::D1(const Standard_Real ,
1105                                       gp_Pnt2d&     , 
1106                                       gp_Vec2d&     ) const 
1107 {
1108   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D1() - method is not implemented");
1109 }
1110
1111
1112 //=======================================================================
1113 //function : D2
1114 //purpose  : 
1115 //=======================================================================
1116
1117 void ProjLib_ProjectedCurve::D2(const Standard_Real , 
1118                                       gp_Pnt2d&     , 
1119                                       gp_Vec2d&     , 
1120                                       gp_Vec2d&     ) const 
1121 {
1122   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D2() - method is not implemented");
1123 }
1124
1125
1126 //=======================================================================
1127 //function : D3
1128 //purpose  : 
1129 //=======================================================================
1130
1131 void ProjLib_ProjectedCurve::D3(const Standard_Real, 
1132                                       gp_Pnt2d&, 
1133                                       gp_Vec2d&, 
1134                                       gp_Vec2d&, 
1135                                       gp_Vec2d&) const 
1136 {
1137   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D3() - method is not implemented");
1138 }
1139
1140
1141 //=======================================================================
1142 //function : DN
1143 //purpose  : 
1144 //=======================================================================
1145
1146 gp_Vec2d ProjLib_ProjectedCurve::DN(const Standard_Real, 
1147                                     const Standard_Integer) const 
1148 {
1149   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::DN() - method is not implemented");
1150 }
1151
1152
1153 //=======================================================================
1154 //function : Resolution
1155 //purpose  : 
1156 //=======================================================================
1157
1158 Standard_Real ProjLib_ProjectedCurve::Resolution(const Standard_Real) const 
1159 {
1160   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Resolution() - method is not implemented");
1161 }
1162     
1163
1164 //=======================================================================
1165 //function : GetType
1166 //purpose  : 
1167 //=======================================================================
1168
1169 GeomAbs_CurveType ProjLib_ProjectedCurve::GetType() const
1170 {
1171   return myResult.GetType();
1172 }
1173
1174
1175 //=======================================================================
1176 //function : Line
1177 //purpose  : 
1178 //=======================================================================
1179
1180 gp_Lin2d ProjLib_ProjectedCurve::Line() const
1181 {
1182   return myResult.Line();
1183 }
1184
1185
1186 //=======================================================================
1187 //function : Circle
1188 //purpose  : 
1189 //=======================================================================
1190
1191 gp_Circ2d ProjLib_ProjectedCurve::Circle() const
1192 {
1193   return myResult.Circle();
1194 }
1195
1196
1197 //=======================================================================
1198 //function : Ellipse
1199 //purpose  : 
1200 //=======================================================================
1201
1202 gp_Elips2d ProjLib_ProjectedCurve::Ellipse() const
1203 {
1204   return myResult.Ellipse();
1205 }
1206
1207
1208 //=======================================================================
1209 //function : Hyperbola
1210 //purpose  : 
1211 //=======================================================================
1212
1213 gp_Hypr2d ProjLib_ProjectedCurve::Hyperbola() const
1214 {
1215   return myResult.Hyperbola();
1216 }
1217
1218
1219 //=======================================================================
1220 //function : Parabola
1221 //purpose  : 
1222 //=======================================================================
1223
1224 gp_Parab2d ProjLib_ProjectedCurve::Parabola() const
1225 {
1226   return myResult.Parabola();
1227 }
1228
1229
1230
1231 //=======================================================================
1232 //function : Degree
1233 //purpose  : 
1234 //=======================================================================
1235
1236 Standard_Integer ProjLib_ProjectedCurve::Degree() const
1237 {
1238   Standard_NoSuchObject_Raise_if 
1239     ( (GetType() != GeomAbs_BSplineCurve) &&
1240       (GetType() != GeomAbs_BezierCurve),
1241      "ProjLib_ProjectedCurve:Degree");
1242   if (GetType() == GeomAbs_BSplineCurve) {
1243     return myResult.BSpline()->Degree();
1244   }
1245   else if (GetType() == GeomAbs_BezierCurve) {
1246     return myResult.Bezier()->Degree();
1247   }
1248
1249   // portage WNT
1250   return 0;
1251 }
1252
1253 //=======================================================================
1254 //function : IsRational
1255 //purpose  : 
1256 //=======================================================================
1257
1258 Standard_Boolean ProjLib_ProjectedCurve::IsRational() const 
1259 {
1260   Standard_NoSuchObject_Raise_if 
1261     ( (GetType() != GeomAbs_BSplineCurve) &&
1262       (GetType() != GeomAbs_BezierCurve),
1263      "ProjLib_ProjectedCurve:IsRational");
1264   if (GetType() == GeomAbs_BSplineCurve) {
1265     return myResult.BSpline()->IsRational();
1266   }
1267   else if (GetType() == GeomAbs_BezierCurve) {
1268     return myResult.Bezier()->IsRational();
1269   }
1270   // portage WNT
1271   return Standard_False;
1272 }
1273
1274 //=======================================================================
1275 //function : NbPoles
1276 //purpose  : 
1277 //=======================================================================
1278
1279 Standard_Integer ProjLib_ProjectedCurve::NbPoles() const
1280 {
1281   Standard_NoSuchObject_Raise_if 
1282     ( (GetType() != GeomAbs_BSplineCurve) &&
1283       (GetType() != GeomAbs_BezierCurve)   
1284      ,"ProjLib_ProjectedCurve:NbPoles"  );
1285   if (GetType() == GeomAbs_BSplineCurve) {
1286     return myResult.BSpline()->NbPoles();
1287   }
1288   else if (GetType() == GeomAbs_BezierCurve) {
1289     return myResult.Bezier()->NbPoles();
1290   }
1291
1292   // portage WNT
1293   return 0;
1294 }
1295
1296 //=======================================================================
1297 //function : NbKnots
1298 //purpose  : 
1299 //=======================================================================
1300
1301 Standard_Integer ProjLib_ProjectedCurve::NbKnots() const 
1302 {
1303   Standard_NoSuchObject_Raise_if ( GetType() != GeomAbs_BSplineCurve, 
1304                                   "ProjLib_ProjectedCurve:NbKnots");
1305   return myResult.BSpline()->NbKnots();
1306 }
1307
1308 //=======================================================================
1309 //function : Bezier
1310 //purpose  : 
1311 //=======================================================================
1312
1313 Handle(Geom2d_BezierCurve) ProjLib_ProjectedCurve::Bezier() const 
1314 {
1315  return myResult.Bezier() ;
1316 }
1317
1318 //=======================================================================
1319 //function : BSpline
1320 //purpose  : 
1321 //=======================================================================
1322
1323 Handle(Geom2d_BSplineCurve) ProjLib_ProjectedCurve::BSpline() const 
1324 {
1325  return myResult.BSpline() ;
1326 }
1327 //=======================================================================
1328 //function : Trim
1329 //purpose  : 
1330 //=======================================================================
1331
1332 Handle(Adaptor2d_Curve2d) ProjLib_ProjectedCurve::Trim 
1333 //(const Standard_Real First,
1334 // const Standard_Real Last,
1335 // const Standard_Real Tolerance) const 
1336 (const Standard_Real ,
1337  const Standard_Real ,
1338  const Standard_Real ) const 
1339 {
1340   throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Trim() - method is not implemented");
1341 }