15 * You should have received a copy of the GNU General Public License |
15 * You should have received a copy of the GNU General Public License |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 */ |
17 */ |
18 |
18 |
19 #pragma once |
19 #pragma once |
20 |
|
21 #include "../main.h" |
20 #include "../main.h" |
22 |
21 |
23 //! |
22 // |
24 //! \brief Provides an algorithm for finding solutions of rings between given radii. |
23 // Implements a ring finding algorithm. It is passed two radii and it tries to |
25 //! |
24 // find solutions of rings that would fill the given space. |
26 //! The RingFinder is a class which implements a ring finding algorithm. It is passed |
25 // |
27 //! two radii and it tries to find solutions of rings that would fill the given space. |
26 // Note: it is not fool-proof and does not always yield a solution. |
28 //! |
27 // |
29 //! \note It is not fool-proof and does not always yield a solution, never assume |
|
30 //! \note that one is a available as none is guaranteed. |
|
31 //! |
|
32 class RingFinder |
28 class RingFinder |
33 { |
29 { |
|
30 public: |
|
31 // A single component in a solution |
|
32 struct Component |
|
33 { |
|
34 int num; |
|
35 double scale; |
|
36 }; |
|
37 |
|
38 // A solution whose components fill the desired ring space. |
|
39 class Solution |
|
40 { |
34 public: |
41 public: |
35 //! A single component in a solution |
42 inline void addComponent (const Component& a); |
36 struct Component |
43 inline const QVector<Component>& getComponents() const; |
37 { |
44 bool isSuperiorTo (const Solution* other) const; |
38 int num; |
|
39 double scale; |
|
40 }; |
|
41 |
|
42 //! A solution whose components would fill the desired ring space. |
|
43 class Solution |
|
44 { |
|
45 public: |
|
46 //! \returns components of this solution |
|
47 inline const QVector<Component>& getComponents() const |
|
48 { |
|
49 return m_components; |
|
50 } |
|
51 |
|
52 //! Add a component to this solution |
|
53 inline void addComponent (const Component& a) |
|
54 { |
|
55 m_components.push_back (a); |
|
56 } |
|
57 |
|
58 //! \brief Compare solutions. |
|
59 //! |
|
60 //! Compares this solution with \c other and determines which |
|
61 //! one is superior. |
|
62 //! |
|
63 //! A solution is considered superior if solution has less |
|
64 //! components than the other one. If both solution have an |
|
65 //! equal amount components, the solution with a lesser maximum |
|
66 //! ring number is found superior, as such solutions should |
|
67 //! yield less new primitives and cleaner definitions. |
|
68 //! |
|
69 //! The solution which is found superior to every other solution |
|
70 //! will be the one returned by \c RingFinder::bestSolution(). |
|
71 //! |
|
72 //! \param other the solution to check against |
|
73 //! \returns whether this solution is considered superior |
|
74 //! \returns to \c other. |
|
75 //! |
|
76 bool isSuperiorTo (const Solution* other) const; |
|
77 |
|
78 private: |
|
79 QVector<Component> m_components; |
|
80 }; |
|
81 |
|
82 //! Constructs a ring finder. |
|
83 RingFinder() {} |
|
84 |
|
85 //! \brief Tries to find rings between \c r0 and \c r1. |
|
86 //! |
|
87 //! This is the main algorithm of the ring finder. It tries to use math |
|
88 //! to find the one ring between r0 and r1. If it fails (the ring number |
|
89 //! is non-integral), it finds an intermediate radius (ceil of the ring |
|
90 //! number times scale) and splits the radius at this point, calling this |
|
91 //! function again to try find the rings between r0 - r and r - r1. |
|
92 //! |
|
93 //! This does not always yield into usable results. If at some point r == |
|
94 //! r0 or r == r1, there is no hope of finding the rings, at least with |
|
95 //! this algorithm, as it would fall into an infinite recursion. |
|
96 //! |
|
97 //! \param r0 the lower radius of the ring space |
|
98 //! \param r1 the higher radius of the ring space |
|
99 //! \returns whether it was possible to find a solution for the given |
|
100 //! \returns ring space. |
|
101 //! |
|
102 bool findRings (double r0, double r1); |
|
103 |
|
104 //! \returns the solution that was considered best. Returns \c null |
|
105 //! \returns if no suitable solution was found. |
|
106 //! \see \c RingFinder::Solution::isSuperiorTo() |
|
107 inline const Solution* bestSolution() |
|
108 { |
|
109 return m_bestSolution; |
|
110 } |
|
111 |
|
112 //! \returns all found solutions. The list is empty if no solutions |
|
113 //! \returns were found. |
|
114 inline const QVector<Solution>& allSolutions() const |
|
115 { |
|
116 return m_solutions; |
|
117 } |
|
118 |
45 |
119 private: |
46 private: |
120 QVector<Solution> m_solutions; |
47 QVector<Component> m_components; |
121 const Solution* m_bestSolution; |
48 }; |
122 int m_stack; |
|
123 |
49 |
124 //! Helper function for \c findRings |
50 RingFinder(); |
125 bool findRingsRecursor (double r0, double r1, Solution& currentSolution); |
51 |
|
52 inline const QVector<Solution>& allSolutions() const; |
|
53 inline const Solution* bestSolution() const; |
|
54 bool findRings (double r0, double r1); |
|
55 |
|
56 private: |
|
57 QVector<Solution> m_solutions; |
|
58 const Solution* m_bestSolution; |
|
59 int m_stack; |
|
60 |
|
61 bool findRingsRecursor (double r0, double r1, Solution& currentSolution); |
126 }; |
62 }; |
127 |
63 |
|
64 // |
|
65 // Gets the components of a solution |
|
66 // |
|
67 inline const QVector<RingFinder::Component>& RingFinder::Solution::getComponents() const |
|
68 { |
|
69 return m_components; |
|
70 } |
|
71 |
|
72 // |
|
73 // Adds a component to a solution |
|
74 // |
|
75 inline void RingFinder::Solution::addComponent (const Component& a) |
|
76 { |
|
77 m_components.push_back (a); |
|
78 } |
|
79 |
|
80 // |
|
81 // Returns the solution that was considered best. Returns null |
|
82 // if there isn't any suitable solution. |
|
83 // |
|
84 inline const RingFinder::Solution* RingFinder::bestSolution() const |
|
85 { |
|
86 return m_bestSolution; |
|
87 } |
|
88 |
|
89 // |
|
90 // Returns all found solutions. |
|
91 // |
|
92 inline const QVector<RingFinder::Solution>& RingFinder::allSolutions() const |
|
93 { |
|
94 return m_solutions; |
|
95 } |
|
96 |
128 extern RingFinder g_RingFinder; |
97 extern RingFinder g_RingFinder; |
129 |
|