1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Sonic Visualiser
An audio file viewer and annotation editor.
Centre for Digital Music, Queen Mary, University of London.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version. See the file
COPYING included with this distribution for more information.
*/
#ifndef COORDINATE_SCALE_H
#define COORDINATE_SCALE_H
#include <QString>
namespace sv {
class LayerGeometryProvider;
/**
* A facility to map between coordinate and value in a given axis.
* Queries a LayerGeometryProvider to find the proper dimensions for
* its axis direction. A CoordinateScale object is self-contained and
* can be passed around by value.
*
* These are generally only used where a scale is monotonic through
* the visible area of the layer. Currently layers which may have more
* than one scale region (e.g. waveforms, whose y axis may be divided
* into multi-channel regions) or layers whose scale occupies only a
* part of their visible area (e.g. the x axis of spectra) are not
* able to make use of this.
*/
class CoordinateScale
{
public:
enum class FrequencyMap {
Linear,
Mel,
Log
};
enum class Direction {
Horizontal,
Vertical
};
/**
* Construct a continuous linear or logarithmic scale with an
* arbitrary unit and given extents. In the case of a log scale,
* the extents are actual values, not log-values. The display
* extents will be initialised to the same as the value extents.
*/
CoordinateScale(Direction direction, QString unit, bool logarithmic,
double minValue, double maxValue);
/**
* Construct a frequency scale with a given map and extents. The
* extents should be in Hz and the unit of the scale will be
* "Hz". The display extents will be initialised to the same as
* the value extents.
*/
CoordinateScale(Direction direction, FrequencyMap map,
double minValue, double maxValue);
/**
* Construct an integer-valued bin scale with the given
* extents. The extents should be in bin number (zero-based) and
* the unit of the scale will be "bins". The display extents will
* be initialised to the same as the value extents.
*/
CoordinateScale(Direction direction, bool logarithmic,
int minBin, int maxBin);
double getCoordForValue(const LayerGeometryProvider *, double value) const;
int getCoordForValueRounded(const LayerGeometryProvider *, double value) const;
double getValueForCoord(const LayerGeometryProvider *, double coordinate) const;
int getValueForCoordRounded(const LayerGeometryProvider *, double coordinate) const;
Direction getDirection() const { return m_direction; }
QString getUnit() const { return m_unit; }
double getValueMinimum() const { return m_valueMin; }
double getValueMaximum() const { return m_valueMax; }
double getDisplayMinimum() const { return m_displayMin; }
double getDisplayMaximum() const { return m_displayMax; }
CoordinateScale withValueExtents(double min, double max) const;
CoordinateScale withDisplayExtents(double min, double max) const;
CoordinateScale unionWith(const CoordinateScale &other) const;
/**
* Return true if the scale is logarithmic. Note that a scale
* could have any kind of mapping - false does not imply linear.
*/
bool isLogarithmic() const {
if (m_isFrequencyScale) {
return m_frequencyMap == FrequencyMap::Log;
} else {
return m_logarithmic;
}
}
/**
* Return true if the scale is linear. Note that a scale could
* have any kind of mapping - false does not imply logarithmic.
*/
bool isLinear() const {
if (m_isFrequencyScale) {
return m_frequencyMap == FrequencyMap::Linear;
} else {
return !m_logarithmic;
}
}
bool visualRangeMatches(const CoordinateScale &other) const;
private:
Direction m_direction;
bool m_isFrequencyScale;
bool m_isBinScale;
QString m_unit;
bool m_logarithmic;
FrequencyMap m_frequencyMap;
double m_valueMin;
double m_valueMax;
double m_displayMin;
double m_displayMax;
double map(double value) const;
double unmap(double point) const;
void mapExtents(double &min, double &max) const;
};
} // end namespace sv
#endif
|