annotate base/RangeMapper.h @ 985:f073d924a7c3

Fix #1058 clicking row in Layer Edit dialog when colour 3d plot layer active jumps to wrong frame (was using sample rate where resolution intended)
author Chris Cannam
date Tue, 16 Sep 2014 10:29:19 +0100
parents 12a6140b3ae0
children cc27f35aa75c
rev   line source
Chris@189 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@189 2
Chris@189 3 /*
Chris@189 4 Sonic Visualiser
Chris@189 5 An audio file viewer and annotation editor.
Chris@189 6 Centre for Digital Music, Queen Mary, University of London.
Chris@202 7 This file copyright 2006 QMUL.
Chris@189 8
Chris@189 9 This program is free software; you can redistribute it and/or
Chris@189 10 modify it under the terms of the GNU General Public License as
Chris@189 11 published by the Free Software Foundation; either version 2 of the
Chris@189 12 License, or (at your option) any later version. See the file
Chris@189 13 COPYING included with this distribution for more information.
Chris@189 14 */
Chris@189 15
Chris@189 16 #ifndef _RANGE_MAPPER_H_
Chris@189 17 #define _RANGE_MAPPER_H_
Chris@189 18
Chris@189 19 #include <QString>
Chris@189 20
Chris@686 21 #include "Debug.h"
Chris@880 22 #include <map>
Chris@189 23
Chris@189 24 class RangeMapper
Chris@189 25 {
Chris@189 26 public:
Chris@189 27 virtual ~RangeMapper() { }
Chris@885 28
Chris@885 29 /**
Chris@885 30 * Return the position that maps to the given value, rounding to
Chris@885 31 * the nearest position and clamping to the minimum and maximum
Chris@885 32 * extents of the mapper's positional range.
Chris@885 33 */
Chris@189 34 virtual int getPositionForValue(float value) const = 0;
Chris@885 35
Chris@885 36 /**
Chris@885 37 * Return the position that maps to the given value, rounding to
Chris@885 38 * the nearest position, without clamping. That is, whatever
Chris@885 39 * mapping function is in use will be projected even outside the
Chris@885 40 * minimum and maximum extents of the mapper's positional
Chris@885 41 * range. (The mapping outside that range is not guaranteed to be
Chris@885 42 * exact, except if the mapper is a linear one.)
Chris@885 43 */
Chris@885 44 virtual int getPositionForValueUnclamped(float value) const = 0;
Chris@885 45
Chris@885 46 /**
Chris@885 47 * Return the value mapped from the given position, clamping to
Chris@885 48 * the minimum and maximum extents of the mapper's value range.
Chris@885 49 */
Chris@189 50 virtual float getValueForPosition(int position) const = 0;
Chris@885 51
Chris@885 52 /**
Chris@885 53 * Return the value mapped from the given positionq, without
Chris@885 54 * clamping. That is, whatever mapping function is in use will be
Chris@885 55 * projected even outside the minimum and maximum extents of the
Chris@885 56 * mapper's value range. (The mapping outside that range is not
Chris@885 57 * guaranteed to be exact, except if the mapper is a linear one.)
Chris@885 58 */
Chris@885 59 virtual float getValueForPositionUnclamped(int position) const = 0;
Chris@885 60
Chris@885 61 /**
Chris@885 62 * Get the unit of the mapper's value range.
Chris@885 63 */
Chris@189 64 virtual QString getUnit() const { return ""; }
Chris@189 65 };
Chris@189 66
Chris@189 67
Chris@189 68 class LinearRangeMapper : public RangeMapper
Chris@189 69 {
Chris@189 70 public:
Chris@879 71 /**
Chris@879 72 * Map values in range minval->maxval linearly into integer range
Chris@879 73 * minpos->maxpos. minval and minpos must be less than maxval and
Chris@879 74 * maxpos respectively. If inverted is true, the range will be
Chris@879 75 * mapped "backwards" (minval to maxpos and maxval to minpos).
Chris@879 76 */
Chris@189 77 LinearRangeMapper(int minpos, int maxpos,
Chris@189 78 float minval, float maxval,
Chris@464 79 QString unit = "", bool inverted = false);
Chris@189 80
Chris@189 81 virtual int getPositionForValue(float value) const;
Chris@885 82 virtual int getPositionForValueUnclamped(float value) const;
Chris@885 83
Chris@189 84 virtual float getValueForPosition(int position) const;
Chris@885 85 virtual float getValueForPositionUnclamped(int position) const;
Chris@189 86
Chris@189 87 virtual QString getUnit() const { return m_unit; }
Chris@189 88
Chris@189 89 protected:
Chris@189 90 int m_minpos;
Chris@189 91 int m_maxpos;
Chris@189 92 float m_minval;
Chris@189 93 float m_maxval;
Chris@189 94 QString m_unit;
Chris@464 95 bool m_inverted;
Chris@189 96 };
Chris@189 97
Chris@189 98 class LogRangeMapper : public RangeMapper
Chris@189 99 {
Chris@189 100 public:
Chris@880 101 /**
Chris@880 102 * Map values in range minval->maxval into integer range
Chris@880 103 * minpos->maxpos such that logs of the values are mapped
Chris@885 104 * linearly. minval must be greater than zero, and minval and
Chris@885 105 * minpos must be less than maxval and maxpos respectively. If
Chris@885 106 * inverted is true, the range will be mapped "backwards" (minval
Chris@885 107 * to maxpos and maxval to minpos).
Chris@880 108 */
Chris@189 109 LogRangeMapper(int minpos, int maxpos,
Chris@356 110 float minval, float maxval,
Chris@464 111 QString m_unit = "", bool inverted = false);
Chris@189 112
Chris@356 113 static void convertRatioMinLog(float ratio, float minlog,
Chris@356 114 int minpos, int maxpos,
Chris@356 115 float &minval, float &maxval);
Chris@356 116
Chris@356 117 static void convertMinMax(int minpos, int maxpos,
Chris@356 118 float minval, float maxval,
Chris@356 119 float &ratio, float &minlog);
Chris@356 120
Chris@189 121 virtual int getPositionForValue(float value) const;
Chris@885 122 virtual int getPositionForValueUnclamped(float value) const;
Chris@885 123
Chris@189 124 virtual float getValueForPosition(int position) const;
Chris@885 125 virtual float getValueForPositionUnclamped(int position) const;
Chris@189 126
Chris@189 127 virtual QString getUnit() const { return m_unit; }
Chris@189 128
Chris@189 129 protected:
Chris@189 130 int m_minpos;
Chris@189 131 int m_maxpos;
Chris@189 132 float m_ratio;
Chris@189 133 float m_minlog;
Chris@189 134 float m_maxlog;
Chris@189 135 QString m_unit;
Chris@464 136 bool m_inverted;
Chris@189 137 };
Chris@189 138
Chris@880 139 class InterpolatingRangeMapper : public RangeMapper
Chris@880 140 {
Chris@880 141 public:
Chris@880 142 typedef std::map<float, int> CoordMap;
Chris@880 143
Chris@880 144 /**
Chris@880 145 * Given a series of (value, position) coordinate mappings,
Chris@880 146 * construct a range mapper that maps arbitrary values, in the
Chris@880 147 * range between minimum and maximum of the provided values, onto
Chris@880 148 * coordinates using linear interpolation between the supplied
Chris@880 149 * points.
Chris@880 150 *
Chris@880 151 *!!! todo: Cubic -- more generally useful than linear interpolation
Chris@880 152 *!!! todo: inverted flag
Chris@880 153 *
Chris@880 154 * The set of provided mappings must contain at least two
Chris@880 155 * coordinates.
Chris@880 156 *
Chris@880 157 * It is expected that the values and positions in the coordinate
Chris@880 158 * mappings will both be monotonically increasing (i.e. no
Chris@880 159 * inflections in the mapping curve). Behaviour is undefined if
Chris@880 160 * this is not the case.
Chris@880 161 */
Chris@880 162 InterpolatingRangeMapper(CoordMap pointMappings,
Chris@880 163 QString unit);
Chris@880 164
Chris@880 165 virtual int getPositionForValue(float value) const;
Chris@885 166 virtual int getPositionForValueUnclamped(float value) const;
Chris@885 167
Chris@880 168 virtual float getValueForPosition(int position) const;
Chris@885 169 virtual float getValueForPositionUnclamped(int position) const;
Chris@880 170
Chris@880 171 virtual QString getUnit() const { return m_unit; }
Chris@880 172
Chris@880 173 protected:
Chris@880 174 CoordMap m_mappings;
Chris@880 175 std::map<int, float> m_reverse;
Chris@880 176 QString m_unit;
Chris@885 177
Chris@885 178 template <typename T>
Chris@885 179 float interpolate(T *mapping, float v) const;
Chris@880 180 };
Chris@880 181
Chris@880 182 class AutoRangeMapper : public RangeMapper
Chris@880 183 {
Chris@880 184 public:
Chris@880 185 enum MappingType {
Chris@880 186 Interpolating,
Chris@880 187 StraightLine,
Chris@880 188 Logarithmic,
Chris@880 189 };
Chris@880 190
Chris@880 191 typedef std::map<float, int> CoordMap;
Chris@880 192
Chris@880 193 /**
Chris@880 194 * Given a series of (value, position) coordinate mappings,
Chris@880 195 * construct a range mapper that maps arbitrary values, in the
Chris@880 196 * range between minimum and maximum of the provided values, onto
Chris@880 197 * coordinates.
Chris@880 198 *
Chris@880 199 * The mapping used may be
Chris@880 200 *
Chris@880 201 * Interpolating -- an InterpolatingRangeMapper will be used
Chris@880 202 *
Chris@880 203 * StraightLine -- a LinearRangeMapper from the minimum to
Chris@880 204 * maximum value coordinates will be used, ignoring all other
Chris@880 205 * supplied coordinate mappings
Chris@880 206 *
Chris@880 207 * Logarithmic -- a LogRangeMapper from the minimum to
Chris@880 208 * maximum value coordinates will be used, ignoring all other
Chris@880 209 * supplied coordinate mappings
Chris@880 210 *
Chris@880 211 * The mapping will be chosen automatically by looking at the
Chris@880 212 * supplied coordinates. If the supplied coordinates fall on a
Chris@880 213 * straight line, a StraightLine mapping will be used; if they
Chris@880 214 * fall on a log curve, a Logarithmic mapping will be used;
Chris@880 215 * otherwise an Interpolating mapping will be used.
Chris@880 216 *
Chris@880 217 *!!! todo: inverted flag
Chris@880 218 *
Chris@880 219 * The set of provided mappings must contain at least two
Chris@880 220 * coordinates, or at least three if the points are not supposed
Chris@880 221 * to be in a straight line.
Chris@880 222 *
Chris@880 223 * It is expected that the values and positions in the coordinate
Chris@880 224 * mappings will both be monotonically increasing (i.e. no
Chris@880 225 * inflections in the mapping curve). Behaviour is undefined if
Chris@880 226 * this is not the case.
Chris@880 227 */
Chris@880 228 AutoRangeMapper(CoordMap pointMappings,
Chris@880 229 QString unit);
Chris@880 230
Chris@880 231 ~AutoRangeMapper();
Chris@880 232
Chris@880 233 /**
Chris@880 234 * Return the mapping type in use.
Chris@880 235 */
Chris@880 236 MappingType getType() const { return m_type; }
Chris@880 237
Chris@880 238 virtual int getPositionForValue(float value) const;
Chris@885 239 virtual int getPositionForValueUnclamped(float value) const;
Chris@885 240
Chris@880 241 virtual float getValueForPosition(int position) const;
Chris@885 242 virtual float getValueForPositionUnclamped(int position) const;
Chris@880 243
Chris@880 244 virtual QString getUnit() const { return m_unit; }
Chris@880 245
Chris@880 246 protected:
Chris@880 247 MappingType m_type;
Chris@880 248 CoordMap m_mappings;
Chris@880 249 QString m_unit;
Chris@880 250 RangeMapper *m_mapper;
Chris@880 251
Chris@880 252 MappingType chooseMappingTypeFor(const CoordMap &);
Chris@880 253 };
Chris@189 254
Chris@189 255 #endif