OCC22163 The bug is appendix to the Salome Bug 0020982
[occt.git] / src / ChFi3d / ChFi3d_Builder_0.cxx
1 // File:      ChFi3d_Builder_0.cxx
2 // Created:   Thu Dec 16 15:54:39 1993
3 // Author:    Isabelle GRIGNON
4 // Copyright: OPEN CASCADE 1993
5
6 //  modified by ofv - Thu Feb 26 11:18:16 2004 OCC5246
7 //  Modified by skv - Fri Oct 24 14:24:47 2003 OCC4077
8 //  Modified by skv - Mon Jun 16 15:50:44 2003 OCC615
9
10 #include <ChFi3d.hxx>
11 #include <Precision.hxx>
12
13 #include <Standard_NotImplemented.hxx>
14 #include <Standard_ConstructionError.hxx>
15
16 #include <gp.hxx>
17 #include <gp_Circ.hxx>
18 #include <gp_Elips.hxx>
19 #include <gp_Lin.hxx>
20 #include <gp_Pnt.hxx>
21 #include <gp_Pnt2d.hxx>
22 #include <gp_Lin2d.hxx>
23 #include <ElCLib.hxx>
24 #include <ElSLib.hxx>
25 #include <BSplCLib.hxx>
26 #include <GeomLib.hxx>
27
28 #include <TColgp_Array1OfPnt2d.hxx>
29 #include <TColgp_Array1OfPnt.hxx>
30 #include <TColgp_Array1OfXYZ.hxx>
31 #include <TColStd_Array1OfInteger.hxx>
32 #include <TColStd_Array1OfReal.hxx>
33
34 #include <Geom_TrimmedCurve.hxx>
35 #include <Geom_BSplineCurve.hxx>
36 #include <Geom_Surface.hxx>
37 #include <Geom_CylindricalSurface.hxx>
38 #include <Geom_RectangularTrimmedSurface.hxx>
39 #include <Geom_Plane.hxx>
40 #include <Geom_Line.hxx>
41 #include <Geom_Circle.hxx>
42 #include <Geom_Ellipse.hxx>
43 #include <Geom2d_BezierCurve.hxx>
44 #include <Geom2d_BSplineCurve.hxx>
45 #include <Geom2d_Line.hxx>
46 #include <Geom2d_Circle.hxx>
47 #include <Geom2d_Ellipse.hxx>
48 #include <Geom2d_Hyperbola.hxx>
49 #include <Geom2d_Parabola.hxx>
50 #include <Geom2d_TrimmedCurve.hxx>
51 #include <Geom2d_Line.hxx>
52 #include <Geom2d_OffsetCurve.hxx>
53 #include <Geom2dAdaptor_Curve.hxx>
54 #include <Geom2dAdaptor_HCurve.hxx>
55 #include <Adaptor3d_TopolTool.hxx>
56 #include <Adaptor3d_CurveOnSurface.hxx>
57 #include <Adaptor3d_HCurveOnSurface.hxx>
58 #include <GeomAdaptor_HSurface.hxx>
59
60 #include <FairCurve_Batten.hxx>
61 #include <FairCurve_AnalysisCode.hxx>
62 #include <Convert_ParameterisationType.hxx>
63 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
64 #include <GeomConvert.hxx>
65 #include <GeomLib_Interpolate.hxx>
66 #include <GeomAPI_ProjectPointOnSurf.hxx>
67 #include <GeomAPI_ProjectPointOnCurve.hxx>
68 #include <GC_MakeCircle.hxx>
69 #include <BRepAdaptor_Curve.hxx>
70 #include <BRepAdaptor_HCurve.hxx>
71 #include <BRepAdaptor_HCurve2d.hxx>
72 #include <BRepAdaptor_Surface.hxx>
73 #include <BRepTopAdaptor_HVertex.hxx>
74
75 #include <BRep_Tool.hxx>
76 #include <BRep_Builder.hxx>
77 #include <BRepTools.hxx>
78 #include <BRepTools_WireExplorer.hxx>
79 #include <BRepLib.hxx>
80 #include <BRepLib_MakeEdge.hxx>
81 #include <BRepLib_MakeWire.hxx>
82 #include <BRepLib_MakeFace.hxx>
83
84 #include <TopAbs.hxx>
85 #include <TopoDS_Shape.hxx>
86 #include <TopoDS_Edge.hxx>
87 #include <TopoDS_Vertex.hxx>
88 #include <TopoDS_Wire.hxx>
89 #include <TopoDS_Face.hxx>
90 #include <TopExp.hxx>
91 #include <TopExp_Explorer.hxx>
92 #include <TopTools_Array1OfShape.hxx>
93
94
95 #include <GeomAbs_Shape.hxx>
96 #include <Bnd_Box2d.hxx>
97
98 //#include <math_FunctionSample.hxx>
99 //#include <math_FunctionAllRoots.hxx>
100 #include <GCPnts_AbscissaPoint.hxx>
101
102 #include <IntCurveSurface_TheQuadCurvFuncOfTheQuadCurvExactHInter.hxx>
103 #include <IntCurveSurface_HInter.hxx>
104 #include <IntCurveSurface_IntersectionPoint.hxx>
105 #include <IntSurf_Quadric.hxx>
106 #include <IntSurf_PntOn2S.hxx>
107 #include <IntSurf_LineOn2S.hxx>
108 #include <IntAna_QuadQuadGeo.hxx>
109 #include <IntAna2d_AnaIntersection.hxx>
110 #include <IntRes2d_IntersectionPoint.hxx>
111 #include <IntPatch_ThePWalkingInter.hxx>
112 #include <IntPatch_WLine.hxx>
113 #include <Geom2dInt_GInter.hxx>
114 #include <GeomInt_WLApprox.hxx>
115 #include <GeomInt_IntSS.hxx>
116 #include <AppParCurves_MultiBSpCurve.hxx>
117 #include <Approx_SameParameter.hxx>
118
119 #include <TopAbs.hxx>
120 #include <TopoDS_Shape.hxx>
121 #include <TopoDS_Edge.hxx>
122 #include <TopExp.hxx>
123
124 #include <TopOpeBRepDS.hxx>
125 #include <TopOpeBRepDS_Surface.hxx>
126 #include <TopOpeBRepDS_Point.hxx>
127 #include <TopOpeBRepDS_SolidSurfaceInterference.hxx>
128 #include <TopOpeBRepDS_CurvePointInterference.hxx>
129 #include <TopOpeBRepDS_ListOfInterference.hxx>
130 #include <TopOpeBRepDS_InterferenceIterator.hxx>
131 #include <ProjLib_ProjectedCurve.hxx>
132
133 #include <BRepBlend_PointOnRst.hxx>
134
135 #include <ChFiDS_HData.hxx>
136 #include <ChFiDS_SurfData.hxx>
137 #include <ChFiDS_FaceInterference.hxx>
138 #include <ChFiDS_Spine.hxx>
139 #include <ChFiDS_FilSpine.hxx>
140 #include <ChFiDS_SequenceOfSurfData.hxx>
141 #include <ChFiDS_Regul.hxx>
142 #include <Law_Function.hxx>
143 #include <Law_Composite.hxx>
144 #include <GeomAPI_PointsToBSpline.hxx>
145 #include <GeomLProp_CLProps.hxx>
146
147 #include <ChFi3d_Builder_0.hxx>
148
149 #ifdef DEB
150 #include <OSD_Chronometer.hxx>
151 extern Standard_Boolean ChFi3d_GetcontextFORCEBLEND(); 
152 extern Standard_Boolean ChFi3d_GettraceDRAWINT();
153 extern Standard_Boolean ChFi3d_GettraceDRAWENLARGE();
154 extern Standard_Boolean ChFi3d_GettraceDRAWSPINE();
155 extern Standard_Real  t_sameparam, t_batten;
156 extern void ChFi3d_SettraceDRAWINT(const Standard_Boolean b);
157 extern void ChFi3d_SettraceDRAWSPINE(const Standard_Boolean b);
158 extern void ChFi3d_InitChron(OSD_Chronometer& ch);
159 extern void ChFi3d_ResultChron(OSD_Chronometer & ch,Standard_Real& time);
160 #endif
161
162 #include <stdio.h>
163
164 #include <GeomAdaptor_HCurve.hxx>
165 #include <BRepAdaptor_HSurface.hxx>
166
167 //=======================================================================
168 //function : ChFi3d_InPeriod
169 //purpose  : 
170 //=======================================================================
171 Standard_Real ChFi3d_InPeriod(const Standard_Real U, 
172                               const Standard_Real UFirst, 
173                               const Standard_Real ULast,
174                               const Standard_Real Eps)
175 {
176   const Standard_Real period = ULast - UFirst;
177   Standard_Real u = U;
178   while (Eps < (UFirst-u)) u += period;
179   while (Eps > (ULast -u)) u -= period;
180   if ( u < UFirst) u = UFirst;
181   return u;
182 }
183 //=======================================================================
184 //function : Boite 
185 //purpose  : Calcul des min/max uv du conge a intersecter.
186 //=======================================================================
187 void ChFi3d_Boite(const gp_Pnt2d& p1,const gp_Pnt2d& p2,
188                   Standard_Real& mu,Standard_Real& Mu,
189                   Standard_Real& mv,Standard_Real& Mv)
190 {
191   mu = Min(p1.X(),p2.X()); Mu = Max(p1.X(),p2.X());
192   mv = Min(p1.Y(),p2.Y()); Mv = Max(p1.Y(),p2.Y());
193 }
194 //=======================================================================
195 //function : Boite 
196 //purpose  : Calcul des min/max uv du conge a intersecter.
197 //=======================================================================
198 void ChFi3d_Boite(const gp_Pnt2d& p1,const gp_Pnt2d& p2,
199                   const gp_Pnt2d& p3,const gp_Pnt2d& p4,
200                   Standard_Real& Du,Standard_Real& Dv,
201                   Standard_Real& mu,Standard_Real& Mu,
202                   Standard_Real& mv,Standard_Real& Mv)
203 {
204   Standard_Real a,b;
205   a = Min(p1.X(),p2.X());  b = Min(p3.X(),p4.X()); mu = Min(a,b);
206   a = Max(p1.X(),p2.X());  b = Max(p3.X(),p4.X()); Mu = Max(a,b);
207   a = Min(p1.Y(),p2.Y());  b = Min(p3.Y(),p4.Y()); mv = Min(a,b);
208   a = Max(p1.Y(),p2.Y());  b = Max(p3.Y(),p4.Y()); Mv = Max(a,b);
209   Du = Mu - mu;
210   Dv = Mv - mv;
211 }
212 //=======================================================================
213 //function : EnlargeBox et ses amis.
214 //purpose  : 
215 //=======================================================================
216 static Handle(Adaptor3d_HSurface) Geometry(TopOpeBRepDS_DataStructure& DStr,
217                                            const Standard_Integer      ind)
218 {
219   if(ind == 0) return Handle(Adaptor3d_HSurface)();
220   if(ind > 0) {
221     TopoDS_Face F = TopoDS::Face(DStr.Shape(ind));
222     if(F.IsNull()) return Handle(Adaptor3d_HSurface)();
223     Handle(BRepAdaptor_HSurface) HS = new BRepAdaptor_HSurface();
224     HS->ChangeSurface().Initialize(F,0);
225     return HS;
226   }
227   else{
228     Handle(Geom_Surface) S  = DStr.Surface(-ind).Surface();
229     if(S.IsNull()) return Handle(Adaptor3d_HSurface)();
230     return new GeomAdaptor_HSurface(S);
231   }
232 }
233 //=======================================================================
234 //function : ChFi3d_SetPointTolerance
235 //purpose  : 
236 //=======================================================================
237 void ChFi3d_SetPointTolerance(TopOpeBRepDS_DataStructure& DStr,
238                               const Bnd_Box&              box,
239                               const Standard_Integer      IP)
240 {
241   Standard_Real a,b,c,d,e,f,vtol;
242   box.Get(a,b,c,d,e,f); 
243   d-=a; e-=b; f-=c; 
244   d*=d; e*=e; f*=f;
245   vtol = sqrt(d + e + f) * 1.5;// on prend un petit rab.
246   DStr.ChangePoint(IP).Tolerance(vtol);
247 }
248 //=======================================================================
249 //function : ChFi3d_EnlargeBox
250 //purpose  : 
251 //=======================================================================
252 void ChFi3d_EnlargeBox(const Handle(Geom_Curve)& C,
253                        const Standard_Real       wd,
254                        const Standard_Real       wf,
255                        Bnd_Box&                  box1,
256                        Bnd_Box&                  box2)
257 {
258   box1.Add(C->Value(wd));
259   box2.Add(C->Value(wf));
260 }
261 //=======================================================================
262 //function : ChFi3d_EnlargeBox
263 //purpose  : 
264 //=======================================================================
265 void ChFi3d_EnlargeBox(const Handle(Adaptor3d_HSurface)& S,
266                        const Handle(Geom2d_Curve)&     PC,
267                        const Standard_Real             wd,
268                        const Standard_Real             wf,
269                        Bnd_Box&                        box1,
270                        Bnd_Box&                        box2)
271 {
272   Standard_Real u,v;
273   PC->Value(wd).Coord(u,v);
274   box1.Add(S->Value(u,v));
275   PC->Value(wf).Coord(u,v);
276   box2.Add(S->Value(u,v));
277 }
278 //=======================================================================
279 //function : ChFi3d_EnlargeBox
280 //purpose  : 
281 //=======================================================================
282 void ChFi3d_EnlargeBox(const TopoDS_Edge&           E,
283                        const TopTools_ListOfShape&  LF,
284                        const Standard_Real          w,
285                        Bnd_Box&                     box)
286
287 {
288   BRepAdaptor_Curve BC(E);
289   box.Add(BC.Value(w));
290   TopTools_ListIteratorOfListOfShape It;
291   for(It.Initialize(LF); It.More(); It.Next()) {
292     TopoDS_Face F = TopoDS::Face(It.Value());
293     if(!F.IsNull()) {
294       BC.Initialize(E,F);
295       box.Add(BC.Value(w));
296     }
297   }
298 }
299 //=======================================================================
300 //function : ChFi3d_EnlargeBox
301 //purpose  : 
302 //=======================================================================
303 void ChFi3d_EnlargeBox(TopOpeBRepDS_DataStructure&    DStr,
304                        const Handle(ChFiDS_Stripe)&   st, 
305                        const Handle(ChFiDS_SurfData)& sd,
306                        Bnd_Box&                       b1,
307                        Bnd_Box&                       b2,
308                        const Standard_Boolean         isfirst)
309 {
310   Standard_Real u,v;
311   const ChFiDS_CommonPoint& cp1 = sd->Vertex(isfirst,1);
312   const ChFiDS_CommonPoint& cp2 = sd->Vertex(isfirst,2);
313   b1.Add(cp1.Point());
314   b2.Add(cp2.Point());
315   const ChFiDS_FaceInterference& fi1 = sd->InterferenceOnS1();
316   const ChFiDS_FaceInterference& fi2 = sd->InterferenceOnS2();
317   const Handle(Geom_Surface)& S = DStr.Surface(sd->Surf()).Surface();
318   const Handle(Geom2d_Curve)& pcs1 = fi1.PCurveOnSurf();
319   const Handle(Geom2d_Curve)& pcs2 = fi2.PCurveOnSurf();
320   const Handle(Geom_Curve)& c3d1 = DStr.Curve(fi1.LineIndex()).Curve();
321   const Handle(Geom_Curve)& c3d2 = DStr.Curve(fi2.LineIndex()).Curve();
322   Handle(Adaptor3d_HSurface) F1 = Geometry(DStr,sd->IndexOfS1());
323   Handle(Adaptor3d_HSurface) F2 = Geometry(DStr,sd->IndexOfS2());
324   Standard_Real p1 = fi1.Parameter(isfirst);
325   if(!c3d1.IsNull()) b1.Add(c3d1->Value(p1));
326   if(!pcs1.IsNull()) {
327     pcs1->Value(p1).Coord(u,v);
328     b1.Add(S->Value(u,v));
329   }
330   if(!F1.IsNull()) {
331     const Handle(Geom2d_Curve)& pcf1 = fi1.PCurveOnFace();
332     if(!pcf1.IsNull()) {
333       pcf1->Value(p1).Coord(u,v);
334       b1.Add(F1->Value(u,v));
335     }
336   }
337   Standard_Real p2 = fi2.Parameter(isfirst);
338   if(!c3d2.IsNull()) b2.Add(c3d2->Value(p2));
339   if(!pcs2.IsNull()) {
340     pcs2->Value(p2).Coord(u,v);
341     b2.Add(S->Value(u,v));
342   }
343   if(!F2.IsNull()) {
344     const Handle(Geom2d_Curve)& pcf2 = fi2.PCurveOnFace();
345     if(!pcf2.IsNull()) {
346       pcf2->Value(p2).Coord(u,v);
347       b2.Add(F2->Value(u,v));
348     }
349   }
350   if(!st.IsNull()) {
351     const Handle(Geom_Curve)& c3d = DStr.Curve(st->Curve(isfirst)).Curve();
352     const Handle(Geom2d_Curve)& c2d = st->PCurve(isfirst);
353     if(st->Orientation(isfirst) == TopAbs_FORWARD) st->Parameters(isfirst,p1,p2);
354     else st->Parameters(isfirst,p2,p1);
355     if(!c3d.IsNull()) {
356       b1.Add(c3d->Value(p1));
357       b2.Add(c3d->Value(p2));
358     }
359     if(!c2d.IsNull()) {
360       c2d->Value(p1).Coord(u,v);
361       b1.Add(S->Value(u,v)); 
362       c2d->Value(p2).Coord(u,v);
363       b2.Add(S->Value(u,v));
364     }
365   }
366 }
367 //=======================================================================
368 //function : conexfaces
369 //purpose  : 
370 //=======================================================================
371 void ChFi3d_conexfaces(const TopoDS_Edge& E,
372                        TopoDS_Face&       F1,
373                        TopoDS_Face&       F2,
374                        const ChFiDS_Map&  EFMap)
375 {
376   TopTools_ListIteratorOfListOfShape It;
377   F1.Nullify();
378   F2.Nullify();
379   for(It.Initialize(EFMap(E));It.More();It.Next()) {  
380     if (F1.IsNull()) {
381       F1 = TopoDS::Face(It.Value());
382     }
383     else {
384       F2 = TopoDS::Face(It.Value());
385       if(!F2.IsSame(F1) || BRep_Tool::IsClosed(E,F1)) {
386         break;
387       }
388       else F2.Nullify();
389     }
390   }  
391 }
392 //=======================================================================
393 //function : EdgeState
394 //purpose  : examun des concavites pour les sommets a 3 aretes.
395 //=======================================================================
396 ChFiDS_State ChFi3d_EdgeState(TopoDS_Edge* E,
397                               const ChFiDS_Map&  EFMap)
398 {
399   ChFiDS_State sst;
400   Standard_Integer i,j;
401   TopoDS_Face F[3];
402   TopoDS_Face F1,F2,F3,F4,F5,F6;
403   ChFi3d_conexfaces(E[0],F1,F2,EFMap);
404   ChFi3d_conexfaces(E[1],F3,F4,EFMap);
405   ChFi3d_conexfaces(E[2],F5,F6,EFMap);
406   if(F1.IsSame(F2)) {
407     F[0] = F[1] = F1;
408     if(F1.IsSame(F3)) F[2] = F4;
409     else F[2] = F3;
410   }
411   else if(F3.IsSame(F4)) {
412     F[0] = F[2] = F3;
413     if(F3.IsSame(F1)) F[1] = F2;
414     else F[1] = F1;
415   }
416   else if(F5.IsSame(F6)) {
417     F[1] = F[2] = F5;
418     if(F5.IsSame(F1)) F[0] = F2;
419     else F[0] = F1;
420   }
421   else{
422     if(F1.IsSame(F3) || F1.IsSame(F4)) F[0] = F1;
423     else F[0] = F2;
424     if(F3.IsSame(F[0])) F[2] = F4;
425     else F[2] = F3;
426     if(F5.IsSame(F[2])) F[1] = F6;
427     else F[1] = F5;
428     
429   }
430   
431   if(F[0].IsNull() || F[1].IsNull() || F[2].IsNull()) sst = ChFiDS_FreeBoundary;
432   else{
433     TopAbs_Orientation o01,o02,o11,o12,o21,o22;
434     i=ChFi3d::ConcaveSide(F[0],F[1],E[0],o01,o02);
435     i=ChFi3d::ConcaveSide(F[0],F[2],E[1],o11,o12);
436     j=ChFi3d::ConcaveSide(F[1],F[2],E[2],o21,o22);
437     if(o01==o11 && o02==o21 && o12==o22) sst = ChFiDS_AllSame;
438     else if(o12==o22 || i ==10 || j ==10) sst = ChFiDS_OnDiff;
439     else sst = ChFiDS_OnSame;
440   }
441   return sst;
442 }
443 //=======================================================================
444 //function : evalconti
445 //purpose  : Methode tres rapide, a la limite de l imposture pour
446 //           coder les regularites CN. Il faudra affiner le traitement
447 //           quand le bug reviendra.
448 //=======================================================================
449 GeomAbs_Shape ChFi3d_evalconti(const TopoDS_Edge& /*E*/,
450                                const TopoDS_Face& F1,
451                                const TopoDS_Face& F2)
452 {
453   GeomAbs_Shape cont = GeomAbs_G1;
454   if(!F1.IsSame(F2)) return cont;
455   TopoDS_Face F = F1;
456   F.Orientation(TopAbs_FORWARD);
457   BRepAdaptor_Surface S(F,Standard_False);
458   GeomAbs_SurfaceType typ = S.GetType();
459   if(typ != GeomAbs_Cone && 
460      typ != GeomAbs_Sphere && 
461      typ != GeomAbs_Torus) return cont;
462   return GeomAbs_CN;
463 }
464 //modified by NIZNHY-PKV Wed Dec 15 11:22:35 2010f
465 //=======================================================================
466 //function : KParticular
467 //purpose  : 
468 //=======================================================================
469 Standard_Boolean ChFi3d_KParticular (const Handle(ChFiDS_Spine)& Spine,
470                                      const Standard_Integer      IE,
471                                      const BRepAdaptor_Surface&  S1,
472                                      const BRepAdaptor_Surface&  S2)
473 {
474   Standard_Boolean bRet;
475   //
476   bRet=Standard_True;
477   //
478   Handle(ChFiDS_FilSpine) fs = Handle(ChFiDS_FilSpine)::DownCast(Spine);
479   if(!fs.IsNull() && !fs->IsConstant(IE)) {
480     return !bRet;
481   }
482   //
483   Standard_Boolean bIsPlane1, bIsPlane2;
484   Standard_Real aPA;
485   GeomAbs_CurveType aCT;
486   GeomAbs_SurfaceType aST1, aST2;
487   //
488   aST1=S1.GetType();
489   aST2=S2.GetType();
490   bIsPlane1=(aST1==GeomAbs_Plane);
491   bIsPlane2=(aST2==GeomAbs_Plane);
492   if (!(bIsPlane1 || bIsPlane2)) {
493     return !bRet;
494   }
495   //
496   const BRepAdaptor_Surface& aS1=(bIsPlane1)? S1 : S2;
497   const BRepAdaptor_Surface& aS2=(bIsPlane1)? S2 : S1;
498   aST1=aS1.GetType();
499   aST2=aS2.GetType();
500   //
501   if (!(aST2==GeomAbs_Plane || aST2==GeomAbs_Cylinder || aST2==GeomAbs_Cone)) {
502     return !bRet;
503   } 
504   //
505   const BRepAdaptor_Curve& bc = Spine->CurrentElementarySpine(IE);
506   aCT = bc.GetType();
507   if (!(aCT==GeomAbs_Line || aCT==GeomAbs_Circle)) {
508     return !bRet;
509   }
510   //
511   aPA=Precision::Angular();
512   //
513   if (aST2==GeomAbs_Plane){
514     if (aCT==GeomAbs_Line) { 
515       return bRet;
516     }
517   }
518   else if (aST2==GeomAbs_Cylinder) {
519     const gp_Dir& aD1=aS1.Plane().Axis().Direction();
520     const gp_Dir& aD2=aS2.Cylinder().Axis().Direction();
521     //
522     if (aCT==GeomAbs_Line && aD1.IsNormal(aD2, aPA)) {
523       return bRet;
524     }
525     else if (aCT==GeomAbs_Circle && aD1.IsParallel(aD2, aPA)) {
526       return bRet;
527     }
528   }
529   else if(aST2==GeomAbs_Cone) {
530     const gp_Dir& aD1=aS1.Plane().Axis().Direction();
531     const gp_Dir& aD2=aS2.Cone().Axis().Direction();
532     if (aCT == GeomAbs_Circle && aD1.IsParallel(aD2, aPA)) {
533       return bRet;
534     }
535   }  
536   return !bRet;    
537 }
538 //modified by NIZNHY-PKV Wed Dec 15 11:22:43 2010t
539 //=======================================================================
540 //function : BoundFac
541 //purpose  : Resize les bornes d une surface au voisinage de la boite 
542 //           donnee. Utile pour les intersections dont on connait les
543 //           extremites. 
544 //=======================================================================
545 void ChFi3d_BoundFac(BRepAdaptor_Surface& S,
546                      const Standard_Real uumin,
547                      const Standard_Real uumax,
548                      const Standard_Real vvmin,
549                      const Standard_Real vvmax,
550                      const Standard_Boolean checknaturalbounds)
551 {
552   ChFi3d_BoundSrf(S.ChangeSurface(), uumin,uumax,vvmin,vvmax,checknaturalbounds);
553 }
554 //=======================================================================
555 //function : ChFi3d_BoundSrf
556 //purpose  : Resize les bornes d une surface au voisinage de la boite 
557 //           donnee. Utile pour les intersections dont on connait les
558 //           extremites. 
559 //=======================================================================
560 void ChFi3d_BoundSrf(GeomAdaptor_Surface& S,
561                      const Standard_Real uumin,
562                      const Standard_Real uumax,
563                      const Standard_Real vvmin,
564                      const Standard_Real vvmax,
565                      const Standard_Boolean checknaturalbounds)
566 {
567   Standard_Real umin = uumin, umax = uumax, vmin = vvmin, vmax = vvmax; 
568   Handle(Geom_Surface) surface = S.Surface();
569   Handle(Geom_RectangularTrimmedSurface) 
570     trs = Handle(Geom_RectangularTrimmedSurface)::DownCast(surface);
571   if(!trs.IsNull()) surface = trs->BasisSurface();
572   Standard_Real u1,u2,v1,v2;
573   surface->Bounds(u1,u2,v1,v2);
574   Standard_Real peru=0, perv=0;
575   if(surface->IsUPeriodic()) {
576     peru = surface->UPeriod();
577   }
578   if(surface->IsVPeriodic()) {
579     perv = surface->VPeriod();
580   }
581   Standard_Real Stepu = umax - umin;
582   Standard_Real Stepv = vmax - vmin;
583
584   //On table sur le fait que la boite uv est non nulle dans
585   //une des directions au moins.
586   Standard_Real scalu = S.UResolution(1.);
587   Standard_Real scalv = S.VResolution(1.);
588
589   Standard_Real step3du = Stepu/scalu; 
590   Standard_Real step3dv = Stepv/scalv;
591   
592   if(step3du > step3dv) Stepv = step3du*scalv;
593   if(step3dv > step3du) Stepu = step3dv*scalu;
594
595   if (peru > 0) Stepu = 0.1 * (peru - (umax - umin));
596   if (perv > 0) Stepv = 0.1 * (perv - (vmax - vmin));
597
598   Standard_Real uu1 = umin - Stepu;
599   Standard_Real uu2 = umax + Stepu;
600   Standard_Real vv1 = vmin - Stepv;
601   Standard_Real vv2 = vmax + Stepv;
602   if(checknaturalbounds) {
603     if(!S.IsUPeriodic()) {uu1 = Max(uu1,u1);  uu2 = Min(uu2,u2);}
604     if(!S.IsVPeriodic()) {vv1 = Max(vv1,v1);  vv2 = Min(vv2,v2);}
605   }
606   S.Load(surface,uu1,uu2,vv1,vv2);
607 }
608 //=======================================================================
609 //function : ChFi3d_InterPlaneEdge
610 //purpose  : 
611 //=======================================================================
612 Standard_Boolean  ChFi3d_InterPlaneEdge (Handle(Adaptor3d_HSurface)& Plan,
613                                          Handle(Adaptor3d_HCurve)&  C,
614                                          Standard_Real& W,
615                                          const Standard_Boolean Sens,
616                                          const Standard_Real tolc)
617
618   IntCurveSurface_HInter Intersection;
619   Standard_Integer isol = 0, nbp ,iip;
620   Standard_Real uf = C->FirstParameter(),ul = C->LastParameter();
621   Standard_Real CW;
622   
623   Intersection.Perform(C,Plan);
624   
625   if(Intersection.IsDone()) {
626     nbp = Intersection.NbPoints();
627     for (iip = 1; iip <= nbp; iip++) {
628       CW = Intersection.Point(iip).W();
629       if(C->IsPeriodic())
630         CW = ElCLib::InPeriod(CW,uf-tolc,uf-tolc+C->Period());
631       if(uf - tolc <= CW && ul + tolc >= CW) {
632         if (isol == 0) {
633           isol = iip; W = CW;
634         }
635         else {
636           if      ( Sens && CW < W) {
637             W = CW; isol = iip;
638           }
639           else if (!Sens && CW > W) {
640             W = CW; isol = iip;
641           }
642         }
643       }
644     }
645   }
646   if(isol == 0) return Standard_False;
647   return Standard_True;
648 }
649 //=======================================================================
650 //function : ExtrSpineCarac
651 //purpose  : 
652 //=======================================================================
653 void ChFi3d_ExtrSpineCarac(const TopOpeBRepDS_DataStructure& DStr,
654                            const Handle(ChFiDS_Stripe)& cd,
655                            const Standard_Integer i,
656                            const Standard_Real p,
657                            const Standard_Integer jf,
658                            const Standard_Integer sens,
659                            gp_Pnt& P,
660                            gp_Vec& V,
661                            Standard_Real& R) 
662      //voir s il ne faudrait pas rajouter D1,D2 et DR
663 {
664   // Attention pour les surfaces approximees on assume que
665   // le parametrage de la pcurve est le meme que celui de 
666   // l elspine qui a servi a la construction.
667   const Handle(Geom_Surface)& fffil = 
668     DStr.Surface(cd->SetOfSurfData()->Value(i)->Surf()).Surface();
669   gp_Pnt2d pp = cd->SetOfSurfData()->Value(i)->Interference(jf).
670     PCurveOnSurf()->Value(p);
671   GeomAdaptor_Surface gs(fffil);
672   P = fffil->Value(pp.X(),pp.Y());
673   gp_Pnt Pbid; gp_Vec Vbid;
674   switch (gs.GetType()) {
675   case GeomAbs_Cylinder :
676     {
677       gp_Cylinder cyl = gs.Cylinder();
678       R = cyl.Radius();
679       ElSLib::D1(pp.X(),pp.Y(),cyl,Pbid,Vbid,V);
680     }
681     break;
682   case GeomAbs_Torus :
683     {
684       gp_Torus tor = gs.Torus();
685       R = tor.MinorRadius();
686       ElSLib::D1(pp.X(),pp.Y(),tor,Pbid,V,Vbid);
687     }
688     break;
689   default:
690     { Standard_Integer nbelspine;
691       const Handle(ChFiDS_Spine)& sp = cd->Spine();
692       Handle(ChFiDS_FilSpine) fsp = Handle(ChFiDS_FilSpine)::DownCast(sp);
693       nbelspine=sp->NbEdges();
694       Handle(ChFiDS_HElSpine) hels;
695       if   (nbelspine==1) hels = sp->ElSpine(1);
696       else hels = sp->ElSpine(p);
697       if(fsp->IsConstant()) { R = fsp->Radius(); }
698       else { R = fsp->Law(hels)->Value(p); }
699       hels->D1(p,Pbid,V);
700     }
701     break;
702   }
703   V.Normalize();
704   if(sens == 1) V.Reverse();
705 }
706 //=======================================================================
707 //function : ChFi3d_CircularSpine
708 //purpose  : Calcule une ligne guide ciculaire pour le du coin a partir 
709 //           des points et vecteurs tangents calcules aux extremites des
710 //           lignes guides des conges deb et fin.
711 //=======================================================================
712 Handle(Geom_Circle) ChFi3d_CircularSpine(Standard_Real&      WFirst,
713                                          Standard_Real&      WLast,
714                                          const gp_Pnt&       Pdeb,
715                                          const gp_Vec&       Vdeb,
716                                          const gp_Pnt&       Pfin,
717                                          const gp_Vec&       Vfin,
718                                          const Standard_Real rad)
719 {
720   gp_Circ ccc;
721   gp_Pln Pl1(Pdeb,gp_Dir(Vdeb)),Pl2(Pfin,gp_Dir(Vfin));
722   IntAna_QuadQuadGeo LInt (Pl1,Pl2,Precision::Angular(),
723                            Precision::Confusion());
724   gp_Lin li;
725   if (LInt.IsDone()) {
726     li = LInt.Line(1);
727     gp_Pnt cendeb = ElCLib::Value(ElCLib::Parameter(li,Pdeb),li);
728     gp_Pnt cenfin = ElCLib::Value(ElCLib::Parameter(li,Pfin),li);
729     gp_Vec vvdeb(cendeb,Pdeb);
730     gp_Vec vvfin(cenfin,Pfin);
731     gp_Dir dddeb(vvdeb);
732     gp_Dir ddfin(vvfin);
733     if(Vdeb.Crossed(vvdeb).Dot(Vfin.Crossed(vvfin)) > 0.) {
734       return Handle(Geom_Circle)();
735     }
736     gp_Ax2 circax2(cendeb,dddeb^ddfin,dddeb);
737     ccc.SetPosition(circax2);
738     ccc.SetRadius(rad);
739     WFirst = 0.;
740     WLast = dddeb.Angle(ddfin);
741     return new Geom_Circle(ccc);
742   }
743
744   return Handle(Geom_Circle)();
745 }
746 //=======================================================================
747 //function : ChFi3d_Spine
748 //purpose  : Calcule les poles de la ligne guide du coin a partir des
749 //           points et vecteurs tangents calcules aux extremites des
750 //           lignes guides des conges deb et fin.
751 //=======================================================================
752 Handle(Geom_BezierCurve) ChFi3d_Spine(const gp_Pnt&       pd,
753                                       gp_Vec&             vd,
754                                       const gp_Pnt&       pf,
755                                       gp_Vec&             vf,
756                                       const Standard_Real R)
757 {     
758   TColgp_Array1OfPnt pol(1,4);
759   const Standard_Real fac = 0.5 * tan((PI-vd.Angle(vf)) * 0.5);
760   pol(1) = pd;
761   vd.Multiply(fac*R);
762   pol(2).SetCoord(pd.X()+vd.X(),pd.Y()+vd.Y(),pd.Z()+vd.Z());
763   pol(4) = pf;
764   vf.Multiply(fac*R);
765   pol(3).SetCoord(pf.X()+vf.X(),pf.Y()+vf.Y(),pf.Z()+vf.Z());
766   return new Geom_BezierCurve(pol);
767 }
768 //=======================================================================
769 //function : IsInFront
770 //purpose  : regarde si les surfdata i1 et i2 sont en vis a vis
771 //=======================================================================
772 Standard_Boolean ChFi3d_IsInFront(TopOpeBRepDS_DataStructure& DStr,
773                                   const Handle(ChFiDS_Stripe)& cd1, 
774                                   const Handle(ChFiDS_Stripe)& cd2,
775                                   const Standard_Integer i1,
776                                   const Standard_Integer i2,
777                                   const Standard_Integer sens1,
778                                   const Standard_Integer sens2,
779                                   Standard_Real& p1,
780                                   Standard_Real& p2,
781                                   TopoDS_Face& face,
782                                   Standard_Boolean& sameside,
783                                   Standard_Integer& jf1,
784                                   Standard_Integer& jf2,
785                                   Standard_Boolean& visavis,
786                                   const TopoDS_Vertex& Vtx,
787                                   const Standard_Boolean Check2dDistance,
788                                   const Standard_Boolean enlarge)
789 {
790   Standard_Boolean isf1 = (sens1 == 1), isf2 = (sens2 == 1);
791   const Handle(ChFiDS_SurfData)& fd1 = cd1->SetOfSurfData()->Value(i1);
792   const Handle(ChFiDS_SurfData)& fd2 = cd2->SetOfSurfData()->Value(i2);
793
794   TopAbs_Orientation Or,OrSave1,OrSave2,OrFace1,OrFace2;
795   visavis = Standard_False;
796   Standard_Real u1 = 0.,u2 = 0.; 
797   Standard_Boolean ss = 0,ok = 0;
798   Standard_Integer j1 = 0,j2 = 0;
799   TopoDS_Face ff;
800   if(fd1->IndexOfS1() == fd2->IndexOfS1()) { 
801     jf1 = 1; jf2 = 1; 
802     face = TopoDS::Face(DStr.Shape(fd1->Index(jf1)));
803     OrSave1 = cd1->Orientation(jf1);
804     Or = OrFace1 = face.Orientation();
805     OrSave2 = cd2->Orientation(jf2);
806     OrFace2 = DStr.Shape(fd2->Index(jf2)).Orientation();
807     visavis = Standard_True;
808     sameside = ChFi3d::SameSide(Or,OrSave1,OrSave2,OrFace1,OrFace2);
809     // On ne detrompe plus a l'aide des parametres de l'autre cote ca posait des problemes.
810     Standard_Integer kf1 = jf1, kf2 = jf2;
811     Standard_Real pref1 = fd1->Interference(kf1).Parameter(isf1);
812     Standard_Real pref2 = fd2->Interference(kf2).Parameter(isf2);
813     gp_Pnt2d P2d;
814     if (Check2dDistance)
815       P2d = BRep_Tool::Parameters( Vtx, face );
816     if(ChFi3d_IntTraces(fd1,pref1,p1,jf1,sens1,fd2,pref2,p2,jf2,sens2,P2d,Check2dDistance,enlarge)) {
817       u1 = p1; u2 = p2; ss = sameside; j1 = jf1; j2 = jf2; ff = face;
818       ok = 1;
819     }
820   }
821   if(fd1->IndexOfS2() == fd2->IndexOfS1()) { 
822     jf1 = 2; jf2 = 1; 
823     face = TopoDS::Face(DStr.Shape(fd1->Index(jf1)));
824     OrSave1 = cd1->Orientation(jf1);
825     Or = OrFace1 = face.Orientation();
826     OrSave2 = cd2->Orientation(jf2);
827     OrFace2 = DStr.Shape(fd2->Index(jf2)).Orientation();
828     visavis = Standard_True;
829     sameside = ChFi3d::SameSide(Or,OrSave1,OrSave2,OrFace1,OrFace2);
830     // On ne detrompe plus a l'aide des parametres de l'autre cote ca posait des problemes.
831     Standard_Integer kf1 = jf1, kf2 = jf2;
832     Standard_Real pref1 = fd1->Interference(kf1).Parameter(isf1);
833     Standard_Real pref2 = fd2->Interference(kf2).Parameter(isf2);
834     gp_Pnt2d P2d;
835     if (Check2dDistance)
836       P2d = BRep_Tool::Parameters( Vtx, face );
837     if(ChFi3d_IntTraces(fd1,pref1,p1,jf1,sens1,fd2,pref2,p2,jf2,sens2,P2d,Check2dDistance,enlarge)) {
838       Standard_Boolean restore = 
839         ok && ((j1 == jf1 && sens1*(p1 - u1) > 0.) || 
840                (j2 == jf2 && sens2*(p2 - u2) > 0.));
841       ok = 1;
842       if(restore) {
843         p1 = u1; p2 = u2; sameside = ss; jf1 = j1; jf2 = j2; face = ff;
844       }
845       else {
846         u1 = p1; u2 = p2; ss = sameside; j1 = jf1; j2 = jf2; ff = face;
847       }
848     }
849     //on rajoute ces re-initialisations au cas ou p1,... auraient pris des valeurs fausses
850     else if (ok) {
851       p1 = u1; p2 = u2; sameside = ss; jf1 = j1; jf2 = j2; face = ff;
852     }
853   }
854   if(fd1->IndexOfS1() == fd2->IndexOfS2()) { 
855     jf1 = 1; jf2 = 2; 
856     face = TopoDS::Face(DStr.Shape(fd1->Index(jf1)));
857     OrSave1 = cd1->Orientation(jf1);
858     Or = OrFace1 = face.Orientation();
859     OrSave2 = cd2->Orientation(jf2);
860     OrFace2 = DStr.Shape(fd2->Index(jf2)).Orientation();
861     visavis = Standard_True;
862     sameside = ChFi3d::SameSide(Or,OrSave1,OrSave2,OrFace1,OrFace2);
863     // On ne detrompe plus a l'aide des parametres de l'autre cote.
864     Standard_Integer kf1 = jf1, kf2 = jf2;
865     Standard_Real pref1 = fd1->Interference(kf1).Parameter(isf1);
866     Standard_Real pref2 = fd2->Interference(kf2).Parameter(isf2);
867     gp_Pnt2d P2d;
868     if (Check2dDistance)
869       P2d = BRep_Tool::Parameters( Vtx, face );
870     if(ChFi3d_IntTraces(fd1,pref1,p1,jf1,sens1,fd2,pref2,p2,jf2,sens2,P2d,Check2dDistance,enlarge)) {
871       Standard_Boolean restore = 
872         ok && ((j1 == jf1 && sens1*(p1 - u1) > 0.) || 
873                (j2 == jf2 && sens2*(p2 - u2) > 0.));
874       ok = 1;
875       if(restore) {
876         p1 = u1; p2 = u2; sameside = ss; jf1 = j1; jf2 = j2; face = ff;
877       }
878       else {
879         u1 = p1; u2 = p2; ss = sameside; j1 = jf1; j2 = jf2; ff = face;
880       }
881     }
882     //on rajoute ces re-initialisations au cas ou p1,... auraient pris des valeurs fausses
883     else if (ok) {
884       p1 = u1; p2 = u2; sameside = ss; jf1 = j1; jf2 = j2; face = ff;
885     }
886   }
887   if(fd1->IndexOfS2() == fd2->IndexOfS2()) { 
888     jf1 = 2; jf2 = 2; 
889     face = TopoDS::Face(DStr.Shape(fd1->Index(jf1)));
890     OrSave1 = cd1->Orientation(jf1);
891     Or = OrFace1 = face.Orientation();
892     OrSave2 = cd2->Orientation(jf2);
893     OrFace2 = DStr.Shape(fd2->Index(jf2)).Orientation();
894     visavis = Standard_True;
895     sameside = ChFi3d::SameSide(Or,OrSave1,OrSave2,OrFace1,OrFace2);
896     // On ne detrompe plus a l'aide des parametres de l'autre cote.
897     Standard_Integer kf1 = jf1, kf2 = jf2;
898     Standard_Real pref1 = fd1->Interference(kf1).Parameter(isf1);
899     Standard_Real pref2 = fd2->Interference(kf2).Parameter(isf2);
900     gp_Pnt2d P2d;
901     if (Check2dDistance)
902       P2d = BRep_Tool::Parameters( Vtx, face );
903     if(ChFi3d_IntTraces(fd1,pref1,p1,jf1,sens1,fd2,pref2,p2,jf2,sens2,P2d,Check2dDistance,enlarge)) {
904       Standard_Boolean restore = 
905         ok && ((j1 == jf1 && sens1*(p1 - u1) > 0.) || 
906                (j2 == jf2 && sens2*(p2 - u2) > 0.));
907       ok = 1;
908       if(restore) {
909         p1 = u1; p2 = u2; sameside = ss; jf1 = j1; jf2 = j2; face = ff;
910       }
911       else {
912         u1 = p1; u2 = p2; ss = sameside; j1 = jf1; j2 = jf2; ff = face;
913       }
914     }
915     //on rajoute ces re-initialisations au cas ou p1,... auraient pris des valeurs fausses
916     else if (ok) {
917       p1 = u1; p2 = u2; sameside = ss; jf1 = j1; jf2 = j2; face = ff;
918     }
919   }
920   return ok;
921 }
922 //=======================================================================
923 //function : recadre
924 //purpose  : 
925 //=======================================================================
926 static Standard_Real recadre(const Standard_Real p,
927                              const Standard_Real ref,
928                              const Standard_Integer sens,
929                              const Standard_Real first,
930                              const Standard_Real last)
931 {
932   const Standard_Real pp = p + (sens > 0 ? (first - last) : (last - first));
933   return ((Abs(pp - ref) < Abs(p - ref))? pp : p);
934 }
935 //=======================================================================
936 //function : ChFi3d_IntTraces
937 //purpose  : 
938 //=======================================================================
939 Standard_Boolean ChFi3d_IntTraces(const Handle(ChFiDS_SurfData)& fd1,
940                                   const Standard_Real            pref1,
941                                   Standard_Real&                 p1,
942                                   const Standard_Integer         jf1,
943                                   const Standard_Integer         sens1,
944                                   const Handle(ChFiDS_SurfData)& fd2,
945                                   const Standard_Real            pref2,
946                                   Standard_Real&                 p2,
947                                   const Standard_Integer         jf2,
948                                   const Standard_Integer         sens2,
949                                   const gp_Pnt2d&                RefP2d,
950                                   const Standard_Boolean         Check2dDistance,
951                                   const Standard_Boolean         enlarge)
952 {
953   Geom2dAdaptor_Curve C1;
954   Geom2dAdaptor_Curve C2;
955   // on aggrandit les pcurves pour etre sur qu'il y a intersection
956   // par ailleurs on prend la totalite des courbes periodiques, on
957   // triera les points sur celles-ci avec un critere specifique.
958
959   Standard_Real first,last,delta = 0.;
960   first = fd1->Interference(jf1).FirstParameter();
961   last = fd1->Interference(jf1).LastParameter();
962   if ((last-first) < Precision::PConfusion())
963     return Standard_False;
964   if(enlarge) delta = Min(0.1,0.05*(last-first));
965   Handle(Geom2d_Curve) pcf1 = fd1->Interference(jf1).PCurveOnFace();
966   if(pcf1.IsNull()) return Standard_False;
967   Standard_Boolean isper1 = pcf1->IsPeriodic();
968   if(isper1) {
969     Handle(Geom2d_TrimmedCurve) tr1 = Handle(Geom2d_TrimmedCurve)::DownCast(pcf1);
970     if(!tr1.IsNull()) pcf1 = tr1->BasisCurve();
971     C1.Load(pcf1);
972   }
973   else C1.Load(pcf1,first-delta,last+delta);
974   Standard_Real first1 = pcf1->FirstParameter(), last1 = pcf1->LastParameter();
975   
976   first = fd2->Interference(jf2).FirstParameter();
977   last = fd2->Interference(jf2).LastParameter();
978   if ((last-first) < Precision::PConfusion())
979     return Standard_False;
980   if(enlarge) delta = Min(0.1,0.05*(last-first));
981   Handle(Geom2d_Curve) pcf2 = fd2->Interference(jf2).PCurveOnFace();
982   if(pcf2.IsNull()) return Standard_False;
983   Standard_Boolean isper2 = pcf2->IsPeriodic();
984   if(isper2) {
985     Handle(Geom2d_TrimmedCurve) tr2 = Handle(Geom2d_TrimmedCurve)::DownCast(pcf2);
986     if(!tr2.IsNull()) pcf2 = tr2->BasisCurve();
987     C2.Load(pcf2);
988   }
989   else C2.Load(fd2->Interference(jf2).PCurveOnFace(),first-delta,last+delta);
990   Standard_Real first2 = pcf2->FirstParameter(), last2 = pcf2->LastParameter();
991     
992   IntRes2d_IntersectionPoint int2d;
993   Geom2dInt_GInter Intersection;
994   Standard_Integer nbpt,nbseg;
995   gp_Pnt2d p2d;
996   if(fd1->Interference(jf1).PCurveOnFace() == fd2->Interference(jf2).PCurveOnFace()) {
997     Intersection.Perform(C1,
998                          Precision::PIntersection(),
999                          Precision::PIntersection());
1000   }
1001   else{
1002     Intersection.Perform(C1,C2,
1003                          Precision::PIntersection(),
1004                          Precision::PIntersection());
1005   }
1006   if (Intersection.IsDone()) {
1007     if (!Intersection.IsEmpty()) {
1008       nbseg = Intersection.NbSegments();
1009       if ( nbseg > 0 ) { 
1010       }
1011       nbpt = Intersection.NbPoints();
1012       if ( nbpt >= 1 ) {
1013         // On manque de billes pour trier les points trouves de facon
1014         // rigoureuse. On adopte donc deux criteres differents un peu
1015         // arbitraires :
1016         // - courbes periodiques : le plus proche de la borne.
1017         // - courbes non periodiques : le plus a gauche sur les 2 courbes
1018         //                             modulo sens1 et sens2
1019         int2d = Intersection.Point(1);
1020         p2d = int2d.Value();
1021         p1 = int2d.ParamOnFirst();
1022         p2 = int2d.ParamOnSecond();
1023         if(isper1) p1 = recadre(p1,pref1,sens1,first1,last1);
1024         if(isper2) p2 = recadre(p2,pref2,sens2,first2,last2);
1025         for(Standard_Integer i = 2; i<=nbpt; i++) {
1026           int2d = Intersection.Point(i);
1027           if(isper1) {
1028             Standard_Real pp1 = int2d.ParamOnFirst();
1029             pp1 = recadre(pp1,pref1,sens1,first1,last1);
1030             if((Abs(pp1 - pref1) < Abs(p1 - pref1))) {
1031               p1 = pp1;
1032               p2 = int2d.ParamOnSecond();
1033               p2d = int2d.Value();
1034             }
1035             //  Modified by skv - Mon Jun 16 15:51:21 2003 OCC615 Begin
1036             else if (Check2dDistance &&
1037                      RefP2d.Distance(int2d.Value()) < RefP2d.Distance(p2d)) {
1038               Standard_Real pp2 = int2d.ParamOnSecond();
1039
1040               if(isper2)
1041                 pp2 = recadre(pp2,pref2,sens2,first2,last2);
1042
1043               p1  = pp1;
1044               p2  = pp2;
1045               p2d = int2d.Value();
1046             }
1047             //  Modified by skv - Mon Jun 16 15:51:22 2003 OCC615 End
1048           }
1049           else if(isper2) {
1050             Standard_Real pp2 = int2d.ParamOnSecond();
1051             pp2 = recadre(pp2,pref2,sens2,first2,last2);
1052             if((Abs(pp2 - pref2) < Abs(p2 - pref2))) {
1053               p2 = pp2;
1054               p1 = int2d.ParamOnFirst();
1055               p2d = int2d.Value();
1056             }
1057             //  Modified by skv - Mon Jun 16 15:51:21 2003 OCC615 Begin
1058             else if (Check2dDistance &&
1059                      RefP2d.Distance(int2d.Value()) < RefP2d.Distance(p2d)) {
1060               Standard_Real pp1 = int2d.ParamOnFirst();
1061
1062               if(isper1)
1063                 pp1 = recadre(pp1,pref1,sens1,first1,last1);
1064
1065               p1  = pp1;
1066               p2  = pp2;
1067               p2d = int2d.Value();
1068             }
1069             //  Modified by skv - Mon Jun 16 15:51:22 2003 OCC615 End
1070           }
1071           else if(((int2d.ParamOnFirst() - p1)*sens1 < 0.) &&
1072                   ((int2d.ParamOnSecond() - p2)*sens2 < 0.)) {
1073             p1 = int2d.ParamOnFirst();
1074             p2 = int2d.ParamOnSecond();
1075             p2d = int2d.Value();
1076           }
1077           else if((Abs(int2d.ParamOnFirst() - pref1) < Abs(p1 - pref1)) &&
1078                   (Abs(int2d.ParamOnSecond() - pref2) < Abs(p2 - pref2))) {
1079             p1 = int2d.ParamOnFirst();
1080             p2 = int2d.ParamOnSecond();
1081             p2d = int2d.Value();
1082           }
1083           else if (Check2dDistance && RefP2d.Distance(int2d.Value()) < RefP2d.Distance(p2d))
1084             {
1085               p1 = int2d.ParamOnFirst();
1086               p2 = int2d.ParamOnSecond();
1087               p2d = int2d.Value();
1088             }
1089         }
1090         return Standard_True; 
1091       }
1092       return Standard_False; 
1093     }
1094     else { return Standard_False; }
1095   }
1096   else { return Standard_False; }
1097
1098 //=======================================================================
1099 //function : Coefficient
1100 //purpose  : 
1101 //=======================================================================
1102 void ChFi3d_Coefficient(const gp_Vec& V3d,
1103                         const gp_Vec& D1u,
1104                         const gp_Vec& D1v,
1105                         Standard_Real& DU,
1106                         Standard_Real& DV) 
1107 {
1108   const Standard_Real AA = D1u.SquareMagnitude();
1109   const Standard_Real BB = D1u.Dot(D1v);
1110   const Standard_Real CC = D1v.SquareMagnitude();
1111   const Standard_Real DD = D1u.Dot(V3d);
1112   const Standard_Real EE = D1v.Dot(V3d);
1113   const Standard_Real Delta = AA*CC-BB*BB;
1114   DU = (DD*CC-EE*BB)/Delta;
1115   DV = (AA*EE-BB*DD)/Delta;
1116 }
1117 //=======================================================================
1118 //function : ReparamPcurv
1119 //purpose  : Dans le cas ou la pcurve est une BSpline on verifie 
1120 //           ses parametres et on la reparametre eventuellement.
1121 //=======================================================================
1122 void ChFi3d_ReparamPcurv(const Standard_Real Uf, 
1123                          const Standard_Real Ul, 
1124                          Handle(Geom2d_Curve)& Pcurv) 
1125 {
1126   if(Pcurv.IsNull()) return;
1127   Standard_Real upcf = Pcurv->FirstParameter();
1128   Standard_Real upcl = Pcurv->LastParameter();
1129   Handle(Geom2d_Curve) basis = Pcurv;
1130   Handle(Geom2d_TrimmedCurve) trpc = Handle(Geom2d_TrimmedCurve)::DownCast(Pcurv);
1131   if(!trpc.IsNull()) basis = trpc->BasisCurve();
1132   Handle(Geom2d_BSplineCurve) pc = Handle(Geom2d_BSplineCurve)::DownCast(basis);
1133   if(pc.IsNull()) return;
1134   if(Abs(upcf - pc->FirstParameter()) > Precision::PConfusion() ||
1135      Abs(upcl - pc->LastParameter()) > Precision::PConfusion()) {
1136     pc->Segment(upcf,upcl);
1137   }
1138   if(Abs(Uf - pc->FirstParameter()) > Precision::PConfusion() ||
1139      Abs(Ul - pc->LastParameter()) > Precision::PConfusion()) {
1140     TColgp_Array1OfPnt2d pol(1,pc->NbPoles());
1141     pc->Poles(pol);
1142     TColStd_Array1OfReal kn(1,pc->NbKnots());
1143     pc->Knots(kn);
1144     TColStd_Array1OfInteger mu(1,pc->NbKnots());
1145     pc->Multiplicities(mu);
1146     Standard_Integer deg = pc->Degree();
1147     BSplCLib::Reparametrize(Uf,Ul,kn);
1148     pc = new Geom2d_BSplineCurve(pol,kn,mu,deg);
1149   }
1150   Pcurv = pc;
1151 }
1152 //=======================================================================
1153 //function : ProjectPCurv
1154 //purpose  : Calcul la pcurve correspondant a une ligne d intersection
1155 //           3d. Ne doit etre appele que dans les cas analytiques.
1156 //=======================================================================
1157 void ChFi3d_ProjectPCurv(const Handle(Adaptor3d_HCurve)&   HCg, 
1158                          const Handle(Adaptor3d_HSurface)& HSg, 
1159                          Handle(Geom2d_Curve)&           Pcurv,
1160                          const Standard_Real             tol,
1161                          Standard_Real&                  tolreached) 
1162 {
1163   if (HSg->GetType() != GeomAbs_BezierSurface &&
1164       HSg->GetType() != GeomAbs_BSplineSurface) {
1165     
1166     ProjLib_ProjectedCurve Projc (HSg,HCg,tol);
1167     tolreached = Projc.GetTolerance();
1168     switch (Projc.GetType()) {
1169     case GeomAbs_Line : 
1170       {
1171         Pcurv = new Geom2d_Line(Projc.Line());
1172       }
1173       break;
1174     case GeomAbs_Circle :
1175       {
1176         Pcurv = new Geom2d_Circle(Projc.Circle());
1177       }
1178       break;
1179     case GeomAbs_Ellipse :
1180       {
1181         Pcurv = new Geom2d_Ellipse(Projc.Ellipse());
1182       }
1183       break;
1184     case GeomAbs_Hyperbola :
1185       {
1186         Pcurv = new Geom2d_Hyperbola(Projc.Hyperbola());
1187       }
1188       break;
1189     case GeomAbs_Parabola :
1190       {
1191         Pcurv = new Geom2d_Parabola(Projc.Parabola());
1192       }
1193       break;
1194     case GeomAbs_BezierCurve :
1195       {
1196         Pcurv = Projc.Bezier(); 
1197       }
1198       break;
1199     case GeomAbs_BSplineCurve :
1200       {
1201         Pcurv = Projc.BSpline();
1202       }
1203       break;
1204     default:
1205       Standard_NotImplemented::Raise("echec approximation de la pcurve ");
1206     }
1207   }
1208 }
1209 //=======================================================================
1210 //function : CheckSameParameter
1211 //purpose  : Controle a posteriori que sameparameter a bien fait son boulot
1212 //=======================================================================
1213 Standard_Boolean ChFi3d_CheckSameParameter (const Handle(Adaptor3d_HCurve)&   C3d,
1214                                             Handle(Geom2d_Curve)&           Pcurv,
1215                                             const Handle(Adaptor3d_HSurface)& S,
1216                                             const Standard_Real             tol3d,
1217                                             Standard_Real&                  tolreached)
1218 {
1219   tolreached = 0.;
1220   Standard_Real f = C3d->FirstParameter();
1221   Standard_Real l = C3d->LastParameter();
1222   Standard_Integer nbp = 45;
1223   Standard_Real step = 1./(nbp -1);
1224   for(Standard_Integer i = 0; i < nbp; i++) {
1225     Standard_Real t,u,v;
1226     t = step * i;
1227     t = (1-t) * f + t * l;
1228     Pcurv->Value(t).Coord(u,v);
1229     gp_Pnt pS = S->Value(u,v);
1230     gp_Pnt pC = C3d->Value(t);
1231     Standard_Real d2 = pS.SquareDistance(pC);
1232     tolreached = Max(tolreached,d2);
1233   }
1234   tolreached = sqrt(tolreached);
1235   if(tolreached > tol3d) {
1236     tolreached *= 2.;
1237     return Standard_False;
1238   }
1239   tolreached *= 2.;
1240   tolreached = Max(tolreached,Precision::Confusion());
1241   return Standard_True;
1242 }
1243 //=======================================================================
1244 //function : SameParameter
1245 //purpose  : Encapsulation de Sameparameter
1246 //=======================================================================
1247 Standard_Boolean ChFi3d_SameParameter(const Handle(Adaptor3d_HCurve)&   C3d,
1248                                       Handle(Geom2d_Curve)&           Pcurv,
1249                                       const Handle(Adaptor3d_HSurface)& S,
1250                                       const Standard_Real             tol3d,
1251                                       Standard_Real&                  tolreached)
1252 {
1253   if(ChFi3d_CheckSameParameter(C3d,Pcurv,S,tol3d,tolreached)) return Standard_True;
1254   Approx_SameParameter sp(C3d,Pcurv,S,tol3d);
1255   if(sp.IsDone() && !sp.IsSameParameter()) Pcurv = sp.Curve2d();
1256   else if(!sp.IsDone() && !sp.IsSameParameter()) {
1257     return Standard_False;
1258   }
1259   tolreached = sp.TolReached();
1260   return Standard_True;
1261 }
1262 //=======================================================================
1263 //function : SameParameter
1264 //purpose  : Encapsulation de Sameparameter
1265 //=======================================================================
1266 Standard_Boolean ChFi3d_SameParameter(const Handle(Geom_Curve)&   C3d,
1267                                       Handle(Geom2d_Curve)&       Pcurv,
1268                                       const Handle(Geom_Surface)& S,
1269                                       const Standard_Real         Pardeb,
1270                                       const Standard_Real         Parfin,
1271                                       const Standard_Real         tol3d,
1272                                       Standard_Real&              tolreached)
1273 {
1274   /*szv:static*/ Handle(GeomAdaptor_HSurface) hs(new GeomAdaptor_HSurface(S));
1275   /*szv:static*/ Handle(GeomAdaptor_HCurve) hc(new GeomAdaptor_HCurve(C3d,Pardeb,Parfin));
1276   return ChFi3d_SameParameter(hc,Pcurv,hs,tol3d,tolreached);
1277 }
1278 //=======================================================================
1279 //function : ComputePCurv 
1280 //purpose  : Calcule une droite eventuellement sous forme de BSpline 
1281 //           pour garantir le range et le parametrage identique
1282 //           a une courbe 3d de reference.
1283 //=======================================================================
1284 void ChFi3d_ComputePCurv(const Handle(Adaptor3d_HCurve)&   C3d,
1285                          const gp_Pnt2d&                 UV1,
1286                          const gp_Pnt2d&                 UV2,
1287                          Handle(Geom2d_Curve)&           Pcurv,
1288                          const Handle(Adaptor3d_HSurface)& S,
1289                          const Standard_Real             Pardeb,
1290                          const Standard_Real             Parfin,
1291                          const Standard_Real             tol3d,
1292                          Standard_Real&                  tolreached,
1293                          const Standard_Boolean          reverse)
1294 {
1295   ChFi3d_ComputePCurv(UV1,UV2,Pcurv,Pardeb,Parfin,reverse);
1296   ChFi3d_SameParameter(C3d,Pcurv,S,tol3d,tolreached);
1297 }
1298 //=======================================================================
1299 //function : ComputePCurv 
1300 //purpose  : Calcule une droite eventuellement sous forme de BSpline 
1301 //           pour garantir le range et le parametrage identique
1302 //           a une courbe 3d de reference.
1303 //=======================================================================
1304 void ChFi3d_ComputePCurv(const Handle(Geom_Curve)&   C3d,
1305                          const gp_Pnt2d&             UV1,
1306                          const gp_Pnt2d&             UV2,
1307                          Handle(Geom2d_Curve)&       Pcurv,
1308                          const Handle(Geom_Surface)& S,
1309                          const Standard_Real         Pardeb,
1310                          const Standard_Real         Parfin,
1311                          const Standard_Real         tol3d,
1312                          Standard_Real&              tolreached,
1313                          const Standard_Boolean      reverse)
1314 {
1315   /*szv:static*/ Handle(GeomAdaptor_HSurface) hs(new GeomAdaptor_HSurface(S));
1316   /*szv:static*/ Handle(GeomAdaptor_HCurve) hc(new GeomAdaptor_HCurve(C3d,Pardeb,Parfin));
1317   ChFi3d_ComputePCurv(hc,UV1,UV2,Pcurv,hs,Pardeb,Parfin,tol3d,tolreached,reverse);
1318 }
1319 //=======================================================================
1320 //function : ComputePCurv 
1321 //purpose  : Calcule une droite eventuellement sous forme de BSpline 
1322 //           pour garantir le range.
1323 //=======================================================================
1324 void ChFi3d_ComputePCurv(const gp_Pnt2d& UV1,
1325                          const gp_Pnt2d& UV2,
1326                          Handle(Geom2d_Curve)& Pcurv,
1327                          const Standard_Real Pardeb,
1328                          const Standard_Real Parfin,
1329                          const Standard_Boolean reverse)
1330 {
1331   const Standard_Real tol = Precision::PConfusion();
1332   gp_Pnt2d p1,p2;
1333   if (!reverse) {
1334     p1 = UV1;
1335     p2 = UV2;
1336   }
1337   else {
1338     p1 = UV2;
1339     p2 = UV1;
1340   }
1341   
1342   if (Abs(p1.X()-p2.X()) <= tol &&
1343       Abs((p2.Y()-p1.Y())-(Parfin-Pardeb)) <= tol) {
1344     gp_Pnt2d ppp(p1.X(),p1.Y()-Pardeb);
1345     Pcurv = new Geom2d_Line(ppp,gp::DY2d());
1346   }
1347   else if (Abs(p1.X()-p2.X()) <= tol &&
1348            Abs((p1.Y()-p2.Y())-(Parfin-Pardeb)) <= tol) {
1349     gp_Pnt2d ppp(p1.X(),p1.Y()+Pardeb);
1350     Pcurv = new Geom2d_Line(ppp,gp::DY2d().Reversed());
1351   }
1352   else if (Abs(p1.Y()-p2.Y()) <= tol &&
1353            Abs((p2.X()-p1.X())-(Parfin-Pardeb)) <= tol) {
1354     gp_Pnt2d ppp(p1.X()-Pardeb,p1.Y());
1355     Pcurv = new Geom2d_Line(ppp,gp::DX2d());
1356   }
1357   else if (Abs(p1.Y()-p2.Y()) <= tol &&
1358            Abs((p1.X()-p2.X())-(Parfin-Pardeb)) <= tol) {
1359     gp_Pnt2d ppp(p1.X()+Pardeb,p1.Y());
1360     Pcurv = new Geom2d_Line(ppp,gp::DX2d().Reversed());
1361   }
1362   else{
1363     TColgp_Array1OfPnt2d p(1,2);
1364     TColStd_Array1OfReal k(1,2);
1365     TColStd_Array1OfInteger m(1,2);
1366     m.Init(2);
1367     k(1) = Pardeb;
1368     k(2) = Parfin;
1369     p(1) = p1;
1370     p(2) = p2;
1371     Pcurv = new Geom2d_BSplineCurve(p,k,m,1);
1372   }
1373   Pcurv = new Geom2d_TrimmedCurve(Pcurv,Pardeb,Parfin);
1374 }
1375 //=======================================================================
1376 //function : ChFi3d_mkbound
1377 //purpose  : 
1378 //=======================================================================
1379 Handle(GeomFill_Boundary) ChFi3d_mkbound(const Handle(Adaptor3d_HSurface)& Fac,
1380                                          Handle(Geom2d_Curve)& curv, 
1381                                          const Standard_Integer sens1,
1382                                          const gp_Pnt2d& pfac1,
1383                                          const gp_Vec2d& vfac1,
1384                                          const Standard_Integer sens2,
1385                                          const gp_Pnt2d& pfac2,
1386                                          const gp_Vec2d& vfac2,
1387                                          const Standard_Real t3d,
1388                                          const Standard_Real ta)
1389 {
1390   gp_Dir2d v1(vfac1);
1391   if(sens1 == 1) v1.Reverse();
1392   gp_Dir2d v2(vfac2);
1393   if(sens2 == 1) v2.Reverse();
1394   curv = ChFi3d_BuildPCurve(Fac,pfac1,v1,pfac2,v2,Standard_False);
1395   return ChFi3d_mkbound(Fac,curv,t3d,ta);
1396 }
1397 //=======================================================================
1398 //function : ChFi3d_mkbound
1399 //purpose  : 
1400 //=======================================================================
1401 Handle(GeomFill_Boundary) ChFi3d_mkbound(const Handle(Adaptor3d_HSurface)& Surf,
1402                                          Handle(Geom2d_Curve)& curv,
1403                                          const Standard_Integer sens1,
1404                                          const gp_Pnt2d& p1,
1405                                          gp_Vec&   v1,
1406                                          const Standard_Integer sens2,
1407                                          const gp_Pnt2d& p2,
1408                                          gp_Vec& v2,
1409                                          const Standard_Real t3d,
1410                                          const Standard_Real ta)
1411 {
1412   if(sens1 == 1) v1.Reverse();
1413   if(sens2 == 1) v2.Reverse();
1414   curv = ChFi3d_BuildPCurve(Surf,p1,v1,p2,v2);
1415   return ChFi3d_mkbound(Surf,curv,t3d,ta);
1416 }
1417 //=======================================================================
1418 //function : ChFi3d_mkbound
1419 //purpose  : 
1420 //=======================================================================
1421 Handle(GeomFill_Boundary) ChFi3d_mkbound(const Handle(Geom_Surface)& s,
1422                                          const gp_Pnt2d& p1,
1423                                          const gp_Pnt2d& p2,
1424                                          const Standard_Real t3d,
1425                                          const Standard_Real ta,
1426                                          const Standard_Boolean isfreeboundary)
1427 {
1428   Handle(GeomAdaptor_HSurface) HS = new GeomAdaptor_HSurface(s);
1429   return ChFi3d_mkbound(HS,p1,p2,t3d,ta,isfreeboundary);
1430 }
1431 //=======================================================================
1432 //function : ChFi3d_mkbound
1433 //purpose  : 
1434 //=======================================================================
1435 Handle(GeomFill_Boundary) ChFi3d_mkbound(const Handle(Adaptor3d_HSurface)& HS,
1436                                          const gp_Pnt2d& p1,
1437                                          const gp_Pnt2d& p2,
1438                                          const Standard_Real t3d,
1439                                          const Standard_Real ta,
1440                                          const Standard_Boolean isfreeboundary)
1441 {
1442   TColgp_Array1OfPnt2d pol(1,2);
1443   pol(1)=p1;
1444   pol(2)=p2;
1445   Handle(Geom2d_Curve) curv = new Geom2d_BezierCurve(pol);
1446   return ChFi3d_mkbound(HS,curv,t3d,ta,isfreeboundary);
1447 }
1448 //=======================================================================
1449 //function : ChFi3d_mkbound
1450 //purpose  : 
1451 //=======================================================================
1452 Handle(GeomFill_Boundary) ChFi3d_mkbound(const Handle(Adaptor3d_HSurface)& HS,
1453                                          const Handle(Geom2d_Curve)& curv,
1454                                          const Standard_Real t3d,
1455                                          const Standard_Real ta,
1456                                          const Standard_Boolean isfreeboundary)
1457 {
1458   Handle(Geom2dAdaptor_HCurve) HC = new Geom2dAdaptor_HCurve(curv);
1459   Adaptor3d_CurveOnSurface COnS(HC,HS);
1460   if (isfreeboundary) {
1461     Handle(Adaptor3d_HCurveOnSurface) HCOnS = new Adaptor3d_HCurveOnSurface(COnS);
1462     return new GeomFill_SimpleBound(HCOnS,t3d,ta); 
1463   }
1464   return new GeomFill_BoundWithSurf(COnS,t3d,ta);
1465 }
1466 //=======================================================================
1467 //function : ChFi3d_mkbound
1468 //purpose  : 
1469 //=======================================================================
1470 Handle(GeomFill_Boundary) ChFi3d_mkbound(const Handle(Adaptor3d_HSurface)& Fac,
1471                                          Handle(Geom2d_Curve)& curv, 
1472                                          const gp_Pnt2d& p1,
1473                                          const gp_Pnt2d& p2,
1474                                          const Standard_Real t3d,
1475                                          const Standard_Real ta,
1476                                          const Standard_Boolean isfreeboundary)
1477 {
1478   TColgp_Array1OfPnt2d pol(1,2);
1479   pol(1)=p1;
1480   pol(2)=p2;
1481   curv = new Geom2d_BezierCurve(pol);
1482   return ChFi3d_mkbound(Fac,curv,t3d,ta,isfreeboundary);
1483 }
1484 //=======================================================================
1485 //function : ChFi3d_BuildPCurve
1486 //purpose  : 
1487 //=======================================================================
1488 Handle(Geom2d_Curve) ChFi3d_BuildPCurve(const gp_Pnt2d& p1,
1489                                         gp_Dir2d& d1,
1490                                         const gp_Pnt2d& p2,
1491                                         gp_Dir2d& d2,
1492                                         const Standard_Boolean redresse)
1493 {
1494   gp_Vec2d vref(p1,p2);
1495   gp_Dir2d dref(vref);
1496   Standard_Real mref = vref.Magnitude();
1497   if(redresse) {
1498     if(d1.Dot(dref) < 0.) d1.Reverse();
1499     if(d2.Dot(dref) > 0.) d2.Reverse();
1500   }
1501   //On fait une cubique a la mords moi le noeud
1502   TColgp_Array1OfPnt2d pol(1,4);
1503   pol(1)=p1;
1504   pol(4)=p2;
1505   Standard_Real Lambda1 = Max(Abs(d2.Dot(d1)),Abs(dref.Dot(d1)));
1506   Lambda1 = Max(0.5*mref*Lambda1,1.e-5);
1507   pol(2) = gp_Pnt2d(p1.XY()+Lambda1*d1.XY());
1508   Standard_Real Lambda2 = Max(Abs(d1.Dot(d2)),Abs(dref.Dot(d2)));
1509   Lambda2 = Max(0.5*mref*Lambda2,1.e-5);
1510   pol(3)=gp_Pnt2d(p2.XY()+Lambda2*d2.XY());
1511   return new Geom2d_BezierCurve(pol);
1512 }
1513 //=======================================================================
1514 //function : ChFi3d_BuildPCurve
1515 //purpose  : 
1516 //=======================================================================
1517 Handle(Geom2d_Curve) ChFi3d_BuildPCurve(const Handle(Adaptor3d_HSurface)& Surf,
1518                                         const gp_Pnt2d&                 p1,
1519                                         const gp_Vec2d&                 v1,
1520                                         const gp_Pnt2d&                 p2,
1521                                         const gp_Vec2d&                 v2,
1522                                         const Standard_Boolean          redresse)
1523 {
1524   gp_Pnt2d pp1 = p1, pp2 = p2;
1525   gp_Vec2d vv1 = v1, vv2 = v2;
1526   const Standard_Real ures = Surf->UResolution(1.);
1527   const Standard_Real vres = Surf->VResolution(1.);
1528   const Standard_Real invures = 1./ures;
1529   const Standard_Real invvres = 1./vres;
1530   pp1.SetX(invures*pp1.X()); pp1.SetY(invvres*pp1.Y()); 
1531   pp2.SetX(invures*pp2.X()); pp2.SetY(invvres*pp2.Y()); 
1532   vv1.SetX(invures*vv1.X()); vv1.SetY(invvres*vv1.Y()); 
1533   vv2.SetX(invures*vv2.X()); vv2.SetY(invvres*vv2.Y()); 
1534   gp_Dir2d d1(vv1), d2(vv2);
1535   Handle(Geom2d_Curve) g2dc = ChFi3d_BuildPCurve(pp1,d1,pp2,d2,redresse);
1536   Handle(Geom2d_BezierCurve) pc = Handle(Geom2d_BezierCurve)::DownCast(g2dc);
1537   const Standard_Integer nbp = pc->NbPoles();
1538   for(Standard_Integer ip = 1; ip <= nbp; ip++) {
1539     gp_Pnt2d pol = pc->Pole(ip);
1540     pol.SetX(ures*pol.X()); pol.SetY(vres*pol.Y());
1541     pc->SetPole(ip,pol);
1542   }
1543   return pc;
1544 }
1545 //=======================================================================
1546 //function : ChFi3d_BuildPCurve
1547 //purpose  : 
1548 //=======================================================================
1549 Handle(Geom2d_Curve) ChFi3d_BuildPCurve(const Handle(Adaptor3d_HSurface)& Surf,
1550                                         const gp_Pnt2d&                 p1,
1551                                         const gp_Vec&                   v1,
1552                                         const gp_Pnt2d&                 p2,
1553                                         const gp_Vec&                   v2,
1554                                         const Standard_Boolean          redresse)
1555 {
1556   gp_Vec D1u,D1v;
1557   gp_Pnt PP1,PP2;
1558   Standard_Real DU,DV;
1559   Surf->D1(p1.X(),p1.Y(),PP1,D1u,D1v);
1560   ChFi3d_Coefficient(v1,D1u,D1v,DU,DV);
1561   gp_Vec2d vv1(DU,DV);
1562   Surf->D1(p2.X(),p2.Y(),PP2,D1u,D1v);
1563   ChFi3d_Coefficient(v2,D1u,D1v,DU,DV);
1564   gp_Vec2d vv2(DU,DV);
1565   gp_Vec Vref(PP1,PP2);
1566   if(redresse) {
1567     if(Vref.Dot(v1) < 0.) vv1.Reverse();
1568     if(Vref.Dot(v2) > 0.) vv2.Reverse();
1569   }
1570   return ChFi3d_BuildPCurve(Surf,p1,vv1,p2,vv2,0);
1571 }
1572 //=======================================================================
1573 //function : ComputeArete
1574 //purpose  : 
1575 // pour les remplissages en s.d. un conge avec ces pcurves est construit ainsi
1576 // firstpoint sur S1 -------------edge:courbe3d/pcurves--->lastpoint sur S1
1577 //  |                                                              |
1578 //  |                                                              |
1579 //  |                                                              |
1580 // edge:courbe 3d/pcurves           conge                        edge
1581 //  |         attention il faut tester l orientation du conge avant|
1582 //  |         de determiner les transitions pcurves/conge          |
1583 //  |                                                              |
1584 //  \/                                                             \/
1585 // firstpoint sur S2 -------------edge:courbe3d/pcurves--->lastpoint sur S2
1586 //
1587 //=======================================================================
1588 void  ChFi3d_ComputeArete(const ChFiDS_CommonPoint&   P1,
1589                           const gp_Pnt2d&             UV1,
1590                           const ChFiDS_CommonPoint&   P2,
1591                           const gp_Pnt2d&             UV2,
1592                           const Handle(Geom_Surface)& Surf,
1593                           Handle(Geom_Curve)&         C3d,
1594                           Handle(Geom2d_Curve)&       Pcurv,
1595                           Standard_Real&              Pardeb,
1596                           Standard_Real&              Parfin,
1597                           const Standard_Real         tol3d,
1598                           const Standard_Real         tol2d,
1599                           Standard_Real&              tolreached,
1600                           const Standard_Integer      IFlag)
1601      // IFlag=0 pcurve et courbe 3d 
1602      // IFlag>0 pcurve (parametrage impose si IFlag=2)
1603 {
1604   /*szv:static*/ Handle(GeomAdaptor_HSurface) hs(new GeomAdaptor_HSurface());
1605   /*szv:static*/ Handle(GeomAdaptor_HCurve) hc(new GeomAdaptor_HCurve());
1606
1607   tolreached = tol3d;
1608
1609   if (Abs(UV1.X()-UV2.X()) <= tol2d) {
1610     if (IFlag == 0) {
1611       Pardeb = UV1.Y();
1612       Parfin = UV2.Y();
1613       C3d = Surf->UIso(UV1.X());
1614       if(Pardeb > Parfin) {
1615         Pardeb = C3d->ReversedParameter(Pardeb);
1616         Parfin = C3d->ReversedParameter(Parfin);
1617         C3d->Reverse();
1618       }
1619       Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C3d);
1620       if(!tc.IsNull()) {
1621         C3d = tc->BasisCurve();
1622         if (C3d->IsPeriodic()) {
1623           ElCLib::AdjustPeriodic(C3d->FirstParameter(),C3d->LastParameter(),
1624                                  tol2d,Pardeb,Parfin);
1625         }
1626       }
1627     }
1628     if(IFlag != 1) {
1629       hs->ChangeSurface().Load(Surf);
1630       hc->ChangeCurve().Load(C3d,Pardeb,Parfin);
1631       ChFi3d_ComputePCurv(hc,UV1,UV2,Pcurv,hs,Pardeb,Parfin,tol3d,tolreached,Standard_False);
1632     }
1633     else{
1634       Pcurv = new Geom2d_Line(UV1,gp_Vec2d(UV1,UV2));
1635     }
1636   }
1637   else if (Abs(UV1.Y()-UV2.Y())<=tol2d) {
1638     //iso v
1639     if (IFlag == 0) {
1640       Pardeb = UV1.X();
1641       Parfin = UV2.X();
1642       C3d = Surf->VIso(UV1.Y());
1643       if(Pardeb > Parfin) {
1644         Pardeb = C3d->ReversedParameter(Pardeb);
1645         Parfin = C3d->ReversedParameter(Parfin);
1646         C3d->Reverse();
1647       }
1648       Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C3d);
1649       if(!tc.IsNull()) {
1650         C3d = tc->BasisCurve();
1651         if (C3d->IsPeriodic()) {
1652           ElCLib::AdjustPeriodic(C3d->FirstParameter(),C3d->LastParameter(),
1653                                  tol2d,Pardeb,Parfin);
1654         }
1655       }
1656     }
1657     if(IFlag != 1) {
1658       hs->ChangeSurface().Load(Surf);
1659       hc->ChangeCurve().Load(C3d,Pardeb,Parfin);
1660       ChFi3d_ComputePCurv(hc,UV1,UV2,Pcurv,hs,Pardeb,Parfin,tol3d,tolreached,Standard_False);
1661     }
1662     else{
1663       Pcurv = new Geom2d_Line(UV1,gp_Vec2d(UV1,UV2));
1664     }
1665   }
1666   else if (IFlag == 0) {
1667
1668     if (P1.IsVertex() || P2.IsVertex() || !P1.IsOnArc() || !P2.IsOnArc()) {
1669     // On construit une droite pour ne pas se tromper 
1670     // d'arc et donc de tangente.
1671       TColgp_Array1OfPnt2d qoles(1,2);
1672       qoles(1)=UV1;
1673       qoles(2)=UV2;
1674       Pcurv = new Geom2d_BezierCurve(qoles);
1675     }
1676     else {
1677       BRepAdaptor_Curve C1(P1.Arc());
1678       gp_Pnt Pp;
1679       gp_Vec Vv1;
1680       C1.D1(P1.ParameterOnArc(),Pp,Vv1);
1681       C1.Initialize(P2.Arc());
1682       gp_Vec Vv2;
1683       C1.D1(P2.ParameterOnArc(),Pp,Vv2);
1684       hs->ChangeSurface().Load(Surf);
1685       Pcurv = ChFi3d_BuildPCurve(hs,UV1,Vv1,UV2,Vv2,Standard_True); 
1686       // Il y a des cas ou la PCurve ainsi construite sort de la 
1687       // surface, en particulier lorsque celle-ci provient d un 
1688       // prolongement. On fait donc un controle a posteriori et
1689       // si ca sort on la remplace par la droite UV1 UV2, tant
1690       // pis pour la tangence avec les arcs voisins!!!
1691       Bnd_Box2d bs;
1692       Standard_Real umin,umax,vmin,vmax;
1693       Surf->Bounds(umin,umax,vmin,vmax);
1694       bs.Update(umin,vmin,umax,vmax);
1695       Standard_Boolean aIN = Standard_True;
1696       for(Standard_Integer ii = 1; ii <= 4 && aIN; ii++) {
1697         if(bs.IsOut((*((Handle_Geom2d_BezierCurve*) &Pcurv))->Pole(ii))) {
1698           aIN = Standard_False;
1699           TColgp_Array1OfPnt2d qoles(1,2);
1700           qoles(1)=UV1;
1701           qoles(2)=UV2;
1702           Pcurv = new Geom2d_BezierCurve(qoles);
1703         }
1704       }
1705     }
1706     Geom2dAdaptor_Curve AC(Pcurv);
1707     Handle(Geom2dAdaptor_HCurve) AHC = 
1708       new Geom2dAdaptor_HCurve(AC);
1709     GeomAdaptor_Surface AS(Surf);
1710     Handle(GeomAdaptor_HSurface) AHS = 
1711       new GeomAdaptor_HSurface(AS);
1712     Adaptor3d_CurveOnSurface Cs(AHC,AHS);
1713     Pardeb = Cs.FirstParameter();
1714     Parfin = Cs.LastParameter();
1715     Standard_Real avtol;
1716     GeomLib::BuildCurve3d(tol3d,Cs,Pardeb,Parfin,C3d,tolreached,avtol);
1717   }
1718   else {
1719     hs->ChangeSurface().Load(Surf);
1720     hc->ChangeCurve().Load(C3d,Pardeb,Parfin);
1721     ChFi3d_ProjectPCurv(hc,hs,Pcurv,tol3d,tolreached);
1722     gp_Pnt2d p2d = Pcurv->Value(Pardeb);
1723     if(!UV1.IsEqual(p2d,Precision::PConfusion())) {
1724       gp_Vec2d v2d(p2d,UV1);
1725       Pcurv->Translate(v2d);
1726     }
1727   }
1728 }
1729 //=======================================================================
1730 //function : FilCurveInDS
1731 //purpose  : 
1732 //=======================================================================
1733 Handle(TopOpeBRepDS_SurfaceCurveInterference)  ChFi3d_FilCurveInDS
1734 (const Standard_Integer Icurv,
1735  const Standard_Integer Isurf,
1736  const Handle(Geom2d_Curve)& Pcurv,
1737  const TopAbs_Orientation Et)
1738 {
1739   Handle(TopOpeBRepDS_SurfaceCurveInterference) SC1;
1740   SC1 = new TopOpeBRepDS_SurfaceCurveInterference(TopOpeBRepDS_Transition(Et),
1741                                                   TopOpeBRepDS_SURFACE,
1742                                                   Isurf,TopOpeBRepDS_CURVE,Icurv,
1743                                                   Pcurv);
1744   return SC1;
1745 }
1746 //=======================================================================
1747 //function : TrsfTrans
1748 //purpose  : 
1749 //           
1750 //=======================================================================
1751 TopAbs_Orientation ChFi3d_TrsfTrans(const IntSurf_TypeTrans T1) 
1752 {
1753   switch (T1)  {
1754     case IntSurf_In:  return TopAbs_FORWARD;
1755     case IntSurf_Out: return TopAbs_REVERSED;
1756   }
1757   return TopAbs_INTERNAL;
1758 }
1759 //=======================================================================
1760 //function : FilCommonPoint
1761 //purpose  : Chargement du common point
1762 //           gestion du fait que l'on est deja sur un vertex existant
1763 //=======================================================================
1764 Standard_EXPORT void ChFi3d_FilCommonPoint(const BRepBlend_Extremity& SP,
1765                                            const IntSurf_TypeTrans TransLine,
1766                                            const Standard_Boolean Start,
1767                                            ChFiDS_CommonPoint& CP,
1768                                            const Standard_Real Tol)
1769 {
1770 //  BRep_Tool Outil;
1771   Standard_Real Dist, maxtol = Max(Tol,CP.Tolerance());
1772
1773   CP.SetPoint(SP.Value()); // On commence par le point, le vecteur
1774   if (SP.HasTangent()) {
1775     if (Start) {
1776       CP.SetVector(SP.Tangent().Reversed()); // On oriente la tangente vers la sortie
1777     }
1778     else {
1779       CP.SetVector(SP.Tangent());
1780     }
1781   }
1782   
1783   CP.SetParameter(SP.ParameterOnGuide()); //et le parametre de la spine
1784
1785   if (SP.IsVertex()) { // On charge le Vertex si besoin est
1786                        // (A l'interieur d'une face)
1787     TopoDS_Vertex V =  
1788       Handle(BRepTopAdaptor_HVertex)::DownCast(SP.Vertex())->Vertex();
1789   
1790     CP.SetVertex(V);  
1791     Dist = (SP.Value()).Distance(BRep_Tool::Pnt(V));
1792     //// modified by jgv, 18.09.02 for OCC571 ////
1793     //maxtol += Dist;
1794     maxtol = Max( Dist, maxtol );
1795     //////////////////////////////////////////////
1796     CP.SetPoint(BRep_Tool::Pnt(V));
1797     
1798     //la sequence d arcs l information est connu par le vertex (ancestor)
1799     //dans ce cas on ne calculera pas les transitions c est a ce programme
1800     //de le faire
1801   }
1802   
1803   if (SP.NbPointOnRst() != 0) { //  On charge un arc, et/ou un vertex
1804
1805     const BRepBlend_PointOnRst& PR = SP.PointOnRst(1);
1806     Handle(BRepAdaptor_HCurve2d) 
1807       Harc = Handle(BRepAdaptor_HCurve2d)::DownCast(PR.Arc());
1808     if(!Harc.IsNull()) {
1809
1810       Standard_Real DistF, DistL, LeParamAmoi;
1811       Standard_Integer Index_min;
1812       TopoDS_Edge E = Harc->ChangeCurve2d().Edge();
1813
1814       TopoDS_Vertex V[2];
1815       TopExp::Vertices(E, V[0], V[1]);
1816
1817       DistF = (SP.Value()).Distance(BRep_Tool::Pnt(V[0]));
1818       DistL = (SP.Value()).Distance(BRep_Tool::Pnt(V[1]));
1819       if (DistF<DistL) { Index_min = 0;
1820                          Dist = DistF; }
1821       else             { Index_min = 1;
1822                          Dist = DistL; }
1823
1824       if (Dist <= maxtol + BRep_Tool::Tolerance(V[Index_min]) ) { 
1825         // On tombe sur un vertex prexistant
1826          CP.SetVertex(V[Index_min]); //On Charge l'ancien vertex
1827          CP.SetPoint( BRep_Tool::Pnt(V[Index_min]) );
1828          maxtol = Max(BRep_Tool::Tolerance(V[Index_min]),maxtol);
1829          //// modified by jgv, 18.09.02 for OCC571 ////
1830          //maxtol += Dist;
1831          maxtol = Max( Dist, maxtol );
1832          //////////////////////////////////////////////
1833          LeParamAmoi = BRep_Tool::Parameter(V[Index_min], E);    
1834       }
1835       else {   // Creation d'un arc seul
1836         maxtol = Max(BRep_Tool::Tolerance(E),maxtol);
1837         maxtol = Max(SP.Tolerance(),maxtol);
1838         LeParamAmoi = PR.ParameterOnArc();
1839       }
1840
1841       // Definition de l'arc
1842       TopAbs_Orientation Tr;
1843       TopAbs_Orientation Or = E.Orientation();
1844       if (Start) {
1845         Tr = TopAbs::Reverse(TopAbs::Compose(ChFi3d_TrsfTrans(TransLine),Or));
1846       }
1847       else {
1848         Tr = TopAbs::Compose(ChFi3d_TrsfTrans(TransLine),Or);
1849       }
1850       CP.SetArc(maxtol, E, LeParamAmoi, Tr);
1851     }
1852   }
1853   CP.SetTolerance(maxtol); // On finit par la tolerance.
1854 }
1855
1856 //=======================================================================
1857 //function : SolidIndex
1858 //purpose  : 
1859 //=======================================================================
1860 Standard_Integer ChFi3d_SolidIndex(const Handle(ChFiDS_Spine)&  sp,
1861                                    TopOpeBRepDS_DataStructure&  DStr,
1862                                    ChFiDS_Map&                  MapESo,
1863                                    ChFiDS_Map&                  MapESh)
1864 {
1865   if(sp.IsNull() || sp->NbEdges() == 0) 
1866     Standard_Failure::Raise("SolidIndex : Spine incomplete");
1867   TopoDS_Shape edref= sp->Edges(1);
1868   TopoDS_Shape shellousolid;
1869   if(!MapESo(edref).IsEmpty()) shellousolid = MapESo(edref).First();
1870   else shellousolid = MapESh(edref).First();
1871   const Standard_Integer solidindex = DStr.AddShape(shellousolid);
1872   return solidindex;
1873 }
1874 //=======================================================================
1875 //function : IndexPointInDS
1876 //purpose  : 
1877 //=======================================================================
1878 Standard_Integer  ChFi3d_IndexPointInDS(const ChFiDS_CommonPoint& P1,
1879                                         TopOpeBRepDS_DataStructure& DStr) 
1880 {
1881   if (P1.IsVertex()) {
1882     // --------------------------------->  !*!*!* 
1883     // Attention : On se permet d'ecrabouiller la tolerance
1884     // il faudrait prevoir un mecanimse propre.
1885     BRep_Builder B;
1886     B.UpdateVertex(P1.Vertex(), P1.Point(), P1.Tolerance());
1887     return DStr.AddShape(P1.Vertex());
1888   }
1889   return DStr.AddPoint(TopOpeBRepDS_Point(P1.Point(),P1.Tolerance()));
1890 }
1891 //=======================================================================
1892 //function : FilPointInDS
1893 //purpose  : 
1894 //=======================================================================
1895 Handle(TopOpeBRepDS_CurvePointInterference) 
1896      ChFi3d_FilPointInDS(const TopAbs_Orientation Et,
1897                          const Standard_Integer Ic,
1898                          const Standard_Integer Ip,
1899                          const Standard_Real Par,
1900                          const Standard_Boolean IsVertex)
1901 {
1902   Handle(TopOpeBRepDS_CurvePointInterference) CP1;
1903   if (IsVertex)    
1904     CP1 = new TopOpeBRepDS_CurvePointInterference (TopOpeBRepDS_Transition(Et),
1905                                                    TopOpeBRepDS_CURVE,Ic,
1906                                                    TopOpeBRepDS_VERTEX,Ip,Par); 
1907   else
1908     CP1 = new TopOpeBRepDS_CurvePointInterference (TopOpeBRepDS_Transition(Et),
1909                                                    TopOpeBRepDS_CURVE,Ic,
1910                                                    TopOpeBRepDS_POINT,Ip,Par);
1911   return CP1;
1912 }
1913 //=======================================================================
1914 //function : FilVertexInDS
1915 //purpose  : 
1916 //=======================================================================
1917 Handle(TopOpeBRepDS_CurvePointInterference) 
1918      ChFi3d_FilVertexInDS(const TopAbs_Orientation Et,
1919                           const Standard_Integer Ic,
1920                           const Standard_Integer Ip,
1921                           const Standard_Real Par)
1922 {
1923   
1924   Handle(TopOpeBRepDS_CurvePointInterference) CP1 = new
1925     TopOpeBRepDS_CurvePointInterference (TopOpeBRepDS_Transition(Et),
1926                                          TopOpeBRepDS_CURVE,Ic,
1927                                          TopOpeBRepDS_VERTEX,Ip,Par);
1928   return CP1;
1929 }
1930 //=======================================================================
1931 //function : Orientation
1932 //purpose  : retourne l'orientation d'une interference (la premiere trouvee
1933 //           dans la liste).
1934 //=======================================================================
1935
1936 static Standard_Boolean
1937   ChFi3d_Orientation(const TopOpeBRepDS_ListOfInterference& LI,
1938                      const Standard_Integer                 igros,
1939                      const Standard_Integer                 ipetit,
1940                      TopAbs_Orientation&                    Or,
1941                      const Standard_Boolean                 isvertex = Standard_False,
1942                      const Standard_Boolean                 aprendre = Standard_False)
1943 {
1944   //Dans le cas, ou on veux inserer un point/vertex, on desire savoir
1945   // si c'est un point ou un vertex, car leur index peuvent etre les memes.
1946   TopOpeBRepDS_Kind typepetit;
1947   if (isvertex)
1948     typepetit =  TopOpeBRepDS_VERTEX;
1949   else
1950     typepetit =  TopOpeBRepDS_POINT;
1951   TopOpeBRepDS_ListIteratorOfListOfInterference itLI(LI);
1952   for (; itLI.More(); itLI.Next() ) {
1953     const Handle(TopOpeBRepDS_Interference)& cur = itLI.Value(); 
1954     TopOpeBRepDS_Kind GK;
1955     TopOpeBRepDS_Kind SK;
1956     Standard_Integer S;
1957     Standard_Integer G;
1958     cur->GKGSKS(GK,G,SK,S);
1959     if (aprendre) {
1960       if ( S == igros && G == ipetit && GK == typepetit) {
1961         Or = cur->Transition().Orientation(TopAbs_IN);
1962         return Standard_True;
1963       }
1964     }
1965     else  {
1966       if ( S == igros && G == ipetit) {
1967         Or = cur->Transition().Orientation(TopAbs_IN);
1968         return Standard_True;
1969       } 
1970     }
1971   }
1972   return Standard_False;
1973 }
1974
1975 //=======================================================================
1976 //function : Contains
1977 //purpose  : Verifie qu une interference n existe pas deja.
1978 //=======================================================================
1979 static Standard_Boolean 
1980   ChFi3d_Contains(const TopOpeBRepDS_ListOfInterference& LI,
1981                   const Standard_Integer                 igros,
1982                   const Standard_Integer                 ipetit,
1983                   const Standard_Boolean                 isvertex = Standard_False,
1984                   const Standard_Boolean                 aprendre = Standard_False)                             
1985 {
1986   TopAbs_Orientation bidOr;
1987   return ChFi3d_Orientation(LI,igros,ipetit,bidOr,isvertex,aprendre);
1988 }
1989 //=======================================================================
1990 //function : QueryAddVertexInEdge
1991 //purpose  : 
1992 //=======================================================================
1993 static void QueryAddVertexInEdge(TopOpeBRepDS_ListOfInterference& LI,
1994                                  const Standard_Integer                 IC,
1995                                  const Standard_Integer                 IV,
1996                                  const Standard_Real                    par,
1997                                  const TopAbs_Orientation               Or)
1998 {
1999   TopOpeBRepDS_ListIteratorOfListOfInterference it(LI);
2000   for (; it.More(); it.Next() ) {
2001     const Handle(TopOpeBRepDS_Interference)& cur = it.Value();
2002     const Handle(TopOpeBRepDS_CurvePointInterference)& cpi = 
2003       Handle(TopOpeBRepDS_CurvePointInterference)::DownCast(cur);
2004     if(!cpi.IsNull()) {
2005       Standard_Integer newIV = cpi->Geometry();
2006       TopOpeBRepDS_Kind kv = cpi->GeometryType();
2007       TopAbs_Orientation newOr = cpi->Transition().Orientation(TopAbs_IN);
2008       Standard_Real newpar = cpi->Parameter();
2009       if(IV == newIV && kv == TopOpeBRepDS_VERTEX && 
2010          Or == newOr && Abs(par - newpar) < 1.e-10) {
2011         return;
2012       }
2013     }
2014   }
2015   Handle(TopOpeBRepDS_CurvePointInterference) interf = 
2016     ChFi3d_FilVertexInDS(Or,IC,IV,par);
2017   LI.Append(interf);
2018 }
2019
2020 //=======================================================================
2021 //function : CutEdge
2022 //purpose  : 
2023 //=======================================================================
2024 static void CutEdge(const TopoDS_Vertex&           V,
2025                     const Handle(ChFiDS_SurfData)& SD,
2026                     TopOpeBRepDS_DataStructure&    DStr,
2027                     const Standard_Boolean         ,
2028                     const Standard_Integer         ons)
2029 {
2030   if(!SD->IsOnCurve(ons)) return;
2031   Standard_Integer IC = SD->IndexOfC(ons);
2032   Standard_Integer IV = DStr.AddShape(V);
2033   TopOpeBRepDS_ListOfInterference& LI = DStr.ChangeShapeInterferences(IC);
2034   TopoDS_Edge E = TopoDS::Edge(DStr.Shape(IC));
2035   E.Orientation(TopAbs_FORWARD);
2036   TopExp_Explorer ex;
2037
2038   // les traiter tous en verifiant que ce n est pas 
2039   // deja fait.
2040   for(ex.Init(E,TopAbs_VERTEX);ex.More();ex.Next()) {
2041     const TopoDS_Vertex& vv = TopoDS::Vertex(ex.Current());
2042     if(vv.IsSame(V)) {
2043       TopAbs_Orientation Or = TopAbs::Reverse(vv.Orientation());
2044       Standard_Real par = BRep_Tool::Parameter(vv,E);
2045       QueryAddVertexInEdge(LI,IC,IV,par,Or);
2046     }
2047   }
2048 }
2049 //=======================================================================
2050 //function : findIndexPoint
2051 //purpose  : returns in <ipon> index of point bounding a courve interfering
2052 //           with <Fd> and coinciding with last common point on <OnS> face
2053 //=======================================================================
2054 static Standard_Boolean 
2055   findIndexPoint(const TopOpeBRepDS_DataStructure& DStr,
2056                  const Handle(ChFiDS_SurfData)&    Fd,
2057                  const Standard_Integer            OnS,
2058                  Standard_Integer&                 ipoin)
2059 {
2060   ipoin = 0;
2061   gp_Pnt P = Fd->Vertex(Standard_False,OnS).Point();
2062
2063   TopOpeBRepDS_ListIteratorOfListOfInterference SCIIt, CPIIt;
2064   
2065   SCIIt.Initialize (DStr.SurfaceInterferences(Fd->Surf()));
2066   for (; SCIIt.More(); SCIIt.Next()) {
2067     Handle(TopOpeBRepDS_SurfaceCurveInterference) SCI =
2068       Handle(TopOpeBRepDS_SurfaceCurveInterference)::DownCast(SCIIt.Value());
2069     if (SCI.IsNull()) continue;
2070     CPIIt.Initialize (DStr.CurveInterferences(SCI->Geometry()));
2071     for (; CPIIt.More(); CPIIt.Next()) {
2072       Handle(TopOpeBRepDS_CurvePointInterference) CPI =
2073         Handle(TopOpeBRepDS_CurvePointInterference)::DownCast(CPIIt.Value());
2074       if (CPI.IsNull()) continue;
2075       Standard_Integer iPoint = CPI->Geometry();
2076       TopOpeBRepDS_Point tp = DStr.Point(iPoint);
2077       if (P.IsEqual(tp.Point(), tp.Tolerance())) {
2078         ipoin = iPoint;
2079         return Standard_True;
2080       }
2081     }
2082   }
2083   return Standard_False;
2084 }
2085 //=======================================================================
2086 //function : FilDS
2087 //purpose  : 
2088 //=======================================================================
2089 void  ChFi3d_FilDS(const Standard_Integer       SolidIndex,
2090                    const Handle(ChFiDS_Stripe)& CorDat,
2091                    TopOpeBRepDS_DataStructure&  DStr,
2092                    ChFiDS_Regularities&         reglist,
2093                    const Standard_Real          tol3d,
2094                    const Standard_Real          tol2d) 
2095 {
2096 //  BRep_Tool Outil;
2097   TopExp_Explorer ex;
2098   Handle(ChFiDS_Spine) spine = CorDat->Spine();
2099   Standard_Boolean Closed = Standard_False;
2100   Standard_Boolean Degene = 0, isVertex1 = 0, isVertex2 = 0, Singulier_en_Bout = 0;
2101   if(!spine.IsNull()) {
2102     Closed = spine->IsPeriodic();
2103   }
2104   const ChFiDS_SequenceOfSurfData& SeqFil = 
2105     CorDat->SetOfSurfData()->Sequence();
2106   Standard_Integer Ipoin1 = CorDat->IndexFirstPointOnS1();
2107   Standard_Integer Ipoin2 = CorDat->IndexFirstPointOnS2();
2108   Standard_Integer NumEdge = 1;
2109   TopoDS_Vertex BoutdeVtx; 
2110   Standard_Integer Icurv = 0;
2111   Standard_Integer Iarc1 = 0,Iarc2 = 0;
2112   TopAbs_Orientation trafil1 = TopAbs_FORWARD, trafil2 = TopAbs_FORWARD;
2113   Standard_Integer IcFil1,IcFil2,Isurf,Ishape1,Ishape2;
2114   Standard_Real Pardeb,Parfin;
2115   TopAbs_Orientation ET1;
2116   Handle(TopOpeBRepDS_CurvePointInterference) Interfp1,Interfp2;
2117   Handle(TopOpeBRepDS_SurfaceCurveInterference) Interfc1,Interfc2;
2118   Handle(TopOpeBRepDS_SurfaceCurveInterference) Interfc3,Interfc4;
2119   Handle(TopOpeBRepDS_CurvePointInterference) Interfp3,Interfp4;
2120   Handle(TopOpeBRepDS_CurvePointInterference) Interfp5,Interfp6;
2121   TopoDS_Face F;
2122   Handle(Geom2d_Curve) PCurv;
2123   TopOpeBRepDS_Curve Crv;
2124
2125   TopOpeBRepDS_ListOfInterference& SolidInterfs = 
2126     DStr.ChangeShapeInterferences(SolidIndex);
2127
2128   ChFiDS_Regul regcout; // pour les CD closed and tangent
2129   ChFiDS_Regul regfilfil; // pour les joints Surf/Surf
2130
2131   ChFiDS_CommonPoint V3;
2132   ChFiDS_CommonPoint V4;
2133
2134   // Nullify degenerated ChFi/Faces interferences, eap occ293
2135   Standard_Integer j;
2136   if (SeqFil.Length() > 1) {
2137     for (j=1; j<=SeqFil.Length(); j++) {
2138       Handle(ChFiDS_SurfData) Fd = SeqFil(j);
2139       Standard_Integer onS;
2140       for (onS=1; onS<=2; onS++) {
2141         const ChFiDS_FaceInterference& Fi = Fd->Interference(onS);
2142         IcFil1 = Fi.LineIndex();
2143         if (!IcFil1) continue;
2144         Standard_Real FiLen = Abs(Fi.FirstParameter()-Fi.LastParameter());
2145         if (FiLen > Precision::PConfusion()) continue;
2146         TopOpeBRepDS_Curve& cc = DStr.ChangeCurve(IcFil1);
2147         cc.ChangeCurve().Nullify();
2148
2149         // care of CommonPoint, eap occ354
2150         if (j!=1 && j!=SeqFil.Length()) continue;
2151         Standard_Boolean isfirst = (j==1);
2152         Standard_Integer i = isfirst ? j+1 : j-1;
2153         ChFiDS_CommonPoint& CP1 = SeqFil(i)->ChangeVertex(isfirst,onS);
2154         if (Fd->Vertex(isfirst,onS).IsOnArc() && CP1.IsOnArc()) {
2155           ChFiDS_CommonPoint& CP2 = Fd->ChangeVertex(!isfirst,onS);
2156           CP1.Reset();
2157           CP1.SetPoint(CP2.Point());
2158           CP2.Reset();
2159           CP2.SetPoint(CP1.Point());
2160         }
2161       }
2162     }
2163   }
2164
2165   for (j=1; j<=SeqFil.Length(); j++) {
2166
2167     const Handle(ChFiDS_SurfData)& Fd = SeqFil(j);
2168     Isurf= Fd->Surf();
2169     Ishape1 = Fd->IndexOfS1();
2170     Ishape2 = Fd->IndexOfS2();
2171
2172     // eap, Apr 29 2002, occ 293
2173     // now IsInDS() returns nb of surfaces at end being in DS;
2174     // vars showing which end is in DS
2175     Standard_Boolean isInDS1 = Standard_False, isInDS2 = Standard_False;
2176     if (j <= CorDat->IsInDS(Standard_True)) {
2177       isInDS1 = Standard_True;
2178       isInDS2 = (j+1 <= CorDat->IsInDS(Standard_True));
2179     }
2180     if (SeqFil.Length()-j < CorDat->IsInDS(Standard_False)) {
2181       isInDS2 = Standard_True;
2182       isInDS1 = isInDS1 || SeqFil.Length()-j+1 < CorDat->IsInDS(Standard_False);
2183     }
2184     
2185     // creation de la SolidSurfaceInterference
2186     
2187     Handle(TopOpeBRepDS_SolidSurfaceInterference) 
2188       SSI = new TopOpeBRepDS_SolidSurfaceInterference
2189         (TopOpeBRepDS_Transition(Fd->Orientation()),
2190          TopOpeBRepDS_SOLID,
2191          SolidIndex,
2192          TopOpeBRepDS_SURFACE,
2193          Isurf);
2194     
2195     SolidInterfs.Append(SSI);
2196     
2197     const ChFiDS_FaceInterference& Fi1 = Fd->InterferenceOnS1();
2198     const ChFiDS_FaceInterference& Fi2 = Fd->InterferenceOnS2();     
2199     const ChFiDS_CommonPoint& V1 = Fd->VertexFirstOnS1();
2200     const ChFiDS_CommonPoint& V2 = Fd->VertexFirstOnS2();
2201
2202     // Un petit traitement pour gerer les interference doubles
2203     if (j>1) {
2204       if (V1.IsOnArc() && V3.IsOnArc() && V1.Arc().IsSame(V3.Arc())) {
2205         //on initialise Iarc1
2206         //Iarc1 = DStr.AddShape(V1.Arc());
2207         if (ChFi3d_Contains(DStr.ShapeInterferences(Iarc1),Iarc1,Ipoin1) && 
2208             (V1.TransitionOnArc() != V3.TransitionOnArc()) ) {
2209           Interfp1= ChFi3d_FilPointInDS(V1.TransitionOnArc(),Iarc1,Ipoin1,
2210                                         V1.ParameterOnArc());
2211           DStr.ChangeShapeInterferences(V1.Arc()).Append(Interfp1);
2212         }
2213       }
2214
2215       if (V2.IsOnArc() && V4.IsOnArc() && V2.Arc().IsSame(V4.Arc())) {
2216         //on initialise Iarc2
2217         //Iarc2 = DStr.AddShape(V2.Arc());
2218         if ( ChFi3d_Contains(DStr.ShapeInterferences(Iarc2),Iarc2,Ipoin2)  && 
2219             (V2.TransitionOnArc() != V4.TransitionOnArc()) ) {
2220           Interfp2= ChFi3d_FilPointInDS(V2.TransitionOnArc(),Iarc2,Ipoin2,
2221                                         V2.ParameterOnArc());
2222           DStr.ChangeShapeInterferences(V2.Arc()).Append(Interfp2);
2223         }
2224       }
2225     }
2226
2227     V3 = Fd->VertexLastOnS1();
2228     V4 = Fd->VertexLastOnS2();
2229     
2230     if(Ishape1 != 0) {
2231       if(Ishape1 > 0) {
2232         trafil1 = DStr.Shape(Ishape1).Orientation();
2233       }
2234       else{
2235         ChFi3d_Orientation(SolidInterfs,SolidIndex,-Ishape1,trafil1);
2236       }
2237       trafil1 = TopAbs::Compose(trafil1,Fd->Orientation());
2238       trafil1 = TopAbs::Compose(TopAbs::Reverse(Fi1.Transition()),trafil1);
2239       trafil2 = TopAbs::Reverse(trafil1);
2240     }
2241     else{
2242       if(Ishape2 > 0) {
2243         trafil2 = DStr.Shape(Ishape2).Orientation();
2244       }
2245       else{
2246         ChFi3d_Orientation(SolidInterfs,SolidIndex,-Ishape2,trafil2);
2247       }
2248       trafil2 = TopAbs::Compose(trafil2,Fd->Orientation());
2249       trafil2 = TopAbs::Compose(TopAbs::Reverse(Fi2.Transition()),trafil2);
2250       trafil1 = TopAbs::Reverse(trafil2);
2251     }
2252     
2253     ET1 = TopAbs::Reverse(trafil1);
2254     
2255     // Un petit paragraphe pour traiter les contacts aretes qui touchent 
2256     // un vertex de l'obstacle.
2257     if(V1.IsVertex() && Fd->IsOnCurve1()) {
2258       const TopoDS_Vertex& vv1 = V1.Vertex();
2259       CutEdge(vv1,Fd,DStr,1,1);
2260     }
2261     if(V2.IsVertex() && Fd->IsOnCurve2()) {
2262       const TopoDS_Vertex& vv2 = V2.Vertex();
2263       CutEdge(vv2,Fd,DStr,1,2);
2264     }
2265     if(V3.IsVertex() && Fd->IsOnCurve1()) {
2266       const TopoDS_Vertex& vv3 = V3.Vertex();
2267       CutEdge(vv3,Fd,DStr,0,1);
2268     }
2269     if(V4.IsVertex() && Fd->IsOnCurve2()) {
2270       const TopoDS_Vertex& vv4 = V4.Vertex();
2271       CutEdge(vv4,Fd,DStr,0,2);
2272     }
2273     
2274     if (j == 1) {
2275       isVertex1 = V1.IsVertex();
2276       isVertex2 = V2.IsVertex();
2277       Singulier_en_Bout =  (V1.Point().IsEqual(V2.Point(), 0));
2278       
2279       if (Singulier_en_Bout) {
2280          // Queue de Billard
2281          if ((!V1.IsVertex()) || (!V2.IsVertex())) {
2282
2283          }
2284          else {
2285            isVertex1 = isVertex2 = Standard_True; //precaution...
2286            // On elimine l'arete de la spine debouchant sur ce vertex.
2287            TopoDS_Edge Arcspine = spine->Edges(1);
2288            BoutdeVtx = V1.Vertex();
2289            Standard_Integer IArcspine = DStr.AddShape(Arcspine);
2290            Standard_Integer IVtx = CorDat->IndexFirstPointOnS1();
2291
2292            TopAbs_Orientation OVtx = TopAbs_FORWARD;;
2293
2294            for(ex.Init(Arcspine.Oriented(TopAbs_FORWARD),TopAbs_VERTEX); 
2295                ex.More(); ex.Next()) {
2296              if(BoutdeVtx.IsSame(ex.Current())) {
2297                OVtx = ex.Current().Orientation();
2298                break;
2299              }
2300            }
2301            OVtx = TopAbs::Reverse(OVtx);
2302            Standard_Real parVtx = BRep_Tool::Parameter(BoutdeVtx,Arcspine);
2303            Handle(TopOpeBRepDS_CurvePointInterference) 
2304              interfv = ChFi3d_FilVertexInDS(OVtx,IArcspine,IVtx,parVtx);
2305            DStr.ChangeShapeInterferences(IArcspine).Append(interfv);
2306          }
2307        }
2308       else {
2309         if (V1.IsOnArc()) {
2310           Iarc1 = DStr.AddShape(V1.Arc()); 
2311           if ( !ChFi3d_Contains(DStr.ShapeInterferences(Iarc1),Iarc1,Ipoin1) ) {
2312             Interfp1= ChFi3d_FilPointInDS(V1.TransitionOnArc(),Iarc1,Ipoin1,
2313                                           V1.ParameterOnArc(), isVertex1);
2314             DStr.ChangeShapeInterferences(V1.Arc()).Append(Interfp1);
2315           }
2316         }
2317
2318         if (V2.IsOnArc()) {
2319           Iarc2 = DStr.AddShape(V2.Arc());
2320           if ( !ChFi3d_Contains(DStr.ShapeInterferences(Iarc2),Iarc2,Ipoin2) ) {
2321             Interfp2= ChFi3d_FilPointInDS(V2.TransitionOnArc(),Iarc2,Ipoin2,
2322                                           V2.ParameterOnArc(),isVertex2);
2323             DStr.ChangeShapeInterferences(V2.Arc()).Append(Interfp2);
2324           }
2325         }
2326       }
2327
2328       if (!isInDS1) {
2329         ET1 = TopAbs::Compose(ET1,CorDat->FirstPCurveOrientation());
2330         Icurv = CorDat->FirstCurve();
2331         if(Closed && !Singulier_en_Bout) {
2332           regcout.SetCurve(Icurv);
2333           regcout.SetS1(Isurf,Standard_False);
2334         }
2335         PCurv = CorDat->FirstPCurve();
2336         CorDat->FirstParameters(Pardeb,Parfin);
2337         
2338         TopOpeBRepDS_ListOfInterference& Li = DStr.ChangeCurveInterferences(Icurv);
2339         if (Li.IsEmpty()) {
2340           if(CorDat->FirstPCurveOrientation()==TopAbs_REVERSED) {
2341             Interfp1=ChFi3d_FilPointInDS
2342               (TopAbs_REVERSED,Icurv,Ipoin1,Parfin,isVertex1);
2343             Interfp2=ChFi3d_FilPointInDS
2344               (TopAbs_FORWARD,Icurv,Ipoin2,Pardeb,isVertex2);
2345           }
2346           else{
2347             Interfp1=ChFi3d_FilPointInDS
2348               (TopAbs_FORWARD,Icurv,Ipoin1,Pardeb,isVertex1);
2349             Interfp2=ChFi3d_FilPointInDS
2350               (TopAbs_REVERSED,Icurv,Ipoin2,Parfin,isVertex2);
2351           }
2352           Li.Append(Interfp1);
2353           Li.Append(Interfp2);
2354         }
2355         Interfc1= ChFi3d_FilCurveInDS (Icurv,Isurf,PCurv,ET1);
2356         DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc1);
2357         if (Ipoin1 == Ipoin2) {
2358           TopOpeBRepDS_Curve& TCurv = DStr.ChangeCurve(Icurv);
2359           TCurv.ChangeCurve().Nullify();
2360           Handle(TopOpeBRepDS_Interference) bidinterf;
2361           TCurv.SetSCI(Interfc1,bidinterf);         
2362         }
2363       }
2364     } // Fin du Traitement Initial (j==1)
2365     else {
2366       // ---- Interference entre Conges ------
2367       
2368       if (!isInDS1) {// eap, Apr 29 2002, occ 293 
2369         
2370         if (Degene && isVertex1) {
2371           // On elimine l'arete de la spine debouchant sur ce vertex.
2372           NumEdge++; // On a dejas trouve l'arete precedente du vertex
2373           TopoDS_Edge Arcspine = spine->Edges(NumEdge);
2374           Standard_Integer IArcspine = DStr.AddShape(Arcspine);
2375           Standard_Integer IVtx = DStr.AddShape(BoutdeVtx);
2376           TopAbs_Orientation OVtx = TopAbs_FORWARD;
2377           for(ex.Init(Arcspine.Oriented(TopAbs_FORWARD),TopAbs_VERTEX); 
2378               ex.More(); ex.Next()) {
2379             if(BoutdeVtx.IsSame(ex.Current())) {
2380               OVtx = ex.Current().Orientation();
2381               break;
2382             }
2383           }
2384           OVtx = TopAbs::Reverse(OVtx);
2385           Standard_Real parVtx = BRep_Tool::Parameter(BoutdeVtx,Arcspine);
2386           Handle(TopOpeBRepDS_CurvePointInterference) 
2387             interfv = ChFi3d_FilVertexInDS(OVtx,IArcspine,IVtx,parVtx);
2388           DStr.ChangeShapeInterferences(IArcspine).Append(interfv);
2389         } // Fin de l'elimination
2390
2391         gp_Pnt2d UV1 = Fd->InterferenceOnS1().PCurveOnSurf()->
2392           Value(Fd->InterferenceOnS1().FirstParameter());
2393         gp_Pnt2d UV2 = Fd->InterferenceOnS2().PCurveOnSurf()-> 
2394           Value(Fd->InterferenceOnS2().FirstParameter());
2395         TopOpeBRepDS_Curve& TCurv = DStr.ChangeCurve(Icurv);
2396         if (Degene) {
2397           // on associe la pcurve via la SCI a la TopOpeBRepDSCurve.
2398           ChFi3d_ComputePCurv(UV1,UV2,PCurv,Pardeb,Parfin);       
2399           Interfc1= ChFi3d_FilCurveInDS (Icurv,Isurf,PCurv,ET1);
2400           DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc1);
2401           TCurv.ChangeCurve().Nullify();
2402           Handle(TopOpeBRepDS_Interference) bidinterf;
2403           TCurv.SetSCI(Interfc1,bidinterf);           
2404         }
2405         else {
2406           regfilfil.SetS2(Isurf,Standard_False);
2407           reglist.Append(regfilfil);
2408           Standard_Real tolreached;
2409           ChFi3d_ComputePCurv(TCurv.ChangeCurve(),UV1,UV2,PCurv,
2410                               DStr.Surface(Fd->Surf()).Surface(),
2411                               Pardeb,Parfin,tol3d,tolreached);
2412           TCurv.Tolerance(Max(TCurv.Tolerance(),tolreached));
2413           Interfc1= ChFi3d_FilCurveInDS (Icurv,Isurf,PCurv,ET1);
2414           DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc1);
2415         }
2416       }
2417     } // Fin Interference entre conges 
2418    
2419     // ---- Interference Conges / Faces
2420     IcFil1 = Fi1.LineIndex();
2421     
2422     if (IcFil1!=0 ) {
2423       Interfc3= ChFi3d_FilCurveInDS (IcFil1,Isurf,
2424                                      Fi1.PCurveOnSurf(),trafil1);
2425       DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc3);
2426       Ishape1 = Fd->IndexOfS1();
2427       // Cas d arete degeneree : on associe la pcurve via la SCI 
2428       // a la TopOpeBRepDSCurve.
2429       TopOpeBRepDS_Curve& cc = DStr.ChangeCurve(IcFil1);
2430       if(cc.Curve().IsNull()) {
2431         Handle(TopOpeBRepDS_Interference) bidinterf;
2432         cc.SetSCI(Interfc3,bidinterf);
2433       }
2434       else{
2435         ChFiDS_Regul regon1;
2436         regon1.SetCurve(IcFil1);
2437         regon1.SetS1(Isurf,Standard_False);
2438         if ( Ishape1 < 0 ) {
2439           Ishape1 = -Ishape1;
2440           regon1.SetS2(Ishape1,Standard_False);
2441           Interfc1=ChFi3d_FilCurveInDS(IcFil1,Ishape1,Fi1.PCurveOnFace(),
2442                                        Fi1.Transition()); 
2443           DStr.ChangeSurfaceInterferences(Ishape1).Append(Interfc1);      
2444         }
2445         else if ( Ishape1 > 0 ) {
2446           regon1.SetS2(Ishape1,Standard_True);
2447           Interfc1=ChFi3d_FilCurveInDS(IcFil1,Ishape1,Fi1.PCurveOnFace(),
2448                                        Fi1.Transition()); 
2449           DStr.ChangeShapeInterferences(Ishape1).Append(Interfc1);      
2450         }
2451         reglist.Append(regon1);
2452       }
2453       // Indice et type du point en Fin
2454       Standard_Integer ipoin;
2455       Standard_Boolean isVertex = Fd->VertexLastOnS1().IsVertex();
2456       if (j == SeqFil.Length()) ipoin = CorDat->IndexLastPointOnS1();
2457       else if ( j == (SeqFil.Length()-1)  &&  /*Closed &&*/
2458                (DStr.Curve(SeqFil.Last()->InterferenceOnS1().
2459                            LineIndex()).Curve().IsNull())) {
2460         if (Closed) {
2461           ipoin = CorDat->IndexFirstPointOnS1();
2462           isVertex = SeqFil(1)->VertexFirstOnS1().IsVertex();
2463         } else {
2464           ipoin = CorDat->IndexLastPointOnS1();
2465           isVertex = SeqFil.Last()->VertexLastOnS1().IsVertex();
2466         }
2467       }
2468       else if(DStr.Curve(IcFil1).Curve().IsNull()) {// Rotation !!
2469         ipoin = Ipoin1;
2470         isVertex = isVertex1;
2471       }
2472       else if ( ((j==1) || (j== SeqFil.Length()-1)) && 
2473                 ( (Fd->VertexLastOnS1().Point().IsEqual(
2474                   SeqFil(1)->VertexFirstOnS1().Point(), 1.e-7)) ||
2475                   (Fd->VertexLastOnS1().Point().IsEqual(
2476                   SeqFil(SeqFil.Length())->VertexLastOnS1().Point(), 1.e-7))) )
2477         // Cas des SurfData coupe de facon "Triangulaire"   
2478         ipoin=CorDat->IndexLastPointOnS1();
2479
2480       // eap, Apr 29 2002, occ 293
2481       else if (isInDS2 && findIndexPoint(DStr, Fd, 1, ipoin)) {
2482
2483       }
2484       else ipoin = ChFi3d_IndexPointInDS(Fd->VertexLastOnS1(),DStr);
2485       
2486       TopOpeBRepDS_ListOfInterference& Li = DStr.ChangeCurveInterferences(IcFil1);
2487
2488       if (!ChFi3d_Contains(Li,IcFil1,Ipoin1)) { 
2489         
2490         Interfp1 = ChFi3d_FilPointInDS(TopAbs_FORWARD,IcFil1,Ipoin1,
2491                                        Fi1.FirstParameter(),isVertex1);
2492         DStr.ChangeCurveInterferences(IcFil1).Append(Interfp1);
2493       }
2494       if (ipoin == Ipoin1 || !ChFi3d_Contains(Li,IcFil1,ipoin)) { 
2495         Interfp3 = ChFi3d_FilPointInDS(TopAbs_REVERSED,IcFil1,ipoin,
2496                                        Fi1.LastParameter(), isVertex);
2497         DStr.ChangeCurveInterferences(IcFil1).Append(Interfp3);
2498       }
2499       Ipoin1 = ipoin;
2500       isVertex1 = isVertex;
2501     }
2502     
2503     IcFil2 = Fi2.LineIndex();
2504     if (IcFil2!=0) {
2505       Interfc4=ChFi3d_FilCurveInDS(IcFil2,Isurf,
2506                                    Fi2.PCurveOnSurf(),trafil2);
2507       DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc4);
2508       Ishape2 = Fd->IndexOfS2();
2509       // Cas d arete degeneree : on associe la pcurve via la SCI 
2510       // a la TopOpeBRepDSCurve.
2511       TopOpeBRepDS_Curve& cc = DStr.ChangeCurve(IcFil2);
2512       if(cc.Curve().IsNull()) {
2513         Handle(TopOpeBRepDS_Interference) bidinterf;
2514         cc.SetSCI(Interfc4,bidinterf);
2515       }
2516       else{
2517         ChFiDS_Regul regon2;
2518         regon2.SetCurve(IcFil2);
2519         regon2.SetS1(Isurf,Standard_False);
2520         if ( Ishape2 < 0 ) {
2521           Ishape2 = -Ishape2;
2522           regon2.SetS2(Ishape2,Standard_False);
2523           Interfc2=ChFi3d_FilCurveInDS(IcFil2,Ishape2,Fi2.PCurveOnFace(),
2524                                        Fi2.Transition());
2525           DStr.ChangeSurfaceInterferences(Ishape2).Append(Interfc2);      
2526         }
2527         else if ( Ishape2 > 0 ) {
2528           regon2.SetS2(Ishape2,Standard_True);
2529           Interfc2=ChFi3d_FilCurveInDS(IcFil2,Ishape2,Fi2.PCurveOnFace(),
2530                                        Fi2.Transition());
2531           DStr.ChangeShapeInterferences(Ishape2).Append(Interfc2);      
2532         }
2533         reglist.Append(regon2);
2534       }
2535       // Indice et type du point en Fin
2536       Standard_Integer ipoin;
2537       Standard_Boolean isVertex = Fd->VertexLastOnS2().IsVertex();
2538       if (j == SeqFil.Length() ) ipoin = CorDat->IndexLastPointOnS2();
2539       else if ( j == (SeqFil.Length()-1)  && /*Closed &&*/
2540                (DStr.Curve(SeqFil.Last()->InterferenceOnS2().
2541                            LineIndex()).Curve().IsNull())) {
2542         if (Closed) {
2543           ipoin = CorDat->IndexFirstPointOnS2();
2544           isVertex = SeqFil(1)->VertexFirstOnS2().IsVertex();
2545         } else {
2546           ipoin = CorDat->IndexLastPointOnS2();
2547           isVertex = SeqFil.Last()->VertexLastOnS2().IsVertex();
2548         }
2549       }
2550       else if(DStr.Curve(IcFil2).Curve().IsNull()) { // Rotation !!
2551         ipoin = Ipoin2;
2552         isVertex = isVertex2;
2553       }
2554       else if(Fd->VertexLastOnS2().Point().IsEqual(
2555               Fd->VertexLastOnS1().Point(), 0) ) {  //Pincement !!
2556         ipoin = Ipoin1;
2557         isVertex = isVertex1;
2558       }
2559       else if ( ((j==1) || (j==SeqFil.Length()-1)) && 
2560                 ( (Fd->VertexLastOnS2().Point().IsEqual(
2561                   SeqFil(1)->VertexFirstOnS2().Point(), 1.e-7)) ||
2562                   (Fd->VertexLastOnS2().Point().IsEqual(
2563                   SeqFil(SeqFil.Length())->VertexLastOnS2().Point(), 1.e-7))) )
2564         // Cas des SurfData coupe de facon "Triangulaire"    
2565         ipoin=CorDat->IndexLastPointOnS2();
2566
2567       // eap, Apr 29 2002, occ 293
2568       else if (isInDS2 && findIndexPoint(DStr, Fd, 2, ipoin)) {
2569
2570       }
2571       else ipoin = ChFi3d_IndexPointInDS(Fd->VertexLastOnS2(),DStr);
2572       
2573       TopOpeBRepDS_ListOfInterference& Li = DStr.ChangeCurveInterferences(IcFil2);
2574
2575       if (!ChFi3d_Contains(Li,IcFil2,Ipoin2)) { 
2576         Interfp2 = ChFi3d_FilPointInDS(TopAbs_FORWARD,IcFil2,Ipoin2,
2577                                        Fi2.FirstParameter(), isVertex2);
2578         DStr.ChangeCurveInterferences(IcFil2).Append(Interfp2);
2579       }
2580       if (ipoin == Ipoin2 || !ChFi3d_Contains(Li,IcFil2,ipoin)) { 
2581         Interfp4= ChFi3d_FilPointInDS(TopAbs_REVERSED,IcFil2,ipoin,
2582                                       Fi2.LastParameter(), isVertex );
2583         DStr.ChangeCurveInterferences(IcFil2).Append(Interfp4);
2584       }
2585       Ipoin2 = ipoin;
2586       isVertex2 = isVertex;      
2587     }
2588     
2589     ET1 = trafil1;
2590     if (j == SeqFil.Length()) {
2591       if (!isInDS2) {
2592         Icurv = CorDat->LastCurve();
2593         if(Closed && !Singulier_en_Bout && (Ipoin1!=Ipoin2)) {
2594           regcout.SetS2(Isurf,Standard_False);
2595           reglist.Append(regcout);
2596         }
2597         PCurv = CorDat->LastPCurve();
2598         ET1 = TopAbs::Compose(ET1,CorDat->LastPCurveOrientation());
2599         CorDat->LastParameters(Pardeb,Parfin);
2600         TopOpeBRepDS_ListOfInterference& Li = DStr.ChangeCurveInterferences(Icurv);
2601         if (Li.IsEmpty()) {
2602           if(CorDat->LastPCurveOrientation()==TopAbs_REVERSED) {
2603             Interfp5=ChFi3d_FilPointInDS
2604               (TopAbs_REVERSED,Icurv,Ipoin1,Parfin, isVertex1);
2605             Interfp6=ChFi3d_FilPointInDS
2606               (TopAbs_FORWARD,Icurv,Ipoin2,Pardeb, isVertex2);
2607           }
2608           else{
2609             Interfp5=ChFi3d_FilPointInDS
2610               (TopAbs_FORWARD,Icurv,Ipoin1,Pardeb, isVertex1);
2611             Interfp6=ChFi3d_FilPointInDS
2612               (TopAbs_REVERSED,Icurv,Ipoin2,Parfin, isVertex2);
2613           }
2614           Li.Append(Interfp5);
2615           Li.Append(Interfp6);
2616         }
2617         Interfc1= ChFi3d_FilCurveInDS(Icurv,Isurf,PCurv,ET1);
2618         DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc1);
2619         if (Ipoin1 == Ipoin2) {
2620           TopOpeBRepDS_Curve& TCurv = DStr.ChangeCurve(Icurv);
2621           TCurv.ChangeCurve().Nullify();
2622           Handle(TopOpeBRepDS_Interference) bidinterf;
2623           TCurv.SetSCI( Interfc1, bidinterf);
2624 //         bidinterf = TCurv.GetSCI1(); 
2625 //        TCurv.SetSCI(bidinterf, Interfc1);        
2626         }
2627       }
2628     }
2629     else {
2630 //      Degene = (Fd->VertexLastOnS1().Point().IsEqual(
2631 //                Fd->VertexLastOnS2().Point(), 0) );
2632       
2633       // eap, Apr 29 2002, occ 293 
2634       if (!isInDS2) {
2635         
2636         Handle(Geom_Curve) C3d;
2637         Standard_Real tolreached;
2638         ChFi3d_ComputeArete(Fd->VertexLastOnS1(),
2639                             Fd->InterferenceOnS1().PCurveOnSurf()->
2640                             Value(Fd->InterferenceOnS1().LastParameter()),
2641                             Fd->VertexLastOnS2(),
2642                             Fd->InterferenceOnS2().PCurveOnSurf()->
2643                             Value(Fd->InterferenceOnS2().LastParameter()),
2644                             DStr.Surface(Fd->Surf()).Surface(),C3d,PCurv,
2645                             Pardeb,Parfin,tol3d,tol2d,tolreached,0);
2646         Crv = TopOpeBRepDS_Curve(C3d,tolreached);
2647         Icurv = DStr.AddCurve(Crv);
2648         regfilfil.SetCurve(Icurv);
2649         regfilfil.SetS1(Isurf,Standard_False);
2650         Interfp5 = ChFi3d_FilPointInDS(TopAbs_FORWARD,Icurv,Ipoin1,Pardeb, isVertex1);
2651         DStr.ChangeCurveInterferences(Icurv).Append(Interfp5);
2652         Interfp6= ChFi3d_FilPointInDS(TopAbs_REVERSED,Icurv,Ipoin2,Parfin, isVertex2);
2653         DStr.ChangeCurveInterferences(Icurv).Append(Interfp6);
2654         Interfc1= ChFi3d_FilCurveInDS(Icurv,Isurf,PCurv,ET1);
2655         DStr.ChangeSurfaceInterferences(Isurf).Append(Interfc1);      
2656       }
2657     }
2658    
2659     Degene = V3.Point().IsEqual(V4.Point(), 0);
2660
2661     // Traitement des cas degenere     
2662     if (Degene) {
2663       // Queue de Billard
2664       Standard_Boolean Vertex = (V3.IsVertex()) && (V4.IsVertex());
2665       if (!Vertex) {
2666
2667       }
2668       else {
2669         // On elimine l'arete de la spine debouchant sur ce vertex.
2670         Standard_Boolean Trouve = Standard_False;
2671         TopoDS_Edge Arcspine;
2672         TopAbs_Orientation OVtx = TopAbs_FORWARD;
2673         BoutdeVtx = V3.Vertex();
2674             
2675         while (NumEdge<= spine->NbEdges() && !Trouve) { 
2676           Arcspine = spine->Edges(NumEdge);
2677           for(ex.Init(Arcspine.Oriented(TopAbs_FORWARD),TopAbs_VERTEX); 
2678               ex.More() && (!Trouve); ex.Next()) {
2679             if(BoutdeVtx.IsSame(ex.Current())) {
2680               OVtx = ex.Current().Orientation();
2681               if (Closed &&  (NumEdge == 1)) 
2682                    Trouve = (spine->NbEdges() == 1);
2683               else Trouve = Standard_True;
2684             }
2685           }
2686           if (!Trouve) NumEdge++; // On passe a l'arete suivante
2687         }
2688         Standard_Integer IArcspine = DStr.AddShape(Arcspine);
2689         Standard_Integer IVtx;
2690         if  (j == SeqFil.Length()) {
2691           IVtx = CorDat->IndexLastPointOnS1();
2692         }
2693         else { IVtx = DStr.AddShape(BoutdeVtx); }
2694         OVtx = TopAbs::Reverse(OVtx);
2695         Standard_Real parVtx = BRep_Tool::Parameter(BoutdeVtx,Arcspine);
2696         Handle(TopOpeBRepDS_CurvePointInterference) 
2697           interfv = ChFi3d_FilVertexInDS(OVtx,IArcspine,IVtx,parVtx);
2698         DStr.ChangeShapeInterferences(IArcspine).Append(interfv);
2699       }
2700     } // fin du cas Degene
2701     else if (!(Closed && j == SeqFil.Length())) {
2702       // Traitement des interference Point / Edges
2703       if (V3.IsOnArc()) {
2704         if(!(V3.IsVertex() && Fd->IsOnCurve1())) {
2705           Iarc1 = DStr.AddShape(V3.Arc());
2706           if ( !ChFi3d_Contains(DStr.ShapeInterferences(Iarc1),Iarc1,Ipoin1,V3.IsVertex(),Standard_True) ) {
2707             Handle(TopOpeBRepDS_CurvePointInterference) Interfpp = 
2708               ChFi3d_FilPointInDS(V3.TransitionOnArc(),
2709                                   Iarc1,Ipoin1,V3.ParameterOnArc(), V3.IsVertex());
2710             DStr.ChangeShapeInterferences(V3.Arc()).Append(Interfpp);
2711           }
2712         }
2713       }
2714
2715       if (V4.IsOnArc()) {
2716         if(!(V4.IsVertex() && Fd->IsOnCurve2())) {
2717           Iarc2 = DStr.AddShape(V4.Arc());
2718           if ( !ChFi3d_Contains(DStr.ShapeInterferences(Iarc2),Iarc2,Ipoin2,V4.IsVertex(),Standard_True) ) {
2719             Handle(TopOpeBRepDS_CurvePointInterference) Intfpp=
2720               ChFi3d_FilPointInDS(V4.TransitionOnArc(),
2721                                   Iarc2,Ipoin2,V4.ParameterOnArc(), V4.IsVertex());
2722             DStr.ChangeShapeInterferences(V4.Arc()).Append(Intfpp);
2723           }
2724         }
2725       }
2726     }
2727   }
2728 }
2729 //=======================================================================
2730 //function : StripeEdgeInter
2731 //purpose  : This function examines two stripes for an intersection 
2732 //           between curves of interference with faces. If the intersection
2733 //           exists, it will cause bad result, so it's better to quit.
2734 //remark   : If someone somewhen computes the interference between stripes, 
2735 //           this function will become useless.
2736 //author   : akm, 06/02/02. Against bug OCC119.
2737 //=======================================================================
2738 void ChFi3d_StripeEdgeInter (const Handle(ChFiDS_Stripe)& theStripe1,
2739                              const Handle(ChFiDS_Stripe)& theStripe2,
2740                              TopOpeBRepDS_DataStructure&  /*DStr*/,
2741                              const Standard_Real          tol2d)
2742 {
2743   // Do not check the stripeshaving common corner points
2744   for (Standard_Integer iSur1=1; iSur1<=2; iSur1++)
2745     for (Standard_Integer iSur2=1; iSur2<=2; iSur2++)
2746       if (theStripe1->IndexPoint(0,iSur1)==theStripe2->IndexPoint(0,iSur2) ||
2747           theStripe1->IndexPoint(0,iSur1)==theStripe2->IndexPoint(1,iSur2) ||
2748           theStripe1->IndexPoint(1,iSur1)==theStripe2->IndexPoint(0,iSur2) ||
2749           theStripe1->IndexPoint(1,iSur1)==theStripe2->IndexPoint(1,iSur2))
2750         return;
2751
2752   Handle(ChFiDS_HData) aSurDat1 = theStripe1->SetOfSurfData();
2753   Handle(ChFiDS_HData) aSurDat2 = theStripe2->SetOfSurfData();
2754
2755   Geom2dInt_GInter anIntersector;
2756   Standard_Integer iPart1, iPart2;
2757   Standard_Integer Ishape11, Ishape12, Ishape21, Ishape22;
2758   // Loop on parts of the first stripe
2759   for (iPart1=1; iPart1<=aSurDat1->Length(); iPart1++) 
2760   {
2761     Handle(ChFiDS_SurfData) aDat1 = aSurDat1->Value(iPart1);
2762     Ishape11 = aDat1->IndexOfS1();
2763     Ishape12 = aDat1->IndexOfS2();
2764     // Loop on parts of the second stripe
2765     for (iPart2=1; iPart2<=aSurDat2->Length(); iPart2++) 
2766     {
2767       Handle(ChFiDS_SurfData) aDat2 = aSurDat2->Value(iPart2);
2768       Ishape21 = aDat2->IndexOfS1();
2769       Ishape22 = aDat2->IndexOfS2();
2770
2771       // Find those FaceInterferences able to intersect
2772       ChFiDS_FaceInterference aFI1, aFI2;
2773       if (Ishape11 == Ishape21)
2774       {
2775         aFI1 = aDat1->InterferenceOnS1();
2776         aFI2 = aDat2->InterferenceOnS1();
2777       } 
2778       else if (Ishape11 == Ishape22)
2779       {
2780         aFI1 = aDat1->InterferenceOnS1();
2781         aFI2 = aDat2->InterferenceOnS2();
2782       } 
2783       else if (Ishape12 == Ishape21)
2784       {
2785         aFI1 = aDat1->InterferenceOnS2();
2786         aFI2 = aDat2->InterferenceOnS1();
2787       } 
2788       else if (Ishape12 == Ishape22)
2789       {
2790         aFI1 = aDat1->InterferenceOnS2();
2791         aFI2 = aDat2->InterferenceOnS2();
2792       }
2793       else
2794       {
2795         // No common faces
2796         continue;
2797       }
2798
2799       if (IsEqual (aFI1.FirstParameter(),aFI1.LastParameter()) ||
2800           IsEqual (aFI2.FirstParameter(),aFI2.LastParameter()) ||
2801           aFI1.PCurveOnFace().IsNull() ||
2802           aFI2.PCurveOnFace().IsNull())
2803         // Do not waste time on degenerates
2804         continue;
2805       // Examine for intersections
2806       Geom2dAdaptor_Curve aPCurve1 (aFI1.PCurveOnFace(),
2807                                     aFI1.FirstParameter(),
2808                                     aFI1.LastParameter());
2809       Geom2dAdaptor_Curve aPCurve2 (aFI2.PCurveOnFace(),
2810                                     aFI2.FirstParameter(),
2811                                     aFI2.LastParameter());
2812       anIntersector.Perform (aPCurve1,
2813                              aPCurve2,
2814                              tol2d,
2815                              Precision::PConfusion());
2816       if (anIntersector.NbSegments() > 0 ||
2817           anIntersector.NbPoints() > 0)
2818         StdFail_NotDone::Raise ("StripeEdgeInter : fillets have too big radiuses");
2819     }
2820   }
2821 }
2822
2823 //=======================================================================
2824 //function : IndexOfSurfData
2825 //purpose  : 
2826 //=======================================================================
2827 Standard_Integer ChFi3d_IndexOfSurfData(const TopoDS_Vertex& V1,
2828                                         const Handle(ChFiDS_Stripe)& CD,
2829                                         Standard_Integer& sens)
2830 {
2831   Handle(ChFiDS_Spine) spine = CD->Spine();
2832   Standard_Integer Index = 0;
2833   sens = 1;
2834   TopoDS_Vertex Vref;
2835   const TopoDS_Edge& E = spine->Edges(1);
2836   if (E.Orientation() == TopAbs_REVERSED) Vref = TopExp::LastVertex(E);
2837   else Vref = TopExp::FirstVertex(E); 
2838   if (Vref.IsSame(V1)) Index =1;
2839   else {
2840     const TopoDS_Edge& E1 = spine->Edges(spine->NbEdges());
2841     if (E1.Orientation() == TopAbs_REVERSED) Vref = TopExp::FirstVertex(E1);
2842     else Vref = TopExp::LastVertex(E1); 
2843     sens = -1;
2844     if(CD->SetOfSurfData().IsNull()) return 0;
2845     else if (Vref.IsSame(V1)) Index = CD->SetOfSurfData()->Length();
2846     else Standard_ConstructionError::Raise("");
2847   }
2848   return Index; 
2849 }  
2850 //=======================================================================
2851 //function : EdgeFromV1
2852 //purpose  : 
2853 //=======================================================================
2854
2855 TopoDS_Edge ChFi3d_EdgeFromV1(const TopoDS_Vertex& V1,
2856                               const Handle(ChFiDS_Stripe)& CD,
2857                               Standard_Integer& sens)
2858 {
2859   Handle(ChFiDS_Spine) spine = CD->Spine();
2860   sens = 1;
2861   TopoDS_Vertex Vref;
2862   const TopoDS_Edge& E = spine->Edges(1);
2863   if (E.Orientation() == TopAbs_REVERSED) Vref = TopExp::LastVertex(E);
2864   else Vref = TopExp::FirstVertex(E); 
2865   if (Vref.IsSame(V1)) return E;
2866   else
2867     {
2868       const TopoDS_Edge& E1 = spine->Edges(spine->NbEdges());
2869       if (E1.Orientation() == TopAbs_REVERSED) Vref = TopExp::FirstVertex(E1);
2870       else Vref = TopExp::LastVertex(E1); 
2871       sens = -1;
2872       if (Vref.IsSame(V1)) return E1;
2873       else Standard_ConstructionError::Raise("");
2874     }
2875   return E;
2876 }
2877 //=======================================================================
2878 //function : ConvTol2dToTol3d
2879 //purpose  : Comme son nom l indique.
2880 //=======================================================================
2881
2882 Standard_Real ChFi3d_ConvTol2dToTol3d(const Handle(Adaptor3d_HSurface)& S,
2883                                       const Standard_Real             tol2d)
2884 {
2885   Standard_Real ures = S->UResolution(1.e-7);
2886   Standard_Real vres = S->VResolution(1.e-7);
2887   Standard_Real uresto3d = 1.e-7*tol2d/ures;
2888   Standard_Real vresto3d = 1.e-7*tol2d/vres;
2889   return Max(uresto3d,vresto3d);
2890 }
2891 //=======================================================================
2892 //function : EvalTolReached
2893 //purpose  : Comme son nom l indique la fonction ci dessus etant trop
2894 //           dure lorsque le parametrage des surfaces n est pas homogene.
2895 //=======================================================================
2896
2897 Standard_Real ChFi3d_EvalTolReached(const Handle(Adaptor3d_HSurface)& S1,
2898                                     const Handle(Geom2d_Curve)&     pc1,
2899                                     const Handle(Adaptor3d_HSurface)& S2,
2900                                     const Handle(Geom2d_Curve)&     pc2,
2901                                     const Handle(Geom_Curve)&       C)
2902 {
2903   Standard_Real distmax = 0.;
2904
2905   Standard_Real f = C->FirstParameter();
2906   Standard_Real l = C->LastParameter();
2907   Standard_Integer nbp = 45;
2908   Standard_Real step = 1./(nbp -1);
2909   for(Standard_Integer i = 0; i < nbp; i++) {
2910     Standard_Real t,u,v;
2911     t = step * i;
2912     t = (1-t) * f + t * l;
2913     pc1->Value(t).Coord(u,v);
2914     gp_Pnt pS1 = S1->Value(u,v);
2915     pc2->Value(t).Coord(u,v);
2916     gp_Pnt pS2 = S2->Value(u,v);
2917     gp_Pnt pC = C->Value(t);
2918     Standard_Real d = pS1.SquareDistance(pC);
2919     if(d>distmax) distmax = d;
2920     d = pS2.SquareDistance(pC);
2921     if(d>distmax) distmax = d;
2922     d = pS1.SquareDistance(pS2);
2923     if(d>distmax) distmax = d;
2924   }
2925   distmax = 1.5*sqrt(distmax);
2926   distmax = Max(distmax, Precision::Confusion());
2927   return distmax;
2928 }
2929
2930 //=======================================================================
2931 //function : trsfsurf
2932 //purpose  : 
2933 //=======================================================================
2934 Handle(Geom_Surface) trsfsurf(const Handle(Adaptor3d_HSurface)& HS,
2935                               Handle(Adaptor3d_TopolTool)&      /*dom*/)
2936 {
2937   //Pour l utilisation des domaines voir avec BUBUCH!!
2938   Handle(Geom_Surface) res;
2939   Handle(BRepAdaptor_HSurface) hbs = Handle(BRepAdaptor_HSurface)::DownCast(HS);
2940   Handle(GeomAdaptor_HSurface) hgs = Handle(GeomAdaptor_HSurface)::DownCast(HS);
2941   if(!hbs.IsNull()) {
2942     res = hbs->ChangeSurface().Surface().Surface();
2943     gp_Trsf trsf = hbs->ChangeSurface().Trsf();
2944     res = Handle(Geom_Surface)::DownCast(res->Transformed(trsf));
2945   }
2946   else if(!hgs.IsNull()) {
2947     res = hgs->ChangeSurface().Surface();
2948   }
2949   Handle(Geom_RectangularTrimmedSurface) 
2950     tr = Handle(Geom_RectangularTrimmedSurface)::DownCast(res);
2951   if(!tr.IsNull()) res = tr->BasisSurface();
2952
2953   Standard_Real U1 = HS->FirstUParameter(), U2 = HS->LastUParameter();
2954   Standard_Real V1 = HS->FirstVParameter(), V2 = HS->LastVParameter();
2955   if(!res.IsNull()) {
2956   // Blindage contre les Construction Error intempestifs
2957     Standard_Real u1, u2, v1, v2;
2958     res->Bounds( u1, u2, v1, v2);
2959     if (!res->IsUPeriodic()) {
2960       if (U1 < u1) U1 = u1;
2961       if (U2 > u2) U2 = u2;
2962     }
2963     if (!res->IsVPeriodic()) {
2964       if (V1 < v1) V1 = v1;
2965       if (V2 > v2) V2 = v2;
2966     }
2967     res = new Geom_RectangularTrimmedSurface(res,U1,U2,V1,V2);
2968   }
2969 //  Handle(GeomAdaptor_HSurface) temp = new GeomAdaptor_HSurface(res,U1,U2,V1,V2);
2970 //  dom = new Adaptor3d_TopolTool(temp);
2971   return res;
2972 }
2973 //=======================================================================
2974 //function : CurveCleaner
2975 //purpose  : Rend une BSpline le plus continue possible
2976 //           a une tolerance donne
2977 //=======================================================================
2978 static void CurveCleaner(Handle(Geom_BSplineCurve)& BS, 
2979                          const Standard_Real Tol,
2980                          const Standard_Integer MultMin)
2981
2982 {
2983   Standard_Real tol = Tol;
2984   Standard_Integer Mult, ii;
2985   const Standard_Integer NbK=BS->NbKnots();
2986   
2987   for (Mult = BS->Degree(); Mult > MultMin; Mult--) {
2988     tol *= 0.5; // Reduction progressive
2989     for (ii=NbK; ii>1; ii--) {
2990       if (BS->Multiplicity(ii) == Mult)
2991         BS->RemoveKnot(ii, Mult-1, tol);
2992     }
2993   }
2994 }
2995 //=======================================================================
2996 //function : ComputeCurves
2997 //purpose  : Calcule une intersection bornee entre deux HSurfaces.
2998 //           Il faut connaitre les extremites de l intersection et 
2999 //           les surfaces doivent avoir ete retouchees en entree 
3000 //           pour encadrer au mieux (ni trop pres ni trop loin) les
3001 //           points de debut et fin de l intersection.
3002 //           Les intersections analytiques sont traitees a part.
3003 //           <wholeCurv> means that resulting curve is restricted by
3004 //           boundaries of input surfaces (eap 30 May occ354)
3005 //=======================================================================
3006 Standard_Boolean ChFi3d_ComputeCurves(Handle(Adaptor3d_HSurface)&   S1,
3007                                       Handle(Adaptor3d_HSurface)&   S2,
3008                                       const TColStd_Array1OfReal& Pardeb,
3009                                       const TColStd_Array1OfReal& Parfin,
3010                                       Handle(Geom_Curve)&         C3d,
3011                                       Handle(Geom2d_Curve)&       Pc1,
3012                                       Handle(Geom2d_Curve)&       Pc2,
3013                                       const Standard_Real         tol3d,
3014                                       const Standard_Real         tol2d,
3015                                       Standard_Real&              tolreached,
3016                                       const Standard_Boolean      wholeCurv) 
3017 {
3018   Standard_Real Step = 0.1;
3019
3020   gp_Pnt pdeb1 = S1->Value(Pardeb(1),Pardeb(2));
3021   gp_Pnt pfin1 = S1->Value(Parfin(1),Parfin(2));
3022   gp_Pnt pdeb2 = S2->Value(Pardeb(3),Pardeb(4));
3023   gp_Pnt pfin2 = S2->Value(Parfin(3),Parfin(4));
3024
3025   Standard_Real distrefdeb = pdeb1.Distance(pdeb2);//mesure la solidite
3026   Standard_Real distreffin = pfin1.Distance(pfin2);//des donnees d entree
3027   if(distrefdeb < tol3d) distrefdeb = tol3d;
3028   if(distreffin < tol3d) distreffin = tol3d;
3029
3030   gp_Pnt pdeb,pfin;
3031   pdeb.SetXYZ(0.5*(pdeb1.XYZ()+pdeb2.XYZ()));
3032   pfin.SetXYZ(0.5*(pfin1.XYZ()+pfin2.XYZ()));
3033
3034   Standard_Real distref = 0.005*pdeb.Distance(pfin);
3035   if(distref < distrefdeb) distref = distrefdeb;
3036   if(distref < distreffin) distref = distreffin;
3037
3038   //On traite a part quelques cas analytiques.
3039   //Pour reorienter eventuellement le resultat de l intersection
3040   //analytique, on postule que la tangente en debut doit etre dans
3041   //le sens de la corde deb/fin.
3042   gp_Vec Vint, Vref(pdeb,pfin);
3043   gp_Pnt Pbid;
3044   Standard_Real Udeb,Ufin;
3045   Standard_Real tolr1,tolr2;
3046   tolr1 = tolr2 = tolreached = tol3d;
3047   if((S1->GetType() == GeomAbs_Cylinder && S2->GetType() == GeomAbs_Plane)||
3048      (S1->GetType() == GeomAbs_Plane && S2->GetType() == GeomAbs_Cylinder)) { 
3049     gp_Pln pl;
3050     gp_Cylinder cyl;
3051     if(S1->GetType() == GeomAbs_Plane) {
3052       pl = S1->Plane();
3053       cyl = S2->Cylinder();
3054     }
3055     else{
3056       pl = S2->Plane();
3057       cyl = S1->Cylinder();
3058     }
3059     IntAna_QuadQuadGeo ImpKK(pl,cyl,Precision::Angular(),tol3d);
3060     if (ImpKK.IsDone()) {
3061       Standard_Boolean c1line = 0;
3062       switch  (ImpKK.TypeInter()) {
3063       case IntAna_Line:
3064         {
3065           c1line = 1;
3066           Standard_Integer nbsol = ImpKK.NbSolutions();
3067           gp_Lin C1;
3068           for(Standard_Integer ilin = 1; ilin <= nbsol; ilin++) {
3069             C1 = ImpKK.Line(ilin);
3070             Udeb = ElCLib::Parameter(C1,pdeb);
3071             gp_Pnt ptest = ElCLib::Value(Udeb,C1);
3072             if(ptest.Distance(pdeb) < tol3d) break;
3073           }
3074           Ufin = ElCLib::Parameter(C1,pfin);
3075           C3d = new Geom_Line(C1);
3076           ElCLib::D1(Udeb,C1,Pbid,Vint);
3077         }
3078         break;
3079       case IntAna_Circle:
3080         {
3081           gp_Circ C1 = ImpKK.Circle(1);
3082           C3d = new Geom_Circle(C1);
3083           Udeb = ElCLib::Parameter(C1,pdeb);
3084           Ufin = ElCLib::Parameter(C1,pfin);
3085           ElCLib::D1(Udeb,C1,Pbid,Vint);
3086         }
3087         break;
3088       case IntAna_Ellipse:
3089         {
3090           gp_Elips C1 = ImpKK.Ellipse(1);
3091           C3d = new Geom_Ellipse(C1);
3092           Udeb = ElCLib::Parameter(C1,pdeb);
3093           Ufin = ElCLib::Parameter(C1,pfin);
3094           ElCLib::D1(Udeb,C1,Pbid,Vint);
3095         }
3096         break;
3097       default:
3098         break;
3099       }
3100       if (Vint.Dot(Vref)<0) {
3101         C3d->Reverse();
3102         if(c1line) {
3103           Udeb = -Udeb;
3104           Ufin = -Ufin;
3105         }
3106         else{
3107           Udeb = 2*PI - Udeb;
3108           Ufin = 2*PI - Ufin;
3109         }
3110       }
3111       if(!c1line) ElCLib::AdjustPeriodic(0.,2*PI,Precision::Angular(),Udeb,Ufin);
3112       Handle(GeomAdaptor_HCurve) HC = new GeomAdaptor_HCurve();
3113       HC->ChangeCurve().Load(C3d,Udeb,Ufin);
3114       ChFi3d_ProjectPCurv(HC,S1,Pc1,tol3d,tolr1);
3115       if(S1->GetType() == GeomAbs_Cylinder) {
3116         Standard_Real x,y;
3117         Pc1->Value(Udeb).Coord(x,y);
3118         x = Pardeb(1) - x;
3119         y = Pardeb(2) - y;
3120         if(Abs(x) >= tol2d || Abs(y) >= tol2d) Pc1->Translate(gp_Vec2d(x,y));
3121       }
3122       ChFi3d_ProjectPCurv(HC,S2,Pc2,tol3d,tolr2);
3123       if(S2->GetType() == GeomAbs_Cylinder) {
3124         Standard_Real x,y;
3125         Pc2->Value(Udeb).Coord(x,y);
3126         x = Pardeb(3) - x;
3127         y = Pardeb(4) - y;
3128         if(Abs(x) >= tol2d || Abs(y) >= tol2d) Pc2->Translate(gp_Vec2d(x,y));
3129       }
3130       C3d = new Geom_TrimmedCurve(C3d,Udeb,Ufin);
3131       tolreached = 1.5*Max(tolr1,tolr2);
3132       tolreached = Min(tolreached,ChFi3d_EvalTolReached(S1,Pc1,S2,Pc2,C3d));
3133       return Standard_True;
3134     }
3135   }    
3136   else if(S1->GetType() == GeomAbs_Plane && S2->GetType() == GeomAbs_Plane) { 
3137     IntAna_QuadQuadGeo LInt(S1->Plane(),S2->Plane(),Precision::Angular(),tol3d);
3138     if (LInt.IsDone()) {
3139       gp_Lin L = LInt.Line(1);
3140       C3d = new Geom_Line(L);
3141       Udeb = ElCLib::Parameter(L,pdeb);
3142       Ufin = ElCLib::Parameter(L,pfin);
3143       ElCLib::D1(Udeb,L,Pbid,Vint);
3144       if (Vint.Dot(Vref)<0) {
3145         C3d->Reverse();
3146         Udeb = - Udeb;
3147         Ufin = - Ufin;
3148       }
3149       Handle(GeomAdaptor_HCurve) HC = new GeomAdaptor_HCurve();
3150       HC->ChangeCurve().Load(C3d,Udeb,Ufin);
3151       ChFi3d_ProjectPCurv(HC,S1,Pc1,tol3d,tolr1);
3152       ChFi3d_ProjectPCurv(HC,S2,Pc2,tol3d,tolr2);
3153       C3d = new Geom_TrimmedCurve(C3d,Udeb,Ufin);
3154       return Standard_True;
3155     }
3156   }
3157   else {
3158     // ici on attaque GeomInt.
3159     //Pour l utilisation des domaines voir avec BUBUCH!!
3160     Handle(Adaptor3d_TopolTool) dom1,dom2;
3161     Handle(Geom_Surface) gs1 = trsfsurf(S1,dom1);
3162     Handle(Geom_Surface) gs2 = trsfsurf(S2,dom2);
3163     Standard_Integer nbl ;
3164     if(!gs1.IsNull() && !gs2.IsNull()) {
3165       GeomInt_IntSS inter;
3166       //  Modified by skv - Fri Oct 24 14:24:47 2003 OCC4077 Begin
3167 //       Standard_Real tolap = 1.e-7;//car l approx de la wline est faite dans [0,1]
3168       // Set the lowest tolerance which is used in new boolean operations.
3169       Standard_Real tolap = 2.e-7;
3170       //  Modified by skv - Fri Oct 24 14:24:48 2003 OCC4077 End
3171       inter.Perform(gs1,gs2,tolap,1,1,1);
3172       if(inter.IsDone()) {
3173         nbl = inter.NbLines();   
3174 #if defined(IRIX) || defined(__sgi)
3175         if(nbl==0) {
3176
3177 //  solution de rattrapage pour SGI 
3178 //  si l'intersection de gs1 avec gs2 ne marche pas alors on  tente 
3179 // l'intersection de gs2 avec gs1 
3180
3181           inter.Perform(gs2,gs1,tolap,1,1,1);
3182 //          inter.Perform(gs2,dom2,gs1,dom1,tolap,1,1,1);
3183           if(!inter.IsDone()) return Standard_False; 
3184           nbl = inter.NbLines(); 
3185
3186 //  si GeomInt ne rend pas d'intersection on ne tente pas la solution de 
3187 //  rattrapage 
3188             if (nbl==0) return Standard_False;
3189         }
3190 #endif
3191         GeomAPI_ProjectPointOnCurve proj;
3192         for(Standard_Integer ilin = 1; ilin <= nbl; ilin++) {
3193           if(inter.HasLineOnS1(ilin) && inter.HasLineOnS2(ilin)) {
3194             C3d = inter.Line(ilin);
3195             Pc1 = inter.LineOnS1(ilin);
3196             Pc2 = inter.LineOnS2(ilin);
3197             gp_Pnt ptestdeb, ptestfin;
3198             Standard_Real Uf=0., Ul=0.;
3199             if (wholeCurv) {
3200               Uf = C3d->FirstParameter();
3201               Ul = C3d->LastParameter();
3202               ptestdeb = C3d->Value(Uf);
3203               ptestfin = C3d->Value(Ul);
3204             }
3205             else {
3206               // find end parameters
3207               Standard_Boolean failedF, failedL;
3208               failedF = failedL = Standard_False;
3209               proj.Init( pdeb1, C3d);
3210               if (proj.NbPoints()==0 && distrefdeb > Precision::Confusion())
3211                 proj.Perform( pdeb2 );
3212               if (proj.NbPoints()==0)
3213                 failedF = Standard_True;
3214               else
3215                 Uf = proj.LowerDistanceParameter();
3216               proj.Perform( pfin1 );
3217               if (proj.NbPoints()==0 && distreffin > Precision::Confusion())
3218                 proj.Perform( pfin2 );
3219               if (proj.NbPoints()==0) 
3220                 failedL = Standard_True;
3221               else
3222                 Ul = proj.LowerDistanceParameter();
3223
3224               if (failedF && failedL) {
3225                 Uf = C3d->FirstParameter();
3226                 Ul = C3d->LastParameter();
3227               }
3228               else if (failedF || failedL) {
3229                 // select right end parameter
3230                 Standard_Real Uok = failedF ? Ul : Uf;
3231                 Standard_Real U1 = C3d->FirstParameter(), U2 = C3d->LastParameter();
3232                 Uok = Abs(Uok-U1) > Abs(Uok-U2) ? U1 : U2;
3233                 if (failedF) Uf = Uok;
3234                 else         Ul = Uok;
3235               }
3236               else { // both projected, but where?
3237                 if (Uf == Ul) continue;
3238               }
3239               ptestdeb = C3d->Value(Uf);
3240               ptestfin = C3d->Value(Ul);
3241               if (C3d->IsPeriodic() && !(failedF && failedL)) {
3242                 // assure the same order of ends, otherwise TrimmedCurve will take
3243                 // the other part of C3d
3244                 gp_Pnt Ptmp;
3245                 gp_Vec DirOld, DirNew(ptestdeb,ptestfin);
3246                 C3d->D1(Uf, Ptmp, DirOld);
3247                 if (DirOld * DirNew < 0) {
3248                   Standard_Real Utmp = Uf; Uf = Ul; Ul = Utmp;
3249                   Ptmp = ptestdeb; ptestdeb = ptestfin; ptestfin = Ptmp;
3250                 }
3251               }
3252             }
3253             C3d = new Geom_TrimmedCurve(C3d,Uf,Ul);
3254             Pc1 = new Geom2d_TrimmedCurve(Pc1,Uf,Ul);
3255             Pc2 = new Geom2d_TrimmedCurve(Pc2,Uf,Ul);
3256             //faut il renverser ?
3257             Standard_Real distdeb = ptestdeb.Distance(pdeb);
3258             Standard_Real distfin = ptestfin.Distance(pfin);
3259             if(distdeb > distref || distfin > distref) {
3260               C3d->Reverse();
3261               Pc1->Reverse();
3262               Pc2->Reverse();
3263               ptestdeb = C3d->Value(C3d->FirstParameter());
3264               ptestfin = C3d->Value(C3d->LastParameter());
3265               distdeb = ptestdeb.Distance(pdeb);
3266               distfin = ptestfin.Distance(pfin);
3267             }
3268             if(distdeb < distref && distfin < distref) {
3269               Uf = C3d->FirstParameter();
3270               Ul = C3d->LastParameter();
3271               ChFi3d_ReparamPcurv(Uf,Ul,Pc1);
3272               ChFi3d_ReparamPcurv(Uf,Ul,Pc2);
3273               Standard_Real x,y;
3274               Pc1->Value(Uf).Coord(x,y);
3275               x = Pardeb(1) - x;
3276               y = Pardeb(2) - y;
3277               if(Abs(x) > tol2d || Abs(y) > tol2d) Pc1->Translate(gp_Vec2d(x,y));
3278               Pc2->Value(Uf).Coord(x,y);
3279               x = Pardeb(3) - x;
3280               y = Pardeb(4) - y;
3281               if(Abs(x) > tol2d || Abs(y) > tol2d) Pc2->Translate(gp_Vec2d(x,y));
3282               tolreached = ChFi3d_EvalTolReached(S1,Pc1,S2,Pc2,C3d);
3283               return Standard_True;
3284             }
3285           }
3286         }
3287       }
3288     }
3289   }
3290   
3291   // A ce stade : 
3292   // les intersections classiques ont echouees on attaque le
3293   // cheminement du desespoir.
3294 //  Standard_Real Step = 0.1;
3295   while(1) {
3296     //Attention les parametres de fleche pour le cheminement et 
3297     //de tolerance pour l'approx ne peuvent etre pris comme ceux 
3298     //du Builder, on les reestime donc comme on peut.
3299     Standard_Real fleche = 1.e-3 * pdeb.Distance(pfin);
3300     Standard_Real tolap = 1.e-7;
3301     IntPatch_ThePWalkingInter
3302       IntKK(S1,S2,tol3d,tol3d,fleche,Step);
3303     
3304     //On connait les extremites de l intersection (Pardeb,Parfin),
3305     //on essaye de trouver un point de depart franchement au
3306     //milieu pour ne pas embrouiller le cheminement.
3307     Standard_Boolean depok = Standard_False;
3308     IntSurf_PntOn2S pintdep;
3309     TColStd_Array1OfReal depart(1,4);
3310     for(Standard_Integer ipdep = 2; ipdep <= 7 && !depok; ipdep++) {
3311       Standard_Real alpha = 0.1 * ipdep;
3312       Standard_Real unmoinsalpha = 1. - alpha;
3313       depart(1) = alpha*Pardeb(1) + unmoinsalpha*Parfin(1);
3314       depart(2) = alpha*Pardeb(2) + unmoinsalpha*Parfin(2);
3315       depart(3) = alpha*Pardeb(3) + unmoinsalpha*Parfin(3);
3316       depart(4) = alpha*Pardeb(4) + unmoinsalpha*Parfin(4);
3317       depok = IntKK.PerformFirstPoint(depart,pintdep);
3318     } 
3319     if(!depok) {
3320       return Standard_False;
3321     }
3322     pintdep.Parameters(depart(1),depart(2),depart(3),depart(4));
3323     IntKK.Perform(depart);
3324     if (!IntKK.IsDone()) return Standard_False;
3325     if (IntKK.NbPoints() <= 30) {
3326       Step *= 0.5;
3327       if (Step <= 0.0001) {
3328         return Standard_False;
3329       }
3330     }
3331     else{
3332       // A ce stade on a une LineOn2S presentable, on la tronque entre les 
3333       // points les plus proches des extremites connues on en fait une 
3334       // WLine et on lance l approx.
3335       // On retouche ensuite le resultat pour avoir les bons points debut 
3336       // et fin.
3337       const Handle(IntSurf_LineOn2S)& L2S = IntKK.Line();
3338       
3339       gp_Pnt codeb1 = S1->Value(Pardeb(1),Pardeb(2));
3340       gp_Pnt codeb2 = S2->Value(Pardeb(3),Pardeb(4));
3341       Standard_Real tol1 = Max(codeb1.Distance(codeb2),tol3d);
3342       Standard_Boolean bondeb = (tol1 == tol3d); 
3343       gp_Pnt pntd(0.5*(codeb1.Coord() + codeb2.Coord()));
3344       
3345       gp_Pnt cofin1 = S1->Value(Parfin(1),Parfin(2));
3346       gp_Pnt cofin2 = S2->Value(Parfin(3),Parfin(4));
3347       Standard_Real tol2 = Max(cofin1.Distance(cofin2),tol3d);
3348       Standard_Boolean bonfin = (tol2 == tol3d); 
3349       gp_Pnt pntf(0.5*(cofin1.Coord() + cofin2.Coord()));
3350       
3351       Standard_Integer nbp = L2S->NbPoints(), i;
3352       Standard_Real ddeb = Precision::Infinite(); 
3353       Standard_Real dfin = Precision::Infinite();
3354       Standard_Real dd;
3355       Standard_Integer indd = 0, indf = 0;
3356       for(i = 1; i <= nbp; i++) {
3357         dd = L2S->Value(i).Value().Distance(pntd);
3358         if(dd < ddeb) { ddeb = dd; indd = i;}
3359         dd = L2S->Value(i).Value().Distance(pntf);
3360         if(dd < dfin) { dfin = dd; indf = i;}
3361       }
3362       if(indd > indf) {
3363         L2S->Reverse();
3364         indd = nbp - indd + 1;
3365         indf = nbp - indf + 1;
3366       }
3367       for (i = 1; i < indd; i++) { L2S->RemovePoint(1); nbp--; indf--; }
3368       for (i = indf + 1; i <= nbp; i++) { L2S->RemovePoint(indf + 1); }
3369       nbp = indf;
3370       if(nbp==1) return Standard_False;
3371       //On insere les extremites dans la ligne si les points extremites de
3372       //celle-ci en sont trop eloignes et si pardeb et parfin sont bons.
3373       if(ddeb >= tol3d && bondeb) {
3374         IntSurf_PntOn2S p1 = L2S->Value(1);
3375         IntSurf_PntOn2S p2 = L2S->Value(2);
3376          
3377         gp_Vec v1(pntd,p1.Value());
3378         gp_Vec v2(p1.Value(),p2.Value());
3379         gp_Vec v3(pntd,p2.Value());
3380         p1.SetValue(pntd,Pardeb(1),Pardeb(2),Pardeb(3),Pardeb(4));
3381         if(v1.Dot(v3) < 0) {
3382           if(v3.Magnitude() < 0.2*v2.Magnitude()) {
3383             L2S->RemovePoint(1);
3384             nbp--;
3385           }
3386           L2S->Value(1,p1);
3387         }
3388         else if(v1.Magnitude() > 0.2*v2.Magnitude()) {
3389           L2S->InsertBefore(1,p1);
3390           nbp++;
3391         }
3392         else{
3393           L2S->Value(1,p1);
3394         }
3395         ddeb = 0.;
3396       }
3397       if(dfin >= tol3d && bonfin) {
3398         IntSurf_PntOn2S p1 = L2S->Value(nbp);
3399         IntSurf_PntOn2S p2 = L2S->Value(nbp - 1);
3400         gp_Vec v1(pntf,p1.Value());
3401         gp_Vec v2(p1.Value(),p2.Value());
3402         gp_Vec v3(pntf,p2.Value());
3403         p1.SetValue(pntf,Parfin(1),Parfin(2),Parfin(3),Parfin(4));
3404         if(v1.Dot(v3) < 0) {
3405           if(v3.Magnitude() < 0.2*v2.Magnitude()) {
3406             L2S->RemovePoint(nbp);
3407             nbp--;
3408           }
3409           L2S->Value(nbp,p1);
3410         }
3411         else if(v1.Magnitude() > 0.2*v2.Magnitude()) {
3412           L2S->Add(p1);
3413           nbp++;
3414         }
3415         else{
3416           L2S->Value(nbp,p1);
3417         }
3418         dfin = 0.;
3419       }      
3420       //
3421       Handle(IntPatch_WLine)    WL = new IntPatch_WLine(L2S,Standard_False);
3422       
3423       GeomInt_WLApprox approx;
3424       approx.SetParameters(tolap,tol2d,4,8,0,1);
3425       // gerer ici les approx inutiles sur les plans!!!!!!!!!!!
3426       approx.Perform(S1,S2,WL,
3427                      Standard_True,Standard_True,Standard_True,
3428                      1,nbp);
3429       if(!approx.IsDone()) return Standard_False;
3430 //      tolreached = approx.TolReached3d();
3431 //      Standard_Real tolr2d = approx.TolReached2d();
3432 //      tolreached = Max(tolreached,ChFi3d_ConvTol2dToTol3d(S1,tolr2d));
3433 //      tolreached = Max(tolreached,ChFi3d_ConvTol2dToTol3d(S2,tolr2d));
3434       const AppParCurves_MultiBSpCurve& mbs = approx.Value(1);
3435       Standard_Integer nbpol = mbs.NbPoles();
3436       TColgp_Array1OfPnt pol3d(1,nbpol);
3437       mbs.Curve(1,pol3d);
3438       TColgp_Array1OfPnt2d pol2d1(1,nbpol);
3439       mbs.Curve(2,pol2d1);
3440       TColgp_Array1OfPnt2d pol2d2(1,nbpol);
3441       mbs.Curve(3,pol2d2);
3442       // On recale les extremites de l intersection sur les points connus.
3443       if(ddeb >= tol1) {
3444         pol3d(1) = pntd;
3445         pol2d1(1).SetCoord(Pardeb(1),Pardeb(2));
3446         pol2d2(1).SetCoord(Pardeb(3),Pardeb(4));
3447 //      tolreached = Max(tolreached,ddeb);
3448       }
3449       
3450       if(dfin >= tol2) {
3451         pol3d(nbpol) = pntf;
3452         pol2d1(nbpol).SetCoord(Parfin(1),Parfin(2));
3453         pol2d2(nbpol).SetCoord(Parfin(3),Parfin(4));
3454 //      tolreached = Max(tolreached,dfin);
3455       }
3456       const TColStd_Array1OfReal& knots = mbs.Knots();
3457       const TColStd_Array1OfInteger& mults = mbs.Multiplicities();
3458       Standard_Integer deg = mbs.Degree();
3459       C3d = new Geom_BSplineCurve(pol3d,knots,mults,deg);
3460       Pc1 = new Geom2d_BSplineCurve(pol2d1,knots,mults,deg);
3461       Pc2 = new Geom2d_BSplineCurve(pol2d2,knots,mults,deg);
3462       tolreached = ChFi3d_EvalTolReached(S1,Pc1,S2,Pc2,C3d);
3463       return Standard_True;
3464     }
3465   }
3466 }
3467
3468 //=======================================================================
3469 //function : IntCS
3470 //purpose  : Calcul rapide de l intersection courbe surface.
3471 //
3472 //=======================================================================
3473
3474 Standard_Boolean ChFi3d_IntCS(Handle(Adaptor3d_HSurface)& S,
3475                               Handle(Adaptor3d_HCurve)& C,
3476                               gp_Pnt2d& p2dS,
3477                               Standard_Real& wc)
3478 {
3479   IntCurveSurface_HInter Intersection;
3480   
3481   Standard_Real uf = C->FirstParameter(), ul = C->LastParameter();
3482   Standard_Real u1 = S->FirstUParameter(), u2 = S->LastUParameter();
3483   Standard_Real v1 = S->FirstVParameter(), v2 = S->LastVParameter();
3484   IntCurveSurface_IntersectionPoint pint;
3485   Intersection.Perform(C,S);
3486   Standard_Boolean keepfirst = (wc < -1.e100), keeplast = (wc > 1.e100);
3487   Standard_Real temp = 0.;
3488   if(keepfirst) temp = 1.e100;
3489   if(keeplast) temp = -1.e100;
3490   Standard_Real dist = 2.e100;
3491   if(Intersection.IsDone()) {
3492     Standard_Integer nbp = Intersection.NbPoints(),i,isol = 0;
3493     for (i = 1; i <= nbp; i++) {
3494       pint = Intersection.Point(i);
3495       Standard_Real up = pint.U();
3496       Standard_Real vp = pint.V();
3497       if(S->IsUPeriodic()) up = ChFi3d_InPeriod(up,u1,u1+S->UPeriod(),1.e-8);
3498       if(S->IsVPeriodic()) vp = ChFi3d_InPeriod(vp,v1,v1+S->VPeriod(),1.e-8);
3499       if(uf <= pint.W() && ul >= pint.W() &&
3500          u1 <= up && u2 >= up &&
3501          v1 <= vp && v2 >= vp) {
3502         if(keepfirst && pint.W() < temp) {
3503           temp = pint.W();
3504           isol = i;
3505         }
3506         else if(keeplast && pint.W() > temp) {
3507           temp = pint.W();
3508           isol = i;
3509         }
3510         else if(Abs(pint.W() - wc) < dist) {
3511           dist = Abs(pint.W() - wc);
3512           isol = i;
3513         }
3514       }
3515     }
3516     if(isol == 0) return Standard_False;
3517     pint = Intersection.Point(isol);
3518     Standard_Real up = pint.U();
3519     Standard_Real vp = pint.V();
3520     if(S->IsUPeriodic()) up = ChFi3d_InPeriod(up,u1,u1+S->UPeriod(),1.e-8);
3521     if(S->IsVPeriodic()) vp = ChFi3d_InPeriod(vp,v1,v1+S->VPeriod(),1.e-8);
3522     p2dS.SetCoord(up,vp);
3523     wc = pint.W();
3524     return Standard_True;
3525   }
3526   return Standard_False;
3527 }
3528
3529 //=======================================================================
3530 //function : ComputesIntPC
3531 //purpose  : Intersection de deux PCurves de type FaceInterference
3532 //           les parametres sur les pcurves du point solution sont 
3533 //           UInt1,UInt2
3534 //=======================================================================
3535
3536 void ChFi3d_ComputesIntPC (const ChFiDS_FaceInterference&      Fi1,
3537                            const ChFiDS_FaceInterference&      Fi2,
3538                            const Handle(GeomAdaptor_HSurface)& HS1,
3539                            const Handle(GeomAdaptor_HSurface)& HS2,
3540                            Standard_Real&                      UInt1, 
3541                            Standard_Real&                      UInt2)
3542 {
3543   gp_Pnt bid;
3544   ChFi3d_ComputesIntPC(Fi1,Fi2,HS1,HS2,UInt1,UInt2,bid);
3545 }
3546
3547 //=======================================================================
3548 //function : ChFi3d_ComputesIntPC
3549 //purpose  : 
3550 //=======================================================================
3551 void ChFi3d_ComputesIntPC (const ChFiDS_FaceInterference&      Fi1,
3552                            const ChFiDS_FaceInterference&      Fi2,
3553                            const Handle(GeomAdaptor_HSurface)& HS1,
3554                            const Handle(GeomAdaptor_HSurface)& HS2,
3555                            Standard_Real&                      UInt1, 
3556                            Standard_Real&                      UInt2,
3557                            gp_Pnt&                             P)
3558 {    
3559   // Une seule intersection a realiser, on prend tout de meme
3560   // le soin de valider les extremites par un extrema c3d/c3d
3561   // realise sur les pcurveonsurf des conges.
3562   
3563   Standard_Real x,y,distref2;
3564   Fi1.PCurveOnSurf()->Value(UInt1).Coord(x,y);
3565   gp_Pnt p3d1 = HS1->Value(x,y);
3566   Fi2.PCurveOnSurf()->Value(UInt2).Coord(x,y);
3567   gp_Pnt p3d2 = HS2->Value(x,y);
3568   distref2 = p3d1.SquareDistance(p3d2);
3569   P.SetXYZ(0.5*(p3d1.XYZ() + p3d2.XYZ()));
3570   // recalcul de l'extrema
3571   Standard_Real delt1 = 
3572     Min(0.1,0.05*(Fi1.LastParameter() - Fi1.FirstParameter()));
3573   Handle(Geom2dAdaptor_HCurve) hc2d1 = 
3574     new Geom2dAdaptor_HCurve(Fi1.PCurveOnSurf(),UInt1-delt1,UInt1+delt1);
3575   Adaptor3d_CurveOnSurface cons1(hc2d1,HS1);
3576   Standard_Real delt2 = 
3577     Min(0.1,0.05*(Fi2.LastParameter() - Fi2.FirstParameter()));
3578   Handle(Geom2dAdaptor_HCurve) hc2d2 = 
3579     new Geom2dAdaptor_HCurve(Fi2.PCurveOnSurf(),UInt2-delt2,UInt2+delt2);
3580   Adaptor3d_CurveOnSurface cons2(hc2d2,HS2);
3581   Extrema_LocateExtCC ext(cons1,cons2,UInt1,UInt2);
3582   if(ext.IsDone()) {
3583     Standard_Real dist2 = ext.SquareDistance();
3584     if(dist2<distref2) {
3585       Extrema_POnCurv ponc1,ponc2;
3586       ext.Point(ponc1,ponc2);
3587       UInt1 = ponc1.Parameter();
3588       UInt2 = ponc2.Parameter();
3589       gp_Pnt Pnt1 = ponc1.Value();
3590       gp_Pnt Pnt2 = ponc2.Value();
3591       P.SetXYZ(0.5*(Pnt1.XYZ() + Pnt2.XYZ()));
3592     }
3593   }
3594
3595
3596 //=======================================================================
3597 //function : BoundSurf
3598 //purpose  : computes a GeomAdaptor_Surface from the surface of the 
3599 //           SurfData Fd1 and trims it to allow the intersection computation
3600
3601 //=======================================================================
3602 Handle(GeomAdaptor_HSurface) ChFi3d_BoundSurf(TopOpeBRepDS_DataStructure&    DStr,
3603                                               const Handle(ChFiDS_SurfData)& Fd1,
3604                                               const Standard_Integer&        IFaCo1,
3605                                               const Standard_Integer&        IFaArc1)
3606 {
3607   //rmq : comme en fait les 2 interferences de Fd1 ne servent qu'a donner les 
3608   //      bornes, les indices  IFaCo1 et IFaArc1 sont inutiles.
3609   //      On les garde ici en option au cas ou il faudrait borner de facon plus
3610   //      restrictive (avec des points d'intersection en argument en plus).
3611   
3612   Handle(GeomAdaptor_HSurface) HS1 = new GeomAdaptor_HSurface();
3613   GeomAdaptor_Surface& S1 = HS1->ChangeSurface();
3614   S1.Load(DStr.Surface(Fd1->Surf()).Surface());
3615   
3616   if ((IFaCo1 == 0)||(IFaArc1 == 0)) 
3617     return HS1;
3618   
3619   const ChFiDS_FaceInterference& FiCo1 = Fd1->Interference(IFaCo1);
3620   const ChFiDS_FaceInterference& FiArc1 = Fd1->Interference(IFaArc1);
3621   
3622   Standard_Real Du,Dv,mu,Mu,mv,Mv;
3623   gp_Pnt2d UVf1,UVf2,UVl1,UVl2;
3624   
3625   UVf1 = FiCo1.PCurveOnSurf()->Value(FiCo1.FirstParameter());
3626   UVl1 = FiCo1.PCurveOnSurf()->Value(FiCo1.LastParameter());
3627   UVf2 = FiArc1.PCurveOnSurf()->Value(FiArc1.FirstParameter());
3628   UVl2 = FiArc1.PCurveOnSurf()->Value(FiArc1.LastParameter());
3629   ChFi3d_Boite(UVf1,UVf2,UVl1,UVl2,Du,Dv,mu,Mu,mv,Mv);
3630   GeomAbs_SurfaceType styp = S1.GetType();
3631   if (styp == GeomAbs_Cylinder) { 
3632     Dv = Max(0.5*Dv,4.*S1.Cylinder().Radius());
3633     Du = 0.;
3634     S1.Load(DStr.Surface(Fd1->Surf()).Surface(),
3635             mu,Mu,mv-Dv,Mv+Dv);
3636   }
3637   //Dans le cas d'un tore ou cone, il ne faut pas que l'agrandissement des bounds engendrent une surface avec une periode plus grande que 2PI. lvt
3638   else if (styp == GeomAbs_Torus ||
3639            styp == GeomAbs_Cone) {
3640     Du = Min(PI-0.5*Du,0.1*Du);
3641     Dv = 0.;
3642     S1.Load(DStr.Surface(Fd1->Surf()).Surface(),
3643             mu-Du,Mu+Du,mv,Mv);
3644   }
3645   else if (styp == GeomAbs_Plane) {
3646     Du = Max(0.5*Du,4.*Dv);
3647     Dv = 0.;
3648     S1.Load(DStr.Surface(Fd1->Surf()).Surface(),
3649             mu-Du,Mu+Du,mv,Mv);
3650   }
3651   return HS1;
3652 }
3653 //=======================================================================
3654 //function : SearchPivot
3655 //purpose  : 
3656 //=======================================================================
3657 Standard_Integer ChFi3d_SearchPivot(Standard_Integer* s,
3658                                     Standard_Real u[3][3],
3659                                     const Standard_Real t)
3660 {
3661   //Cette fonction recherche comme pivot une cd dont les sections 
3662   //ne se croisent pas sur la face opposee. 
3663   //         - il y aura peut etre des cas suffisamment asymetriques
3664   //           pour qu aucun des trois conges ne convienne!! A VOIR.
3665   //         - dans le cas ou plusieurs conviennent on prend le 
3666   //           premier qui n est pas forcement le meilleur, prevoir 
3667   //           d affiner cela en comparant les parametres sur les
3668   //           lignes guide et (/ou) les rayons.
3669   
3670   Standard_Boolean bondeb,bonfin;
3671   for(Standard_Integer i = 0; i <= 2; i++) {
3672     if(s[(i+1)%3] == 1) {bondeb = (u[(i+1)%3][i]-u[(i+1)%3][(i+2)%3] >= -t);}
3673     else {bondeb = (u[(i+1)%3][i]-u[(i+1)%3][(i+2)%3] <= t);}
3674     if(s[(i+2)%3] == 1) {bonfin = (u[(i+2)%3][i]-u[(i+2)%3][(i+1)%3] >= -t);}
3675     else {bonfin = (u[(i+2)%3][i]-u[(i+2)%3][(i+1)%3] <= t);}
3676     if (bondeb && bonfin) { return i; }
3677   }
3678   return -1;
3679 }
3680
3681
3682
3683 //=======================================================================
3684 //function : SearchFD
3685 //purpose  : 
3686 //=======================================================================
3687 Standard_Boolean ChFi3d_SearchFD(TopOpeBRepDS_DataStructure& DStr,
3688                                  const Handle(ChFiDS_Stripe)& cd1, 
3689                                  const Handle(ChFiDS_Stripe)& cd2,
3690                                  const Standard_Integer sens1,
3691                                  const Standard_Integer sens2,
3692                                  Standard_Integer& i1,
3693                                  Standard_Integer& i2,
3694                                  Standard_Real& p1,
3695                                  Standard_Real& p2,
3696                                  const Standard_Integer ind1,
3697                                  const Standard_Integer ind2,
3698                                  TopoDS_Face& face,
3699                                  Standard_Boolean& sameside,
3700                                  Standard_Integer& jf1,
3701                                  Standard_Integer& jf2)
3702 {
3703   Standard_Boolean found = Standard_False;
3704   Standard_Integer id1 = ind1, id2 = ind2;
3705   Standard_Integer if1 = ind1, if2 = ind2;
3706   Standard_Integer l1 = cd1->SetOfSurfData()->Length();
3707   Standard_Integer l2 = cd2->SetOfSurfData()->Length();
3708   Standard_Integer i;
3709   Standard_Boolean fini1 = Standard_False, fini2 = Standard_False;
3710   Standard_Boolean visavis,visavisok = Standard_False;
3711   TopoDS_Vertex Vtx;
3712   while( !found ) {
3713     for(i = id1; (i*sens1) <= (if1*sens1) && !found && !fini2; i = i+sens1 ) { 
3714       if(ChFi3d_IsInFront(DStr,cd1,cd2,i,if2,sens1,sens2,p1,p2,face,sameside,jf1,jf2,visavis,Vtx,Standard_False,0)) {
3715         i1 = i;
3716         i2 = if2;
3717         found = Standard_True;
3718       }
3719       else if (visavis && !visavisok) {
3720         visavisok = Standard_True;
3721         i1 = i;
3722         i2 = if2;
3723       }
3724     }
3725     if(!fini1) {
3726       if1 = if1 + sens1;
3727       if(if1 < 1 || if1 > l1) { if1 = if1 - sens1; fini1 = Standard_True; }
3728     }
3729     
3730     for(i = id2; (i*sens2) <= (if2*sens2) && !found && !fini1; i = i+sens2 ) { 
3731       if(ChFi3d_IsInFront(DStr,cd1,cd2,if1,i,sens1,sens2,p1,p2,face,sameside,jf1,jf2,visavis,Vtx,Standard_False,0)) {
3732         i1 = if1;
3733         i2 = i;
3734         found = Standard_True;
3735       }
3736       else if (visavis && !visavisok) {
3737         visavisok = Standard_True;
3738         i1 = if1;
3739         i2 = i;
3740       }
3741     }
3742     if(!fini2) {
3743       if2 = if2 + sens2;
3744       if(if2 < 1 || if2 > l2) { if2 = if2 - sens2; fini2 = Standard_True; }
3745     }
3746     if(fini1 && fini2) break;
3747   }
3748   return found;
3749 }
3750
3751 //=======================================================================
3752 //function : Parameters
3753 //purpose  : compute the parameters <u> and <v> of the 3d point <p3d> 
3754 //           on the surface <S> if it's an analytic surface
3755 //=======================================================================
3756
3757 void ChFi3d_Parameters(const Handle(Geom_Surface)& S,
3758                        const gp_Pnt& p3d,
3759                        Standard_Real& u,
3760                        Standard_Real& v)
3761 {
3762   GeomAdaptor_Surface gas(S);
3763   switch ( gas.GetType() ) {
3764   case GeomAbs_Plane :
3765     ElSLib::Parameters(gas.Plane(),p3d,u,v);
3766     break;
3767   case GeomAbs_Cylinder :
3768     ElSLib::Parameters(gas.Cylinder(),p3d,u,v);
3769     break;
3770   case GeomAbs_Cone :
3771     ElSLib::Parameters(gas.Cone(),p3d,u,v);
3772     break;
3773   case GeomAbs_Sphere :
3774     ElSLib::Parameters(gas.Sphere(),p3d,u,v);
3775     break;
3776   case GeomAbs_Torus :
3777     ElSLib::Parameters(gas.Torus(),p3d,u,v);
3778     break;
3779   case GeomAbs_BezierSurface :
3780   case GeomAbs_BSplineSurface :  
3781   default :
3782     {
3783       GeomAPI_ProjectPointOnSurf tool(p3d,S);
3784       if ( tool.NbPoints() != 1 )
3785         StdFail_NotDone::Raise("");
3786       else
3787         tool.Parameters(1,u,v);
3788     }
3789   }
3790 }
3791
3792 //=======================================================================
3793 //function : TrimCurve
3794 //purpose  : trims the curve <gc> between the points <FirstP> and
3795 //           <LastP>. The trimmed curve is <gtc>
3796 //=======================================================================
3797
3798 void ChFi3d_TrimCurve(const Handle(Geom_Curve)& gc,
3799                       const gp_Pnt& FirstP,
3800                       const gp_Pnt& LastP,
3801                       Handle(Geom_TrimmedCurve)& gtc)
3802 {
3803   Standard_Real uf = 0.,ul = 0.;
3804   GeomAdaptor_Curve gac(gc);
3805   switch ( gac.GetType() ) {
3806   case GeomAbs_Line :
3807     {
3808       uf = ElCLib::Parameter(gac.Line(),FirstP);
3809       ul = ElCLib::Parameter(gac.Line(),LastP);
3810     }
3811     break;
3812   case GeomAbs_Circle :
3813     {
3814       uf = ElCLib::Parameter(gac.Circle(),FirstP);
3815       ul = ElCLib::Parameter(gac.Circle(),LastP);
3816     }
3817     break;
3818   case GeomAbs_Ellipse :
3819     {
3820       uf = ElCLib::Parameter(gac.Ellipse(),FirstP);
3821       ul = ElCLib::Parameter(gac.Ellipse(),LastP);
3822     }
3823     break;
3824   case GeomAbs_Hyperbola :
3825     {
3826       uf = ElCLib::Parameter(gac.Hyperbola(),FirstP);
3827       ul = ElCLib::Parameter(gac.Hyperbola(),LastP);
3828     }
3829     break;
3830   case GeomAbs_Parabola :
3831     {
3832       uf = ElCLib::Parameter(gac.Parabola(),FirstP);
3833       ul = ElCLib::Parameter(gac.Parabola(),LastP);
3834     }
3835     break;
3836   default :
3837     {
3838     GeomAPI_ProjectPointOnCurve tool(FirstP,gc);
3839     if ( tool.NbPoints() != 1 )
3840       StdFail_NotDone::Raise("");
3841     else
3842       uf = tool.Parameter(1);
3843     tool.Init(LastP,gc);
3844     if ( tool.NbPoints() != 1 )
3845       StdFail_NotDone::Raise("");
3846     else
3847       ul = tool.Parameter(1);
3848   }
3849   }
3850   gtc = new Geom_TrimmedCurve(gc,uf,ul);
3851 }
3852
3853
3854
3855 //=======================================================================
3856 //function : GoodExt
3857 //purpose  : 
3858 //=======================================================================
3859 static Standard_Boolean GoodExt(const Handle(Geom_Curve)& C,
3860                                 const gp_Vec&             V,
3861                                 const Standard_Real       f,
3862                                 const Standard_Real       l,
3863                                 const Standard_Real       a)
3864 {
3865   for(Standard_Integer i = 0; i < 6; i++) {
3866     gp_Pnt d0; gp_Vec d1;
3867     const Standard_Real t = i * 0.2;
3868     C->D1(((1-t)*f+t*l),d0,d1);
3869     const Standard_Real ang = d1.Angle(V);
3870     const Standard_Real angref = a*t + 0.002;
3871     if(ang > angref) return Standard_False;
3872   }
3873   return Standard_True;
3874 }
3875 //=======================================================================
3876 //function : PerformElSpine
3877 //purpose  : 
3878 //=======================================================================
3879 Standard_EXPORT 
3880   void ChFi3d_PerformElSpine(Handle(ChFiDS_HElSpine)& HES,
3881                              Handle(ChFiDS_Spine)&    Spine,
3882                              const GeomAbs_Shape      continuity,
3883                              const Standard_Real      tol) 
3884 {
3885   
3886   Standard_Boolean periodic, Bof, checkdeb, cepadur,bIsSmooth;
3887   Standard_Integer IEdge,IF,IL,nbed, iToApproxByC2;
3888   Standard_Real WF, WL, Wrefdeb, Wreffin,nwf,nwl,period,pared,tolpared;
3889   Standard_Real First, Last, epsV, urefdeb, tolrac;
3890   GeomAbs_Shape aContinuity;
3891   gp_Pnt PDeb, PFin, Bout;
3892   gp_Vec VrefDeb, VrefFin;
3893   Handle(Geom_Curve) Cv;
3894   Handle(Geom_BoundedCurve) TC;
3895   Handle(Geom_BSplineCurve) BS, BSpline;
3896   TopoDS_Edge E, Eold;
3897   TopoDS_Vertex V;
3898     //
3899   ChFiDS_ElSpine& ES = HES->ChangeCurve();
3900   WF = ES.FirstParameter();
3901   WL = ES.LastParameter();
3902   Wrefdeb = WF;
3903   Wreffin = WL;
3904   nwf = WF;
3905   nwl = WL;
3906   nbed = Spine->NbEdges();
3907   periodic = Spine->IsPeriodic();
3908   if(periodic) {
3909     period = Spine->Period();
3910     nwf = ElCLib::InPeriod(WF,-tol,period-tol);
3911     IF = Spine->Index(nwf,1);
3912     nwl = ElCLib::InPeriod(WL,tol,period+tol);
3913     IL = Spine->Index(nwl,0);
3914     if(nwl<nwf+tol) IL += nbed;
3915   }
3916   else{
3917     IF = Spine->Index(WF,1);
3918     IL = Spine->Index(WL,0);
3919     Wrefdeb = Max(Spine->FirstParameter(IF),WF);
3920     Wreffin = Min(Spine->LastParameter(IL),WL);
3921   }
3922   //
3923   Spine->D1(WF,PDeb,VrefDeb);
3924   Spine->D1(WL,PFin,VrefFin);
3925   VrefDeb.Normalize();
3926   VrefFin.Normalize();
3927   //
3928   TColgp_Array1OfPnt ExtrapPole(1, 5);
3929   TColgp_Array1OfPnt ExtraCoeffs(1, 5);
3930   TColgp_Array1OfXYZ Cont(1,5);
3931   // Attention on segmente eventuellement la premiere et la
3932   // derniere arete.
3933   // Traitment de la premiere arete
3934   cepadur = 0;
3935   E=Spine->Edges(IF);
3936   Bof=BRepLib::BuildCurve3d(E);
3937   const BRepAdaptor_Curve& edc = Spine->CurrentElementarySpine(IF);
3938   tolpared = edc.Resolution(tol);
3939   Cv = BRep_Tool::Curve(E, First, Last);
3940   urefdeb = Spine->FirstParameter(IF);
3941   checkdeb = (nwf > urefdeb);
3942   if(checkdeb) {
3943     Spine->Parameter(IF,nwf,pared,0);
3944   }
3945   //
3946   if(E.Orientation() == TopAbs_REVERSED) {
3947     Standard_Real sov = First;
3948     First = Cv->ReversedParameter(Last);
3949     Last = Cv->ReversedParameter(sov);
3950     if(checkdeb) {
3951       pared = Cv->ReversedParameter(pared);
3952     }
3953     else{
3954       pared = First;
3955     }
3956     if(First < pared) {
3957       First = pared; 
3958     }
3959     if(IL == IF) {
3960       Standard_Real ureffin = Spine->LastParameter(IL);
3961       Standard_Boolean checkfin = (nwl < ureffin);
3962       if(checkfin) {
3963         Spine->Parameter(IL,nwl,pared,0);
3964         pared = Cv->ReversedParameter(pared);
3965       }
3966       else {
3967         pared = Last;
3968       }
3969       if(pared < Last) {
3970         Last = pared; 
3971       }
3972     }
3973     Cv = Cv->Reversed();
3974   }//if(E.Orientation() == TopAbs_REVERSED) 
3975   else {//#1
3976     if(!checkdeb) {
3977       pared = First;
3978     }
3979     if(First < pared) {
3980       First = pared; 
3981     }
3982     if(IL == IF) {
3983       Standard_Real ureffin = Spine->LastParameter(IL);
3984       Standard_Boolean checkfin = (nwl < ureffin);
3985       if(checkfin) {
3986         Spine->Parameter(IL,nwl,pared,0);
3987       }
3988       else {
3989         pared = Last;
3990       }
3991       if(pared < Last) {
3992         Last = pared; 
3993       }
3994     }
3995   }// else {//#1
3996   //
3997   if(Abs(Last-First) < tolpared) {
3998     cepadur = 1;
3999   }
4000   //
4001   //Petite veru pour les cas ou un KPart a bouffe l arete
4002   //sans parvenir a terminer. On tire une droite.
4003   if(cepadur) {
4004     Handle(Geom_Line) L;
4005     gp_Pnt ptemp; gp_Vec vtemp;
4006     if(WL < Spine->FirstParameter(1) + tol) {
4007       ES.LastPointAndTgt(ptemp,vtemp);
4008       gp_Dir d(vtemp);
4009       gp_Pnt olin;
4010       olin.ChangeCoord().SetLinearForm(-WL,d.XYZ(),PFin.XYZ());
4011       L = new Geom_Line(olin,d);
4012       ES.SetCurve(L);
4013     }
4014     else if(WF > Spine->LastParameter(nbed) - tol) {
4015       ES.FirstPointAndTgt(ptemp,vtemp);
4016       gp_Dir d(vtemp);
4017       gp_Pnt olin;
4018       olin.ChangeCoord().SetLinearForm(-WF,d.XYZ(),PDeb.XYZ());
4019       L = new Geom_Line(olin,d);
4020       ES.SetCurve(L);
4021     }
4022     return;// => 
4023   }
4024   //
4025   TC = new (Geom_TrimmedCurve)(Cv, First, Last);
4026   BS=GeomConvert::CurveToBSplineCurve(TC);
4027   CurveCleaner(BS, Abs(WL-WF)*1.e-4, 0);
4028   //
4029   //Smoothing of the curve
4030   iToApproxByC2=0;
4031   aContinuity=TC->Continuity();
4032   bIsSmooth=ChFi3d_IsSmooth(TC);
4033   if (aContinuity < GeomAbs_C2 && !bIsSmooth) {
4034     ++iToApproxByC2;
4035     BS = ChFi3d_ApproxByC2(TC);
4036     TC=BS;
4037   }
4038   //
4039   //  Concatenation des aretes suivantes
4040   GeomConvert_CompCurveToBSplineCurve Concat( TC, Convert_QuasiAngular );
4041   //
4042   Eold = E;
4043   for (IEdge=IF+1; IEdge<=IL; ++IEdge) {
4044     Standard_Integer iloc = IEdge;
4045     if(periodic) {
4046       iloc = (IEdge - 1)%nbed + 1;
4047     }
4048     //
4049     E = Spine->Edges(iloc);
4050     if (BRep_Tool::Degenerated(E)) {
4051       continue;
4052     }
4053     //  
4054     epsV = tol;
4055     Bof = TopExp::CommonVertex(Eold, E, V);
4056     if (Bof) {
4057       epsV = BRep_Tool::Tolerance(V);
4058     }
4059     //
4060     Bof = BRepLib::BuildCurve3d(E);
4061     if (!Bof) {
4062       Standard_ConstructionError::Raise("PerformElSpine : BuildCurve3d error");
4063     }
4064     //
4065     Cv = BRep_Tool::Curve(E, First, Last);
4066     if(IEdge == IL) {
4067       Standard_Real ureffin = Spine->LastParameter(iloc);
4068       Standard_Boolean checkfin = (nwl < ureffin);
4069       if(checkfin) {
4070         Spine->Parameter(iloc,nwl,pared,0);
4071       }
4072       else {
4073         pared = Last;
4074       }
4075       if(E.Orientation() == TopAbs_REVERSED) {
4076         Standard_Real sov = First;
4077         First = Cv->ReversedParameter(Last);
4078         Last = Cv->ReversedParameter(sov);
4079         if(checkfin) {
4080           pared = Cv->ReversedParameter(pared);
4081         }
4082         else{
4083           pared = Last;
4084         }
4085         Cv = Cv->Reversed();
4086       }
4087       if(pared < Last) {
4088         Last = pared; 
4089       }
4090     }
4091     //
4092     TC = new (Geom_TrimmedCurve)(Cv, First, Last);
4093     BS = GeomConvert::CurveToBSplineCurve(TC);
4094     CurveCleaner(BS, Abs(WL-WF)*1.e-4, 0);
4095     //
4096     //Smoothing of the curve
4097     aContinuity=TC->Continuity();
4098     bIsSmooth=ChFi3d_IsSmooth(TC);
4099     if (aContinuity < GeomAbs_C2 && !bIsSmooth) {
4100       ++iToApproxByC2;
4101       BS = ChFi3d_ApproxByC2( TC );
4102       TC = BS;
4103     }
4104     //
4105     tolrac = Min(tol, epsV);
4106     Bof = Concat.Add( TC, 2.*tolrac, Standard_True );
4107     // si l'ajout ne s'est pas bien passe on essai d'augmenter la tolerance
4108     if (!Bof) {
4109       Bof = Concat.Add( TC, 2.*epsV, Standard_True );
4110     }
4111     if (!Bof) {
4112       Bof = Concat.Add( TC, 200.*epsV, Standard_True );
4113       if (!Bof) {
4114         Standard_ConstructionError::Raise("PerformElSpine: spine merged error");
4115         }
4116     }
4117     Eold = E;
4118   }// for (IEdge=IF+1; IEdge<=IL; ++IEdge) {
4119   //
4120   // On a la portion d elspine calculee sans prolongements sur la partie 
4121   // valide des aretes du chemin.
4122   BSpline = Concat.BSplineCurve();
4123   // On reparametre ici pour coller au mieux a l abscisse des aretes.
4124   TColStd_Array1OfReal BSNoeuds (1, BSpline->NbKnots());
4125   BSpline->Knots(BSNoeuds);
4126   BSplCLib::Reparametrize (Wrefdeb, Wreffin, BSNoeuds);
4127   BSpline->SetKnots(BSNoeuds);
4128   //
4129   // Traitement des Extremites
4130   Standard_Integer caredeb, carefin;
4131   Standard_Real LocalWL, LocalWF, Angle;
4132   GeomAdaptor_Curve gacurve;
4133   Handle(Geom_BSplineCurve) newc;
4134   //
4135   caredeb = 0;
4136   carefin = 0;
4137   Angle = PI*0.75;
4138   LocalWL = WL;
4139   LocalWF = WF;
4140   if (!ES.IsPeriodic() && !PDeb.IsEqual(BSpline->Pole(1), tol) ) {
4141     // Prolongement C3 au debut
4142     // afin d'eviter des pts d'inflexions dans la partie utile de la
4143     // spine le prolongement se fait jusqu'a un point eloigne.
4144     if(BSpline->IsRational()) {
4145       caredeb = 1;
4146     }
4147     //
4148     Standard_Real rabdist = Wrefdeb - WF;
4149     Bout = PDeb.Translated(-20*rabdist * VrefDeb);
4150     Standard_Boolean goodext = 0;
4151     for(Standard_Integer icont = 3; icont>=1 && !goodext; icont--) {
4152       newc = BSpline;
4153       GeomLib::ExtendCurveToPoint( newc, Bout, icont, Standard_False);
4154       gacurve.Load(newc);
4155       GCPnts_AbscissaPoint GCP(gacurve,-rabdist,Wrefdeb,WF);
4156       if(GCP.IsDone()) {
4157         WF = GCP.Parameter();
4158         goodext = GoodExt(newc,VrefDeb,Wrefdeb,WF,Angle);
4159       }
4160     }
4161     if(caredeb) {
4162       caredeb = newc->NbKnots() - BSpline->NbKnots();
4163     }
4164     BSpline = newc;
4165     LocalWF = BSpline->FirstParameter();
4166   }
4167   //
4168   if (!ES.IsPeriodic() && !PFin.IsEqual(BSpline->Pole(BSpline->NbPoles()), tol) ) {
4169     // Prolongement C3 en fin
4170     if(BSpline->IsRational()) {
4171       carefin = 1;
4172     }
4173     Standard_Real rabdist = WL - Wreffin;
4174     Bout = PFin.Translated(20*rabdist * VrefFin);
4175     Standard_Boolean goodext = 0;
4176     for(Standard_Integer icont = 3; icont>=1 && !goodext; icont--) {
4177       newc = BSpline;
4178       GeomLib::ExtendCurveToPoint( newc, Bout, icont, Standard_True);
4179       gacurve.Load(newc);
4180       GCPnts_AbscissaPoint GCP(gacurve,rabdist,Wreffin,WL);
4181       if(GCP.IsDone()) {
4182         WL = GCP.Parameter();
4183         goodext = GoodExt(newc, VrefFin, Wreffin,WL,Angle);
4184       }
4185     }
4186     if(carefin) {
4187       carefin = newc->NbKnots() - BSpline->NbKnots();
4188     }
4189     BSpline = newc;
4190     LocalWL = BSpline->LastParameter(); 
4191   }
4192   //
4193   //Reparametrisation et segmentation sur le domaine de la Spine.
4194   if(Abs(BSpline->FirstParameter() - WF)<tol) {
4195     WF = BSpline->FirstParameter();
4196   }
4197   if(Abs(BSpline->LastParameter() - WL)<tol) {
4198     WL = BSpline->LastParameter();
4199   }
4200   //
4201   if ( (LocalWF<WF) ||  (LocalWL>WL)) {   // pour eviter des pb avec segment!
4202     BSpline->Segment(WF, WL);
4203     ES.FirstParameter(WF);
4204     ES.LastParameter(WL);
4205   }
4206   //
4207   if (BSpline->IsRational()) {
4208     Handle(Geom_BSplineCurve) C1;
4209     C1 =  Handle(Geom_BSplineCurve)::DownCast(BSpline->Copy());
4210     GeomConvert::C0BSplineToC1BSplineCurve(C1, tol, 0.1);
4211     // Il faut s'assurer que l'origine n'a pas bouge (cts21158)
4212     if (C1->FirstParameter() == BSpline->FirstParameter()) {
4213       BSpline = C1;
4214     }
4215     else {
4216       //cout << "Attention : Echec de C0BSplineToC1 !" << endl;
4217     }
4218   }
4219   //
4220   Standard_Integer fk, lk, MultMax, ii;
4221   // Deformation eventuelle pour rendre la spine C2.
4222   // ou C3 pour des approx C2
4223   if((caredeb || carefin) && BSpline->Degree() < 8) {
4224     BSpline->IncreaseDegree(8);
4225   }
4226   //
4227   fk = 2;
4228   lk = BSpline->NbKnots()-1;
4229   if(BSpline->IsPeriodic()) {
4230     fk = 1;
4231   }
4232   if(caredeb) {
4233     fk += caredeb;
4234   }
4235   if(carefin) {
4236     lk -= carefin;
4237   }
4238   //
4239   if (continuity == GeomAbs_C3) {
4240     if (BSpline->Degree() < 7) {
4241       BSpline->IncreaseDegree(7);
4242     }
4243     MultMax = BSpline->Degree() - 3;
4244   }
4245   else {
4246     if (BSpline->Degree() < 5) {
4247       BSpline->IncreaseDegree(5);
4248     }
4249     MultMax = BSpline->Degree() - 2;
4250   }
4251   // correction C2 ou C3 (si possible)
4252   CurveCleaner(BSpline, Abs(WL-WF)*1.e-4, 1);
4253   CurveCleaner(BSpline, Abs(WL-WF)*1.e-2, MultMax);
4254   Standard_Integer MultMin = Max(BSpline->Degree() - 4, 1);
4255   for (ii = fk; ii <= lk; ii++) {
4256     if( BSpline->Multiplicity(ii) > MultMax ) {
4257       Bof = BSpline->RemoveKnot(ii, MultMax, Abs(WL-WF)/10);
4258     }
4259     // Voir C4
4260     if( BSpline->Multiplicity(ii) > MultMin ) {
4261       Bof = BSpline->RemoveKnot(ii, MultMin, Abs(WL-WF)*1.e-4);
4262     }       
4263   }
4264   // elspine periodique => BSpline Periodique
4265   if(ES.IsPeriodic()) {
4266     if(!BSpline->IsPeriodic()) {
4267       BSpline->SetPeriodic();
4268       //modified by NIZNHY-PKV Fri Dec 10 12:20:22 2010ft
4269       if (iToApproxByC2) {
4270         Bof = BSpline->RemoveKnot(1, MultMax, Abs(WL-WF)/10);
4271       }
4272       //Bof = BSpline->RemoveKnot(1, MultMax, Abs(WL-WF)/10);
4273       //modified by NIZNHY-PKV Mon Dec 13 14:12:54 2010t
4274     }
4275   }
4276   else { 
4277     // Sinon faut il bouger les poles pour les adapter 
4278     // aux nouvelles tangentes ?
4279     Standard_Boolean adjust = Standard_False; 
4280     gp_Pnt P1, P2;
4281     gp_Vec V1, V2;
4282     BSpline->D1(WF, P1, V1);
4283     V1.Normalize();
4284     ES.FirstPointAndTgt(PDeb,VrefDeb);
4285     Standard_Real scaldeb = VrefDeb.Dot(V1);
4286     Standard_Real disdeb = PDeb.Distance(P1);
4287     if((Abs(WF-LocalWF) < 1.e-12) && 
4288        ((scaldeb <= 0.9999999) || disdeb >= tol)) {   
4289       // Oui s'il n'y as pas eu de prolongement et que la tangente n'est pas
4290       // la bonne.
4291       adjust = Standard_True;
4292     } 
4293     BSpline->D1(WL, P2, V2);
4294     V2.Normalize();
4295     ES.LastPointAndTgt(PFin,VrefFin);
4296     Standard_Real scalfin = VrefFin.Dot(V2); 
4297     Standard_Real disfin = PFin.Distance(P2);
4298     if((Abs(WL-LocalWL) < 1.e-12) && 
4299        ((scalfin <= 0.9999999) || disfin >= tol)) {
4300       // de meme a la fin
4301       adjust = Standard_True;
4302     }
4303     if(adjust) {
4304       GeomLib::AdjustExtremity(BSpline, PDeb, PFin, VrefDeb, VrefFin);
4305     }
4306   }
4307
4308   // Le Resultat       
4309   ES.SetCurve(BSpline);
4310 }
4311
4312 //=======================================================================
4313 //function : cherche_face1
4314 //purpose  : cherche la face F differente de F1 dans la map.
4315 // La map  contient  les deux faces adjacentes a une edge 
4316 //=======================================================================
4317 void ChFi3d_cherche_face1 (const TopTools_ListOfShape & map,
4318                            const TopoDS_Face & F1,
4319                            TopoDS_Face &  F)   
4320
4321   TopoDS_Face Fcur;
4322   Standard_Boolean trouve=Standard_False;
4323   TopTools_ListIteratorOfListOfShape It;
4324   for (It.Initialize(map);It.More()&&!trouve;It.Next()) { 
4325     Fcur=TopoDS::Face (It.Value());
4326     if (!Fcur.IsSame(F1)) {
4327       F=Fcur;trouve=Standard_True;}
4328   }
4329
4330 //=======================================================================
4331 //function : cherche_element
4332 //purpose  : cherche l'edge E  de F1 differente de E1 et contenant le vertex V
4333 // Vtx est l'autre vertex de E 
4334 //=======================================================================
4335 void ChFi3d_cherche_element(const TopoDS_Vertex & V,
4336                             const TopoDS_Edge & E1,
4337                             const TopoDS_Face & F1,
4338                             TopoDS_Edge & E , 
4339                             TopoDS_Vertex  & Vtx )
4340
4341   Standard_Integer ie; 
4342   TopoDS_Vertex V1,V2;
4343   Standard_Boolean trouve=Standard_False;
4344   TopoDS_Edge Ecur;
4345   TopTools_IndexedMapOfShape  MapE;
4346   TopExp::MapShapes( F1,TopAbs_EDGE,MapE);
4347   for ( ie=1; ie<= MapE.Extent()&& !trouve; ie++) {  
4348     Ecur = TopoDS::Edge (MapE(ie));
4349     if (!Ecur.IsSame(E1)) { 
4350       TopTools_IndexedMapOfShape  MapV;
4351       TopExp::MapShapes(Ecur, TopAbs_VERTEX, MapV);
4352       if (MapV.Extent()==2) {
4353         V1 = TopoDS::Vertex (MapV(1));
4354         V2 = TopoDS::Vertex (MapV(2));
4355         if (V1.IsSame(V)) { 
4356           Vtx=V2;
4357           E=Ecur;
4358           trouve=Standard_True;
4359         }
4360         else if (V2.IsSame(V)) {
4361           Vtx=V1;
4362           E=Ecur;
4363           trouve=Standard_True;
4364         }
4365       }
4366     }
4367   }
4368
4369 //=======================================================================
4370 //function : cherche_edge
4371 //purpose  : cherche l'edge E  de F1 differente de la liste d'edges E1 et
4372 //            contenant le vertex V  Vtx est l'autre vertex de E 
4373 //=======================================================================
4374 void ChFi3d_cherche_edge(const TopoDS_Vertex & V,
4375                             const  TopTools_Array1OfShape & E1,
4376                             const TopoDS_Face & F1,
4377                             TopoDS_Edge & E , 
4378                             TopoDS_Vertex  & Vtx )
4379
4380   Standard_Integer ie,i; 
4381   TopoDS_Vertex V1,V2;
4382   Standard_Boolean trouve=Standard_False;
4383   TopoDS_Edge Ecur;
4384   Standard_Boolean same;
4385   TopTools_IndexedMapOfShape  MapE;
4386   TopExp::MapShapes( F1,TopAbs_EDGE,MapE);
4387   for ( ie=1; ie<= MapE.Extent()&& !trouve; ie++) {  
4388     Ecur=TopoDS::Edge (MapE(ie));
4389     same=Standard_False;
4390     for (i=E1.Lower();i<=E1.Upper() ;i++) {
4391        if (Ecur.IsSame(E1.Value(i))) same=Standard_True;
4392     }
4393       if (!same) {
4394       TopTools_IndexedMapOfShape  MapV;
4395       TopExp::MapShapes(Ecur, TopAbs_VERTEX, MapV);
4396       if (MapV.Extent()==2) {
4397         V1 = TopoDS::Vertex (MapV(1));
4398         V2 = TopoDS::Vertex (MapV(2));
4399         if (V1.IsSame(V)) { 
4400           Vtx=V2;
4401           E=Ecur;
4402           trouve=Standard_True;
4403         }
4404         else if (V2.IsSame(V)) {
4405           Vtx=V1;
4406           E=Ecur;
4407           trouve=Standard_True;
4408         }
4409       }
4410     }
4411   }
4412 }
4413
4414 //=======================================================================
4415 //function : nbface
4416 //purpose  : calcule le nombre de faces communes a un vertex
4417 //           
4418 //=======================================================================
4419 Standard_Integer  ChFi3d_nbface (const TopTools_ListOfShape & mapVF )
4420 { Standard_Integer nface=0;     
4421   TopTools_ListIteratorOfListOfShape ItF,JtF;
4422   Standard_Integer  fj = 0;
4423   for (ItF.Initialize(mapVF); ItF.More(); ItF.Next()) {
4424     fj++;
4425     Standard_Integer kf = 1;
4426     const TopoDS_Shape& cur = ItF.Value();
4427     for (JtF.Initialize(mapVF); JtF.More( )&&(kf<fj); JtF.Next(), kf++) {
4428       if(cur.IsSame(JtF.Value())) break;
4429     }
4430     if(kf == fj) nface++;
4431   }
4432   return nface;  
4433 }
4434
4435 //=======================================================================
4436 //function : edge_common_faces 
4437 //purpose  :  determine les deux faces partageant une edge.
4438 //            F1 =F2 si on a une arete de couure 
4439 //=======================================================================
4440 void ChFi3d_edge_common_faces (const TopTools_ListOfShape & mapEF,
4441                                TopoDS_Face & F1,
4442                                TopoDS_Face &  F2)   
4443 { TopTools_ListIteratorOfListOfShape It;
4444   TopoDS_Face F;
4445   Standard_Boolean trouve;
4446   It.Initialize(mapEF);  
4447   F1=TopoDS::Face(It.Value());
4448   trouve=Standard_False;
4449   for(It.Initialize(mapEF);It.More()&&!trouve;It.Next()) { 
4450      F=TopoDS::Face (It.Value());
4451      if (!F.IsSame(F1)) {
4452        F2=F;trouve=Standard_True;
4453      }
4454   }
4455   if (!trouve) F2=F1;
4456 }
4457
4458 /***********************************************************/
4459 // donne l'angle entre les edges E1 et E2 . Vtx est le vertex
4460 // commun aux edges
4461 /************************************************************/
4462 Standard_Real ChFi3d_AngleEdge (const TopoDS_Vertex & Vtx,
4463                                   const TopoDS_Edge&  E1,
4464                                   const TopoDS_Edge &  E2)
4465 {   Standard_Real angle;
4466     BRepAdaptor_Curve BCurv1(E1);
4467     BRepAdaptor_Curve BCurv2(E2);
4468     Standard_Real parE1,parE2;
4469     gp_Vec dir1,dir2 ;
4470     gp_Pnt P1,P2 ;
4471     parE1=BRep_Tool::Parameter(Vtx,E1);
4472     parE2=BRep_Tool::Parameter(Vtx,E2);
4473     BCurv1.D1(parE1,P1,dir1);
4474     BCurv2.D1(parE2,P2,dir2);
4475     if (!Vtx.IsSame(TopExp::FirstVertex(E1))) dir1.Reverse();
4476     if (!Vtx.IsSame(TopExp::FirstVertex(E2)))  dir2.Reverse();
4477     angle=Abs(dir1.Angle(dir2));
4478     return angle;
4479 }
4480
4481 //==================================================================
4482 // ChercheBordsLibres
4483 // determine si le vertex V1 a des aretes de bords libres
4484 // edgelibre1 et edgelibre2 .
4485 // On suppose qu'un sommet ne peut avoir que 2 aretes de bords libres
4486 //===================================================================
4487 void ChFi3d_ChercheBordsLibres(const  ChFiDS_Map & myVEMap,
4488                                const TopoDS_Vertex & V1,
4489                                Standard_Boolean & bordlibre,
4490                                TopoDS_Edge & edgelibre1,
4491                                TopoDS_Edge & edgelibre2) 
4492
4493   bordlibre=Standard_False;
4494   TopTools_ListIteratorOfListOfShape ItE,ItE1;
4495   Standard_Integer nboccur;
4496   for (ItE.Initialize(myVEMap(V1)); ItE.More()&&!bordlibre; ItE.Next()) {
4497     nboccur=0;
4498     const TopoDS_Edge& cur = TopoDS::Edge(ItE.Value());
4499     if (!BRep_Tool::Degenerated(cur)) {
4500       for (ItE1.Initialize(myVEMap(V1)); ItE1.More(); ItE1.Next()) {
4501         const TopoDS_Edge& cur1 = TopoDS::Edge(ItE1.Value());
4502         if (cur1.IsSame(cur)) nboccur++;
4503       }
4504     }
4505     if (nboccur==1) {
4506       edgelibre1=cur;
4507       bordlibre=Standard_True;
4508     }
4509   }
4510   if (bordlibre) {
4511     bordlibre=Standard_False;
4512     for (ItE.Initialize(myVEMap(V1)); ItE.More()&&!bordlibre; ItE.Next()) {
4513       nboccur=0;
4514       const TopoDS_Edge& cur = TopoDS::Edge(ItE.Value());
4515       if (!BRep_Tool::Degenerated(cur)&&!cur.IsSame(edgelibre1)) {
4516         for (ItE1.Initialize(myVEMap(V1)); ItE1.More(); ItE1.Next()) {
4517           const TopoDS_Edge& cur1 = TopoDS::Edge(ItE1.Value());
4518           if (cur1.IsSame(cur)) nboccur++;
4519         }
4520       }
4521       if (nboccur==1) {
4522         edgelibre2=cur;
4523         bordlibre=Standard_True;
4524       }
4525     }
4526   }
4527 }
4528
4529 //=======================================================================
4530 //function : NbNotDegeneratedEdges
4531 //purpose  : calcule le nb d'aretes non degenerees de la Map VEMap(Vtx)
4532 // Attention les aretes de jointures sont comptees deux fois
4533 //=======================================================================
4534 Standard_Integer ChFi3d_NbNotDegeneratedEdges (const TopoDS_Vertex& Vtx,
4535                                       const ChFiDS_Map& VEMap)
4536 {
4537   TopTools_ListIteratorOfListOfShape ItE;
4538   Standard_Integer nba=VEMap(Vtx).Extent();
4539   for (ItE.Initialize(VEMap(Vtx)); ItE.More(); ItE.Next()) {
4540     const TopoDS_Edge& cur = TopoDS::Edge(ItE.Value());
4541     if (BRep_Tool::Degenerated(cur)) nba--;
4542   }
4543   return nba;
4544 }
4545
4546 //=======================================================================
4547 //function : NumberOfEdges
4548 //purpose  : calcule le nombre d'aretes arrivant au sommet Vtx
4549 // les aretes degenerees ne sont pas comptees. 
4550 //=======================================================================
4551 Standard_Integer ChFi3d_NumberOfEdges(const TopoDS_Vertex& Vtx,
4552                                       const ChFiDS_Map& VEMap)
4553 {
4554   Standard_Integer nba;
4555   Standard_Boolean bordlibre;
4556   TopoDS_Edge edgelibre1,edgelibre2;
4557   nba=ChFi3d_NbNotDegeneratedEdges(Vtx, VEMap);
4558   ChFi3d_ChercheBordsLibres(VEMap,Vtx,bordlibre,edgelibre1,edgelibre2);
4559   if (bordlibre) nba=(nba-2)/2 +2;
4560   else  nba=nba/2;
4561   return nba;
4562 }
4563 //=======================================================================
4564 //function : ChFi3d_cherche_vertex
4565 //purpose  : function cherche_vertex
4566 //           cherche le vertex commun entre deux edges 
4567 //=======================================================================
4568 void ChFi3d_cherche_vertex (const TopoDS_Edge & E1,
4569                             const TopoDS_Edge & E2,
4570                             TopoDS_Vertex & vertex,
4571                             Standard_Boolean & trouve)
4572 { Standard_Integer i,j; 
4573   TopoDS_Vertex Vcur1,Vcur2;
4574   trouve=Standard_False;
4575   TopTools_IndexedMapOfShape  MapV1,MapV2;
4576   TopExp::MapShapes( E1,TopAbs_VERTEX,MapV1);
4577   TopExp::MapShapes( E2,TopAbs_VERTEX,MapV2);
4578   for ( i=1; i<= MapV1.Extent()&&!trouve; i++) {
4579     TopoDS_Shape alocalshape = TopoDS_Shape (MapV1(i));
4580     Vcur1=TopoDS::Vertex(alocalshape);
4581 //    Vcur1=TopoDS::Vertex(TopoDS_Shape (MapV1(i)));
4582     for ( j=1; j<= MapV2.Extent()&&!trouve; j++) {
4583       TopoDS_Shape aLocalShape = TopoDS_Shape (MapV2(j));
4584       Vcur2=TopoDS::Vertex(aLocalShape);
4585 //      Vcur2=TopoDS::Vertex(TopoDS_Shape (MapV2(j)));
4586       if (Vcur2.IsSame(Vcur1)) {
4587         vertex=Vcur1;trouve=Standard_True;
4588       }
4589     }
4590   }
4591 }       
4592 //=======================================================================
4593 //function : ChFi3d_Couture
4594 //purpose  : determine si F a une arete de couture
4595 //=======================================================================
4596 void ChFi3d_Couture( const TopoDS_Face & F,
4597                      Standard_Boolean & couture,
4598                      TopoDS_Edge & edgecouture)
4599 {   TopoDS_Edge Ecur;
4600     couture=Standard_False;
4601     TopTools_IndexedMapOfShape  MapE1;
4602     TopExp::MapShapes( F,TopAbs_EDGE,MapE1);
4603     TopLoc_Location Loc;
4604     Handle(Geom_Surface) Surf =BRep_Tool::Surface(F,Loc);
4605     for ( Standard_Integer i=1; i<= MapE1.Extent()&&!couture; i++) {
4606       TopoDS_Shape aLocalShape = TopoDS_Shape (MapE1(i));
4607       Ecur=TopoDS::Edge(aLocalShape);
4608 //      Ecur=TopoDS::Edge(TopoDS_Shape (MapE1(i)));
4609       if (BRep_Tool::IsClosed(Ecur,Surf,Loc)) {
4610         couture=Standard_True;
4611         edgecouture=Ecur;
4612       } 
4613     }
4614 }
4615
4616 //=======================================================================
4617 //function : ChFi3d_CoutureOnVertex
4618 //purpose  : 
4619 //=======================================================================
4620 void ChFi3d_CoutureOnVertex( const TopoDS_Face & F,
4621                              const TopoDS_Vertex & V,
4622                              Standard_Boolean & couture,
4623                              TopoDS_Edge & edgecouture)
4624 {   TopoDS_Edge Ecur;
4625     couture = Standard_False;
4626     TopTools_IndexedMapOfShape  MapE1;
4627     TopExp::MapShapes( F,TopAbs_EDGE,MapE1);
4628     TopLoc_Location Loc;
4629     Handle(Geom_Surface) Surf = BRep_Tool::Surface(F,Loc);
4630     for ( Standard_Integer i=1; i <= MapE1.Extent(); i++) {
4631       TopoDS_Shape aLocalShape = TopoDS_Shape (MapE1(i));
4632       Ecur=TopoDS::Edge(aLocalShape);
4633 //      Ecur=TopoDS::Edge(TopoDS_Shape (MapE1(i)));
4634       if (BRep_Tool::IsClosed(Ecur,Surf,Loc)) {
4635         TopoDS_Vertex Vf, Vl;
4636         TopExp::Vertices( Ecur, Vf, Vl );
4637         if (Vf.IsSame(V) || Vl.IsSame(V))
4638           {
4639             couture = Standard_True;
4640             edgecouture = Ecur;
4641             break;
4642           }
4643       } 
4644     }
4645 }
4646 //=======================================================================
4647 //function : ChFi3d_IsPseudoSeam
4648 //purpose  : 
4649 //=======================================================================
4650 Standard_Boolean ChFi3d_IsPseudoSeam( const TopoDS_Edge& E,
4651                                      const TopoDS_Face& F )
4652 {
4653   if (! BRep_Tool::IsClosed( E, F ))
4654     return Standard_False;
4655
4656   Standard_Boolean NeighborSeamFound = Standard_False;
4657   TopoDS_Vertex Vf, Vl, V1, V2;
4658   TopExp::Vertices( E, Vf, Vl );
4659   TopExp_Explorer Explo( F, TopAbs_EDGE );
4660   for (; Explo.More(); Explo.Next())
4661     {
4662       TopoDS_Edge Ecur = TopoDS::Edge( Explo.Current() );
4663       if (! Ecur.IsSame(E))
4664         {
4665           TopExp::Vertices( Ecur, V1, V2 );
4666           if ((V1.IsSame(Vf) || V1.IsSame(Vl) || V2.IsSame(Vf) || V2.IsSame(Vl)) &&
4667               BRepTools::IsReallyClosed( Ecur, F ))
4668             {
4669               NeighborSeamFound = Standard_True;
4670               break;
4671             }
4672         }
4673     }
4674   return NeighborSeamFound;
4675 }
4676
4677 //=======================================================================
4678 //function : ChFi3d_ApproxByC2
4679 //purpose  : 
4680 //=======================================================================
4681 Handle(Geom_BSplineCurve) ChFi3d_ApproxByC2( const Handle(Geom_Curve)& C )
4682 {
4683   Standard_Real First = C->FirstParameter(), Last = C->LastParameter();
4684   Standard_Integer NbPoints = 101;
4685
4686   TColgp_Array1OfPnt Points( 1, NbPoints );
4687   Standard_Real delta = (Last - First) / (NbPoints-1);
4688   for (Standard_Integer i = 1; i <= NbPoints-1; i++)
4689     Points(i) = C->Value(First + (i-1)*delta);
4690   Points(NbPoints) = C->Value(Last);
4691
4692   GeomAPI_PointsToBSpline Approx( Points , Approx_ChordLength, 3, 8, GeomAbs_C2, 1.000001e-3);
4693   Handle(Geom_BSplineCurve) BS = Approx.Curve();
4694   return BS;
4695 }
4696 //=======================================================================
4697 //function : ChFi3d_IsSmooth
4698 //purpose  : 
4699 //=======================================================================
4700 Standard_Boolean ChFi3d_IsSmooth( const Handle(Geom_Curve)& C )
4701 {
4702   GeomAdaptor_Curve GAC( C );
4703
4704   Standard_Integer ii;
4705   Standard_Integer intrv, nbintv = GAC.NbIntervals(GeomAbs_CN);
4706   TColStd_Array1OfReal TI(1,nbintv+1);
4707   GAC.Intervals(TI,GeomAbs_CN);
4708   Standard_Real Resolution = gp::Resolution(), Curvature;
4709   GeomLProp_CLProps LProp(C, 2, Resolution);
4710   gp_Pnt P1, P2;
4711   Standard_Integer Discretisation = 30;
4712   
4713   gp_Vec PrevVec;
4714   Standard_Boolean prevVecFound = Standard_False;
4715   Standard_Integer intrvFound = 0;
4716   for( intrv = 1; intrv <= nbintv; intrv++) {
4717     Standard_Real t = TI(intrv);
4718     Standard_Real step = (TI(intrv+1) - t) / Discretisation;
4719     for (ii = 1; ii <= Discretisation; ii++) {
4720       LProp.SetParameter(t);
4721       if (!LProp.IsTangentDefined())
4722         return Standard_False;
4723       Curvature = Abs(LProp.Curvature());
4724       if (Curvature > Resolution) {
4725         C->D0(t, P1);
4726         LProp.CentreOfCurvature(P2);
4727         PrevVec = gp_Vec(P1, P2);
4728         prevVecFound = Standard_True;
4729         break;
4730       }
4731       t += step;
4732     }
4733     if( prevVecFound ) {
4734       intrvFound = intrv;
4735       break;
4736     }
4737   }
4738
4739   if( !prevVecFound )
4740     return Standard_True;
4741
4742   //for (intrv = 1; intrv <= nbintv; intrv++) {
4743   for (intrv = intrvFound; intrv <= nbintv; intrv++) {
4744     Standard_Real t = TI(intrv);
4745     Standard_Real step = (TI(intrv+1) - t) / Discretisation;
4746     for (ii = 1; ii <= Discretisation; ii++)
4747       {  
4748         LProp.SetParameter(t);
4749         if (!LProp.IsTangentDefined())
4750           return Standard_False;
4751         Curvature = Abs(LProp.Curvature());
4752         if (Curvature > Resolution)
4753           {
4754             C->D0(t, P1);
4755             LProp.CentreOfCurvature(P2);
4756             gp_Vec Vec(P1, P2);
4757             Standard_Real Angle = PrevVec.Angle( Vec );
4758             if (Angle > PI/3.)
4759               return Standard_False;
4760             Standard_Real Ratio = Vec.Magnitude() / PrevVec.Magnitude();
4761             if (Ratio < 1.)
4762               Ratio = 1. / Ratio;
4763             if (Ratio > 2. && (intrv != nbintv || ii != Discretisation))
4764               return Standard_False;
4765             PrevVec = Vec;
4766           }
4767         t += step;
4768       }
4769   }
4770
4771   return Standard_True;
4772 }