16#include <unordered_map>
20RPalette::RPalette(
bool interpolate,
bool knownNormalized,
const std::vector<RPalette::OrdinalAndColor> &
points)
21 : fColors(
points), fInterpolate(interpolate), fNormalized(knownNormalized)
24 throw std::runtime_error(
"Must have at least two points to build a palette!");
28 if (!knownNormalized) {
30 double high =
fColors.back().fOrdinal;
31 double low =
fColors.front().fOrdinal;
32 double prec = (high - low) * 1
e-8;
34 auto reasonablyEqual = [&](
double val,
double expected) ->
bool {
return std::fabs(val - expected) < prec; };
35 fNormalized = reasonablyEqual(low, 0.) && reasonablyEqual(high, 1.);
40static std::vector<RPalette::OrdinalAndColor> AddOrdinals(
const std::vector<RColor> &
points)
42 std::vector<RPalette::OrdinalAndColor> ret(
points.size());
44 return {1. / (
points.size() - 1) * (&col -
points.data()), col};
46 std::transform(
points.begin(),
points.end(), ret.begin(), addOneOrdinal);
70 auto iColor2 = std::lower_bound(
fColors.begin(),
fColors.end(), ordinal);
71 auto iColor1 = iColor2 - 1;
73 auto diff1 = ordinal - iColor1->fOrdinal;
74 auto diff2 = iColor2->fOrdinal - ordinal;
82 return iColor1->fColor;
85 return iColor2->fColor;
88 auto dist = diff1 + diff2;
89 auto rgba1 = iColor1->fColor.AsRGBA();
90 auto rgba2 = iColor2->fColor.AsRGBA();
91 if ((
dist >
epsilon) && (rgba1.size() > 2) && (rgba2.size() > 2)) {
92 if (rgba1.size() == 4)
93 rgba2.resize(4, 0xff);
94 else if (rgba2.size() == 4)
95 rgba1.resize(4, 0xff);
97 for (
unsigned i = 0; i < rgba1.size(); ++i)
98 rgba1[i] = (
uint8_t) std::lround( (diff2*rgba1[i] + diff1*rgba2[i]) /
dist);
101 res.
SetRGB(rgba1[0], rgba1[1], rgba1[2]);
102 if (rgba1.size() == 4)
111 return (diff2 < diff1) ? iColor2->fColor : iColor1->fColor;
115using GlobalPalettes_t = std::unordered_map<std::string, RPalette>;
116static GlobalPalettes_t CreateDefaultPalettes()
118 GlobalPalettes_t ret;
130static GlobalPalettes_t &GetGlobalPalettes()
132 static GlobalPalettes_t globalPalettes = CreateDefaultPalettes();
133 return globalPalettes;
139 GetGlobalPalettes()[std::string(
name)] = palette;
144 static const RPalette sNoPaletteWithThatName;
146 auto iGlobalPalette = GetGlobalPalettes().find(std::string(
name));
147 if (iGlobalPalette == GetGlobalPalettes().end())
148 return sNoPaletteWithThatName;
149 return iGlobalPalette->second;
#define R__ERROR_HERE(GROUP)
static constexpr RGB_t kRed
void SetRGB(const RGB_t &rgb)
Set r/g/b components of color.
static constexpr RGB_t kWhite
static constexpr RGB_t kBlack
static constexpr RGB_t kBlue
void SetAlpha(uint8_t alpha)
Set alpha as value from range 0..255.
static void RegisterPalette(std::string_view name, const RPalette &palette)
Register a palette in the set of global palettes, making it available to GetPalette().
RColor GetColor(double ordinal)
Get the color associated with the ordinal value.
std::vector< OrdinalAndColor > fColors
Palette colors: the color points and their ordinal value.
static const RPalette & GetPalette(std::string_view name="")
Get a global palette by name.
bool fNormalized
Whether the palette's ordinal numbers are normalized.
bool IsGradient() const
Whether the palette is a smooth gradient generated by interpolating between the color points.
basic_string_view< char > string_view
double dist(Rotation3D const &r1, Rotation3D const &r2)
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
An ordinal value and its associated color.