0024023: Revamp the OCCT Handle -- general
[occt.git] / src / ChFi2d / ChFi2d_FilletAPI.cxx
1 // Created on: 2013-06-06
2 // Created by: Vlad ROMASHKO
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <ChFi2d_FilletAPI.hxx>
17 #include <BRepAdaptor_Curve.hxx>
18 #include <TopoDS_Iterator.hxx>
19 #include <TopoDS.hxx>
20
21 // An empty constructor of the fillet algorithm.
22 // Call a method Init() to initialize the algorithm
23 // before calling of a Perform() method.
24 ChFi2d_FilletAPI::ChFi2d_FilletAPI():myIsAnalytical(Standard_False)
25 {
26
27 }
28
29 // A constructor of a fillet algorithm: accepts a wire consisting of two edges in a plane.
30 ChFi2d_FilletAPI::ChFi2d_FilletAPI(const TopoDS_Wire& theWire, 
31                                    const gp_Pln& thePlane):myIsAnalytical(Standard_False)
32 {
33   Init(theWire, thePlane);
34 }
35
36 // A constructor of a fillet algorithm: accepts two edges in a plane.
37 ChFi2d_FilletAPI::ChFi2d_FilletAPI(const TopoDS_Edge& theEdge1, 
38                                    const TopoDS_Edge& theEdge2, 
39                                    const gp_Pln& thePlane):myIsAnalytical(Standard_False)
40 {
41   Init(theEdge1, theEdge2, thePlane);
42 }
43
44 // Initializes a fillet algorithm: accepts a wire consisting of two edges in a plane.
45 void ChFi2d_FilletAPI::Init(const TopoDS_Wire& theWire, 
46                             const gp_Pln& thePlane)
47 {
48   // Decide whether we may apply an analytical solution.
49   TopoDS_Edge E1, E2;
50   TopoDS_Iterator itr(theWire);
51   for (; itr.More(); itr.Next())
52   {
53     if (E1.IsNull())
54       E1 = TopoDS::Edge(itr.Value());
55     else if (E2.IsNull())
56       E2 = TopoDS::Edge(itr.Value());
57     else
58       break;
59   }
60   if (!E1.IsNull() && !E2.IsNull())
61     myIsAnalytical = IsAnalytical(E1, E2);
62
63   // Initialize the algorithm.
64   myIsAnalytical ? myAnaFilletAlgo.Init(theWire, thePlane) :
65                    myFilletAlgo.Init(theWire, thePlane);
66 }
67
68 // Initializes a fillet algorithm: accepts two edges in a plane.
69 void ChFi2d_FilletAPI::Init(const TopoDS_Edge& theEdge1, 
70                             const TopoDS_Edge& theEdge2, 
71                             const gp_Pln& thePlane)
72 {
73   // Decide whether we may apply an analytical solution.
74   myIsAnalytical = IsAnalytical(theEdge1, theEdge2);
75
76   // Initialize the algorithm.
77   myIsAnalytical ? myAnaFilletAlgo.Init(theEdge1, theEdge2, thePlane) :
78                    myFilletAlgo.Init(theEdge1, theEdge2, thePlane);
79 }
80
81 // Returns true, if at least one result was found.
82 Standard_Boolean ChFi2d_FilletAPI::Perform(const Standard_Real theRadius)
83 {
84   return myIsAnalytical ? myAnaFilletAlgo.Perform(theRadius) : 
85                           myFilletAlgo.Perform(theRadius);
86 }
87
88 // Returns number of possible solutions.
89 Standard_Integer ChFi2d_FilletAPI::NbResults(const gp_Pnt& thePoint)
90 {
91   return myIsAnalytical ? 1 : myFilletAlgo.NbResults(thePoint);
92 }
93
94 // Returns result (fillet edge, modified edge1, modified edge2), 
95 // nearest to the given point <thePoint> if iSolution == -1
96 TopoDS_Edge ChFi2d_FilletAPI::Result(const gp_Pnt& thePoint, 
97                                      TopoDS_Edge& theEdge1, TopoDS_Edge& theEdge2, 
98                                      const Standard_Integer iSolution)
99 {
100   return myIsAnalytical ? myAnaFilletAlgo.Result(theEdge1, theEdge2) :
101                           myFilletAlgo.Result(thePoint, theEdge1, theEdge2, iSolution);
102 }
103
104 // Decides whether the input parameters may use an analytical algorithm
105 // for calculation of the fillets, or an iteration-recursive method is needed.
106 // The analytical solution is applicable for linear and circular edges having a common point.
107 Standard_Boolean ChFi2d_FilletAPI::IsAnalytical(const TopoDS_Edge& theEdge1, 
108                                                 const TopoDS_Edge& theEdge2)
109 {
110   Standard_Boolean ret(Standard_False);
111   BRepAdaptor_Curve AC1(theEdge1), AC2(theEdge2);
112   if ((AC1.GetType() == GeomAbs_Line || AC1.GetType() == GeomAbs_Circle) &&
113       (AC2.GetType() == GeomAbs_Line || AC2.GetType() == GeomAbs_Circle))
114   {
115     // The edges are lines or arcs of circle.
116     // Now check wether they have a common point.
117     gp_Pnt p11 = AC1.Value(AC1.FirstParameter());
118     gp_Pnt p12 = AC1.Value(AC1.LastParameter());
119     gp_Pnt p21 = AC2.Value(AC2.FirstParameter());
120     gp_Pnt p22 = AC2.Value(AC2.LastParameter());
121     if (p11.SquareDistance(p21) < Precision::SquareConfusion() ||
122         p11.SquareDistance(p22) < Precision::SquareConfusion() ||
123         p12.SquareDistance(p21) < Precision::SquareConfusion() ||
124         p12.SquareDistance(p22) < Precision::SquareConfusion())
125     {
126       ret = Standard_True;
127     }
128   }
129   return ret;
130 }