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