486 lines
14 KiB
C++
486 lines
14 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library 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 Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
#ifndef APP_COLORMODEL_H
|
|
#define APP_COLORMODEL_H
|
|
|
|
#include "Material.h"
|
|
|
|
#include <algorithm>
|
|
#include <deque>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#define CCR_EPS 1.0e-5f
|
|
|
|
namespace App
|
|
{
|
|
|
|
/**
|
|
* Abstract base class that calculates the matching RGB color to a given value.
|
|
*/
|
|
class AppExport ValueFloatToRGB
|
|
{
|
|
public:
|
|
virtual Color getColor(float fVal) const = 0;
|
|
|
|
protected:
|
|
ValueFloatToRGB (void) {}
|
|
virtual ~ValueFloatToRGB () {}
|
|
};
|
|
|
|
|
|
class AppExport ColorModel
|
|
{
|
|
public:
|
|
ColorModel (unsigned short usCt);
|
|
ColorModel (const ColorModel &rclM);
|
|
virtual ~ColorModel ();
|
|
ColorModel& operator = (const ColorModel &rclM);
|
|
unsigned short _usColors;
|
|
Color *_pclColors;
|
|
};
|
|
|
|
class AppExport ColorModelTria : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelTria (void) : ColorModel(5)
|
|
{
|
|
_pclColors[0] = Color( 0, 0, 1);
|
|
_pclColors[1] = Color( 0, 1, 1);
|
|
_pclColors[2] = Color( 0, 1, 0);
|
|
_pclColors[3] = Color( 1, 1, 0);
|
|
_pclColors[4] = Color( 1, 0, 0);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorModelTriaBottom : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelTriaBottom (void) : ColorModel(3)
|
|
{
|
|
_pclColors[0] = Color( 0, 0, 1);
|
|
_pclColors[1] = Color( 0, 1, 1);
|
|
_pclColors[2] = Color( 0, 1, 0);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorModelTriaTop : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelTriaTop (void) : ColorModel(3)
|
|
{
|
|
_pclColors[0] = Color( 0, 1, 0);
|
|
_pclColors[1] = Color( 1, 1, 0);
|
|
_pclColors[2] = Color( 1, 0, 0);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorModelInverseTria : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelInverseTria (void) : ColorModel(5)
|
|
{
|
|
_pclColors[0] = Color( 1, 0, 0);
|
|
_pclColors[1] = Color( 1, 1, 0);
|
|
_pclColors[2] = Color( 0, 1, 0);
|
|
_pclColors[3] = Color( 0, 1, 1);
|
|
_pclColors[4] = Color( 0, 0, 1);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorModelInverseTriaTop : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelInverseTriaTop (void) : ColorModel(3)
|
|
{
|
|
_pclColors[2] = Color( 0, 0, 1);
|
|
_pclColors[1] = Color( 0, 1, 1);
|
|
_pclColors[0] = Color( 0, 1, 0);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorModelInverseTriaBottom : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelInverseTriaBottom (void) : ColorModel(3)
|
|
{
|
|
_pclColors[2] = Color( 0, 1, 0);
|
|
_pclColors[1] = Color( 1, 1, 0);
|
|
_pclColors[0] = Color( 1, 0, 0);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorModelGray : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelGray (void) : ColorModel(2)
|
|
{
|
|
_pclColors[0] = Color( 0, 0, 0);
|
|
_pclColors[1] = Color( 1, 1, 1);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorModelGrayBottom : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelGrayBottom (void) : ColorModel(2)
|
|
{
|
|
_pclColors[0] = Color( 0.0f, 0.0f, 0.0f);
|
|
_pclColors[1] = Color( 0.5f, 0.5f, 0.5f);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorModelGrayTop : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelGrayTop (void) : ColorModel(2)
|
|
{
|
|
_pclColors[0] = Color( 0.5f, 0.5f, 0.5f);
|
|
_pclColors[1] = Color( 1.0f, 1.0f, 1.0f);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorModelInverseGray : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelInverseGray (void) : ColorModel(2)
|
|
{
|
|
_pclColors[0] = Color( 1, 1, 1);
|
|
_pclColors[1] = Color( 0, 0, 0);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorModelInverseGrayBottom : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelInverseGrayBottom (void) : ColorModel(2)
|
|
{
|
|
_pclColors[0] = Color( 1.0f, 1.0f, 1.0f);
|
|
_pclColors[1] = Color( 0.5f, 0.5f, 0.5f);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorModelInverseGrayTop : public ColorModel
|
|
{
|
|
public:
|
|
ColorModelInverseGrayTop (void) : ColorModel(2)
|
|
{
|
|
_pclColors[0] = Color( 0.5f, 0.5f, 0.5f);
|
|
_pclColors[1] = Color( 0.0f, 0.0f, 0.0f);
|
|
}
|
|
};
|
|
|
|
class AppExport ColorField
|
|
{
|
|
public:
|
|
ColorField (void);
|
|
ColorField (const ColorField &rclCF);
|
|
ColorField (const ColorModel &rclModel, float fMin, float fMax, unsigned short usCt);
|
|
virtual ~ColorField ();
|
|
|
|
ColorField& operator = (const ColorField &rclCF);
|
|
|
|
unsigned short getCountColors (void) const { return _usCtColors; }
|
|
void set (const ColorModel &rclModel, float fMin, float fMax, unsigned short usCt);
|
|
void setCountColors (unsigned short usCt) { set(_clModel, _fMin, _fMax, usCt); }
|
|
void setRange (float fMin, float fMax) { set(_clModel, fMin, fMax, _usCtColors); }
|
|
void getRange (float &rfMin, float &rfMax) { rfMin = _fMin; rfMax = _fMax; }
|
|
unsigned short getMinColors (void) const { return _clModel._usColors; }
|
|
void setColorModel (const ColorModel &rclModel);
|
|
const ColorModel& getColorModel (void) const { return _clModel; }
|
|
void setDirect (unsigned short usInd, Color clCol) { _aclField[usInd] = clCol; }
|
|
float getMinValue (void) const { return _fMin; }
|
|
float getMaxValue (void) const { return _fMax; }
|
|
|
|
Color getColor (unsigned short usIndex) const { return _aclField[usIndex]; }
|
|
inline Color getColor (float fVal) const;
|
|
inline unsigned short getColorIndex (float fVal) const;
|
|
|
|
protected:
|
|
ColorModel _clModel;
|
|
float _fMin, _fMax;
|
|
float _fAscent, _fConstant; // Index := _fConstant + _fAscent * WERT
|
|
unsigned short _usCtColors;
|
|
std::vector<Color> _aclField;
|
|
|
|
void rebuild (void);
|
|
void interpolate (Color clCol1, unsigned short usPos1, Color clCol2, unsigned short usPos2);
|
|
};
|
|
|
|
inline Color ColorField::getColor (float fVal) const
|
|
{
|
|
#if 1
|
|
// if the value is outside or at the border of the range
|
|
unsigned short ct = _clModel._usColors-1;
|
|
if ( fVal <= _fMin )
|
|
return _clModel._pclColors[0];
|
|
else if ( fVal >= _fMax )
|
|
return _clModel._pclColors[ct];
|
|
|
|
// get the color field position (with 0 < t < 1)
|
|
float t = (fVal-_fMin) / (_fMax-_fMin);
|
|
Color col(1.0f, 1.0f, 1.0f); // white as default
|
|
for ( unsigned short i=0; i<ct; i++ )
|
|
{
|
|
float r = (float)(i+1)/(float)ct;
|
|
if ( t < r )
|
|
{
|
|
// calculate the exact position in the subrange
|
|
float s = t*(float)ct-(float)i;
|
|
Color c1 = _clModel._pclColors[i];
|
|
Color c2 = _clModel._pclColors[i+1];
|
|
col.r = (1.0f-s) * c1.r + s * c2.r;
|
|
col.g = (1.0f-s) * c1.g + s * c2.g;
|
|
col.b = (1.0f-s) * c1.b + s * c2.b;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return col;
|
|
#else
|
|
return _aclField[getColorIndex(fVal)];
|
|
#endif
|
|
}
|
|
|
|
inline unsigned short ColorField::getColorIndex (float fVal) const
|
|
{
|
|
return (unsigned short)(std::min<int>(std::max<int>(int(_fConstant + _fAscent * fVal), 0), int(_usCtColors-1)));
|
|
}
|
|
|
|
|
|
class AppExport ColorGradient
|
|
{
|
|
public:
|
|
enum TStyle { FLOW, ZERO_BASED };
|
|
enum TColorModel { TRIA, INVERSE_TRIA, GRAY, INVERSE_GRAY };
|
|
|
|
ColorGradient (void);
|
|
ColorGradient (float fMin, float fMax, unsigned short usCtColors, TStyle tS, bool bOG = false);
|
|
ColorGradient (const ColorGradient &rclCR);
|
|
|
|
ColorGradient& operator = (const ColorGradient &rclCR);
|
|
|
|
void set (float fMin, float fMax, unsigned short usCt, TStyle tS, bool bOG);
|
|
void setRange (float fMin, float fMax) { set(fMin, fMax, _usCtColors, _tStyle, _bOutsideGrayed); }
|
|
void getRange (float &rfMin, float &rfMax) const { rfMin = _fMin; rfMax = _fMax; }
|
|
unsigned short getCountColors (void) const { return _usCtColors; }
|
|
void setCountColors (unsigned short usCt) { set(_fMin, _fMax, usCt, _tStyle, _bOutsideGrayed); }
|
|
void setStyle (TStyle tS) { set(_fMin, _fMax, _usCtColors, tS, _bOutsideGrayed); }
|
|
unsigned short getMinColors (void) const;
|
|
TStyle getStyle (void) const { return _tStyle; }
|
|
void setOutsideGrayed (bool bGrayed) { _bOutsideGrayed = bGrayed; }
|
|
bool isOutsideGrayed (void) const { return _bOutsideGrayed; }
|
|
void setColorModel (TColorModel tModel);
|
|
TColorModel getColorModelType (void) const { return _tColorModel; }
|
|
inline const ColorModel& getColorModel (void) const;
|
|
float getMinValue (void) const { return _fMin; }
|
|
float getMaxValue (void) const { return _fMax; }
|
|
|
|
inline Color getColor (float fVal) const;
|
|
inline unsigned short getColorIndex (float fVal) const;
|
|
|
|
protected:
|
|
ColorField _clColFld1, _clColFld2;
|
|
TColorModel _tColorModel;
|
|
TStyle _tStyle;
|
|
float _fMin, _fMax;
|
|
unsigned short _usCtColors;
|
|
bool _bOutsideGrayed;
|
|
ColorModel _clTotal, _clTop, _clBottom;
|
|
|
|
void rebuild (void);
|
|
void setColorModel (void);
|
|
};
|
|
|
|
|
|
class AppExport ColorLegend
|
|
{
|
|
public:
|
|
ColorLegend (void);
|
|
ColorLegend (const ColorLegend &rclCL);
|
|
virtual ~ColorLegend () {}
|
|
|
|
ColorLegend& operator = (const ColorLegend &rclCL);
|
|
bool operator == (const ColorLegend &rclCL) const;
|
|
bool operator != (const ColorLegend &rclCL) const { return !(*this == rclCL); }
|
|
|
|
void resize (unsigned long ulN);
|
|
bool addMin (const std::string &rclName);
|
|
bool addMax (const std::string &rclName);
|
|
bool remove (unsigned long ulPos);
|
|
void removeFirst (void);
|
|
void removeLast (void);
|
|
|
|
Color getColor (unsigned long ulPos) const;
|
|
uint32_t getPackedColor (unsigned long ulPos) const;
|
|
bool setColor (unsigned long ulPos, float ucRed, float ucGreen, float ucBlue);
|
|
bool setColor (unsigned long ulPos, unsigned long ulColor);
|
|
float getValue (unsigned long ulPos) const;
|
|
bool setValue (unsigned long ulPos, float fVal);
|
|
std::string getText (unsigned long ulPos) const;
|
|
bool setText (unsigned long ulPos, const std::string &rclName);
|
|
unsigned long hasNumberOfFields (void) const { return (unsigned long)_aclColorFields.size(); }
|
|
void setOutsideGrayed (bool bOS) { _bOutsideGrayed = bOS; }
|
|
bool isOutsideGrayed (void) const { return _bOutsideGrayed; }
|
|
inline float getMinValue (void) const;
|
|
inline float getMaxValue (void) const;
|
|
|
|
inline Color getColor (float fVal) const;
|
|
inline unsigned short getColorIndex (float fVal) const;
|
|
|
|
protected:
|
|
std::deque<Color> _aclColorFields;
|
|
std::deque<std::string> _aclNames;
|
|
std::deque<float> _aclValues;
|
|
bool _bOutsideGrayed;
|
|
};
|
|
|
|
inline Color ColorLegend::getColor (float fVal) const
|
|
{
|
|
std::deque<float>::const_iterator pI;
|
|
for (pI = _aclValues.begin(); pI != _aclValues.end(); ++pI)
|
|
{
|
|
if (fVal < *pI)
|
|
break;
|
|
}
|
|
|
|
if (_bOutsideGrayed == true)
|
|
{
|
|
if ((pI == _aclValues.begin()) || (pI == _aclValues.end()))
|
|
return Color(0.5f, 0.5f, 0.5f);
|
|
else
|
|
return _aclColorFields[pI - _aclValues.begin() - 1];
|
|
}
|
|
|
|
if (pI == _aclValues.begin())
|
|
return *_aclColorFields.begin();
|
|
else if (pI == _aclValues.end())
|
|
return *(_aclColorFields.end()-1);
|
|
else
|
|
return _aclColorFields[pI - _aclValues.begin() - 1];
|
|
}
|
|
|
|
inline unsigned short ColorLegend::getColorIndex (float fVal) const
|
|
{
|
|
std::deque<float>::const_iterator pI;
|
|
for (pI = _aclValues.begin(); pI != _aclValues.end(); ++pI)
|
|
{
|
|
if (fVal < *pI)
|
|
break;
|
|
}
|
|
|
|
if (pI == _aclValues.begin())
|
|
return 0;
|
|
else if (pI == _aclValues.end())
|
|
return (unsigned short)(_aclColorFields.size() - 1);
|
|
else
|
|
return pI - _aclValues.begin() - 1;
|
|
}
|
|
|
|
inline float ColorLegend::getMinValue (void) const
|
|
{
|
|
return *_aclValues.begin();
|
|
}
|
|
|
|
inline float ColorLegend::getMaxValue (void) const
|
|
{
|
|
return *(_aclValues.end()-1);
|
|
}
|
|
|
|
inline Color ColorGradient::getColor (float fVal) const
|
|
{
|
|
if (_bOutsideGrayed == true)
|
|
{
|
|
if ((fVal < _fMin) || (fVal > _fMax))
|
|
return Color(0.5f, 0.5f, 0.5f);
|
|
}
|
|
switch (_tStyle)
|
|
{
|
|
case ZERO_BASED:
|
|
{
|
|
if ((_fMin < 0.0f) && (_fMax > 0.0f))
|
|
{
|
|
if (fVal < 0.0f)
|
|
return _clColFld1.getColor(fVal);
|
|
else
|
|
return _clColFld2.getColor(fVal);
|
|
}
|
|
else
|
|
return _clColFld1.getColor(fVal);
|
|
}
|
|
|
|
default:
|
|
case FLOW:
|
|
{
|
|
return _clColFld1.getColor(fVal);
|
|
}
|
|
}
|
|
}
|
|
|
|
inline unsigned short ColorGradient::getColorIndex (float fVal) const
|
|
{
|
|
switch (_tStyle)
|
|
{
|
|
case ZERO_BASED:
|
|
{
|
|
if ((_fMin < 0.0f) && (_fMax > 0.0f))
|
|
{
|
|
if (fVal < 0.0f)
|
|
return _clColFld1.getColorIndex(fVal);
|
|
else
|
|
return (unsigned short)(_clColFld1.getCountColors() + _clColFld2.getColorIndex(fVal));
|
|
}
|
|
else
|
|
return _clColFld1.getColorIndex(fVal);
|
|
}
|
|
|
|
default:
|
|
case FLOW:
|
|
{
|
|
return _clColFld1.getColorIndex(fVal);
|
|
}
|
|
}
|
|
}
|
|
|
|
inline const ColorModel& ColorGradient::getColorModel (void) const
|
|
{
|
|
if ( _tStyle == ZERO_BASED )
|
|
{
|
|
if ( _fMax <= 0.0f )
|
|
return _clBottom;
|
|
else if ( _fMin >= 0.0f )
|
|
return _clTop;
|
|
else
|
|
return _clTotal;
|
|
}
|
|
else
|
|
{
|
|
return _clTotal;
|
|
}
|
|
}
|
|
|
|
} // namespace App
|
|
|
|
#endif // APP_COLORMODEL_H
|