Mercurial > hg > svcore
comparison base/RangeMapper.cpp @ 885:12a6140b3ae0
Add unclamped range mapper methods
author | Chris Cannam |
---|---|
date | Thu, 06 Feb 2014 15:31:16 +0000 |
parents | b4787b595db3 |
children | cc27f35aa75c |
comparison
equal
deleted
inserted
replaced
884:633a8fa622c9 | 885:12a6140b3ae0 |
---|---|
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 if (m_inverted) return m_maxpos - (position - m_minpos); | 62 float value = getValueForPositionUnclamped(position); |
47 else return position; | 63 return value; |
48 } | 64 } |
49 | 65 |
50 float | 66 float |
51 LinearRangeMapper::getValueForPosition(int position) const | 67 LinearRangeMapper::getValueForPositionUnclamped(int position) const |
52 { | 68 { |
53 if (m_inverted) position = m_maxpos - (position - m_minpos); | 69 if (m_inverted) position = m_maxpos - (position - m_minpos); |
54 if (position < m_minpos) position = m_minpos; | |
55 if (position > m_maxpos) position = m_maxpos; | |
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 return value; | 73 return value; |
60 } | 74 } |
102 } | 116 } |
103 | 117 |
104 int | 118 int |
105 LogRangeMapper::getPositionForValue(float value) const | 119 LogRangeMapper::getPositionForValue(float value) const |
106 { | 120 { |
107 int position = lrintf((log10(value) - m_minlog) * m_ratio) + m_minpos; | 121 int position = getPositionForValueUnclamped(value); |
108 if (position < m_minpos) position = m_minpos; | 122 if (position < m_minpos) position = m_minpos; |
109 if (position > m_maxpos) position = m_maxpos; | 123 if (position > m_maxpos) position = m_maxpos; |
110 // cerr << "LogRangeMapper::getPositionForValue: " << value << " -> " | 124 return position; |
111 // << position << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", ratio " << m_ratio << ", minlog " << m_minlog << ")" << endl; | 125 } |
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; | |
112 if (m_inverted) return m_maxpos - (position - m_minpos); | 133 if (m_inverted) return m_maxpos - (position - m_minpos); |
113 else return position; | 134 else return position; |
114 } | 135 } |
115 | 136 |
116 float | 137 float |
117 LogRangeMapper::getValueForPosition(int position) const | 138 LogRangeMapper::getValueForPosition(int position) const |
118 { | 139 { |
119 if (m_inverted) position = m_maxpos - (position - m_minpos); | |
120 if (position < m_minpos) position = m_minpos; | 140 if (position < m_minpos) position = m_minpos; |
121 if (position > m_maxpos) position = m_maxpos; | 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 // cerr << "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 |
128 InterpolatingRangeMapper::InterpolatingRangeMapper(CoordMap pointMappings, | 154 InterpolatingRangeMapper::InterpolatingRangeMapper(CoordMap pointMappings, |
129 QString unit) : | 155 QString unit) : |
137 } | 163 } |
138 | 164 |
139 int | 165 int |
140 InterpolatingRangeMapper::getPositionForValue(float value) const | 166 InterpolatingRangeMapper::getPositionForValue(float value) const |
141 { | 167 { |
142 CoordMap::const_iterator i = m_mappings.lower_bound(value); | 168 int pos = getPositionForValueUnclamped(value); |
143 CoordMap::const_iterator j = i; | 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; | |
144 --j; | 220 --j; |
145 | 221 |
146 if (i == m_mappings.end()) return j->second; | 222 float gradient = float(i->second - j->second) / float(i->first - j->first); |
147 if (i == m_mappings.begin()) return i->second; | 223 |
148 if (i->first == value) return i->second; | 224 return j->second + (value - j->first) * gradient; |
149 | |
150 return lrintf(((value - j->first) / (i->first - j->first)) * | |
151 float(i->second - j->second) + j->second); | |
152 } | |
153 | |
154 float | |
155 InterpolatingRangeMapper::getValueForPosition(int position) const | |
156 { | |
157 std::map<int, float>::const_iterator i = m_reverse.lower_bound(position); | |
158 std::map<int, float>::const_iterator j = i; | |
159 --j; | |
160 | |
161 if (i == m_reverse.end()) return j->second; | |
162 if (i == m_reverse.begin()) return i->second; | |
163 if (i->first == position) return i->second; | |
164 | |
165 return ((float(position) - j->first) / (i->first - j->first)) * | |
166 (i->second - j->second) + j->second; | |
167 } | 225 } |
168 | 226 |
169 AutoRangeMapper::AutoRangeMapper(CoordMap pointMappings, | 227 AutoRangeMapper::AutoRangeMapper(CoordMap pointMappings, |
170 QString unit) : | 228 QString unit) : |
171 m_mappings(pointMappings), | 229 m_mappings(pointMappings), |
218 i != mappings.end(); ++i) { | 276 i != mappings.end(); ++i) { |
219 int candidate = linm.getPositionForValue(i->first); | 277 int candidate = linm.getPositionForValue(i->first); |
220 int diff = candidate - i->second; | 278 int diff = candidate - i->second; |
221 if (diff < 0) diff = -diff; | 279 if (diff < 0) diff = -diff; |
222 if (diff > 1) { | 280 if (diff > 1) { |
223 cerr << "AutoRangeMapper::chooseMappingTypeFor: diff = " << diff | 281 // cerr << "AutoRangeMapper::chooseMappingTypeFor: diff = " << diff |
224 << ", straight-line mapping inadequate" << endl; | 282 // << ", straight-line mapping inadequate" << endl; |
225 inadequate = true; | 283 inadequate = true; |
226 break; | 284 break; |
227 } | 285 } |
228 } | 286 } |
229 | 287 |
241 i != mappings.end(); ++i) { | 299 i != mappings.end(); ++i) { |
242 int candidate = logm.getPositionForValue(i->first); | 300 int candidate = logm.getPositionForValue(i->first); |
243 int diff = candidate - i->second; | 301 int diff = candidate - i->second; |
244 if (diff < 0) diff = -diff; | 302 if (diff < 0) diff = -diff; |
245 if (diff > 1) { | 303 if (diff > 1) { |
246 cerr << "AutoRangeMapper::chooseMappingTypeFor: diff = " << diff | 304 // cerr << "AutoRangeMapper::chooseMappingTypeFor: diff = " << diff |
247 << ", log mapping inadequate" << endl; | 305 // << ", log mapping inadequate" << endl; |
248 inadequate = true; | 306 inadequate = true; |
249 break; | 307 break; |
250 } | 308 } |
251 } | 309 } |
252 | 310 |
266 float | 324 float |
267 AutoRangeMapper::getValueForPosition(int position) const | 325 AutoRangeMapper::getValueForPosition(int position) const |
268 { | 326 { |
269 return m_mapper->getValueForPosition(position); | 327 return m_mapper->getValueForPosition(position); |
270 } | 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 } |