File: ccColorScale.h

package info (click to toggle)
cloudcompare 2.10.1-2
  • links: PTS
  • area: main
  • in suites: buster
  • size: 55,916 kB
  • sloc: cpp: 219,837; ansic: 29,944; makefile: 67; sh: 45
file content (323 lines) | stat: -rw-r--r-- 10,565 bytes parent folder | download | duplicates (2)
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
//##########################################################################
//#                                                                        #
//#                              CLOUDCOMPARE                              #
//#                                                                        #
//#  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; version 2 or later of the License.      #
//#                                                                        #
//#  This program is distributed in the hope that it will be useful,       #
//#  but WITHOUT ANY WARRANTY; without even the implied warranty of        #
//#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the          #
//#  GNU General Public License for more details.                          #
//#                                                                        #
//#          COPYRIGHT: EDF R&D / TELECOM ParisTech (ENST-TSI)             #
//#                                                                        #
//##########################################################################

#ifndef CC_COLOR_SCALE_HEADER
#define CC_COLOR_SCALE_HEADER

//Local
#include "ccColorTypes.h"
#include "ccSerializableObject.h"

//Qt
#include <QList>
#include <QSharedPointer>

//System
#include <set>

//! Color scale element: one value + one color
class ccColorScaleElement
{
public:
	
	//! Default constructor
	ccColorScaleElement() : m_relativePos(0.0), m_color(Qt::black) {}

	//! Constructor from a (relative) position and a color
	ccColorScaleElement(double relativePos, QColor color) : m_relativePos(relativePos), m_color(color) {}

	//! Sets associated value (relative to scale boundaries)
	/** \param pos relative position (always between 0.0 and 1.0!)
	**/
	inline void setRelativePos(double pos) { m_relativePos = pos; }
	//! Returns step position (relative to scale boundaries)
	/** \return relative position (always between 0.0 and 1.0!)
	**/
	inline double getRelativePos() const { return m_relativePos; }

	//! Sets color
	inline void setColor(QColor color) { m_color = color; }
	//! Returns color
	inline const QColor& getColor() const { return m_color; }

	//! Comparison operator between two color scale elements
	inline static bool IsSmaller(const ccColorScaleElement& e1, const ccColorScaleElement& e2)
	{
		return e1.getRelativePos() < e2.getRelativePos();
	}

protected:
	
	//! Step (relative) position
	/** Must always be between 0.0 and 1.0!
	**/
	double m_relativePos;
	//! Color
	QColor m_color;
};

//! Color scale
/** A color scale is defined by several 'steps' corresponding to given colors.
	The color between each step is linearly interpolated. A vald color scale
	must have at least 2 steps, one at relative position 0.0 (scale start) and
	one at relative position 1.0 (scale end). Steps can't be defined outside
	this intervale.

	For faster access, a array of interpolated colors is maintained internally.
	Be sure that the 'refresh' method has been called after any modification(s)
	of the scale steps (position or color).
**/
class QCC_DB_LIB_API ccColorScale : public ccSerializableObject
{
public:

	//! Shared pointer type
	typedef QSharedPointer<ccColorScale> Shared;

	//! Creates a new color scale (with auto-generated unique id)
	/** Warning: color scale is relative by default.
	**/
	static ccColorScale::Shared Create(QString name); 

	//! Default constructor
	/** \param name scale name
		\param uuid UUID (automatically generated if none is provided)
		Scale are 'relative' by default (can be changed afterwards, see setAbsolute).
		On construction they already have the two extreme steps defined (at position
		0.0 and 1.0).
	**/
	ccColorScale(QString name, QString uuid = QString());

	//! Destructor
	virtual ~ccColorScale();

	//! Minimum number of steps
	/** \warning Never pass a 'constant initializer' by reference
	**/
	static const unsigned MIN_STEPS = 2;

	//! Default number of steps for display
	/** \warning Never pass a 'constant initializer' by reference
	**/
	static const unsigned DEFAULT_STEPS = 256;

	//! Maximum number of steps (internal representation)
	/** \warning Never pass a 'constant initializer' by reference
	**/
	static const unsigned MAX_STEPS = 1024;

	//! Returns name
	inline const QString& getName() const { return m_name; }
	//! Sets name
	void setName(const QString& name) { m_name = name; }

	//! Returns unique ID
	QString getUuid() const { return m_uuid; }
	//! Sets unique ID
	void setUuid(QString uuid) { m_uuid = uuid; }
	//! Generates a new unique ID
	void generateNewUuid();

	//! Returns whether scale is relative or absoute
	/** Relative means that internal 'values' are percentage.
	**/
	inline bool isRelative() const { return m_relative; }

	//! Sets scale as relative
	inline void setRelative() { m_relative = true; }

	//! Sets scale as absolute
	void setAbsolute(double minVal, double maxVal);

	//! Get absolute scale boundaries
	/** Warning: only valid with absolute scales!
	**/
	void getAbsoluteBoundaries(double& minVal, double& maxVal) const;

	//! Returns whether scale is locked or not
	inline bool isLocked() const { return m_locked; }

	//! Sets whether scale is locked or not
	inline void setLocked(bool state) { m_locked = state; }

	//! Type of a list of custom labels
	typedef std::set<double> LabelSet;

