0029691: Constructor of BRepFill_MultiLine adjusts V-parameter of sphere in the range...
[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   // end try duplication
231
232   myU1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU1, BasisPlane),
233     Umin, Umax);
234
235   UU1->D1(Umin, P, DZ);
236   RefPlane = new Geom_Plane(gp_Ax3(P,DZ,gp::DZ()));
237
238   myV1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV1, RefPlane),
239     Vmin, Vmax);
240
241
242   First = Standard_True;
243   for (Exp.Init(myFace2,TopAbs_EDGE);Exp.More(); Exp.Next()) {
244     TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
245     BRep_Tool::UVPoints(CurEdge,myFace2,P1,P2);
246     if ( First) {
247       First = Standard_False;
248       Umin = Min(P1.X(),P2.X());
249       Umax = Max(P1.X(),P2.X());
250
251       Vmin = Min(P1.Y(),P2.Y());
252       Vmax = Max(P1.Y(),P2.Y());
253     }
254     else {
255       U    = Min(P1.X(),P2.X());
256       Umin = Min(Umin,U);
257       U    = Max(P1.X(),P2.X());
258       Umax = Max(Umax,U);
259
260       V    = Min(P1.Y(),P2.Y());
261       Vmin = Min(Vmin,V);
262       V    = Max(P1.Y(),P2.Y());
263       Vmax = Max(Vmax,V);
264     }
265   }
266
267   // return isos in their domain of restriction.
268   S = BRep_Tool::Surface(myFace2,L);
269
270   if (!L.IsIdentity())
271     S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
272
273   if ( myIsoU2) {
274     if (!BRep_Tool::Degenerated(Edge2) && !Inv2) {
275       UU2 = S->UIso(Umin);    
276       GeomAdaptor_Curve Dummy(UU2);
277       if (Dummy.GetType() == GeomAbs_Circle && 
278         Dummy.Circle().Radius() < eps) {
279           UU2 = S->UIso(Umax);
280       }
281     }
282     else {
283       UU2 = S->UIso(Umax);
284       GeomAdaptor_Curve Dummy(UU2);
285       if (Dummy.GetType() == GeomAbs_Circle && 
286         Dummy.Circle().Radius() < eps) {
287           UU2 = S->UIso(Umin);
288       }
289     }
290     VV2 = S->VIso(Vmin);
291   }
292   else {
293     if (!BRep_Tool::Degenerated(Edge2) && !Inv2) {
294       UU2 = S->VIso(Vmin);
295       GeomAdaptor_Curve Dummy(UU2);
296       if (Dummy.GetType() == GeomAbs_Circle && 
297         Dummy.Circle().Radius() < eps) {
298           UU2 = S->VIso(Vmax);
299       }
300     }
301     else {
302       UU2 = S->VIso(Vmax);
303       GeomAdaptor_Curve Dummy(UU2);
304       if (Dummy.GetType() == GeomAbs_Circle && 
305         Dummy.Circle().Radius() < eps) {
306           UU2 = S->VIso(Vmin);
307       }
308     }
309     VV2 = S->UIso(Umin);
310   }
311
312   if ( myIsoU2) {
313     Standard_Real dummyUmin = Umin, dummyUmax = Umax;
314     Umin = Vmin; 
315     Umax = Vmax;
316     Vmin = dummyUmin;
317     Vmax = dummyUmax;
318   }
319
320   // try duplication
321   GeomAdaptor_Surface GAS2(S);
322   GeomAbs_SurfaceType Type2 = GAS2.GetType();
323
324   if ( UU2->IsPeriodic()) {
325     ElCLib::AdjustPeriodic(UU2->FirstParameter(),
326       UU2->LastParameter(),
327       Precision::PConfusion(),
328       Umin, Umax);
329   }
330   if ( VV2->IsPeriodic()) {
331     ElCLib::AdjustPeriodic(VV2->FirstParameter(),
332       VV2->LastParameter(),
333       Precision::PConfusion(),
334       Vmin, Vmax);
335   }
336   // end try duplication
337
338   myU2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU2, BasisPlane),
339     Umin, Umax);
340
341   UU2->D1(Umin, P, DZ);
342   RefPlane = new Geom_Plane(gp_Ax3(P,DZ,gp::DZ()));
343   myV2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV2, RefPlane),
344     Vmin, Vmax);
345
346   // eval if in a particular case.
347   // Particular case if :
348   //     1) - Straight Bissectrice
349   //        - Bissectrice orthogonal to the base element.
350   //        ==> Iso on 2 faces.
351   //     2) - Straight Bissectrice
352   //        - 2 surfaces are planes.
353   myCont  = GeomAbs_C0;
354
355   if ( myBis.GetType() == GeomAbs_Line) {
356     Standard_Real DeltaU = myBis.LastParameter()  - myBis.FirstParameter();
357     gp_Pnt2d aPnt1 = ValueOnF1(myBis.FirstParameter() + 0.1*DeltaU);
358     gp_Pnt2d aPnt2 = ValueOnF1(myBis.FirstParameter() + 0.9*DeltaU);
359     if ( myIsoU1) {
360       if ( Abs(aPnt1.Y() - aPnt2.Y()) < eps)
361         myKPart = 1;
362     }
363     else {
364       if ( Abs(aPnt1.X() - aPnt2.X()) < eps)
365         myKPart = 1;
366     }
367
368     if ( myKPart == 1)
369       myCont = GeomAbs_G1;
370
371     if ( (Type1 == GeomAbs_Plane) && (Type2 == GeomAbs_Plane)) {
372       myKPart = 2;
373     }
374   }
375 }
376
377
378 //=======================================================================
379 //function : IsParticularCase
380 //purpose  : 
381 //=======================================================================
382
383 Standard_Boolean BRepFill_MultiLine::IsParticularCase() const 
384 {
385   return ( myKPart != 0);
386 }
387
388
389 //=======================================================================
390 //function : Curves
391 //purpose  : 
392 //=======================================================================
393
394 void BRepFill_MultiLine::Curves(Handle(Geom_Curve)& Curve,
395   Handle(Geom2d_Curve)& PCurve1,
396   Handle(Geom2d_Curve)& PCurve2) const 
397 {
398   if ( myKPart == 1) {
399     gp_Pnt2d      P1,P2,PMil;
400     Standard_Real f,l;
401
402     P1   = ValueOnF1(myBis.FirstParameter());
403     P2   = ValueOnF1(myBis.LastParameter());
404
405     // find value of the with medium point 
406     // the ends can be degenerated points.
407
408     PMil = ValueOnF1(0.5*(myBis.FirstParameter() + myBis.LastParameter()));
409
410     TopLoc_Location L;
411     Handle(Geom_Surface) S = BRep_Tool::Surface(myFace1,L);
412     if (!L.IsIdentity())
413       S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
414
415     Standard_Boolean Sens;
416     if ( !myIsoU1) {
417       Curve   = S->UIso(PMil.X());
418       Sens    = P1.Y() < P2.Y();
419       if ( Sens) 
420         Curve   = new Geom_TrimmedCurve(Curve, P1.Y(), P2.Y(), Sens);
421       else
422         Curve   = new Geom_TrimmedCurve(Curve, P2.Y(), P1.Y(), Sens);
423
424       f = Curve->FirstParameter();
425       l = Curve->LastParameter();
426       if ( Sens) 
427         PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(),P1.Y() - f), gp::DY2d());
428       else
429         PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(),P1.Y() + f),-gp::DY2d());
430       PCurve1 = new Geom2d_TrimmedCurve( PCurve1 ,f ,l);
431     }
432     else {
433       Curve   = S->VIso(PMil.Y());
434       Sens = P1.X() < P2.X();
435       if (Sens)
436         Curve   = new Geom_TrimmedCurve(Curve, P1.X(), P2.X(), Sens);
437       else
438         Curve   = new Geom_TrimmedCurve(Curve, P2.X(), P1.X(), Sens);
439
440       f = Curve->FirstParameter();
441       l = Curve->LastParameter();
442       if ( Sens) 
443         PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() - f,PMil.Y()), gp::DX2d());
444       else
445         PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() + f,PMil.Y()), -gp::DX2d());
446       PCurve1 = new Geom2d_TrimmedCurve( PCurve1 ,f ,l);
447     }
448
449     P1   = ValueOnF2(myBis.FirstParameter());
450     P2   = ValueOnF2(myBis.LastParameter());
451     PMil = ValueOnF2(0.5*(myBis.FirstParameter() + myBis.LastParameter()));
452
453     if (!myIsoU2) {
454       Sens = P1.Y() < P2.Y();
455       if ( Sens) 
456         PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(),(P1.Y() - f)), gp::DY2d());
457       else
458         PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(),(P1.Y() + f)), -gp::DY2d());
459     }
460     else {
461       Sens = P1.X() < P2.X();
462       if ( Sens) 
463         PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() - f ,PMil.Y()), gp::DX2d());
464       else
465         PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() + f ,PMil.Y()), -gp::DX2d());
466     }
467     PCurve2 = new Geom2d_TrimmedCurve( PCurve2 ,f ,l);
468   }
469   else if ( myKPart == 2) {
470     TopLoc_Location L;
471
472     Handle(Geom_Surface) S = BRep_Tool::Surface(myFace1,L);
473     if (!L.IsIdentity())
474       S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
475
476     if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
477       S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
478
479     Handle(Geom_Plane) Plane = Handle(Geom_Plane)::DownCast(S);
480     // eval the 3d curve corresponding to the bissectrice.
481     gp_Pnt2d P = myBis.Line().Location();
482     gp_Dir2d D = myBis.Line().Direction();
483     Handle(Geom_Line) Line = new Geom_Line(gp_Pnt(P.X(),P.Y(),0.),
484       gp_Dir(D.X(),D.Y(),0.) );
485     Handle(Geom_TrimmedCurve) TLine = 
486       new Geom_TrimmedCurve(Line, myBis.FirstParameter(),
487       myBis.LastParameter());
488     Curve = GeomProjLib::ProjectOnPlane(TLine, Plane, 
489       gp::DZ(), Standard_False);
490
491 #ifdef DRAW
492     if ( AffichCurve) {
493       char name[100];
494       sprintf(name,"C2_%d",NbProj);
495       DrawTrSurf::Set(name,TLine);
496       sprintf(name,"C3_%d",NbProj);
497       DrawTrSurf::Set(name,Curve);
498       sprintf(name,"SS_%d",NbProj);
499       DrawTrSurf::Set(name,Plane);
500       NbProj++;
501     }
502 #endif
503
504     // eval PCurve1
505     PCurve1 = GeomProjLib::Curve2d(Curve,Plane);
506
507     // eval PCurve2
508     S = BRep_Tool::Surface(myFace2,L);
509     if (!L.IsIdentity())
510       S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
511     if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) 
512       S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
513     Plane = Handle(Geom_Plane)::DownCast(S);
514     PCurve2 = GeomProjLib::Curve2d(Curve,Plane);
515   }
516 }
517
518
519 //=======================================================================
520 //function : FirstParameter
521 //purpose  : 
522 //=======================================================================
523
524 Standard_Real BRepFill_MultiLine::FirstParameter() const 
525 {
526   return myBis.FirstParameter();
527 }
528
529
530 //=======================================================================
531 //function : LastParameter
532 //purpose  : 
533 //=======================================================================
534
535 Standard_Real BRepFill_MultiLine::LastParameter() const 
536 {
537   return myBis.LastParameter();
538 }
539
540
541 //=======================================================================
542 //function : Value
543 //purpose  : 
544 //=======================================================================
545
546 gp_Pnt BRepFill_MultiLine::Value(const Standard_Real U) const 
547 {
548   Handle(Geom_Surface) S;
549   TopLoc_Location L;
550
551   S = BRep_Tool::Surface(myFace1,L);  
552
553   gp_Pnt2d P2d = ValueOnF1(U);
554
555   gp_Pnt P3d = S->Value(P2d.X(), P2d.Y());
556   P3d.Transform(L.Transformation());
557
558   return P3d;
559 }
560
561
562 //=======================================================================
563 //function : ValueOnFace
564 //purpose  : 
565 //=======================================================================
566
567 static gp_Pnt2d ValueOnFace(const Standard_Real        U,
568   const Geom2dAdaptor_Curve& TheBis,
569   const Geom2dAdaptor_Curve& TheU,
570   const Geom2dAdaptor_Curve& TheV,
571   const Standard_Boolean     IsIsoU)
572 {
573   gp_Pnt2d P = TheBis.Value(U);
574
575   Geom2dAPI_ProjectPointOnCurve Ext(P,TheU.Curve(),
576     TheU.FirstParameter(),
577     TheU.LastParameter());
578 #ifdef DRAW
579   if (AffichCurve) {
580     char* TheUname = "TheU";
581     char* PP1name = "PP1";
582     DrawTrSurf::Set(TheUname,TheU.Curve());
583     DrawTrSurf::Set(PP1name,P);
584     //    DrawTrSurf::Set("TheU",TheU.Curve());
585     //    DrawTrSurf::Set("PP1",P);
586   }
587 #endif
588   //
589   const Standard_Real mult = 5.;
590   const Standard_Real eps = mult * Precision::Confusion();
591   //
592   Standard_Real UU =0., Dist = Precision::Infinite(), D1, D2;
593
594   if ( Ext.NbPoints() != 0 ) {
595     UU = Ext.LowerDistanceParameter();
596     Dist = Ext.LowerDistance();
597   }
598   // Control with `ends` 
599   D1 = P.Distance(TheU.Value(TheU.FirstParameter()));
600   D2 = P.Distance(TheU.Value(TheU.LastParameter()));
601
602   if (D1 < Dist || D2 < Dist || Abs(D1 - Dist) < eps || Abs(D2 - Dist) < eps) {
603     if ( Abs( D1 - D2) < eps) {
604       if ( TheU.GetType() == GeomAbs_Circle) {
605         gp_Vec2d Axis = TheU.Circle().XAxis().Direction();
606         gp_Vec2d D12d = TheBis.DN(TheBis.FirstParameter(),1);
607         Standard_Real Ang = Axis.Angle(D12d);
608         if ( !TheU.Circle().IsDirect()) Ang = -Ang;
609         UU = ElCLib::InPeriod( Ang, TheU.FirstParameter(), 
610           TheU.FirstParameter() + 2*M_PI);
611         Dist = TheU.Circle().Radius();
612       }
613       else {
614 #ifdef OCCT_DEBUG
615         cout << "MultiLine : D1 = D2 and the Curve is not a circle" << endl;
616         cout << "  ---> ValueOnFace failed at parameter U = " << U << endl;
617 #endif
618         throw Standard_ConstructionError("BRepFill_MultiLine: ValueOnFace");
619       }
620     }
621     else if ( D1 < D2) {
622       Dist = D1;
623       UU   = TheU.FirstParameter();
624     }
625     else {
626       Dist = D2;
627       UU   = TheU.LastParameter();
628     }
629   }
630
631   const Standard_Real Tol = Precision::Confusion();
632   Standard_Real VV;
633
634   gp_Pnt2d PF = TheV.Value(TheV.FirstParameter());
635   gp_Pnt2d PL = TheV.Value(TheV.LastParameter());  
636
637   if (Abs(Dist - Abs(PF.Y())) < Tol) {
638     VV = TheV.FirstParameter();
639   }
640   else if (Abs(Dist - Abs(PL.Y())) < Tol) {
641     VV = TheV.LastParameter();
642   }  
643   else {  
644     // test if the curve is at the side `negative Y`.
645     if ( Min( PF.Y(),PL.Y()) < -Tol)  Dist = -Dist;
646
647     Handle(Geom2d_Line) Line 
648       = new Geom2d_Line(gp_Pnt2d(0., Dist), gp::DX2d());
649
650 #ifdef DRAW
651     if (AffichCurve) {
652       static Standard_CString aTheV = "TheV" ;
653       DrawTrSurf::Set(aTheV,TheV.Curve());
654       static Standard_CString aLINF1 = "LINF1" ;
655       DrawTrSurf::Set(aLINF1,Line);
656     }
657 #endif    
658
659     Geom2dAdaptor_Curve Cu1 = TheV;
660     Geom2dAdaptor_Curve Cu2( Line);
661
662     Standard_Real TolConf = 0.;
663
664     Geom2dInt_GInter Intersector(Cu1,Cu2,TolConf,Tol);
665
666     if ( !Intersector.IsDone()) {
667 #ifdef OCCT_DEBUG
668       cout << "Intersector not done" << endl;
669       cout << "  ---> ValueonFace failed at parameter U = " << U << endl;
670 #endif
671       return gp_Pnt2d(0.,0.);
672     }
673     else {
674       if ( Intersector.NbPoints() > 0) {
675         VV = Intersector.Point(1).ParamOnFirst();
676       }
677       else if ( Intersector.NbSegments() > 0) {
678         IntRes2d_IntersectionSegment Seg = Intersector.Segment(1);
679         Standard_Real VS1 = Seg.FirstPoint().ParamOnFirst();
680         Standard_Real VS2 = Seg.LastPoint().ParamOnFirst();
681         gp_Pnt2d      PS1 = TheV.Value(VS1);
682         gp_Pnt2d      PS2 = TheV.Value(VS2);
683         Standard_Real Alp = (Dist - PS1.Y())/(PS2.Y() - PS1.Y());
684         VV = Alp*(VS2 - VS1) + VS1;
685       }
686       else {
687 #ifdef OCCT_DEBUG
688         cout << "Intersector done, but no points found" << endl;
689         cout << "  ---> ValueonFace failed at parameter U = " << U << endl;
690 #endif
691         if (Abs(Dist - PL.Y()) < Abs(Dist - PF.Y()))
692           VV = TheV.LastParameter();
693         else 
694           VV = TheV.FirstParameter();
695       }
696     }
697   }
698
699   if ( IsIsoU) 
700     return gp_Pnt2d(VV,UU);
701   else
702     return gp_Pnt2d(UU,VV);
703 }
704
705 //=======================================================================
706 //function : ValueOnF1
707 //purpose  : 
708 //=======================================================================
709
710 gp_Pnt2d BRepFill_MultiLine::ValueOnF1(const Standard_Real U) const 
711 {
712   return ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
713 }
714
715
716 //=======================================================================
717 //function : ValueOnF2
718 //purpose  : 
719 //=======================================================================
720
721 gp_Pnt2d BRepFill_MultiLine::ValueOnF2(const Standard_Real U) const 
722 {
723   return ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
724 }
725
726 //=======================================================================
727 //function : Value3dOnF1OnF2
728 //purpose  : 
729 //=======================================================================
730
731 void BRepFill_MultiLine::Value3dOnF1OnF2(const Standard_Real U,
732   gp_Pnt&       P3d,
733   gp_Pnt2d&     PF1,
734   gp_Pnt2d&     PF2)
735   const
736 {
737   PF1 = ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
738   PF2 = ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
739
740   Handle(Geom_Surface) S;
741   TopLoc_Location L;
742
743   S = BRep_Tool::Surface(myFace1,L);  
744   P3d = S->Value(PF1.X(), PF1.Y());
745   P3d.Transform(L.Transformation());
746 }
747
748 //=======================================================================
749 //function : Continuity
750 //purpose  : 
751 //=======================================================================
752
753 GeomAbs_Shape BRepFill_MultiLine::Continuity() const
754 {
755   return myCont;
756 }
757
758 //=======================================================================
759 //function : Value
760 //purpose  : 
761 //=======================================================================
762
763 Standard_Boolean BRepFill_MultiLine::Value(const Standard_Real   theT,
764   NCollection_Array1<gp_Pnt2d>& thePnt2d,
765   NCollection_Array1<gp_Pnt>&   thePnt) const
766 {
767   thePnt(1)   = Value(theT);
768   thePnt2d(1) = ValueOnF1(theT);
769   thePnt2d(2) = ValueOnF2(theT);
770   return Standard_True;
771 }
772
773 //=======================================================================
774 //function : Value
775 //purpose  : 
776 //=======================================================================
777
778 Standard_Boolean BRepFill_MultiLine::D1(const Standard_Real   /*theT*/,
779   NCollection_Array1<gp_Vec2d>& /*theVec2d*/,
780   NCollection_Array1<gp_Vec>&   /*theVec*/) const
781 {
782   return Standard_False;
783 }