src/misc/RingFinder.h

changeset 690
9e9c52ca955e
parent 650
db7146a87ae4
equal deleted inserted replaced
689:397870c6ed38 690:9e9c52ca955e
14 * 14 *
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 #ifndef LDFORGE_MISC_RINGFINDER_H 19 #pragma once
20 #define LDFORGE_MISC_RINGFINDER_H
21 20
22 #include "../Main.h" 21 #include "../Main.h"
23 22
24 // ============================================================================= 23 //!
25 // RingFinder 24 //! \brief Provides an algorithm for finding solutions of rings between given radii.
26 // 25 //!
27 // Provides an algorithm for finding a solution of rings between radii r0 and r1. 26 //! The RingFinder is a class which implements a ring finding algorithm. It is passed
28 // ============================================================================= 27 //! two radii and it tries to find solutions of rings that would fill the given space.
28 //!
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 //!
29 class RingFinder 32 class RingFinder
30 { 33 {
31 public: 34 public:
35 //! A single component in a solution
32 struct Component 36 struct Component
33 { 37 {
34 int num; 38 int num;
35 double scale; 39 double scale;
36 }; 40 };
37 41
42 //! A solution whose components would fill the desired ring space.
38 class Solution 43 class Solution
39 { 44 {
40 public: 45 public:
41 // Components of this solution 46 //! \returns components of this solution
42 inline const QVector<Component>& getComponents() const 47 inline const QVector<Component>& getComponents() const
43 { 48 {
44 return m_components; 49 return m_components;
45 } 50 }
46 51
47 // Add a component to this solution 52 //! Add a component to this solution
48 inline void addComponent (const Component& a) 53 inline void addComponent (const Component& a)
49 { 54 {
50 m_components.push_back (a); 55 m_components.push_back (a);
51 } 56 }
52 57
53 // Compare solutions 58 //! \brief Compare solutions.
54 bool isBetterThan (const Solution* other) const; 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;
55 77
56 private: 78 private:
57 QVector<Component> m_components; 79 QVector<Component> m_components;
58 }; 80 };
59 81
82 //! Constructs a ring finder.
60 RingFinder() {} 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 //!
61 bool findRings (double r0, double r1); 102 bool findRings (double r0, double r1);
62 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()
63 inline const Solution* bestSolution() 107 inline const Solution* bestSolution()
64 { 108 {
65 return m_bestSolution; 109 return m_bestSolution;
66 } 110 }
67 111
112 //! \returns all found solutions. The list is empty if no solutions
113 //! \returns were found.
68 inline const QVector<Solution>& allSolutions() const 114 inline const QVector<Solution>& allSolutions() const
69 { 115 {
70 return m_solutions; 116 return m_solutions;
71 }
72
73 inline bool operator() (double r0, double r1)
74 {
75 return findRings (r0, r1);
76 } 117 }
77 118
78 private: 119 private:
79 QVector<Solution> m_solutions; 120 QVector<Solution> m_solutions;
80 const Solution* m_bestSolution; 121 const Solution* m_bestSolution;
81 int m_stack; 122 int m_stack;
82 123
124 //! Helper function for \c findRings
83 bool findRingsRecursor (double r0, double r1, Solution& currentSolution); 125 bool findRingsRecursor (double r0, double r1, Solution& currentSolution);
84 }; 126 };
85 127
86 extern RingFinder g_RingFinder; 128 extern RingFinder g_RingFinder;
87 129
88 #endif // LDFORGE_MISC_RINGFINDER_H

mercurial