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