c02477ba7e2789adbcd40e332b40e638f4653acf
[occt.git] / src / BRepFill / BRepFill_MultiLine.cxx
1 // Created on: 1994-11-14
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22
23 #include <BRepFill_MultiLine.ixx>
24
25 #include <BRepIntCurveSurface_Inter.hxx>
26 #include <gp.hxx>
27 #include <gp_Lin.hxx>
28 #include <gp_Ax3.hxx>
29 #include <gp_Lin2d.hxx>
30 #include <gp_Circ2d.hxx>
31 #include <Precision.hxx>
32 #include <BRep_Tool.hxx>
33 #include <Geom_Line.hxx>
34 #include <Geom_Plane.hxx>
35 #include <Geom_TrimmedCurve.hxx>
36 #include <Geom2d_TrimmedCurve.hxx>
37 #include <Geom_Surface.hxx>
38 #include <Geom_RectangularTrimmedSurface.hxx>
39 #include <Geom2d_Line.hxx>
40 #include <GeomProjLib.hxx>
41 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
42 #include <Geom2dInt_GInter.hxx>
43 #include <IntRes2d_IntersectionPoint.hxx>
44 #include <Standard_ConstructionError.hxx>
45 #include <IntRes2d_IntersectionSegment.hxx>
46 #include <TopExp_Explorer.hxx>
47 #include <TopoDS.hxx>
48 #include <ElCLib.hxx>
49
50
51 #include <GeomAdaptor_Surface.hxx>
52 #include <GeomAbs_SurfaceType.hxx>
53
54 #ifdef DRAW
55 #include <DrawTrSurf.hxx>
56 #endif
57
58 #ifdef DEB
59 static Standard_Boolean AffichCurve = Standard_False;
60 static Standard_Integer NbProj = 1;
61 #endif
62 //POP pour NT
63 #include <stdio.h>
64
65 //=======================================================================
66 //function : isIsoU
67 //purpose  : 
68 //=======================================================================
69
70 static Standard_Boolean isIsoU(const TopoDS_Face& Face,
71                                const TopoDS_Edge& Edge ) 
72 {
73   Handle(Geom2d_Curve) C;
74   Handle(Geom2d_Line) Li;
75   Standard_Real f,l;
76
77   C = BRep_Tool::CurveOnSurface(Edge,Face, f, l);
78   if ( C.IsNull()) {
79     Standard_ConstructionError::Raise ("BRepFill_MultiLine : Edge without PCurve");
80   }
81   
82   gp_Dir2d D = C->DN(f,1);
83
84   if (Abs(D.Dot(gp::DX2d())) < Abs(D.Dot(gp::DY2d()))) 
85     return Standard_True;
86   else            
87     return Standard_False;
88 }
89
90
91
92
93 //=======================================================================
94 //function : BRepFill_MultiLine
95 //purpose  : 
96 //=======================================================================
97
98 BRepFill_MultiLine::BRepFill_MultiLine()
99 {
100 }
101
102
103 //=======================================================================
104 //function : BRepFill_MultiLine
105 //purpose  : 
106 //=======================================================================
107
108 BRepFill_MultiLine::BRepFill_MultiLine(const TopoDS_Face&     Face1, 
109                                        const TopoDS_Face&     Face2,
110                                        const TopoDS_Edge&     Edge1,
111                                        const TopoDS_Edge&     Edge2,
112                                        const Standard_Boolean Inv1,
113                                        const Standard_Boolean Inv2,
114                                        const Handle(Geom2d_Curve)& Bissec) :
115 myFace1(Face1 ),
116 myFace2(Face2 ),
117 myBis  (Bissec),
118 myKPart(0)
119 {
120   // eval if myedges are IsoU or not
121   myIsoU1 = isIsoU(Face1, Edge1);
122   myIsoU2 = isIsoU(Face2, Edge2);
123
124   // eval myU1, myV1, myU2, myV2;
125   Handle(Geom_Plane) RefPlane;
126   Handle(Geom_Plane) BasisPlane = new Geom_Plane(0.,0.,1.,0.);
127   TopLoc_Location L;
128
129   TopExp_Explorer Exp;
130   Standard_Real Umin,Vmin,Umax,Vmax,U,V;
131   gp_Pnt2d P1,P2;
132   gp_Vec DZ;
133   gp_Pnt P;
134
135   // Result on Face1
136   Standard_Boolean First = Standard_True;
137   for (Exp.Init(myFace1,TopAbs_EDGE);Exp.More(); Exp.Next()) {
138     TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
139     BRep_Tool::UVPoints(CurEdge,myFace1,P1,P2);
140     if ( First) {
141       First = Standard_False;
142       Umin = Min(P1.X(),P2.X());
143       Umax = Max(P1.X(),P2.X());
144  
145       Vmin = Min(P1.Y(),P2.Y());
146       Vmax = Max(P1.Y(),P2.Y());
147     }
148     else {
149       U    = Min(P1.X(),P2.X());
150       Umin = Min(Umin,U);
151       U    = Max(P1.X(),P2.X());
152       Umax = Max(Umax,U);
153
154       V    = Min(P1.Y(),P2.Y());
155       Vmin = Min(Vmin,V);
156       V    = Max(P1.Y(),P2.Y());
157       Vmax = Max(Vmax,V);
158     }
159   }
160   
161
162   // return isos in their domain of restriction.
163   Handle(Geom_Curve) UU1, UU2, VV1, VV2;
164   Handle(Geom_Surface) S;
165   S = BRep_Tool::Surface(myFace1,L);  
166   if (!L.IsIdentity())
167     S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
168
169   if ( myIsoU1) {
170     if (!BRep_Tool::Degenerated(Edge1) && !Inv1) {
171       UU1 = S->UIso(Umin);
172       GeomAdaptor_Curve Dummy(UU1);
173       if (Dummy.GetType() == GeomAbs_Circle && 
174           Dummy.Circle().Radius() < Precision::Confusion()) {
175         UU1 = S->UIso(Umax);
176       }
177     }
178     else {
179       UU1 = S->UIso(Umax);
180       GeomAdaptor_Curve Dummy(UU1);
181       if (Dummy.GetType() == GeomAbs_Circle && 
182           Dummy.Circle().Radius() < Precision::Confusion()) {
183         UU1 = S->UIso(Umin);
184       }
185     }
186     VV1 = S->VIso(Vmin);
187   }
188   else {
189     if (!BRep_Tool::Degenerated(Edge1) && !Inv1) {
190       UU1 = S->VIso(Vmin);    
191       GeomAdaptor_Curve Dummy(UU1);
192       if (Dummy.GetType() == GeomAbs_Circle && 
193           Dummy.Circle().Radius() < Precision::Confusion()) {
194         UU1 = S->VIso(Vmax);
195       }
196     }
197     else {
198       UU1 = S->VIso(Vmax);
199       GeomAdaptor_Curve Dummy(UU1);
200       if (Dummy.GetType() == GeomAbs_Circle && 
201           Dummy.Circle().Radius() < Precision::Confusion()) {
202         UU1 = S->VIso(Vmin);
203       }
204     }
205     VV1 = S->UIso(Umin);
206   }
207
208   if ( myIsoU1) {
209     Standard_Real dummyUmin = Umin, dummyUmax = Umax;
210     Umin = Vmin; 
211     Umax = Vmax;
212     Vmin = dummyUmin;
213     Vmax = dummyUmax;
214   }
215
216   // try duplication
217   GeomAdaptor_Surface GAS1(S);
218   GeomAbs_SurfaceType Type1 = GAS1.GetType();
219
220   if ( UU1->IsPeriodic()) {
221     ElCLib::AdjustPeriodic(UU1->FirstParameter(),
222                            UU1->LastParameter(),
223                            Precision::PConfusion(),
224                            Umin, Umax);
225   }
226   if ( VV1->IsPeriodic()) {
227     ElCLib::AdjustPeriodic(VV1->FirstParameter(),
228                            VV1->LastParameter(),
229                            Precision::PConfusion(),
230                            Vmin, Vmax);
231   }
232   if (GAS1.GetType() == GeomAbs_Sphere) {
233     if (myIsoU1)
234       ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
235                              Precision::PConfusion(),
236                              Umin, Umax);
237     else
238       ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
239                              Precision::PConfusion(),
240                              Vmin, Vmax);
241   }
242   // end try duplication
243
244   myU1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU1, BasisPlane),
245                              Umin, Umax);
246
247   UU1->D1(Umin, P, DZ);
248   RefPlane = new Geom_Plane(gp_Ax3(P,DZ,gp::DZ()));
249
250   myV1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV1, RefPlane),
251                              Vmin, Vmax);
252
253
254   First = Standard_True;
255   for (Exp.Init(myFace2,TopAbs_EDGE);Exp.More(); Exp.Next()) {
256     TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
257     BRep_Tool::UVPoints(CurEdge,myFace2,P1,P2);
258     if ( First) {
259       First = Standard_False;
260       Umin = Min(P1.X(),P2.X());
261       Umax = Max(P1.X(),P2.X());
262  
263       Vmin = Min(P1.Y(),P2.Y());
264       Vmax = Max(P1.Y(),P2.Y());
265     }
266     else {
267       U    = Min(P1.X(),P2.X());
268       Umin = Min(Umin,U);
269       U    = Max(P1.X(),P2.X());
270       Umax = Max(Umax,U);
271
272       V    = Min(P1.Y(),P2.Y());
273       Vmin = Min(Vmin,V);
274       V    = Max(P1.Y(),P2.Y());
275       Vmax = Max(Vmax,V);
276     }
277   }
278
279   // return isos in their domain of restriction.
280   S = BRep_Tool::Surface(myFace2,L);
281
282   if (!L.IsIdentity())
283     S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
284
285   if ( myIsoU2) {
286     if (!BRep_Tool::Degenerated(Edge2) && !Inv2) {
287       UU2 = S->UIso(Umin);    
288       GeomAdaptor_Curve Dummy(UU2);
289       if (Dummy.GetType() == GeomAbs_Circle && 
290           Dummy.Circle().Radius() < Precision::Confusion()) {
291         UU2 = S->UIso(Umax);
292       }
293     }
294     else {
295       UU2 = S->UIso(Umax);
296       GeomAdaptor_Curve Dummy(UU2);
297       if (Dummy.GetType() == GeomAbs_Circle && 
298           Dummy.Circle().Radius() < Precision::Confusion()) {
299         UU2 = S->UIso(Umin);
300       }
301     }
302     VV2 = S->VIso(Vmin);
303   }
304   else {
305     if (!BRep_Tool::Degenerated(Edge2) && !Inv2) {
306       UU2 = S->VIso(Vmin);
307       GeomAdaptor_Curve Dummy(UU2);
308       if (Dummy.GetType() == GeomAbs_Circle && 
309           Dummy.Circle().Radius() < Precision::Confusion()) {
310         UU2 = S->VIso(Vmax);
311       }
312     }
313     else {
314       UU2 = S->VIso(Vmax);
315       GeomAdaptor_Curve Dummy(UU2);
316       if (Dummy.GetType() == GeomAbs_Circle && 
317           Dummy.Circle().Radius() < Precision::Confusion()) {
318         UU2 = S->VIso(Vmin);
319       }
320     }
321     VV2 = S->UIso(Umin);
322   }
323     
324   if ( myIsoU2) {
325     Standard_Real dummyUmin = Umin, dummyUmax = Umax;
326     Umin = Vmin; 
327     Umax = Vmax;
328     Vmin = dummyUmin;
329     Vmax = dummyUmax;
330   }
331
332   // try duplication
333   GeomAdaptor_Surface GAS2(S);
334   GeomAbs_SurfaceType Type2 = GAS2.GetType();
335
336   if ( UU2->IsPeriodic()) {
337     ElCLib::AdjustPeriodic(UU2->FirstParameter(),
338                            UU2->LastParameter(),
339                            Precision::PConfusion(),
340                            Umin, Umax);
341   }
342   if ( VV2->IsPeriodic()) {
343     ElCLib::AdjustPeriodic(VV2->FirstParameter(),
344                            VV2->LastParameter(),
345                            Precision::PConfusion(),
346                            Vmin, Vmax);
347   }
348   if (GAS2.GetType() == GeomAbs_Sphere) {
349     if (myIsoU2)
350       ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
351                              Precision::PConfusion(),
352                              Umin, Umax);
353     else
354       ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
355                              Precision::PConfusion(),
356                              Vmin, Vmax);
357   }
358   // end try duplication
359
360   myU2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU2, BasisPlane),
361                              Umin, Umax);
362
363   UU2->D1(Umin, P, DZ);
364   RefPlane = new Geom_Plane(gp_Ax3(P,DZ,gp::DZ()));
365   myV2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV2, RefPlane),
366                              Vmin, Vmax);
367
368   // eval if in a particular case.
369   // Particular case if :
370   //     1) - Straight Bissectrice
371   //        - Bissectrice orthogonal to the base element.
372   //        ==> Iso on 2 faces.
373   //     2) - Straight Bissectrice
374   //        - 2 surfaces are planes.
375   myCont  = GeomAbs_C0;
376
377   if ( myBis.GetType() == GeomAbs_Line) {
378     Standard_Real DeltaU = myBis.LastParameter()  - myBis.FirstParameter();
379     gp_Pnt2d P1 = ValueOnF1(myBis.FirstParameter() + 0.1*DeltaU);
380     gp_Pnt2d P2 = ValueOnF1(myBis.FirstParameter() + 0.9*DeltaU);
381     if ( myIsoU1) {
382       if ( Abs(P1.Y() - P2.Y()) < Precision::Confusion())
383         myKPart = 1;
384     }
385     else {
386       if ( Abs(P1.X() - P2.X()) < Precision::Confusion())
387         myKPart = 1;
388     }
389     
390     if ( myKPart == 1)
391       myCont = GeomAbs_G1;
392
393     if ( (Type1 == GeomAbs_Plane) && (Type2 == GeomAbs_Plane)) {
394       myKPart = 2;
395     }
396   }
397 }
398
399
400 //=======================================================================
401 //function : IsParticularCase
402 //purpose  : 
403 //=======================================================================
404
405 Standard_Boolean BRepFill_MultiLine::IsParticularCase() const 
406 {
407   return ( myKPart != 0);
408 }
409
410
411 //=======================================================================
412 //function : Curves
413 //purpose  : 
414 //=======================================================================
415
416 void BRepFill_MultiLine::Curves(Handle(Geom_Curve)& Curve,
417                                 Handle(Geom2d_Curve)& PCurve1,
418                                 Handle(Geom2d_Curve)& PCurve2) const 
419 {
420   if ( myKPart == 1) {
421     gp_Pnt2d      P1,P2,PMil;
422     Standard_Real f,l;
423
424     P1   = ValueOnF1(myBis.FirstParameter());
425     P2   = ValueOnF1(myBis.LastParameter());
426
427     // find value of the with medium point 
428     // the ends can be degenerated points.
429
430     PMil = ValueOnF1(0.5*(myBis.FirstParameter() + myBis.LastParameter()));
431     
432     TopLoc_Location L;
433     Handle(Geom_Surface) S = BRep_Tool::Surface(myFace1,L);
434     if (!L.IsIdentity())
435       S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
436     
437     Standard_Boolean Sens;
438     if ( !myIsoU1) {
439       Curve   = S->UIso(PMil.X());
440       Sens    = P1.Y() < P2.Y();
441       if ( Sens) 
442         Curve   = new Geom_TrimmedCurve(Curve, P1.Y(), P2.Y(), Sens);
443       else
444         Curve   = new Geom_TrimmedCurve(Curve, P2.Y(), P1.Y(), Sens);
445       
446       f = Curve->FirstParameter();
447       l = Curve->LastParameter();
448       if ( Sens) 
449         PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(),P1.Y() - f), gp::DY2d());
450       else
451         PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(),P1.Y() + f),-gp::DY2d());
452       PCurve1 = new Geom2d_TrimmedCurve( PCurve1 ,f ,l);
453     }
454     else {
455       Curve   = S->VIso(PMil.Y());
456       Sens = P1.X() < P2.X();
457       if (Sens)
458         Curve   = new Geom_TrimmedCurve(Curve, P1.X(), P2.X(), Sens);
459       else
460         Curve   = new Geom_TrimmedCurve(Curve, P2.X(), P1.X(), Sens);
461       
462       f = Curve->FirstParameter();
463       l = Curve->LastParameter();
464       if ( Sens) 
465         PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() - f,PMil.Y()), gp::DX2d());
466       else
467         PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() + f,PMil.Y()), -gp::DX2d());
468       PCurve1 = new Geom2d_TrimmedCurve( PCurve1 ,f ,l);
469     }
470                      
471     P1   = ValueOnF2(myBis.FirstParameter());
472     P2   = ValueOnF2(myBis.LastParameter());
473     PMil = ValueOnF2(0.5*(myBis.FirstParameter() + myBis.LastParameter()));
474                      
475     if (!myIsoU2) {
476       Sens = P1.Y() < P2.Y();
477       if ( Sens) 
478         PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(),(P1.Y() - f)), gp::DY2d());
479       else
480         PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(),(P1.Y() + f)), -gp::DY2d());
481     }
482     else {
483       Sens = P1.X() < P2.X();
484       if ( Sens) 
485         PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() - f ,PMil.Y()), gp::DX2d());
486       else
487         PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() + f ,PMil.Y()), -gp::DX2d());
488     }
489     PCurve2 = new Geom2d_TrimmedCurve( PCurve2 ,f ,l);
490   }
491   else if ( myKPart == 2) {
492     TopLoc_Location L;
493     
494     Handle(Geom_Surface) S = BRep_Tool::Surface(myFace1,L);
495     if (!L.IsIdentity())
496       S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
497     
498     if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
499       S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
500
501     Handle(Geom_Plane) Plane = Handle(Geom_Plane)::DownCast(S);
502     // eval the 3d curve corresponding to the bissectrice.
503     gp_Pnt2d P = myBis.Line().Location();
504     gp_Dir2d D = myBis.Line().Direction();
505     Handle(Geom_Line) Line = new Geom_Line(gp_Pnt(P.X(),P.Y(),0.),
506                                            gp_Dir(D.X(),D.Y(),0.) );
507     Handle(Geom_TrimmedCurve) TLine = 
508       new Geom_TrimmedCurve(Line, myBis.FirstParameter(),
509                                   myBis.LastParameter());
510     Curve = GeomProjLib::ProjectOnPlane(TLine, Plane, 
511                                         gp::DZ(), Standard_False);
512
513 #ifdef DRAW
514     if ( AffichCurve) {
515 //POP pour NT
516       //      char name[100];
517       char* name = new char[100];
518       sprintf(name,"C2_%d",NbProj);
519       DrawTrSurf::Set(name,TLine);
520       sprintf(name,"C3_%d",NbProj);
521       DrawTrSurf::Set(name,Curve);
522       sprintf(name,"SS_%d",NbProj);
523       DrawTrSurf::Set(name,Plane);
524       NbProj++;
525     }
526 #endif
527
528     // eval PCurve1
529     PCurve1 = GeomProjLib::Curve2d(Curve,Plane);
530     
531     // eval PCurve2
532     S = BRep_Tool::Surface(myFace2,L);
533     if (!L.IsIdentity())
534       S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
535     if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
536       S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
537     Plane = Handle(Geom_Plane)::DownCast(S);
538     PCurve2 = GeomProjLib::Curve2d(Curve,Plane);
539   }
540 }
541
542
543 //=======================================================================
544 //function : FirstParameter
545 //purpose  : 
546 //=======================================================================
547
548 Standard_Real BRepFill_MultiLine::FirstParameter() const 
549 {
550   return myBis.FirstParameter();
551 }
552
553
554 //=======================================================================
555 //function : LastParameter
556 //purpose  : 
557 //=======================================================================
558
559 Standard_Real BRepFill_MultiLine::LastParameter() const 
560 {
561   return myBis.LastParameter();
562 }
563
564
565 //=======================================================================
566 //function : Value
567 //purpose  : 
568 //=======================================================================
569
570 gp_Pnt BRepFill_MultiLine::Value(const Standard_Real U) const 
571 {
572   Handle(Geom_Surface) S;
573   TopLoc_Location L;
574
575   S = BRep_Tool::Surface(myFace1,L);  
576
577   gp_Pnt2d P2d = ValueOnF1(U);
578
579   gp_Pnt P3d = S->Value(P2d.X(), P2d.Y());
580   P3d.Transform(L.Transformation());
581
582   return P3d;
583 }
584
585
586 //=======================================================================
587 //function : ValueOnFace
588 //purpose  : 
589 //=======================================================================
590
591 static gp_Pnt2d ValueOnFace(const Standard_Real        U,
592                             const Geom2dAdaptor_Curve& TheBis,
593                             const Geom2dAdaptor_Curve& TheU,
594                             const Geom2dAdaptor_Curve& TheV,
595                             const Standard_Boolean     IsIsoU)
596 {
597   gp_Pnt2d P = TheBis.Value(U);
598
599   Geom2dAPI_ProjectPointOnCurve Ext(P,TheU.Curve(),
600                                     TheU.FirstParameter(),
601                                     TheU.LastParameter());
602 #ifdef DRAW
603   if (AffichCurve) {
604     char* TheUname = "TheU";
605     char* PP1name = "PP1";
606     DrawTrSurf::Set(TheUname,TheU.Curve());
607     DrawTrSurf::Set(PP1name,P);
608 //    DrawTrSurf::Set("TheU",TheU.Curve());
609 //    DrawTrSurf::Set("PP1",P);
610   }
611 #endif
612
613   Standard_Real UU =0., Dist = Precision::Infinite(), D1, D2;
614
615   if ( !Ext.NbPoints() == 0 ) {    
616     UU = Ext.LowerDistanceParameter();
617     Dist = Ext.LowerDistance();
618   }
619   // Control with `ends` 
620   D1 = P.Distance(TheU.Value(TheU.FirstParameter()));
621   D2 = P.Distance(TheU.Value(TheU.LastParameter()));
622
623   if (D1 < Dist || D2 < Dist) {
624     if ( Abs( D1 - D2) < Precision::Confusion()) {
625       if ( TheU.GetType() == GeomAbs_Circle) {
626         gp_Vec2d Axis = TheU.Circle().XAxis().Direction();
627         gp_Vec2d D12d = TheBis.DN(TheBis.FirstParameter(),1);
628         Standard_Real Ang = Axis.Angle(D12d);
629         if ( !TheU.Circle().IsDirect()) Ang = -Ang;
630         UU = ElCLib::InPeriod( Ang, TheU.FirstParameter(), 
631                                     TheU.FirstParameter() + 2*M_PI);
632         Dist = TheU.Circle().Radius();
633       }
634       else {
635 #ifdef DEB
636         cout << "MultiLine : D1 = D2 and the Curve is not a circle" << endl;
637         cout << "  ---> ValueOnFace failed at parameter U = " << U << endl;
638 #endif
639         Standard_ConstructionError::Raise("BRepFill_MultiLine: ValueOnFace");
640       }
641     }
642     else if ( D1 < D2) {
643       Dist = D1;
644       UU   = TheU.FirstParameter();
645     }
646     else {
647       Dist = D2;
648       UU   = TheU.LastParameter();
649     }
650   }
651
652   Standard_Real Tol = Precision::Confusion();
653   Standard_Real VV;
654
655   gp_Pnt2d PF = TheV.Value(TheV.FirstParameter());
656   gp_Pnt2d PL = TheV.Value(TheV.LastParameter());  
657   
658   if (Abs(Dist - Abs(PF.Y())) < Tol) {
659     VV = TheV.FirstParameter();
660   }
661   else if (Abs(Dist - Abs(PL.Y())) < Tol) {
662     VV = TheV.LastParameter();
663   }  
664   else {  
665     // test if the curve is at the side `negative Y`.
666     if ( Min( PF.Y(),PL.Y()) < -Tol)  Dist = -Dist;
667    
668     Handle(Geom2d_Line) Line 
669       = new Geom2d_Line(gp_Pnt2d(0., Dist), gp::DX2d());
670     
671 #ifdef DRAW
672     if (AffichCurve) {
673       static Standard_CString aTheV = "TheV" ;
674       DrawTrSurf::Set(aTheV,TheV.Curve());
675       static Standard_CString aLINF1 = "LINF1" ;
676       DrawTrSurf::Set(aLINF1,Line);
677     }
678 #endif    
679     
680     Geom2dAdaptor_Curve Cu1 = TheV;
681     Geom2dAdaptor_Curve Cu2( Line);
682     
683     Standard_Real TolConf = 0.;
684
685     Geom2dInt_GInter Intersector(Cu1,Cu2,TolConf,Tol);
686
687     if ( !Intersector.IsDone()) {
688 #ifdef DEB
689       cout << "Intersector not done" << endl;
690       cout << "  ---> ValueonFace failed at parameter U = " << U << endl;
691 #endif
692       return gp_Pnt2d(0.,0.);
693     }
694     else {
695       if ( Intersector.NbPoints() > 0) {
696         VV = Intersector.Point(1).ParamOnFirst();
697       }
698       else if ( Intersector.NbSegments() > 0) {
699         IntRes2d_IntersectionSegment Seg = Intersector.Segment(1);
700         Standard_Real VS1 = Seg.FirstPoint().ParamOnFirst();
701         Standard_Real VS2 = Seg.LastPoint().ParamOnFirst();
702         gp_Pnt2d      PS1 = TheV.Value(VS1);
703         gp_Pnt2d      PS2 = TheV.Value(VS2);
704         Standard_Real Alp = (Dist - PS1.Y())/(PS2.Y() - PS1.Y());
705         VV = Alp*(VS2 - VS1) + VS1;
706       }
707       else {
708 #ifdef DEB
709         cout << "Intersector done, but no points found" << endl;
710         cout << "  ---> ValueonFace failed at parameter U = " << U << endl;
711 #endif
712         if (Abs(Dist - PL.Y()) < Abs(Dist - PF.Y()))
713           VV = TheV.LastParameter();
714         else 
715           VV = TheV.FirstParameter();
716       }
717     }
718   }
719
720   if ( IsIsoU) 
721     return gp_Pnt2d(VV,UU);
722   else
723     return gp_Pnt2d(UU,VV);
724 }
725
726 //=======================================================================
727 //function : ValueOnF1
728 //purpose  : 
729 //=======================================================================
730
731 gp_Pnt2d BRepFill_MultiLine::ValueOnF1(const Standard_Real U) const 
732 {
733   return ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
734 }
735
736
737 //=======================================================================
738 //function : ValueOnF2
739 //purpose  : 
740 //=======================================================================
741
742 gp_Pnt2d BRepFill_MultiLine::ValueOnF2(const Standard_Real U) const 
743 {
744   return ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
745 }
746
747 //=======================================================================
748 //function : Value3dOnF1OnF2
749 //purpose  : 
750 //=======================================================================
751
752 void BRepFill_MultiLine::Value3dOnF1OnF2(const Standard_Real U,
753                                                gp_Pnt&       P3d,
754                                                gp_Pnt2d&     PF1,
755                                                gp_Pnt2d&     PF2)
756 const
757 {
758   PF1 = ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
759   PF2 = ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
760
761   Handle(Geom_Surface) S;
762   TopLoc_Location L;
763
764   S = BRep_Tool::Surface(myFace1,L);  
765   P3d = S->Value(PF1.X(), PF1.Y());
766   P3d.Transform(L.Transformation());
767 }
768
769 //=======================================================================
770 //function : Continuity
771 //purpose  : 
772 //=======================================================================
773
774 GeomAbs_Shape BRepFill_MultiLine::Continuity() const
775 {
776   return myCont;
777 }