0027104: DownCast() cannot return null for mismatched handle
[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()
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     fillets.Append(NewEdge);
643   else // the new edge is a chamfer
644     chamfers.Append(NewEdge);
645     if (history.IsBound(E1)) history.UnBind(E1);
646   if ( status != ChFi2d_FirstEdgeDegenerated
647        && status != ChFi2d_BothEdgesDegenerated) {
648     if (!E1.IsSame(TrimE1)) history.Bind(E1, TrimE1);
649   }
650     if (history.IsBound(E2)) history.UnBind(E2);
651   if ( status != ChFi2d_LastEdgeDegenerated
652        && status != ChFi2d_BothEdgesDegenerated) {
653     if (!E2.IsSame(TrimE2)) history.Bind(E2, TrimE2);
654   }
655 } // UpDateHistory
656
657
658 //=======================================================================
659 //function : UpDateHistory
660 //purpose  : 
661 //=======================================================================
662 void ChFi2d_Builder::UpDateHistory(const TopoDS_Edge& E1, 
663                                  const TopoDS_Edge& E2, 
664                                  const TopoDS_Edge& TrimE1, 
665                                  const TopoDS_Edge& TrimE2) 
666 {
667
668
669   if (history.IsBound(E1)) history.UnBind(E1);
670   if (!E1.IsSame(TrimE1)) history.Bind(E1, TrimE1);
671   if (history.IsBound(E2)) history.UnBind(E2);
672   if (!E2.IsSame(TrimE2)) history.Bind(E2, TrimE2);
673 } // UpDateHistory
674
675
676 //=======================================================================
677 //function : BasisEdge
678 //purpose  : 
679 //=======================================================================
680 const TopoDS_Edge& ChFi2d_Builder::BasisEdge(const TopoDS_Edge& E) const 
681 {
682   TopTools_DataMapIteratorOfDataMapOfShapeShape iterator(history);
683   TopoDS_Edge anEdge;
684   while (iterator.More()) {
685     anEdge = TopoDS::Edge(iterator.Value());
686     if (anEdge.IsSame(E)) { 
687       const TopoDS_Edge& anotherEdge = TopoDS::Edge(iterator.Key());
688       return anotherEdge;
689     } // if (anEdge.IsSame ...
690     iterator.Next();
691   } // while (Iterator.More ...
692   return E;
693 } // BasisEdge
694
695
696 //=======================================================================
697 //function : BuildFilletEdge
698 //purpose  : 
699 //=======================================================================
700 TopoDS_Edge ChFi2d_Builder::BuildFilletEdge(const TopoDS_Vertex& V, 
701                                           const TopoDS_Edge& AdjEdge1, 
702                                           const TopoDS_Edge& AdjEdge2, 
703                                           const Standard_Real Radius,
704                                           TopoDS_Vertex& NewExtr1,
705                                           TopoDS_Vertex& NewExtr2)
706 {
707   TopoDS_Edge E1, E2;
708   E1 = AdjEdge1;
709   E2 = AdjEdge2;
710   TopoDS_Vertex V1 = TopExp::FirstVertex(E1);
711   TopoDS_Vertex V2 = TopExp::LastVertex(E1);
712   TopoDS_Vertex V3 = TopExp::FirstVertex(E2);
713   TopoDS_Vertex V4 = TopExp::LastVertex(E2);
714
715   //========================================================================
716   //    The first arc is found.                                        +
717   //========================================================================
718
719   TopAbs_Orientation O1;
720   TopAbs_Orientation OE1;
721   OE1 = E1.Orientation();
722   E1.Orientation(TopAbs_FORWARD);
723   E2.Orientation(TopAbs_FORWARD);
724   TopoDS_Shape aLocalShape = E1.EmptyCopied();
725   TopoDS_Edge Ebid1 = TopoDS::Edge(aLocalShape);
726   aLocalShape = E2.EmptyCopied();
727   TopoDS_Edge Ebid2 = TopoDS::Edge(aLocalShape);
728 //  TopoDS_Edge Ebid1 = TopoDS::Edge(E1.EmptyCopied());
729 //  TopoDS_Edge Ebid2 = TopoDS::Edge(E2.EmptyCopied());
730   Standard_Real param1,param2,param3,param4;
731   
732   //========================================================================
733   //    Save non-modified parts of edges concerned.      +
734   //========================================================================
735
736   if (V1.IsSame(V)) {
737     param1 = BRep_Tool::Parameter(V1,E1);
738     param2 = BRep_Tool::Parameter(V2,E1);
739     O1 = V2.Orientation();
740   }
741   else {
742     param1 = BRep_Tool::Parameter(V2,E1);
743     param2 = BRep_Tool::Parameter(V1,E1);
744     O1 = V1.Orientation();
745   }
746   if (V3.IsSame(V)) {
747     param3 = BRep_Tool::Parameter(V3,E2);
748     param4 = BRep_Tool::Parameter(V4,E2);
749   }
750   else {
751     param3 = BRep_Tool::Parameter(V4,E2);
752     param4 = BRep_Tool::Parameter(V3,E2);
753   }
754   
755   //========================================================================
756   //    Restore geometric supports.                            +
757   //========================================================================
758
759   Handle(Geom2d_Curve) C1,C2; 
760   Standard_Real ufirst1,ulast1,ufirst2,ulast2,U1,U2,PU1,PU2,Vv1,Vv2;
761   Standard_Real PPU1,PPU2;
762   C1 = BRep_Tool::CurveOnSurface(E1,newFace,ufirst1,ulast1);
763   C2 = BRep_Tool::CurveOnSurface(E2,newFace,ufirst2,ulast2);
764
765   //========================================================================
766   //   Determination of the face for fillet.                                +
767   //========================================================================
768
769   gp_Pnt2d p;
770   gp_Vec2d Ve1,Ve2;
771   gp_Vec2d Ve3,Ve4;
772   Standard_Boolean Sens1 , Sens2;
773
774   Handle(Geom2d_Curve) basisC1,basisC2; 
775   Handle(Geom2d_TrimmedCurve) T1 = Handle(Geom2d_TrimmedCurve)::DownCast(C1);
776   if (!T1.IsNull())
777     basisC1 = T1->BasisCurve();
778   else
779     basisC1 = C1;
780   Handle(Geom2d_TrimmedCurve) T2 = Handle(Geom2d_TrimmedCurve)::DownCast(C2);
781   if (!T2.IsNull())
782     basisC2 = T2->BasisCurve();
783   else
784     basisC2 = C2;
785
786   if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
787     Handle(Geom2d_Circle) CC1 = Handle(Geom2d_Circle)::DownCast(basisC1);
788     ElCLib::D1(param1,CC1->Circ2d(),p,Ve1);
789     Sens1 = (CC1->Circ2d()).IsDirect(); 
790   } // if (C1->DynamicType() ...
791   else {
792     Handle(Geom2d_Line) CC1 = Handle(Geom2d_Line)::DownCast(basisC1);
793     ElCLib::D1(param1,CC1->Lin2d(),p,Ve1);
794     Sens1=Standard_True;
795   } // else ...
796   if (basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
797     Handle(Geom2d_Circle) CC2 = Handle(Geom2d_Circle)::DownCast(basisC2);
798     ElCLib::D1(param3,CC2->Circ2d(),p,Ve2);
799     Sens2 = (CC2->Circ2d()).IsDirect(); 
800   } // if if (C2->DynamicType() ...
801   else {
802     Handle(Geom2d_Line) CC2 = Handle(Geom2d_Line)::DownCast(basisC2);
803     ElCLib::D1(param3,CC2->Lin2d(),p,Ve2);
804     Sens2=Standard_True;
805   } // else ...
806
807   TopoDS_Edge filletEdge;
808
809   Standard_Real cross = Ve1.Crossed(Ve2);
810   Ve3 = Ve1;
811   Ve4 = Ve2;
812
813   // processing of tangency or downcast point 
814   if (Ve1.IsParallel(Ve2,Precision::Angular())) {
815     // Ve1 and Ve2 are parallel : cross at 0
816     cross = 0.;
817     if (param1<param2) {
818       Ve3 = -Ve1;
819     }
820     if (param3>param4) {
821       Ve4 = -Ve2;
822     }
823
824     if (! Ve4.IsOpposite(Ve3,Precision::Angular())) {
825       // There is a true tangency point and the calculation is stopped
826       status = ChFi2d_TangencyError;
827       return filletEdge;
828     }
829       // Otherwise this is a downcast point, and the calculation is continued
830   }
831
832   GccEnt_Position Qual1,Qual2;
833   if (cross < 0.) {
834     if (param3 > param4 ) {
835         if(Sens1 == Standard_True){
836            Qual1 = GccEnt_enclosed;
837          }
838         else {
839            Qual1 = GccEnt_outside;
840          }
841     }
842     else {
843         if(Sens1 == Standard_True){
844            Qual1 = GccEnt_outside;
845          }
846         else {
847            Qual1 = GccEnt_enclosed;
848         }
849     }
850     if (param1 > param2) {
851         if(Sens2 == Standard_True)
852           Qual2 = GccEnt_outside;
853         else
854            Qual2 = GccEnt_enclosed;
855     }
856     else {
857         if(Sens2 == Standard_True)
858            Qual2 = GccEnt_enclosed;
859         else
860            Qual2 = GccEnt_outside;      
861     }
862   } // if (cross < 0 ...
863   else {
864     if (param3 > param4 ) {
865         if( Sens1 == Standard_True)
866             Qual1 = GccEnt_outside;
867         else
868             Qual1 = GccEnt_enclosed;
869     }
870     else {
871         if( Sens1 == Standard_True)
872             Qual1 = GccEnt_enclosed;
873         else
874             Qual1 = GccEnt_outside;
875     }
876     if (param1 > param2 ) {
877         if( Sens2 == Standard_True)
878              Qual2 = GccEnt_enclosed;
879         else
880              Qual2 = GccEnt_outside;
881     }
882     else {
883         if( Sens2 == Standard_True)
884             Qual2 = GccEnt_outside;
885         else
886             Qual2 = GccEnt_enclosed;
887     }
888   } // else ...
889
890   Standard_Real Tol = Precision::Confusion();
891   Geom2dGcc_Circ2d2TanRad Fillet(Geom2dGcc_QualifiedCurve(basisC1,Qual1),
892                                  Geom2dGcc_QualifiedCurve(basisC2,Qual2),
893                                  Radius, Tol);
894   if (!Fillet.IsDone() || Fillet.NbSolutions()==0) {
895     status = ChFi2d_ComputationError;
896     return filletEdge;
897   }
898   else if (Fillet.NbSolutions() >= 1) {
899     status = ChFi2d_IsDone;
900     Standard_Integer numsol = 1;
901     Standard_Integer nsol = 1;
902     TopoDS_Vertex Vertex1,Vertex2;
903     gp_Pnt2d Ptg1,Ptg2;
904     Standard_Real dist;
905     Standard_Real dist1 = 1.e40;
906     Standard_Boolean inside = Standard_False;
907     while (nsol<=Fillet.NbSolutions()) {
908       Fillet.Tangency1(nsol,PU1,PU2,Ptg1);
909       dist = Ptg1.Distance(p);
910       if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Line)) {
911         inside = (PU2<param1 && PU2>param2) || (PU2<param2 && PU2>param1);
912         if ( inside && dist < dist1) {
913           numsol = nsol;
914           dist1 = dist;
915         } // if ((((inside && ...
916       } // if (C1->DynamicType( ...
917       else {
918         Fillet.Tangency2(nsol,PPU1,PPU2,Ptg2);
919         dist = Ptg2.Distance(p);
920         inside = (PPU2<param3 && PPU2>param4) || (PPU2<param4 && PPU2>param3);
921         //  case of arc of circle passing on the sewing
922         if ( ( basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle) ) && 
923             ( (2*M_PI<param3 && 2*M_PI>param4) || (2*M_PI<param4 && 2*M_PI>param3) ) ) {
924         //  cas param3<param4
925           inside = (param3<PPU2 && PPU2<2*M_PI) 
926                      || (0<=PPU2 && PPU2<param4-2*M_PI);
927         //  cas param4<param3
928           inside = inside || (param4<PPU2 && PPU2<2*M_PI) 
929                                || (0<=PPU2 && PPU2<param3-2*M_PI);
930         }
931         if ( inside && dist < dist1) {
932           numsol = nsol;
933           dist1 = dist;
934         } // if ((((param3 ...
935       } // else ...
936       nsol++;
937     } // while (nsol ...
938     gp_Circ2d cir(Fillet.ThisSolution(numsol));
939     Handle(Geom2d_Circle) circle = new Geom2d_Circle(cir);
940
941     BRep_Builder B;
942     BRepAdaptor_Surface Adaptor3dSurface(refFace);
943     Handle(Geom_Plane) refSurf = new Geom_Plane(Adaptor3dSurface.Plane());
944     Fillet.Tangency1(numsol,U1,U2,Ptg1);
945     Fillet.Tangency2(numsol,Vv1,Vv2,Ptg2);
946
947     // check the validity of parameters
948     //// modified by jgv, 08.08.2011 for bug 0022695 ////
949     //inside = (U2<param1 && U2>param2) || (U2<param2 && U2>param1);
950     inside = (U2 < param1 && U2 >= param2) || (U2 <= param2 && U2 > param1);
951     /////////////////////////////////////////////////////
952     if ( (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle))
953       &&  ( (2*M_PI<param1 && 2*M_PI>param2) || (2*M_PI<param2 && 2*M_PI>param1) ) ) {
954       // arc of circle containing the circle origin
955       //  case param1<param2
956       inside = (param1<U2 && U2<2*M_PI) || (0<=U2 && U2<param2-2*M_PI);
957       //  case param2<param1
958       inside = inside || (param2<U2 && U2<2*M_PI) || (0<=U2 && U2<param1-2*M_PI);
959     }
960     if (!inside) {
961       status = ChFi2d_ComputationError;
962       return filletEdge;
963     }
964
965     //// modified by jgv, 08.08.2011 for bug 0022695 ////
966     //inside = (Vv2<param3 && Vv2>param4) || (Vv2<param4 && Vv2>param3);
967     inside = (Vv2 < param3 && Vv2 >= param4) || (Vv2 <= param4 && Vv2 > param3);
968     /////////////////////////////////////////////////////
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     // arc of circle containing the circle origin
972       //  cas param3<param4
973       inside = (param3<Vv2 && Vv2<2*M_PI) || (0<=Vv2 && Vv2<param4-2*M_PI);
974       //  cas param4<param3
975       inside = inside || (param4<Vv2 && Vv2<2*M_PI) || (0<=Vv2 && Vv2<param3-2*M_PI);
976     }
977     if (!inside) {
978       status = ChFi2d_ComputationError;
979       return filletEdge;
980     }
981
982     gp_Pnt p1 = Adaptor3dSurface.Value(Ptg1.X(), Ptg1.Y());
983     gp_Pnt p2 = Adaptor3dSurface.Value(Ptg2.X(), Ptg2.Y());
984     B.MakeVertex(Vertex1, p1,Tol);
985     NewExtr1 = Vertex1;
986     if (Abs(U2-ufirst1) <= Precision::PConfusion()) {
987       NewExtr1 = V1;
988     }
989     if (Abs(U2-ulast1) <= Precision::PConfusion()) {
990       NewExtr1 = V2;
991     }
992
993     B.MakeVertex(Vertex2, p2,Tol);
994     NewExtr2 = Vertex2;
995     if (Abs(Vv2-ufirst2) <= Precision::PConfusion()) {
996       NewExtr2 = V3;
997     }
998     if (Abs(Vv2-ulast2) <= Precision::PConfusion()) {
999       NewExtr2 = V4;
1000     }
1001
1002     //=======================================================================
1003     //   Update tops of the fillet.                                  +
1004     //=======================================================================
1005     gp_Pnt Pntbid;
1006     gp_Pnt2d sommet;
1007     Pntbid = BRep_Tool::Pnt(V);
1008     sommet = gp_Pnt2d(Pntbid.X(),Pntbid.Y());
1009
1010     gp_Pnt pntBid;
1011     gp_Pnt2d somBid;
1012     if (V1.IsSame(V)) {
1013       pntBid = BRep_Tool::Pnt(V2);
1014       somBid = gp_Pnt2d(pntBid.X(),pntBid.Y());
1015     }
1016     else {
1017       pntBid = BRep_Tool::Pnt(V1);
1018       somBid = gp_Pnt2d(pntBid.X(),pntBid.Y());
1019     }
1020
1021     gp_Vec2d vec;
1022     ElCLib::D1(U1,cir,Ptg1,vec);
1023
1024     gp_Vec2d vec1;
1025     if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
1026       Handle(Geom2d_Circle) CC1 = Handle(Geom2d_Circle)::DownCast(basisC1);
1027       gp_Circ2d cir2d(CC1->Circ2d());
1028       Standard_Real par = ElCLib::Parameter(cir2d,Ptg1);
1029       gp_Pnt2d Pd;
1030       ElCLib::D1(par,cir2d,Pd,vec1);
1031     } // if (C1->DynamicType() ...
1032     else if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Line)) {
1033       Handle(Geom2d_Line) CC1 = Handle(Geom2d_Line)::DownCast(basisC1);
1034       gp_Lin2d lin2d(CC1->Lin2d());
1035       Standard_Real par = ElCLib::Parameter(lin2d,sommet);
1036       vec1 = gp_Vec2d(sommet.X()-somBid.X(),sommet.Y()-somBid.Y());
1037       gp_Pnt2d Pd;
1038       ElCLib::D1(par,lin2d,Pd,vec1);
1039     } // else if ...
1040
1041     if (OE1 == TopAbs_REVERSED) {
1042       vec1.Reverse();
1043     } // if (OE1 ...
1044     Standard_Boolean Sense = ( vec1*vec ) > 0.;
1045     if (U1 > Vv1 && U1 > 2.*M_PI) {
1046       ElCLib::AdjustPeriodic(0.,2.*M_PI,Precision::Confusion(),U1,Vv1);
1047     } // if (U1 ... 
1048     if ( (O1 == TopAbs_FORWARD && OE1 == TopAbs_FORWARD) ||
1049          (O1 == TopAbs_REVERSED && OE1 == TopAbs_REVERSED) ) {
1050       filletEdge = BRepLib_MakeEdge(circle, refSurf,
1051                                     NewExtr1, NewExtr2, U1, Vv1);
1052     } // if (O1 == ...
1053     else {
1054       filletEdge = BRepLib_MakeEdge(circle, refSurf, 
1055                                     NewExtr2, NewExtr1, Vv1, U1);
1056     } // else ...
1057     if (!Sense) {
1058       TopAbs_Orientation S1 = filletEdge.Orientation();
1059       if ((O1 == TopAbs_FORWARD && OE1 == TopAbs_FORWARD) ||
1060           (O1 == TopAbs_REVERSED && OE1 == TopAbs_REVERSED) ) {
1061         filletEdge = BRepLib_MakeEdge(circle, refSurf, 
1062                                       NewExtr2, NewExtr1, Vv1, U1);
1063       }
1064       else {
1065         filletEdge = BRepLib_MakeEdge(circle, refSurf, 
1066                                       NewExtr1, NewExtr2, U1, Vv1);
1067       }
1068       if (S1 == TopAbs_FORWARD) {
1069         filletEdge.Orientation(TopAbs_REVERSED);
1070       }
1071       else {
1072         filletEdge.Orientation(TopAbs_FORWARD);
1073       }
1074     } // if (!Sense
1075
1076   } //  else if
1077
1078   BRepLib::BuildCurves3d(filletEdge);  
1079   return filletEdge;
1080 } // BuildFilletEdge
1081
1082
1083 //=======================================================================
1084 //function : IsAFillet
1085 //purpose  : 
1086 //=======================================================================
1087
1088 Standard_Boolean ChFi2d_Builder::IsAFillet(const TopoDS_Edge& E) const 
1089 {
1090   Standard_Integer i = 1;
1091   while (i <= fillets.Length()) {
1092     const TopoDS_Edge& currentEdge = TopoDS::Edge(fillets.Value(i));
1093     if (currentEdge.IsSame(E)) return Standard_True;
1094     i++;
1095   }
1096   return Standard_False;
1097 } // IsAFillet
1098
1099
1100 //=======================================================================
1101 //function : IsAChamfer
1102 //purpose  : 
1103 //=======================================================================
1104
1105 Standard_Boolean ChFi2d_Builder::IsAChamfer(const TopoDS_Edge& E) const 
1106 {
1107   Standard_Integer i = 1;
1108   while (i <= chamfers.Length()) {
1109     const TopoDS_Edge& currentEdge = TopoDS::Edge(chamfers.Value(i));
1110     if (currentEdge.IsSame(E)) return Standard_True;
1111     i++;
1112   }
1113   return Standard_False;
1114 } // IsAChamfer
1115
1116
1117
1118 //=======================================================================
1119 //function : IsLineOrCircle
1120 //purpose  : 
1121 //=======================================================================
1122
1123 Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E,
1124                                 const TopoDS_Face& F) 
1125 {
1126   Standard_Real first, last;
1127   TopLoc_Location loc;
1128 //  syntaxe invalide sur NT
1129 //      const Handle(Geom2d_Curve)& C = 
1130 //      BRep_Tool::CurveOnSurface(E,F,first,last);   
1131   Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,first,last);
1132   Handle(Geom2d_Curve) basisC; 
1133   Handle(Geom2d_TrimmedCurve) TC = Handle(Geom2d_TrimmedCurve)::DownCast(C);
1134   if (!TC.IsNull())
1135     basisC = TC->BasisCurve();
1136   else
1137     basisC = C;
1138
1139   if ( basisC->DynamicType() == STANDARD_TYPE(Geom2d_Circle)
1140       || basisC->DynamicType() == STANDARD_TYPE(Geom2d_Line) ) {
1141     return Standard_True;
1142   }
1143   else {
1144     return Standard_False;
1145   } // else ...
1146 } // IsLineOrCircle