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