#pragma once //########################################################################## //# # //# 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) # //# # //########################################################################## //CCCoreLib #include //qCC_db #include "ccColorScale.h" //! A scalar field associated to display-related parameters /** Extends the CCCoreLib::ScalarField object. **/ class QCC_DB_LIB_API ccScalarField : public CCCoreLib::ScalarField, public ccSerializableObject { public: //! Default constructor /** \param name scalar field name **/ explicit ccScalarField(const std::string& name = std::string()); //! Copy constructor /** \param sf scalar field to copy \warning May throw a std::bad_alloc exception **/ ccScalarField(const ccScalarField& sf); /*** Scalar values display handling ***/ //! Scalar field range structure class QCC_DB_LIB_API Range { public: //! Default constructor Range() : m_min(0), m_start(0), m_stop(0), m_max(0), m_range(1) {} //getters inline ScalarType min() const { return m_min; } inline ScalarType start() const { return m_start; } inline ScalarType stop() const { return m_stop; } inline ScalarType max() const { return m_max; } inline ScalarType range() const { return m_range; } inline ScalarType maxRange() const { return m_max-m_min; } //setters void setBounds(ScalarType minVal, ScalarType maxVal, bool resetStartStop = true) { assert(std::isnan(minVal) || std::isnan(maxVal) || minVal <= maxVal); m_min = minVal; m_max = maxVal; if (resetStartStop) { m_start = m_min; m_stop = m_max; } else { m_start = inbound(m_start); m_stop = inbound(m_stop); } updateRange(); } inline void setStart(ScalarType value) { m_start = inbound(value); if (m_stop < m_start) m_stop = m_start; updateRange(); } inline void setStop(ScalarType value) { m_stop = inbound(value); if (m_stop < m_start) m_start = m_stop; updateRange(); } //! Returns the nearest inbound value inline ScalarType inbound(ScalarType val) const { return (val < m_min ? m_min : (val > m_max ? m_max : val)); } //! Returns whether a value is inbound or not inline bool isInbound(ScalarType val) const { return (val >= m_min && val <= m_max); } //! Returns whether a value is inside range or not inline bool isInRange(ScalarType val) const { return (val >= m_start && val <= m_stop); } protected: //! Updates actual range inline void updateRange() { m_range = std::max(m_stop - m_start, CCCoreLib::ZERO_TOLERANCE_SCALAR); } ScalarType m_min; /**< Minimum value **/ ScalarType m_start; /**< Current start value (in [min,max]) **/ ScalarType m_stop; /**< Current stop value (in [min,max]) **/ ScalarType m_max; /**< Minimum value **/ ScalarType m_range; /**< Actual range: start-stop (but can't be ZERO!) **/ }; //! Access to the range of displayed values /** Values outside of the [start;stop] interval will either be grey or invisible (see showNaNValuesInGrey). **/ inline const Range& displayRange() const { return m_displayRange; } //! Access to the range of saturation values /** Relative color scales will only be applied to values inside the [start;stop] interval. **/ inline const Range& saturationRange() const { return m_logScale ? m_logSaturationRange : m_saturationRange; } //! Access to the range of log scale saturation values /** Relative color scales will only be applied to values inside the [start;stop] interval. **/ inline const Range& logSaturationRange() const { return m_logSaturationRange; } //! Sets the minimum displayed value void setMinDisplayed(ScalarType val); //! Sets the maximum displayed value void setMaxDisplayed(ScalarType val); //! Sets the value at which to start color gradient void setSaturationStart(ScalarType val); //! Sets the value at which to stop color gradient void setSaturationStop(ScalarType val); //! Returns the color corresponding to a given value (wrt to the current display parameters) /** Warning: must no be called if the SF is not associated to a color scale! **/ inline const ccColor::Rgb* getColor(ScalarType value) const { assert(m_colorScale); return m_colorScale->getColorByRelativePos(normalize(value), m_colorRampSteps, m_showNaNValuesInGrey ? &ccColor::lightGreyRGB : nullptr); } //! Shortcut to getColor inline const ccColor::Rgb* getValueColor(unsigned index) const { return getColor(getValue(index)); } //! Sets whether NaN/out of displayed range values should be displayed in grey or hidden void showNaNValuesInGrey(bool state); //! Returns whether NaN values are displayed in grey or hidden inline bool areNaNValuesShownInGrey() const { return m_showNaNValuesInGrey; } //! Sets whether 0 should always appear in associated color ramp or not void alwaysShowZero(bool state); //! Returns whether 0 should always appear in associated color ramp or not inline bool isZeroAlwaysShown() const { return m_alwaysShowZero; } //! Sets whether the color scale should be symmetrical or not /** For relative color scales only. **/ void setSymmetricalScale(bool state); //! Returns whether the color scale s symmetrical or not /** For relative color scales only. **/ inline bool symmetricalScale() const { return m_symmetricalScale; } //! Sets whether scale is logarithmic or not void setLogScale(bool state); //! Returns whether scalar field is logarithmic or not inline bool logScale() const { return m_logScale; } //inherited void computeMinAndMax() override; //! Returns associated color scale inline const ccColorScale::Shared& getColorScale() const { return m_colorScale; } //! Sets associated color scale void setColorScale(ccColorScale::Shared scale); //! Returns number of color ramp steps inline unsigned getColorRampSteps() const { return m_colorRampSteps; } //! Sets number of color ramp steps used for display void setColorRampSteps(unsigned steps); //! Simple histogram structure struct Histogram : std::vector { //! Max histogram value unsigned maxValue = 0; }; //! Returns associated histogram values (for display) inline const Histogram& getHistogram() const { return m_histogram; } //! Returns whether the scalar field in its current configuration MAY have 'hidden' values or not /** 'Hidden' values are typically NaN values or values outside of the 'displayed' interval while those values are not displayed in grey (see ccScalarField::showNaNValuesInGrey). **/ bool mayHaveHiddenValues() const; //! Sets modification flag state inline void setModificationFlag(bool state) { m_modified = state; } //! Returns modification flag state inline bool getModificationFlag() const { return m_modified; } //! Imports the parameters from another scalar field void importParametersFrom(const ccScalarField* sf); //inherited from ccSerializableObject inline bool isSerializable() const override { return true; } bool toFile(QFile& out, short dataVersion) const override; bool fromFile(QFile& in, short dataVersion, int flags, LoadedIDMap& oldToNewIDMap) override; short minimumFileVersion() const override; protected: //methods //! Default destructor /** Call release instead **/ ~ccScalarField() override = default; //! Updates saturation values void updateSaturationBounds(); //! Normalizes a scalar value between 0 and 1 (wrt to current parameters) /** \param val scalar value \return a number between 0 and 1 if inside displayed range or -1 otherwise **/ ScalarType normalize(ScalarType val) const; protected: //members //! Displayed values range Range m_displayRange; //! Saturation values range /** For color mapping with relative scales. **/ Range m_saturationRange; //! saturation values range (log scale mode) /** For log scale color mapping with relative scales. **/ Range m_logSaturationRange; //! Whether NaN values are shown in grey or are hidden bool m_showNaNValuesInGrey; //! Whether color scale is symmetrical or not /** For relative color scales only. **/ bool m_symmetricalScale; //! Whether scale is logarithmic or not bool m_logScale; //! Whether 0 should always appear in associated color ramp bool m_alwaysShowZero; //! Active color ramp (for display) ccColorScale::Shared m_colorScale; //! Number of color ramps steps (for display) unsigned m_colorRampSteps; //! Associated histogram values (for display) Histogram m_histogram; //! Modification flag /** Any modification to the scalar field values or parameters will turn this flag on. **/ bool m_modified; };