	//! Returns the list of custom labels (if any)
	inline LabelSet& customLabels() { return m_customLabels; }
	//! Returns the list of custom labels (if any - const version)
	inline const LabelSet& customLabels() const { return m_customLabels; }

	//! Sets the list of custom labels (only if the scale is absolute)
	/** \warning May throw std::bad_alloc exception)
	**/
	inline void setCustomLabels(const LabelSet& labels) { m_customLabels = labels; }

	//! Returns the current number of steps
	/** A valid scale should always have at least 2 steps!
	**/
	inline int stepCount() const { return m_steps.size(); }

	//! Access to a given step
	inline ccColorScaleElement& step(int index) { return m_steps[index]; }

	//! Access to a given step (const)
	inline const ccColorScaleElement& step(int index) const { return m_steps[index]; }

	//! Adds a step
	/** Scale must not be locked.
	**/
	void insert(const ccColorScaleElement& step, bool autoUpdate = true);

	//! Deletes a given step
	/** The first and last index shouldn't be deleted!
		Scale must not be locked.
	**/
	void remove(int index, bool autoUpdate = true);

	//! Clears all steps
	/** There should be at least 2 steps for the scale to be valid!
		Scale must not be locked.
	**/
	void clear();

	//! Updates internal representation
	/** Must be called at least once after any modification
		(before using this scale).
	**/
	void update();

	//! Returns relative position of a given value (wrt to scale absolute min and max)
	/** Warning: only valid with absolute scales! Use 'getColorByRelativePos' otherwise.
	**/
	inline double getRelativePosition(double value) const
	{
		assert(m_updated && !m_relative);
		return (value - m_absoluteMinValue) / m_absoluteRange;
	}

	//! Returns color by value
	/** Warning: only valid with absolute scales!
		\param value value
		\param outOfRangeColor default color to return if relativePos if out of [0;1]
		\return corresponding color
	**/
	inline const ccColor::Rgb* getColorByValue(double value, const ccColor::Rgb* outOfRangeColor = nullptr) const
	{
		assert(m_updated && !m_relative);
		double relativePos = getRelativePosition(value);
		return (relativePos >= 0.0 && relativePos <= 1.0 ? getColorByRelativePos(relativePos) : outOfRangeColor);
	}

	//! Returns color by relative position in scale
	/** \param relativePos relative position (should be in [0;1])
		\param outOfRangeColor default color to return if relativePos if out of [0;1]
		\return corresponding color
	**/
	inline const ccColor::Rgb* getColorByRelativePos(double relativePos, const ccColor::Rgb* outOfRangeColor = nullptr) const
	{
		assert(m_updated);
		if (relativePos >= 0.0 && relativePos <= 1.0)
			return &getColorByIndex(static_cast<unsigned>(relativePos * (MAX_STEPS - 1)));
		else
			return outOfRangeColor;
	}

	//! Returns color by relative position in scale with a given 'resolution'
	/** \param relativePos relative position (must be between 0 and 1!)
		\param steps desired resolution (must be greater than 1 and smaller than MAX_STEPS)
		\param outOfRangeColor default color to return if relativePos if out of [0;1]
		\return corresponding color
	**/
	inline const ccColor::Rgb* getColorByRelativePos(double relativePos, unsigned steps, const ccColor::Rgb* outOfRangeColor = nullptr) const
	{
		assert(m_updated);
		if (relativePos >= 0.0 && relativePos <= 1.0)
		{
			//quantized (16 bits) version --> much faster than floor!
			unsigned index = (static_cast<unsigned>((relativePos*steps)*65535.0)) >> 16;
			return &getColorByIndex((index*(MAX_STEPS - 1)) / steps);
		}
		else
		{
			return outOfRangeColor;
		}
	}

	//! Returns color by index
	/** \param index color index in m_rgbaScale array (must be below MAX_STEPS)
		\return corresponding color
	**/
	inline const ccColor::Rgb& getColorByIndex(unsigned index) const
	{
		assert(m_updated && index < MAX_STEPS);
		return m_rgbaScale[index];
	}

	//! Saves this color scale as an XML file
	bool saveAsXML(QString filename) const;
	//! Loads a color scale from an XML file
	static Shared LoadFromXML(QString filename);

	//inherited from ccSerializableObject
	virtual bool isSerializable() const { return true; }
	virtual bool toFile(QFile& out) const;
	virtual bool fromFile(QFile& in, short dataVersion, int flags);

protected:

	//! Sort elements
	void sort();

	//! Name
	QString m_name;

	//! Unique ID
	QString m_uuid;

	//! Elements
	QList<ccColorScaleElement> m_steps;

	//! Internal representation (RGB)
	ccColor::Rgb m_rgbaScale[MAX_STEPS];

	//! Internal representation validity
	bool m_updated;

	//! Whether scale is relative or not
	bool m_relative;

	//! Whether scale is locked or not
	bool m_locked;

	//! 'Absolute' minimum value
	/** Only used if scale is 'absolute' (i.e. not relative).
		'Absolute' should not be taken in its mathematical meaning!
	**/
	double m_absoluteMinValue;

	//! 'Absolute' range
	/** Only used if scale is 'absolute' (i.e. not relative).
		'Absolute' should not be taken in its mathematical meaning!
	**/
	double m_absoluteRange;

	//! List of custom labels
	LabelSet m_customLabels;
};

#endif //CC_COLOR_SCALE_HEADER