6bbb10245b436d015b95ba0329c9accfe71210e9
[occt.git] / src / BiTgte / BiTgte_Blend.cxx
1 // Created on: 1996-12-16
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <AppCont_Function.hxx>
19 #include <AppParCurves_MultiCurve.hxx>
20 #include <Approx_FitAndDivide.hxx>
21 #include <BiTgte_Blend.hxx>
22 #include <BiTgte_CurveOnEdge.hxx>
23 #include <Bnd_Box.hxx>
24 #include <BRep_Builder.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRepAlgo_AsDes.hxx>
27 #include <BRepAlgo_Loop.hxx>
28 #include <BRepBndLib.hxx>
29 #include <BRepBuilderAPI_Sewing.hxx>
30 #include <BRepLib.hxx>
31 #include <BRepLib_MakeEdge.hxx>
32 #include <BRepOffset_DataMapIteratorOfDataMapOfShapeOffset.hxx>
33 #include <BRepOffset_DataMapOfShapeOffset.hxx>
34 #include <BRepOffset_Inter2d.hxx>
35 #include <BRepOffset_Inter3d.hxx>
36 #include <BRepOffset_Interval.hxx>
37 #include <BRepOffset_ListOfInterval.hxx>
38 #include <BRepOffset_MakeLoops.hxx>
39 #include <BRepOffset_Offset.hxx>
40 #include <BRepOffset_Tool.hxx>
41 #include <BRepTools.hxx>
42 #include <BRepTools_Quilt.hxx>
43 #include <BSplCLib.hxx>
44 #include <ChFi3d.hxx>
45 #include <Convert_CompBezierCurvesToBSplineCurve.hxx>
46 #include <ElSLib.hxx>
47 #include <Geom2d_Curve.hxx>
48 #include <Geom2dAdaptor_Curve.hxx>
49 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
50 #include <Geom_BSplineCurve.hxx>
51 #include <Geom_Circle.hxx>
52 #include <Geom_Curve.hxx>
53 #include <Geom_Line.hxx>
54 #include <Geom_Surface.hxx>
55 #include <Geom_TrimmedCurve.hxx>
56 #include <GeomAbs_SurfaceType.hxx>
57 #include <GeomAdaptor_Surface.hxx>
58 #include <GeomAPI.hxx>
59 #include <GeomAPI_ProjectPointOnCurve.hxx>
60 #include <gp.hxx>
61 #include <gp_Ax1.hxx>
62 #include <gp_Ax3.hxx>
63 #include <gp_Circ.hxx>
64 #include <gp_Dir.hxx>
65 #include <gp_Dir2d.hxx>
66 #include <gp_Lin.hxx>
67 #include <gp_Lin2d.hxx>
68 #include <gp_Pnt.hxx>
69 #include <gp_Pnt2d.hxx>
70 #include <gp_Sphere.hxx>
71 #include <Precision.hxx>
72 #include <Standard_NotImplemented.hxx>
73 #include <Standard_OutOfRange.hxx>
74 #include <StdFail_NotDone.hxx>
75 #include <TColgp_Array1OfPnt.hxx>
76 #include <TColStd_Array1OfInteger.hxx>
77 #include <TColStd_Array1OfReal.hxx>
78 #include <TopExp.hxx>
79 #include <TopExp_Explorer.hxx>
80 #include <TopoDS.hxx>
81 #include <TopoDS_Compound.hxx>
82 #include <TopoDS_Edge.hxx>
83 #include <TopoDS_Face.hxx>
84 #include <TopoDS_Shape.hxx>
85 #include <TopoDS_Vertex.hxx>
86 #include <TopoDS_Wire.hxx>
87 #include <TopTools_DataMapOfShapeShape.hxx>
88 #include <TopTools_ListIteratorOfListOfShape.hxx>
89 #include <TopTools_ListOfShape.hxx>
90 #include <TopTools_MapIteratorOfMapOfShape.hxx>
91 #include <TopTools_SequenceOfShape.hxx>
92
93 #ifdef OCCT_DEBUG
94 #include <OSD_Chronometer.hxx>
95 #endif
96
97 #include <stdio.h>
98 // include - all hxx,
99 //         - all small static functions.
100 //======================== START STATIC FUNCTIONS ============
101 // variables for performance 
102 Standard_Real t_mkcurve;
103 #ifdef OCCT_DEBUG
104 extern void ChFi3d_InitChron(OSD_Chronometer& ch);
105 extern void ChFi3d_ResultChron(OSD_Chronometer & ch, Standard_Real&    time);
106 #endif
107 #ifdef DRAW
108 static Standard_Boolean Affich = Standard_False;
109 static char name[100];
110 #include <DBRep.hxx>
111 #endif
112
113 //=======================================================================
114 //function : IsOnRestriction
115 //purpose  : 
116 //=======================================================================
117
118 static Standard_Boolean IsOnRestriction(const TopoDS_Vertex& V,
119                                         const TopoDS_Edge&   CurE,
120                                         const TopoDS_Face&   F,
121                                               TopoDS_Edge&   E) 
122 {
123   // find if Vertex V of CurE is on a restriction of F.
124   // if yes, store this restriction in E.
125
126   // dub - 03 01 97
127   // Method somewhat brutal : possible to really optimize by a
128   // direct call the SD of intersections -> See LBR
129
130   Standard_Real f,l;
131   Handle(Geom2d_Curve) CurC = BRep_Tool::CurveOnSurface(CurE,F,f,l);
132   Standard_Real U = BRep_Tool::Parameter(V,CurE,F);
133   gp_Pnt2d P = CurC->Value(U);
134
135   Geom2dAPI_ProjectPointOnCurve Proj;
136   
137   // The tolerance is exaggerated : it is better to construct too many
138   // tubes than to miss intersections.
139   // Standard_Real Tol = 100 * BRep_Tool::Tolerance(V);
140   Standard_Real Tol = BRep_Tool::Tolerance(V);
141   TopExp_Explorer exp(F,TopAbs_EDGE);
142   for ( ; exp.More(); exp.Next()) {
143     E = TopoDS::Edge(exp.Current());
144     Handle(Geom2d_Curve) PC = BRep_Tool::CurveOnSurface(E,F,f,l);
145     Proj.Init(P,PC,f,l);
146     if ( Proj.NbPoints() > 0) {
147       if (Proj.LowerDistance() < Tol) {
148         return Standard_True; 
149       }
150     }
151   }
152   return Standard_False;
153 }
154
155 //=======================================================================
156 //function : Add
157 //purpose  : 
158 //=======================================================================
159
160 static void Add(const TopoDS_Edge&         E,
161                       TopTools_IndexedMapOfShape& Map,
162                 const TopoDS_Shape&        S,
163                 const BRepOffset_Offset&   OF,
164                 const BRepOffset_Analyse&  Analyse,
165                 const Standard_Boolean     WarningSurBordLibre)
166 // If WarningSurBordLibre = TRUE, no propagation if the edge is open.
167 {
168   TopAbs_ShapeEnum Type = S.ShapeType();
169
170   if ( Type == TopAbs_FACE) {
171     TopExp_Explorer exp(S,TopAbs_EDGE);
172     for ( ; exp.More(); exp.Next()) {
173       const TopoDS_Edge& OriE = TopoDS::Edge(exp.Current());
174       TopoDS_Shape aLocalShape = OF.Generated(OriE);
175       const TopoDS_Edge& IE   = TopoDS::Edge(aLocalShape);
176 //      const TopoDS_Edge& IE   = TopoDS::Edge(OF.Generated(OriE));
177       if ( E.IsEqual(IE)) {
178         if (WarningSurBordLibre) {
179           // It is checked that the border is not free.
180           const TopTools_ListOfShape& L = Analyse.Ancestors(OriE);
181           if (L.Extent() == 1) break; // Nothing is done.
182         }
183         Map.Add(exp.Current());
184         break;
185       }
186     }
187   }
188   else if ( Type == TopAbs_EDGE) {
189     TopExp_Explorer exp(S,TopAbs_VERTEX);
190     for ( ; exp.More(); exp.Next()) {
191       TopoDS_Shape aLocalShape = OF.Generated(exp.Current());
192       const TopoDS_Edge& IE = TopoDS::Edge(aLocalShape);
193 //      const TopoDS_Edge& IE = TopoDS::Edge(OF.Generated(exp.Current()));
194       if ( E.IsEqual(IE)) {
195         const TopTools_ListOfShape& L = Analyse.Ancestors(exp.Current());
196         TopTools_ListIteratorOfListOfShape it(L);
197         for ( ; it.More(); it.Next()) {
198           Map.Add(it.Value());
199         }
200         break;
201       }
202     }
203   }
204 }
205
206
207 //=======================================================================
208 //function : IsInFace
209 //purpose  : 
210 //=======================================================================
211
212 static Standard_Boolean IsInFace(const TopoDS_Edge& E,
213                                  const TopoDS_Face& F)
214 {
215   TopExp_Explorer exp(F,TopAbs_EDGE);
216   for ( ;exp.More(); exp.Next()) 
217     if ( E.IsSame(exp.Current())) return Standard_True;
218   return Standard_False;
219 }
220
221
222 //=======================================================================
223 //function : KPartCurve3d
224 //purpose  : 
225 //=======================================================================
226
227 static void KPartCurve3d(TopoDS_Edge           Edge,
228                          Handle(Geom2d_Curve)  Curve,
229                          Handle(Geom_Surface)  Surf)
230 {
231   // try to find the particular case
232   // if not found call BRepLib::BuildCurve3d
233
234   TopLoc_Location Loc;
235   Standard_Real Tol = Precision::Confusion();
236
237   // Seach only isos on analytical surfaces.
238   Geom2dAdaptor_Curve C(Curve);
239   GeomAdaptor_Surface S(Surf);
240   GeomAbs_CurveType   CTy = C.GetType();
241   GeomAbs_SurfaceType STy = S.GetType();
242   BRep_Builder TheBuilder;
243
244   if ( STy != GeomAbs_Plane) { // if plane buildcurve3d manage KPart
245     if ( CTy == GeomAbs_Line) {
246       gp_Dir2d D = C.Line().Direction();
247       if ( D.IsParallel(gp::DX2d(),Precision::Angular())) { // Iso V.
248         if ( STy == GeomAbs_Sphere) {
249           gp_Pnt2d  P    = C.Line().Location();
250           if ( Abs( Abs(P.Y()) -M_PI/2. ) < Precision::PConfusion()) {
251             TheBuilder.Degenerated(Edge, Standard_True);
252           }
253           else {
254             gp_Sphere Sph  = S.Sphere();
255             gp_Ax3    Axis = Sph.Position();
256             gp_Circ   Ci   = ElSLib::SphereVIso(Axis,
257                                                 Sph.Radius(),
258                                                 P.Y());
259             gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
260             gp_Ax1 AxeRev(Axis.Location(), DRev);
261             Ci.Rotate(AxeRev, P.X());
262             Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
263             if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
264               Circle->Reverse();
265             TheBuilder.UpdateEdge(Edge, Circle, Loc, Tol);
266           }
267         }
268         else if ( STy == GeomAbs_Cylinder) {
269           gp_Cylinder Cyl  = S.Cylinder();
270           gp_Pnt2d    P    = C.Line().Location();
271           gp_Ax3      Axis = Cyl.Position();
272           gp_Circ     Ci   = ElSLib::CylinderVIso(Axis,
273                                                   Cyl.Radius(),
274                                                   P.Y());
275           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
276           gp_Ax1 AxeRev(Axis.Location(), DRev);
277           Ci.Rotate(AxeRev, P.X());
278           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
279           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
280             Circle->Reverse();
281           TheBuilder.UpdateEdge(Edge, Circle, Loc, Tol);
282         }
283         else if ( STy == GeomAbs_Cone) {
284           gp_Cone  Cone = S.Cone();
285           gp_Pnt2d P    = C.Line().Location();
286           gp_Ax3   Axis = Cone.Position();
287           gp_Circ  Ci   = ElSLib::ConeVIso(Axis,
288                                            Cone.RefRadius(),
289                                            Cone.SemiAngle(),
290                                            P.Y());
291           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
292           gp_Ax1 AxeRev(Axis.Location(), DRev);
293           Ci.Rotate(AxeRev, P.X());
294           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
295           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
296             Circle->Reverse();
297           TheBuilder.UpdateEdge(Edge, Circle, Loc, Tol);
298         }
299         else if ( STy == GeomAbs_Torus) {
300           gp_Torus Tore = S.Torus();
301           gp_Pnt2d P    = C.Line().Location();
302           gp_Ax3   Axis = Tore.Position();
303           gp_Circ  Ci   = ElSLib::TorusVIso(Axis,
304                                             Tore.MajorRadius(),
305                                             Tore.MinorRadius(),
306                                             P.Y());
307           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
308           gp_Ax1 AxeRev(Axis.Location(), DRev);
309           Ci.Rotate(AxeRev, P.X());
310           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
311           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
312             Circle->Reverse();
313           TheBuilder.UpdateEdge(Edge, Circle, Loc, Tol);
314         }
315       }
316       else if ( D.IsParallel(gp::DY2d(),Precision::Angular())) { // Iso U.
317         if ( STy == GeomAbs_Sphere) {
318           gp_Sphere Sph  = S.Sphere();
319           gp_Pnt2d  P    = C.Line().Location();
320           gp_Ax3    Axis = Sph.Position();
321           // calculate iso 0.
322           gp_Circ   Ci   = ElSLib::SphereUIso(Axis, Sph.Radius(),0.);
323
324           // set to sameparameter (rotation of the circle - offset from Y)
325           gp_Dir DRev = Axis.XDirection().Crossed(Axis. Direction());
326           gp_Ax1 AxeRev(Axis.Location(),DRev);
327           Ci.Rotate(AxeRev, P.Y());
328
329           // transformation by iso U ( = P.X())
330           DRev = Axis.XDirection().Crossed(Axis.YDirection());
331           AxeRev = gp_Ax1(Axis.Location(), DRev);
332           Ci.Rotate(AxeRev, P.X());
333           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
334           
335           if ( D.IsOpposite(gp::DY2d(),Precision::Angular())) 
336             Circle->Reverse();
337           TheBuilder.UpdateEdge(Edge, Circle, Loc, Tol);
338         }
339         else if ( STy == GeomAbs_Cylinder) {
340           gp_Cylinder Cyl = S.Cylinder();
341           gp_Pnt2d    P   = C.Line().Location();
342           gp_Lin      L   = ElSLib::CylinderUIso(Cyl.Position(),
343                                                  Cyl.Radius(),
344                                                  P.X());
345           gp_Vec Tr(L.Direction());
346           Tr.Multiply(P.Y());
347           L.Translate(Tr);
348           Handle(Geom_Line) Line = new Geom_Line(L);
349           if ( D.IsOpposite(gp::DY2d(),Precision::Angular()))
350             Line->Reverse();
351           TheBuilder.UpdateEdge(Edge, Line, Loc, Tol);
352         }
353         else if ( STy == GeomAbs_Cone) {
354           gp_Cone  Cone = S.Cone();
355           gp_Pnt2d P    = C.Line().Location();
356           gp_Lin   L    = ElSLib::ConeUIso(Cone.Position(),
357                                            Cone.RefRadius(),
358                                            Cone.SemiAngle(),
359                                            P.X());
360           gp_Vec Tr(L.Direction());
361           Tr.Multiply(P.Y());
362           L.Translate(Tr);        Handle(Geom_Line) Line = new Geom_Line(L);
363           if ( D.IsOpposite(gp::DY2d(),Precision::Angular()))
364             Line->Reverse();
365           TheBuilder.UpdateEdge(Edge, Line, Loc, Tol);
366         }
367         else if ( STy == GeomAbs_Torus) {
368         }
369       }
370     }
371   }
372   else { // Case Plane
373     Handle(Geom_Curve) C3d = GeomAPI::To3d(Curve,S.Plane());
374     TheBuilder.UpdateEdge(Edge, C3d, Loc, Tol);
375   }
376 }
377
378
379 //=======================================================================
380 //function : MakeCurve
381 //purpose  : 
382 //=======================================================================
383
384 class MakeCurve_Function : public AppCont_Function
385 {
386   BiTgte_CurveOnEdge myCurve;
387
388   public :
389
390   MakeCurve_Function(const BiTgte_CurveOnEdge& C)
391   : myCurve(C)
392   {
393     myNbPnt = 1;
394     myNbPnt2d = 0;
395   }
396
397   Standard_Real FirstParameter() const
398   {
399     return myCurve.FirstParameter();
400   }
401
402   Standard_Real LastParameter() const
403   {
404     return myCurve.LastParameter();
405   }
406
407   Standard_Boolean Value(const Standard_Real   theT,
408                          NCollection_Array1<gp_Pnt2d>& /*thePnt2d*/,
409                          NCollection_Array1<gp_Pnt>&   thePnt) const
410   {
411       thePnt(1) = myCurve.Value(theT);
412       return Standard_True;
413   }
414   
415   Standard_Boolean D1(const Standard_Real   /*theT*/,
416                       NCollection_Array1<gp_Vec2d>& /*theVec2d*/,
417                       NCollection_Array1<gp_Vec>&   /*theVec*/) const
418   {
419       return Standard_False;
420   }
421
422 };
423
424 Handle(Geom_Curve) MakeCurve (const BiTgte_CurveOnEdge& HC)
425 {
426   Handle(Geom_Curve) C;
427
428 #ifdef OCCT_DEBUG
429    OSD_Chronometer ch;
430    ChFi3d_InitChron(ch);
431 #endif
432
433   if ( HC.GetType() == GeomAbs_Circle) {
434     C = new Geom_Circle(HC.Circle());
435     C = new Geom_TrimmedCurve(C,HC.FirstParameter(),HC.LastParameter());
436   }
437   else { // the approximation is done
438     MakeCurve_Function F(HC);
439     Standard_Integer Deg1, Deg2;
440     Deg1 = Deg2 = 8;
441     Standard_Real Tol = Precision::Approximation();
442     Approx_FitAndDivide Fit(F,Deg1,Deg2,Tol,Tol,Standard_True);
443     Standard_Integer i;
444     Standard_Integer NbCurves = Fit.NbMultiCurves();
445     // it is attempted to make the curve at least C1
446     Convert_CompBezierCurvesToBSplineCurve Conv;
447     
448     for (i = 1; i <= NbCurves; i++) {
449       AppParCurves_MultiCurve MC = Fit.Value( i);    //Load the Ith Curve
450       TColgp_Array1OfPnt Poles( 1, MC.Degree() + 1); //Return poles
451       MC.Curve(1, Poles);
452       
453       Conv.AddCurve(Poles);
454     }
455     
456     Conv.Perform();
457     
458     Standard_Integer NbPoles    = Conv.NbPoles();
459     Standard_Integer NbKnots    = Conv.NbKnots();
460     TColgp_Array1OfPnt      NewPoles(1,NbPoles);
461     TColStd_Array1OfReal    NewKnots(1,NbKnots);
462     TColStd_Array1OfInteger NewMults(1,NbKnots);
463     
464     Conv.KnotsAndMults(NewKnots,NewMults);
465     Conv.Poles(NewPoles);
466     
467     BSplCLib::Reparametrize(HC.FirstParameter(),
468                             HC.LastParameter(),
469                             NewKnots);
470     
471     C = new Geom_BSplineCurve (NewPoles,
472                                NewKnots,
473                                NewMults,
474                                Conv.Degree());
475   }
476
477 #ifdef OCCT_DEBUG
478   ChFi3d_ResultChron(ch, t_mkcurve);
479 #endif
480
481   return C;
482 }
483
484
485 //=======================================================================
486 //function : Touched
487 //purpose  : Only the faces connected with caps are given
488 //=======================================================================
489
490 static void Touched(const BRepOffset_Analyse&, 
491                     const TopTools_MapOfShape&, 
492                     const TopoDS_Shape&,
493                     TopTools_MapOfShape&)
494 {
495   // currently nothing is done !!
496   /*if ( Standard_True) {
497     return;
498   }
499   else {
500     TopExp_Explorer exp(Shape, TopAbs_EDGE);
501     for ( ; exp.More(); exp.Next()) {
502       const TopTools_ListOfShape& L = Analyse.Ancestors(exp.Current());
503       if (StopFaces.Contains(L.First())) 
504         TouchedByCork.Add(L.Last());
505       else if (StopFaces.Contains(L.Last())) 
506         TouchedByCork.Add(L.First());
507     }
508   }*/
509   return;
510 }
511
512 //=======================================================================
513 //function : FindVertex
514 //purpose  : 
515 //=======================================================================
516
517 static TopoDS_Vertex FindVertex(const gp_Pnt&              P,
518                                 const TopTools_MapOfShape& Map,
519                                 const Standard_Real        Tol)
520 {
521   BRep_Builder B;
522   // Find in <Map> a vertex which represent the point <P>.
523   Standard_Real Tol2,Dist;
524   TopoDS_Vertex V,VV[2];
525   Standard_Real TolCarre = Tol*Tol;
526   TopTools_MapIteratorOfMapOfShape it(Map);
527   for ( ; it.More(); it.Next()) {
528     const TopoDS_Edge& E = TopoDS::Edge(it.Key());
529     if ( !E.IsNull()) {
530       TopExp::Vertices(E,VV[0],VV[1]);
531
532       for (Standard_Integer i = 0; i < 2 ; i++) {
533         // if OK la Tolerance du Vertex
534         Tol2 = BRep_Tool::Tolerance(VV[i]);
535         Tol2 *= Tol2;
536         gp_Pnt P1 = BRep_Tool::Pnt(VV[i]);
537         Dist = P.SquareDistance(P1);
538         if ( Dist <= Tol2) return VV[i];
539         // otherwise with the required tolerance.
540         if (TolCarre > Tol2) {
541           if ( Dist <= TolCarre) {
542             // so it is necessary to update the tolerance of Vertex.
543             B.UpdateVertex(VV[i],Tol);
544             return VV[i];
545           }
546         }
547       }
548     }
549   }
550
551   return V;
552 }
553
554
555 //=======================================================================
556 //function : MakeDegeneratedEdge
557 //purpose  : 
558 //=======================================================================
559
560 static TopoDS_Edge MakeDegeneratedEdge(const Handle(Geom_Curve)& CC,
561                                        const TopoDS_Vertex&    VfOnE)
562 {
563   BRep_Builder B;
564   Standard_Real Tol = Precision::Confusion();
565   // kill trimmed curves
566   Handle(Geom_Curve) C = CC;
567   Handle(Geom_TrimmedCurve) CT = Handle(Geom_TrimmedCurve)::DownCast(C);
568   while (!CT.IsNull()) {
569     C = CT->BasisCurve();
570     CT = Handle(Geom_TrimmedCurve)::DownCast(C);
571   }
572
573   TopoDS_Vertex V1,V2;
574   if ( VfOnE.IsNull()) {
575     gp_Pnt P = C->Value(C->FirstParameter());
576     B.MakeVertex(V1,P,Tol);
577     V2 = V1;
578   }
579   else {
580     V1 = V2 = VfOnE;
581   }
582   V1.Orientation(TopAbs_FORWARD);
583   V2.Orientation(TopAbs_REVERSED);
584
585   TopoDS_Edge E;
586   B.MakeEdge(E,C,Tol);
587   B.Add(E,V1); B.Add(E,V2);
588 //  B.UpdateVertex(V1,C->FirstParameter(),E,Tol);
589 //  B.UpdateVertex(V2,C->LastParameter(),E,Tol);
590   B.Range(E,CC->FirstParameter(),CC->LastParameter());
591   return E;
592 }
593
594
595 //=======================================================================
596 //function : Orientation
597 //purpose  : 
598 //=======================================================================
599
600 static TopAbs_Orientation Orientation(const TopoDS_Edge& E,
601                                       const TopoDS_Face& F,
602                                       const TopTools_ListOfShape& L)
603 {
604   TopAbs_Orientation Orien = TopAbs_FORWARD;
605   TopTools_ListIteratorOfListOfShape itld;
606   for ( itld.Initialize(L); itld.More(); itld.Next()) {
607     if ( itld.Value().IsSame(E)) {
608       Orien = itld.Value().Orientation();
609       break;
610     }
611   }
612   if ( F.Orientation() == TopAbs_REVERSED) 
613     Orien = TopAbs::Reverse(Orien);
614   
615   return Orien;
616 }
617
618 //=======================================================================
619 //function : FindCreatedEdge
620 //purpose  : 
621 //=======================================================================
622
623 static TopoDS_Edge FindCreatedEdge
624 (const TopoDS_Vertex&                   V1,
625  const TopoDS_Edge&                     E,
626  const BRepOffset_DataMapOfShapeOffset& MapSF,
627        TopTools_MapOfShape&             MapOnV,
628  const BRepOffset_Analyse&              CenterAnalyse,
629        Standard_Real                    Radius,
630        Standard_Real                    Tol)
631 {
632   TopoDS_Edge E1;
633   if (!CenterAnalyse.HasAncestor(V1)) return E1; // return a Null Shape.
634
635   TopTools_ListOfShape TangE;
636   CenterAnalyse.TangentEdges(E,V1,TangE);
637
638   TopTools_ListIteratorOfListOfShape itl(TangE);
639   Standard_Boolean Find = Standard_False;
640   for ( ; itl.More() && !Find; itl.Next()) {
641     const TopoDS_Edge& ET = TopoDS::Edge(itl.Value());
642     if ( MapSF.IsBound(ET)) {
643       TopoDS_Shape aLocalShape = MapSF(ET).Generated(V1);
644       E1 = TopoDS::Edge(aLocalShape);
645 //      E1 = TopoDS::Edge(MapSF(ET).Generated(V1));
646       MapOnV.Add(E1);
647       Find = Standard_True;
648     }
649     else {
650       // Find the sharing of vertices in case of tangent consecutive 3 edges 
651       // the second of which is the edge that degenerates the tube.
652       TopLoc_Location CLoc;
653       Standard_Real ff,ll;
654       Handle(Geom_Curve) CET = 
655         BRep_Tool::Curve(ET,CLoc,ff,ll);
656       if ( CET->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
657         CET = Handle(Geom_TrimmedCurve)::DownCast(CET)->BasisCurve();
658       }
659       Handle(Geom_Circle) Circ = Handle(Geom_Circle)::DownCast(CET);
660       if ( Circ.IsNull()) continue;
661       if ( Abs(Circ->Radius() - Abs(Radius)) > Tol) continue;
662       
663       TopoDS_Vertex U1,U2;
664       TopExp::Vertices(ET,U1,U2);
665       if ( U1.IsSame(V1)) U1 = U2;
666       TopTools_ListOfShape Tang2;
667       CenterAnalyse.TangentEdges(ET,U1,Tang2);
668       TopTools_ListIteratorOfListOfShape it2(Tang2);
669       for ( ; it2.More() ; it2.Next()) {
670         const TopoDS_Edge& ET2 = TopoDS::Edge(it2.Value());
671         if ( MapSF.IsBound(ET2)) {
672           TopoDS_Shape aLocalShape = MapSF(ET2).Generated(U1);
673           MapOnV.Add(TopoDS::Edge(aLocalShape));
674 //        MapOnV.Add(TopoDS::Edge(MapSF(ET2).Generated(U1)));
675         }
676       }
677     }
678   }
679   if (!Find) {
680     TangE.Clear();
681     //  CenterAnalyse.Edges(V1f, OT, TangE);
682     if (CenterAnalyse.HasAncestor(V1)) {
683       TangE = CenterAnalyse.Ancestors(V1);
684       itl.Initialize(TangE);
685       for ( ; itl.More() && !Find; itl.Next()) {
686         if ( MapSF.IsBound(itl.Value())) {
687           MapOnV.Add(MapSF(itl.Value()).Generated(V1));
688         }
689       }
690     }
691   }
692   
693   return E1;
694 }
695
696 #ifdef DRAW
697 //=======================================================================
698 //function : Bubble
699 //purpose  : Sets in increasing order the sequence of vertices. 
700 //=======================================================================
701
702 static void Bubble(const TopoDS_Edge&        E,
703                    TopTools_SequenceOfShape& Seq) 
704 {
705   Standard_Boolean Invert   = Standard_True;
706   Standard_Integer NbPoints = Seq.Length();
707   Standard_Real    U1,U2;
708   TopoDS_Vertex    V1,V2;
709
710   while (Invert) {
711     Invert = Standard_False;
712     for ( Standard_Integer i = 1; i < NbPoints; i++) {
713       TopoDS_Shape aLocalShape = Seq.Value(i)  .Oriented(TopAbs_INTERNAL);
714       V1 = TopoDS::Vertex(aLocalShape);
715       aLocalShape = Seq.Value(i+1).Oriented(TopAbs_INTERNAL);
716       V2 = TopoDS::Vertex(aLocalShape);
717 //      V1 = TopoDS::Vertex(Seq.Value(i)  .Oriented(TopAbs_INTERNAL));
718 //      V2 = TopoDS::Vertex(Seq.Value(i+1).Oriented(TopAbs_INTERNAL));
719
720       U1 = BRep_Tool::Parameter(V1,E);
721       U2 = BRep_Tool::Parameter(V2,E);
722       if (U2 < U1) {
723         Seq.Exchange(i,i+1);
724         Invert = Standard_True;
725       }
726     }
727   }
728 }
729
730 //=======================================================================
731 //function : CutEdge
732 //purpose  : 
733 //=======================================================================
734
735 static void CutEdge (const TopoDS_Edge&          E,
736                      const TopTools_ListOfShape& VOnE,
737                            TopTools_ListOfShape& NE   )
738 {
739   TopoDS_Shape aLocalShapeOrientedE = E.Oriented(TopAbs_FORWARD);
740   TopoDS_Edge WE = TopoDS::Edge(aLocalShapeOrientedE);
741 //  TopoDS_Edge WE = TopoDS::Edge(E.Oriented(TopAbs_FORWARD));
742
743   Standard_Real                      U1,U2;
744   TopoDS_Vertex                      V1,V2;
745   TopTools_SequenceOfShape           SV;
746   TopTools_ListIteratorOfListOfShape it(VOnE);
747   BRep_Builder                       B;
748
749   for ( ; it.More(); it.Next()) {
750     SV.Append(it.Value());
751   }
752   //--------------------------------
753   // Parse vertices on the edge.
754   //--------------------------------
755   Bubble (WE,SV);
756
757   Standard_Integer NbVer = SV.Length();
758   //----------------------------------------------------------------
759   // Construction of new edges.
760   // The vertices at the extremities of edges are not 
761   // necessarily in the list of vertices
762   //----------------------------------------------------------------
763   if (SV.IsEmpty()) {
764     NE.Append(E);
765     return;
766   }
767   TopoDS_Vertex    VF,VL;
768   Standard_Real    f,l;
769   BRep_Tool::Range(WE,f,l);
770   TopExp::Vertices(WE,VF,VL);
771
772   if (NbVer == 2) {
773     if (SV(1).IsEqual(VF) && SV(2).IsEqual(VL)) {
774       NE.Append(E);
775       return;
776     }
777   }
778   //----------------------------------------------------
779   // Processing of closed edges 
780   // If a vertex of intersection is on the common vertex,
781   // it should appear at the beginning and the end of SV.
782   //----------------------------------------------------
783   TopoDS_Vertex VCEI;
784
785   if (!VF.IsNull() && !VF.IsSame(SV.First())) SV.Prepend(VF);
786   if (!VL.IsNull() && !VL.IsSame(SV.Last ())) SV.Append (VL);
787
788   V1  = TopoDS::Vertex(SV.First());
789   SV.Remove(1);
790
791   while (!SV.IsEmpty()) {
792     
793     V2  = TopoDS::Vertex(SV.First());
794     SV.Remove(1);
795     
796     if ( V1.IsSame(V2)) {
797       std::cout << "Vertex Confondus dans CutEdges" << std::endl;
798       continue;
799     }
800     //-------------------------------------------
801     // Copy the edge and restriction by V1 V2.
802     //-------------------------------------------
803     TopoDS_Shape aLocalShape =WE.EmptyCopied();
804     TopoDS_Edge NewEdge = TopoDS::Edge(aLocalShape);
805 //    TopoDS_Edge NewEdge = TopoDS::Edge(WE.EmptyCopied());
806     B.Add  (NewEdge,V1.Oriented(TopAbs_FORWARD));
807     B.Add  (NewEdge,V2.Oriented(TopAbs_REVERSED));
808     if (V1.IsSame(VF)) 
809       U1 = f;
810     else {
811       aLocalShape = V1.Oriented(TopAbs_INTERNAL);
812       U1 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),WE);
813 //      U1 = BRep_Tool::Parameter
814 //      (TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),WE);
815     }
816     if (V2.IsSame(VL))
817       U2 = l;
818     else {
819       aLocalShape = V2.Oriented(TopAbs_INTERNAL);
820       U2 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),WE);
821 //      U2 = BRep_Tool::Parameter
822 //      (TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),WE);
823     }
824     B.Range (NewEdge,U1,U2);
825     NE.Append(NewEdge.Oriented(E.Orientation()));
826
827     V1 = V2;
828   }
829 }
830 #endif
831
832 //======================== END OF STATIC FUNCTIONS ============
833
834
835
836
837 //=======================================================================
838 //function : BiTgte_Blend
839 //purpose  : 
840 //=======================================================================
841
842 BiTgte_Blend::BiTgte_Blend()
843 {
844   myAsDes = new BRepAlgo_AsDes();
845   myNbBranches = -1;
846 }
847
848
849 //=======================================================================
850 //function : BiTgte_Blend
851 //purpose  : 
852 //=======================================================================
853
854 BiTgte_Blend::BiTgte_Blend(const TopoDS_Shape&    S,
855                            const Standard_Real    Radius,
856                            const Standard_Real    Tol,
857                            const Standard_Boolean NUBS)
858 {
859   myAsDes = new BRepAlgo_AsDes();
860   Init(S,Radius,Tol,NUBS);
861 }
862
863
864 //=======================================================================
865 //function : Init
866 //purpose  : 
867 //=======================================================================
868
869 void BiTgte_Blend::Init(const TopoDS_Shape&    S,
870                         const Standard_Real    Radius,
871                         const Standard_Real    Tol,
872                         const Standard_Boolean NUBS) 
873 {
874   Clear();
875   myShape      = S;
876   myTol        = Tol;
877   myNubs       = NUBS;
878   myRadius     = Radius;
879   myNbBranches = -1;
880 //  TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,myAncestors);
881 }
882
883
884 //=======================================================================
885 //function : Clear
886 //purpose  : 
887 //=======================================================================
888
889 void BiTgte_Blend::Clear() 
890 {
891   myInitOffsetFace.Clear();
892   myImage         .Clear();
893   myImageOffset   .Clear();
894   myStopFaces     .Clear();  
895   myAnalyse       .Clear();
896   myAsDes        ->Clear();
897   myNbBranches   = -1;
898   myDone         = Standard_False;
899 }
900
901
902 //=======================================================================
903 //function : SetStoppingFace
904 //purpose  : 
905 //=======================================================================
906
907 void BiTgte_Blend::SetStoppingFace(const TopoDS_Face& Face) 
908 {
909   myStopFaces.Add(Face);    
910   //-------------
911   // MAJ SD. -> To end loop, set faces of edges
912   //-------------
913 //  myInitOffsetFace.SetRoot(Face);    
914 //  myInitOffsetFace.Bind   (Face,Face);
915 //  myImageOffset.SetRoot   (Face);  
916 }
917
918
919 //=======================================================================
920 //function : SetFaces
921 //purpose  : 
922 //=======================================================================
923
924 void BiTgte_Blend::SetFaces(const TopoDS_Face& F1,const TopoDS_Face& F2) 
925 {
926   myFaces.Add(F1);
927   myFaces.Add(F2);
928 }
929
930
931 //=======================================================================
932 //function : SetEdge
933 //purpose  : 
934 //=======================================================================
935
936 void BiTgte_Blend::SetEdge(const TopoDS_Edge& Edge) 
937 {
938   myEdges.Add(Edge);
939 }
940
941
942 //=======================================================================
943 //function : Perform
944 //purpose  : 
945 //=======================================================================
946
947 void BiTgte_Blend::Perform(const Standard_Boolean BuildShape) 
948 {
949   myBuildShape = BuildShape;
950
951   // Try cutting to avoid tubes on free borders
952   // that are not actually free.
953   Handle(BRepBuilderAPI_Sewing) Sew = new BRepBuilderAPI_Sewing(myTol);
954   BRepLib::BuildCurves3d(myShape);
955   TopExp_Explorer expf(myShape,TopAbs_FACE);
956   for ( ;expf.More(); expf.Next()) Sew->Add(expf.Current());
957   Sew->Perform();
958   TopoDS_Shape SewedShape = Sew->SewedShape();
959   if ( SewedShape.IsNull()) throw Standard_Failure("Sewing aux fraises");
960
961   // Check if the sewing modified the orientation.
962   expf.Init(myShape,TopAbs_FACE);
963   TopoDS_Face FaceRef = TopoDS::Face(expf.Current());
964   TopAbs_Orientation OriRef  = FaceRef.Orientation();
965   if (Sew->IsModified(FaceRef)) FaceRef = TopoDS::Face(Sew->Modified(FaceRef));
966   expf.Init(SewedShape, TopAbs_FACE);
967   for (; expf.More(); expf.Next()) {
968     const TopoDS_Face& FF = TopoDS::Face(expf.Current());
969     if (FaceRef.IsSame(FF) && (FF.Orientation() != OriRef)) {
970       SewedShape.Reverse();
971       break;
972     }
973   } 
974   
975   // Make SameParameter if Sew does not do it (Detect that edges
976   // are not sameparameter but it does nothing.)
977   expf.Init(SewedShape, TopAbs_EDGE);
978   for (; expf.More(); expf.Next()) {
979     const TopoDS_Edge& sec = TopoDS::Edge(expf.Current());
980     BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec));
981   }
982   
983   TopExp::MapShapesAndAncestors
984     (SewedShape,TopAbs_EDGE,TopAbs_FACE,myAncestors);
985   
986   // Extend myFaces with the faces of the sewed shape.
987   expf.Init(myShape,TopAbs_FACE);
988   for ( ; expf.More(); expf.Next()) {
989     const TopoDS_Shape& F = expf.Current();
990     if ( myFaces.Contains(F) && Sew->IsModified(F)) {
991       myFaces.RemoveKey(F);
992       myFaces.Add(Sew->Modified(F));
993     }
994   }
995   
996   myShape = SewedShape;
997 // end Sewing for false free borders.
998
999 #ifdef OCCT_DEBUG
1000   OSD_Chronometer cl_total, ch;
1001   Standard_Real   t_total, t_center, t_surface, t_shape;
1002
1003   t_total=0; t_center=0; t_surface=0; t_mkcurve=0; t_shape=0;
1004   ChFi3d_InitChron(cl_total); 
1005 #endif  
1006
1007   // ----------------------------------------------------------------
1008   // place faces with the proper orientation in the initial shape
1009   // ----------------------------------------------------------------
1010   TopExp_Explorer exp(myShape,TopAbs_FACE);
1011   for ( ; exp.More(); exp.Next()) {
1012     const TopoDS_Shape& F = exp.Current();
1013     if ( myFaces.Contains(F)) {
1014       myFaces.RemoveKey(F);
1015       myFaces.Add(F);
1016     }
1017     else if ( myStopFaces.Contains(F)) {
1018       myStopFaces.Remove(F);
1019       myStopFaces.Add(F);
1020     }
1021   }
1022
1023   // ----------------------------------------------
1024   // Calculate lines of centers and of surfaces
1025   // ----------------------------------------------
1026 #ifdef OCCT_DEBUG
1027   ChFi3d_InitChron(ch);
1028 #endif  
1029
1030   ComputeCenters();
1031   
1032 #ifdef OCCT_DEBUG
1033   ChFi3d_ResultChron(ch, t_center);
1034 #endif 
1035
1036   // -----------------------------
1037   // Calculate connection Surfaces
1038   // -----------------------------
1039 #ifdef OCCT_DEBUG
1040   ChFi3d_InitChron(ch);
1041 #endif
1042
1043   ComputeSurfaces();
1044
1045 #ifdef OCCT_DEBUG
1046   ChFi3d_ResultChron(ch, t_surface);
1047 #endif 
1048
1049   // ----------------------------------
1050   // Calculate the generated shape if required
1051   // ----------------------------------
1052 #ifdef OCCT_DEBUG
1053   ChFi3d_InitChron(ch);
1054 #endif  
1055
1056   if ( myBuildShape) ComputeShape();
1057
1058 #ifdef OCCT_DEBUG
1059   ChFi3d_ResultChron(ch, t_shape);
1060 #endif 
1061
1062   // Finally construct curves 3d from edges to be transfered
1063   // since the partition is provided ( A Priori);
1064   BRepLib::BuildCurves3d(myResult, Precision::Confusion());
1065
1066 #ifdef OCCT_DEBUG
1067   ChFi3d_ResultChron(cl_total, t_total);
1068   std::cout<<std::endl; 
1069   std::cout<<"Blend_PERFORM: temps total "<<t_total<<" s  dont :"<<std::endl;
1070   std::cout<<"- ComputeCenters  "<<t_center<<" s"<<std::endl;  
1071   std::cout<<"- ComputeSurfaces "<<t_surface<<" s"<<std::endl;
1072   std::cout<<"----> MakeCurve   "<<t_mkcurve<<" s"<<std::endl;
1073   if ( myBuildShape)  std::cout<<"- ComputeShape "<<t_shape<<" s"<<std::endl;
1074 #endif
1075
1076   myDone = Standard_True;
1077 }
1078
1079
1080 //=======================================================================
1081 //function : IsDone
1082 //purpose  : 
1083 //=======================================================================
1084
1085 Standard_Boolean BiTgte_Blend::IsDone() const
1086 {
1087   return myDone;
1088 }
1089
1090 //=======================================================================
1091 //function : Shape
1092 //purpose  : 
1093 //=======================================================================
1094
1095 const TopoDS_Shape& BiTgte_Blend::Shape() const
1096 {
1097   return myResult;
1098 }
1099
1100
1101 //=======================================================================
1102 //function : NbSurfaces
1103 //purpose  : 
1104 //=======================================================================
1105
1106 Standard_Integer BiTgte_Blend::NbSurfaces() const
1107 {
1108   return myCenters.Extent();
1109 }
1110
1111
1112 //=======================================================================
1113 //function : Surface
1114 //purpose  : 
1115 //=======================================================================
1116
1117 Handle(Geom_Surface) BiTgte_Blend::Surface(const Standard_Integer Index) const
1118 {
1119   return Surface(myCenters(Index));
1120 }
1121
1122 //=======================================================================
1123 //function : TopoDS_Face&
1124 //purpose  : 
1125 //=======================================================================
1126
1127 const TopoDS_Face& BiTgte_Blend::Face(const Standard_Integer Index) const
1128 {
1129   return Face(myCenters(Index));
1130 }
1131
1132
1133
1134 //=======================================================================
1135 //function : CenterLines
1136 //purpose  : 
1137 //=======================================================================
1138
1139 void BiTgte_Blend::CenterLines(TopTools_ListOfShape& LC) const
1140 {
1141   LC.Clear();
1142   Standard_Integer Nb = NbSurfaces();
1143   for ( Standard_Integer i = 1; i <= Nb; i++) 
1144     LC.Append(myCenters(i));
1145 }
1146
1147
1148 //=======================================================================
1149 //function : Surface
1150 //purpose  : 
1151 //=======================================================================
1152
1153 Handle(Geom_Surface) BiTgte_Blend::Surface(const TopoDS_Shape& CenterLine) 
1154 const
1155
1156   const TopoDS_Face& F = myMapSF(CenterLine).Face();
1157   return BRep_Tool::Surface(F);
1158 }
1159
1160 //=======================================================================
1161 //function : TopoDS_Face&
1162 //purpose  : 
1163 //=======================================================================
1164
1165 const TopoDS_Face& BiTgte_Blend::Face(const TopoDS_Shape& CenterLine) const
1166 {
1167   if ( !myMapSF.IsBound(CenterLine)) {
1168     throw Standard_DomainError("BiTgte_Blend::Face");
1169   }
1170
1171   return myMapSF(CenterLine).Face();
1172 }
1173
1174 //=======================================================================
1175 //function : ContactType
1176 //purpose  : 
1177 //=======================================================================
1178
1179 BiTgte_ContactType BiTgte_Blend::ContactType(const Standard_Integer Index)
1180      const
1181 {
1182   const TopoDS_Shape& S1 = SupportShape1(Index);
1183   const TopoDS_Shape& S2 = SupportShape2(Index);
1184
1185   TopAbs_ShapeEnum Type1 = S1.ShapeType();
1186   TopAbs_ShapeEnum Type2 = S2.ShapeType();
1187   
1188   if (Type2 < Type1) {
1189     TopAbs_ShapeEnum Dummy = Type1;
1190     Type1 = Type2;
1191     Type2 = Dummy;
1192   }
1193   BiTgte_ContactType Type = BiTgte_VertexVertex;
1194
1195   switch (Type1) {
1196     
1197   case TopAbs_VERTEX:
1198     switch (Type2) {
1199     case TopAbs_VERTEX: Type = BiTgte_VertexVertex; break;
1200     case TopAbs_EDGE:   Type = BiTgte_EdgeVertex;   break;
1201     case TopAbs_FACE:   Type = BiTgte_FaceVertex;   break;
1202     default:
1203       break;
1204     }
1205     
1206   case TopAbs_EDGE:
1207     switch (Type2) {
1208     case TopAbs_EDGE:   Type = BiTgte_EdgeEdge; break;
1209     case TopAbs_FACE:   Type = BiTgte_FaceEdge; break;
1210     default:
1211       break;
1212    }
1213     
1214   case TopAbs_FACE:
1215     switch (Type2) {
1216     case TopAbs_FACE:   Type = BiTgte_FaceEdge; break;
1217     default:
1218       break;
1219     }
1220   default:
1221     break;
1222   }
1223   
1224   return Type;
1225 }
1226
1227
1228
1229 //=======================================================================
1230 //function : SupportShape1
1231 //purpose  : 
1232 //=======================================================================
1233
1234 const TopoDS_Shape& BiTgte_Blend::SupportShape1(const Standard_Integer Index)
1235      const
1236 {
1237   const TopoDS_Edge& CurE = TopoDS::Edge(myCenters(Index));
1238   
1239   const TopTools_ListOfShape& L = myAsDes->Ascendant(CurE);
1240     
1241   // --------------------------------------------------------------
1242   // F1 and F2 = 2 parallel faces intersecting at CurE.
1243   // --------------------------------------------------------------
1244   const TopoDS_Face& F1 = TopoDS::Face(L.First()); 
1245   const TopoDS_Shape& Or1 = myInitOffsetFace.ImageFrom(F1);
1246   return Or1;
1247 }
1248
1249
1250 //=======================================================================
1251 //function : SupportShape2
1252 //purpose  : 
1253 //=======================================================================
1254
1255 const TopoDS_Shape& BiTgte_Blend::SupportShape2(const Standard_Integer Index)
1256      const
1257 {
1258   const TopoDS_Edge& CurE = TopoDS::Edge(myCenters(Index));
1259   
1260   const TopTools_ListOfShape& L = myAsDes->Ascendant(CurE);
1261     
1262   // --------------------------------------------------------------
1263   // F1 and F2 = 2 parallel faces intersecting at CurE.
1264   // --------------------------------------------------------------
1265   const TopoDS_Face& F2 = TopoDS::Face(L.Last()); 
1266   const TopoDS_Shape& Or2 = myInitOffsetFace.ImageFrom(F2);
1267   return Or2;
1268 }
1269
1270
1271 //=======================================================================
1272 //function : CurveOnShape1
1273 //purpose  : 
1274 //=======================================================================
1275
1276 Handle(Geom_Curve) BiTgte_Blend::CurveOnShape1
1277 (const Standard_Integer Index) const
1278 {
1279   const TopoDS_Edge& CurE = TopoDS::Edge(myCenters(Index));
1280   const TopoDS_Shape& F = myMapSF(CurE).Face();
1281
1282   // somewhat brutal method based ONLY on the construction of the fillet:
1283   // the first edge of the tube is exactly the edge on Shape1.
1284
1285   TopExp_Explorer exp(F,TopAbs_EDGE);
1286   const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1287   Handle(Geom_Curve) C;
1288   if ( !BRep_Tool::Degenerated(E)) { 
1289     Standard_Real f,l;
1290     C = BRep_Tool::Curve(E,f,l);
1291     C = new Geom_TrimmedCurve(C,f,l);
1292   }
1293   return C;
1294 }
1295
1296
1297 //=======================================================================
1298 //function : CurveOnShape2
1299 //purpose  : 
1300 //=======================================================================
1301
1302 Handle(Geom_Curve) BiTgte_Blend::CurveOnShape2
1303 (const Standard_Integer Index) const
1304 {
1305   const TopoDS_Edge& CurE = TopoDS::Edge(myCenters(Index));
1306   const TopoDS_Shape& F = myMapSF(CurE).Face();
1307
1308   // somewhat brutal method based ONLY on the construction of the fillet:
1309   // the first edge of the tube is exactly the edge on Shape2.
1310
1311   TopExp_Explorer exp(F,TopAbs_EDGE);
1312   exp.Next();
1313   const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1314   Handle(Geom_Curve) C;
1315   if ( !BRep_Tool::Degenerated(E)) { 
1316     Standard_Real f,l;
1317     C = BRep_Tool::Curve(E,f,l);
1318     C = new Geom_TrimmedCurve(C,f,l);
1319   }
1320   return C;
1321 }
1322
1323
1324 //=======================================================================
1325 //function : PCurveOnFace1
1326 //purpose  : 
1327 //=======================================================================
1328
1329 Handle(Geom2d_Curve) BiTgte_Blend::PCurveOnFace1
1330 (const Standard_Integer /*Index*/) const
1331 {
1332   Handle(Geom2d_Curve) C;
1333   return C;
1334 }
1335
1336
1337 //=======================================================================
1338 //function : PCurve1OnFillet
1339 //purpose  : 
1340 //=======================================================================
1341
1342 Handle(Geom2d_Curve) BiTgte_Blend::PCurve1OnFillet
1343 (const Standard_Integer /*Index*/) const
1344 {
1345   Handle(Geom2d_Curve) C;
1346   return C;
1347 }
1348
1349
1350 //=======================================================================
1351 //function : PCurveOnFace2
1352 //purpose  : 
1353 //=======================================================================
1354
1355 Handle(Geom2d_Curve) BiTgte_Blend::PCurveOnFace2
1356 (const Standard_Integer /*Index*/) const
1357 {
1358   Handle(Geom2d_Curve) C;
1359   return C;
1360 }
1361
1362
1363 //=======================================================================
1364 //function : Curve2OnFillet
1365 //purpose  : 
1366 //=======================================================================
1367
1368 Handle(Geom2d_Curve) BiTgte_Blend::PCurve2OnFillet
1369 (const Standard_Integer /*Index*/) const
1370 {
1371   Handle(Geom2d_Curve) C;
1372   return C;
1373 }
1374
1375
1376
1377 //=======================================================================
1378 //function : NbBranches
1379 //purpose  : 
1380 //=======================================================================
1381
1382 Standard_Integer BiTgte_Blend::NbBranches() 
1383 {
1384   if (myNbBranches != -1) return myNbBranches;
1385
1386   // else, compute the Branches.
1387   BRepTools_Quilt Glue;
1388   
1389   Standard_Integer NbFaces = myCenters.Extent();
1390
1391
1392   if (NbFaces == 0) return 0;
1393
1394
1395   Standard_Integer i;
1396   for ( i = 1; i <= NbFaces; i++) {
1397     const TopoDS_Shape& CenterLine = myCenters(i);
1398     Glue.Add(myMapSF(CenterLine).Face()); 
1399   }
1400
1401   const TopoDS_Shape Shells = Glue.Shells();
1402
1403
1404   // Reorder Map myCenters.
1405   // The method is brutal and unpolished, 
1406   // it is possible to refine it.
1407   myNbBranches = 0;
1408   TopTools_IndexedMapOfShape tmpMap;
1409
1410   TopExp_Explorer exp(Shells,TopAbs_SHELL);
1411   for (; exp.More(); exp.Next()) {
1412     myNbBranches++;
1413   }
1414
1415   myIndices = new TColStd_HArray1OfInteger(1,myNbBranches+1);
1416
1417   myIndices->SetValue(1,0);
1418   Standard_Integer Count = 0;
1419   Standard_Integer Index = 2;
1420   
1421
1422   exp.Init(Shells,TopAbs_SHELL);
1423   for (; exp.More(); exp.Next()) {
1424     // CurS = the current Shell.
1425     const TopoDS_Shape CurS = exp.Current();
1426
1427     TopExp_Explorer exp2(CurS, TopAbs_FACE);
1428     for (; exp2.More(); exp2.Next()) {
1429       // CurF = the current face of the current Shell.
1430       const TopoDS_Shape CurF = exp2.Current();
1431
1432       for ( i = 1; i <= NbFaces; i++) {
1433         const TopoDS_Shape& Center = myCenters(i);
1434         const TopoDS_Shape& Rakk   = myMapSF(Center).Face();
1435         // Rakk = the ith generated connection face
1436         if (CurF.IsEqual(Rakk)) {
1437           tmpMap.Add(Center);
1438           Count++;
1439           break;
1440         }
1441       }
1442     }
1443     myIndices->SetValue(Index, Count);
1444     Index++;
1445   }
1446   
1447   myCenters = tmpMap;
1448   return myNbBranches;
1449 }
1450
1451
1452 //=======================================================================
1453 //function : IndicesOfBranche
1454 //purpose  : 
1455 //=======================================================================
1456
1457 void BiTgte_Blend::IndicesOfBranche
1458 (const Standard_Integer  Index,
1459        Standard_Integer& From,
1460        Standard_Integer& To   ) const 
1461 {
1462   // Attention to the ranking in myIndices:
1463   // If the branches are  1-4 5-9 10-12, it is ranked in myIndices:
1464   //                      0 4   9    12
1465   From = myIndices->Value(Index) + 1;
1466   To   = myIndices->Value(Index + 1);
1467 }
1468
1469
1470 //=======================================================================
1471 //function : ComputeCenters
1472 //purpose  : 
1473 //=======================================================================
1474
1475 void BiTgte_Blend::ComputeCenters() 
1476 {
1477   // ------------
1478   // Preanalyze.
1479   // ------------
1480   Standard_Real TolAngle = 2*ASin(myTol/Abs(myRadius*0.5));
1481   myAnalyse.Perform(myShape,TolAngle);
1482
1483   // ------------------------------------------
1484   // calculate faces touched by caps
1485   // ------------------------------------------
1486   TopTools_MapOfShape TouchedByCork;
1487   Touched(myAnalyse, myStopFaces, myShape, TouchedByCork);
1488
1489   // -----------------------
1490   // init of the intersector
1491   // -----------------------
1492   TopAbs_State       Side = TopAbs_IN;
1493   if (myRadius < 0.) Side = TopAbs_OUT;
1494   BRepOffset_Inter3d Inter(myAsDes,Side,myTol);
1495
1496   TopTools_DataMapOfShapeBox         MapSBox;
1497   TopTools_MapOfShape              Done;
1498   //TopTools_MapIteratorOfMapOfShape it;
1499
1500   BRep_Builder B;
1501   TopoDS_Compound Co; // to only know on which edges the tubes are made
1502   B.MakeCompound(Co);
1503
1504   // ----------------------------------------
1505   // Calculate Sections Face/Face + Propagation
1506   // ----------------------------------------
1507   Standard_Boolean JenRajoute = Standard_True;
1508   Standard_Integer i;
1509   
1510   while ( JenRajoute) {
1511     JenRajoute = Standard_False;
1512
1513     Standard_Boolean Fini = Standard_False;
1514
1515     TopTools_DataMapOfShapeShape EdgeTgt;
1516     
1517     while ( !Fini) {
1518
1519       // -------------------------------------------------
1520       // locate in myFaces the Faces connected to myEdges.
1521       // -------------------------------------------------
1522       Fini = Standard_True;
1523       //for (it.Initialize(myEdges); it.More(); it.Next()) {
1524       for (i = 1; i <= myEdges.Extent(); i++) {
1525         const TopoDS_Edge& E = TopoDS::Edge(myEdges(i));
1526         if (BRep_Tool::Degenerated(E)) continue;
1527
1528         const TopTools_ListOfShape& L = myAncestors.FindFromKey(E);
1529         if ( L.Extent() == 1) {
1530           // So this is a free border onwhich the ball should roll.
1531           myFaces.Add(E);
1532           
1533           // set in myStopFaces to not propagate the tube on free border.
1534           myStopFaces.Add(E);
1535         }
1536         else {
1537           TopTools_ListIteratorOfListOfShape itl;
1538           for (itl.Initialize(L); itl.More(); itl.Next()) {
1539             const TopoDS_Shape& Sh = itl.Value();
1540             if ( !myStopFaces.Contains(Sh)) myFaces.Add(itl.Value());
1541           }
1542         }
1543       }
1544       myEdges.Clear();
1545       
1546       // --------------------------------------------
1547       // Construction of Offsets of all faces.
1548       // --------------------------------------------
1549       //for (it.Initialize(myFaces); it.More(); it.Next()) {
1550       for (i = 1; i <= myFaces.Extent(); i++) {
1551         const TopoDS_Shape& AS = myFaces(i);
1552         if ( myMapSF.IsBound(AS)) continue;
1553
1554         BRepOffset_Offset OF1;
1555         TopoDS_Face BigF;
1556
1557         if (AS.ShapeType() == TopAbs_FACE) {
1558           const TopoDS_Face& F = TopoDS::Face(myFaces(i));
1559           if ( TouchedByCork.Contains(F)) {
1560             BRepOffset_Tool::EnLargeFace(F,BigF,Standard_True);
1561             OF1.Init(BigF,myRadius,EdgeTgt);
1562           }
1563           else {
1564             OF1.Init(F,myRadius,EdgeTgt);
1565           }
1566         }
1567         else { // So this is a Free Border edge on which the ball rolls.
1568           OF1.Init(TopoDS::Edge(AS),myRadius);
1569         }
1570
1571         // ------------------------------------
1572         // Increment the map of created tangents
1573         // ------------------------------------
1574         TopTools_ListOfShape Let;
1575         if ( AS.ShapeType() == TopAbs_FACE) { 
1576           myAnalyse.Edges(TopoDS::Face(AS),BRepOffset_Tangent,Let);
1577         }
1578         TopTools_ListIteratorOfListOfShape itlet(Let);
1579     
1580         for ( ; itlet.More(); itlet.Next()) {
1581           const TopoDS_Edge& Cur = TopoDS::Edge(itlet.Value());
1582           if ( !EdgeTgt.IsBound(Cur)) {
1583             TopoDS_Shape aLocalShape = OF1.Generated(Cur);
1584             const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
1585 //          const TopoDS_Edge& OTE = TopoDS::Edge(OF1.Generated(Cur));
1586             EdgeTgt.Bind(Cur,OF1.Generated(Cur));
1587             TopoDS_Vertex V1,V2,OV1,OV2;
1588             TopExp::Vertices (Cur,V1,V2);
1589             TopExp::Vertices (OTE,OV1,OV2);      
1590             TopTools_ListOfShape LE;
1591             if (!EdgeTgt.IsBound(V1)) {
1592               myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
1593               const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V1);
1594               if (LE.Extent() == LA.Extent())
1595                 EdgeTgt.Bind(V1,OV1);
1596             }
1597             if (!EdgeTgt.IsBound(V2)) {
1598               LE.Clear();
1599               myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
1600               const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V2);
1601               if (LE.Extent() == LA.Extent())
1602                 EdgeTgt.Bind(V2,OV2);
1603             }
1604           }
1605         }
1606         // end of map created tangent
1607
1608         if (OF1.Status() == BRepOffset_Reversed ||
1609             OF1.Status() == BRepOffset_Degenerated ) continue;
1610
1611         const TopoDS_Face& F1 = OF1.Face();
1612
1613         // increment S D
1614         myInitOffsetFace.SetRoot(AS);
1615         myInitOffsetFace.Bind(AS,F1);
1616
1617         Bnd_Box Box1;
1618         BRepBndLib::Add(F1,Box1);
1619         MapSBox.Bind(F1,Box1);
1620
1621         // ---------------------------------------------
1622         // intersection with all already created faces.
1623         // ---------------------------------------------
1624         Fini = !Intersect(AS,F1,MapSBox,OF1,Inter);
1625
1626         if (AS.ShapeType() == TopAbs_FACE) B.Add(Co,AS);
1627
1628         myMapSF.Bind(AS, OF1);
1629
1630       }
1631     } // end of : while ( !Fini)
1632
1633
1634     //--------------------------------------------------------
1635     // so the offsets were created and intersected.
1636     // now the tubes are constructed.
1637     //--------------------------------------------------------
1638     // Construction of tubes on edge.
1639     //--------------------------------------------------------
1640     BRepOffset_Type    OT = BRepOffset_Convex;
1641     if (myRadius < 0.) OT = BRepOffset_Concave; 
1642     
1643     TopTools_IndexedDataMapOfShapeListOfShape Map;
1644     TopExp::MapShapesAndAncestors(Co,TopAbs_EDGE,TopAbs_FACE,Map);
1645     TopExp::MapShapesAndAncestors(Co,TopAbs_VERTEX,TopAbs_EDGE,Map);
1646     
1647     TopExp_Explorer exp(Co,TopAbs_EDGE);
1648     for ( ; exp.More(); exp.Next()) {
1649       const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1650       if ( myMapSF.IsBound(E)) continue;
1651       
1652       const TopTools_ListOfShape& Anc = Map.FindFromKey(E);
1653       if (Anc.Extent() == 2) {
1654         const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
1655         if (!L.IsEmpty() && L.First().Type() == OT) {
1656           TopoDS_Shape aLocalShapeGen = myMapSF(Anc.First()).Generated(E);
1657           TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShapeGen);
1658     aLocalShapeGen = myMapSF(Anc.Last()) .Generated(E);
1659           TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShapeGen);
1660 //        TopoDS_Edge EOn1 = TopoDS::Edge(myMapSF(Anc.First()).Generated(E));
1661 //        TopoDS_Edge EOn2 = TopoDS::Edge(myMapSF(Anc.Last()) .Generated(E));
1662           // find if exits tangent edges in the original shape
1663           TopoDS_Edge E1f, E1l;
1664           TopoDS_Vertex V1f, V1l;
1665           TopExp::Vertices(E,V1f,V1l);
1666           TopTools_ListOfShape TangE;
1667           myAnalyse.TangentEdges(E,V1f,TangE);
1668           // find if the pipe on the tangent edges are soon created.
1669           TopTools_ListIteratorOfListOfShape itl(TangE);
1670           Standard_Boolean Find = Standard_False;
1671           for ( ; itl.More() && !Find; itl.Next()) {
1672             if ( myMapSF.IsBound(itl.Value())) {
1673               TopoDS_Shape aLocalShape = myMapSF(itl.Value()).Generated(V1f);
1674               E1f  = TopoDS::Edge(aLocalShape);
1675 //            E1f  = TopoDS::Edge(myMapSF(itl.Value()).Generated(V1f));
1676               Find = Standard_True;
1677             }
1678           }
1679           TangE.Clear();
1680           myAnalyse.TangentEdges(E,V1l,TangE);
1681           // find if the pipe on the tangent edges are soon created.
1682           itl.Initialize(TangE);
1683           Find = Standard_False;
1684           for ( ; itl.More() && !Find; itl.Next()) {
1685             if ( myMapSF.IsBound(itl.Value())) {
1686               TopoDS_Shape aLocalShape = myMapSF(itl.Value()).Generated(V1l);
1687               E1l  = TopoDS::Edge(aLocalShape);
1688 //            E1l  = TopoDS::Edge(myMapSF(itl.Value()).Generated(V1l));
1689               Find = Standard_True;
1690             }
1691           }
1692           BRepOffset_Offset OF1 (E,EOn1,EOn2,myRadius,E1f, E1l);
1693           const TopoDS_Face& F1 = OF1.Face();
1694
1695           // maj S D
1696           myInitOffsetFace.SetRoot(E);
1697           myInitOffsetFace.Bind(E,F1);
1698
1699           Bnd_Box Box1;
1700           BRepBndLib::Add(F1,Box1);
1701           MapSBox.Bind(F1,Box1);
1702
1703           // ---------------------------------------------
1704           // intersection with all already created faces.
1705           // ---------------------------------------------
1706           Standard_Boolean IsOnRest = Intersect(E,F1,MapSBox,OF1,Inter);
1707           JenRajoute = JenRajoute || IsOnRest;
1708
1709           myMapSF.Bind(E,OF1);
1710         }
1711       }
1712     }
1713     
1714   } // end while JenRajoute
1715   
1716
1717   myEdges.Clear();
1718   myEdges = Inter.NewEdges();
1719
1720   // -------------------------------------------------------------------
1721   // now it is necessary to limit edges on the neighbors (otherwise one 
1722   // will go too far and will not be able to construct faces).
1723   // -------------------------------------------------------------------
1724
1725   // Proceed with MakeLoops 
1726   TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
1727   BRepOffset_Type    OT = BRepOffset_Concave;
1728   if (myRadius < 0.) OT = BRepOffset_Convex; 
1729    
1730   TopTools_ListOfShape LOF;
1731   //it.Initialize(myFaces);
1732   for (i = 1; i <= myFaces.Extent(); i++) {
1733     const TopoDS_Shape& CurS  = myFaces(i);
1734
1735     // tube on free border, it is undesirable.
1736     if ( myStopFaces.Contains(CurS)) continue;
1737
1738     if ( !myMapSF.IsBound(CurS)) continue; // inverted or degenerated
1739
1740     const TopoDS_Face& CurOF = myMapSF(CurS).Face();
1741     LOF.Append(CurOF);
1742
1743     if (CurS.ShapeType() == TopAbs_FACE) {
1744       const TopoDS_Face& CurF = TopoDS::Face(CurS);
1745       TopExp_Explorer expe(CurF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1746       for (; expe.More(); expe.Next()) {
1747         // --------------------------------------------------------------
1748         // set in myAsDes the edges generated by limitations of the 
1749         // initial square if the type is correct (The edges that will 
1750         // disappear are not set)
1751         // --------------------------------------------------------------
1752         const TopoDS_Edge& CurE = TopoDS::Edge(expe.Current());
1753         const BRepOffset_ListOfInterval& L = myAnalyse.Type(CurE);
1754         if (!L.IsEmpty() && L.First().Type() != OT) {
1755           // a priori doe s not disappear, so it is set
1756           TopoDS_Shape aLocalShape = myMapSF(CurF).Generated(CurE);
1757           const TopoDS_Edge& CurOE = TopoDS::Edge(aLocalShape);
1758 //        const TopoDS_Edge& CurOE = 
1759 //          TopoDS::Edge(myMapSF(CurF).Generated(CurE));
1760           myAsDes->Add(CurOF,CurOE.Oriented(CurE.Orientation()));
1761         }
1762         else {
1763           const TopTools_ListOfShape& Lanc = myAnalyse.Ancestors(CurE);
1764           if (   !myFaces    .Contains(Lanc.First()) 
1765               || !myFaces    .Contains(Lanc.Last ())
1766               ||  myStopFaces.Contains(Lanc.First()) 
1767               ||  myStopFaces.Contains(Lanc.Last ())) {
1768             TopoDS_Shape aLocalShape = myMapSF(CurF).Generated(CurE);
1769             const TopoDS_Edge& CurOE = TopoDS::Edge(aLocalShape);
1770 //          const TopoDS_Edge& CurOE = 
1771 //            TopoDS::Edge(myMapSF(CurF).Generated(CurE));
1772             myAsDes->Add(CurOF,CurOE.Oriented(CurE.Orientation()));
1773           }
1774         }
1775       }
1776       BRepOffset_Inter2d::Compute(myAsDes,
1777                                   CurOF,
1778                                   myEdges,
1779                                   myTol,
1780                                   aDMVV);
1781     }
1782   }
1783
1784   // ----------------------------------------------------------------
1785   // It is also required to make 2D intersections with generated tubes
1786   // (Useful for unwinding)
1787   // ----------------------------------------------------------------
1788   BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(myMapSF);
1789   for ( ; It.More(); It.Next()) {
1790     const TopoDS_Shape& CurS = It.Key();
1791     if ( CurS.ShapeType() == TopAbs_FACE) continue;
1792
1793     const TopoDS_Face& CurOF = It.Value().Face();
1794
1795     // no unwinding by tubes on free border.
1796     if ( myStopFaces.Contains(CurS)) continue;
1797
1798     LOF.Append(CurOF);
1799
1800     // --------------------------------------------------------------
1801     // set in myAsDes the edge restrictions of the square
1802     // --------------------------------------------------------------
1803     TopExp_Explorer expe(CurOF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1804     for (; expe.More(); expe.Next()) {
1805       const TopoDS_Edge& CurOE = TopoDS::Edge(expe.Current());
1806       myAsDes->Add(CurOF,CurOE);
1807     }
1808
1809     BRepOffset_Inter2d::Compute(myAsDes,
1810                                 CurOF,
1811                                 myEdges,
1812                                 myTol,
1813                                 aDMVV);
1814   }
1815   //
1816   // fuse vertices on edges stored in AsDes
1817   BRepOffset_Inter2d::FuseVertices(aDMVV, myAsDes);
1818   // ------------
1819   // unwinding 
1820   // ------------
1821   BRepOffset_MakeLoops MakeLoops;
1822   MakeLoops.Build( LOF, myAsDes, myImageOffset );
1823
1824   // ------------------------------------------------------------
1825   // It is possible to unwind edges at least one ancestor which of 
1826   // is a face of the initial shape, so:
1827   // the edges generated by intersection tube-tube are missing
1828   // ------------------------------------------------------------
1829
1830   // --------------------------------------------------------------
1831   // Currently set the unwinded surfaces in <myResult>
1832   // --------------------------------------------------------------
1833   B.MakeCompound(TopoDS::Compound(myResult));
1834   TopTools_ListIteratorOfListOfShape itLOF(LOF);
1835   for ( ; itLOF.More(); itLOF.Next()) {
1836     const TopoDS_Shape& CurLOF = itLOF.Value();
1837
1838     if ( !myImageOffset.HasImage(CurLOF)) 
1839       continue;
1840     
1841     TopTools_ListOfShape Lim;
1842     myImageOffset.LastImage(CurLOF,Lim);
1843     TopTools_ListIteratorOfListOfShape itLim(Lim);
1844     for ( ;itLim.More(); itLim.Next()) {
1845       // If a face is its own image, it is not set
1846       const TopoDS_Shape& CurLIM = itLim.Value();
1847       if (CurLIM.IsSame(CurLOF)) break;
1848
1849       B.Add(myResult,CurLIM);
1850     }
1851   }
1852
1853 #ifdef OCCT_DEBUG
1854   if ( myResult.IsNull()) {
1855     std::cout << " No Lines of Generated Centers" << std::endl;
1856   }
1857 #ifdef DRAW
1858   else {
1859     if (Affich) DBRep::Set("Unwind",myResult);
1860   }
1861 #endif
1862 #endif
1863 }
1864
1865
1866 //=======================================================================
1867 //function : ComputeSurfaces
1868 //purpose  : 
1869 //=======================================================================
1870
1871 void BiTgte_Blend::ComputeSurfaces()
1872 {
1873   // set in myFaces, the faces actually implied in the connection
1874   myFaces.Clear();
1875
1876   // construct
1877   // 1 - Tubes (True Fillets)
1878   // 2 - Spheres.
1879
1880 #ifdef DRAW
1881   Standard_Integer nbc = 1;
1882 #endif
1883
1884   TopTools_ListOfShape Empty;
1885   TopTools_DataMapOfShapeListOfShape EmptyMap;
1886
1887   Handle(Geom_Surface) GS1, GS2;
1888   Handle(Geom_Curve)   GC1, GC2;
1889
1890   Standard_Real TolAngle = 2*ASin(myTol/Abs(myRadius*0.5));
1891   BRepOffset_Analyse CenterAnalyse(myResult,TolAngle);
1892
1893   // -----------------------------------------------------
1894   // Construction of tubes in myResult
1895   // -----------------------------------------------------
1896   BRep_Builder B;
1897   B.MakeCompound(TopoDS::Compound(myResult));
1898
1899   // --------------------------------------------------------------------
1900   // Dummy: for construction of spheres:
1901   // Set in Co the center line, then it there are at least 3
1902   // center lines sharing the same vertex, Sphere on this vertex.
1903   // --------------------------------------------------------------------
1904   TopoDS_Compound Co; 
1905   B.MakeCompound(Co);
1906
1907   // --------------------------------------------------------------------
1908   // Iteration on the edges lines of center
1909   // and their valid valid part is taken after cut and tube construction.
1910   // --------------------------------------------------------------------
1911
1912   //TopTools_MapIteratorOfMapOfShape ic(myEdges);
1913   Standard_Integer i;
1914   for (i = 1; i <= myEdges.Extent(); i++) {
1915     const TopoDS_Edge& CurE = TopoDS::Edge(myEdges(i));
1916
1917     const TopTools_ListOfShape& L = myAsDes->Ascendant(CurE);
1918     if ( L.Extent() != 2) continue;
1919     
1920     // --------------------------------------------------------------
1921     // F1 and F2 = 2 parallel faces intersecting in CurE.
1922     // --------------------------------------------------------------
1923     const TopoDS_Face& F1 = TopoDS::Face(L.First()); 
1924     const TopoDS_Face& F2 = TopoDS::Face(L.Last());
1925
1926     // -----------------------------------------------------
1927     // find the orientation of edges of intersection
1928     // in the initial faces.
1929     // -----------------------------------------------------
1930     const TopTools_ListOfShape& LD1 = myAsDes->Descendant(F1);
1931     const TopTools_ListOfShape& LD2 = myAsDes->Descendant(F2);
1932
1933     TopAbs_Orientation Orien1 = Orientation(CurE, F1, LD1);
1934     TopAbs_Orientation Orien2 = Orientation(CurE, F2, LD2);
1935     
1936     // ---------------------------------------------------------
1937     // Or1 and Or2 : the shapes generators of parallel faces 
1938     // ---------------------------------------------------------
1939     const TopoDS_Shape& Or1 = myInitOffsetFace.ImageFrom(F1);
1940     const TopoDS_Shape& Or2 = myInitOffsetFace.ImageFrom(F2);
1941
1942     myFaces.Add(Or1);
1943     myFaces.Add(Or2);
1944
1945     TopoDS_Edge     OE1, OE2;
1946     TopoDS_Face     OF1, OF2;
1947     TopLoc_Location Loc;
1948     Standard_Real   f1,l1,f2,l2;
1949     
1950     Standard_Boolean OF1isEdge = Standard_False;
1951     
1952     if ( Or1.ShapeType() == TopAbs_EDGE) {
1953       OF1isEdge = Standard_True;
1954       OE1 = TopoDS::Edge(Or1);
1955       GC1 = BRep_Tool::Curve(OE1,Loc,f1,l1);
1956       GC1 = 
1957         Handle(Geom_Curve)::DownCast(GC1->Transformed(Loc.Transformation()));
1958     }
1959     else if ( Or1.ShapeType() == TopAbs_FACE) {
1960       OF1 = TopoDS::Face(Or1);
1961       GS1 = BRep_Tool::Surface(OF1);
1962     }
1963
1964     // ----------------------------------------------------------------
1965     // If a vertex is used in contact, currently nothing is done  
1966     // and the vertexes are not managed (Intersections with sphere);
1967     // ----------------------------------------------------------------
1968     if ( OF1.IsNull() && OE1.IsNull()) continue;
1969     
1970     Standard_Boolean OF2isEdge = Standard_False;
1971     
1972     if ( Or2.ShapeType() == TopAbs_EDGE) {
1973       OF2isEdge = Standard_True;
1974       OE2 = TopoDS::Edge(Or2);
1975       GC2 = BRep_Tool::Curve(OE2,Loc,f2,l2);
1976       GC2 = 
1977         Handle(Geom_Curve)::
1978           DownCast(GC2->Transformed(Loc.Transformation()));
1979     }
1980     else if ( Or2.ShapeType() == TopAbs_FACE) {
1981       OF2 = TopoDS::Face(Or2);
1982       GS2 = BRep_Tool::Surface(OF2);
1983     }
1984     // ----------------------------------------------------------------
1985     // If a vertex is used in contact, currently nothing is done  
1986     // and the vertexes are not managed (Intersections with sphere);
1987     // ----------------------------------------------------------------
1988     if ( OF2.IsNull() && OE2.IsNull()) continue;
1989
1990
1991     TopTools_ListOfShape CurL;
1992
1993     if ( !myImageOffset.HasImage(CurE)) {// the tubes are not unwinded
1994       if ( OF1isEdge && OF2isEdge) {     // if I don't have the image, possibly
1995         CurL.Append(CurE);               // I'm on intersection tube-tube
1996       }                                  // See comment on the call to 
1997       else                               // MakeLoops
1998         continue;
1999     }
2000     else {
2001       myImageOffset.LastImage(CurE,CurL);
2002     }
2003
2004     // ---------------------------------------------------------------
2005     // CurL = List of edges descending from CurE ( = Cuts of CurE)
2006     // ---------------------------------------------------------------
2007     TopTools_ListIteratorOfListOfShape itl(CurL);
2008     for ( ; itl.More(); itl.Next()) {
2009       const TopoDS_Edge& CurCutE = TopoDS::Edge(itl.Value());
2010       
2011       Handle(Geom2d_Curve) PC1 = 
2012         BRep_Tool::CurveOnSurface(CurCutE,F1,f1,l1);
2013       Handle(Geom2d_Curve) PC2 = 
2014         BRep_Tool::CurveOnSurface(CurCutE,F2,f2,l2);
2015       if ( PC1.IsNull() || PC2.IsNull()) {
2016 #ifdef OCCT_DEBUG
2017         std::cout << "No PCurves on Intersections : No tubes constructed";
2018         std::cout << std::endl;
2019 #endif  
2020         continue;
2021       }
2022
2023       TopoDS_Edge   E1f, E1l;
2024       TopoDS_Vertex V1f, V1l;
2025       TopoDS_Vertex VfOnE1,VlOnE1,VfOnE2,VlOnE2;
2026       TopTools_ListOfShape TangE;
2027       TopTools_MapOfShape MapOnV1f, MapOnV1l;
2028
2029       TopExp::Vertices(CurCutE,V1f,V1l);
2030
2031       // find if the pipe on the tangent edges are soon created.
2032       // edges generated by V1f and V1l + Maj MapOnV1f/l
2033       E1f = FindCreatedEdge(V1f,CurCutE,myMapSF,MapOnV1f,
2034                             CenterAnalyse,myRadius,myTol);
2035
2036       E1l = FindCreatedEdge(V1l,CurCutE,myMapSF,MapOnV1l,
2037                             CenterAnalyse,myRadius,myTol);
2038       
2039       TopoDS_Edge E1, E2;
2040       if ( OF1isEdge) {
2041         BiTgte_CurveOnEdge ConE(CurCutE, OE1);
2042         Handle(Geom_Curve) C = MakeCurve(ConE);
2043         gp_Pnt P1 = C->Value(C->FirstParameter());
2044         gp_Pnt P2 = C->Value(C->LastParameter());
2045         VfOnE1 = FindVertex(P1,MapOnV1f,myTol);
2046         if ( VfOnE1.IsNull())
2047           VfOnE1 = FindVertex(P1,MapOnV1l,myTol);
2048         VlOnE1 = FindVertex(P2,MapOnV1l,myTol);
2049         if ( VlOnE1.IsNull()) 
2050           VlOnE1 = FindVertex(P2,MapOnV1f,myTol);
2051         if ( P1.SquareDistance(P2) < myTol*myTol) {
2052           //BRepOffset_Offset manages degenerated KPart 
2053           //It is REQUIRED that C should be a circle with ZERO radius
2054           E1 = MakeDegeneratedEdge(C,VfOnE1);
2055         }
2056         else {
2057           E1 = BRepLib_MakeEdge(C,VfOnE1,VlOnE1);
2058         }
2059       }
2060       else {
2061         gp_Pnt2d P2d;
2062         P2d = PC1->Value(f1);
2063         gp_Pnt P1 = GS1->Value(P2d.X(),P2d.Y());
2064         P2d = PC1->Value(l1);
2065         gp_Pnt P2 = GS1->Value(P2d.X(),P2d.Y());
2066         VfOnE1 = FindVertex(P1,MapOnV1f,myTol);
2067         VlOnE1 = FindVertex(P2,MapOnV1l,myTol);
2068         BRepLib_MakeEdge MKE(PC1,GS1,VfOnE1,VlOnE1,f1,l1);
2069         if (MKE.IsDone()) 
2070           E1 = MKE.Edge();
2071         else  {
2072           std::cout << "Edge Not Done" << std::endl;
2073           E1 = MKE.Edge();
2074         }
2075           
2076         KPartCurve3d(E1,PC1,GS1);
2077       }
2078
2079       if ( OF2isEdge) {
2080         BiTgte_CurveOnEdge ConE(CurCutE, OE2);
2081         Handle(Geom_Curve) C = MakeCurve(ConE);
2082         gp_Pnt P1 = C->Value(C->FirstParameter());
2083         gp_Pnt P2 = C->Value(C->LastParameter());
2084         VfOnE2 = FindVertex(P1,MapOnV1f,myTol);
2085         if ( VfOnE2.IsNull()) 
2086           VfOnE2 = FindVertex(P1,MapOnV1l,myTol);
2087         VlOnE2 = FindVertex(P2,MapOnV1l,myTol);
2088         if ( VlOnE2.IsNull())
2089           VlOnE2 = FindVertex(P2,MapOnV1f,myTol);
2090         if ( P1.SquareDistance(P2) < myTol*myTol) {
2091           //BRepOffset_Offset manages degenerated KParts
2092           //It is REQUIRED that C should be a circle with ZERO radius
2093           E2 = MakeDegeneratedEdge(C,VfOnE2);
2094         }
2095         else {
2096           E2 = BRepLib_MakeEdge(C,VfOnE2,VlOnE2);
2097         }
2098       }
2099       else {
2100         gp_Pnt2d P2d;
2101         P2d = PC2->Value(f2);
2102         gp_Pnt P1 = GS2->Value(P2d.X(),P2d.Y());
2103         P2d = PC2->Value(l2);
2104         gp_Pnt P2 = GS2->Value(P2d.X(),P2d.Y());
2105         VfOnE2 = FindVertex(P1,MapOnV1f,myTol);
2106         VlOnE2 = FindVertex(P2,MapOnV1l,myTol);
2107         BRepLib_MakeEdge MKE(PC2,GS2,VfOnE2,VlOnE2,f2,l2);
2108         if (MKE.IsDone()) 
2109           E2 = MKE.Edge();
2110         else {
2111           std::cout << "edge not Done" << std::endl;
2112           E2 = MKE.Edge();
2113         }
2114         KPartCurve3d(E2,PC2,GS2);
2115       }
2116       // Increment of the Map of Created if reconstruction of the Shape is required
2117       if ( myBuildShape) {
2118         myCreated.Bind(CurCutE,EmptyMap);
2119
2120         myCreated(CurCutE).Bind(Or1,Empty);
2121         myCreated(CurCutE)(Or1).Append(E1);
2122
2123         myCreated(CurCutE).Bind(Or2,Empty);
2124         myCreated(CurCutE)(Or2).Append(E2);
2125       }
2126
2127       // ----------------------------------------------------------
2128       // try to init E1f, E1l, if not found with Analysis.
2129       // Should happen only if the THEORETICALLY tangent edges 
2130       // are not actually tangent ( Cf: Approximation of lines 
2131       // of intersection that add noise.)
2132       // ----------------------------------------------------------
2133       TopoDS_Vertex aVertex1, aVertex2;
2134       if ( E1f.IsNull() && !VfOnE1.IsNull() && !VfOnE2.IsNull()) {
2135         TopTools_MapIteratorOfMapOfShape it(MapOnV1f);
2136         for ( ; it.More(); it.Next()) {
2137           const TopoDS_Edge& E = TopoDS::Edge(it.Key());
2138           if ( !E.IsNull()) {
2139             TopExp::Vertices(E, aVertex1, aVertex2);
2140             if ((aVertex1.IsSame(VfOnE1) && aVertex2.IsSame(VfOnE2)) ||
2141                 (aVertex2.IsSame(VfOnE1) && aVertex1.IsSame(VfOnE2))   ) {
2142               E1f = E;
2143               break;
2144             }
2145           }
2146         }
2147       }
2148       if ( E1l.IsNull() && !VlOnE1.IsNull() && !VlOnE2.IsNull()) {
2149         TopTools_MapIteratorOfMapOfShape it(MapOnV1l);
2150         for ( ; it.More(); it.Next()) {
2151           const TopoDS_Edge& E = TopoDS::Edge(it.Key());
2152           if ( !E.IsNull()) {
2153             TopExp::Vertices(E, aVertex1, aVertex2);
2154             if ((aVertex1.IsSame(VlOnE1) && aVertex2.IsSame(VlOnE2)) ||
2155                 (aVertex2.IsSame(VlOnE1) && aVertex1.IsSame(VlOnE2))   ) {
2156               E1l = E;
2157               break;
2158             }
2159           }
2160         }
2161       }
2162       
2163       E1.Orientation(Orien1);
2164       E2.Orientation(Orien2);
2165
2166       BRepOffset_Offset AnOffset(CurCutE,E1,E2,-myRadius,E1f,E1l,
2167                                  myNubs, myTol, GeomAbs_C2);
2168       myMapSF.Bind(CurCutE,AnOffset);
2169       myCenters.Add(CurCutE);
2170       B.Add(Co, CurCutE);
2171
2172       const TopoDS_Face& Tuyo = AnOffset.Face();
2173       B.Add(myResult,Tuyo);
2174
2175       if ( myBuildShape) {
2176         // method based ONLY on the construction of fillet:
2177         // the first edge of the tube is exactly on Shape1.
2178         GeomAPI_ProjectPointOnCurve Projector;
2179         TopExp_Explorer exp(Tuyo,TopAbs_EDGE);
2180         TopoDS_Vertex V1,V2;
2181         if (OF1isEdge) { // Update CutEdges.
2182           const TopoDS_Edge& EOnF1 = TopoDS::Edge(exp.Current());
2183           TopExp::Vertices(EOnF1,V1,V2);
2184
2185           gp_Pnt P1 = BRep_Tool::Pnt(V1);
2186           Projector.Init(P1,GC1);
2187           Standard_Real U1 = Projector.LowerDistanceParameter();
2188
2189           gp_Pnt P2 = BRep_Tool::Pnt(V2);
2190           Projector.Init(P2,GC1);
2191           Standard_Real U2 = Projector.LowerDistanceParameter();
2192
2193           TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
2194           B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,TopoDS::Edge(Or1),myTol);
2195           aLocalShape = V2.Oriented(TopAbs_INTERNAL);
2196           B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,TopoDS::Edge(Or1),myTol);
2197 //        B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),U1,
2198 //                       TopoDS::Edge(Or1),myTol);
2199 //        B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),U2,
2200 //                       TopoDS::Edge(Or1),myTol);
2201
2202           if (!myCutEdges.IsBound(Or1)) {
2203             TopTools_ListOfShape Dummy;
2204             myCutEdges.Bind(Or1,Dummy);
2205           }
2206           TopTools_ListOfShape& L1 = myCutEdges(Or1);
2207           L1.Append(V1); L1.Append(V2);
2208         }
2209         if (OF2isEdge) { // Update CutEdges.
2210           exp.Next();
2211           const TopoDS_Edge& EOnF2 = TopoDS::Edge(exp.Current());
2212           TopExp::Vertices(EOnF2,V1,V2);;
2213
2214           gp_Pnt P1 = BRep_Tool::Pnt(V1);
2215           Projector.Init(P1,GC2);
2216           Standard_Real U1 = Projector.LowerDistanceParameter();
2217
2218           gp_Pnt P2 = BRep_Tool::Pnt(V2);
2219           Projector.Init(P2,GC2);
2220           Standard_Real U2 = Projector.LowerDistanceParameter();
2221
2222           TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
2223           B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,TopoDS::Edge(Or2),myTol);
2224           aLocalShape = V2.Oriented(TopAbs_INTERNAL);
2225           B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,TopoDS::Edge(Or2),myTol);
2226 //        B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),U1,
2227 //                       TopoDS::Edge(Or2),myTol);
2228 //        B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),U2,
2229 //                       TopoDS::Edge(Or2),myTol);
2230
2231           if (!myCutEdges.IsBound(Or2)) {
2232             TopTools_ListOfShape Dummy;
2233             myCutEdges.Bind(Or2,Dummy);
2234           }
2235           TopTools_ListOfShape& L2 = myCutEdges(Or2);
2236           L2.Append(V1); L2.Append(V2);
2237         }
2238       }
2239
2240 #ifdef DRAW
2241       if ( Affich) {
2242         sprintf(name,"%s_%d","SURF",nbc);
2243         DBRep::Set(name,AnOffset.Face());
2244         nbc++;
2245       }
2246 #endif
2247     }
2248   }
2249
2250   // ---------------------------------------------------
2251   // Construction of spheres, 
2252   // if enough tubes arrive at the vertex
2253   // ---------------------------------------------------
2254   TopTools_IndexedDataMapOfShapeListOfShape Map;
2255   TopExp::MapShapesAndAncestors(Co,TopAbs_VERTEX,TopAbs_EDGE,Map);
2256   
2257   for ( Standard_Integer j = 1; j <= Map.Extent(); j++) {
2258     const TopoDS_Vertex& V = TopoDS::Vertex(Map.FindKey(j));
2259     if ( Map(j).Extent() != 3) continue;
2260
2261     TopTools_ListOfShape LOE;
2262     TopTools_ListIteratorOfListOfShape it;
2263     
2264     for (it.Initialize(Map(j)) ; it.More(); it.Next()) {
2265       Standard_Boolean Reverse = Standard_True;
2266       if ( Reverse) 
2267         LOE.Append(myMapSF(it.Value()).Generated(V).Reversed());
2268       else 
2269         LOE.Append(myMapSF(it.Value()).Generated(V));
2270     }
2271     
2272     BRepOffset_Offset OFT(V,LOE,-myRadius,myNubs, myTol, GeomAbs_C2);
2273     myMapSF.Bind(V,OFT);
2274     myCenters.Add(V);
2275
2276     B.Add(myResult,OFT.Face());
2277
2278 #ifdef DRAW
2279     if (Affich) {
2280       sprintf(name,"%s_%d","SURF",nbc);
2281       DBRep::Set(name,OFT.Face());
2282       nbc++;
2283     }
2284 #endif
2285   }
2286 }
2287
2288
2289 //=======================================================================
2290 //function : ComputeShape
2291 //purpose  : 
2292 //=======================================================================
2293 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
2294 #include <Geom_Curve.hxx>
2295
2296 void BiTgte_Blend::ComputeShape() 
2297 {
2298   // Find in the initial Shapel:
2299   //  - untouched Faces
2300   //  - generated tubes
2301   //  - the faces neighbors of tubes that sould be reconstucted preserving sharing.
2302
2303   // For Debug : Visualize edges of the initial shape that should be reconstructed.
2304 #ifdef DRAW
2305   if (Affich) {
2306     TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myCutEdges);
2307     Standard_Integer NbEdges = 0;
2308     for ( ; itm.More(); itm.Next()) {
2309       const TopoDS_Edge&          E    = TopoDS::Edge(itm.Key());
2310       const TopTools_ListOfShape& VonE = itm.Value();
2311       TopTools_ListOfShape NewE;
2312       
2313       CutEdge(E,VonE,NewE);
2314       for (TopTools_ListIteratorOfListOfShape it(NewE); it.More(); it.Next()) {
2315         sprintf(name,"%s_%d","CUTE",++NbEdges);
2316         DBRep::Set(name,it.Value());
2317       }
2318     }
2319   }
2320 #endif
2321   // end debug
2322
2323   TopTools_DataMapOfShapeShape Created;
2324
2325   TopTools_ListOfShape Empty;
2326   TopTools_DataMapOfShapeListOfShape EmptyMap;
2327   
2328   BRep_Builder B;
2329
2330
2331   // Maj of the Map of created.
2332   // Update edges that do not change in the resulting shape 
2333   // i.e. invariant edges in the unwinding.
2334   TopExp_Explorer exp(myShape,TopAbs_FACE);
2335   // Standard_Integer nbe = 1;
2336   for ( ;exp.More(); exp.Next()) {
2337
2338     const TopoDS_Face& CurF = TopoDS::Face(exp.Current());
2339
2340     if ( !myFaces.Contains(CurF)) continue; // so the face is not touched
2341
2342     // so the faces are unwinded
2343     if ( !myMapSF.IsBound(CurF)) continue; // inverted or degenerated
2344     
2345     const BRepOffset_Offset& Offset = myMapSF(CurF);
2346     const TopoDS_Face& CurOF = myMapSF(CurF).Face();
2347     
2348     if ( !myImageOffset.HasImage(CurOF)) // face disappears in unwinding
2349       continue;
2350     
2351     TopExp_Explorer exp2(CurF,TopAbs_EDGE);
2352     for ( ;exp2.More(); exp2.Next()) {
2353       const TopoDS_Edge& CurE  = TopoDS::Edge(exp2.Current());
2354       TopoDS_Shape aLocalShape = Offset.Generated(CurE);
2355       const TopoDS_Edge& CurOE = TopoDS::Edge(aLocalShape);
2356 //      const TopoDS_Edge& CurOE = TopoDS::Edge(Offset.Generated(CurE));
2357
2358       if (!myImageOffset.HasImage(CurOE)) continue; 
2359       // CurOE disappears
2360
2361       const TopoDS_Edge& ImE = 
2362         TopoDS::Edge(myImageOffset.Image(CurOE).First());
2363       if (ImE.IsSame(CurOE)) {
2364         myCreated.Bind(CurOE,EmptyMap);      
2365         myCreated(CurOE).Bind(CurF,Empty);
2366         myCreated(CurOE)(CurF).Append(CurE);
2367       }
2368     }
2369   }
2370
2371   // The connected faces are already in myResult.
2372   // So it is necessary to add faces:
2373   //    - non-touched (so not in myFaces)
2374   //    - issuing from the unwinding (non degenerated, non inverted, non disappeared)
2375   exp.Init(myShape,TopAbs_FACE);
2376   for ( ;exp.More(); exp.Next()) {
2377
2378     const TopoDS_Face& CurF = TopoDS::Face(exp.Current());
2379
2380     if ( !myFaces.Contains(CurF)) { 
2381       // so the face is not touched
2382       B.Add(myResult,CurF);
2383     }
2384     else { // so the faces are unwindeds
2385
2386       if ( !myMapSF.IsBound(CurF)) continue; // inverted or degenerated
2387
2388       const TopoDS_Face& CurOF = myMapSF(CurF).Face();
2389       
2390       if ( !myImageOffset.HasImage(CurOF)) // face disappears in unwinding
2391         continue;
2392       
2393       // List of faces generated by a face in the unwinding
2394       TopTools_ListOfShape Lim;
2395       myImageOffset.LastImage(CurOF,Lim);
2396       TopTools_ListIteratorOfListOfShape itLim(Lim);
2397       for ( ;itLim.More(); itLim.Next()) {
2398         // DeboucFace = offset Face unwinded in "Debouc".
2399         const TopoDS_Face& DeboucFace = TopoDS::Face(itLim.Value());
2400
2401         TopLoc_Location L;
2402         Handle(Geom_Surface) S = BRep_Tool::Surface(CurF,L);
2403         
2404         TopoDS_Face NewF; B.MakeFace(NewF);
2405         B.UpdateFace(NewF,S,L,BRep_Tool::Tolerance(CurF));
2406         
2407         TopTools_DataMapOfShapeShape MapSS;
2408                  
2409         TopoDS_Shape aLocalShape = DeboucFace.Oriented(TopAbs_FORWARD);
2410         const TopoDS_Face& Face = TopoDS::Face(aLocalShape);
2411 //      const TopoDS_Face& Face = 
2412 //        TopoDS::Face(DeboucFace.Oriented(TopAbs_FORWARD));
2413         TopExp_Explorer exp2(Face, TopAbs_EDGE);
2414         for ( ; exp2.More(); exp2.Next()) {
2415           const TopoDS_Edge& E = TopoDS::Edge(exp2.Current());
2416           TopoDS_Vertex V1,V2,OV1,OV2;
2417           TopExp::Vertices(E ,V1 ,V2 );
2418           if (myCreated.IsBound(E)) {
2419             if (myCreated(E).IsBound(CurF)) {
2420               const TopoDS_Edge& OE = TopoDS::Edge(myCreated(E)(CurF).First());
2421               TopExp::Vertices(OE,OV1,OV2);
2422               if ( !myCreated.IsBound(V1)) myCreated.Bind(V1,EmptyMap);
2423               if ( !myCreated.IsBound(V2)) myCreated.Bind(V2,EmptyMap);
2424               if ( !myCreated(V1).IsBound(CurF))  {
2425                 myCreated(V1).Bind(CurF,Empty);
2426                 myCreated(V1)(CurF).Append(OV1);
2427               }
2428               if ( !myCreated(V2).IsBound(CurF))  {
2429                 myCreated(V2).Bind(CurF,Empty);
2430                 myCreated(V2)(CurF).Append(OV2);
2431               }
2432             }
2433           }
2434         }
2435
2436         TopExp_Explorer expw(Face, TopAbs_WIRE);
2437         for ( ; expw.More(); expw.Next()) {
2438           const TopoDS_Wire& W = TopoDS::Wire(expw.Current());
2439           TopExp_Explorer expe(W.Oriented(TopAbs_FORWARD),
2440                                TopAbs_EDGE);
2441           TopoDS_Wire OW;
2442           B.MakeWire(OW);
2443           
2444           for ( ; expe.More(); expe.Next()) {
2445             const TopoDS_Edge& E = TopoDS::Edge(expe.Current());
2446             Standard_Real f,l;
2447             Handle(Geom2d_Curve) C2d = 
2448               BRep_Tool::CurveOnSurface(E,Face,f,l);
2449             TopoDS_Edge OE;
2450             if ( MapSS.IsBound(E)) { // this is an edge of cutting 
2451               OE = TopoDS::Edge(MapSS(E));
2452               TopoDS_Shape aLocalShapeReversedE = E.Reversed();
2453               Handle(Geom2d_Curve) C2d_1 = 
2454                 BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalShapeReversedE),Face,f,l);
2455 //            Handle(Geom2d_Curve) C2d_1 = 
2456 //              BRep_Tool::CurveOnSurface(TopoDS::Edge(E.Reversed()),
2457 //                                        Face,f,l);
2458               if ( E.Orientation() == TopAbs_FORWARD)
2459                 B.UpdateEdge(OE,C2d,C2d_1,NewF,BRep_Tool::Tolerance(E));
2460               else
2461                 B.UpdateEdge(OE,C2d_1,C2d,NewF,BRep_Tool::Tolerance(E));
2462               B.Range(OE,f,l);
2463             }
2464             else {
2465               // Is there an image in the Map of Created ?
2466               if ( myCreated.IsBound(E)) {
2467                 if ( myCreated(E).IsBound(CurF)) {
2468                   OE = TopoDS::Edge(myCreated(E)(CurF).First());
2469                 }
2470               }
2471               else {
2472                 B.MakeEdge(OE);
2473                 TopoDS_Vertex V1,V2,OV1,OV2;
2474                 TopExp::Vertices(E,V1,V2);
2475                 if ( myCreated.IsBound(V1) && myCreated(V1).IsBound(CurF)) {
2476                   OV1 = TopoDS::Vertex(myCreated(V1)(CurF).First());
2477                 }
2478                 else {
2479                   B.MakeVertex(OV1);
2480                   gp_Pnt2d P2d = 
2481                     C2d->Value(BRep_Tool::Parameter(V1,E,Face));
2482                   gp_Pnt P;
2483                   S->D0(P2d.X(),P2d.Y(),P);
2484                   P.Transform(L.Transformation());
2485                   B.UpdateVertex(OV1,P,BRep_Tool::Tolerance(V1));
2486                   myCreated.Bind(V1,EmptyMap);
2487                   myCreated(V1).Bind(CurF,Empty);
2488                   myCreated(V1)(CurF).Append(OV1);
2489                 }
2490                 if ( myCreated.IsBound(V2) && myCreated(V2).IsBound(CurF)) {
2491                   OV2 = TopoDS::Vertex(myCreated(V2)(CurF).First());
2492                 }
2493                 else {
2494                   B.MakeVertex(OV2);
2495                   gp_Pnt2d P2d = 
2496                     C2d->Value(BRep_Tool::Parameter(V2,E,Face));
2497                   gp_Pnt P;
2498                   S->D0(P2d.X(),P2d.Y(),P);
2499                   P.Transform(L.Transformation());
2500                   B.UpdateVertex(OV2,P,BRep_Tool::Tolerance(V2));
2501                   myCreated.Bind(V2,EmptyMap);
2502                   myCreated(V2).Bind(CurF,Empty);
2503                   myCreated(V2)(CurF).Append(OV2);
2504                 }
2505                 B.Add(OE,OV1.Oriented(V1.Orientation()));
2506                 B.Add(OE,OV2.Oriented(V2.Orientation()));
2507               }
2508               B.UpdateEdge(OE,C2d,NewF,BRep_Tool::Tolerance(E));
2509               B.Range(OE,f,l);
2510 //            ComputeCurve3d(OE,C2d,TheSurf,L,BRep_Tool::Tolerance(E));
2511               MapSS.Bind(E,OE);
2512             }
2513             B.Add(OW, OE.Oriented(E.Orientation()));
2514           }
2515           B.Add(NewF, OW.Oriented(W.Orientation()));
2516         }
2517
2518         NewF.Orientation(DeboucFace.Orientation());
2519   
2520         BRepTools::Update(NewF);
2521         B.Add(myResult,NewF);
2522       }
2523     }
2524   }
2525
2526   // non-regarding the cause, there always remain greeb borders on this Shape, so it is sewn.
2527   Handle(BRepBuilderAPI_Sewing) Sew = new BRepBuilderAPI_Sewing(myTol);
2528   
2529   BRepLib::BuildCurves3d(myResult);
2530   
2531   exp.Init(myResult,TopAbs_FACE);
2532   for ( ;exp.More(); exp.Next())
2533     Sew->Add(exp.Current());
2534   
2535   Sew->Perform();
2536
2537   // SameParameter is done in case Sew does not do it (Detect that the edges
2538   // are not sameparameter but does nothing.)
2539   
2540   const TopoDS_Shape& SewedShape = Sew->SewedShape();
2541   if ( !SewedShape.IsNull()) {
2542     exp.Init(Sew->SewedShape(), TopAbs_EDGE);
2543     for (; exp.More(); exp.Next()) {
2544       const TopoDS_Edge& sec = TopoDS::Edge(exp.Current());
2545       BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec));
2546     }
2547     myResult = SewedShape;
2548   }
2549 }
2550
2551
2552 //=======================================================================
2553 //function : Intersect
2554 //purpose  : 
2555 //=======================================================================
2556
2557 Standard_Boolean BiTgte_Blend::Intersect
2558 (const TopoDS_Shape&             Init,
2559  const TopoDS_Face&              Face,
2560  const TopTools_DataMapOfShapeBox& MapSBox,
2561  const BRepOffset_Offset&        OF1,
2562        BRepOffset_Inter3d&       Inter) 
2563 {
2564   Standard_Boolean JenRajoute = Standard_False;
2565
2566   const Bnd_Box& Box1 = MapSBox(Face);
2567
2568   // -----------------------------------------------
2569   // intersection with all already created faces.
2570   // -----------------------------------------------
2571   const TopoDS_Shape& InitShape1 = OF1.InitialShape();
2572   Standard_Boolean F1surBordLibre = 
2573     InitShape1.ShapeType() == TopAbs_EDGE &&
2574       myStopFaces.Contains(InitShape1);
2575
2576   TopTools_MapOfShape Done;
2577   BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(myMapSF);
2578   for ( ; It.More(); It.Next()) {
2579     const BRepOffset_Offset& OF2 = It.Value();
2580     const TopoDS_Face&       F2  = OF2.Face();
2581     
2582     if (Box1.IsOut(MapSBox(F2))) continue;
2583     
2584     if ( Inter.IsDone(Face,F2)) continue;
2585     
2586     // 2 tubes created on free border are not intersected.
2587     const TopoDS_Shape& InitShape2 = OF2.InitialShape();
2588     Standard_Boolean F2surBordLibre = 
2589       InitShape2.ShapeType() == TopAbs_EDGE &&
2590         myStopFaces.Contains(InitShape2);
2591
2592 #ifdef OCCT_DEBUG
2593     if ( F1surBordLibre && F2surBordLibre) {
2594       std::cout << "Rejection : 2 tubes on free border are not intersected";
2595       std::cout << std::endl;
2596     }
2597 #endif
2598
2599     if ( F1surBordLibre && F2surBordLibre) continue;
2600
2601     // -------------------------------------------------------
2602     // Tubes are not intersected with neighbor faces.
2603     // -------------------------------------------------------
2604     const TopoDS_Shape& ItKey = It.Key();
2605
2606     if ( Init.ShapeType() == TopAbs_EDGE) {
2607       if (ItKey.ShapeType() == TopAbs_FACE &&
2608           IsInFace(TopoDS::Edge(Init), TopoDS::Face(ItKey)))  continue;
2609     }
2610     
2611     Inter.FaceInter(Face,F2,myInitOffsetFace);
2612     
2613     // ------------------------------------------
2614     // an edge of F1 or F2 has been touched ?
2615     // if yes, add faces in myFaces
2616     //   ==> JenRajoute = True
2617     // ------------------------------------------
2618     TopTools_ListOfShape LInt;
2619     Done.Clear();
2620     if (myAsDes->HasCommonDescendant(Face,F2,LInt)) {
2621       TopTools_ListIteratorOfListOfShape  itl2;
2622       for (itl2.Initialize(LInt); itl2.More(); itl2.Next()) {
2623         const TopoDS_Edge& CurE = TopoDS::Edge(itl2.Value());
2624         TopoDS_Vertex V1,V2;
2625         TopoDS_Edge   E1,E2;
2626         TopExp::Vertices(CurE,V1,V2);
2627         
2628         if ( Done.Add(V1)) {
2629           Standard_Boolean IsOnR1 = IsOnRestriction(V1,CurE,Face,E1);
2630           Standard_Boolean IsOnR2 = IsOnRestriction(V1,CurE,F2,E2);
2631 #ifdef OCCT_DEBUG
2632           if (IsOnR1 && IsOnR2) {
2633             std::cout << "Leave in the same tps on 2 faces, ";
2634             std::cout << "propagation only on free border";
2635             std::cout << std::endl;
2636           }
2637 #endif
2638           if ( IsOnR1 ) {
2639             if ( !myStopFaces.Contains(Init)) {
2640               Add(E1,myEdges,Init,OF1,myAnalyse,IsOnR1 && IsOnR2);
2641               JenRajoute = Standard_True;
2642             }
2643           }
2644           if ( IsOnR2) {
2645             if ( !myStopFaces.Contains(ItKey)) {
2646               Add(E2,myEdges, ItKey,OF2,myAnalyse,IsOnR1 && IsOnR2);
2647               JenRajoute = Standard_True;
2648             }
2649           }
2650         }
2651
2652         if ( Done.Add(V2)) {
2653           Standard_Boolean IsOnR1 = IsOnRestriction(V2,CurE,Face,E1);
2654           Standard_Boolean IsOnR2 = IsOnRestriction(V2,CurE,F2,E2);
2655
2656           // If IsOnR1 && IsOnR2,
2657           // Leave in the same tps on 2 faces, propagate only on 
2658           // free borders.
2659           // A priori, only facet is closed.
2660 #ifdef OCCT_DEBUG
2661           if (IsOnR1 && IsOnR2) {
2662             std::cout << "Leave with the same tps on 2 faces, ";
2663             std::cout << "propagate only if the border is free";
2664             std::cout << std::endl;
2665           }
2666 #endif
2667           if ( IsOnR1) {
2668             if ( !myStopFaces.Contains(Init)) {
2669               Add(E1,myEdges,Init,OF1,myAnalyse,IsOnR1 && IsOnR2);
2670               JenRajoute = Standard_True;
2671             }
2672           }
2673           if ( IsOnR2) {
2674             if ( !myStopFaces.Contains(ItKey)) {
2675               Add(E2,myEdges,ItKey,OF2,myAnalyse,IsOnR1 && IsOnR2);
2676               JenRajoute = Standard_True;
2677             }
2678           }
2679         }
2680       }
2681     }
2682   }
2683
2684   return JenRajoute;
2685 }
2686
2687