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 } |
