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