7bd095dbe4cbd6676d4bc9ff4251d967043695ec
[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 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 // 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;
760   TopAbs_Orientation OE1;
761   OE1 = E1.Orientation();
762   E1.Orientation(TopAbs_FORWARD);
763   E2.Orientation(TopAbs_FORWARD);
764   TopoDS_Shape aLocalShape = E1.EmptyCopied();
765   TopoDS_Edge Ebid1 = TopoDS::Edge(aLocalShape);
766   aLocalShape = E2.EmptyCopied();
767   TopoDS_Edge Ebid2 = TopoDS::Edge(aLocalShape);
768 //  TopoDS_Edge Ebid1 = TopoDS::Edge(E1.EmptyCopied());
769 //  TopoDS_Edge Ebid2 = TopoDS::Edge(E2.EmptyCopied());
770   Standard_Real param1,param2,param3,param4;
771   
772   //========================================================================
773   //    Save non-modified parts of edges concerned.      +
774   //========================================================================
775
776   if (V1.IsSame(V)) {
777     param1 = BRep_Tool::Parameter(V1,E1);
778     param2 = BRep_Tool::Parameter(V2,E1);
779     O1 = V2.Orientation();
780   }
781   else {
782     param1 = BRep_Tool::Parameter(V2,E1);
783     param2 = BRep_Tool::Parameter(V1,E1);
784     O1 = V1.Orientation();
785   }
786   if (V3.IsSame(V)) {
787     param3 = BRep_Tool::Parameter(V3,E2);
788     param4 = BRep_Tool::Parameter(V4,E2);
789   }
790   else {
791     param3 = BRep_Tool::Parameter(V4,E2);
792     param4 = BRep_Tool::Parameter(V3,E2);
793   }
794   
795   //========================================================================
796   //    Restore geometric supports.                            +
797   //========================================================================
798
799   Handle(Geom2d_Curve) C1,C2; 
800   Standard_Real ufirst1,ulast1,ufirst2,ulast2,U1,U2,PU1,PU2,Vv1,Vv2;
801   Standard_Real PPU1,PPU2;
802   C1 = BRep_Tool::CurveOnSurface(E1,newFace,ufirst1,ulast1);
803   C2 = BRep_Tool::CurveOnSurface(E2,newFace,ufirst2,ulast2);
804
805   //========================================================================
806   //   Determination of the face for fillet.                                +
807   //========================================================================
808
809   gp_Pnt2d p;
810   gp_Vec2d Ve1,Ve2;
811   gp_Vec2d Ve3,Ve4;
812   Standard_Boolean Sens1 , Sens2;
813
814   Handle(Geom2d_Curve) basisC1,basisC2; 
815   Handle(Geom2d_TrimmedCurve) T1 = Handle(Geom2d_TrimmedCurve)::DownCast(C1);
816   if (!T1.IsNull())
817     basisC1 = Handle(Geom2d_Curve)::DownCast(T1->BasisCurve());
818   else
819     basisC1 = Handle(Geom2d_Curve)::DownCast(C1);
820   Handle(Geom2d_TrimmedCurve) T2 = Handle(Geom2d_TrimmedCurve)::DownCast(C2);
821   if (!T2.IsNull())
822     basisC2 = Handle(Geom2d_Curve)::DownCast(T2->BasisCurve());
823   else
824     basisC2 = Handle(Geom2d_Curve)::DownCast(C2);
825
826   if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
827     Handle(Geom2d_Circle) CC1 = Handle(Geom2d_Circle)::DownCast(basisC1);
828     ElCLib::D1(param1,CC1->Circ2d(),p,Ve1);
829     Sens1 = (CC1->Circ2d()).IsDirect(); 
830   } // if (C1->DynamicType() ...
831   else {
832     Handle(Geom2d_Line) CC1 = Handle(Geom2d_Line)::DownCast(basisC1);
833     ElCLib::D1(param1,CC1->Lin2d(),p,Ve1);
834     Sens1=Standard_True;
835   } // else ...
836   if (basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
837     Handle(Geom2d_Circle) CC2 = Handle(Geom2d_Circle)::DownCast(basisC2);
838     ElCLib::D1(param3,CC2->Circ2d(),p,Ve2);
839     Sens2 = (CC2->Circ2d()).IsDirect(); 
840   } // if if (C2->DynamicType() ...
841   else {
842     Handle(Geom2d_Line) CC2 = Handle(Geom2d_Line)::DownCast(basisC2);
843     ElCLib::D1(param3,CC2->Lin2d(),p,Ve2);
844     Sens2=Standard_True;
845   } // else ...
846
847   TopoDS_Edge filletEdge;
848
849   Standard_Real cross = Ve1.Crossed(Ve2);
850   Ve3 = Ve1;
851   Ve4 = Ve2;
852
853   // processing of tangency or downcast point 
854   if (Ve1.IsParallel(Ve2,Precision::Angular())) {
855     // Ve1 and Ve2 are parallel : cross at 0
856     cross = 0.;
857     if (param1<param2) {
858       Ve3 = -Ve1;
859     }
860     if (param3>param4) {
861       Ve4 = -Ve2;
862     }
863
864     if (! Ve4.IsOpposite(Ve3,Precision::Angular())) {
865       // There is a true tangency point and the calculation is stopped
866       status = ChFi2d_TangencyError;
867       return filletEdge;
868     }
869       // Otherwise this is a downcast point, and the calculation is continued
870   }
871
872   GccEnt_Position Qual1,Qual2;
873   if (cross < 0.) {
874     if (param3 > param4 ) {
875         if(Sens1 == Standard_True){
876            Qual1 = GccEnt_enclosed;
877          }
878         else {
879            Qual1 = GccEnt_outside;
880          }
881     }
882     else {
883         if(Sens1 == Standard_True){
884            Qual1 = GccEnt_outside;
885          }
886         else {
887            Qual1 = GccEnt_enclosed;
888         }
889     }
890     if (param1 > param2) {
891         if(Sens2 == Standard_True)
892           Qual2 = GccEnt_outside;
893         else
894            Qual2 = GccEnt_enclosed;
895     }
896     else {
897         if(Sens2 == Standard_True)
898            Qual2 = GccEnt_enclosed;
899         else
900            Qual2 = GccEnt_outside;      
901     }
902   } // if (cross < 0 ...
903   else {
904     if (param3 > param4 ) {
905         if( Sens1 == Standard_True)
906             Qual1 = GccEnt_outside;
907         else
908             Qual1 = GccEnt_enclosed;
909     }
910     else {
911         if( Sens1 == Standard_True)
912             Qual1 = GccEnt_enclosed;
913         else
914             Qual1 = GccEnt_outside;
915     }
916     if (param1 > param2 ) {
917         if( Sens2 == Standard_True)
918              Qual2 = GccEnt_enclosed;
919         else
920              Qual2 = GccEnt_outside;
921     }
922     else {
923         if( Sens2 == Standard_True)
924             Qual2 = GccEnt_outside;
925         else
926             Qual2 = GccEnt_enclosed;
927     }
928   } // else ...
929
930   Standard_Real Tol = Precision::Confusion();
931   Geom2dGcc_Circ2d2TanRad Fillet(Geom2dGcc_QualifiedCurve(basisC1,Qual1),
932                                  Geom2dGcc_QualifiedCurve(basisC2,Qual2),
933                                  Radius, Tol);
934   if (!Fillet.IsDone() || Fillet.NbSolutions()==0) {
935     status = ChFi2d_ComputationError;
936     return filletEdge;
937   }
938   else if (Fillet.NbSolutions() >= 1) {
939     status = ChFi2d_IsDone;
940     Standard_Integer numsol = 1;
941     Standard_Integer nsol = 1;
942     TopoDS_Vertex Vertex1,Vertex2;
943     gp_Pnt2d Ptg1,Ptg2;
944     Standard_Real dist;
945     Standard_Real dist1 = 1.e40;
946     Standard_Boolean inside = Standard_False;
947     while (nsol<=Fillet.NbSolutions()) {
948       Fillet.Tangency1(nsol,PU1,PU2,Ptg1);
949       dist = Ptg1.Distance(p);
950       if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Line)) {
951         inside = (PU2<param1 && PU2>param2) || (PU2<param2 && PU2>param1);
952         if ( inside && dist < dist1) {
953           numsol = nsol;
954           dist1 = dist;
955         } // if ((((inside && ...
956       } // if (C1->DynamicType( ...
957       else {
958         Fillet.Tangency2(nsol,PPU1,PPU2,Ptg2);
959         dist = Ptg2.Distance(p);
960         inside = (PPU2<param3 && PPU2>param4) || (PPU2<param4 && PPU2>param3);
961         //  case of arc of circle passing on the sewing
962         if ( ( basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle) ) && 
963             ( (2*M_PI<param3 && 2*M_PI>param4) || (2*M_PI<param4 && 2*M_PI>param3) ) ) {
964         //  cas param3<param4
965           inside = (param3<PPU2 && PPU2<2*M_PI) 
966                      || (0<=PPU2 && PPU2<param4-2*M_PI);
967         //  cas param4<param3
968           inside = inside || (param4<PPU2 && PPU2<2*M_PI) 
969                                || (0<=PPU2 && PPU2<param3-2*M_PI);
970         }
971         if ( inside && dist < dist1) {
972           numsol = nsol;
973           dist1 = dist;
974         } // if ((((param3 ...
975       } // else ...
976       nsol++;
977     } // while (nsol ...
978     gp_Circ2d cir(Fillet.ThisSolution(numsol));
979     Handle(Geom2d_Circle) circle = new Geom2d_Circle(cir);
980
981     BRep_Builder B;
982     BRepAdaptor_Surface Adaptor3dSurface(refFace);
983     Handle(Geom_Plane) refSurf = new Geom_Plane(Adaptor3dSurface.Plane());
984     Fillet.Tangency1(numsol,U1,U2,Ptg1);
985     Fillet.Tangency2(numsol,Vv1,Vv2,Ptg2);
986
987     // check the validity of parameters
988     //// modified by jgv, 08.08.2011 for bug 0022695 ////
989     //inside = (U2<param1 && U2>param2) || (U2<param2 && U2>param1);
990     inside = (U2 < param1 && U2 >= param2) || (U2 <= param2 && U2 > param1);
991     /////////////////////////////////////////////////////
992     if ( (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle))
993       &&  ( (2*M_PI<param1 && 2*M_PI>param2) || (2*M_PI<param2 && 2*M_PI>param1) ) ) {
994       // arc of circle containing the circle origin
995       //  case param1<param2
996       inside = (param1<U2 && U2<2*M_PI) || (0<=U2 && U2<param2-2*M_PI);
997       //  case param2<param1
998       inside = inside || (param2<U2 && U2<2*M_PI) || (0<=U2 && U2<param1-2*M_PI);
999     }
1000     if (!inside) {
1001       status = ChFi2d_ComputationError;
1002       return filletEdge;
1003     }
1004
1005     //// modified by jgv, 08.08.2011 for bug 0022695 ////
1006     //inside = (Vv2<param3 && Vv2>param4) || (Vv2<param4 && Vv2>param3);
1007     inside = (Vv2 < param3 && Vv2 >= param4) || (Vv2 <= param4 && Vv2 > param3);
1008     /////////////////////////////////////////////////////
1009     if ( (basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle))
1010       &&  ( (2*M_PI<param3 && 2*M_PI>param4) || (2*M_PI<param4 && 2*M_PI>param3) ) ) {
1011     // arc of circle containing the circle origin
1012       //  cas param3<param4
1013       inside = (param3<Vv2 && Vv2<2*M_PI) || (0<=Vv2 && Vv2<param4-2*M_PI);
1014       //  cas param4<param3
1015       inside = inside || (param4<Vv2 && Vv2<2*M_PI) || (0<=Vv2 && Vv2<param3-2*M_PI);
1016     }
1017     if (!inside) {
1018       status = ChFi2d_ComputationError;
1019       return filletEdge;
1020     }
1021
1022     gp_Pnt p1 = Adaptor3dSurface.Value(Ptg1.X(), Ptg1.Y());
1023     gp_Pnt p2 = Adaptor3dSurface.Value(Ptg2.X(), Ptg2.Y());
1024     B.MakeVertex(Vertex1, p1,Tol);
1025     NewExtr1 = Vertex1;
1026     if (Abs(U2-ufirst1) <= Precision::PConfusion()) {
1027       NewExtr1 = V1;
1028     }
1029     if (Abs(U2-ulast1) <= Precision::PConfusion()) {
1030       NewExtr1 = V2;
1031     }
1032
1033     B.MakeVertex(Vertex2, p2,Tol);
1034     NewExtr2 = Vertex2;
1035     if (Abs(Vv2-ufirst2) <= Precision::PConfusion()) {
1036       NewExtr2 = V3;
1037     }
1038     if (Abs(Vv2-ulast2) <= Precision::PConfusion()) {
1039       NewExtr2 = V4;
1040     }
1041
1042     //=======================================================================
1043     //   Update tops of the fillet.                                  +
1044     //=======================================================================
1045     gp_Pnt Pntbid;
1046     gp_Pnt2d sommet;
1047     Pntbid = BRep_Tool::Pnt(V);
1048     sommet = gp_Pnt2d(Pntbid.X(),Pntbid.Y());
1049
1050     gp_Pnt pntBid;
1051     gp_Pnt2d somBid;
1052     if (V1.IsSame(V)) {
1053       pntBid = BRep_Tool::Pnt(V2);
1054       somBid = gp_Pnt2d(pntBid.X(),pntBid.Y());
1055     }
1056     else {
1057       pntBid = BRep_Tool::Pnt(V1);
1058       somBid = gp_Pnt2d(pntBid.X(),pntBid.Y());
1059     }
1060
1061     gp_Vec2d vec;
1062     ElCLib::D1(U1,cir,Ptg1,vec);
1063
1064     gp_Vec2d vec1;
1065     if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
1066       Handle(Geom2d_Circle) CC1 = Handle(Geom2d_Circle)::DownCast(basisC1);
1067       gp_Circ2d cir2d(CC1->Circ2d());
1068       Standard_Real par = ElCLib::Parameter(cir2d,Ptg1);
1069       gp_Pnt2d Pd;
1070       ElCLib::D1(par,cir2d,Pd,vec1);
1071     } // if (C1->DynamicType() ...
1072     else if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Line)) {
1073       Handle(Geom2d_Line) CC1 = Handle(Geom2d_Line)::DownCast(basisC1);
1074       gp_Lin2d lin2d(CC1->Lin2d());
1075       Standard_Real par = ElCLib::Parameter(lin2d,sommet);
1076       vec1 = gp_Vec2d(sommet.X()-somBid.X(),sommet.Y()-somBid.Y());
1077       gp_Pnt2d Pd;
1078       ElCLib::D1(par,lin2d,Pd,vec1);
1079     } // else if ...
1080
1081     if (OE1 == TopAbs_REVERSED) {
1082       vec1.Reverse();
1083     } // if (OE1 ...
1084     Standard_Real cross = vec1*vec;
1085     Standard_Boolean Sense = cross > 0.;
1086     if (U1 > Vv1 && U1 > 2.*M_PI) {
1087       ElCLib::AdjustPeriodic(0.,2.*M_PI,Precision::Confusion(),U1,Vv1);
1088     } // if (U1 ... 
1089     if ( (O1 == TopAbs_FORWARD && OE1 == TopAbs_FORWARD) ||
1090          (O1 == TopAbs_REVERSED && OE1 == TopAbs_REVERSED) ) {
1091       filletEdge = BRepLib_MakeEdge(circle, refSurf,
1092                                     NewExtr1, NewExtr2, U1, Vv1);
1093     } // if (O1 == ...
1094     else {
1095       filletEdge = BRepLib_MakeEdge(circle, refSurf, 
1096                                     NewExtr2, NewExtr1, Vv1, U1);
1097     } // else ...
1098     if (!Sense) {
1099       TopAbs_Orientation S1 = filletEdge.Orientation();
1100       if ((O1 == TopAbs_FORWARD && OE1 == TopAbs_FORWARD) ||
1101           (O1 == TopAbs_REVERSED && OE1 == TopAbs_REVERSED) ) {
1102         filletEdge = BRepLib_MakeEdge(circle, refSurf, 
1103                                       NewExtr2, NewExtr1, Vv1, U1);
1104       }
1105       else {
1106         filletEdge = BRepLib_MakeEdge(circle, refSurf, 
1107                                       NewExtr1, NewExtr2, U1, Vv1);
1108       }
1109       if (S1 == TopAbs_FORWARD) {
1110         filletEdge.Orientation(TopAbs_REVERSED);
1111       }
1112       else {
1113         filletEdge.Orientation(TopAbs_FORWARD);
1114       }
1115     } // if (!Sense
1116
1117   } //  else if
1118
1119   BRepLib::BuildCurves3d(filletEdge);  
1120   return filletEdge;
1121 } // BuildFilletEdge
1122
1123
1124 //=======================================================================
1125 //function : IsAFillet
1126 //purpose  : 
1127 //=======================================================================
1128
1129 Standard_Boolean ChFi2d_Builder::IsAFillet(const TopoDS_Edge& E) const 
1130 {
1131   Standard_Integer i = 1;
1132   while (i <= fillets.Length()) {
1133     const TopoDS_Edge& currentEdge = TopoDS::Edge(fillets.Value(i));
1134     if (currentEdge.IsSame(E)) return Standard_True;
1135     i++;
1136   }
1137   return Standard_False;
1138 } // IsAFillet
1139
1140
1141 //=======================================================================
1142 //function : IsAChamfer
1143 //purpose  : 
1144 //=======================================================================
1145
1146 Standard_Boolean ChFi2d_Builder::IsAChamfer(const TopoDS_Edge& E) const 
1147 {
1148   Standard_Integer i = 1;
1149   while (i <= chamfers.Length()) {
1150     const TopoDS_Edge& currentEdge = TopoDS::Edge(chamfers.Value(i));
1151     if (currentEdge.IsSame(E)) return Standard_True;
1152     i++;
1153   }
1154   return Standard_False;
1155 } // IsAChamfer
1156
1157
1158
1159 //=======================================================================
1160 //function : IsLineOrCircle
1161 //purpose  : 
1162 //=======================================================================
1163
1164 Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E,
1165                                 const TopoDS_Face& F) 
1166 {
1167   Standard_Real first, last;
1168   TopLoc_Location loc;
1169 //  syntaxe invalide sur NT
1170 //      const Handle(Geom2d_Curve)& C = 
1171 //      BRep_Tool::CurveOnSurface(E,F,first,last);   
1172   Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,first,last);
1173   Handle(Geom2d_Curve) basisC; 
1174   Handle(Geom2d_TrimmedCurve) TC = Handle(Geom2d_TrimmedCurve)::DownCast(C);
1175   if (!TC.IsNull())
1176     basisC = Handle(Geom2d_Curve)::DownCast(TC->BasisCurve());
1177   else
1178     basisC = Handle(Geom2d_Curve)::DownCast(C);
1179
1180   if ( basisC->DynamicType() == STANDARD_TYPE(Geom2d_Circle)
1181       || basisC->DynamicType() == STANDARD_TYPE(Geom2d_Line) ) {
1182     return Standard_True;
1183   }
1184   else {
1185     return Standard_False;
1186   } // else ...
1187 } // IsLineOrCircle