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