0023987: 2D fillets
[occt.git] / src / ChFi2d / ChFi2d_FilletAPI.cxx
1 #include <ChFi2d_FilletAPI.hxx>
2 #include <BRepAdaptor_Curve.hxx>
3 #include <TopoDS_Iterator.hxx>
4 #include <TopoDS.hxx>
5
6 // An empty constructor of the fillet algorithm.
7 // Call a method Init() to initialize the algorithm
8 // before calling of a Perform() method.
9 ChFi2d_FilletAPI::ChFi2d_FilletAPI():myIsAnalytical(Standard_False)
10 {
11
12 }
13
14 // A constructor of a fillet algorithm: accepts a wire consisting of two edges in a plane.
15 ChFi2d_FilletAPI::ChFi2d_FilletAPI(const TopoDS_Wire& theWire, 
16                                    const gp_Pln& thePlane):myIsAnalytical(Standard_False)
17 {
18   Init(theWire, thePlane);
19 }
20
21 // A constructor of a fillet algorithm: accepts two edges in a plane.
22 ChFi2d_FilletAPI::ChFi2d_FilletAPI(const TopoDS_Edge& theEdge1, 
23                                    const TopoDS_Edge& theEdge2, 
24                                    const gp_Pln& thePlane):myIsAnalytical(Standard_False)
25 {
26   Init(theEdge1, theEdge2, thePlane);
27 }
28
29 // Initializes a fillet algorithm: accepts a wire consisting of two edges in a plane.
30 void ChFi2d_FilletAPI::Init(const TopoDS_Wire& theWire, 
31                             const gp_Pln& thePlane)
32 {
33   // Decide whether we may apply an analytical solution.
34   TopoDS_Edge E1, E2;
35   TopoDS_Iterator itr(theWire);
36   for (; itr.More(); itr.Next())
37   {
38     if (E1.IsNull())
39       E1 = TopoDS::Edge(itr.Value());
40     else if (E2.IsNull())
41       E2 = TopoDS::Edge(itr.Value());
42     else
43       break;
44   }
45   if (!E1.IsNull() && !E2.IsNull())
46     myIsAnalytical = IsAnalytical(E1, E2);
47
48   // Initialize the algorithm.
49   myIsAnalytical ? myAnaFilletAlgo.Init(theWire, thePlane) :
50                    myFilletAlgo.Init(theWire, thePlane);
51 }
52
53 // Initializes a fillet algorithm: accepts two edges in a plane.
54 void ChFi2d_FilletAPI::Init(const TopoDS_Edge& theEdge1, 
55                             const TopoDS_Edge& theEdge2, 
56                             const gp_Pln& thePlane)
57 {
58   // Decide whether we may apply an analytical solution.
59   myIsAnalytical = IsAnalytical(theEdge1, theEdge2);
60
61   // Initialize the algorithm.
62   myIsAnalytical ? myAnaFilletAlgo.Init(theEdge1, theEdge2, thePlane) :
63                    myFilletAlgo.Init(theEdge1, theEdge2, thePlane);
64 }
65
66 // Returns true, if at least one result was found.
67 Standard_Boolean ChFi2d_FilletAPI::Perform(const Standard_Real theRadius)
68 {
69   return myIsAnalytical ? myAnaFilletAlgo.Perform(theRadius) : 
70                           myFilletAlgo.Perform(theRadius);
71 }
72
73 // Returns number of possible solutions.
74 Standard_Integer ChFi2d_FilletAPI::NbResults(const gp_Pnt& thePoint)
75 {
76   return myIsAnalytical ? 1 : myFilletAlgo.NbResults(thePoint);
77 }
78
79 // Returns result (fillet edge, modified edge1, modified edge2), 
80 // nearest to the given point <thePoint> if iSolution == -1
81 TopoDS_Edge ChFi2d_FilletAPI::Result(const gp_Pnt& thePoint, 
82                                      TopoDS_Edge& theEdge1, TopoDS_Edge& theEdge2, 
83                                      const Standard_Integer iSolution)
84 {
85   return myIsAnalytical ? myAnaFilletAlgo.Result(theEdge1, theEdge2) :
86                           myFilletAlgo.Result(thePoint, theEdge1, theEdge2, iSolution);
87 }
88
89 // Decides whether the input parameters may use an analytical algorithm
90 // for calculation of the fillets, or an iteration-recursive method is needed.
91 // The analytical solution is applicable for linear and circular edges having a common point.
92 Standard_Boolean ChFi2d_FilletAPI::IsAnalytical(const TopoDS_Edge& theEdge1, 
93                                                 const TopoDS_Edge& theEdge2)
94 {
95   Standard_Boolean ret(Standard_False);
96   BRepAdaptor_Curve AC1(theEdge1), AC2(theEdge2);
97   if ((AC1.GetType() == GeomAbs_Line || AC1.GetType() == GeomAbs_Circle) &&
98       (AC2.GetType() == GeomAbs_Line || AC2.GetType() == GeomAbs_Circle))
99   {
100     // The edges are lines or arcs of circle.
101     // Now check wether they have a common point.
102     gp_Pnt p11 = AC1.Value(AC1.FirstParameter());
103     gp_Pnt p12 = AC1.Value(AC1.LastParameter());
104     gp_Pnt p21 = AC2.Value(AC2.FirstParameter());
105     gp_Pnt p22 = AC2.Value(AC2.LastParameter());
106     if (p11.SquareDistance(p21) < Precision::SquareConfusion() ||
107         p11.SquareDistance(p22) < Precision::SquareConfusion() ||
108         p12.SquareDistance(p21) < Precision::SquareConfusion() ||
109         p12.SquareDistance(p22) < Precision::SquareConfusion())
110     {
111       ret = Standard_True;
112     }
113   }
114   return ret;
115 }