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