93e55f83c519c1e26e5fc016e08d2d8776ac0cba
[occt.git] / src / ChFi2d / ChFi2d_Builder.cxx
1 // Created on: 1995-07-07
2 // Created by: Joelle CHAUVET
3 // Copyright (c) 1995-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
9 // under the terms of the GNU Lesser General Public 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 // Modified:    Tue Oct 15 10:12:02 1996
18 //              correction in BuildFilletEdge (PRO3529 : computation of dist)
19 // Modified:    Tue Oct 22 09:23:11 1996
20 //              correction in BuildFilletEdge (PRO5827 : computation of vec1)
21 // Modified:    Tue Oct 22 09:23:11 1996
22 //              new status in ComputeFillet for degenerated edges (PRO4896)
23 // Modified:    Thu Dec  5 16:25:44 1996
24 //              correction in BuildFilletEdge (PRO4896 : NewExtr1, NewExtr2)
25 // Modified:    Tue Apr 22 16:25:44 1996
26 //              correction in BuildFilletEdge (ID140047 : inside)
27 // Modified:    Fri Oct 24 10:47:52 1997
28 //              distinction point de tangence --> on arrete
29 //                         point de rebroussement --> on continue
30 //              (PRO10404 : Ve3, Ve4)
31 // Modified:    Tue Oct 28 11:55:53 1997
32 //              construction de filletEdge avec les parametres U1 et Vv1
33 //              au lieu des vertex (PRO10434)
34 // Modified:    Tue Apr  7 14:35:58 1998
35 //              construction de filletEdge avec les parametres U1 et Vv1
36 //              ET les vertex NewExtr1, NewExtr2 sinon pb sur qq aretes
37 //              degenerees (GER60069 + controle de PRO10434)
38 // Modified:    Mon Jun 22 13:32:25 1998
39 //              verification de la validite des parametres (PRO13078 partiel)
40 // Modified:    Fri Sep 25 09:38:04 1998
41 //              status = ChFi2d_NotAuthorized si les aretes ne sont pas
42 //              des droites ou des cercles; fonction IsLineOrCircle
43 //              (BUC60288)
44
45
46
47 #include <ChFi2d.hxx>
48 #include <ChFi2d_Builder.ixx>
49
50 #include <BRepAdaptor_Surface.hxx>
51 #include <BRepLib.hxx>
52 #include <BRepLib_MakeEdge.hxx>
53 #include <BRepLib_MakeFace.hxx>
54
55 #include <BRep_Builder.hxx>
56 #include <BRep_Tool.hxx>
57
58 #include <ElCLib.hxx>
59
60 #include <GccEnt_Position.hxx>
61
62 #include <Geom_Circle.hxx>
63 #include <Geom_Curve.hxx>
64 #include <Geom_Line.hxx>
65 #include <Geom_Plane.hxx>
66 #include <Geom_Surface.hxx>
67
68
69 #include <Geom2d_TrimmedCurve.hxx>
70 #include <Geom2d_Circle.hxx>
71 #include <Geom2d_Curve.hxx>
72 #include <Geom2d_Line.hxx>
73
74 #include <Geom2dInt_GInter.hxx>
75 #include <Geom2dGcc_Circ2d2TanRad.hxx>
76 #include <Geom2dGcc_QualifiedCurve.hxx>
77
78 #include <IntRes2d_IntersectionPoint.hxx>
79
80 #include <gp_Pln.hxx>
81 #include <gp_Pnt.hxx>
82 #include <gp_Pnt2d.hxx>
83 #include <gp_Circ2d.hxx>
84 #include <gp_Vec2d.hxx>
85
86 #include <Precision.hxx>
87
88 #include <TopAbs_Orientation.hxx>
89 #include <TopExp.hxx>
90 #include <TopExp_Explorer.hxx>
91 #include <TopLoc_Location.hxx>
92 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
93 #include <TopTools_ListIteratorOfListOfShape.hxx>
94 #include <TopTools_IndexedMapOfShape.hxx>
95
96 #include <TopoDS.hxx>
97 #include <TopoDS_Edge.hxx>
98 #include <TopoDS_Wire.hxx>
99
100 static Standard_Boolean IsIssuedFrom(const TopoDS_Edge& E,
101                                      const TopTools_IndexedMapOfShape& Map,
102                                      TopoDS_Edge& BasisEdge);
103
104 static Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E,
105                                        const TopoDS_Face& F);
106
107
108 //=======================================================================
109 //function : ChFi2d_Builder
110 //purpose  : 
111 //=======================================================================
112
113  ChFi2d_Builder::ChFi2d_Builder()
114 {
115 }
116
117 //=======================================================================
118 //function : ChFi2d_Builder
119 //purpose  : 
120 //=======================================================================
121
122  ChFi2d_Builder::ChFi2d_Builder(const TopoDS_Face& F)
123 {
124   if (F.IsNull()) {
125     status = ChFi2d_NoFace;
126     return;
127   }
128   TopLoc_Location Loc;
129 //  syntaxe invalide sur NT
130 //  const Handle(Geom_Surface)&  surf = BRep_Tool::Surface( F, Loc);
131 //  if (surf->IsKind(STANDARD_TYPE(Geom_Plane))) {
132   if ( BRep_Tool::Surface( F, Loc)
133                         -> IsKind(STANDARD_TYPE(Geom_Plane)) ) {
134     newFace = refFace = F;
135     newFace.Orientation(TopAbs_FORWARD);
136     BRepLib::BuildCurves3d(newFace);
137     status = ChFi2d_Ready;
138   }
139   else status = ChFi2d_NotPlanar;
140 } // ChFi2d_Builder
141
142 //=======================================================================
143 //function : Init
144 //purpose  : 
145 //=======================================================================
146
147 void ChFi2d_Builder::Init(const TopoDS_Face& F)
148 {
149   if (F.IsNull()) {
150     status = ChFi2d_NoFace;
151     return;
152   }
153   fillets.Clear();
154   chamfers.Clear();
155   history.Clear();
156   TopLoc_Location Loc;
157 //  syntaxe invalide sur NT
158 //  const Handle(Geom_Surface)&  surf = BRep_Tool::Surface( F, Loc);
159 //  if (surf->IsKind(STANDARD_TYPE(Geom_Plane))) {
160   if ( BRep_Tool::Surface( F, Loc)
161                         -> IsKind(STANDARD_TYPE(Geom_Plane)) ) {
162     newFace = refFace = F;
163     newFace.Orientation(TopAbs_FORWARD);
164     status = ChFi2d_Ready;
165   }
166   else status = ChFi2d_NotPlanar;
167 } // Init
168
169
170 //=======================================================================
171 //function : Init
172 //purpose  : 
173 //=======================================================================
174
175 void ChFi2d_Builder::Init(const TopoDS_Face& RefFace, 
176                         const TopoDS_Face& ModFace)
177 {
178   if (RefFace.IsNull() || ModFace.IsNull()) {
179     status = ChFi2d_NoFace;
180     return;
181   }
182   fillets.Clear();
183   chamfers.Clear();
184   history.Clear();
185   TopLoc_Location loc;
186 //  syntaxe invalide sur NT
187 //  const Handle(Geom_Surface)&  surf = BRep_Tool::Surface( RefFace, Loc);
188 //  if (!surf->IsKind(STANDARD_TYPE(Geom_Plane))) {
189   if ( ! BRep_Tool::Surface( RefFace, loc)
190               -> IsKind(STANDARD_TYPE(Geom_Plane)) ) {
191     status = ChFi2d_NotPlanar;
192     return;
193   }
194
195   refFace = RefFace;
196   newFace = ModFace;
197   newFace.Orientation(TopAbs_FORWARD);
198   status = ChFi2d_Ready;
199
200   // Research in newFace all the edges which not appear in RefFace
201   // The sequence newEdges will contains this edges.
202
203   TopTools_SequenceOfShape newEdges;
204   TopTools_IndexedMapOfShape refEdgesMap;
205   TopExp::MapShapes(refFace, TopAbs_EDGE, refEdgesMap);
206   TopExp_Explorer ex(newFace, TopAbs_EDGE);
207   while (ex.More()){
208     const TopoDS_Edge& currentEdge = TopoDS::Edge(ex.Current());
209     if (!refEdgesMap.Contains(currentEdge))
210       newEdges.Append(currentEdge);
211     ex.Next();
212   } // while (ex ...
213
214   // update of history, fillets and chamfers fields
215   Standard_Integer i = 1;
216   Standard_Real first, last;
217   TopoDS_Edge basisEdge;
218   while ( i <= newEdges.Length()) {
219     const TopoDS_Edge& currentEdge = TopoDS::Edge(newEdges.Value(i));
220     if (IsIssuedFrom(currentEdge, refEdgesMap, basisEdge))
221       history.Bind(basisEdge, currentEdge);
222     else {
223       // this edge is a chamfer or a fillet
224 //  syntaxe invalide sur NT
225 //      const Handle(Geom_Curve)& curve = 
226 //      BRep_Tool::Curve(currentEdge, loc, first, last);
227       Handle(Geom_Curve) curve = 
228         BRep_Tool::Curve(currentEdge, loc, first, last);
229       if (curve->IsKind(STANDARD_TYPE(Geom_Circle))) {
230         fillets.Append(currentEdge);
231       }
232       else if (curve->IsKind(STANDARD_TYPE(Geom_Line))) {
233         chamfers.Append(currentEdge);
234       }
235       else {
236         status = ChFi2d_InitialisationError;
237         return;
238       } // else ...
239     } // this edge is ...
240     i++;
241   } // while ...
242 } // Init
243
244
245 //=======================================================================
246 //function : IsIssuedFrom
247 //purpose  : Search in <Map> if <E> has a parent edge. If a parent has 
248 //           been find, this edge is returned in <BasisEdge>, else <E> is
249 //           returned in <BasisEdge>.
250 //=======================================================================
251 Standard_Boolean IsIssuedFrom(const TopoDS_Edge& E,
252                               const TopTools_IndexedMapOfShape& Map,
253                               TopoDS_Edge& BasisEdge)
254 {
255   TopLoc_Location loc1, loc2;
256   Standard_Real f1, L1, f2, L2;
257 //  syntaxe invalide sur NT
258 //  const Handle(Geom_Curve)& c1 = 
259 //    BRep_Tool::Curve(E, loc1, f1, L1);
260   Handle(Geom_Curve) c1 = BRep_Tool::Curve(E, loc1, f1, L1);
261
262   for (Standard_Integer i = 1; i <= Map.Extent(); i++ ) {
263     const TopoDS_Edge& currentEdge = TopoDS::Edge(Map.FindKey(i));
264 //  syntaxe invalide sur NT
265 //    const Handle(Geom_Curve)& c2 = 
266 //      BRep_Tool::Curve(currentEdge, loc2, f2, L2);
267     Handle(Geom_Curve) c2 = BRep_Tool::Curve(currentEdge, loc2, f2, L2);
268     if (c1 == c2 &&
269         (((f1 > f2 && f1 < L2) || (L1 > f2 && L1 < L2) ) ||
270         ( (f1 > L2 && f1 < f2) || (L1 > L2 && L1 < f2) )) ) {
271       BasisEdge = currentEdge;
272       BasisEdge.Orientation(E.Orientation());
273       return Standard_True;
274     } //  if (c1 == c2
275   } // for (Standard_Integer i ...
276
277   return Standard_False;
278 } // IsIssuedFrom
279
280
281 //=======================================================================
282 //function : AddFillet
283 //purpose  : 
284 //=======================================================================
285  TopoDS_Edge ChFi2d_Builder::AddFillet(const TopoDS_Vertex& V,
286                                      const Standard_Real Radius)
287 {
288   TopoDS_Edge adjEdge1, adjEdge2, basisEdge1, basisEdge2;
289   TopoDS_Edge adjEdge1Mod, adjEdge2Mod, fillet;
290   status = ChFi2d::FindConnectedEdges(newFace, V, adjEdge1, adjEdge2);
291   if (status == ChFi2d_ConnexionError) return fillet;
292
293   if (IsAFillet(adjEdge1) || IsAChamfer(adjEdge1) ||
294       IsAFillet(adjEdge2) || IsAChamfer(adjEdge2)) {
295     status = ChFi2d_NotAuthorized;
296     return fillet;
297   } //  if (IsAFillet ...
298
299   if (!IsLineOrCircle(adjEdge1,newFace) 
300       || !IsLineOrCircle(adjEdge2,newFace) ) {
301     status = ChFi2d_NotAuthorized;
302     return fillet;
303   } //  if (!IsLineOrCircle ...
304
305   ComputeFillet(V, adjEdge1, adjEdge2, Radius,
306                 adjEdge1Mod, adjEdge2Mod, fillet);
307   if (status == ChFi2d_IsDone
308       || status == ChFi2d_FirstEdgeDegenerated
309       || status == ChFi2d_LastEdgeDegenerated
310       || status == ChFi2d_BothEdgesDegenerated) {
311     BuildNewWire(adjEdge1, adjEdge2, adjEdge1Mod, fillet, adjEdge2Mod);
312     basisEdge1 = BasisEdge(adjEdge1);
313     basisEdge2 = BasisEdge(adjEdge2);
314     UpDateHistory(basisEdge1, basisEdge2,
315                   adjEdge1Mod, adjEdge2Mod, fillet, 1);
316     status = ChFi2d_IsDone;
317     return TopoDS::Edge(fillets.Value(fillets.Length()));
318   }
319   return fillet;
320 } // AddFillet
321
322 //=======================================================================
323 //function : ModifyFillet
324 //purpose  : 
325 //=======================================================================
326
327 TopoDS_Edge ChFi2d_Builder::ModifyFillet(const TopoDS_Edge& Fillet,
328                                        const Standard_Real Radius)
329 {
330  TopoDS_Vertex aVertex = RemoveFillet(Fillet);
331   TopoDS_Edge aFillet = AddFillet(aVertex, Radius);
332  return aFillet;
333 } // ModifyFillet
334
335 //=======================================================================
336 //function : RemoveFillet
337 //purpose  : 
338 //=======================================================================
339
340 TopoDS_Vertex ChFi2d_Builder::RemoveFillet(const TopoDS_Edge& Fillet)
341 {
342   TopoDS_Vertex commonVertex;
343   Standard_Integer i = 1;
344   Standard_Integer IsFind = Standard_False;
345   while (i <= fillets.Length()) {
346     const TopoDS_Edge& aFillet = TopoDS::Edge(fillets.Value(i));
347     if (aFillet.IsSame(Fillet)) {
348       fillets.Remove(i);
349       IsFind = Standard_True;
350       break;
351     }
352     i++;
353   }
354   if (!IsFind) return commonVertex;
355
356     
357   TopoDS_Vertex firstVertex, lastVertex;
358   TopExp::Vertices(Fillet, firstVertex, lastVertex);
359
360
361   TopoDS_Edge adjEdge1, adjEdge2;
362   status = ChFi2d::FindConnectedEdges(newFace, firstVertex,
363                                      adjEdge1, adjEdge2);
364   if (status == ChFi2d_ConnexionError) return commonVertex;
365
366   TopoDS_Edge basisEdge1, basisEdge2, E1, E2;
367   // E1 and E2 are the adjacent edges to Fillet
368
369   if (adjEdge1.IsSame(Fillet)) E1 = adjEdge2;
370   else E1 = adjEdge1;
371   basisEdge1 = BasisEdge(E1);
372   status = ChFi2d::FindConnectedEdges(newFace, lastVertex,adjEdge1, adjEdge2);
373   if (status == ChFi2d_ConnexionError) return commonVertex;
374   if (adjEdge1.IsSame(Fillet)) E2 = adjEdge2;
375   else E2 = adjEdge1;
376   basisEdge2 = BasisEdge(E2);
377   TopoDS_Vertex connectionE1Fillet, connectionE2Fillet;
378   Standard_Boolean hasConnection = 
379     ChFi2d::CommonVertex(basisEdge1, basisEdge2, commonVertex);
380   if (!hasConnection) {
381     status = ChFi2d_ConnexionError;
382     return commonVertex;
383   }
384   hasConnection = ChFi2d::CommonVertex(E1, Fillet, connectionE1Fillet);
385   if (!hasConnection) {
386     status = ChFi2d_ConnexionError;
387     return commonVertex;
388   }
389   hasConnection = ChFi2d::CommonVertex(E2, Fillet, connectionE2Fillet);
390   if (!hasConnection) {
391     status = ChFi2d_ConnexionError;
392     return commonVertex;
393   }
394
395   // rebuild edges on wire
396   TopoDS_Edge newEdge1, newEdge2;
397   TopoDS_Vertex v, v1, v2;
398   BRepLib_MakeEdge makeEdge;
399   TopLoc_Location loc;
400   Standard_Real first, last;
401   
402   TopExp::Vertices(E1, firstVertex, lastVertex);
403   TopExp::Vertices(basisEdge1, v1, v2);
404   if (v1.IsSame(commonVertex)) v = v2;
405   else v = v1;
406
407   if ( firstVertex.IsSame(v) || lastVertex.IsSame(v)) 
408     // It means the edge support only one fillet. In this case
409     // the new edge must be the basis edge.
410     newEdge1 = basisEdge1;
411   else {
412     // It means the edge support one fillet on each end.
413     if (firstVertex.IsSame(connectionE1Fillet)) {
414 //  syntaxe invalide sur NT
415 //      const Handle(Geom_Curve)& curve = 
416 //      BRep_Tool::Curve(E1, loc, first, last);   
417       Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, loc, first, last);   
418       makeEdge.Init(curve, commonVertex, lastVertex);  
419       newEdge1 = makeEdge.Edge();
420       newEdge1.Orientation(E1.Orientation());
421       newEdge1.Location(E1.Location());
422     } // if (firstVertex ...
423     else if (lastVertex.IsSame(connectionE1Fillet)) { 
424 //  syntax wrong on NT
425 //      const Handle(Geom_Curve)& curve = 
426 //      BRep_Tool::Curve(E1, loc, first, last);   
427       Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, loc, first, last);   
428       makeEdge.Init(curve, firstVertex, commonVertex);
429       newEdge1 = makeEdge.Edge();
430       newEdge1.Orientation(E1.Orientation());
431       newEdge1.Location(E1.Location());
432     } // else if (lastVertex ...
433   } // else ...
434
435   TopExp::Vertices(basisEdge2, v1, v2);
436   if (v1.IsSame(commonVertex)) v = v2;
437   else v = v1;
438
439   TopExp::Vertices(E2, firstVertex, lastVertex);   
440   if ( firstVertex.IsSame(v) || lastVertex.IsSame(v)) 
441     // It means the edge support only one fillet. In this case
442     // the new edge must be the basis edge.
443     newEdge2 = basisEdge2;
444   else {
445     // It means the edge support one fillet on each end.
446     if (firstVertex.IsSame(connectionE2Fillet)) {
447 //  syntax wrong on NT
448 //      const Handle(Geom_Curve)& curve = 
449 //      BRep_Tool::Curve(E2, loc, first, last);   
450       Handle(Geom_Curve) curve = BRep_Tool::Curve(E2, loc, first, last);
451       makeEdge.Init(curve, commonVertex, lastVertex);
452       newEdge2 = makeEdge.Edge();
453       newEdge2.Orientation(E2.Orientation());
454       newEdge2.Location(E2.Location());
455     } // if (firstVertex ...
456     else if (lastVertex.IsSame(connectionE2Fillet)) {
457 //  syntax wrong on NT
458 //      const Handle(Geom_Curve)& curve = 
459 //      BRep_Tool::Curve(E2, loc, first, last);   
460       Handle(Geom_Curve) curve = BRep_Tool::Curve(E2, loc, first, last);
461       makeEdge.Init(curve, firstVertex, commonVertex);
462       newEdge2 = makeEdge.Edge();
463       newEdge2.Orientation(E2.Orientation());
464       newEdge2.Location(E2.Location());
465     } // else if (lastVertex ... 
466   } // else ...
467
468   // rebuild the newFace
469   TopExp_Explorer Ex(newFace, TopAbs_EDGE);
470   TopoDS_Wire newWire;
471
472   BRep_Builder B;
473   B.MakeWire(newWire);
474
475   while (Ex.More()) {
476     const TopoDS_Edge& theEdge = TopoDS::Edge(Ex.Current());
477     if (!theEdge.IsSame(E1) && 
478         !theEdge.IsSame(E2) && 
479         !theEdge.IsSame(Fillet)) 
480       B.Add(newWire, theEdge);
481     else {
482       if (theEdge == E1) 
483         B.Add(newWire, newEdge1);
484       else if (theEdge == E2)
485         B.Add(newWire, newEdge2);
486     } // else
487     Ex.Next();
488   } // while ...
489   BRepAdaptor_Surface Adaptor3dSurface(refFace);
490   BRepLib_MakeFace mFace(Adaptor3dSurface.Plane(), newWire);
491   newFace.Nullify();
492   newFace = mFace;
493
494   UpDateHistory(basisEdge1, basisEdge2, newEdge1, newEdge2);  
495
496   return commonVertex;
497 } // RemoveFillet
498
499
500 //=======================================================================
501 //function : ComputeFillet
502 //purpose  : 
503 //=======================================================================
504
505 void ChFi2d_Builder::ComputeFillet(const TopoDS_Vertex& V, 
506                                  const TopoDS_Edge& E1, 
507                                  const TopoDS_Edge& E2, 
508                                  const Standard_Real Radius,
509                                  TopoDS_Edge& TrimE1, 
510                                  TopoDS_Edge& TrimE2, 
511                                  TopoDS_Edge& Fillet) 
512 {
513   TopoDS_Vertex newExtr1, newExtr2;
514   Standard_Boolean Degen1, Degen2;
515   Fillet = BuildFilletEdge(V, E1, E2, Radius, newExtr1, newExtr2);
516   if ( status != ChFi2d_IsDone) return;
517   TrimE1 = BuildNewEdge(E1, V, newExtr1, Degen1);
518   TrimE2 = BuildNewEdge(E2, V, newExtr2, Degen2);
519   if (Degen1 && Degen2 ) status = ChFi2d_BothEdgesDegenerated;
520   if (Degen1 && !Degen2 ) status = ChFi2d_FirstEdgeDegenerated;
521   if (!Degen1 && Degen2 ) status = ChFi2d_LastEdgeDegenerated;
522 } // ComputeFillet
523
524
525
526 //=======================================================================
527 //function : BuildNewWire
528 //purpose  : 
529 //=======================================================================
530
531 void ChFi2d_Builder::BuildNewWire (const TopoDS_Edge& OldE1,
532                                    const TopoDS_Edge& OldE2, 
533                                    const TopoDS_Edge& E1, 
534                                    const TopoDS_Edge& Fillet, 
535                                    const TopoDS_Edge& E2)
536 {
537   
538   Standard_Boolean aClosedStatus = Standard_True;
539
540   TopExp_Explorer Ex(refFace, TopAbs_WIRE);
541   while (Ex.More()) {
542     const TopoDS_Wire& aWire = TopoDS::Wire(Ex.Current());
543     aClosedStatus = aWire.Closed();
544     break;
545   }
546   
547
548   Standard_Boolean filletIsAdded = Standard_False;
549
550   Ex.Init(newFace, TopAbs_EDGE);
551   TopoDS_Wire newWire;
552   BRep_Builder B;
553   B.MakeWire(newWire);
554
555   while (Ex.More()) {
556     const TopoDS_Edge& theEdge = TopoDS::Edge(Ex.Current());
557     if (!theEdge.IsSame(OldE1) && !theEdge.IsSame(OldE2)) {
558       B.Add(newWire, theEdge);
559     }
560     else {
561       if (theEdge == OldE1) {
562         if (status != ChFi2d_FirstEdgeDegenerated
563             && status != ChFi2d_BothEdgesDegenerated) {
564                 B.Add(newWire, E1);
565         }
566         if ( !filletIsAdded) {
567           B.Add(newWire, Fillet);
568           filletIsAdded = Standard_True;
569         } // if ( !filletIsAdded ...
570       } // if (theEdge == ...
571       else {
572         if (status != ChFi2d_LastEdgeDegenerated
573             && status != ChFi2d_BothEdgesDegenerated) {
574                 B.Add(newWire, E2);
575         }
576         if ( !filletIsAdded) {
577           B.Add(newWire, Fillet);
578           filletIsAdded = Standard_True;
579         }// if ( !filletIsAdded ...
580       } // else ...
581     } // else ...
582     Ex.Next();
583   } // while ...
584
585   newWire.Closed(aClosedStatus);
586   BRepAdaptor_Surface Adaptor3dSurface(refFace);
587   BRepLib_MakeFace mFace(Adaptor3dSurface.Plane(), newWire);
588   newFace = mFace;
589
590 } // BuildNewWire
591
592
593 //=======================================================================
594 //function : BuildNewEdge
595 //purpose  : 
596 //=======================================================================
597
598 TopoDS_Edge ChFi2d_Builder::BuildNewEdge(const TopoDS_Edge& E1,
599                                        const TopoDS_Vertex& OldExtr,
600                                        const TopoDS_Vertex& NewExtr) const 
601 {
602   BRepLib_MakeEdge makeEdge;
603   TopLoc_Location loc;
604   Standard_Real first, last;
605   TopoDS_Vertex firstVertex, lastVertex;
606   TopExp::Vertices(E1, firstVertex, lastVertex);
607 //  syntaxe invalide sur NT
608 //      const Handle(Geom_Curve)& curve = 
609 //      BRep_Tool::Curve(E1, first, last);   
610   Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, first, last);   
611   if (firstVertex.IsSame(OldExtr)) 
612     makeEdge.Init(curve, NewExtr, lastVertex);  
613   else 
614     makeEdge.Init(curve, firstVertex, NewExtr);
615   TopoDS_Edge anEdge = makeEdge;
616   anEdge.Orientation(E1.Orientation());
617 //  anEdge.Location(E1.Location());
618   return anEdge;
619 }
620
621
622 //=======================================================================
623 //function : BuildNewEdge
624 //purpose  : special flag if the new edge is degenerated
625 //=======================================================================
626
627 TopoDS_Edge ChFi2d_Builder::BuildNewEdge(const TopoDS_Edge& E1,
628                                        const TopoDS_Vertex& OldExtr,
629                                        const TopoDS_Vertex& NewExtr,
630                                        Standard_Boolean& IsDegenerated) const 
631 {
632   BRepLib_MakeEdge makeEdge;
633   TopLoc_Location loc;
634   Standard_Real first, last;
635   IsDegenerated = Standard_False;
636   TopoDS_Vertex firstVertex, lastVertex;
637   TopExp::Vertices(E1, firstVertex, lastVertex);
638   gp_Pnt Pnew = BRep_Tool::Pnt(NewExtr);
639   Standard_Boolean PonctualEdge = Standard_False;
640   Standard_Real Tol = Precision::Confusion();
641 //  syntax wrong on NT
642 //      const Handle(Geom_Curve)& curve = 
643 //      BRep_Tool::Curve(E1, first, last);   
644   Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, first, last);   
645   if (firstVertex.IsSame(OldExtr)) {
646     makeEdge.Init(curve, NewExtr, lastVertex);
647     gp_Pnt PV = BRep_Tool::Pnt(lastVertex);
648     PonctualEdge = (Pnew.Distance(PV)<Tol);
649   }
650   else {
651     makeEdge.Init(curve, firstVertex, NewExtr);
652     gp_Pnt PV = BRep_Tool::Pnt(firstVertex);
653     PonctualEdge = (Pnew.Distance(PV)<Tol);
654   }
655   TopoDS_Edge anEdge;
656   BRepLib_EdgeError error = makeEdge.Error();
657   if (error==BRepLib_LineThroughIdenticPoints || PonctualEdge) {
658     IsDegenerated = Standard_True;
659     anEdge = E1;
660   }
661   else {
662     anEdge = makeEdge;
663     anEdge.Orientation(E1.Orientation());
664 //    anEdge.Location(E1.Location());
665   }
666   return anEdge;
667 }
668
669
670 //=======================================================================
671 //function : UpDateHistory
672 //purpose  : 
673 //=======================================================================
674 void ChFi2d_Builder::UpDateHistory(const TopoDS_Edge& E1, 
675                                  const TopoDS_Edge& E2, 
676                                  const TopoDS_Edge& TrimE1, 
677                                  const TopoDS_Edge& TrimE2, 
678                                  const TopoDS_Edge& NewEdge,
679                                  const Standard_Integer Id)
680 {
681   if (Id == 1) // the new edge is a fillet
682     fillets.Append(NewEdge);
683   else // the new edge is a chamfer
684     chamfers.Append(NewEdge);
685     if (history.IsBound(E1)) history.UnBind(E1);
686   if ( status != ChFi2d_FirstEdgeDegenerated
687        && status != ChFi2d_BothEdgesDegenerated) {
688     if (!E1.IsSame(TrimE1)) history.Bind(E1, TrimE1);
689   }
690     if (history.IsBound(E2)) history.UnBind(E2);
691   if ( status != ChFi2d_LastEdgeDegenerated
692        && status != ChFi2d_BothEdgesDegenerated) {
693     if (!E2.IsSame(TrimE2)) history.Bind(E2, TrimE2);
694   }
695 } // UpDateHistory
696
697
698 //=======================================================================
699 //function : UpDateHistory
700 //purpose  : 
701 //=======================================================================
702 void ChFi2d_Builder::UpDateHistory(const TopoDS_Edge& E1, 
703                                  const TopoDS_Edge& E2, 
704                                  const TopoDS_Edge& TrimE1, 
705                                  const TopoDS_Edge& TrimE2) 
706 {
707
708
709   if (history.IsBound(E1)) history.UnBind(E1);
710   if (!E1.IsSame(TrimE1)) history.Bind(E1, TrimE1);
711   if (history.IsBound(E2)) history.UnBind(E2);
712   if (!E2.IsSame(TrimE2)) history.Bind(E2, TrimE2);
713 } // UpDateHistory
714
715
716 //=======================================================================
717 //function : BasisEdge
718 //purpose  : 
719 //=======================================================================
720 const TopoDS_Edge& ChFi2d_Builder::BasisEdge(const TopoDS_Edge& E) const 
721 {
722   TopTools_DataMapIteratorOfDataMapOfShapeShape iterator(history);
723   TopoDS_Edge anEdge;
724   while (iterator.More()) {
725     anEdge = TopoDS::Edge(iterator.Value());
726     if (anEdge.IsSame(E)) { 
727       const TopoDS_Edge& anotherEdge = TopoDS::Edge(iterator.Key());
728       return anotherEdge;
729     } // if (anEdge.IsSame ...
730     iterator.Next();
731   } // while (Iterator.More ...
732   return E;
733 } // BasisEdge
734
735
736 //=======================================================================
737 //function : BuildFilletEdge
738 //purpose  : 
739 //=======================================================================
740 TopoDS_Edge ChFi2d_Builder::BuildFilletEdge(const TopoDS_Vertex& V, 
741                                           const TopoDS_Edge& AdjEdge1, 
742                                           const TopoDS_Edge& AdjEdge2, 
743                                           const Standard_Real Radius,
744                                           TopoDS_Vertex& NewExtr1,
745                                           TopoDS_Vertex& NewExtr2)
746 {
747   TopoDS_Edge E1, E2;
748   E1 = AdjEdge1;
749   E2 = AdjEdge2;
750   TopoDS_Vertex V1 = TopExp::FirstVertex(E1);
751   TopoDS_Vertex V2 = TopExp::LastVertex(E1);
752   TopoDS_Vertex V3 = TopExp::FirstVertex(E2);
753   TopoDS_Vertex V4 = TopExp::LastVertex(E2);
754
755   //========================================================================
756   //    The first arc is found.                                        +
757   //========================================================================
758
759   TopAbs_Orientation O1,O2;
760   TopAbs_Orientation OE1,OE2;
761   OE1 = E1.Orientation();
762   OE2 = E2.Orientation();
763   E1.Orientation(TopAbs_FORWARD);
764   E2.Orientation(TopAbs_FORWARD);
765   TopoDS_Shape aLocalShape = E1.EmptyCopied();
766   TopoDS_Edge Ebid1 = TopoDS::Edge(aLocalShape);
767   aLocalShape = E2.EmptyCopied();
768   TopoDS_Edge Ebid2 = TopoDS::Edge(aLocalShape);
769 //  TopoDS_Edge Ebid1 = TopoDS::Edge(E1.EmptyCopied());
770 //  TopoDS_Edge Ebid2 = TopoDS::Edge(E2.EmptyCopied());
771   Standard_Real param1,param2,param3,param4;
772   
773   //========================================================================
774   //    Save non-modified parts of edges concerned.      +
775   //========================================================================
776
777   if (V1.IsSame(V)) {
778     param1 = BRep_Tool::Parameter(V1,E1);
779     param2 = BRep_Tool::Parameter(V2,E1);
780     O1 = V2.Orientation();
781   }
782   else {
783     param1 = BRep_Tool::Parameter(V2,E1);
784     param2 = BRep_Tool::Parameter(V1,E1);
785     O1 = V1.Orientation();
786   }
787   if (V3.IsSame(V)) {
788     param3 = BRep_Tool::Parameter(V3,E2);
789     param4 = BRep_Tool::Parameter(V4,E2);
790     O2 = V4.Orientation();
791   }
792   else {
793     param3 = BRep_Tool::Parameter(V4,E2);
794     param4 = BRep_Tool::Parameter(V3,E2);
795     O2 = V3.Orientation();
796   }
797   
798   //========================================================================
799   //    Restore geometric supports.                            +
800   //========================================================================
801
802   Handle(Geom2d_Curve) C1,C2; 
803   Standard_Real ufirst1,ulast1,ufirst2,ulast2,U1,U2,PU1,PU2,Vv1,Vv2;
804   Standard_Real PPU1,PPU2;
805   C1 = BRep_Tool::CurveOnSurface(E1,newFace,ufirst1,ulast1);
806   C2 = BRep_Tool::CurveOnSurface(E2,newFace,ufirst2,ulast2);
807
808   //========================================================================
809   //   Determination of the face for fillet.                                +
810   //========================================================================
811
812   gp_Pnt2d p;
813   gp_Vec2d Ve1,Ve2;
814   gp_Vec2d Ve3,Ve4;
815   Standard_Boolean Sens1 , Sens2;
816
817   Handle(Geom2d_Curve) basisC1,basisC2; 
818   Handle(Geom2d_TrimmedCurve) T1 = Handle(Geom2d_TrimmedCurve)::DownCast(C1);
819   if (!T1.IsNull())
820     basisC1 = Handle(Geom2d_Curve)::DownCast(T1->BasisCurve());
821   else
822     basisC1 = Handle(Geom2d_Curve)::DownCast(C1);
823   Handle(Geom2d_TrimmedCurve) T2 = Handle(Geom2d_TrimmedCurve)::DownCast(C2);
824   if (!T2.IsNull())
825     basisC2 = Handle(Geom2d_Curve)::DownCast(T2->BasisCurve());
826   else
827     basisC2 = Handle(Geom2d_Curve)::DownCast(C2);
828
829   if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
830     Handle(Geom2d_Circle) CC1 = Handle(Geom2d_Circle)::DownCast(basisC1);
831     ElCLib::D1(param1,CC1->Circ2d(),p,Ve1);
832     Sens1 = (CC1->Circ2d()).IsDirect(); 
833   } // if (C1->DynamicType() ...
834   else {
835     Handle(Geom2d_Line) CC1 = Handle(Geom2d_Line)::DownCast(basisC1);
836     ElCLib::D1(param1,CC1->Lin2d(),p,Ve1);
837     Sens1=Standard_True;
838   } // else ...
839   if (basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
840     Handle(Geom2d_Circle) CC2 = Handle(Geom2d_Circle)::DownCast(basisC2);
841     ElCLib::D1(param3,CC2->Circ2d(),p,Ve2);
842     Sens2 = (CC2->Circ2d()).IsDirect(); 
843   } // if if (C2->DynamicType() ...
844   else {
845     Handle(Geom2d_Line) CC2 = Handle(Geom2d_Line)::DownCast(basisC2);
846     ElCLib::D1(param3,CC2->Lin2d(),p,Ve2);
847     Sens2=Standard_True;
848   } // else ...
849
850   TopoDS_Edge filletEdge;
851
852   Standard_Real cross = Ve1.Crossed(Ve2);
853   Ve3 = Ve1;
854   Ve4 = Ve2;
855
856   // processing of tangency or downcast point 
857   if (Ve1.IsParallel(Ve2,Precision::Angular())) {
858     // Ve1 and Ve2 are parallel : cross at 0
859     cross = 0.;
860     if (param1<param2) {
861       Ve3 = -Ve1;
862     }
863     if (param3>param4) {
864       Ve4 = -Ve2;
865     }
866
867     if (! Ve4.IsOpposite(Ve3,Precision::Angular())) {
868       // There is a true tangency point and the calculation is stopped
869       status = ChFi2d_TangencyError;
870       return filletEdge;
871     }
872       // Otherwise this is a downcast point, and the calculation is continued
873   }
874
875   GccEnt_Position Qual1,Qual2;
876   if (cross < 0.) {
877     if (param3 > param4 ) {
878         if(Sens1 == Standard_True){
879            Qual1 = GccEnt_enclosed;
880          }
881         else {
882            Qual1 = GccEnt_outside;
883          }
884     }
885     else {
886         if(Sens1 == Standard_True){
887            Qual1 = GccEnt_outside;
888          }
889         else {
890            Qual1 = GccEnt_enclosed;
891         }
892     }
893     if (param1 > param2) {
894         if(Sens2 == Standard_True)
895           Qual2 = GccEnt_outside;
896         else
897            Qual2 = GccEnt_enclosed;
898     }
899     else {
900         if(Sens2 == Standard_True)
901            Qual2 = GccEnt_enclosed;
902         else
903            Qual2 = GccEnt_outside;      
904     }
905   } // if (cross < 0 ...
906   else {
907     if (param3 > param4 ) {
908         if( Sens1 == Standard_True)
909             Qual1 = GccEnt_outside;
910         else
911             Qual1 = GccEnt_enclosed;
912     }
913     else {
914         if( Sens1 == Standard_True)
915             Qual1 = GccEnt_enclosed;
916         else
917             Qual1 = GccEnt_outside;
918     }
919     if (param1 > param2 ) {
920         if( Sens2 == Standard_True)
921              Qual2 = GccEnt_enclosed;
922         else
923              Qual2 = GccEnt_outside;
924     }
925     else {
926         if( Sens2 == Standard_True)
927             Qual2 = GccEnt_outside;
928         else
929             Qual2 = GccEnt_enclosed;
930     }
931   } // else ...
932
933   Standard_Real Tol = Precision::Confusion();
934   Geom2dGcc_Circ2d2TanRad Fillet(Geom2dGcc_QualifiedCurve(basisC1,Qual1),
935                                  Geom2dGcc_QualifiedCurve(basisC2,Qual2),
936                                  Radius, Tol);
937   if (!Fillet.IsDone() || Fillet.NbSolutions()==0) {
938     status = ChFi2d_ComputationError;
939     return filletEdge;
940   }
941   else if (Fillet.NbSolutions() >= 1) {
942     status = ChFi2d_IsDone;
943     Standard_Integer numsol = 1;
944     Standard_Integer nsol = 1;
945     TopoDS_Vertex Vertex1,Vertex2;
946     gp_Pnt2d Ptg1,Ptg2;
947     Standard_Real dist;
948     Standard_Real dist1 = 1.e40;
949     Standard_Boolean inside = Standard_False;
950     while (nsol<=Fillet.NbSolutions()) {
951       Fillet.Tangency1(nsol,PU1,PU2,Ptg1);
952       dist = Ptg1.Distance(p);
953       if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Line)) {
954         inside = (PU2<param1 && PU2>param2) || (PU2<param2 && PU2>param1);
955         if ( inside && dist < dist1) {
956           numsol = nsol;
957           dist1 = dist;
958         } // if ((((inside && ...
959       } // if (C1->DynamicType( ...
960       else {
961         Fillet.Tangency2(nsol,PPU1,PPU2,Ptg2);
962         dist = Ptg2.Distance(p);
963         inside = (PPU2<param3 && PPU2>param4) || (PPU2<param4 && PPU2>param3);
964         //  case of arc of circle passing on the sewing
965         if ( ( basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle) ) && 
966             ( (2*M_PI<param3 && 2*M_PI>param4) || (2*M_PI<param4 && 2*M_PI>param3) ) ) {
967         //  cas param3<param4
968           inside = (param3<PPU2 && PPU2<2*M_PI) 
969                      || (0<=PPU2 && PPU2<param4-2*M_PI);
970         //  cas param4<param3
971           inside = inside || (param4<PPU2 && PPU2<2*M_PI) 
972                                || (0<=PPU2 && PPU2<param3-2*M_PI);
973         }
974         if ( inside && dist < dist1) {
975           numsol = nsol;
976           dist1 = dist;
977         } // if ((((param3 ...
978       } // else ...
979       nsol++;
980     } // while (nsol ...
981     gp_Circ2d cir(Fillet.ThisSolution(numsol));
982     Handle(Geom2d_Circle) circle = new Geom2d_Circle(cir);
983
984     BRep_Builder B;
985     BRepAdaptor_Surface Adaptor3dSurface(refFace);
986     Handle(Geom_Plane) refSurf = new Geom_Plane(Adaptor3dSurface.Plane());
987     Fillet.Tangency1(numsol,U1,U2,Ptg1);
988     Fillet.Tangency2(numsol,Vv1,Vv2,Ptg2);
989
990     // check the validity of parameters
991     //// modified by jgv, 08.08.2011 for bug 0022695 ////
992     //inside = (U2<param1 && U2>param2) || (U2<param2 && U2>param1);
993     inside = (U2 < param1 && U2 >= param2) || (U2 <= param2 && U2 > param1);
994     /////////////////////////////////////////////////////
995     if ( (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle))
996       &&  ( (2*M_PI<param1 && 2*M_PI>param2) || (2*M_PI<param2 && 2*M_PI>param1) ) ) {
997       // arc of circle containing the circle origin
998       //  case param1<param2
999       inside = (param1<U2 && U2<2*M_PI) || (0<=U2 && U2<param2-2*M_PI);
1000       //  case param2<param1
1001       inside = inside || (param2<U2 && U2<2*M_PI) || (0<=U2 && U2<param1-2*M_PI);
1002     }
1003     if (!inside) {
1004       status = ChFi2d_ComputationError;
1005       return filletEdge;
1006     }
1007
1008     //// modified by jgv, 08.08.2011 for bug 0022695 ////
1009     //inside = (Vv2<param3 && Vv2>param4) || (Vv2<param4 && Vv2>param3);
1010     inside = (Vv2 < param3 && Vv2 >= param4) || (Vv2 <= param4 && Vv2 > param3);
1011     /////////////////////////////////////////////////////
1012     if ( (basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle))
1013       &&  ( (2*M_PI<param3 && 2*M_PI>param4) || (2*M_PI<param4 && 2*M_PI>param3) ) ) {
1014     // arc of circle containing the circle origin
1015       //  cas param3<param4
1016       inside = (param3<Vv2 && Vv2<2*M_PI) || (0<=Vv2 && Vv2<param4-2*M_PI);
1017       //  cas param4<param3
1018       inside = inside || (param4<Vv2 && Vv2<2*M_PI) || (0<=Vv2 && Vv2<param3-2*M_PI);
1019     }
1020     if (!inside) {
1021       status = ChFi2d_ComputationError;
1022       return filletEdge;
1023     }
1024
1025     gp_Pnt p1 = Adaptor3dSurface.Value(Ptg1.X(), Ptg1.Y());
1026     gp_Pnt p2 = Adaptor3dSurface.Value(Ptg2.X(), Ptg2.Y());
1027     B.MakeVertex(Vertex1, p1,Tol);
1028     NewExtr1 = Vertex1;
1029     if (Abs(U2-ufirst1) <= Precision::PConfusion()) {
1030       NewExtr1 = V1;
1031     }
1032     if (Abs(U2-ulast1) <= Precision::PConfusion()) {
1033       NewExtr1 = V2;
1034     }
1035
1036     B.MakeVertex(Vertex2, p2,Tol);
1037     NewExtr2 = Vertex2;
1038     if (Abs(Vv2-ufirst2) <= Precision::PConfusion()) {
1039       NewExtr2 = V3;
1040     }
1041     if (Abs(Vv2-ulast2) <= Precision::PConfusion()) {
1042       NewExtr2 = V4;
1043     }
1044
1045     //=======================================================================
1046     //   Update tops of the fillet.                                  +
1047     //=======================================================================
1048     gp_Pnt Pntbid;
1049     gp_Pnt2d sommet;
1050     Pntbid = BRep_Tool::Pnt(V);
1051     sommet = gp_Pnt2d(Pntbid.X(),Pntbid.Y());
1052
1053     gp_Pnt pntBid;
1054     gp_Pnt2d somBid;
1055     if (V1.IsSame(V)) {
1056       pntBid = BRep_Tool::Pnt(V2);
1057       somBid = gp_Pnt2d(pntBid.X(),pntBid.Y());
1058     }
1059     else {
1060       pntBid = BRep_Tool::Pnt(V1);
1061       somBid = gp_Pnt2d(pntBid.X(),pntBid.Y());
1062     }
1063
1064     gp_Vec2d vec;
1065     ElCLib::D1(U1,cir,Ptg1,vec);
1066
1067     gp_Vec2d vec1;
1068     if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
1069       Handle(Geom2d_Circle) CC1 = Handle(Geom2d_Circle)::DownCast(basisC1);
1070       gp_Circ2d cir2d(CC1->Circ2d());
1071       Standard_Real par = ElCLib::Parameter(cir2d,Ptg1);
1072       gp_Pnt2d Pd;
1073       ElCLib::D1(par,cir2d,Pd,vec1);
1074     } // if (C1->DynamicType() ...
1075     else if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Line)) {
1076       Handle(Geom2d_Line) CC1 = Handle(Geom2d_Line)::DownCast(basisC1);
1077       gp_Lin2d lin2d(CC1->Lin2d());
1078       Standard_Real par = ElCLib::Parameter(lin2d,sommet);
1079       vec1 = gp_Vec2d(sommet.X()-somBid.X(),sommet.Y()-somBid.Y());
1080       gp_Pnt2d Pd;
1081       ElCLib::D1(par,lin2d,Pd,vec1);
1082     } // else if ...
1083
1084     if (OE1 == TopAbs_REVERSED) {
1085       vec1.Reverse();
1086     } // if (OE1 ...
1087     Standard_Real cross = vec1*vec;
1088     Standard_Boolean Sense = cross > 0.;
1089     if (U1 > Vv1 && U1 > 2.*M_PI) {
1090       ElCLib::AdjustPeriodic(0.,2.*M_PI,Precision::Confusion(),U1,Vv1);
1091     } // if (U1 ... 
1092     if ( (O1 == TopAbs_FORWARD && OE1 == TopAbs_FORWARD) ||
1093          (O1 == TopAbs_REVERSED && OE1 == TopAbs_REVERSED) ) {
1094       filletEdge = BRepLib_MakeEdge(circle, refSurf,
1095                                     NewExtr1, NewExtr2, U1, Vv1);
1096     } // if (O1 == ...
1097     else {
1098       filletEdge = BRepLib_MakeEdge(circle, refSurf, 
1099                                     NewExtr2, NewExtr1, Vv1, U1);
1100     } // else ...
1101     if (!Sense) {
1102       TopAbs_Orientation S1 = filletEdge.Orientation();
1103       if ((O1 == TopAbs_FORWARD && OE1 == TopAbs_FORWARD) ||
1104           (O1 == TopAbs_REVERSED && OE1 == TopAbs_REVERSED) ) {
1105         filletEdge = BRepLib_MakeEdge(circle, refSurf, 
1106                                       NewExtr2, NewExtr1, Vv1, U1);
1107       }
1108       else {
1109         filletEdge = BRepLib_MakeEdge(circle, refSurf, 
1110                                       NewExtr1, NewExtr2, U1, Vv1);
1111       }
1112       if (S1 == TopAbs_FORWARD) {
1113         filletEdge.Orientation(TopAbs_REVERSED);
1114       }
1115       else {
1116         filletEdge.Orientation(TopAbs_FORWARD);
1117       }
1118     } // if (!Sense
1119
1120   } //  else if
1121
1122   BRepLib::BuildCurves3d(filletEdge);  
1123   return filletEdge;
1124 } // BuildFilletEdge
1125
1126
1127 //=======================================================================
1128 //function : IsAFillet
1129 //purpose  : 
1130 //=======================================================================
1131
1132 Standard_Boolean ChFi2d_Builder::IsAFillet(const TopoDS_Edge& E) const 
1133 {
1134   Standard_Integer i = 1;
1135   while (i <= fillets.Length()) {
1136     const TopoDS_Edge& currentEdge = TopoDS::Edge(fillets.Value(i));
1137     if (currentEdge.IsSame(E)) return Standard_True;
1138     i++;
1139   }
1140   return Standard_False;
1141 } // IsAFillet
1142
1143
1144 //=======================================================================
1145 //function : IsAChamfer
1146 //purpose  : 
1147 //=======================================================================
1148
1149 Standard_Boolean ChFi2d_Builder::IsAChamfer(const TopoDS_Edge& E) const 
1150 {
1151   Standard_Integer i = 1;
1152   while (i <= chamfers.Length()) {
1153     const TopoDS_Edge& currentEdge = TopoDS::Edge(chamfers.Value(i));
1154     if (currentEdge.IsSame(E)) return Standard_True;
1155     i++;
1156   }
1157   return Standard_False;
1158 } // IsAChamfer
1159
1160
1161
1162 //=======================================================================
1163 //function : IsLineOrCircle
1164 //purpose  : 
1165 //=======================================================================
1166
1167 Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E,
1168                                 const TopoDS_Face& F) 
1169 {
1170   Standard_Real first, last;
1171   TopLoc_Location loc;
1172 //  syntaxe invalide sur NT
1173 //      const Handle(Geom2d_Curve)& C = 
1174 //      BRep_Tool::CurveOnSurface(E,F,first,last);   
1175   Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,first,last);
1176   Handle(Geom2d_Curve) basisC; 
1177   Handle(Geom2d_TrimmedCurve) TC = Handle(Geom2d_TrimmedCurve)::DownCast(C);
1178   if (!TC.IsNull())
1179     basisC = Handle(Geom2d_Curve)::DownCast(TC->BasisCurve());
1180   else
1181     basisC = Handle(Geom2d_Curve)::DownCast(C);
1182
1183   if ( basisC->DynamicType() == STANDARD_TYPE(Geom2d_Circle)
1184       || basisC->DynamicType() == STANDARD_TYPE(Geom2d_Line) ) {
1185     return Standard_True;
1186   }
1187   else {
1188     return Standard_False;
1189   } // else ...
1190 } // IsLineOrCircle