0026431: Can't cut a sphere from a cylinder
[occt.git] / src / GeomInt / GeomInt_IntSS_1.cxx
1 // Created on: 1995-01-27
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1995-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 #include <algorithm>
18 #include <GeomInt_IntSS.hxx>
19
20 #include <Adaptor3d_TopolTool.hxx>
21 #include <Approx_CurveOnSurface.hxx>
22 #include <ElSLib.hxx>
23 #include <Extrema_ExtPS.hxx>
24 #include <Geom2dAdaptor.hxx>
25 #include <Geom2dAdaptor_Curve.hxx>
26 #include <Geom2dInt_GInter.hxx>
27 #include <Geom2d_Curve.hxx>
28 #include <Geom2d_Line.hxx>
29 #include <Geom2d_TrimmedCurve.hxx>
30 #include <GeomAdaptor.hxx>
31 #include <GeomAdaptor_HSurface.hxx>
32 #include <GeomInt.hxx>
33 #include <GeomInt_LineTool.hxx>
34 #include <GeomInt_WLApprox.hxx>
35 #include <GeomLib_Check2dBSplineCurve.hxx>
36 #include <GeomLib_CheckBSplineCurve.hxx>
37 #include <GeomProjLib.hxx>
38 #include <Geom_BSplineCurve.hxx>
39 #include <Geom_Circle.hxx>
40 #include <Geom_Ellipse.hxx>
41 #include <Geom_Hyperbola.hxx>
42 #include <Geom_Line.hxx>
43 #include <Geom_Parabola.hxx>
44 #include <Geom_TrimmedCurve.hxx>
45 #include <IntPatch_ALine.hxx>
46 #include <IntPatch_ALineToWLine.hxx>
47 #include <IntPatch_GLine.hxx>
48 #include <IntPatch_RLine.hxx>
49 #include <IntPatch_WLine.hxx>
50 #include <IntRes2d_IntersectionSegment.hxx>
51 #include <IntSurf_Quadric.hxx>
52 #include <Geom_Surface.hxx>
53
54 //=======================================================================
55 //function : AdjustUPeriodic
56 //purpose  : 
57 //=======================================================================
58  static void AdjustUPeriodic (const Handle(Geom_Surface)& aS, const Handle(Geom2d_Curve)& aC2D)
59 {
60   if (aC2D.IsNull() || !aS->IsUPeriodic())
61     return;
62   //
63   const Standard_Real aEps=Precision::PConfusion();//1.e-9
64   const Standard_Real aEpsilon=Epsilon(10.);//1.77e-15 
65   //
66   Standard_Real umin,umax,vmin,vmax;
67   aS->Bounds(umin,umax,vmin,vmax);
68   const Standard_Real aPeriod = aS->UPeriod();
69   
70   const Standard_Real aT1=aC2D->FirstParameter();
71   const Standard_Real aT2=aC2D->LastParameter();
72   const Standard_Real aTx=aT1+0.467*(aT2-aT1);
73   const gp_Pnt2d aPx=aC2D->Value(aTx);
74   //
75   Standard_Real aUx=aPx.X();
76   if (fabs(aUx)<aEpsilon)
77     aUx=0.;
78   if (fabs(aUx-aPeriod)<aEpsilon)
79     aUx=aPeriod;
80   //
81   Standard_Real dU=0.;
82   while(aUx <(umin-aEps)) {
83     aUx+=aPeriod;
84     dU+=aPeriod;
85   }
86   while(aUx>(umax+aEps)) {
87     aUx-=aPeriod;
88     dU-=aPeriod;
89   }
90   // 
91   if (dU!=0.) {
92     gp_Vec2d aV2D(dU, 0.);
93     aC2D->Translate(aV2D);
94   }
95 }
96
97  //=======================================================================
98 //function : GetQuadric
99 //purpose  : 
100 //=======================================================================
101  static void GetQuadric(const Handle(GeomAdaptor_HSurface)& HS1, IntSurf_Quadric& quad1)
102 {
103   switch (HS1->Surface().GetType())
104   {
105     case GeomAbs_Plane:    quad1.SetValue(HS1->Surface().Plane()); break;
106     case GeomAbs_Cylinder: quad1.SetValue(HS1->Surface().Cylinder()); break;
107     case GeomAbs_Cone:     quad1.SetValue(HS1->Surface().Cone()); break;
108     case GeomAbs_Sphere:   quad1.SetValue(HS1->Surface().Sphere()); break;
109     case GeomAbs_Torus:    quad1.SetValue(HS1->Surface().Torus()); break;
110     default: Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve");
111   }
112 }
113
114 //=======================================================================
115 //function : Parameters
116 //purpose  : 
117 //=======================================================================
118  static void Parameters(  const Handle(GeomAdaptor_HSurface)& HS1,
119                          const Handle(GeomAdaptor_HSurface)& HS2,
120                          const gp_Pnt& Ptref,
121                          Standard_Real& U1,
122                          Standard_Real& V1,
123                          Standard_Real& U2,
124                          Standard_Real& V2)
125 {
126   IntSurf_Quadric quad1,quad2;
127   //
128   GetQuadric(HS1, quad1);
129   GetQuadric(HS2, quad2);
130   //
131   quad1.Parameters(Ptref,U1,V1);
132   quad2.Parameters(Ptref,U2,V2);
133 }
134
135 //=======================================================================
136 //function : ParametersOfNearestPointOnSurface
137 //purpose  : 
138 //=======================================================================
139 static Standard_Boolean ParametersOfNearestPointOnSurface(const Extrema_ExtPS theExtr,
140                                                           Standard_Real& theU,
141                                                           Standard_Real& theV)
142 {
143   if(!theExtr.IsDone() || !theExtr.NbExt())
144     return Standard_False;
145
146   Standard_Integer anIndex = 1;
147   Standard_Real aMinSQDist = theExtr.SquareDistance(anIndex);
148   for(Standard_Integer i = 2; i <= theExtr.NbExt(); i++)
149   {
150     Standard_Real aSQD = theExtr.SquareDistance(i);
151     if (aSQD < aMinSQDist)
152     {
153       aMinSQDist = aSQD;
154       anIndex = i;
155     }
156   }
157
158   theExtr.Point(anIndex).Parameter(theU, theV);
159
160   return Standard_True;
161 }
162
163 //=======================================================================
164 //function : GetSegmentBoundary
165 //purpose  : 
166 //=======================================================================
167 static void GetSegmentBoundary( const IntRes2d_IntersectionSegment& theSegm,
168                                 const Handle(Geom2d_Curve)& theCurve,
169                                 GeomInt_VectorOfReal& theArrayOfParameters)
170 {
171   Standard_Real aU1 = theCurve->FirstParameter(), aU2 = theCurve->LastParameter();
172
173   if(theSegm.HasFirstPoint())
174   {
175     const IntRes2d_IntersectionPoint& anIPF = theSegm.FirstPoint();
176     aU1 = anIPF.ParamOnFirst();
177   }
178
179   if(theSegm.HasLastPoint())
180   {
181     const IntRes2d_IntersectionPoint& anIPL = theSegm.LastPoint();
182     aU2 = anIPL.ParamOnFirst();
183   }
184
185   theArrayOfParameters.Append(aU1);
186   theArrayOfParameters.Append(aU2);
187 }
188
189 //=======================================================================
190 //function : IntersectCurveAndBoundary
191 //purpose  : 
192 //=======================================================================
193 static void IntersectCurveAndBoundary(const Handle(Geom2d_Curve)& theC2d,
194                                       const Handle(Geom2d_Curve)* const theArrBounds,
195                                       const Standard_Integer theNumberOfCurves,
196                                       const Standard_Real theTol,
197                                       GeomInt_VectorOfReal& theArrayOfParameters)
198 {
199   if(theC2d.IsNull())
200     return;
201
202   Geom2dAdaptor_Curve anAC1(theC2d);
203   for(Standard_Integer aCurID = 0; aCurID < theNumberOfCurves; aCurID++)
204   {
205     if(theArrBounds[aCurID].IsNull())
206       continue;
207
208     Geom2dAdaptor_Curve anAC2(theArrBounds[aCurID]);
209     Geom2dInt_GInter anIntCC2d(anAC1, anAC2, theTol, theTol);
210
211     if(!anIntCC2d.IsDone() || anIntCC2d.IsEmpty())
212       continue;
213
214     for (Standard_Integer aPntID = 1; aPntID <= anIntCC2d.NbPoints(); aPntID++)
215     {
216       const Standard_Real aParam = anIntCC2d.Point(aPntID).ParamOnFirst();
217       theArrayOfParameters.Append(aParam);
218     }
219
220     for (Standard_Integer aSegmID = 1; aSegmID <= anIntCC2d.NbSegments(); aSegmID++)
221     {
222       GetSegmentBoundary(anIntCC2d.Segment(aSegmID), theC2d, theArrayOfParameters);
223     }
224   }
225 }
226
227 //=======================================================================
228 //function : MakeCurve
229 //purpose  : 
230 //=======================================================================
231 void GeomInt_IntSS::MakeCurve(const Standard_Integer Index,
232                                                 const Handle(Adaptor3d_TopolTool) & dom1,
233                                                 const Handle(Adaptor3d_TopolTool) & dom2,
234                                                 const Standard_Real Tol,
235                                                 const Standard_Boolean Approx,
236                                                 const Standard_Boolean ApproxS1,
237                                                 const Standard_Boolean ApproxS2)
238
239 {
240   Standard_Boolean myApprox1, myApprox2, myApprox;
241   Standard_Real Tolpc, myTolApprox;
242   IntPatch_IType typl;
243   Handle(Geom2d_BSplineCurve) H1;
244   Handle(Geom_Surface) aS1, aS2;
245   //
246   Tolpc = Tol;
247   myApprox=Approx;
248   myApprox1=ApproxS1;
249   myApprox2=ApproxS2;
250   myTolApprox=0.0000001;
251   //
252   aS1=myHS1->ChangeSurface().Surface();
253   aS2=myHS2->ChangeSurface().Surface();
254   //
255   Handle(IntPatch_Line) L = myIntersector.Line(Index);
256   typl = L->ArcType();
257   //
258   if(typl==IntPatch_Walking) {
259     Handle(IntPatch_WLine) aWLine (Handle(IntPatch_WLine)::DownCast(L));
260     if(aWLine.IsNull()) {
261       return;
262     }
263     L = aWLine;
264   }
265   //
266   // Line Constructor
267   myLConstruct.Perform(L);
268   if (!myLConstruct.IsDone() || myLConstruct.NbParts() <= 0) {
269     return;
270   }
271   // Do the Curve
272   Standard_Boolean ok;
273   Standard_Integer i, j,  aNbParts;
274   Standard_Real fprm, lprm;
275   Handle(Geom_Curve) newc;
276
277   switch (typl) {
278     //########################################  
279     // Line, Parabola, Hyperbola
280     //########################################  
281   case IntPatch_Lin:
282   case IntPatch_Parabola: 
283   case IntPatch_Hyperbola: {
284     if (typl == IntPatch_Lin) {
285       newc=new Geom_Line (Handle(IntPatch_GLine)::DownCast(L)->Line());
286     }
287     else if (typl == IntPatch_Parabola) {
288       newc=new Geom_Parabola(Handle(IntPatch_GLine)::DownCast(L)->Parabola());
289     }
290     else if (typl == IntPatch_Hyperbola) {
291       newc=new Geom_Hyperbola (Handle(IntPatch_GLine)::DownCast(L)->Hyperbola());
292     }
293     //
294     aNbParts=myLConstruct.NbParts();
295     for (i=1; i<=aNbParts; i++) {
296       myLConstruct.Part(i, fprm, lprm);
297
298       if (!Precision::IsNegativeInfinite(fprm) && 
299         !Precision::IsPositiveInfinite(lprm)) {
300           Handle(Geom_TrimmedCurve) aCT3D=new Geom_TrimmedCurve(newc, fprm, lprm);
301           sline.Append(aCT3D);
302           //
303           if(myApprox1) { 
304             Handle (Geom2d_Curve) C2d;
305             BuildPCurves(fprm, lprm, Tolpc, myHS1->ChangeSurface().Surface(), newc, C2d);
306             if(Tolpc>myTolReached2d || myTolReached2d==0.) { 
307               myTolReached2d=Tolpc;
308             }
309             slineS1.Append(new Geom2d_TrimmedCurve(C2d,fprm,lprm));
310           }
311           else { 
312             slineS1.Append(H1);
313           }
314           //
315           if(myApprox2) { 
316             Handle (Geom2d_Curve) C2d;
317             BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
318             if(Tolpc>myTolReached2d || myTolReached2d==0.) { 
319               myTolReached2d=Tolpc;
320             }
321             //
322             slineS2.Append(new Geom2d_TrimmedCurve(C2d,fprm,lprm));
323           }
324           else { 
325             slineS2.Append(H1);
326           }
327       } // if (!Precision::IsNegativeInfinite(fprm) &&  !Precision::IsPositiveInfinite(lprm))
328
329       else {
330         GeomAbs_SurfaceType typS1 = myHS1->Surface().GetType();
331         GeomAbs_SurfaceType typS2 = myHS2->Surface().GetType();
332         if( typS1 == GeomAbs_SurfaceOfExtrusion ||
333           typS1 == GeomAbs_OffsetSurface ||
334           typS1 == GeomAbs_SurfaceOfRevolution ||
335           typS2 == GeomAbs_SurfaceOfExtrusion ||
336           typS2 == GeomAbs_OffsetSurface ||
337           typS2 == GeomAbs_SurfaceOfRevolution) {
338             sline.Append(newc);
339             slineS1.Append(H1);
340             slineS2.Append(H1);
341             continue;
342         }
343         Standard_Boolean bFNIt, bLPIt;
344         Standard_Real aTestPrm, dT=100.;
345         Standard_Real u1, v1, u2, v2, TolX;
346         //
347         bFNIt=Precision::IsNegativeInfinite(fprm);
348         bLPIt=Precision::IsPositiveInfinite(lprm);
349
350         aTestPrm=0.;
351
352         if (bFNIt && !bLPIt) {
353           aTestPrm=lprm-dT;
354         }
355         else if (!bFNIt && bLPIt) {
356           aTestPrm=fprm+dT;
357         }
358         //
359         gp_Pnt ptref(newc->Value(aTestPrm));
360         //
361         TolX = Precision::Confusion();
362         Parameters(myHS1, myHS2, ptref,  u1, v1, u2, v2);
363         ok = (dom1->Classify(gp_Pnt2d(u1, v1), TolX) != TopAbs_OUT);
364         if(ok) { 
365           ok = (dom2->Classify(gp_Pnt2d(u2,v2),TolX) != TopAbs_OUT); 
366         }
367         if (ok) {
368           sline.Append(newc);
369           slineS1.Append(H1);
370           slineS2.Append(H1);
371         }
372       }
373     }// end of for (i=1; i<=myLConstruct.NbParts(); i++)
374   }// case IntPatch_Lin:  case IntPatch_Parabola:  case IntPatch_Hyperbola:
375   break;
376
377                            //########################################  
378                            // Circle and Ellipse
379                            //########################################  
380   case IntPatch_Circle: 
381   case IntPatch_Ellipse: {
382
383     if (typl == IntPatch_Circle) {
384       newc = new Geom_Circle
385         (Handle(IntPatch_GLine)::DownCast(L)->Circle());
386     }
387     else { 
388       newc = new Geom_Ellipse
389         (Handle(IntPatch_GLine)::DownCast(L)->Ellipse());
390     }
391     //
392     Standard_Real aPeriod, aRealEpsilon;
393     //
394     aRealEpsilon=RealEpsilon();
395     aPeriod=M_PI+M_PI;
396     //
397     aNbParts=myLConstruct.NbParts();
398     //
399     for (i=1; i<=aNbParts; i++) {
400       myLConstruct.Part(i, fprm, lprm);
401       //
402       if (Abs(fprm) > aRealEpsilon || Abs(lprm-aPeriod) > aRealEpsilon) {
403         //==============================================
404         Handle(Geom_TrimmedCurve) aTC3D=new Geom_TrimmedCurve(newc,fprm,lprm);
405         //
406         sline.Append(aTC3D);
407         //
408         fprm=aTC3D->FirstParameter();
409         lprm=aTC3D->LastParameter ();
410         ////    
411         if(myApprox1) { 
412           Handle (Geom2d_Curve) C2d;
413           BuildPCurves(fprm,lprm,Tolpc,myHS1->ChangeSurface().Surface(),newc,C2d);
414           if(Tolpc>myTolReached2d || myTolReached2d==0.) { 
415             myTolReached2d=Tolpc;
416           }
417           slineS1.Append(C2d);
418         }
419         else { //// 
420           slineS1.Append(H1);
421         }
422         //
423         if(myApprox2) { 
424           Handle (Geom2d_Curve) C2d;
425           BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
426           if(Tolpc>myTolReached2d || myTolReached2d==0) { 
427             myTolReached2d=Tolpc;
428           }
429           slineS2.Append(C2d);
430         }
431         else { 
432           slineS2.Append(H1);  
433         }
434         //==============================================        
435       } //if (Abs(fprm) > RealEpsilon() || Abs(lprm-2.*M_PI) > RealEpsilon())
436       //
437       else {//  on regarde si on garde
438         //
439         if (aNbParts==1) {
440           if (Abs(fprm) < RealEpsilon() &&  Abs(lprm-2.*M_PI) < RealEpsilon()) {
441             Handle(Geom_TrimmedCurve) aTC3D=new Geom_TrimmedCurve(newc,fprm,lprm);
442             //
443             sline.Append(aTC3D);
444             fprm=aTC3D->FirstParameter();
445             lprm=aTC3D->LastParameter ();
446
447             if(myApprox1) { 
448               Handle (Geom2d_Curve) C2d;
449               BuildPCurves(fprm,lprm,Tolpc,myHS1->ChangeSurface().Surface(),newc,C2d);
450               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
451                 myTolReached2d=Tolpc;
452               }
453               slineS1.Append(C2d);
454             }
455             else { //// 
456               slineS1.Append(H1);
457             }
458
459             if(myApprox2) { 
460               Handle (Geom2d_Curve) C2d;
461               BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
462               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
463                 myTolReached2d=Tolpc;
464               }
465               slineS2.Append(C2d);
466             }
467             else { 
468               slineS2.Append(H1);
469             }
470             break;
471           }
472         }
473         //
474         Standard_Real aTwoPIdiv17, u1, v1, u2, v2, TolX;
475         //
476         aTwoPIdiv17=2.*M_PI/17.;
477         //
478         for (j=0; j<=17; j++) {
479           gp_Pnt ptref (newc->Value (j*aTwoPIdiv17));
480           TolX = Precision::Confusion();
481
482           Parameters(myHS1, myHS2, ptref, u1, v1, u2, v2);
483           ok = (dom1->Classify(gp_Pnt2d(u1,v1),TolX) != TopAbs_OUT);
484           if(ok) { 
485             ok = (dom2->Classify(gp_Pnt2d(u2,v2),TolX) != TopAbs_OUT);
486           }
487           if (ok) {
488             sline.Append(newc);
489             //==============================================
490             if(myApprox1) { 
491               Handle (Geom2d_Curve) C2d;
492               BuildPCurves(fprm, lprm, Tolpc, myHS1->ChangeSurface().Surface(), newc, C2d);
493               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
494                 myTolReached2d=Tolpc;
495               }
496               slineS1.Append(C2d);
497             }
498             else { 
499               slineS1.Append(H1);  
500             }
501
502             if(myApprox2) { 
503               Handle (Geom2d_Curve) C2d;
504               BuildPCurves(fprm, lprm, Tolpc,myHS2->ChangeSurface().Surface(), newc, C2d);
505               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
506                 myTolReached2d=Tolpc;
507               } 
508               slineS2.Append(C2d);
509             }
510             else { 
511               slineS2.Append(H1);  
512             }
513             break;
514           }//  end of if (ok) {
515         }//  end of for (Standard_Integer j=0; j<=17; j++)
516       }//  end of else { on regarde si on garde
517     }// for (i=1; i<=myLConstruct.NbParts(); i++)
518   }// IntPatch_Circle: IntPatch_Ellipse
519   break;
520
521                          //########################################  
522                          // Analytic
523                          //######################################## 
524   case IntPatch_Analytic: {
525     IntSurf_Quadric quad1,quad2;
526     //
527     GetQuadric(myHS1, quad1);
528     GetQuadric(myHS2, quad2);
529     //=========
530     IntPatch_ALineToWLine convert (quad1, quad2);
531
532     if (!myApprox) {
533       Handle(Geom2d_BSplineCurve) aH1, aH2;
534       //
535       aNbParts=myLConstruct.NbParts();
536       for (i=1; i<=aNbParts; i++) {
537         myLConstruct.Part(i, fprm, lprm);
538         Handle(IntPatch_WLine) WL = 
539           convert.MakeWLine(Handle(IntPatch_ALine)::DownCast(L), fprm, lprm);
540         //
541         if(myApprox1) {
542           aH1 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
543         }
544
545         if(myApprox2) {
546           aH2 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
547         }
548         sline.Append(MakeBSpline(WL,1,WL->NbPnts()));
549         slineS1.Append(aH1);
550         slineS2.Append(aH2);
551       }
552     } // if (!myApprox)
553
554     else { // myApprox=TRUE
555       GeomInt_WLApprox theapp3d;
556       Standard_Real tol2d = myTolApprox;
557       //        
558       theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30, Standard_True);
559
560       aNbParts=myLConstruct.NbParts();
561       for (i=1; i<=aNbParts; i++) {
562         myLConstruct.Part(i, fprm, lprm);
563         Handle(IntPatch_WLine) WL = 
564           convert.MakeWLine(Handle(IntPatch_ALine):: DownCast(L),fprm,lprm);
565
566         theapp3d.Perform(myHS1,myHS2,WL,Standard_True,myApprox1,myApprox2, 1, WL->NbPnts());
567         if (!theapp3d.IsDone()) {
568           //
569           Handle(Geom2d_BSplineCurve) aH1, aH2;
570
571           if(myApprox1) {
572             aH1 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
573           }
574
575           if(myApprox2) {
576             aH2 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
577           }
578           sline.Append(MakeBSpline(WL,1,WL->NbPnts()));
579           slineS1.Append(aH1);
580           slineS2.Append(aH1);
581         }
582         //
583         else {
584           if(myApprox1 || myApprox2) { 
585             if( theapp3d.TolReached2d()>myTolReached2d || myTolReached2d==0) { 
586               myTolReached2d = theapp3d.TolReached2d();
587             }
588           }
589
590           if( theapp3d.TolReached3d()>myTolReached3d || myTolReached3d==0) { 
591             myTolReached3d = theapp3d.TolReached3d();
592           }
593
594           Standard_Integer aNbMultiCurves, nbpoles;
595           aNbMultiCurves=theapp3d.NbMultiCurves();
596           for (j=1; j<=aNbMultiCurves; j++) {
597             const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
598
599             nbpoles = mbspc.NbPoles();
600             TColgp_Array1OfPnt tpoles(1, nbpoles);
601             mbspc.Curve(1, tpoles);
602             Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
603               mbspc.Knots(),
604               mbspc.Multiplicities(),
605               mbspc.Degree());
606
607             GeomLib_CheckBSplineCurve Check(BS, myTolCheck, myTolAngCheck);
608             Check.FixTangent(Standard_True,Standard_True);
609             // 
610             sline.Append(BS);
611             //
612             if(myApprox1) { 
613               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
614               mbspc.Curve(2,tpoles2d);
615               Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
616                 mbspc.Knots(),
617                 mbspc.Multiplicities(),
618                 mbspc.Degree());
619
620               GeomLib_Check2dBSplineCurve newCheck(BS2,myTolCheck,myTolAngCheck);
621               newCheck.FixTangent(Standard_True,Standard_True);
622               slineS1.Append(BS2);              
623             }
624             else {
625               slineS1.Append(H1);
626             }
627
628             if(myApprox2) { 
629               TColgp_Array1OfPnt2d tpoles2d(1, nbpoles);
630               Standard_Integer TwoOrThree;
631               TwoOrThree=myApprox1 ? 3 : 2;
632               mbspc.Curve(TwoOrThree, tpoles2d);
633               Handle(Geom2d_BSplineCurve) BS2 =new Geom2d_BSplineCurve(tpoles2d,
634                 mbspc.Knots(),
635                 mbspc.Multiplicities(),
636                 mbspc.Degree());
637
638               GeomLib_Check2dBSplineCurve newCheck(BS2,myTolCheck,myTolAngCheck);
639               newCheck.FixTangent(Standard_True,Standard_True);
640               //        
641               slineS2.Append(BS2);
642             }
643             else { 
644               slineS2.Append(H1);
645             }
646             // 
647           }// for (j=1; j<=aNbMultiCurves; j++) {
648         }// else from if (!theapp3d.IsDone())
649       }// for (i=1; i<=aNbParts; i++) {
650     }// else { // myApprox=TRUE
651   }// case IntPatch_Analytic:
652   break;
653
654   //########################################  
655   // Walking
656   //######################################## 
657   case IntPatch_Walking:{
658     Handle(IntPatch_WLine) WL = 
659       Handle(IntPatch_WLine)::DownCast(L);
660
661 #ifdef OCCT_DEBUG
662     //WL->Dump(0);
663 #endif
664
665     //
666     Standard_Integer ifprm, ilprm;
667     //
668     if (!myApprox) {
669       aNbParts=myLConstruct.NbParts();
670       for (i=1; i<=aNbParts; i++) {
671         myLConstruct.Part(i, fprm, lprm);
672         ifprm=(Standard_Integer)fprm;
673         ilprm=(Standard_Integer)lprm;
674         //        
675         Handle(Geom2d_BSplineCurve) aH1, aH2;
676
677         if(myApprox1) {
678           aH1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
679         }
680         if(myApprox2) {
681           aH2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
682         }
683         //
684         Handle(Geom_Curve) aBSp=MakeBSpline(WL, ifprm, ilprm);
685         //      
686         sline.Append(aBSp);
687         slineS1.Append(aH1);
688         slineS2.Append(aH2);
689       }
690     }
691     //
692     else {
693       Standard_Boolean bIsDecomposited;
694       Standard_Integer nbiter, aNbSeqOfL;
695       GeomInt_WLApprox theapp3d;
696       IntPatch_SequenceOfLine aSeqOfL;
697       Standard_Real tol2d, aTolSS;
698       //        
699       tol2d = myTolApprox;
700       aTolSS=2.e-7;
701       theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30, myHS1 != myHS2);
702       //
703       bIsDecomposited = 
704         GeomInt_LineTool::DecompositionOfWLine(WL, myHS1, myHS2, aTolSS, myLConstruct, aSeqOfL);
705       //
706       aNbParts=myLConstruct.NbParts();
707       aNbSeqOfL=aSeqOfL.Length();
708       //
709       nbiter = (bIsDecomposited) ? aNbSeqOfL : aNbParts;
710       //
711       for(i = 1; i <= nbiter; i++) {
712         if(bIsDecomposited) {
713           WL = Handle(IntPatch_WLine)::DownCast(aSeqOfL.Value(i));
714           ifprm = 1;
715           ilprm = WL->NbPnts();
716         }
717         else {
718           myLConstruct.Part(i, fprm, lprm);
719           ifprm = (Standard_Integer)fprm;
720           ilprm = (Standard_Integer)lprm;
721         }
722         //-- lbr : 
723         //-- Si une des surfaces est un plan , on approxime en 2d
724         //-- sur cette surface et on remonte les points 2d en 3d.
725         GeomAbs_SurfaceType typs1, typs2;
726         typs1 = myHS1->Surface().GetType();
727         typs2 = myHS2->Surface().GetType();
728         //
729         if(typs1 == GeomAbs_Plane) { 
730           theapp3d.Perform(myHS1, myHS2, WL, Standard_False,
731             Standard_True, myApprox2,
732             ifprm,  ilprm);
733         }         
734         else if(typs2 == GeomAbs_Plane) { 
735           theapp3d.Perform(myHS1,myHS2,WL,Standard_False,
736             myApprox1,Standard_True,
737             ifprm,  ilprm);
738         }
739         else { 
740           //
741           if (myHS1 != myHS2){
742             if ((typs1==GeomAbs_BezierSurface || typs1==GeomAbs_BSplineSurface) &&
743               (typs2==GeomAbs_BezierSurface || typs2==GeomAbs_BSplineSurface)) {
744
745                 theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30, Standard_True);
746                 //Standard_Boolean bUseSurfaces;
747                 //bUseSurfaces=NotUseSurfacesForApprox(myFace1, myFace2, WL, ifprm,  ilprm);
748                 //if (bUseSurfaces) {
749                 //theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False);
750                 //}
751             }
752           }
753           //
754           theapp3d.Perform(myHS1,myHS2,WL,Standard_True,
755             myApprox1,myApprox2,
756             ifprm,  ilprm);
757         }
758
759         if (!theapp3d.IsDone()) {
760           //      
761           Handle(Geom2d_BSplineCurve) aH1, aH2;
762           //      
763           Handle(Geom_Curve) aBSp=MakeBSpline(WL, ifprm, ilprm);
764           if(myApprox1) {
765             aH1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
766           }
767           if(myApprox2) {
768             aH2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
769           }
770           //
771           sline.Append(aBSp);
772           slineS1.Append(aH1);
773           slineS2.Append(aH2);
774         }//if (!theapp3d.IsDone())
775
776         else {
777           if(myApprox1 || myApprox2 || (typs1==GeomAbs_Plane || typs2==GeomAbs_Plane)) { 
778             if( theapp3d.TolReached2d()>myTolReached2d || myTolReached2d==0.) { 
779               myTolReached2d = theapp3d.TolReached2d();
780             }
781           }
782           if(typs1==GeomAbs_Plane || typs2==GeomAbs_Plane) { 
783             myTolReached3d = myTolReached2d;
784           }
785           else  if( theapp3d.TolReached3d()>myTolReached3d || myTolReached3d==0.) { 
786             myTolReached3d = theapp3d.TolReached3d();
787           }
788
789           Standard_Integer aNbMultiCurves, nbpoles;
790           //
791           aNbMultiCurves=theapp3d.NbMultiCurves(); 
792           for (j=1; j<=aNbMultiCurves; j++) {
793             if(typs1 == GeomAbs_Plane) {
794               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
795               nbpoles = mbspc.NbPoles();
796
797               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
798               TColgp_Array1OfPnt   tpoles(1,nbpoles);
799
800               mbspc.Curve(1,tpoles2d);
801               const gp_Pln&  Pln = myHS1->Surface().Plane();
802               //
803               Standard_Integer ik; 
804               for(ik = 1; ik<= nbpoles; ik++) { 
805                 tpoles.SetValue(ik,
806                   ElSLib::Value(tpoles2d.Value(ik).X(),
807                   tpoles2d.Value(ik).Y(),
808                   Pln));
809               }
810               //
811               Handle(Geom_BSplineCurve) BS = 
812                 new Geom_BSplineCurve(tpoles,
813                 mbspc.Knots(),
814                 mbspc.Multiplicities(),
815                 mbspc.Degree());
816               GeomLib_CheckBSplineCurve Check(BS,myTolCheck,myTolAngCheck);
817               Check.FixTangent(Standard_True, Standard_True);
818               //        
819               sline.Append(BS);
820               //
821               if(myApprox1) { 
822                 Handle(Geom2d_BSplineCurve) BS1 = 
823                   new Geom2d_BSplineCurve(tpoles2d,
824                   mbspc.Knots(),
825                   mbspc.Multiplicities(),
826                   mbspc.Degree());
827                 GeomLib_Check2dBSplineCurve Check1(BS1,myTolCheck,myTolAngCheck);
828                 Check1.FixTangent(Standard_True,Standard_True);
829                 //      
830                 AdjustUPeriodic (aS1, BS1);  
831                 //
832                 slineS1.Append(BS1);
833               }
834               else {
835                 slineS1.Append(H1);
836               }
837
838               if(myApprox2) { 
839                 mbspc.Curve(2, tpoles2d);
840
841                 Handle(Geom2d_BSplineCurve) BS2 = new Geom2d_BSplineCurve(tpoles2d,
842                   mbspc.Knots(),
843                   mbspc.Multiplicities(),
844                   mbspc.Degree());
845                 GeomLib_Check2dBSplineCurve newCheck(BS2,myTolCheck,myTolAngCheck);
846                 newCheck.FixTangent(Standard_True,Standard_True);
847                 //
848                 AdjustUPeriodic (aS2, BS2);  
849                 //
850                 slineS2.Append(BS2); 
851               }
852               else { 
853                 slineS2.Append(H1); 
854               }
855             }//if(typs1 == GeomAbs_Plane) 
856             //
857             else if(typs2 == GeomAbs_Plane) { 
858               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
859               nbpoles = mbspc.NbPoles();
860
861               TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
862               TColgp_Array1OfPnt   tpoles(1,nbpoles);
863               mbspc.Curve((myApprox1==Standard_True)? 2 : 1,tpoles2d);
864               const gp_Pln&  Pln = myHS2->Surface().Plane();
865               //
866               Standard_Integer ik; 
867               for(ik = 1; ik<= nbpoles; ik++) { 
868                 tpoles.SetValue(ik,
869                   ElSLib::Value(tpoles2d.Value(ik).X(),
870                   tpoles2d.Value(ik).Y(),
871                   Pln));
872
873               }
874               //
875               Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
876                 mbspc.Knots(),
877                 mbspc.Multiplicities(),
878                 mbspc.Degree());
879               GeomLib_CheckBSplineCurve Check(BS,myTolCheck,myTolAngCheck);
880               Check.FixTangent(Standard_True,Standard_True);
881               //        
882               sline.Append(BS);
883               //
884               if(myApprox2) {
885                 Handle(Geom2d_BSplineCurve) BS1=new Geom2d_BSplineCurve(tpoles2d,
886                   mbspc.Knots(),
887                   mbspc.Multiplicities(),
888                   mbspc.Degree());
889                 GeomLib_Check2dBSplineCurve Check1(BS1,myTolCheck,myTolAngCheck);
890                 Check1.FixTangent(Standard_True,Standard_True);
891                 //
892                 //
893                 AdjustUPeriodic (aS2, BS1);  
894                 //
895                 slineS2.Append(BS1);
896               }
897               else {
898                 slineS2.Append(H1);
899               }
900
901               if(myApprox1) { 
902                 mbspc.Curve(1,tpoles2d);
903                 Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
904                   mbspc.Knots(),
905                   mbspc.Multiplicities(),
906                   mbspc.Degree());
907                 GeomLib_Check2dBSplineCurve Check2(BS2,myTolCheck,myTolAngCheck);
908                 Check2.FixTangent(Standard_True,Standard_True);
909                 // 
910                 //
911                 AdjustUPeriodic (aS1, BS2);  
912                 //      
913                 slineS1.Append(BS2);
914               }
915               else { 
916                 slineS1.Append(H1);
917               }
918             } // else if(typs2 == GeomAbs_Plane)
919             //
920             else { // typs1!=GeomAbs_Plane && typs2!=GeomAbs_Plane
921               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
922               nbpoles = mbspc.NbPoles();
923               TColgp_Array1OfPnt tpoles(1,nbpoles);
924               mbspc.Curve(1,tpoles);
925               Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
926                 mbspc.Knots(),
927                 mbspc.Multiplicities(),
928                 mbspc.Degree());
929               GeomLib_CheckBSplineCurve Check(BS,myTolCheck,myTolAngCheck);
930               Check.FixTangent(Standard_True,Standard_True);
931               //        
932               //Check IsClosed()
933               Standard_Real aDist = Max(BS->StartPoint().XYZ().SquareModulus(),
934                 BS->EndPoint().XYZ().SquareModulus());
935               Standard_Real eps = Epsilon(aDist);
936               if(BS->StartPoint().SquareDistance(BS->EndPoint()) < 2.*eps)
937               {
938                 // Avoid creating B-splines containing two coincident poles only
939                 if (mbspc.Degree() == 1 && nbpoles == 2)
940                   continue;
941
942                 if (!BS->IsClosed() && !BS->IsPeriodic())
943                 {
944                   //force Closed()
945                   gp_Pnt aPm((BS->Pole(1).XYZ() + BS->Pole(BS->NbPoles()).XYZ()) / 2.);
946                   BS->SetPole(1, aPm);
947                   BS->SetPole(BS->NbPoles(), aPm);
948                 }
949               }
950               sline.Append(BS);
951
952               if(myApprox1) { 
953                 TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
954                 mbspc.Curve(2,tpoles2d);
955                 Handle(Geom2d_BSplineCurve) BS1=new Geom2d_BSplineCurve(tpoles2d,
956                   mbspc.Knots(),
957                   mbspc.Multiplicities(),
958                   mbspc.Degree());
959                 GeomLib_Check2dBSplineCurve newCheck(BS1,myTolCheck,myTolAngCheck);
960                 newCheck.FixTangent(Standard_True,Standard_True);
961                 //
962                 AdjustUPeriodic (aS1, BS1);  
963                 //
964                 slineS1.Append(BS1);
965               }
966               else {
967                 slineS1.Append(H1);
968               }
969               if(myApprox2) { 
970                 TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
971                 mbspc.Curve((myApprox1==Standard_True)? 3 : 2,tpoles2d);
972                 Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
973                   mbspc.Knots(),
974                   mbspc.Multiplicities(),
975                   mbspc.Degree());
976                 GeomLib_Check2dBSplineCurve newCheck(BS2,myTolCheck,myTolAngCheck);
977                 newCheck.FixTangent(Standard_True,Standard_True);
978                 //
979                 AdjustUPeriodic (aS2, BS2);  
980                 //
981                 slineS2.Append(BS2);
982               }
983               else { 
984                 slineS2.Append(H1);
985               }
986             }// else { // typs1!=GeomAbs_Plane && typs2!=GeomAbs_Plane
987           }// for (j=1; j<=aNbMultiCurves; j++
988         }
989       }
990     }
991   }
992   break;
993
994   case IntPatch_Restriction: 
995     {
996       Handle(IntPatch_RLine) RL = 
997         Handle(IntPatch_RLine)::DownCast(L);
998       Handle(Geom_Curve) aC3d;
999       Handle(Geom2d_Curve) aC2d1, aC2d2;
1000       Standard_Real aTolReached;
1001       TreatRLine(RL, myHS1, myHS2, aC3d,
1002                   aC2d1, aC2d2, aTolReached);
1003
1004       if(aC3d.IsNull())
1005         break;
1006
1007       Bnd_Box2d aBox1, aBox2;
1008
1009       const Standard_Real aU1f = myHS1->FirstUParameter(),
1010                           aV1f = myHS1->FirstVParameter(),
1011                           aU1l = myHS1->LastUParameter(),
1012                           aV1l = myHS1->LastVParameter();
1013       const Standard_Real aU2f = myHS2->FirstUParameter(),
1014                           aV2f = myHS2->FirstVParameter(),
1015                           aU2l = myHS2->LastUParameter(),
1016                           aV2l = myHS2->LastVParameter();
1017
1018       aBox1.Add(gp_Pnt2d(aU1f, aV1f));
1019       aBox1.Add(gp_Pnt2d(aU1l, aV1l));
1020       aBox2.Add(gp_Pnt2d(aU2f, aV2f));
1021       aBox2.Add(gp_Pnt2d(aU2l, aV2l));
1022
1023       GeomInt_VectorOfReal anArrayOfParameters;
1024
1025       //We consider here that the intersection line is same-parameter-line
1026       anArrayOfParameters.Append(aC3d->FirstParameter());
1027       anArrayOfParameters.Append(aC3d->LastParameter());
1028
1029       TrimILineOnSurfBoundaries(aC2d1, aC2d2, aBox1, aBox2, anArrayOfParameters);
1030
1031       const Standard_Integer aNbIntersSolutionsm1 = anArrayOfParameters.Length() - 1;
1032
1033       //Trim RLine found.
1034       for(Standard_Integer anInd = 0; anInd < aNbIntersSolutionsm1; anInd++)
1035       {
1036         const Standard_Real aParF = anArrayOfParameters(anInd),
1037                             aParL = anArrayOfParameters(anInd+1);
1038
1039         if((aParL - aParF) <= Precision::PConfusion())
1040           continue;
1041
1042         const Standard_Real aPar = 0.5*(aParF + aParL);
1043         gp_Pnt2d aPt;
1044
1045         Handle(Geom2d_Curve) aCurv2d1, aCurv2d2;
1046         if(!aC2d1.IsNull())
1047         {
1048           aC2d1->D0(aPar, aPt);
1049
1050           if(aBox1.IsOut(aPt))
1051             continue;
1052
1053           if(myApprox1)
1054             aCurv2d1 = new Geom2d_TrimmedCurve(aC2d1, aParF, aParL);
1055         }
1056
1057         if(!aC2d2.IsNull())
1058         {
1059           aC2d2->D0(aPar, aPt);
1060
1061           if(aBox2.IsOut(aPt))
1062             continue;
1063
1064           if(myApprox2)
1065             aCurv2d2 = new Geom2d_TrimmedCurve(aC2d2, aParF, aParL);
1066         }
1067
1068         Handle(Geom_Curve) aCurv3d = new Geom_TrimmedCurve(aC3d, aParF, aParL);
1069
1070         sline.Append(aCurv3d);
1071         slineS1.Append(aCurv2d1);
1072         slineS2.Append(aCurv2d2);
1073       }
1074     }
1075     break;
1076   }
1077 }
1078
1079 //=======================================================================
1080 //function : TreatRLine
1081 //purpose  : Approx of Restriction line
1082 //=======================================================================
1083 void GeomInt_IntSS::TreatRLine(const Handle(IntPatch_RLine)& theRL, 
1084                 const Handle(GeomAdaptor_HSurface)& theHS1, 
1085                 const Handle(GeomAdaptor_HSurface)& theHS2, 
1086                 Handle(Geom_Curve)& theC3d,
1087                 Handle(Geom2d_Curve)& theC2d1, 
1088                 Handle(Geom2d_Curve)& theC2d2, 
1089                 Standard_Real& theTolReached)
1090 {
1091   Handle(GeomAdaptor_HSurface) aGAHS;
1092   Handle(Adaptor2d_HCurve2d) anAHC2d;
1093   Standard_Real tf, tl;
1094   gp_Lin2d aL;
1095   // It is assumed that 2d curve is 2d line (rectangular surface domain)
1096   if(theRL->IsArcOnS1())
1097   {
1098     aGAHS = theHS1;
1099     anAHC2d = theRL->ArcOnS1();
1100     theRL->ParamOnS1(tf, tl);
1101     theC2d1 = Geom2dAdaptor::MakeCurve(anAHC2d->Curve2d());
1102     tf = Max(tf, theC2d1->FirstParameter());
1103     tl = Min(tl, theC2d1->LastParameter());
1104     theC2d1 = new Geom2d_TrimmedCurve(theC2d1, tf, tl);
1105   }
1106   else if (theRL->IsArcOnS2())
1107   {
1108     aGAHS = theHS2;
1109     anAHC2d = theRL->ArcOnS2();
1110     theRL->ParamOnS2(tf, tl);
1111     theC2d2 = Geom2dAdaptor::MakeCurve(anAHC2d->Curve2d());
1112     tf = Max(tf, theC2d2->FirstParameter());
1113     tl = Min(tl, theC2d2->LastParameter());
1114     theC2d2 = new Geom2d_TrimmedCurve(theC2d2, tf, tl);
1115   }
1116   else
1117   {
1118     return;
1119   }
1120   //
1121   //To provide sameparameter it is necessary to get 3d curve as
1122   //approximation of curve on surface.
1123   Standard_Integer aMaxDeg = 8;
1124   Standard_Integer aMaxSeg = 1000;
1125   Approx_CurveOnSurface anApp(anAHC2d, aGAHS, tf, tl, Precision::Confusion(),
1126                               GeomAbs_C1, aMaxDeg, aMaxSeg, 
1127                               Standard_True, Standard_False);
1128   if(!anApp.HasResult())
1129     return;
1130
1131   theC3d = anApp.Curve3d();
1132   theTolReached = anApp.MaxError3d();
1133   Standard_Real aTol = Precision::Confusion();
1134   if(theRL->IsArcOnS1())
1135   {
1136     Handle(Geom_Surface) aS = GeomAdaptor::MakeSurface(theHS2->Surface());
1137     BuildPCurves (tf, tl, aTol, 
1138                   aS, theC3d, theC2d2);
1139   }
1140   if(theRL->IsArcOnS2())
1141   {
1142     Handle(Geom_Surface) aS = GeomAdaptor::MakeSurface(theHS1->Surface());
1143     BuildPCurves (tf, tl, aTol, 
1144                   aS, theC3d, theC2d1);
1145   }
1146   theTolReached = Max(theTolReached, aTol);
1147 }
1148
1149 //=======================================================================
1150 //function : BuildPCurves
1151 //purpose  : 
1152 //=======================================================================
1153 void GeomInt_IntSS::BuildPCurves (Standard_Real f,
1154                                   Standard_Real l,
1155                                   Standard_Real& Tol,
1156                                   const Handle (Geom_Surface)& S,
1157                                   const Handle (Geom_Curve)&   C,
1158                                   Handle (Geom2d_Curve)& C2d)
1159 {
1160   if (!C2d.IsNull()) {
1161     return;
1162   }
1163   //
1164   Standard_Real umin,umax,vmin,vmax;
1165   // 
1166   S->Bounds(umin, umax, vmin, vmax);
1167   // in class ProjLib_Function the range of parameters is shrank by 1.e-09
1168   if((l - f) > 2.e-09) {
1169     C2d = GeomProjLib::Curve2d(C,f,l,S,umin,umax,vmin,vmax,Tol);
1170     //
1171     if (C2d.IsNull()) {
1172       // proj. a circle that goes through the pole on a sphere to the sphere     
1173       Tol += Precision::Confusion();
1174       C2d = GeomProjLib::Curve2d(C,f,l,S,Tol);
1175     }
1176   }
1177   else {
1178     if((l - f) > Epsilon(Abs(f)))
1179     {
1180       //The domain of C2d is [Epsilon(Abs(f)), 2.e-09]
1181       //On this small range C2d can be considered as segment 
1182       //of line.
1183
1184       Standard_Real aU=0., aV=0.;
1185       GeomAdaptor_Surface anAS;
1186       anAS.Load(S);
1187       Extrema_ExtPS anExtr;
1188       const gp_Pnt aP3d1 = C->Value(f);
1189       const gp_Pnt aP3d2 = C->Value(l);
1190
1191       anExtr.SetAlgo(Extrema_ExtAlgo_Grad);
1192       anExtr.Initialize(anAS, umin, umax, vmin, vmax,
1193                                 Precision::Confusion(), Precision::Confusion());
1194       anExtr.Perform(aP3d1);
1195
1196       if(ParametersOfNearestPointOnSurface(anExtr, aU, aV))
1197       {
1198         const gp_Pnt2d aP2d1(aU, aV);
1199
1200         anExtr.Perform(aP3d2);
1201
1202         if(ParametersOfNearestPointOnSurface(anExtr, aU, aV))
1203         {
1204           const gp_Pnt2d aP2d2(aU, aV);
1205
1206           if(aP2d1.Distance(aP2d2) > gp::Resolution())
1207           {
1208             TColgp_Array1OfPnt2d poles(1,2);
1209             TColStd_Array1OfReal knots(1,2);
1210             TColStd_Array1OfInteger mults(1,2);
1211             poles(1) = aP2d1;
1212             poles(2) = aP2d2;
1213             knots(1) = f;
1214             knots(2) = l;
1215             mults(1) = mults(2) = 2;
1216
1217             C2d = new Geom2d_BSplineCurve(poles,knots,mults,1);
1218
1219             //Check same parameter in middle point .begin
1220             const gp_Pnt PMid(C->Value(0.5*(f+l)));
1221             const gp_Pnt2d pmidcurve2d(0.5*(aP2d1.XY() + aP2d2.XY()));
1222             const gp_Pnt aPC(anAS.Value(pmidcurve2d.X(), pmidcurve2d.Y()));
1223             const Standard_Real aDist = PMid.Distance(aPC);
1224             Tol = Max(aDist, Tol);
1225             //Check same parameter in middle point .end
1226           }
1227         }
1228       }
1229     }
1230   }
1231   //
1232   if (S->IsUPeriodic() && !C2d.IsNull()) {
1233     // Recadre dans le domaine UV de la face
1234     Standard_Real aTm, U0, aEps, period, du, U0x;
1235     Standard_Boolean bAdjust;
1236     //
1237     aEps = Precision::PConfusion();
1238     period = S->UPeriod();
1239     //
1240     aTm = .5*(f + l);
1241     gp_Pnt2d pm = C2d->Value(aTm);
1242     U0 = pm.X();
1243     //
1244     bAdjust = 
1245       GeomInt::AdjustPeriodic(U0, umin, umax, period, U0x, du, aEps);
1246     if (bAdjust) {
1247       gp_Vec2d T1(du, 0.);
1248       C2d->Translate(T1);
1249     }
1250   }
1251 }
1252
1253 //=======================================================================
1254 //function : TrimILineOnSurfBoundaries
1255 //purpose  : This function finds intersection points of given curves with
1256 //            surface boundaries and fills theArrayOfParameters by parameters
1257 //            along the given curves corresponding of these points.
1258 //=======================================================================
1259 void GeomInt_IntSS::TrimILineOnSurfBoundaries(const Handle(Geom2d_Curve)& theC2d1,
1260                                               const Handle(Geom2d_Curve)& theC2d2,
1261                                               const Bnd_Box2d& theBound1,
1262                                               const Bnd_Box2d& theBound2,
1263                                               GeomInt_VectorOfReal& theArrayOfParameters)
1264 {
1265   //Rectangular boundaries of two surfaces: [0]:U=Ufirst, [1]:U=Ulast,
1266   //                                        [2]:V=Vfirst, [3]:V=Vlast 
1267   const Standard_Integer aNumberOfCurves = 4;
1268   Handle(Geom2d_Curve) aCurS1Bounds[aNumberOfCurves];
1269   Handle(Geom2d_Curve) aCurS2Bounds[aNumberOfCurves];
1270
1271   Standard_Real aU1f=0.0, aV1f=0.0, aU1l=0.0, aV1l=0.0;
1272   Standard_Real aU2f=0.0, aV2f=0.0, aU2l=0.0, aV2l=0.0;
1273
1274   theBound1.Get(aU1f, aV1f, aU1l, aV1l);
1275   theBound2.Get(aU2f, aV2f, aU2l, aV2l);
1276
1277   Standard_Real aDelta = aV1l-aV1f;
1278   if(Abs(aDelta) > RealSmall())
1279   {
1280     if(!Precision::IsInfinite(aU1f))
1281     {
1282       aCurS1Bounds[0] = new Geom2d_Line(gp_Pnt2d(aU1f, aV1f), gp_Dir2d(0.0, 1.0));
1283
1284       if(!Precision::IsInfinite(aDelta))
1285         aCurS1Bounds[0] = new Geom2d_TrimmedCurve(aCurS1Bounds[0], 0, aDelta);
1286     }
1287
1288     if(!Precision::IsInfinite(aU1l))
1289     {
1290       aCurS1Bounds[1] = new Geom2d_Line(gp_Pnt2d(aU1l, aV1f), gp_Dir2d(0.0, 1.0));
1291       if(!Precision::IsInfinite(aDelta))
1292         aCurS1Bounds[1] = new Geom2d_TrimmedCurve(aCurS1Bounds[1], 0, aDelta);
1293     }
1294   }
1295
1296   aDelta = aU1l-aU1f;
1297   if(Abs(aDelta) > RealSmall())
1298   {
1299     if(!Precision::IsInfinite(aV1f))
1300     {
1301       aCurS1Bounds[2] = new Geom2d_Line(gp_Pnt2d(aU1f, aV1f), gp_Dir2d(1.0, 0.0));
1302       if(!Precision::IsInfinite(aDelta))
1303         aCurS1Bounds[2] = new Geom2d_TrimmedCurve(aCurS1Bounds[2], 0, aDelta);
1304     }
1305
1306     if(!Precision::IsInfinite(aV1l))
1307     {
1308       aCurS1Bounds[3] = new Geom2d_Line(gp_Pnt2d(aU1l, aV1l), gp_Dir2d(1.0, 0.0));
1309       if(!Precision::IsInfinite(aDelta))
1310         aCurS1Bounds[3] = new Geom2d_TrimmedCurve(aCurS1Bounds[3], 0, aDelta);
1311     }
1312   }
1313
1314   aDelta = aV2l-aV2f;
1315   if(Abs(aDelta) > RealSmall())
1316   {
1317     if(!Precision::IsInfinite(aU2f))
1318     {
1319       aCurS2Bounds[0] = new Geom2d_Line(gp_Pnt2d(aU2f, aV2f), gp_Dir2d(0.0, 1.0));
1320       if(!Precision::IsInfinite(aDelta))
1321         aCurS2Bounds[0] = new Geom2d_TrimmedCurve(aCurS2Bounds[0], 0, aDelta);
1322     }
1323
1324     if(!Precision::IsInfinite(aU2l))
1325     {
1326       aCurS2Bounds[1] = new Geom2d_Line(gp_Pnt2d(aU2l, aV2f), gp_Dir2d(0.0, 1.0));
1327       if(!Precision::IsInfinite(aDelta))
1328         aCurS2Bounds[1] = new Geom2d_TrimmedCurve(aCurS2Bounds[1], 0, aDelta);
1329     }
1330   }
1331
1332   aDelta = aU2l-aU2f;
1333   if(Abs(aDelta) > RealSmall())
1334   {
1335     if(!Precision::IsInfinite(aV2f))
1336     {
1337       aCurS2Bounds[2] = new Geom2d_Line(gp_Pnt2d(aU2f, aV2f), gp_Dir2d(1.0, 0.0));
1338       if(!Precision::IsInfinite(aDelta))
1339         aCurS2Bounds[2] = new Geom2d_TrimmedCurve(aCurS2Bounds[2], 0, aDelta);
1340     }
1341
1342     if(!Precision::IsInfinite(aV2l))
1343     {
1344       aCurS2Bounds[3] = new Geom2d_Line(gp_Pnt2d(aU2l, aV2l), gp_Dir2d(1.0, 0.0));
1345       if(!Precision::IsInfinite(aDelta))
1346         aCurS2Bounds[3] = new Geom2d_TrimmedCurve(aCurS2Bounds[3], 0, aDelta);
1347     }
1348   }
1349
1350   const Standard_Real anIntTol = 10.0*Precision::Confusion();
1351
1352   IntersectCurveAndBoundary(theC2d1, aCurS1Bounds,
1353                         aNumberOfCurves, anIntTol, theArrayOfParameters);
1354
1355   IntersectCurveAndBoundary(theC2d2, aCurS2Bounds,
1356                         aNumberOfCurves, anIntTol, theArrayOfParameters);
1357
1358   std::sort(theArrayOfParameters.begin(), theArrayOfParameters.end());
1359 }
1360
1361 //=======================================================================
1362 //function : MakeBSpline
1363 //purpose  : 
1364 //=======================================================================
1365 Handle(Geom_Curve) GeomInt_IntSS::MakeBSpline  (const Handle(IntPatch_WLine)& WL,
1366                                                 const Standard_Integer ideb,
1367                                                 const Standard_Integer ifin)
1368 {
1369   const Standard_Integer nbpnt = ifin-ideb+1;
1370   TColgp_Array1OfPnt poles(1,nbpnt);
1371   TColStd_Array1OfReal knots(1,nbpnt);
1372   TColStd_Array1OfInteger mults(1,nbpnt);
1373   Standard_Integer i = 1, ipidebm1 = ideb;
1374   for(; i<=nbpnt; ipidebm1++, i++)
1375   {
1376     poles(i) = WL->Point(ipidebm1).Value();
1377     mults(i) = 1;
1378     knots(i) = i-1;
1379   }
1380   mults(1) = mults(nbpnt) = 2;
1381   return new Geom_BSplineCurve(poles,knots,mults,1);
1382 }
1383
1384 //=======================================================================
1385 //function : MakeBSpline2d
1386 //purpose  : 
1387 //=======================================================================
1388 Handle(Geom2d_BSplineCurve) GeomInt_IntSS::
1389       MakeBSpline2d(const Handle(IntPatch_WLine)& theWLine,
1390                     const Standard_Integer ideb,
1391                     const Standard_Integer ifin,
1392                     const Standard_Boolean onFirst)
1393 {
1394   const Standard_Integer nbpnt = ifin-ideb+1;
1395   TColgp_Array1OfPnt2d poles(1,nbpnt);
1396   TColStd_Array1OfReal knots(1,nbpnt);
1397   TColStd_Array1OfInteger mults(1,nbpnt);
1398   Standard_Integer i = 1, ipidebm1 = ideb;
1399   for(; i <= nbpnt; ipidebm1++, i++)
1400   {
1401     Standard_Real U, V;
1402     if(onFirst)
1403           theWLine->Point(ipidebm1).ParametersOnS1(U, V);
1404     else
1405           theWLine->Point(ipidebm1).ParametersOnS2(U, V);
1406     poles(i).SetCoord(U, V);
1407     mults(i) = 1;
1408     knots(i) = i-1;
1409   }
1410
1411   mults(1) = mults(nbpnt) = 2;
1412   return new Geom2d_BSplineCurve(poles,knots,mults,1);
1413 }