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