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