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