annotate base/RangeMapper.h @ 1061:c1e43c8d2527 tonioni

Thread-local debug was causing crash on exit with Qt 5.4.x. But we introduced that because QDebug itself was crashing when used from multiple threads. Replace with simpler fstream version
author Chris Cannam
date Tue, 31 Mar 2015 10:36:52 +0100
parents cc27f35aa75c
children 932487fe515a
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@1038 34 virtual int getPositionForValue(double 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@1038 44 virtual int getPositionForValueUnclamped(double 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@1038 50 virtual double 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@1038 59 virtual double 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@1038 78 double minval, double maxval,
Chris@464 79 QString unit = "", bool inverted = false);
Chris@189 80
Chris@1038 81 virtual int getPositionForValue(double value) const;
Chris@1038 82 virtual int getPositionForValueUnclamped(double value) const;
Chris@885 83
Chris@1038 84 virtual double getValueForPosition(int position) const;
Chris@1038 85 virtual double 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@1038 92 double m_minval;
Chris@1038 93 double 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@1038 110 double minval, double maxval,
Chris@464 111 QString m_unit = "", bool inverted = false);
Chris@189 112
Chris@1038 113 static void convertRatioMinLog(double ratio, double minlog,
Chris@356 114 int minpos, int maxpos,
Chris@1038 115 double &minval, double &maxval);
Chris@356 116
Chris@356 117 static void convertMinMax(int minpos, int maxpos,
Chris@1038 118 double minval, double maxval,
Chris@1038 119 double &ratio, double &minlog);
Chris@356 120
Chris@1038 121 virtual int getPositionForValue(double value) const;
Chris@1038 122 virtual int getPositionForValueUnclamped(double value) const;
Chris@885 123
Chris@1038 124 virtual double getValueForPosition(int position) const;
Chris@1038 125 virtual double 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@1038 132 double m_ratio;
Chris@1038 133 double m_minlog;
Chris@1038 134 double 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@1038 142 typedef std::map<double, 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@1038 165 virtual int getPositionForValue(double value) const;
Chris@1038 166 virtual int getPositionForValueUnclamped(double value) const;
Chris@885 167
Chris@1038 168 virtual double getValueForPosition(int position) const;
Chris@1038 169 virtual double 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@1038 175 std::map<int, double> m_reverse;
Chris@880 176 QString m_unit;
Chris@885 177
Chris@885 178 template <typename T>
Chris@1038 179 double interpolate(T *mapping, double 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@1038 191 typedef std::map<double, 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@1038 238 virtual int getPositionForValue(double value) const;
Chris@1038 239 virtual int getPositionForValueUnclamped(double value) const;
Chris@885 240
Chris@1038 241 virtual double getValueForPosition(int position) const;
Chris@1038 242 virtual double 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