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 }