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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Modified: Tue Oct 15 10:12:02 1996
18 // correction in BuildFilletEdge (PRO3529 : computation of dist)
19 // Modified: Tue Oct 22 09:23:11 1996
20 // correction in BuildFilletEdge (PRO5827 : computation of vec1)
21 // Modified: Tue Oct 22 09:23:11 1996
22 // new status in ComputeFillet for degenerated edges (PRO4896)
23 // Modified: Thu Dec 5 16:25:44 1996
24 // correction in BuildFilletEdge (PRO4896 : NewExtr1, NewExtr2)
25 // Modified: Tue Apr 22 16:25:44 1996
26 // correction in BuildFilletEdge (ID140047 : inside)
27 // Modified: Fri Oct 24 10:47:52 1997
28 // distinction point de tangence --> on arrete
29 // point de rebroussement --> on continue
30 // (PRO10404 : Ve3, Ve4)
31 // Modified: Tue Oct 28 11:55:53 1997
32 // construction de filletEdge avec les parametres U1 et Vv1
33 // au lieu des vertex (PRO10434)
34 // Modified: Tue Apr 7 14:35:58 1998
35 // construction de filletEdge avec les parametres U1 et Vv1
36 // ET les vertex NewExtr1, NewExtr2 sinon pb sur qq aretes
37 // degenerees (GER60069 + controle de PRO10434)
38 // Modified: Mon Jun 22 13:32:25 1998
39 // verification de la validite des parametres (PRO13078 partiel)
40 // Modified: Fri Sep 25 09:38:04 1998
41 // status = ChFi2d_NotAuthorized si les aretes ne sont pas
42 // des droites ou des cercles; fonction IsLineOrCircle
48 #include <ChFi2d_Builder.ixx>
50 #include <BRepAdaptor_Surface.hxx>
51 #include <BRepLib.hxx>
52 #include <BRepLib_MakeEdge.hxx>
53 #include <BRepLib_MakeFace.hxx>
55 #include <BRep_Builder.hxx>
56 #include <BRep_Tool.hxx>
60 #include <GccEnt_Position.hxx>
62 #include <Geom_Circle.hxx>
63 #include <Geom_Curve.hxx>
64 #include <Geom_Line.hxx>
65 #include <Geom_Plane.hxx>
66 #include <Geom_Surface.hxx>
69 #include <Geom2d_TrimmedCurve.hxx>
70 #include <Geom2d_Circle.hxx>
71 #include <Geom2d_Curve.hxx>
72 #include <Geom2d_Line.hxx>
74 #include <Geom2dInt_GInter.hxx>
75 #include <Geom2dGcc_Circ2d2TanRad.hxx>
76 #include <Geom2dGcc_QualifiedCurve.hxx>
78 #include <IntRes2d_IntersectionPoint.hxx>
82 #include <gp_Pnt2d.hxx>
83 #include <gp_Circ2d.hxx>
84 #include <gp_Vec2d.hxx>
86 #include <Precision.hxx>
88 #include <TopAbs_Orientation.hxx>
90 #include <TopExp_Explorer.hxx>
91 #include <TopLoc_Location.hxx>
92 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
93 #include <TopTools_ListIteratorOfListOfShape.hxx>
94 #include <TopTools_IndexedMapOfShape.hxx>
97 #include <TopoDS_Edge.hxx>
98 #include <TopoDS_Wire.hxx>
100 static Standard_Boolean IsIssuedFrom(const TopoDS_Edge& E,
101 const TopTools_IndexedMapOfShape& Map,
102 TopoDS_Edge& BasisEdge);
104 static Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E,
105 const TopoDS_Face& F);
108 //=======================================================================
109 //function : ChFi2d_Builder
111 //=======================================================================
113 ChFi2d_Builder::ChFi2d_Builder()
117 //=======================================================================
118 //function : ChFi2d_Builder
120 //=======================================================================
122 ChFi2d_Builder::ChFi2d_Builder(const TopoDS_Face& F)
125 status = ChFi2d_NoFace;
129 // syntaxe invalide sur NT
130 // const Handle(Geom_Surface)& surf = BRep_Tool::Surface( F, Loc);
131 // if (surf->IsKind(STANDARD_TYPE(Geom_Plane))) {
132 if ( BRep_Tool::Surface( F, Loc)
133 -> IsKind(STANDARD_TYPE(Geom_Plane)) ) {
134 newFace = refFace = F;
135 newFace.Orientation(TopAbs_FORWARD);
136 BRepLib::BuildCurves3d(newFace);
137 status = ChFi2d_Ready;
139 else status = ChFi2d_NotPlanar;
142 //=======================================================================
145 //=======================================================================
147 void ChFi2d_Builder::Init(const TopoDS_Face& F)
150 status = ChFi2d_NoFace;
157 // syntaxe invalide sur NT
158 // const Handle(Geom_Surface)& surf = BRep_Tool::Surface( F, Loc);
159 // if (surf->IsKind(STANDARD_TYPE(Geom_Plane))) {
160 if ( BRep_Tool::Surface( F, Loc)
161 -> IsKind(STANDARD_TYPE(Geom_Plane)) ) {
162 newFace = refFace = F;
163 newFace.Orientation(TopAbs_FORWARD);
164 status = ChFi2d_Ready;
166 else status = ChFi2d_NotPlanar;
170 //=======================================================================
173 //=======================================================================
175 void ChFi2d_Builder::Init(const TopoDS_Face& RefFace,
176 const TopoDS_Face& ModFace)
178 if (RefFace.IsNull() || ModFace.IsNull()) {
179 status = ChFi2d_NoFace;
186 // syntaxe invalide sur NT
187 // const Handle(Geom_Surface)& surf = BRep_Tool::Surface( RefFace, Loc);
188 // if (!surf->IsKind(STANDARD_TYPE(Geom_Plane))) {
189 if ( ! BRep_Tool::Surface( RefFace, loc)
190 -> IsKind(STANDARD_TYPE(Geom_Plane)) ) {
191 status = ChFi2d_NotPlanar;
197 newFace.Orientation(TopAbs_FORWARD);
198 status = ChFi2d_Ready;
200 // Research in newFace all the edges which not appear in RefFace
201 // The sequence newEdges will contains this edges.
203 TopTools_SequenceOfShape newEdges;
204 TopTools_IndexedMapOfShape refEdgesMap;
205 TopExp::MapShapes(refFace, TopAbs_EDGE, refEdgesMap);
206 TopExp_Explorer ex(newFace, TopAbs_EDGE);
208 const TopoDS_Edge& currentEdge = TopoDS::Edge(ex.Current());
209 if (!refEdgesMap.Contains(currentEdge))
210 newEdges.Append(currentEdge);
214 // update of history, fillets and chamfers fields
215 Standard_Integer i = 1;
216 Standard_Real first, last;
217 TopoDS_Edge basisEdge;
218 while ( i <= newEdges.Length()) {
219 const TopoDS_Edge& currentEdge = TopoDS::Edge(newEdges.Value(i));
220 if (IsIssuedFrom(currentEdge, refEdgesMap, basisEdge))
221 history.Bind(basisEdge, currentEdge);
223 // this edge is a chamfer or a fillet
224 // syntaxe invalide sur NT
225 // const Handle(Geom_Curve)& curve =
226 // BRep_Tool::Curve(currentEdge, loc, first, last);
227 Handle(Geom_Curve) curve =
228 BRep_Tool::Curve(currentEdge, loc, first, last);
229 if (curve->IsKind(STANDARD_TYPE(Geom_Circle))) {
230 fillets.Append(currentEdge);
232 else if (curve->IsKind(STANDARD_TYPE(Geom_Line))) {
233 chamfers.Append(currentEdge);
236 status = ChFi2d_InitialisationError;
239 } // this edge is ...
245 //=======================================================================
246 //function : IsIssuedFrom
247 //purpose : Search in <Map> if <E> has a parent edge. If a parent has
248 // been find, this edge is returned in <BasisEdge>, else <E> is
249 // returned in <BasisEdge>.
250 //=======================================================================
251 Standard_Boolean IsIssuedFrom(const TopoDS_Edge& E,
252 const TopTools_IndexedMapOfShape& Map,
253 TopoDS_Edge& BasisEdge)
255 TopLoc_Location loc1, loc2;
256 Standard_Real f1, L1, f2, L2;
257 // syntaxe invalide sur NT
258 // const Handle(Geom_Curve)& c1 =
259 // BRep_Tool::Curve(E, loc1, f1, L1);
260 Handle(Geom_Curve) c1 = BRep_Tool::Curve(E, loc1, f1, L1);
262 for (Standard_Integer i = 1; i <= Map.Extent(); i++ ) {
263 const TopoDS_Edge& currentEdge = TopoDS::Edge(Map.FindKey(i));
264 // syntaxe invalide sur NT
265 // const Handle(Geom_Curve)& c2 =
266 // BRep_Tool::Curve(currentEdge, loc2, f2, L2);
267 Handle(Geom_Curve) c2 = BRep_Tool::Curve(currentEdge, loc2, f2, L2);
269 (((f1 > f2 && f1 < L2) || (L1 > f2 && L1 < L2) ) ||
270 ( (f1 > L2 && f1 < f2) || (L1 > L2 && L1 < f2) )) ) {
271 BasisEdge = currentEdge;
272 BasisEdge.Orientation(E.Orientation());
273 return Standard_True;
275 } // for (Standard_Integer i ...
277 return Standard_False;
281 //=======================================================================
282 //function : AddFillet
284 //=======================================================================
285 TopoDS_Edge ChFi2d_Builder::AddFillet(const TopoDS_Vertex& V,
286 const Standard_Real Radius)
288 TopoDS_Edge adjEdge1, adjEdge2, basisEdge1, basisEdge2;
289 TopoDS_Edge adjEdge1Mod, adjEdge2Mod, fillet;
290 status = ChFi2d::FindConnectedEdges(newFace, V, adjEdge1, adjEdge2);
291 if (status == ChFi2d_ConnexionError) return fillet;
293 if (IsAFillet(adjEdge1) || IsAChamfer(adjEdge1) ||
294 IsAFillet(adjEdge2) || IsAChamfer(adjEdge2)) {
295 status = ChFi2d_NotAuthorized;
297 } // if (IsAFillet ...
299 if (!IsLineOrCircle(adjEdge1,newFace)
300 || !IsLineOrCircle(adjEdge2,newFace) ) {
301 status = ChFi2d_NotAuthorized;
303 } // if (!IsLineOrCircle ...
305 ComputeFillet(V, adjEdge1, adjEdge2, Radius,
306 adjEdge1Mod, adjEdge2Mod, fillet);
307 if (status == ChFi2d_IsDone
308 || status == ChFi2d_FirstEdgeDegenerated
309 || status == ChFi2d_LastEdgeDegenerated
310 || status == ChFi2d_BothEdgesDegenerated) {
311 BuildNewWire(adjEdge1, adjEdge2, adjEdge1Mod, fillet, adjEdge2Mod);
312 basisEdge1 = BasisEdge(adjEdge1);
313 basisEdge2 = BasisEdge(adjEdge2);
314 UpDateHistory(basisEdge1, basisEdge2,
315 adjEdge1Mod, adjEdge2Mod, fillet, 1);
316 status = ChFi2d_IsDone;
317 return TopoDS::Edge(fillets.Value(fillets.Length()));
322 //=======================================================================
323 //function : ModifyFillet
325 //=======================================================================
327 TopoDS_Edge ChFi2d_Builder::ModifyFillet(const TopoDS_Edge& Fillet,
328 const Standard_Real Radius)
330 TopoDS_Vertex aVertex = RemoveFillet(Fillet);
331 TopoDS_Edge aFillet = AddFillet(aVertex, Radius);
335 //=======================================================================
336 //function : RemoveFillet
338 //=======================================================================
340 TopoDS_Vertex ChFi2d_Builder::RemoveFillet(const TopoDS_Edge& Fillet)
342 TopoDS_Vertex commonVertex;
343 Standard_Integer i = 1;
344 Standard_Integer IsFind = Standard_False;
345 while (i <= fillets.Length()) {
346 const TopoDS_Edge& aFillet = TopoDS::Edge(fillets.Value(i));
347 if (aFillet.IsSame(Fillet)) {
349 IsFind = Standard_True;
354 if (!IsFind) return commonVertex;
357 TopoDS_Vertex firstVertex, lastVertex;
358 TopExp::Vertices(Fillet, firstVertex, lastVertex);
361 TopoDS_Edge adjEdge1, adjEdge2;
362 status = ChFi2d::FindConnectedEdges(newFace, firstVertex,
364 if (status == ChFi2d_ConnexionError) return commonVertex;
366 TopoDS_Edge basisEdge1, basisEdge2, E1, E2;
367 // E1 and E2 are the adjacent edges to Fillet
369 if (adjEdge1.IsSame(Fillet)) E1 = adjEdge2;
371 basisEdge1 = BasisEdge(E1);
372 status = ChFi2d::FindConnectedEdges(newFace, lastVertex,adjEdge1, adjEdge2);
373 if (status == ChFi2d_ConnexionError) return commonVertex;
374 if (adjEdge1.IsSame(Fillet)) E2 = adjEdge2;
376 basisEdge2 = BasisEdge(E2);
377 TopoDS_Vertex connectionE1Fillet, connectionE2Fillet;
378 Standard_Boolean hasConnection =
379 ChFi2d::CommonVertex(basisEdge1, basisEdge2, commonVertex);
380 if (!hasConnection) {
381 status = ChFi2d_ConnexionError;
384 hasConnection = ChFi2d::CommonVertex(E1, Fillet, connectionE1Fillet);
385 if (!hasConnection) {
386 status = ChFi2d_ConnexionError;
389 hasConnection = ChFi2d::CommonVertex(E2, Fillet, connectionE2Fillet);
390 if (!hasConnection) {
391 status = ChFi2d_ConnexionError;
395 // rebuild edges on wire
396 TopoDS_Edge newEdge1, newEdge2;
397 TopoDS_Vertex v, v1, v2;
398 BRepLib_MakeEdge makeEdge;
400 Standard_Real first, last;
402 TopExp::Vertices(E1, firstVertex, lastVertex);
403 TopExp::Vertices(basisEdge1, v1, v2);
404 if (v1.IsSame(commonVertex)) v = v2;
407 if ( firstVertex.IsSame(v) || lastVertex.IsSame(v))
408 // It means the edge support only one fillet. In this case
409 // the new edge must be the basis edge.
410 newEdge1 = basisEdge1;
412 // It means the edge support one fillet on each end.
413 if (firstVertex.IsSame(connectionE1Fillet)) {
414 // syntaxe invalide sur NT
415 // const Handle(Geom_Curve)& curve =
416 // BRep_Tool::Curve(E1, loc, first, last);
417 Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, loc, first, last);
418 makeEdge.Init(curve, commonVertex, lastVertex);
419 newEdge1 = makeEdge.Edge();
420 newEdge1.Orientation(E1.Orientation());
421 newEdge1.Location(E1.Location());
422 } // if (firstVertex ...
423 else if (lastVertex.IsSame(connectionE1Fillet)) {
424 // syntax wrong on NT
425 // const Handle(Geom_Curve)& curve =
426 // BRep_Tool::Curve(E1, loc, first, last);
427 Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, loc, first, last);
428 makeEdge.Init(curve, firstVertex, commonVertex);
429 newEdge1 = makeEdge.Edge();
430 newEdge1.Orientation(E1.Orientation());
431 newEdge1.Location(E1.Location());
432 } // else if (lastVertex ...
435 TopExp::Vertices(basisEdge2, v1, v2);
436 if (v1.IsSame(commonVertex)) v = v2;
439 TopExp::Vertices(E2, firstVertex, lastVertex);
440 if ( firstVertex.IsSame(v) || lastVertex.IsSame(v))
441 // It means the edge support only one fillet. In this case
442 // the new edge must be the basis edge.
443 newEdge2 = basisEdge2;
445 // It means the edge support one fillet on each end.
446 if (firstVertex.IsSame(connectionE2Fillet)) {
447 // syntax wrong on NT
448 // const Handle(Geom_Curve)& curve =
449 // BRep_Tool::Curve(E2, loc, first, last);
450 Handle(Geom_Curve) curve = BRep_Tool::Curve(E2, loc, first, last);
451 makeEdge.Init(curve, commonVertex, lastVertex);
452 newEdge2 = makeEdge.Edge();
453 newEdge2.Orientation(E2.Orientation());
454 newEdge2.Location(E2.Location());
455 } // if (firstVertex ...
456 else if (lastVertex.IsSame(connectionE2Fillet)) {
457 // syntax wrong on NT
458 // const Handle(Geom_Curve)& curve =
459 // BRep_Tool::Curve(E2, loc, first, last);
460 Handle(Geom_Curve) curve = BRep_Tool::Curve(E2, loc, first, last);
461 makeEdge.Init(curve, firstVertex, commonVertex);
462 newEdge2 = makeEdge.Edge();
463 newEdge2.Orientation(E2.Orientation());
464 newEdge2.Location(E2.Location());
465 } // else if (lastVertex ...
468 // rebuild the newFace
469 TopExp_Explorer Ex(newFace, TopAbs_EDGE);
476 const TopoDS_Edge& theEdge = TopoDS::Edge(Ex.Current());
477 if (!theEdge.IsSame(E1) &&
478 !theEdge.IsSame(E2) &&
479 !theEdge.IsSame(Fillet))
480 B.Add(newWire, theEdge);
483 B.Add(newWire, newEdge1);
484 else if (theEdge == E2)
485 B.Add(newWire, newEdge2);
489 BRepAdaptor_Surface Adaptor3dSurface(refFace);
490 BRepLib_MakeFace mFace(Adaptor3dSurface.Plane(), newWire);
494 UpDateHistory(basisEdge1, basisEdge2, newEdge1, newEdge2);
500 //=======================================================================
501 //function : ComputeFillet
503 //=======================================================================
505 void ChFi2d_Builder::ComputeFillet(const TopoDS_Vertex& V,
506 const TopoDS_Edge& E1,
507 const TopoDS_Edge& E2,
508 const Standard_Real Radius,
513 TopoDS_Vertex newExtr1, newExtr2;
514 Standard_Boolean Degen1, Degen2;
515 Fillet = BuildFilletEdge(V, E1, E2, Radius, newExtr1, newExtr2);
516 if ( status != ChFi2d_IsDone) return;
517 TrimE1 = BuildNewEdge(E1, V, newExtr1, Degen1);
518 TrimE2 = BuildNewEdge(E2, V, newExtr2, Degen2);
519 if (Degen1 && Degen2 ) status = ChFi2d_BothEdgesDegenerated;
520 if (Degen1 && !Degen2 ) status = ChFi2d_FirstEdgeDegenerated;
521 if (!Degen1 && Degen2 ) status = ChFi2d_LastEdgeDegenerated;
526 //=======================================================================
527 //function : BuildNewWire
529 //=======================================================================
531 void ChFi2d_Builder::BuildNewWire (const TopoDS_Edge& OldE1,
532 const TopoDS_Edge& OldE2,
533 const TopoDS_Edge& E1,
534 const TopoDS_Edge& Fillet,
535 const TopoDS_Edge& E2)
538 Standard_Boolean aClosedStatus = Standard_True;
540 TopExp_Explorer Ex(refFace, TopAbs_WIRE);
542 const TopoDS_Wire& aWire = TopoDS::Wire(Ex.Current());
543 aClosedStatus = aWire.Closed();
548 Standard_Boolean filletIsAdded = Standard_False;
550 Ex.Init(newFace, TopAbs_EDGE);
556 const TopoDS_Edge& theEdge = TopoDS::Edge(Ex.Current());
557 if (!theEdge.IsSame(OldE1) && !theEdge.IsSame(OldE2)) {
558 B.Add(newWire, theEdge);
561 if (theEdge == OldE1) {
562 if (status != ChFi2d_FirstEdgeDegenerated
563 && status != ChFi2d_BothEdgesDegenerated) {
566 if ( !filletIsAdded) {
567 B.Add(newWire, Fillet);
568 filletIsAdded = Standard_True;
569 } // if ( !filletIsAdded ...
570 } // if (theEdge == ...
572 if (status != ChFi2d_LastEdgeDegenerated
573 && status != ChFi2d_BothEdgesDegenerated) {
576 if ( !filletIsAdded) {
577 B.Add(newWire, Fillet);
578 filletIsAdded = Standard_True;
579 }// if ( !filletIsAdded ...
585 newWire.Closed(aClosedStatus);
586 BRepAdaptor_Surface Adaptor3dSurface(refFace);
587 BRepLib_MakeFace mFace(Adaptor3dSurface.Plane(), newWire);
593 //=======================================================================
594 //function : BuildNewEdge
596 //=======================================================================
598 TopoDS_Edge ChFi2d_Builder::BuildNewEdge(const TopoDS_Edge& E1,
599 const TopoDS_Vertex& OldExtr,
600 const TopoDS_Vertex& NewExtr) const
602 BRepLib_MakeEdge makeEdge;
604 Standard_Real first, last;
605 TopoDS_Vertex firstVertex, lastVertex;
606 TopExp::Vertices(E1, firstVertex, lastVertex);
607 // syntaxe invalide sur NT
608 // const Handle(Geom_Curve)& curve =
609 // BRep_Tool::Curve(E1, first, last);
610 Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, first, last);
611 if (firstVertex.IsSame(OldExtr))
612 makeEdge.Init(curve, NewExtr, lastVertex);
614 makeEdge.Init(curve, firstVertex, NewExtr);
615 TopoDS_Edge anEdge = makeEdge;
616 anEdge.Orientation(E1.Orientation());
617 // anEdge.Location(E1.Location());
622 //=======================================================================
623 //function : BuildNewEdge
624 //purpose : special flag if the new edge is degenerated
625 //=======================================================================
627 TopoDS_Edge ChFi2d_Builder::BuildNewEdge(const TopoDS_Edge& E1,
628 const TopoDS_Vertex& OldExtr,
629 const TopoDS_Vertex& NewExtr,
630 Standard_Boolean& IsDegenerated) const
632 BRepLib_MakeEdge makeEdge;
634 Standard_Real first, last;
635 IsDegenerated = Standard_False;
636 TopoDS_Vertex firstVertex, lastVertex;
637 TopExp::Vertices(E1, firstVertex, lastVertex);
638 gp_Pnt Pnew = BRep_Tool::Pnt(NewExtr);
639 Standard_Boolean PonctualEdge = Standard_False;
640 Standard_Real Tol = Precision::Confusion();
641 // syntax wrong on NT
642 // const Handle(Geom_Curve)& curve =
643 // BRep_Tool::Curve(E1, first, last);
644 Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, first, last);
645 if (firstVertex.IsSame(OldExtr)) {
646 makeEdge.Init(curve, NewExtr, lastVertex);
647 gp_Pnt PV = BRep_Tool::Pnt(lastVertex);
648 PonctualEdge = (Pnew.Distance(PV)<Tol);
651 makeEdge.Init(curve, firstVertex, NewExtr);
652 gp_Pnt PV = BRep_Tool::Pnt(firstVertex);
653 PonctualEdge = (Pnew.Distance(PV)<Tol);
656 BRepLib_EdgeError error = makeEdge.Error();
657 if (error==BRepLib_LineThroughIdenticPoints || PonctualEdge) {
658 IsDegenerated = Standard_True;
663 anEdge.Orientation(E1.Orientation());
664 // anEdge.Location(E1.Location());
670 //=======================================================================
671 //function : UpDateHistory
673 //=======================================================================
674 void ChFi2d_Builder::UpDateHistory(const TopoDS_Edge& E1,
675 const TopoDS_Edge& E2,
676 const TopoDS_Edge& TrimE1,
677 const TopoDS_Edge& TrimE2,
678 const TopoDS_Edge& NewEdge,
679 const Standard_Integer Id)
681 if (Id == 1) // the new edge is a fillet
682 fillets.Append(NewEdge);
683 else // the new edge is a chamfer
684 chamfers.Append(NewEdge);
685 if (history.IsBound(E1)) history.UnBind(E1);
686 if ( status != ChFi2d_FirstEdgeDegenerated
687 && status != ChFi2d_BothEdgesDegenerated) {
688 if (!E1.IsSame(TrimE1)) history.Bind(E1, TrimE1);
690 if (history.IsBound(E2)) history.UnBind(E2);
691 if ( status != ChFi2d_LastEdgeDegenerated
692 && status != ChFi2d_BothEdgesDegenerated) {
693 if (!E2.IsSame(TrimE2)) history.Bind(E2, TrimE2);
698 //=======================================================================
699 //function : UpDateHistory
701 //=======================================================================
702 void ChFi2d_Builder::UpDateHistory(const TopoDS_Edge& E1,
703 const TopoDS_Edge& E2,
704 const TopoDS_Edge& TrimE1,
705 const TopoDS_Edge& TrimE2)
709 if (history.IsBound(E1)) history.UnBind(E1);
710 if (!E1.IsSame(TrimE1)) history.Bind(E1, TrimE1);
711 if (history.IsBound(E2)) history.UnBind(E2);
712 if (!E2.IsSame(TrimE2)) history.Bind(E2, TrimE2);
716 //=======================================================================
717 //function : BasisEdge
719 //=======================================================================
720 const TopoDS_Edge& ChFi2d_Builder::BasisEdge(const TopoDS_Edge& E) const
722 TopTools_DataMapIteratorOfDataMapOfShapeShape iterator(history);
724 while (iterator.More()) {
725 anEdge = TopoDS::Edge(iterator.Value());
726 if (anEdge.IsSame(E)) {
727 const TopoDS_Edge& anotherEdge = TopoDS::Edge(iterator.Key());
729 } // if (anEdge.IsSame ...
731 } // while (Iterator.More ...
736 //=======================================================================
737 //function : BuildFilletEdge
739 //=======================================================================
740 TopoDS_Edge ChFi2d_Builder::BuildFilletEdge(const TopoDS_Vertex& V,
741 const TopoDS_Edge& AdjEdge1,
742 const TopoDS_Edge& AdjEdge2,
743 const Standard_Real Radius,
744 TopoDS_Vertex& NewExtr1,
745 TopoDS_Vertex& NewExtr2)
750 TopoDS_Vertex V1 = TopExp::FirstVertex(E1);
751 TopoDS_Vertex V2 = TopExp::LastVertex(E1);
752 TopoDS_Vertex V3 = TopExp::FirstVertex(E2);
753 TopoDS_Vertex V4 = TopExp::LastVertex(E2);
755 //========================================================================
756 // The first arc is found. +
757 //========================================================================
759 TopAbs_Orientation O1;
760 TopAbs_Orientation OE1;
761 OE1 = E1.Orientation();
762 E1.Orientation(TopAbs_FORWARD);
763 E2.Orientation(TopAbs_FORWARD);
764 TopoDS_Shape aLocalShape = E1.EmptyCopied();
765 TopoDS_Edge Ebid1 = TopoDS::Edge(aLocalShape);
766 aLocalShape = E2.EmptyCopied();
767 TopoDS_Edge Ebid2 = TopoDS::Edge(aLocalShape);
768 // TopoDS_Edge Ebid1 = TopoDS::Edge(E1.EmptyCopied());
769 // TopoDS_Edge Ebid2 = TopoDS::Edge(E2.EmptyCopied());
770 Standard_Real param1,param2,param3,param4;
772 //========================================================================
773 // Save non-modified parts of edges concerned. +
774 //========================================================================
777 param1 = BRep_Tool::Parameter(V1,E1);
778 param2 = BRep_Tool::Parameter(V2,E1);
779 O1 = V2.Orientation();
782 param1 = BRep_Tool::Parameter(V2,E1);
783 param2 = BRep_Tool::Parameter(V1,E1);
784 O1 = V1.Orientation();
787 param3 = BRep_Tool::Parameter(V3,E2);
788 param4 = BRep_Tool::Parameter(V4,E2);
791 param3 = BRep_Tool::Parameter(V4,E2);
792 param4 = BRep_Tool::Parameter(V3,E2);
795 //========================================================================
796 // Restore geometric supports. +
797 //========================================================================
799 Handle(Geom2d_Curve) C1,C2;
800 Standard_Real ufirst1,ulast1,ufirst2,ulast2,U1,U2,PU1,PU2,Vv1,Vv2;
801 Standard_Real PPU1,PPU2;
802 C1 = BRep_Tool::CurveOnSurface(E1,newFace,ufirst1,ulast1);
803 C2 = BRep_Tool::CurveOnSurface(E2,newFace,ufirst2,ulast2);
805 //========================================================================
806 // Determination of the face for fillet. +
807 //========================================================================
812 Standard_Boolean Sens1 , Sens2;
814 Handle(Geom2d_Curve) basisC1,basisC2;
815 Handle(Geom2d_TrimmedCurve) T1 = Handle(Geom2d_TrimmedCurve)::DownCast(C1);
817 basisC1 = Handle(Geom2d_Curve)::DownCast(T1->BasisCurve());
819 basisC1 = Handle(Geom2d_Curve)::DownCast(C1);
820 Handle(Geom2d_TrimmedCurve) T2 = Handle(Geom2d_TrimmedCurve)::DownCast(C2);
822 basisC2 = Handle(Geom2d_Curve)::DownCast(T2->BasisCurve());
824 basisC2 = Handle(Geom2d_Curve)::DownCast(C2);
826 if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
827 Handle(Geom2d_Circle) CC1 = Handle(Geom2d_Circle)::DownCast(basisC1);
828 ElCLib::D1(param1,CC1->Circ2d(),p,Ve1);
829 Sens1 = (CC1->Circ2d()).IsDirect();
830 } // if (C1->DynamicType() ...
832 Handle(Geom2d_Line) CC1 = Handle(Geom2d_Line)::DownCast(basisC1);
833 ElCLib::D1(param1,CC1->Lin2d(),p,Ve1);
836 if (basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
837 Handle(Geom2d_Circle) CC2 = Handle(Geom2d_Circle)::DownCast(basisC2);
838 ElCLib::D1(param3,CC2->Circ2d(),p,Ve2);
839 Sens2 = (CC2->Circ2d()).IsDirect();
840 } // if if (C2->DynamicType() ...
842 Handle(Geom2d_Line) CC2 = Handle(Geom2d_Line)::DownCast(basisC2);
843 ElCLib::D1(param3,CC2->Lin2d(),p,Ve2);
847 TopoDS_Edge filletEdge;
849 Standard_Real cross = Ve1.Crossed(Ve2);
853 // processing of tangency or downcast point
854 if (Ve1.IsParallel(Ve2,Precision::Angular())) {
855 // Ve1 and Ve2 are parallel : cross at 0
864 if (! Ve4.IsOpposite(Ve3,Precision::Angular())) {
865 // There is a true tangency point and the calculation is stopped
866 status = ChFi2d_TangencyError;
869 // Otherwise this is a downcast point, and the calculation is continued
872 GccEnt_Position Qual1,Qual2;
874 if (param3 > param4 ) {
875 if(Sens1 == Standard_True){
876 Qual1 = GccEnt_enclosed;
879 Qual1 = GccEnt_outside;
883 if(Sens1 == Standard_True){
884 Qual1 = GccEnt_outside;
887 Qual1 = GccEnt_enclosed;
890 if (param1 > param2) {
891 if(Sens2 == Standard_True)
892 Qual2 = GccEnt_outside;
894 Qual2 = GccEnt_enclosed;
897 if(Sens2 == Standard_True)
898 Qual2 = GccEnt_enclosed;
900 Qual2 = GccEnt_outside;
902 } // if (cross < 0 ...
904 if (param3 > param4 ) {
905 if( Sens1 == Standard_True)
906 Qual1 = GccEnt_outside;
908 Qual1 = GccEnt_enclosed;
911 if( Sens1 == Standard_True)
912 Qual1 = GccEnt_enclosed;
914 Qual1 = GccEnt_outside;
916 if (param1 > param2 ) {
917 if( Sens2 == Standard_True)
918 Qual2 = GccEnt_enclosed;
920 Qual2 = GccEnt_outside;
923 if( Sens2 == Standard_True)
924 Qual2 = GccEnt_outside;
926 Qual2 = GccEnt_enclosed;
930 Standard_Real Tol = Precision::Confusion();
931 Geom2dGcc_Circ2d2TanRad Fillet(Geom2dGcc_QualifiedCurve(basisC1,Qual1),
932 Geom2dGcc_QualifiedCurve(basisC2,Qual2),
934 if (!Fillet.IsDone() || Fillet.NbSolutions()==0) {
935 status = ChFi2d_ComputationError;
938 else if (Fillet.NbSolutions() >= 1) {
939 status = ChFi2d_IsDone;
940 Standard_Integer numsol = 1;
941 Standard_Integer nsol = 1;
942 TopoDS_Vertex Vertex1,Vertex2;
945 Standard_Real dist1 = 1.e40;
946 Standard_Boolean inside = Standard_False;
947 while (nsol<=Fillet.NbSolutions()) {
948 Fillet.Tangency1(nsol,PU1,PU2,Ptg1);
949 dist = Ptg1.Distance(p);
950 if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Line)) {
951 inside = (PU2<param1 && PU2>param2) || (PU2<param2 && PU2>param1);
952 if ( inside && dist < dist1) {
955 } // if ((((inside && ...
956 } // if (C1->DynamicType( ...
958 Fillet.Tangency2(nsol,PPU1,PPU2,Ptg2);
959 dist = Ptg2.Distance(p);
960 inside = (PPU2<param3 && PPU2>param4) || (PPU2<param4 && PPU2>param3);
961 // case of arc of circle passing on the sewing
962 if ( ( basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle) ) &&
963 ( (2*M_PI<param3 && 2*M_PI>param4) || (2*M_PI<param4 && 2*M_PI>param3) ) ) {
965 inside = (param3<PPU2 && PPU2<2*M_PI)
966 || (0<=PPU2 && PPU2<param4-2*M_PI);
968 inside = inside || (param4<PPU2 && PPU2<2*M_PI)
969 || (0<=PPU2 && PPU2<param3-2*M_PI);
971 if ( inside && dist < dist1) {
974 } // if ((((param3 ...
978 gp_Circ2d cir(Fillet.ThisSolution(numsol));
979 Handle(Geom2d_Circle) circle = new Geom2d_Circle(cir);
982 BRepAdaptor_Surface Adaptor3dSurface(refFace);
983 Handle(Geom_Plane) refSurf = new Geom_Plane(Adaptor3dSurface.Plane());
984 Fillet.Tangency1(numsol,U1,U2,Ptg1);
985 Fillet.Tangency2(numsol,Vv1,Vv2,Ptg2);
987 // check the validity of parameters
988 //// modified by jgv, 08.08.2011 for bug 0022695 ////
989 //inside = (U2<param1 && U2>param2) || (U2<param2 && U2>param1);
990 inside = (U2 < param1 && U2 >= param2) || (U2 <= param2 && U2 > param1);
991 /////////////////////////////////////////////////////
992 if ( (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle))
993 && ( (2*M_PI<param1 && 2*M_PI>param2) || (2*M_PI<param2 && 2*M_PI>param1) ) ) {
994 // arc of circle containing the circle origin
995 // case param1<param2
996 inside = (param1<U2 && U2<2*M_PI) || (0<=U2 && U2<param2-2*M_PI);
997 // case param2<param1
998 inside = inside || (param2<U2 && U2<2*M_PI) || (0<=U2 && U2<param1-2*M_PI);
1001 status = ChFi2d_ComputationError;
1005 //// modified by jgv, 08.08.2011 for bug 0022695 ////
1006 //inside = (Vv2<param3 && Vv2>param4) || (Vv2<param4 && Vv2>param3);
1007 inside = (Vv2 < param3 && Vv2 >= param4) || (Vv2 <= param4 && Vv2 > param3);
1008 /////////////////////////////////////////////////////
1009 if ( (basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle))
1010 && ( (2*M_PI<param3 && 2*M_PI>param4) || (2*M_PI<param4 && 2*M_PI>param3) ) ) {
1011 // arc of circle containing the circle origin
1012 // cas param3<param4
1013 inside = (param3<Vv2 && Vv2<2*M_PI) || (0<=Vv2 && Vv2<param4-2*M_PI);
1014 // cas param4<param3
1015 inside = inside || (param4<Vv2 && Vv2<2*M_PI) || (0<=Vv2 && Vv2<param3-2*M_PI);
1018 status = ChFi2d_ComputationError;
1022 gp_Pnt p1 = Adaptor3dSurface.Value(Ptg1.X(), Ptg1.Y());
1023 gp_Pnt p2 = Adaptor3dSurface.Value(Ptg2.X(), Ptg2.Y());
1024 B.MakeVertex(Vertex1, p1,Tol);
1026 if (Abs(U2-ufirst1) <= Precision::PConfusion()) {
1029 if (Abs(U2-ulast1) <= Precision::PConfusion()) {
1033 B.MakeVertex(Vertex2, p2,Tol);
1035 if (Abs(Vv2-ufirst2) <= Precision::PConfusion()) {
1038 if (Abs(Vv2-ulast2) <= Precision::PConfusion()) {
1042 //=======================================================================
1043 // Update tops of the fillet. +
1044 //=======================================================================
1047 Pntbid = BRep_Tool::Pnt(V);
1048 sommet = gp_Pnt2d(Pntbid.X(),Pntbid.Y());
1053 pntBid = BRep_Tool::Pnt(V2);
1054 somBid = gp_Pnt2d(pntBid.X(),pntBid.Y());
1057 pntBid = BRep_Tool::Pnt(V1);
1058 somBid = gp_Pnt2d(pntBid.X(),pntBid.Y());
1062 ElCLib::D1(U1,cir,Ptg1,vec);
1065 if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
1066 Handle(Geom2d_Circle) CC1 = Handle(Geom2d_Circle)::DownCast(basisC1);
1067 gp_Circ2d cir2d(CC1->Circ2d());
1068 Standard_Real par = ElCLib::Parameter(cir2d,Ptg1);
1070 ElCLib::D1(par,cir2d,Pd,vec1);
1071 } // if (C1->DynamicType() ...
1072 else if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Line)) {
1073 Handle(Geom2d_Line) CC1 = Handle(Geom2d_Line)::DownCast(basisC1);
1074 gp_Lin2d lin2d(CC1->Lin2d());
1075 Standard_Real par = ElCLib::Parameter(lin2d,sommet);
1076 vec1 = gp_Vec2d(sommet.X()-somBid.X(),sommet.Y()-somBid.Y());
1078 ElCLib::D1(par,lin2d,Pd,vec1);
1081 if (OE1 == TopAbs_REVERSED) {
1084 Standard_Real cross = vec1*vec;
1085 Standard_Boolean Sense = cross > 0.;
1086 if (U1 > Vv1 && U1 > 2.*M_PI) {
1087 ElCLib::AdjustPeriodic(0.,2.*M_PI,Precision::Confusion(),U1,Vv1);
1089 if ( (O1 == TopAbs_FORWARD && OE1 == TopAbs_FORWARD) ||
1090 (O1 == TopAbs_REVERSED && OE1 == TopAbs_REVERSED) ) {
1091 filletEdge = BRepLib_MakeEdge(circle, refSurf,
1092 NewExtr1, NewExtr2, U1, Vv1);
1095 filletEdge = BRepLib_MakeEdge(circle, refSurf,
1096 NewExtr2, NewExtr1, Vv1, U1);
1099 TopAbs_Orientation S1 = filletEdge.Orientation();
1100 if ((O1 == TopAbs_FORWARD && OE1 == TopAbs_FORWARD) ||
1101 (O1 == TopAbs_REVERSED && OE1 == TopAbs_REVERSED) ) {
1102 filletEdge = BRepLib_MakeEdge(circle, refSurf,
1103 NewExtr2, NewExtr1, Vv1, U1);
1106 filletEdge = BRepLib_MakeEdge(circle, refSurf,
1107 NewExtr1, NewExtr2, U1, Vv1);
1109 if (S1 == TopAbs_FORWARD) {
1110 filletEdge.Orientation(TopAbs_REVERSED);
1113 filletEdge.Orientation(TopAbs_FORWARD);
1119 BRepLib::BuildCurves3d(filletEdge);
1121 } // BuildFilletEdge
1124 //=======================================================================
1125 //function : IsAFillet
1127 //=======================================================================
1129 Standard_Boolean ChFi2d_Builder::IsAFillet(const TopoDS_Edge& E) const
1131 Standard_Integer i = 1;
1132 while (i <= fillets.Length()) {
1133 const TopoDS_Edge& currentEdge = TopoDS::Edge(fillets.Value(i));
1134 if (currentEdge.IsSame(E)) return Standard_True;
1137 return Standard_False;
1141 //=======================================================================
1142 //function : IsAChamfer
1144 //=======================================================================
1146 Standard_Boolean ChFi2d_Builder::IsAChamfer(const TopoDS_Edge& E) const
1148 Standard_Integer i = 1;
1149 while (i <= chamfers.Length()) {
1150 const TopoDS_Edge& currentEdge = TopoDS::Edge(chamfers.Value(i));
1151 if (currentEdge.IsSame(E)) return Standard_True;
1154 return Standard_False;
1159 //=======================================================================
1160 //function : IsLineOrCircle
1162 //=======================================================================
1164 Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E,
1165 const TopoDS_Face& F)
1167 Standard_Real first, last;
1168 TopLoc_Location loc;
1169 // syntaxe invalide sur NT
1170 // const Handle(Geom2d_Curve)& C =
1171 // BRep_Tool::CurveOnSurface(E,F,first,last);
1172 Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,first,last);
1173 Handle(Geom2d_Curve) basisC;
1174 Handle(Geom2d_TrimmedCurve) TC = Handle(Geom2d_TrimmedCurve)::DownCast(C);
1176 basisC = Handle(Geom2d_Curve)::DownCast(TC->BasisCurve());
1178 basisC = Handle(Geom2d_Curve)::DownCast(C);
1180 if ( basisC->DynamicType() == STANDARD_TYPE(Geom2d_Circle)
1181 || basisC->DynamicType() == STANDARD_TYPE(Geom2d_Line) ) {
1182 return Standard_True;
1185 return Standard_False;