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.
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>
25 #include <ChFi2d_Builder.hxx>
27 #include <GccEnt_Position.hxx>
28 #include <Geom2d_Circle.hxx>
29 #include <Geom2d_Curve.hxx>
30 #include <Geom2d_Line.hxx>
31 #include <Geom2d_TrimmedCurve.hxx>
32 #include <Geom2dGcc_Circ2d2TanRad.hxx>
33 #include <Geom2dGcc_QualifiedCurve.hxx>
34 #include <Geom2dInt_GInter.hxx>
35 #include <Geom_Circle.hxx>
36 #include <Geom_Curve.hxx>
37 #include <Geom_Line.hxx>
38 #include <Geom_Plane.hxx>
39 #include <Geom_Surface.hxx>
40 #include <gp_Circ2d.hxx>
43 #include <gp_Pnt2d.hxx>
44 #include <gp_Vec2d.hxx>
45 #include <IntRes2d_IntersectionPoint.hxx>
46 #include <Precision.hxx>
47 #include <TopAbs_Orientation.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <TopLoc_Location.hxx>
52 #include <TopoDS_Edge.hxx>
53 #include <TopoDS_Face.hxx>
54 #include <TopoDS_Vertex.hxx>
55 #include <TopoDS_Wire.hxx>
56 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
57 #include <TopTools_IndexedMapOfShape.hxx>
58 #include <TopTools_ListIteratorOfListOfShape.hxx>
60 static Standard_Boolean IsIssuedFrom(const TopoDS_Edge& E,
61 const TopTools_IndexedMapOfShape& Map,
62 TopoDS_Edge& BasisEdge);
64 static Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E,
65 const TopoDS_Face& F);
68 //=======================================================================
69 //function : ChFi2d_Builder
71 //=======================================================================
73 ChFi2d_Builder::ChFi2d_Builder() : status (ChFi2d_NotPlanar)
77 //=======================================================================
78 //function : ChFi2d_Builder
80 //=======================================================================
82 ChFi2d_Builder::ChFi2d_Builder(const TopoDS_Face& F)
85 status = ChFi2d_NoFace;
89 // syntaxe invalide sur NT
90 // const Handle(Geom_Surface)& surf = BRep_Tool::Surface( F, Loc);
91 // if (surf->IsKind(STANDARD_TYPE(Geom_Plane))) {
92 if ( BRep_Tool::Surface( F, Loc)
93 -> IsKind(STANDARD_TYPE(Geom_Plane)) ) {
94 newFace = refFace = F;
95 newFace.Orientation(TopAbs_FORWARD);
96 BRepLib::BuildCurves3d(newFace);
97 status = ChFi2d_Ready;
99 else status = ChFi2d_NotPlanar;
102 //=======================================================================
105 //=======================================================================
107 void ChFi2d_Builder::Init(const TopoDS_Face& F)
110 status = ChFi2d_NoFace;
117 // syntaxe invalide sur NT
118 // const Handle(Geom_Surface)& surf = BRep_Tool::Surface( F, Loc);
119 // if (surf->IsKind(STANDARD_TYPE(Geom_Plane))) {
120 if ( BRep_Tool::Surface( F, Loc)
121 -> IsKind(STANDARD_TYPE(Geom_Plane)) ) {
122 newFace = refFace = F;
123 newFace.Orientation(TopAbs_FORWARD);
124 status = ChFi2d_Ready;
126 else status = ChFi2d_NotPlanar;
130 //=======================================================================
133 //=======================================================================
135 void ChFi2d_Builder::Init(const TopoDS_Face& RefFace,
136 const TopoDS_Face& ModFace)
138 if (RefFace.IsNull() || ModFace.IsNull()) {
139 status = ChFi2d_NoFace;
146 // syntaxe invalide sur NT
147 // const Handle(Geom_Surface)& surf = BRep_Tool::Surface( RefFace, Loc);
148 // if (!surf->IsKind(STANDARD_TYPE(Geom_Plane))) {
149 if ( ! BRep_Tool::Surface( RefFace, loc)
150 -> IsKind(STANDARD_TYPE(Geom_Plane)) ) {
151 status = ChFi2d_NotPlanar;
157 newFace.Orientation(TopAbs_FORWARD);
158 status = ChFi2d_Ready;
160 // Research in newFace all the edges which not appear in RefFace
161 // The sequence newEdges will contains this edges.
163 TopTools_SequenceOfShape newEdges;
164 TopTools_IndexedMapOfShape refEdgesMap;
165 TopExp::MapShapes(refFace, TopAbs_EDGE, refEdgesMap);
166 TopExp_Explorer ex(newFace, TopAbs_EDGE);
168 const TopoDS_Edge& currentEdge = TopoDS::Edge(ex.Current());
169 if (!refEdgesMap.Contains(currentEdge))
170 newEdges.Append(currentEdge);
174 // update of history, fillets and chamfers fields
175 Standard_Integer i = 1;
176 Standard_Real first, last;
177 TopoDS_Edge basisEdge;
178 while ( i <= newEdges.Length()) {
179 const TopoDS_Edge& currentEdge = TopoDS::Edge(newEdges.Value(i));
180 if (IsIssuedFrom(currentEdge, refEdgesMap, basisEdge))
181 history.Bind(basisEdge, currentEdge);
183 // this edge is a chamfer or a fillet
184 // syntaxe invalide sur NT
185 // const Handle(Geom_Curve)& curve =
186 // BRep_Tool::Curve(currentEdge, loc, first, last);
187 Handle(Geom_Curve) curve =
188 BRep_Tool::Curve(currentEdge, loc, first, last);
189 if (curve->IsKind(STANDARD_TYPE(Geom_Circle))) {
190 fillets.Append(currentEdge);
192 else if (curve->IsKind(STANDARD_TYPE(Geom_Line))) {
193 chamfers.Append(currentEdge);
196 status = ChFi2d_InitialisationError;
199 } // this edge is ...
205 //=======================================================================
206 //function : IsIssuedFrom
207 //purpose : Search in <Map> if <E> has a parent edge. If a parent has
208 // been find, this edge is returned in <BasisEdge>, else <E> is
209 // returned in <BasisEdge>.
210 //=======================================================================
211 Standard_Boolean IsIssuedFrom(const TopoDS_Edge& E,
212 const TopTools_IndexedMapOfShape& Map,
213 TopoDS_Edge& BasisEdge)
215 TopLoc_Location loc1, loc2;
216 Standard_Real f1, L1, f2, L2;
217 // syntaxe invalide sur NT
218 // const Handle(Geom_Curve)& c1 =
219 // BRep_Tool::Curve(E, loc1, f1, L1);
220 Handle(Geom_Curve) c1 = BRep_Tool::Curve(E, loc1, f1, L1);
222 for (Standard_Integer i = 1; i <= Map.Extent(); i++ ) {
223 const TopoDS_Edge& currentEdge = TopoDS::Edge(Map.FindKey(i));
224 // syntaxe invalide sur NT
225 // const Handle(Geom_Curve)& c2 =
226 // BRep_Tool::Curve(currentEdge, loc2, f2, L2);
227 Handle(Geom_Curve) c2 = BRep_Tool::Curve(currentEdge, loc2, f2, L2);
229 (((f1 > f2 && f1 < L2) || (L1 > f2 && L1 < L2) ) ||
230 ( (f1 > L2 && f1 < f2) || (L1 > L2 && L1 < f2) )) ) {
231 BasisEdge = currentEdge;
232 BasisEdge.Orientation(E.Orientation());
233 return Standard_True;
235 } // for (Standard_Integer i ...
237 return Standard_False;
241 //=======================================================================
242 //function : AddFillet
244 //=======================================================================
245 TopoDS_Edge ChFi2d_Builder::AddFillet(const TopoDS_Vertex& V,
246 const Standard_Real Radius)
248 TopoDS_Edge adjEdge1, adjEdge2, basisEdge1, basisEdge2;
249 TopoDS_Edge adjEdge1Mod, adjEdge2Mod, fillet;
250 status = ChFi2d::FindConnectedEdges(newFace, V, adjEdge1, adjEdge2);
251 if (status == ChFi2d_ConnexionError) return fillet;
253 if (IsAFillet(adjEdge1) || IsAChamfer(adjEdge1) ||
254 IsAFillet(adjEdge2) || IsAChamfer(adjEdge2)) {
255 status = ChFi2d_NotAuthorized;
257 } // if (IsAFillet ...
259 if (!IsLineOrCircle(adjEdge1,newFace)
260 || !IsLineOrCircle(adjEdge2,newFace) ) {
261 status = ChFi2d_NotAuthorized;
263 } // if (!IsLineOrCircle ...
265 ComputeFillet(V, adjEdge1, adjEdge2, Radius,
266 adjEdge1Mod, adjEdge2Mod, fillet);
267 if (status == ChFi2d_IsDone
268 || status == ChFi2d_FirstEdgeDegenerated
269 || status == ChFi2d_LastEdgeDegenerated
270 || status == ChFi2d_BothEdgesDegenerated) {
271 BuildNewWire(adjEdge1, adjEdge2, adjEdge1Mod, fillet, adjEdge2Mod);
272 basisEdge1 = BasisEdge(adjEdge1);
273 basisEdge2 = BasisEdge(adjEdge2);
274 UpDateHistory(basisEdge1, basisEdge2,
275 adjEdge1Mod, adjEdge2Mod, fillet, 1);
276 status = ChFi2d_IsDone;
277 return TopoDS::Edge(fillets.Value(fillets.Length()));
282 //=======================================================================
283 //function : ModifyFillet
285 //=======================================================================
287 TopoDS_Edge ChFi2d_Builder::ModifyFillet(const TopoDS_Edge& Fillet,
288 const Standard_Real Radius)
290 TopoDS_Vertex aVertex = RemoveFillet(Fillet);
291 TopoDS_Edge aFillet = AddFillet(aVertex, Radius);
295 //=======================================================================
296 //function : RemoveFillet
298 //=======================================================================
300 TopoDS_Vertex ChFi2d_Builder::RemoveFillet(const TopoDS_Edge& Fillet)
302 TopoDS_Vertex commonVertex;
303 Standard_Integer i = 1;
304 Standard_Integer IsFind = Standard_False;
305 while (i <= fillets.Length()) {
306 const TopoDS_Edge& aFillet = TopoDS::Edge(fillets.Value(i));
307 if (aFillet.IsSame(Fillet)) {
309 IsFind = Standard_True;
314 if (!IsFind) return commonVertex;
317 TopoDS_Vertex firstVertex, lastVertex;
318 TopExp::Vertices(Fillet, firstVertex, lastVertex);
321 TopoDS_Edge adjEdge1, adjEdge2;
322 status = ChFi2d::FindConnectedEdges(newFace, firstVertex,
324 if (status == ChFi2d_ConnexionError) return commonVertex;
326 TopoDS_Edge basisEdge1, basisEdge2, E1, E2;
327 // E1 and E2 are the adjacent edges to Fillet
329 if (adjEdge1.IsSame(Fillet)) E1 = adjEdge2;
331 basisEdge1 = BasisEdge(E1);
332 status = ChFi2d::FindConnectedEdges(newFace, lastVertex,adjEdge1, adjEdge2);
333 if (status == ChFi2d_ConnexionError) return commonVertex;
334 if (adjEdge1.IsSame(Fillet)) E2 = adjEdge2;
336 basisEdge2 = BasisEdge(E2);
337 TopoDS_Vertex connectionE1Fillet, connectionE2Fillet;
338 Standard_Boolean hasConnection =
339 ChFi2d::CommonVertex(basisEdge1, basisEdge2, commonVertex);
340 if (!hasConnection) {
341 status = ChFi2d_ConnexionError;
344 hasConnection = ChFi2d::CommonVertex(E1, Fillet, connectionE1Fillet);
345 if (!hasConnection) {
346 status = ChFi2d_ConnexionError;
349 hasConnection = ChFi2d::CommonVertex(E2, Fillet, connectionE2Fillet);
350 if (!hasConnection) {
351 status = ChFi2d_ConnexionError;
355 // rebuild edges on wire
356 TopoDS_Edge newEdge1, newEdge2;
357 TopoDS_Vertex v, v1, v2;
358 BRepLib_MakeEdge makeEdge;
360 Standard_Real first, last;
362 TopExp::Vertices(E1, firstVertex, lastVertex);
363 TopExp::Vertices(basisEdge1, v1, v2);
364 if (v1.IsSame(commonVertex)) v = v2;
367 if ( firstVertex.IsSame(v) || lastVertex.IsSame(v))
368 // It means the edge support only one fillet. In this case
369 // the new edge must be the basis edge.
370 newEdge1 = basisEdge1;
372 // It means the edge support one fillet on each end.
373 if (firstVertex.IsSame(connectionE1Fillet)) {
374 // syntaxe invalide sur NT
375 // const Handle(Geom_Curve)& curve =
376 // BRep_Tool::Curve(E1, loc, first, last);
377 Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, loc, first, last);
378 makeEdge.Init(curve, commonVertex, lastVertex);
379 newEdge1 = makeEdge.Edge();
380 newEdge1.Orientation(E1.Orientation());
381 newEdge1.Location(E1.Location());
382 } // if (firstVertex ...
383 else if (lastVertex.IsSame(connectionE1Fillet)) {
384 // syntax wrong on NT
385 // const Handle(Geom_Curve)& curve =
386 // BRep_Tool::Curve(E1, loc, first, last);
387 Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, loc, first, last);
388 makeEdge.Init(curve, firstVertex, commonVertex);
389 newEdge1 = makeEdge.Edge();
390 newEdge1.Orientation(E1.Orientation());
391 newEdge1.Location(E1.Location());
392 } // else if (lastVertex ...
395 TopExp::Vertices(basisEdge2, v1, v2);
396 if (v1.IsSame(commonVertex)) v = v2;
399 TopExp::Vertices(E2, firstVertex, lastVertex);
400 if ( firstVertex.IsSame(v) || lastVertex.IsSame(v))
401 // It means the edge support only one fillet. In this case
402 // the new edge must be the basis edge.
403 newEdge2 = basisEdge2;
405 // It means the edge support one fillet on each end.
406 if (firstVertex.IsSame(connectionE2Fillet)) {
407 // syntax wrong on NT
408 // const Handle(Geom_Curve)& curve =
409 // BRep_Tool::Curve(E2, loc, first, last);
410 Handle(Geom_Curve) curve = BRep_Tool::Curve(E2, loc, first, last);
411 makeEdge.Init(curve, commonVertex, lastVertex);
412 newEdge2 = makeEdge.Edge();
413 newEdge2.Orientation(E2.Orientation());
414 newEdge2.Location(E2.Location());
415 } // if (firstVertex ...
416 else if (lastVertex.IsSame(connectionE2Fillet)) {
417 // syntax wrong on NT
418 // const Handle(Geom_Curve)& curve =
419 // BRep_Tool::Curve(E2, loc, first, last);
420 Handle(Geom_Curve) curve = BRep_Tool::Curve(E2, loc, first, last);
421 makeEdge.Init(curve, firstVertex, commonVertex);
422 newEdge2 = makeEdge.Edge();
423 newEdge2.Orientation(E2.Orientation());
424 newEdge2.Location(E2.Location());
425 } // else if (lastVertex ...
428 // rebuild the newFace
429 TopExp_Explorer Ex(newFace, TopAbs_EDGE);
436 const TopoDS_Edge& theEdge = TopoDS::Edge(Ex.Current());
437 if (!theEdge.IsSame(E1) &&
438 !theEdge.IsSame(E2) &&
439 !theEdge.IsSame(Fillet))
440 B.Add(newWire, theEdge);
443 B.Add(newWire, newEdge1);
444 else if (theEdge == E2)
445 B.Add(newWire, newEdge2);
449 BRepAdaptor_Surface Adaptor3dSurface(refFace);
450 BRepLib_MakeFace mFace(Adaptor3dSurface.Plane(), newWire);
454 UpDateHistory(basisEdge1, basisEdge2, newEdge1, newEdge2);
460 //=======================================================================
461 //function : ComputeFillet
463 //=======================================================================
465 void ChFi2d_Builder::ComputeFillet(const TopoDS_Vertex& V,
466 const TopoDS_Edge& E1,
467 const TopoDS_Edge& E2,
468 const Standard_Real Radius,
473 TopoDS_Vertex newExtr1, newExtr2;
474 Standard_Boolean Degen1, Degen2;
475 Fillet = BuildFilletEdge(V, E1, E2, Radius, newExtr1, newExtr2);
476 if ( status != ChFi2d_IsDone) return;
477 TrimE1 = BuildNewEdge(E1, V, newExtr1, Degen1);
478 TrimE2 = BuildNewEdge(E2, V, newExtr2, Degen2);
479 if (Degen1 && Degen2 ) status = ChFi2d_BothEdgesDegenerated;
480 if (Degen1 && !Degen2 ) status = ChFi2d_FirstEdgeDegenerated;
481 if (!Degen1 && Degen2 ) status = ChFi2d_LastEdgeDegenerated;
486 //=======================================================================
487 //function : BuildNewWire
489 //=======================================================================
491 void ChFi2d_Builder::BuildNewWire (const TopoDS_Edge& OldE1,
492 const TopoDS_Edge& OldE2,
493 const TopoDS_Edge& E1,
494 const TopoDS_Edge& Fillet,
495 const TopoDS_Edge& E2)
498 Standard_Boolean aClosedStatus = Standard_True;
500 TopExp_Explorer Ex(refFace, TopAbs_WIRE);
502 const TopoDS_Wire& aWire = TopoDS::Wire(Ex.Current());
503 aClosedStatus = aWire.Closed();
508 Standard_Boolean filletIsAdded = Standard_False;
510 Ex.Init(newFace, TopAbs_EDGE);
516 const TopoDS_Edge& theEdge = TopoDS::Edge(Ex.Current());
517 if (!theEdge.IsSame(OldE1) && !theEdge.IsSame(OldE2)) {
518 B.Add(newWire, theEdge);
521 if (theEdge == OldE1) {
522 if (status != ChFi2d_FirstEdgeDegenerated
523 && status != ChFi2d_BothEdgesDegenerated) {
526 if ( !filletIsAdded) {
527 B.Add(newWire, Fillet);
528 filletIsAdded = Standard_True;
529 } // if ( !filletIsAdded ...
530 } // if (theEdge == ...
532 if (status != ChFi2d_LastEdgeDegenerated
533 && status != ChFi2d_BothEdgesDegenerated) {
536 if ( !filletIsAdded) {
537 B.Add(newWire, Fillet);
538 filletIsAdded = Standard_True;
539 }// if ( !filletIsAdded ...
545 newWire.Closed(aClosedStatus);
546 BRepAdaptor_Surface Adaptor3dSurface(refFace);
547 BRepLib_MakeFace mFace(Adaptor3dSurface.Plane(), newWire);
553 //=======================================================================
554 //function : BuildNewEdge
556 //=======================================================================
558 TopoDS_Edge ChFi2d_Builder::BuildNewEdge(const TopoDS_Edge& E1,
559 const TopoDS_Vertex& OldExtr,
560 const TopoDS_Vertex& NewExtr) const
562 BRepLib_MakeEdge makeEdge;
564 Standard_Real first, last;
565 TopoDS_Vertex firstVertex, lastVertex;
566 TopExp::Vertices(E1, firstVertex, lastVertex);
567 // syntaxe invalide sur NT
568 // const Handle(Geom_Curve)& curve =
569 // BRep_Tool::Curve(E1, first, last);
570 Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, first, last);
571 if (firstVertex.IsSame(OldExtr))
572 makeEdge.Init(curve, NewExtr, lastVertex);
574 makeEdge.Init(curve, firstVertex, NewExtr);
575 TopoDS_Edge anEdge = makeEdge;
576 anEdge.Orientation(E1.Orientation());
577 // anEdge.Location(E1.Location());
582 //=======================================================================
583 //function : BuildNewEdge
584 //purpose : special flag if the new edge is degenerated
585 //=======================================================================
587 TopoDS_Edge ChFi2d_Builder::BuildNewEdge(const TopoDS_Edge& E1,
588 const TopoDS_Vertex& OldExtr,
589 const TopoDS_Vertex& NewExtr,
590 Standard_Boolean& IsDegenerated) const
592 BRepLib_MakeEdge makeEdge;
594 Standard_Real first, last;
595 IsDegenerated = Standard_False;
596 TopoDS_Vertex firstVertex, lastVertex;
597 TopExp::Vertices(E1, firstVertex, lastVertex);
598 gp_Pnt Pnew = BRep_Tool::Pnt(NewExtr);
599 Standard_Boolean PonctualEdge = Standard_False;
600 Standard_Real Tol = Precision::Confusion();
601 // syntax wrong on NT
602 // const Handle(Geom_Curve)& curve =
603 // BRep_Tool::Curve(E1, first, last);
604 Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, first, last);
605 if (firstVertex.IsSame(OldExtr)) {
606 makeEdge.Init(curve, NewExtr, lastVertex);
607 gp_Pnt PV = BRep_Tool::Pnt(lastVertex);
608 PonctualEdge = (Pnew.Distance(PV)<Tol);
611 makeEdge.Init(curve, firstVertex, NewExtr);
612 gp_Pnt PV = BRep_Tool::Pnt(firstVertex);
613 PonctualEdge = (Pnew.Distance(PV)<Tol);
616 BRepLib_EdgeError error = makeEdge.Error();
617 if (error==BRepLib_LineThroughIdenticPoints || PonctualEdge) {
618 IsDegenerated = Standard_True;
623 anEdge.Orientation(E1.Orientation());
624 // anEdge.Location(E1.Location());
630 //=======================================================================
631 //function : UpDateHistory
633 //=======================================================================
634 void ChFi2d_Builder::UpDateHistory(const TopoDS_Edge& E1,
635 const TopoDS_Edge& E2,
636 const TopoDS_Edge& TrimE1,
637 const TopoDS_Edge& TrimE2,
638 const TopoDS_Edge& NewEdge,
639 const Standard_Integer Id)
641 if (Id == 1) // the new edge is a fillet
643 fillets.Append(NewEdge);
645 else // the new edge is a chamfer
647 chamfers.Append(NewEdge);
651 if (status != ChFi2d_FirstEdgeDegenerated
652 && status != ChFi2d_BothEdgesDegenerated)
654 if (!E1.IsSame(TrimE1))
656 history.Bind(E1, TrimE1);
660 if (status != ChFi2d_LastEdgeDegenerated
661 && status != ChFi2d_BothEdgesDegenerated)
663 if (!E2.IsSame(TrimE2))
665 history.Bind(E2, TrimE2);
671 //=======================================================================
672 //function : UpDateHistory
674 //=======================================================================
675 void ChFi2d_Builder::UpDateHistory(const TopoDS_Edge& E1,
676 const TopoDS_Edge& E2,
677 const TopoDS_Edge& TrimE1,
678 const TopoDS_Edge& TrimE2)
682 if (history.IsBound(E1)) history.UnBind(E1);
683 if (!E1.IsSame(TrimE1)) history.Bind(E1, TrimE1);
684 if (history.IsBound(E2)) history.UnBind(E2);
685 if (!E2.IsSame(TrimE2)) history.Bind(E2, TrimE2);
689 //=======================================================================
690 //function : BasisEdge
692 //=======================================================================
693 const TopoDS_Edge& ChFi2d_Builder::BasisEdge(const TopoDS_Edge& E) const
695 TopTools_DataMapIteratorOfDataMapOfShapeShape iterator(history);
697 while (iterator.More()) {
698 anEdge = TopoDS::Edge(iterator.Value());
699 if (anEdge.IsSame(E)) {
700 const TopoDS_Edge& anotherEdge = TopoDS::Edge(iterator.Key());
702 } // if (anEdge.IsSame ...
704 } // while (Iterator.More ...
709 //=======================================================================
710 //function : BuildFilletEdge
712 //=======================================================================
713 TopoDS_Edge ChFi2d_Builder::BuildFilletEdge(const TopoDS_Vertex& V,
714 const TopoDS_Edge& AdjEdge1,
715 const TopoDS_Edge& AdjEdge2,
716 const Standard_Real Radius,
717 TopoDS_Vertex& NewExtr1,
718 TopoDS_Vertex& NewExtr2)
723 TopoDS_Vertex V1 = TopExp::FirstVertex(E1);
724 TopoDS_Vertex V2 = TopExp::LastVertex(E1);
725 TopoDS_Vertex V3 = TopExp::FirstVertex(E2);
726 TopoDS_Vertex V4 = TopExp::LastVertex(E2);
728 //========================================================================
729 // The first arc is found. +
730 //========================================================================
732 TopAbs_Orientation O1;
733 TopAbs_Orientation OE1;
734 OE1 = E1.Orientation();
735 E1.Orientation(TopAbs_FORWARD);
736 E2.Orientation(TopAbs_FORWARD);
737 TopoDS_Shape aLocalShape = E1.EmptyCopied();
738 TopoDS_Edge Ebid1 = TopoDS::Edge(aLocalShape);
739 aLocalShape = E2.EmptyCopied();
740 TopoDS_Edge Ebid2 = TopoDS::Edge(aLocalShape);
741 // TopoDS_Edge Ebid1 = TopoDS::Edge(E1.EmptyCopied());
742 // TopoDS_Edge Ebid2 = TopoDS::Edge(E2.EmptyCopied());
743 Standard_Real param1,param2,param3,param4;
745 //========================================================================
746 // Save non-modified parts of edges concerned. +
747 //========================================================================
750 param1 = BRep_Tool::Parameter(V1,E1);
751 param2 = BRep_Tool::Parameter(V2,E1);
752 O1 = V2.Orientation();
755 param1 = BRep_Tool::Parameter(V2,E1);
756 param2 = BRep_Tool::Parameter(V1,E1);
757 O1 = V1.Orientation();
760 param3 = BRep_Tool::Parameter(V3,E2);
761 param4 = BRep_Tool::Parameter(V4,E2);
764 param3 = BRep_Tool::Parameter(V4,E2);
765 param4 = BRep_Tool::Parameter(V3,E2);
768 //========================================================================
769 // Restore geometric supports. +
770 //========================================================================
772 Handle(Geom2d_Curve) C1,C2;
773 Standard_Real ufirst1,ulast1,ufirst2,ulast2,U1,U2,PU1,PU2,Vv1,Vv2;
774 Standard_Real PPU1,PPU2;
775 C1 = BRep_Tool::CurveOnSurface(E1,newFace,ufirst1,ulast1);
776 C2 = BRep_Tool::CurveOnSurface(E2,newFace,ufirst2,ulast2);
778 //========================================================================
779 // Determination of the face for fillet. +
780 //========================================================================
785 Standard_Boolean Sens1 , Sens2;
787 Handle(Geom2d_Curve) basisC1,basisC2;
788 Handle(Geom2d_TrimmedCurve) T1 = Handle(Geom2d_TrimmedCurve)::DownCast(C1);
790 basisC1 = T1->BasisCurve();
793 Handle(Geom2d_TrimmedCurve) T2 = Handle(Geom2d_TrimmedCurve)::DownCast(C2);
795 basisC2 = T2->BasisCurve();
799 if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
800 Handle(Geom2d_Circle) CC1 = Handle(Geom2d_Circle)::DownCast(basisC1);
801 ElCLib::D1(param1,CC1->Circ2d(),p,Ve1);
802 Sens1 = (CC1->Circ2d()).IsDirect();
803 } // if (C1->DynamicType() ...
805 Handle(Geom2d_Line) CC1 = Handle(Geom2d_Line)::DownCast(basisC1);
806 ElCLib::D1(param1,CC1->Lin2d(),p,Ve1);
809 if (basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
810 Handle(Geom2d_Circle) CC2 = Handle(Geom2d_Circle)::DownCast(basisC2);
811 ElCLib::D1(param3,CC2->Circ2d(),p,Ve2);
812 Sens2 = (CC2->Circ2d()).IsDirect();
813 } // if if (C2->DynamicType() ...
815 Handle(Geom2d_Line) CC2 = Handle(Geom2d_Line)::DownCast(basisC2);
816 ElCLib::D1(param3,CC2->Lin2d(),p,Ve2);
820 TopoDS_Edge filletEdge;
822 Standard_Real cross = Ve1.Crossed(Ve2);
826 // processing of tangency or downcast point
827 if (Ve1.IsParallel(Ve2,Precision::Angular())) {
828 // Ve1 and Ve2 are parallel : cross at 0
837 if (! Ve4.IsOpposite(Ve3,Precision::Angular())) {
838 // There is a true tangency point and the calculation is stopped
839 status = ChFi2d_TangencyError;
842 // Otherwise this is a downcast point, and the calculation is continued
845 GccEnt_Position Qual1,Qual2;
847 if (param3 > param4 ) {
848 if(Sens1 == Standard_True){
849 Qual1 = GccEnt_enclosed;
852 Qual1 = GccEnt_outside;
856 if(Sens1 == Standard_True){
857 Qual1 = GccEnt_outside;
860 Qual1 = GccEnt_enclosed;
863 if (param1 > param2) {
864 if(Sens2 == Standard_True)
865 Qual2 = GccEnt_outside;
867 Qual2 = GccEnt_enclosed;
870 if(Sens2 == Standard_True)
871 Qual2 = GccEnt_enclosed;
873 Qual2 = GccEnt_outside;
875 } // if (cross < 0 ...
877 if (param3 > param4 ) {
878 if( Sens1 == Standard_True)
879 Qual1 = GccEnt_outside;
881 Qual1 = GccEnt_enclosed;
884 if( Sens1 == Standard_True)
885 Qual1 = GccEnt_enclosed;
887 Qual1 = GccEnt_outside;
889 if (param1 > param2 ) {
890 if( Sens2 == Standard_True)
891 Qual2 = GccEnt_enclosed;
893 Qual2 = GccEnt_outside;
896 if( Sens2 == Standard_True)
897 Qual2 = GccEnt_outside;
899 Qual2 = GccEnt_enclosed;
903 Standard_Real Tol = Precision::Confusion();
904 Geom2dGcc_Circ2d2TanRad Fillet(Geom2dGcc_QualifiedCurve(basisC1,Qual1),
905 Geom2dGcc_QualifiedCurve(basisC2,Qual2),
907 if (!Fillet.IsDone() || Fillet.NbSolutions()==0) {
908 status = ChFi2d_ComputationError;
911 else if (Fillet.NbSolutions() >= 1) {
912 status = ChFi2d_IsDone;
913 Standard_Integer numsol = 1;
914 Standard_Integer nsol = 1;
915 TopoDS_Vertex Vertex1,Vertex2;
918 Standard_Real dist1 = 1.e40;
919 Standard_Boolean inside = Standard_False;
920 while (nsol<=Fillet.NbSolutions()) {
921 Fillet.Tangency1(nsol,PU1,PU2,Ptg1);
922 dist = Ptg1.Distance(p);
923 if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Line)) {
924 inside = (PU2<param1 && PU2>param2) || (PU2<param2 && PU2>param1);
925 if ( inside && dist < dist1) {
928 } // if ((((inside && ...
929 } // if (C1->DynamicType( ...
931 Fillet.Tangency2(nsol,PPU1,PPU2,Ptg2);
932 dist = Ptg2.Distance(p);
933 inside = (PPU2<param3 && PPU2>param4) || (PPU2<param4 && PPU2>param3);
934 // case of arc of circle passing on the sewing
935 if ( ( basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle) ) &&
936 ( (2*M_PI<param3 && 2*M_PI>param4) || (2*M_PI<param4 && 2*M_PI>param3) ) ) {
938 inside = (param3<PPU2 && PPU2<2*M_PI)
939 || (0<=PPU2 && PPU2<param4-2*M_PI);
941 inside = inside || (param4<PPU2 && PPU2<2*M_PI)
942 || (0<=PPU2 && PPU2<param3-2*M_PI);
944 if ( inside && dist < dist1) {
947 } // if ((((param3 ...
951 gp_Circ2d cir(Fillet.ThisSolution(numsol));
952 Handle(Geom2d_Circle) circle = new Geom2d_Circle(cir);
955 BRepAdaptor_Surface Adaptor3dSurface(refFace);
956 Handle(Geom_Plane) refSurf = new Geom_Plane(Adaptor3dSurface.Plane());
957 Fillet.Tangency1(numsol,U1,U2,Ptg1);
958 Fillet.Tangency2(numsol,Vv1,Vv2,Ptg2);
960 // check the validity of parameters
961 //// modified by jgv, 08.08.2011 for bug 0022695 ////
962 //inside = (U2<param1 && U2>param2) || (U2<param2 && U2>param1);
963 inside = (U2 < param1 && U2 >= param2) || (U2 <= param2 && U2 > param1);
964 /////////////////////////////////////////////////////
965 if ( (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle))
966 && ( (2*M_PI<param1 && 2*M_PI>param2) || (2*M_PI<param2 && 2*M_PI>param1) ) ) {
967 // arc of circle containing the circle origin
968 // case param1<param2
969 inside = (param1<U2 && U2<2*M_PI) || (0<=U2 && U2<param2-2*M_PI);
970 // case param2<param1
971 inside = inside || (param2<U2 && U2<2*M_PI) || (0<=U2 && U2<param1-2*M_PI);
974 status = ChFi2d_ComputationError;
978 //// modified by jgv, 08.08.2011 for bug 0022695 ////
979 //inside = (Vv2<param3 && Vv2>param4) || (Vv2<param4 && Vv2>param3);
980 inside = (Vv2 < param3 && Vv2 >= param4) || (Vv2 <= param4 && Vv2 > param3);
981 /////////////////////////////////////////////////////
982 if ( (basisC2->DynamicType() == STANDARD_TYPE(Geom2d_Circle))
983 && ( (2*M_PI<param3 && 2*M_PI>param4) || (2*M_PI<param4 && 2*M_PI>param3) ) ) {
984 // arc of circle containing the circle origin
986 inside = (param3<Vv2 && Vv2<2*M_PI) || (0<=Vv2 && Vv2<param4-2*M_PI);
988 inside = inside || (param4<Vv2 && Vv2<2*M_PI) || (0<=Vv2 && Vv2<param3-2*M_PI);
991 status = ChFi2d_ComputationError;
995 gp_Pnt p1 = Adaptor3dSurface.Value(Ptg1.X(), Ptg1.Y());
996 gp_Pnt p2 = Adaptor3dSurface.Value(Ptg2.X(), Ptg2.Y());
997 B.MakeVertex(Vertex1, p1,Tol);
999 if (Abs(U2-ufirst1) <= Precision::PConfusion()) {
1002 if (Abs(U2-ulast1) <= Precision::PConfusion()) {
1006 B.MakeVertex(Vertex2, p2,Tol);
1008 if (Abs(Vv2-ufirst2) <= Precision::PConfusion()) {
1011 if (Abs(Vv2-ulast2) <= Precision::PConfusion()) {
1015 //=======================================================================
1016 // Update tops of the fillet. +
1017 //=======================================================================
1020 Pntbid = BRep_Tool::Pnt(V);
1021 sommet = gp_Pnt2d(Pntbid.X(),Pntbid.Y());
1026 pntBid = BRep_Tool::Pnt(V2);
1027 somBid = gp_Pnt2d(pntBid.X(),pntBid.Y());
1030 pntBid = BRep_Tool::Pnt(V1);
1031 somBid = gp_Pnt2d(pntBid.X(),pntBid.Y());
1035 ElCLib::D1(U1,cir,Ptg1,vec);
1038 if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Circle)) {
1039 Handle(Geom2d_Circle) CC1 = Handle(Geom2d_Circle)::DownCast(basisC1);
1040 gp_Circ2d cir2d(CC1->Circ2d());
1041 Standard_Real par = ElCLib::Parameter(cir2d,Ptg1);
1043 ElCLib::D1(par,cir2d,Pd,vec1);
1044 } // if (C1->DynamicType() ...
1045 else if (basisC1->DynamicType() == STANDARD_TYPE(Geom2d_Line)) {
1046 Handle(Geom2d_Line) CC1 = Handle(Geom2d_Line)::DownCast(basisC1);
1047 gp_Lin2d lin2d(CC1->Lin2d());
1048 Standard_Real par = ElCLib::Parameter(lin2d,sommet);
1049 vec1 = gp_Vec2d(sommet.X()-somBid.X(),sommet.Y()-somBid.Y());
1051 ElCLib::D1(par,lin2d,Pd,vec1);
1054 if (OE1 == TopAbs_REVERSED) {
1057 Standard_Boolean Sense = ( vec1*vec ) > 0.;
1058 if (U1 > Vv1 && U1 > 2.*M_PI) {
1059 ElCLib::AdjustPeriodic(0.,2.*M_PI,Precision::Confusion(),U1,Vv1);
1061 if ( (O1 == TopAbs_FORWARD && OE1 == TopAbs_FORWARD) ||
1062 (O1 == TopAbs_REVERSED && OE1 == TopAbs_REVERSED) ) {
1063 filletEdge = BRepLib_MakeEdge(circle, refSurf,
1064 NewExtr1, NewExtr2, U1, Vv1);
1067 filletEdge = BRepLib_MakeEdge(circle, refSurf,
1068 NewExtr2, NewExtr1, Vv1, U1);
1071 TopAbs_Orientation S1 = filletEdge.Orientation();
1072 if ((O1 == TopAbs_FORWARD && OE1 == TopAbs_FORWARD) ||
1073 (O1 == TopAbs_REVERSED && OE1 == TopAbs_REVERSED) ) {
1074 filletEdge = BRepLib_MakeEdge(circle, refSurf,
1075 NewExtr2, NewExtr1, Vv1, U1);
1078 filletEdge = BRepLib_MakeEdge(circle, refSurf,
1079 NewExtr1, NewExtr2, U1, Vv1);
1081 if (S1 == TopAbs_FORWARD) {
1082 filletEdge.Orientation(TopAbs_REVERSED);
1085 filletEdge.Orientation(TopAbs_FORWARD);
1091 BRepLib::BuildCurves3d(filletEdge);
1093 } // BuildFilletEdge
1096 //=======================================================================
1097 //function : IsAFillet
1099 //=======================================================================
1101 Standard_Boolean ChFi2d_Builder::IsAFillet(const TopoDS_Edge& E) const
1103 Standard_Integer i = 1;
1104 while (i <= fillets.Length()) {
1105 const TopoDS_Edge& currentEdge = TopoDS::Edge(fillets.Value(i));
1106 if (currentEdge.IsSame(E)) return Standard_True;
1109 return Standard_False;
1113 //=======================================================================
1114 //function : IsAChamfer
1116 //=======================================================================
1118 Standard_Boolean ChFi2d_Builder::IsAChamfer(const TopoDS_Edge& E) const
1120 Standard_Integer i = 1;
1121 while (i <= chamfers.Length()) {
1122 const TopoDS_Edge& currentEdge = TopoDS::Edge(chamfers.Value(i));
1123 if (currentEdge.IsSame(E)) return Standard_True;
1126 return Standard_False;
1131 //=======================================================================
1132 //function : IsLineOrCircle
1134 //=======================================================================
1136 Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E,
1137 const TopoDS_Face& F)
1139 Standard_Real first, last;
1140 TopLoc_Location loc;
1141 // syntaxe invalide sur NT
1142 // const Handle(Geom2d_Curve)& C =
1143 // BRep_Tool::CurveOnSurface(E,F,first,last);
1144 Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,first,last);
1145 Handle(Geom2d_Curve) basisC;
1146 Handle(Geom2d_TrimmedCurve) TC = Handle(Geom2d_TrimmedCurve)::DownCast(C);
1148 basisC = TC->BasisCurve();
1152 if ( basisC->DynamicType() == STANDARD_TYPE(Geom2d_Circle)
1153 || basisC->DynamicType() == STANDARD_TYPE(Geom2d_Line) ) {
1154 return Standard_True;
1157 return Standard_False;