annotate base/RangeMapper.h @ 961:fae5689f7e27

Frame this condition more defensively (from coverity scan)
author Chris Cannam
date Wed, 03 Sep 2014 09:57:30 +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