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