comparison base/RangeMapper.h @ 912:2175c2ebd5c6 tonioni

Merge from default branch
author Chris Cannam
date Wed, 14 May 2014 09:58:07 +0100
parents 12a6140b3ae0
children cc27f35aa75c
comparison
equal deleted inserted replaced
901:68e880e0b857 912:2175c2ebd5c6
17 #define _RANGE_MAPPER_H_ 17 #define _RANGE_MAPPER_H_
18 18
19 #include <QString> 19 #include <QString>
20 20
21 #include "Debug.h" 21 #include "Debug.h"
22 22 #include <map>
23 23
24 class RangeMapper 24 class RangeMapper
25 { 25 {
26 public: 26 public:
27 virtual ~RangeMapper() { } 27 virtual ~RangeMapper() { }
28
29 /**
30 * Return the position that maps to the given value, rounding to
31 * the nearest position and clamping to the minimum and maximum
32 * extents of the mapper's positional range.
33 */
28 virtual int getPositionForValue(float value) const = 0; 34 virtual int getPositionForValue(float value) const = 0;
35
36 /**
37 * Return the position that maps to the given value, rounding to
38 * the nearest position, without clamping. That is, whatever
39 * mapping function is in use will be projected even outside the
40 * minimum and maximum extents of the mapper's positional
41 * range. (The mapping outside that range is not guaranteed to be
42 * exact, except if the mapper is a linear one.)
43 */
44 virtual int getPositionForValueUnclamped(float value) const = 0;
45
46 /**
47 * Return the value mapped from the given position, clamping to
48 * the minimum and maximum extents of the mapper's value range.
49 */
29 virtual float getValueForPosition(int position) const = 0; 50 virtual float getValueForPosition(int position) const = 0;
51
52 /**
53 * Return the value mapped from the given positionq, without
54 * clamping. That is, whatever mapping function is in use will be
55 * projected even outside the minimum and maximum extents of the
56 * mapper's value range. (The mapping outside that range is not
57 * guaranteed to be exact, except if the mapper is a linear one.)
58 */
59 virtual float getValueForPositionUnclamped(int position) const = 0;
60
61 /**
62 * Get the unit of the mapper's value range.
63 */
30 virtual QString getUnit() const { return ""; } 64 virtual QString getUnit() const { return ""; }
31 }; 65 };
32 66
33 67
34 class LinearRangeMapper : public RangeMapper 68 class LinearRangeMapper : public RangeMapper
35 { 69 {
36 public: 70 public:
71 /**
72 * Map values in range minval->maxval linearly into integer range
73 * minpos->maxpos. minval and minpos must be less than maxval and
74 * maxpos respectively. If inverted is true, the range will be
75 * mapped "backwards" (minval to maxpos and maxval to minpos).
76 */
37 LinearRangeMapper(int minpos, int maxpos, 77 LinearRangeMapper(int minpos, int maxpos,
38 float minval, float maxval, 78 float minval, float maxval,
39 QString unit = "", bool inverted = false); 79 QString unit = "", bool inverted = false);
40 80
41 virtual int getPositionForValue(float value) const; 81 virtual int getPositionForValue(float value) const;
42 virtual float getValueForPosition(int position) const; 82 virtual int getPositionForValueUnclamped(float value) const;
83
84 virtual float getValueForPosition(int position) const;
85 virtual float getValueForPositionUnclamped(int position) const;
43 86
44 virtual QString getUnit() const { return m_unit; } 87 virtual QString getUnit() const { return m_unit; }
45 88
46 protected: 89 protected:
47 int m_minpos; 90 int m_minpos;
50 float m_maxval; 93 float m_maxval;
51 QString m_unit; 94 QString m_unit;
52 bool m_inverted; 95 bool m_inverted;
53 }; 96 };
54 97
55
56 class LogRangeMapper : public RangeMapper 98 class LogRangeMapper : public RangeMapper
57 { 99 {
58 public: 100 public:
101 /**
102 * Map values in range minval->maxval into integer range
103 * minpos->maxpos such that logs of the values are mapped
104 * linearly. minval must be greater than zero, and minval and
105 * minpos must be less than maxval and maxpos respectively. If
106 * inverted is true, the range will be mapped "backwards" (minval
107 * to maxpos and maxval to minpos).
108 */
59 LogRangeMapper(int minpos, int maxpos, 109 LogRangeMapper(int minpos, int maxpos,
60 float minval, float maxval, 110 float minval, float maxval,
61 QString m_unit = "", bool inverted = false); 111 QString m_unit = "", bool inverted = false);
62 112
63 static void convertRatioMinLog(float ratio, float minlog, 113 static void convertRatioMinLog(float ratio, float minlog,
67 static void convertMinMax(int minpos, int maxpos, 117 static void convertMinMax(int minpos, int maxpos,
68 float minval, float maxval, 118 float minval, float maxval,
69 float &ratio, float &minlog); 119 float &ratio, float &minlog);
70 120
71 virtual int getPositionForValue(float value) const; 121 virtual int getPositionForValue(float value) const;
72 virtual float getValueForPosition(int position) const; 122 virtual int getPositionForValueUnclamped(float value) const;
123
124 virtual float getValueForPosition(int position) const;
125 virtual float getValueForPositionUnclamped(int position) const;
73 126
74 virtual QString getUnit() const { return m_unit; } 127 virtual QString getUnit() const { return m_unit; }
75 128
76 protected: 129 protected:
77 int m_minpos; 130 int m_minpos;
81 float m_maxlog; 134 float m_maxlog;
82 QString m_unit; 135 QString m_unit;
83 bool m_inverted; 136 bool m_inverted;
84 }; 137 };
85 138
139 class InterpolatingRangeMapper : public RangeMapper
140 {
141 public:
142 typedef std::map<float, int> CoordMap;
143
144 /**
145 * Given a series of (value, position) coordinate mappings,
146 * construct a range mapper that maps arbitrary values, in the
147 * range between minimum and maximum of the provided values, onto
148 * coordinates using linear interpolation between the supplied
149 * points.
150 *
151 *!!! todo: Cubic -- more generally useful than linear interpolation
152 *!!! todo: inverted flag
153 *
154 * The set of provided mappings must contain at least two
155 * coordinates.
156 *
157 * It is expected that the values and positions in the coordinate
158 * mappings will both be monotonically increasing (i.e. no
159 * inflections in the mapping curve). Behaviour is undefined if
160 * this is not the case.
161 */
162 InterpolatingRangeMapper(CoordMap pointMappings,
163 QString unit);
164
165 virtual int getPositionForValue(float value) const;
166 virtual int getPositionForValueUnclamped(float value) const;
167
168 virtual float getValueForPosition(int position) const;
169 virtual float getValueForPositionUnclamped(int position) const;
170
171 virtual QString getUnit() const { return m_unit; }
172
173 protected:
174 CoordMap m_mappings;
175 std::map<int, float> m_reverse;
176 QString m_unit;
177
178 template <typename T>
179 float interpolate(T *mapping, float v) const;
180 };
181
182 class AutoRangeMapper : public RangeMapper
183 {
184 public:
185 enum MappingType {
186 Interpolating,
187 StraightLine,
188 Logarithmic,
189 };
190
191 typedef std::map<float, int> CoordMap;
192
193 /**
194 * Given a series of (value, position) coordinate mappings,
195 * construct a range mapper that maps arbitrary values, in the
196 * range between minimum and maximum of the provided values, onto
197 * coordinates.
198 *
199 * The mapping used may be
200 *
201 * Interpolating -- an InterpolatingRangeMapper will be used
202 *
203 * StraightLine -- a LinearRangeMapper from the minimum to
204 * maximum value coordinates will be used, ignoring all other
205 * supplied coordinate mappings
206 *
207 * Logarithmic -- a LogRangeMapper from the minimum to
208 * maximum value coordinates will be used, ignoring all other
209 * supplied coordinate mappings
210 *
211 * The mapping will be chosen automatically by looking at the
212 * supplied coordinates. If the supplied coordinates fall on a
213 * straight line, a StraightLine mapping will be used; if they
214 * fall on a log curve, a Logarithmic mapping will be used;
215 * otherwise an Interpolating mapping will be used.
216 *
217 *!!! todo: inverted flag
218 *
219 * The set of provided mappings must contain at least two
220 * coordinates, or at least three if the points are not supposed
221 * to be in a straight line.
222 *
223 * It is expected that the values and positions in the coordinate
224 * mappings will both be monotonically increasing (i.e. no
225 * inflections in the mapping curve). Behaviour is undefined if
226 * this is not the case.
227 */
228 AutoRangeMapper(CoordMap pointMappings,
229 QString unit);
230
231 ~AutoRangeMapper();
232
233 /**
234 * Return the mapping type in use.
235 */
236 MappingType getType() const { return m_type; }
237
238 virtual int getPositionForValue(float value) const;
239 virtual int getPositionForValueUnclamped(float value) const;
240
241 virtual float getValueForPosition(int position) const;
242 virtual float getValueForPositionUnclamped(int position) const;
243
244 virtual QString getUnit() const { return m_unit; }
245
246 protected:
247 MappingType m_type;
248 CoordMap m_mappings;
249 QString m_unit;
250 RangeMapper *m_mapper;
251
252 MappingType chooseMappingTypeFor(const CoordMap &);
253 };
86 254
87 #endif 255 #endif