Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RPalette.hxx
Go to the documentation of this file.
1 /*************************************************************************
2  * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. *
3  * All rights reserved. *
4  * *
5  * For the licensing terms see $ROOTSYS/LICENSE. *
6  * For the list of contributors see $ROOTSYS/README/CREDITS. *
7  *************************************************************************/
8 
9 #ifndef ROOT7_RPalette
10 #define ROOT7_RPalette
11 
12 #include <ROOT/RStringView.hxx>
13 #include <ROOT/RColor.hxx>
14 
15 #include <utility>
16 #include <vector>
17 
18 namespace ROOT {
19 namespace Experimental {
20 
21 /** \class RPalette
22 \ingroup GpadROOT7
23 \brief A set of colors. `RColor`s can be conveniently generated from this.
24 
25  A palette associates a color with an ordinal number: for a normalized palette,
26  this number ranges from 0..1. For user-valued palettes, the palette yields a color for
27  user-coordinates (for instance histogram content), in an arbitrary range.
28 
29  A palette can be a smooth gradients by interpolation of support points, or a set of
30  discrete colors.
31 
32 \author Axel Naumann <axel@cern.ch>
33 \date 2017-09-26
34 \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
35 
36 */
37 
38 class RPalette {
39 public:
40  /// An ordinal value and its associated color.
41  struct OrdinalAndColor {
42  double fOrdinal; ///< The value associated with the color.
43  RColor fColor; ///< The color associated with the value.
44 
45  /// Compare two `OrdinalAndColor`s, for sorting.
46  friend bool operator<(const OrdinalAndColor &lhs, const OrdinalAndColor &rhs)
47  {
48  return lhs.fOrdinal < rhs.fOrdinal;
49  }
50  /// Compare an `OrdinalAndColor` and an ordinal value.
51  friend bool operator<(const OrdinalAndColor &lhs, double rhs) { return lhs.fOrdinal < rhs; }
52  };
53 
54 private:
55  /// Palette colors: the color points and their ordinal value.
56  std::vector<OrdinalAndColor> fColors;
57 
58  /// Whether to interpolate between the colors (in contrast to picking one of fColors).
59  bool fInterpolate = true;
60 
61  /// Whether the palette's ordinal numbers are normalized.
62  bool fNormalized = true;
63 
64  RPalette(bool interpolate, bool knownNormalized, const std::vector<OrdinalAndColor> &points);
65  RPalette(bool interpolate, const std::vector<RColor> &points);
66 
67 public:
68  /// Tag type used to signal that the palette's colors should not be interpolated.
69  struct Discrete_t {
70  };
71 
72  /// Tag value used to signal that the palette's colors should not be interpolated. Can be passed to the
73  /// constructor: `RPalette palette(RPalette::kDiscrete, {{-100., RColor::kWhite}, {100., RColor::kRed}})`
74  static constexpr const Discrete_t kDiscrete{};
75 
76  RPalette() = default;
77 
78  /// Construct a RPalette from a vector of (ordinal|color) pairs as interpolation points.
79  /// Palette colors will be these points for the ordinal, and interpolated in between the
80  /// ordinal points. The points will be sorted.
81  /// The palette is normalized if the lowest ordinal is 0. and the highest ordinal is 1.;
82  /// otherwise, the palette is a user-valued palette.
83  RPalette(const std::vector<OrdinalAndColor> &interpPoints): RPalette(true, false, interpPoints) {}
84 
85  /// Construct a RPalette from a vector of (ordinal|color) pairs. For a given value, the palette returns
86  /// the color with an ordinal that is closest to the value. The points will be sorted.
87  /// The palette is normalized if the lowest ordinal is 0. and the highest ordinal is 1.;
88  /// otherwise, the palette is a user-valued palette.
89  RPalette(Discrete_t, const std::vector<OrdinalAndColor> &points): RPalette(false, false, points) {}
90 
91  /// Construct a normalized RPalette from a vector of colors as interpolation points. The ordinal associated
92  /// with each color is equidistant from 0..1, i.e. for three colors it will be 0., 0.5 and 1, respectively.
93  /// Palette colors will be these points for the ordinal associated with the color,
94  /// and interpolated in between the ordinal points.
95  RPalette(const std::vector<RColor> &interpPoints): RPalette(true, interpPoints) {}
96 
97  /// Construct a normalized RPalette from a vector of colors. The ordinal associated
98  /// with each color is equidistant from 0..1, i.e. for three colors it will be 0., 0.5 and 1, respectively.
99  /// For a given value, the palette returns the color with an ordinal that is closest to the value.
100  RPalette(Discrete_t, const std::vector<RColor> &points): RPalette(false, points) {}
101 
102  /// Whether the palette is normalized, i.e. covers colors in the ordinal range 0..1.
103  bool IsNormalized() const { return fNormalized; }
104 
105  /// Whether the palette is discrete, i.e. does no interpolation between colors.
106  bool IsDiscrete() const { return !fInterpolate; }
107 
108  /// Whether the palette is a smooth gradient generated by interpolating between the color points.
109  bool IsGradient() const { return fInterpolate; }
110 
111  /// Get the color associated with the ordinal value. The value is expected to be 0..1 for a normalized
112  /// palette.
113  RColor GetColor(double ordinal);
114 
115  ///\{
116  ///\name Global Palettes
117 
118  /// Register a palette in the set of global palettes, making it available to `GetPalette()`.
119  /// This function is not thread safe; any concurrent call to global Palette manipulation must be synchronized!
120  static void RegisterPalette(std::string_view name, const RPalette &palette);
121 
122  /// Get a global palette by name. Returns an empty palette if no palette with that name is known.
123  /// This function is not thread safe; any concurrent call to global Palette manipulation must be synchronized!
124  static const RPalette &GetPalette(std::string_view name);
125 
126  ///\}
127 };
128 
129 } // namespace Experimental
130 } // namespace ROOT
131 
132 #endif