annotate base/RangeMapper.h @ 880:b4787b595db3

Implement and test the interpolating and auto range mappers
author Chris Cannam
date Fri, 31 Jan 2014 17:09:02 +0000
parents eb6b6a88faed
children 12a6140b3ae0
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@189 28 virtual int getPositionForValue(float value) const = 0;
Chris@189 29 virtual float getValueForPosition(int position) const = 0;
Chris@189 30 virtual QString getUnit() const { return ""; }
Chris@189 31 };
Chris@189 32
Chris@189 33
Chris@189 34 class LinearRangeMapper : public RangeMapper
Chris@189 35 {
Chris@189 36 public:
Chris@879 37 /**
Chris@879 38 * Map values in range minval->maxval linearly into integer range
Chris@879 39 * minpos->maxpos. minval and minpos must be less than maxval and
Chris@879 40 * maxpos respectively. If inverted is true, the range will be
Chris@879 41 * mapped "backwards" (minval to maxpos and maxval to minpos).
Chris@879 42 */
Chris@189 43 LinearRangeMapper(int minpos, int maxpos,
Chris@189 44 float minval, float maxval,
Chris@464 45 QString unit = "", bool inverted = false);
Chris@189 46
Chris@189 47 virtual int getPositionForValue(float value) const;
Chris@189 48 virtual float getValueForPosition(int position) const;
Chris@189 49
Chris@189 50 virtual QString getUnit() const { return m_unit; }
Chris@189 51
Chris@189 52 protected:
Chris@189 53 int m_minpos;
Chris@189 54 int m_maxpos;
Chris@189 55 float m_minval;
Chris@189 56 float m_maxval;
Chris@189 57 QString m_unit;
Chris@464 58 bool m_inverted;
Chris@189 59 };
Chris@189 60
Chris@189 61 class LogRangeMapper : public RangeMapper
Chris@189 62 {
Chris@189 63 public:
Chris@880 64 /**
Chris@880 65 * Map values in range minval->maxval into integer range
Chris@880 66 * minpos->maxpos such that logs of the values are mapped
Chris@880 67 * linearly. minval and minpos must be less than maxval and maxpos
Chris@880 68 * respectively. If inverted is true, the range will be mapped
Chris@880 69 * "backwards" (minval to maxpos and maxval to minpos).
Chris@880 70 */
Chris@189 71 LogRangeMapper(int minpos, int maxpos,
Chris@356 72 float minval, float maxval,
Chris@464 73 QString m_unit = "", bool inverted = false);
Chris@189 74
Chris@356 75 static void convertRatioMinLog(float ratio, float minlog,
Chris@356 76 int minpos, int maxpos,
Chris@356 77 float &minval, float &maxval);
Chris@356 78
Chris@356 79 static void convertMinMax(int minpos, int maxpos,
Chris@356 80 float minval, float maxval,
Chris@356 81 float &ratio, float &minlog);
Chris@356 82
Chris@189 83 virtual int getPositionForValue(float value) const;
Chris@189 84 virtual float getValueForPosition(int position) const;
Chris@189 85
Chris@189 86 virtual QString getUnit() const { return m_unit; }
Chris@189 87
Chris@189 88 protected:
Chris@189 89 int m_minpos;
Chris@189 90 int m_maxpos;
Chris@189 91 float m_ratio;
Chris@189 92 float m_minlog;
Chris@189 93 float m_maxlog;
Chris@189 94 QString m_unit;
Chris@464 95 bool m_inverted;
Chris@189 96 };
Chris@189 97
Chris@880 98 class InterpolatingRangeMapper : public RangeMapper
Chris@880 99 {
Chris@880 100 public:
Chris@880 101 typedef std::map<float, int> CoordMap;
Chris@880 102
Chris@880 103 /**
Chris@880 104 * Given a series of (value, position) coordinate mappings,
Chris@880 105 * construct a range mapper that maps arbitrary values, in the
Chris@880 106 * range between minimum and maximum of the provided values, onto
Chris@880 107 * coordinates using linear interpolation between the supplied
Chris@880 108 * points.
Chris@880 109 *
Chris@880 110 *!!! todo: Cubic -- more generally useful than linear interpolation
Chris@880 111 *!!! todo: inverted flag
Chris@880 112 *
Chris@880 113 * The set of provided mappings must contain at least two
Chris@880 114 * coordinates.
Chris@880 115 *
Chris@880 116 * It is expected that the values and positions in the coordinate
Chris@880 117 * mappings will both be monotonically increasing (i.e. no
Chris@880 118 * inflections in the mapping curve). Behaviour is undefined if
Chris@880 119 * this is not the case.
Chris@880 120 */
Chris@880 121 InterpolatingRangeMapper(CoordMap pointMappings,
Chris@880 122 QString unit);
Chris@880 123
Chris@880 124 virtual int getPositionForValue(float value) const;
Chris@880 125 virtual float getValueForPosition(int position) const;
Chris@880 126
Chris@880 127 virtual QString getUnit() const { return m_unit; }
Chris@880 128
Chris@880 129 protected:
Chris@880 130 CoordMap m_mappings;
Chris@880 131 std::map<int, float> m_reverse;
Chris@880 132 QString m_unit;
Chris@880 133 };
Chris@880 134
Chris@880 135 class AutoRangeMapper : public RangeMapper
Chris@880 136 {
Chris@880 137 public:
Chris@880 138 enum MappingType {
Chris@880 139 Interpolating,
Chris@880 140 StraightLine,
Chris@880 141 Logarithmic,
Chris@880 142 };
Chris@880 143
Chris@880 144 typedef std::map<float, int> CoordMap;
Chris@880 145
Chris@880 146 /**
Chris@880 147 * Given a series of (value, position) coordinate mappings,
Chris@880 148 * construct a range mapper that maps arbitrary values, in the
Chris@880 149 * range between minimum and maximum of the provided values, onto
Chris@880 150 * coordinates.
Chris@880 151 *
Chris@880 152 * The mapping used may be
Chris@880 153 *
Chris@880 154 * Interpolating -- an InterpolatingRangeMapper will be used
Chris@880 155 *
Chris@880 156 * StraightLine -- a LinearRangeMapper from the minimum to
Chris@880 157 * maximum value coordinates will be used, ignoring all other
Chris@880 158 * supplied coordinate mappings
Chris@880 159 *
Chris@880 160 * Logarithmic -- a LogRangeMapper from the minimum to
Chris@880 161 * maximum value coordinates will be used, ignoring all other
Chris@880 162 * supplied coordinate mappings
Chris@880 163 *
Chris@880 164 * The mapping will be chosen automatically by looking at the
Chris@880 165 * supplied coordinates. If the supplied coordinates fall on a
Chris@880 166 * straight line, a StraightLine mapping will be used; if they
Chris@880 167 * fall on a log curve, a Logarithmic mapping will be used;
Chris@880 168 * otherwise an Interpolating mapping will be used.
Chris@880 169 *
Chris@880 170 *!!! todo: inverted flag
Chris@880 171 *
Chris@880 172 * The set of provided mappings must contain at least two
Chris@880 173 * coordinates, or at least three if the points are not supposed
Chris@880 174 * to be in a straight line.
Chris@880 175 *
Chris@880 176 * It is expected that the values and positions in the coordinate
Chris@880 177 * mappings will both be monotonically increasing (i.e. no
Chris@880 178 * inflections in the mapping curve). Behaviour is undefined if
Chris@880 179 * this is not the case.
Chris@880 180 */
Chris@880 181 AutoRangeMapper(CoordMap pointMappings,
Chris@880 182 QString unit);
Chris@880 183
Chris@880 184 ~AutoRangeMapper();
Chris@880 185
Chris@880 186 /**
Chris@880 187 * Return the mapping type in use.
Chris@880 188 */
Chris@880 189 MappingType getType() const { return m_type; }
Chris@880 190
Chris@880 191 virtual int getPositionForValue(float value) const;
Chris@880 192 virtual float getValueForPosition(int position) const;
Chris@880 193
Chris@880 194 virtual QString getUnit() const { return m_unit; }
Chris@880 195
Chris@880 196 protected:
Chris@880 197 MappingType m_type;
Chris@880 198 CoordMap m_mappings;
Chris@880 199 QString m_unit;
Chris@880 200 RangeMapper *m_mapper;
Chris@880 201
Chris@880 202 MappingType chooseMappingTypeFor(const CoordMap &);
Chris@880 203 };
Chris@189 204
Chris@189 205 #endif