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