comparison base/RangeMapper.cpp @ 891:8962f80f5d8e tony_integration

Merge from default branch
author Chris Cannam
date Tue, 11 Mar 2014 17:32:31 +0000
parents 12a6140b3ae0
children cc27f35aa75c
comparison
equal deleted inserted replaced
890:4cbf8c6a462d 891:8962f80f5d8e
36 } 36 }
37 37
38 int 38 int
39 LinearRangeMapper::getPositionForValue(float value) const 39 LinearRangeMapper::getPositionForValue(float value) const
40 { 40 {
41 int position = getPositionForValueUnclamped(value);
42 if (position < m_minpos) position = m_minpos;
43 if (position > m_maxpos) position = m_maxpos;
44 return position;
45 }
46
47 int
48 LinearRangeMapper::getPositionForValueUnclamped(float value) const
49 {
41 int position = m_minpos + 50 int position = m_minpos +
42 lrintf(((value - m_minval) / (m_maxval - m_minval)) 51 lrintf(((value - m_minval) / (m_maxval - m_minval))
43 * (m_maxpos - m_minpos)); 52 * (m_maxpos - m_minpos));
53 if (m_inverted) return m_maxpos - (position - m_minpos);
54 else return position;
55 }
56
57 float
58 LinearRangeMapper::getValueForPosition(int position) const
59 {
44 if (position < m_minpos) position = m_minpos; 60 if (position < m_minpos) position = m_minpos;
45 if (position > m_maxpos) position = m_maxpos; 61 if (position > m_maxpos) position = m_maxpos;
46 // SVDEBUG << "LinearRangeMapper::getPositionForValue: " << value << " -> " 62 float value = getValueForPositionUnclamped(position);
47 // << position << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", minval " << m_minval << ", maxval " << m_maxval << ")" << endl; 63 return value;
48 if (m_inverted) return m_maxpos - position; 64 }
49 else return position; 65
50 } 66 float
51 67 LinearRangeMapper::getValueForPositionUnclamped(int position) const
52 float 68 {
53 LinearRangeMapper::getValueForPosition(int position) const 69 if (m_inverted) position = m_maxpos - (position - m_minpos);
54 {
55 if (m_inverted) position = m_maxpos - position;
56 float value = m_minval + 70 float value = m_minval +
57 ((float(position - m_minpos) / float(m_maxpos - m_minpos)) 71 ((float(position - m_minpos) / float(m_maxpos - m_minpos))
58 * (m_maxval - m_minval)); 72 * (m_maxval - m_minval));
59 if (value < m_minval) value = m_minval;
60 if (value > m_maxval) value = m_maxval;
61 // SVDEBUG << "LinearRangeMapper::getValueForPosition: " << position << " -> "
62 // << value << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", minval " << m_minval << ", maxval " << m_maxval << ")" << endl;
63 return value; 73 return value;
64 } 74 }
65 75
66 LogRangeMapper::LogRangeMapper(int minpos, int maxpos, 76 LogRangeMapper::LogRangeMapper(int minpos, int maxpos,
67 float minval, float maxval, 77 float minval, float maxval,
71 m_unit(unit), 81 m_unit(unit),
72 m_inverted(inverted) 82 m_inverted(inverted)
73 { 83 {
74 convertMinMax(minpos, maxpos, minval, maxval, m_minlog, m_ratio); 84 convertMinMax(minpos, maxpos, minval, maxval, m_minlog, m_ratio);
75 85
76 cerr << "LogRangeMapper: minpos " << minpos << ", maxpos " 86 // cerr << "LogRangeMapper: minpos " << minpos << ", maxpos "
77 << maxpos << ", minval " << minval << ", maxval " 87 // << maxpos << ", minval " << minval << ", maxval "
78 << maxval << ", minlog " << m_minlog << ", ratio " << m_ratio 88 // << maxval << ", minlog " << m_minlog << ", ratio " << m_ratio
79 << ", unit " << unit << endl; 89 // << ", unit " << unit << endl;
80 90
81 assert(m_maxpos != m_minpos); 91 assert(m_maxpos != m_minpos);
82 92
83 m_maxlog = (m_maxpos - m_minpos) / m_ratio + m_minlog; 93 m_maxlog = (m_maxpos - m_minpos) / m_ratio + m_minlog;
94
95 // cerr << "LogRangeMapper: maxlog = " << m_maxlog << endl;
84 } 96 }
85 97
86 void 98 void
87 LogRangeMapper::convertMinMax(int minpos, int maxpos, 99 LogRangeMapper::convertMinMax(int minpos, int maxpos,
88 float minval, float maxval, 100 float minval, float maxval,
104 } 116 }
105 117
106 int 118 int
107 LogRangeMapper::getPositionForValue(float value) const 119 LogRangeMapper::getPositionForValue(float value) const
108 { 120 {
109 int position = (log10(value) - m_minlog) * m_ratio + m_minpos; 121 int position = getPositionForValueUnclamped(value);
110 if (position < m_minpos) position = m_minpos; 122 if (position < m_minpos) position = m_minpos;
111 if (position > m_maxpos) position = m_maxpos; 123 if (position > m_maxpos) position = m_maxpos;
112 // SVDEBUG << "LogRangeMapper::getPositionForValue: " << value << " -> " 124 return position;
113 // << position << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", ratio " << m_ratio << ", minlog " << m_minlog << ")" << endl; 125 }
114 if (m_inverted) return m_maxpos - position; 126
127 int
128 LogRangeMapper::getPositionForValueUnclamped(float value) const
129 {
130 static float thresh = powf(10, -10);
131 if (value < thresh) value = thresh;
132 int position = lrintf((log10(value) - m_minlog) * m_ratio) + m_minpos;
133 if (m_inverted) return m_maxpos - (position - m_minpos);
115 else return position; 134 else return position;
116 } 135 }
117 136
118 float 137 float
119 LogRangeMapper::getValueForPosition(int position) const 138 LogRangeMapper::getValueForPosition(int position) const
120 { 139 {
121 if (m_inverted) position = m_maxpos - position; 140 if (position < m_minpos) position = m_minpos;
141 if (position > m_maxpos) position = m_maxpos;
142 float value = getValueForPositionUnclamped(position);
143 return value;
144 }
145
146 float
147 LogRangeMapper::getValueForPositionUnclamped(int position) const
148 {
149 if (m_inverted) position = m_maxpos - (position - m_minpos);
122 float value = powf(10, (position - m_minpos) / m_ratio + m_minlog); 150 float value = powf(10, (position - m_minpos) / m_ratio + m_minlog);
123 // SVDEBUG << "LogRangeMapper::getValueForPosition: " << position << " -> "
124 // << value << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", ratio " << m_ratio << ", minlog " << m_minlog << ")" << endl;
125 return value; 151 return value;
126 } 152 }
127 153
154 InterpolatingRangeMapper::InterpolatingRangeMapper(CoordMap pointMappings,
155 QString unit) :
156 m_mappings(pointMappings),
157 m_unit(unit)
158 {
159 for (CoordMap::const_iterator i = m_mappings.begin();
160 i != m_mappings.end(); ++i) {
161 m_reverse[i->second] = i->first;
162 }
163 }
164
165 int
166 InterpolatingRangeMapper::getPositionForValue(float value) const
167 {
168 int pos = getPositionForValueUnclamped(value);
169 CoordMap::const_iterator i = m_mappings.begin();
170 if (pos < i->second) pos = i->second;
171 i = m_mappings.end(); --i;
172 if (pos > i->second) pos = i->second;
173 return pos;
174 }
175
176 int
177 InterpolatingRangeMapper::getPositionForValueUnclamped(float value) const
178 {
179 float p = interpolate(&m_mappings, value);
180 return lrintf(p);
181 }
182
183 float
184 InterpolatingRangeMapper::getValueForPosition(int position) const
185 {
186 float val = getValueForPositionUnclamped(position);
187 CoordMap::const_iterator i = m_mappings.begin();
188 if (val < i->first) val = i->first;
189 i = m_mappings.end(); --i;
190 if (val > i->first) val = i->first;
191 return val;
192 }
193
194 float
195 InterpolatingRangeMapper::getValueForPositionUnclamped(int position) const
196 {
197 return interpolate(&m_reverse, position);
198 }
199
200 template <typename T>
201 float
202 InterpolatingRangeMapper::interpolate(T *mapping, float value) const
203 {
204 // lower_bound: first element which does not compare less than value
205 typename T::const_iterator i = mapping->lower_bound(value);
206
207 if (i == mapping->begin()) {
208 // value is less than or equal to first element, so use the
209 // gradient from first to second and extend it
210 ++i;
211 }
212
213 if (i == mapping->end()) {
214 // value is off the end, so use the gradient from penultimate
215 // to ultimate and extend it
216 --i;
217 }
218
219 typename T::const_iterator j = i;
220 --j;
221
222 float gradient = float(i->second - j->second) / float(i->first - j->first);
223
224 return j->second + (value - j->first) * gradient;
225 }
226
227 AutoRangeMapper::AutoRangeMapper(CoordMap pointMappings,
228 QString unit) :
229 m_mappings(pointMappings),
230 m_unit(unit)
231 {
232 m_type = chooseMappingTypeFor(m_mappings);
233
234 CoordMap::const_iterator first = m_mappings.begin();
235 CoordMap::const_iterator last = m_mappings.end();
236 --last;
237
238 switch (m_type) {
239 case StraightLine:
240 m_mapper = new LinearRangeMapper(first->second, last->second,
241 first->first, last->first,
242 unit, false);
243 break;
244 case Logarithmic:
245 m_mapper = new LogRangeMapper(first->second, last->second,
246 first->first, last->first,
247 unit, false);
248 break;
249 case Interpolating:
250 m_mapper = new InterpolatingRangeMapper(m_mappings, unit);
251 break;
252 }
253 }
254
255 AutoRangeMapper::~AutoRangeMapper()
256 {
257 delete m_mapper;
258 }
259
260 AutoRangeMapper::MappingType
261 AutoRangeMapper::chooseMappingTypeFor(const CoordMap &mappings)
262 {
263 // how do we work out whether a linear/log mapping is "close enough"?
264
265 CoordMap::const_iterator first = mappings.begin();
266 CoordMap::const_iterator last = mappings.end();
267 --last;
268
269 LinearRangeMapper linm(first->second, last->second,
270 first->first, last->first,
271 "", false);
272
273 bool inadequate = false;
274
275 for (CoordMap::const_iterator i = mappings.begin();
276 i != mappings.end(); ++i) {
277 int candidate = linm.getPositionForValue(i->first);
278 int diff = candidate - i->second;
279 if (diff < 0) diff = -diff;
280 if (diff > 1) {
281 // cerr << "AutoRangeMapper::chooseMappingTypeFor: diff = " << diff
282 // << ", straight-line mapping inadequate" << endl;
283 inadequate = true;
284 break;
285 }
286 }
287
288 if (!inadequate) {
289 return StraightLine;
290 }
291
292 LogRangeMapper logm(first->second, last->second,
293 first->first, last->first,
294 "", false);
295
296 inadequate = false;
297
298 for (CoordMap::const_iterator i = mappings.begin();
299 i != mappings.end(); ++i) {
300 int candidate = logm.getPositionForValue(i->first);
301 int diff = candidate - i->second;
302 if (diff < 0) diff = -diff;
303 if (diff > 1) {
304 // cerr << "AutoRangeMapper::chooseMappingTypeFor: diff = " << diff
305 // << ", log mapping inadequate" << endl;
306 inadequate = true;
307 break;
308 }
309 }
310
311 if (!inadequate) {
312 return Logarithmic;
313 }
314
315 return Interpolating;
316 }
317
318 int
319 AutoRangeMapper::getPositionForValue(float value) const
320 {
321 return m_mapper->getPositionForValue(value);
322 }
323
324 float
325 AutoRangeMapper::getValueForPosition(int position) const
326 {
327 return m_mapper->getValueForPosition(position);
328 }
329
330 int
331 AutoRangeMapper::getPositionForValueUnclamped(float value) const
332 {
333 return m_mapper->getPositionForValueUnclamped(value);
334 }
335
336 float
337 AutoRangeMapper::getValueForPositionUnclamped(int position) const
338 {
339 return m_mapper->getValueForPositionUnclamped(position);
340 }