Reorganize, rename, and complete the set of perceptually linear maps.
authorMartin Lambers <marlam@marlam.de>
Fri, 12 Feb 2016 14:20:19 +0000 (15:20 +0100)
committerMartin Lambers <marlam@marlam.de>
Fri, 12 Feb 2016 14:20:19 +0000 (15:20 +0100)
cmdline.cpp
colormap.cpp
colormap.hpp
colormapwidgets.cpp
colormapwidgets.hpp
gui.cpp
gui.hpp

index 76cee1b..e49702f 100644 (file)
@@ -37,11 +37,13 @@ enum type {
     brewer_seq,
     brewer_div,
     brewer_qual,
-    isolum_seq,
-    isolum_div,
-    isolum_qual,
-    unirainbow,
-    blackbody,
+    plseq_lightness,
+    plseq_saturation,
+    plseq_rainbow,
+    plseq_blackbody,
+    pldiv_lightness,
+    pldiv_saturation,
+    plqual_hue,
     cubehelix,
     moreland,
     mcnames
@@ -59,7 +61,7 @@ int main(int argc, char* argv[])
     float saturation = -1.0f;
     float brightness = -1.0f;
     float warmth = -1.0f;
-    float luminance = -1.0f;
+    float lightness = -1.0f;
     float rotations = NAN;
     float temperature = -1.0f;
     float range = -1.0f;
@@ -80,7 +82,7 @@ int main(int argc, char* argv[])
         { "saturation",  required_argument, 0, 's' },
         { "brightness",  required_argument, 0, 'b' },
         { "warmth",      required_argument, 0, 'w' },
-        { "luminance",   required_argument, 0, 'l' },
+        { "lightness",   required_argument, 0, 'l' },
         { "rotations",   required_argument, 0, 'r' },
         { "temperature", required_argument, 0, 'T' },
         { "range",       required_argument, 0, 'R' },
@@ -106,11 +108,13 @@ int main(int argc, char* argv[])
             type = (strcmp(optarg, "brewer-sequential") == 0 ? brewer_seq
                     : strcmp(optarg, "brewer-diverging") == 0 ? brewer_div
                     : strcmp(optarg, "brewer-qualitative") == 0 ? brewer_qual
-                    : strcmp(optarg, "isoluminant-sequential") == 0 ? isolum_seq
-                    : strcmp(optarg, "isoluminant-divergent") == 0 ? isolum_div
-                    : strcmp(optarg, "isoluminant-qualitative") == 0 ? isolum_qual
-                    : strcmp(optarg, "uniformrainbow") == 0 ? unirainbow
-                    : strcmp(optarg, "blackbody") == 0 ? blackbody
+                    : strcmp(optarg, "plsequential-lightness") == 0 ? plseq_lightness
+                    : strcmp(optarg, "plsequential-saturation") == 0 ? plseq_saturation
+                    : strcmp(optarg, "plsequential-rainbow") == 0 ? plseq_rainbow
+                    : strcmp(optarg, "plsequential-blackbody") == 0 ? plseq_blackbody
+                    : strcmp(optarg, "pldiverging-lightness") == 0 ? pldiv_lightness
+                    : strcmp(optarg, "pldiverging-saturation") == 0 ? pldiv_saturation
+                    : strcmp(optarg, "plqualitative-hue") == 0 ? plqual_hue
                     : strcmp(optarg, "cubehelix") == 0 ? cubehelix
                     : strcmp(optarg, "moreland") == 0 ? moreland
                     : strcmp(optarg, "mcnames") == 0 ? mcnames
@@ -138,7 +142,7 @@ int main(int argc, char* argv[])
             warmth = atof(optarg);
             break;
         case 'l':
-            luminance = atof(optarg);
+            lightness = atof(optarg);
             break;
         case 'r':
             rotations = atof(optarg);
@@ -191,24 +195,21 @@ int main(int argc, char* argv[])
                 "    [-b|--brightness=B]               Set brightness in [0,1]\n"
                 "    [-w|--warmth=W]                   Set warmth in [0,1] for seq. and div. maps\n"
                 "    [-d|--divergence=D]               Set divergence in deg. for div. and qual. maps\n"
-                "  Isoluminant color maps:\n"
-                "    -t|--type=isoluminant-sequential  Generate a sequential color map\n"
-                "    -t|--type=isoluminant-diverging   Generate a diverging color map\n"
-                "    -t|--type=isoluminant-qualitative Generate a qualitative color map\n"
-                "    [-l|--luminance=L]                Set luminance in [0,1]\n"
+                "  Perceptually linear color maps:\n"
+                "    -t|--type=plsequential-lightness  Sequential map with varying lightness\n"
+                "    -t|--type=plsequential-saturation Sequential map with varying saturation\n"
+                "    -t|--type=plsequential-rainbow    Sequential map with varying hue (rainbow)\n"
+                "    -t|--type=plsequential-blackbody  Sequential map with varying hue (black body)\n"
+                "    -t|--type=pldiverging-lightness   Diverging map with varying lightness\n"
+                "    -t|--type=pldiverging-saturation  Diverging map with varying saturation\n"
+                "    -t|--type=plqualitative-hue       Qualitative map with evenly distributed hue\n"
+                "    [-l|--lightness=L]                Set lightness in [0,1]\n"
                 "    [-s|--saturation=S]               Set saturation in [0,1]\n"
                 "    [-h|--hue=H]                      Set default hue in [0,360] degrees\n"
                 "    [-d|--divergence=D]               Set divergence in deg. for div. and qual. maps\n"
-                "  Uniform Rainbow color maps:\n"
-                "    -t|--type=uniformrainbow          Generate a uniform rainbow color map\n"
-                "    [-h|--hue=H]                      Set start hue in [0,360] degrees\n"
-                "    [-r|--rotations=R]                Set number of rotations, in (-infty,infty)\n"
-                "    [-s|--saturation=S]               Set saturation, in [0,5]\n"
-                "  Black Body color maps:\n"
-                "    -t|--type=blackbody               Generate a Black Body color map\n"
-                "    [-T|--temperature=T]              Start temperature of the map in Kelvin\n"
-                "    [-R|--range=R]                    Range of temperatures of the map in Kelvin\n"
-                "    [-s|--saturation=S]               Set saturation, in [0,5]\n"
+                "    [-r|--rotations=R]                Set number of rotations for rainbow maps\n"
+                "    [-T|--temperature=T]              Set start temp. in K for blackbody maps\n"
+                "    [-R|--range=R]                    Set temp. range in K for blackbody maps\n"
                 "  CubeHelix color maps:\n"
                 "    -t|--type=cubehelix               Generate a CubeHelix color map\n"
                 "    [-h|--hue=H]                      Set start hue in [0,180] degrees\n"
@@ -242,14 +243,18 @@ int main(int argc, char* argv[])
             hue = ColorMap::BrewerDivergingDefaultHue;
         else if (type == brewer_qual)
             hue = ColorMap::BrewerQualitativeDefaultHue;
-        else if (type == isolum_seq)
-            hue = ColorMap::IsoluminantSequentialDefaultHue;
-        else if (type == isolum_div)
-            hue = ColorMap::IsoluminantDivergingDefaultHue;
-        else if (type == isolum_qual)
-            hue = ColorMap::IsoluminantQualitativeDefaultHue;
-        else if (type == unirainbow)
-            hue = ColorMap::UniformRainbowDefaultHue;
+        else if (type == plseq_lightness)
+            hue = ColorMap::PLSequentialLightnessDefaultHue;
+        else if (type == plseq_saturation)
+            hue = ColorMap::PLSequentialSaturationDefaultHue;
+        else if (type == plseq_rainbow)
+            hue = ColorMap::PLSequentialRainbowDefaultHue;
+        else if (type == pldiv_lightness)
+            hue = ColorMap::PLDivergingLightnessDefaultHue;
+        else if (type == pldiv_saturation)
+            hue = ColorMap::PLDivergingSaturationDefaultHue;
+        else if (type == plqual_hue)
+            hue = ColorMap::PLQualitativeHueDefaultHue;
         else if (type == cubehelix)
             hue = ColorMap::CubeHelixDefaultHue;
     }
@@ -258,8 +263,10 @@ int main(int argc, char* argv[])
             divergence = ColorMap::BrewerDivergingDefaultDivergence;
         else if (type == brewer_qual)
             divergence = ColorMap::BrewerQualitativeDefaultDivergence;
-        else if (type == isolum_div)
-            divergence = ColorMap::IsoluminantDivergingDefaultDivergence;
+        else if (type == pldiv_lightness)
+            divergence = ColorMap::PLDivergingLightnessDefaultDivergence;
+        else if (type == pldiv_saturation)
+            divergence = ColorMap::PLDivergingSaturationDefaultDivergence;
     }
     if (contrast < 0.0f) {
         if (type == brewer_seq)
@@ -278,16 +285,20 @@ int main(int argc, char* argv[])
             saturation = ColorMap::BrewerDivergingDefaultSaturation;
         else if (type == brewer_qual)
             saturation = ColorMap::BrewerQualitativeDefaultSaturation;
-        else if (type == isolum_seq)
-            saturation = ColorMap::IsoluminantSequentialDefaultSaturation;
-        else if (type == isolum_div)
-            saturation = ColorMap::IsoluminantDivergingDefaultSaturation;
-        else if (type == isolum_qual)
-            saturation = ColorMap::IsoluminantQualitativeDefaultSaturation;
-        else if (type == unirainbow)
-            saturation = ColorMap::UniformRainbowDefaultSaturation;
-        else if (type == blackbody)
-            saturation = ColorMap::BlackBodyDefaultSaturation;
+        else if (type == plseq_lightness)
+            saturation = ColorMap::PLSequentialLightnessDefaultSaturation;
+        else if (type == plseq_saturation)
+            saturation = ColorMap::PLSequentialSaturationDefaultSaturation;
+        else if (type == plseq_rainbow)
+            saturation = ColorMap::PLSequentialRainbowDefaultSaturation;
+        else if (type == plseq_blackbody)
+            saturation = ColorMap::PLSequentialBlackBodyDefaultSaturation;
+        else if (type == pldiv_lightness)
+            saturation = ColorMap::PLDivergingLightnessDefaultSaturation;
+        else if (type == pldiv_saturation)
+            saturation = ColorMap::PLDivergingSaturationDefaultSaturation;
+        else if (type == plqual_hue)
+            saturation = ColorMap::PLQualitativeHueDefaultSaturation;
         else if (type == cubehelix)
             saturation = ColorMap::CubeHelixDefaultSaturation;
     }
@@ -305,27 +316,29 @@ int main(int argc, char* argv[])
         else if (type == brewer_div)
             warmth = ColorMap::BrewerDivergingDefaultWarmth;
     }
-    if (luminance < 0.0f) {
-        if (type == isolum_seq)
-            luminance = ColorMap::IsoluminantSequentialDefaultLuminance;
-        else if (type == isolum_div)
-            luminance = ColorMap::IsoluminantDivergingDefaultLuminance;
-        else if (type == isolum_qual)
-            luminance = ColorMap::IsoluminantQualitativeDefaultLuminance;
+    if (lightness < 0.0f) {
+        if (type == plseq_saturation)
+            lightness = ColorMap::PLSequentialSaturationDefaultLightness;
+        else if (type == pldiv_lightness)
+            lightness = ColorMap::PLDivergingLightnessDefaultLightness;
+        else if (type == pldiv_saturation)
+            lightness = ColorMap::PLDivergingSaturationDefaultLightness;
+        else if (type == plqual_hue)
+            lightness = ColorMap::PLQualitativeHueDefaultLightness;
     }
     if (std::isnan(rotations)) {
-        if (type == unirainbow)
-            rotations = ColorMap::UniformRainbowDefaultRotations;
+        if (type == plseq_rainbow)
+            rotations = ColorMap::PLSequentialRainbowDefaultRotations;
         else if (type == cubehelix)
             rotations = ColorMap::CubeHelixDefaultRotations;
     }
     if (temperature < 0.0f) {
-        if (type == blackbody)
-            temperature = ColorMap::BlackBodyDefaultTemperature;
+        if (type == plseq_blackbody)
+            temperature = ColorMap::PLSequentialBlackBodyDefaultTemperature;
     }
     if (range < 0.0f) {
-        if (type == blackbody)
-            range = ColorMap::BlackBodyDefaultRange;
+        if (type == plseq_blackbody)
+            range = ColorMap::PLSequentialBlackBodyDefaultRange;
     }
     if (gamma < 0.0f) {
         if (type == cubehelix)
@@ -361,20 +374,26 @@ int main(int argc, char* argv[])
     case brewer_qual:
         ColorMap::BrewerQualitative(n, &(colormap[0]), hue, divergence, contrast, saturation, brightness);
         break;
-    case isolum_seq:
-        ColorMap::IsoluminantSequential(n, &(colormap[0]), luminance, saturation, hue);
+    case plseq_lightness:
+        ColorMap::PLSequentialLightness(n, &(colormap[0]), saturation, hue);
+        break;
+    case plseq_saturation:
+        ColorMap::PLSequentialSaturation(n, &(colormap[0]), lightness, saturation, hue);
+        break;
+    case plseq_rainbow:
+        ColorMap::PLSequentialRainbow(n, &(colormap[0]), hue, rotations, saturation);
         break;
-    case isolum_div:
-        ColorMap::IsoluminantDiverging(n, &(colormap[0]), luminance, saturation, hue, divergence);
+    case plseq_blackbody:
+        ColorMap::PLSequentialBlackBody(n, &(colormap[0]), temperature, range, saturation);
         break;
-    case isolum_qual:
-        ColorMap::IsoluminantQualitative(n, &(colormap[0]), luminance, saturation, hue);
+    case pldiv_lightness:
+        ColorMap::PLDivergingLightness(n, &(colormap[0]), lightness, saturation, hue, divergence);
         break;
-    case unirainbow:
-        ColorMap::UniformRainbow(n, &(colormap[0]), hue, rotations, saturation);
+    case pldiv_saturation:
+        ColorMap::PLDivergingSaturation(n, &(colormap[0]), lightness, saturation, hue, divergence);
         break;
-    case blackbody:
-        ColorMap::BlackBody(n, &(colormap[0]), temperature, range, saturation);
+    case plqual_hue:
+        ColorMap::PLQualitativeHue(n, &(colormap[0]), lightness, saturation, hue);
         break;
     case cubehelix:
         ColorMap::CubeHelix(n, &(colormap[0]), hue, rotations, saturation, gamma);
index 06c8856..5e87ac7 100644 (file)
@@ -552,53 +552,34 @@ void BrewerQualitative(int n, unsigned char* colormap, float hue, float divergen
     }
 }
 
-/* Isoluminant */
+/* Perceptually linear (PL) */
 
-void IsoluminantSequential(int n, unsigned char* colormap,
-        float luminance, float saturation, float hue)
+void PLSequentialLightness(int n, unsigned char* colormap, float saturation, float hue)
 {
     triplet lch;
-    lch.l = luminance * 100.0f;
     lch.h = hue;
     for (int i = 0; i < n; i++) {
         float t = i / (n - 1.0f);
-        float s = saturation * 5.0f * (1.0f - t);
-        lch.c = lch_chroma(lch.l, s);
-        lch_to_colormap(lch, colormap + 3 * i);
-    }
-}
-
-void IsoluminantDiverging(int n, unsigned char* colormap,
-        float luminance, float saturation, float hue, float divergence)
-{
-    triplet lch;
-    lch.l = luminance * 100.0f;
-    for (int i = 0; i < n; i++) {
-        float t = i / (n - 1.0f);
-        float s = saturation * 5.0f * (t <= 0.5f ? 2.0f * (0.5f - t) : 2.0f * (t - 0.5f));
-        lch.c = lch_chroma(lch.l, s);
-        lch.h = (t <= 0.5f ? hue : hue + divergence);
+        lch.l = t * 100.0f;
+        lch.c = lch_chroma(lch.l, saturation * 5.0f * (1.0f - t));
         lch_to_colormap(lch, colormap + 3 * i);
     }
 }
 
-void IsoluminantQualitative(int n, unsigned char* colormap,
-        float luminance, float saturation, float hue)
+void PLSequentialSaturation(int n, unsigned char* colormap,
+        float lightness, float saturation, float hue)
 {
-    float divergence = twopi * (n - 1.0f) / n;
     triplet lch;
-    lch.l = luminance * 100.0f;
-    lch.c = lch_chroma(lch.l, saturation * 5.0f);
+    lch.l = lightness * 100.0f;
+    lch.h = hue;
     for (int i = 0; i < n; i++) {
         float t = i / (n - 1.0f);
-        lch.h = hue + t * divergence;
+        lch.c = lch_chroma(lch.l, saturation * 5.0f * (1.0f - t));
         lch_to_colormap(lch, colormap + 3 * i);
     }
 }
 
-/* UniformRainbow */
-
-void UniformRainbow(int n, unsigned char* colormap, float hue, float rotations, float saturation)
+void PLSequentialRainbow(int n, unsigned char* colormap, float hue, float rotations, float saturation)
 {
     triplet luv, lch;
     for (int i = 0; i < n; i++) {
@@ -610,8 +591,6 @@ void UniformRainbow(int n, unsigned char* colormap, float hue, float rotations,
     }
 }
 
-/* BlackBody */
-
 static float plancks_law(float temperature, float lambda)
 {
     const float c = 299792458.0f;     // speed of light in vacuum
@@ -743,7 +722,7 @@ static triplet color_matching_function(int lambda /* in nanometers */)
     return xyz;
 }
 
-void BlackBody(int n, unsigned char* colormap, float temperature, float range, float saturation)
+void PLSequentialBlackBody(int n, unsigned char* colormap, float temperature, float range, float saturation)
 {
     for (int i = 0; i < n; i++) {
         float fract = i / (n - 1.0f);
@@ -767,6 +746,47 @@ void BlackBody(int n, unsigned char* colormap, float temperature, float range, f
     }
 }
 
+void PLDivergingLightness(int n, unsigned char* colormap, float lightness, float saturation, float hue, float divergence)
+{
+    triplet lch;
+    for (int i = 0; i < n; i++) {
+        float t = i / (n - 1.0f);
+        lch.l = 100.0f * lightness + 100.0f * (1.0f - lightness) * (t <= 0.5f ? 2.0f * t : 2.0f * (1.0f - t));
+        float s = saturation * 5.0f * (t <= 0.5f ? 2.0f * (0.5f - t) : 2.0f * (t - 0.5f));
+        lch.c = lch_chroma(lch.l, s);
+        lch.h = (t <= 0.5f ? hue : hue + divergence);
+        lch_to_colormap(lch, colormap + 3 * i);
+    }
+}
+
+void PLDivergingSaturation(int n, unsigned char* colormap,
+        float lightness, float saturation, float hue, float divergence)
+{
+    triplet lch;
+    lch.l = lightness * 100.0f;
+    for (int i = 0; i < n; i++) {
+        float t = i / (n - 1.0f);
+        float s = saturation * 5.0f * (t <= 0.5f ? 2.0f * (0.5f - t) : 2.0f * (t - 0.5f));
+        lch.c = lch_chroma(lch.l, s);
+        lch.h = (t <= 0.5f ? hue : hue + divergence);
+        lch_to_colormap(lch, colormap + 3 * i);
+    }
+}
+
+void PLQualitativeHue(int n, unsigned char* colormap,
+        float lightness, float saturation, float hue)
+{
+    float divergence = twopi * (n - 1.0f) / n;
+    triplet lch;
+    lch.l = lightness * 100.0f;
+    lch.c = lch_chroma(lch.l, saturation * 5.0f);
+    for (int i = 0; i < n; i++) {
+        float t = i / (n - 1.0f);
+        lch.h = hue + t * divergence;
+        lch_to_colormap(lch, colormap + 3 * i);
+    }
+}
+
 /* CubeHelix */
 
 int CubeHelix(int n, unsigned char* colormap, float hue,
index cd67cdb..d9eb98e 100644 (file)
@@ -101,83 +101,101 @@ void BrewerQualitative(int n, unsigned char* colormap,
         float brightness = BrewerQualitativeDefaultBrightness);
 
 /*
- * Isoluminant color maps.
+ * Perceptually linear (PL) color maps.
  *
- * These are useful for coloring surfaces because their constant luminance
- * allows non-interfering combination with shading.
+ * These are computed in CIELUV/LCH to achieve perceptual linearity.
+ * One or two of lightness, saturation, and hue are changed while the other(s)
+ * stay constant.
+ *
+ * For example, color maps of constant lightness are useful for 3D surfaces
+ * because they do not interfere with additional shading.
  */
 
-// Create a sequential isoluminant color map with n colors.
+/* Sequential perceptually linear maps */
 
-const float IsoluminantSequentialDefaultLuminance = 0.5f;
-const float IsoluminantSequentialDefaultSaturation = 0.5f;
-const float IsoluminantSequentialDefaultHue = 0.349065850399f; // 20 deg
+// Varying lightness
 
-void IsoluminantSequential(int n, unsigned char* colormap,
-        float luminance = IsoluminantSequentialDefaultLuminance,
-        float saturation = IsoluminantSequentialDefaultSaturation,
-        float hue = IsoluminantSequentialDefaultHue);
+const float PLSequentialLightnessDefaultSaturation = 0.5f;
+const float PLSequentialLightnessDefaultHue = 0.349065850399f; // 20 deg
 
-// Create a diverging isoluminant color map with n colors.
+void PLSequentialLightness(int n, unsigned char* colormap,
+        float saturation = PLSequentialLightnessDefaultSaturation,
+        float hue = PLSequentialLightnessDefaultHue);
 
-const float IsoluminantDivergingDefaultLuminance = 0.5f;
-const float IsoluminantDivergingDefaultSaturation = 0.5f;
-const float IsoluminantDivergingDefaultHue = 0.349065850399f; // 20 deg
-const float IsoluminantDivergingDefaultDivergence = 4.18879020479f; // 2/3 * 2PI
+// Varying saturation
 
-void IsoluminantDiverging(int n, unsigned char* colormap,
-        float luminance = IsoluminantDivergingDefaultLuminance,
-        float saturation = IsoluminantDivergingDefaultSaturation,
-        float hue = IsoluminantDivergingDefaultHue,
-        float divergence = IsoluminantDivergingDefaultDivergence);
+const float PLSequentialSaturationDefaultLightness = 0.5f;
+const float PLSequentialSaturationDefaultSaturation = 0.5f;
+const float PLSequentialSaturationDefaultHue = 0.349065850399f; // 20 deg
 
-// Create a qualitative isoluminant color map with n colors.
+void PLSequentialSaturation(int n, unsigned char* colormap,
+        float lightness = PLSequentialSaturationDefaultLightness,
+        float saturation = PLSequentialSaturationDefaultSaturation,
+        float hue = PLSequentialSaturationDefaultHue);
 
-const float IsoluminantQualitativeDefaultLuminance = 0.55f;
-const float IsoluminantQualitativeDefaultSaturation = 0.35f;
-const float IsoluminantQualitativeDefaultHue = 0.0;
+// Varying hue (through all colors, rainbow-like)
 
-void IsoluminantQualitative(int n, unsigned char* colormap,
-        float luminance = IsoluminantQualitativeDefaultLuminance,
-        float saturation = IsoluminantQualitativeDefaultSaturation,
-        float hue = IsoluminantQualitativeDefaultHue);
+const float PLSequentialRainbowDefaultHue = 0.0f;
+const float PLSequentialRainbowDefaultRotations = -1.5f;
+const float PLSequentialRainbowDefaultSaturation = 1.2f;
 
-/*
- * Perceptually uniform rainbow.
- *
- * These are similar to CubeHelix, but are constructed in LCH color space
- * to achieve better perceptual uniformity.
- */
+void PLSequentialRainbow(int n, unsigned char* colormap,
+        float hue = PLSequentialRainbowDefaultHue,
+        float rotations = PLSequentialRainbowDefaultRotations,
+        float saturation = PLSequentialRainbowDefaultSaturation);
 
-const float UniformRainbowDefaultHue = 0.0f;
-const float UniformRainbowDefaultRotations = -1.5f;
-const float UniformRainbowDefaultSaturation = 1.2f;
+// Varying hue (through physically plausible black body colors at increasing
+// temperatures).
+// The defaults are chosen so that we start at red and arrive at the D65 white
+// point (6500 K), thus excluding the blue colors that occur at higher
+// temperatures.
+const float PLSequentialBlackBodyDefaultTemperature = 250.0f;
+const float PLSequentialBlackBodyDefaultRange = 6250.0f;
+const float PLSequentialBlackBodyDefaultSaturation = 2.5f;
 
-void UniformRainbow(int n, unsigned char* colormap,
-        float hue = UniformRainbowDefaultHue,
-        float rotations = UniformRainbowDefaultRotations,
-        float saturation = UniformRainbowDefaultSaturation);
+void PLSequentialBlackBody(int n, unsigned char* colormap,
+        float temperature = PLSequentialBlackBodyDefaultTemperature,
+        float range = PLSequentialBlackBodyDefaultRange,
+        float saturation = PLSequentialBlackBodyDefaultSaturation);
 
-/*
- * Black Body color maps, based on the hue of a black body at increading
- * temperatures, but with linearly increasing lightness and chromaticity.
- *
- * Parameters are the temperature at the lower end of the map, and the range of
- * temperatures in the map. (The temperature at the higher end of the map is the
- * sum of the two). Furthermore, the saturation can be adjusted, but high
- * saturations will lead to color clipping.
- */
+/* Diverging perceptually linear maps */
+
+// Varying lightness
+
+const float PLDivergingLightnessDefaultLightness = 0.1f;
+const float PLDivergingLightnessDefaultSaturation = 0.5f;
+const float PLDivergingLightnessDefaultHue = 0.349065850399f; // 20 deg
+const float PLDivergingLightnessDefaultDivergence = 4.18879020479f; // 2/3 * 2PI
+
+void PLDivergingLightness(int n, unsigned char* colormap,
+        float lightness = PLDivergingLightnessDefaultLightness,
+        float saturation = PLDivergingLightnessDefaultSaturation,
+        float hue = PLDivergingLightnessDefaultHue,
+        float divergence = PLDivergingLightnessDefaultDivergence);
+
+// Varying saturation
+
+const float PLDivergingSaturationDefaultLightness = 0.5f;
+const float PLDivergingSaturationDefaultSaturation = 0.5f;
+const float PLDivergingSaturationDefaultHue = 0.349065850399f; // 20 deg
+const float PLDivergingSaturationDefaultDivergence = 4.18879020479f; // 2/3 * 2PI
+
+void PLDivergingSaturation(int n, unsigned char* colormap,
+        float lightness = PLDivergingSaturationDefaultLightness,
+        float saturation = PLDivergingSaturationDefaultSaturation,
+        float hue = PLDivergingSaturationDefaultHue,
+        float divergence = PLDivergingSaturationDefaultDivergence);
+
+/* Qualitative perceptually linear maps */
 
-// The defaults are chosen so that we start at red and arrive the D65 white point
-// (6500 K), thus excluding the blue colors that occur at higher temperatures.
-const float BlackBodyDefaultTemperature = 250.0f;
-const float BlackBodyDefaultRange = 6250.0f;
-const float BlackBodyDefaultSaturation = 2.5f;
+const float PLQualitativeHueDefaultLightness = 0.55f;
+const float PLQualitativeHueDefaultSaturation = 0.35f;
+const float PLQualitativeHueDefaultHue = 0.0f;
 
-void BlackBody(int n, unsigned char* colormap,
-        float temperature = BlackBodyDefaultTemperature,
-        float range = BlackBodyDefaultRange,
-        float saturation = BlackBodyDefaultSaturation);
+void PLQualitativeHue(int n, unsigned char* colormap,
+        float lightness = PLQualitativeHueDefaultLightness,
+        float saturation = PLQualitativeHueDefaultSaturation,
+        float hue = PLQualitativeHueDefaultHue);
 
 /*
  * CubeHelix color maps, as described in
index a6f1f0d..5bea625 100644 (file)
@@ -43,26 +43,33 @@ static QString brewerlike_reference = QString("Relevant paper: "
         "<a href=\"http://dx.doi.org/10.1111/j.1467-8659.2008.01203.x\">Generating Color Palettes using Intuitive Parameters</a>, "
         "Computer Graphics Forum 27(3), May 2008.");
 
-static QString isoluminant_seq_reference = QString(
-        "Constant lightness, constant hue, linearly decreasing saturation. "
-        "Computed in CIELUV color space (LCH variant).");
+static QString plseq_lightness_reference = QString(
+        "Perceptually linear, varying lightness.<br>"
+        "Computed in CIELUV/LCH color space.");
 
-static QString isoluminant_div_reference = QString(
-        "Constant lightness, constant hue in each half, linearly decreasing saturation towards the middle. "
-        "Computed in CIELUV color space (LCH variant).");
+static QString plseq_saturation_reference = QString(
+        "Perceptually linear, varying saturation.<br>"
+        "Computed in CIELUV/LCH color space.");
 
-static QString isoluminant_qual_reference = QString(
-        "Constant lightness, constant saturation, evenly distributed hue. "
-        "Computed in CIELUV color space (LCH variant).");
+static QString plseq_rainbow_reference = QString(
+        "Perceptually linear, varying hue (rainbow).<br>"
+        "Computed in CIELUV/LCH color space.");
 
-static QString uniformrainbow_reference = QString(
-        "Linearly increasing lightness, linearly decreasing saturation, rotating hue. "
-        "Computed in CIELUV color space (LCH variant).");
+static QString plseq_blackbody_reference = QString(
+        "Perceptually linear, varying hue (black body at increasing temperatures).<br>"
+        "Computed in CIELUV/LCH color space.");
 
-static QString blackbody_reference = QString(
-        "Linearly increasing lightness, linearly decreasing saturation, hues taken from "
-        "a physically plausible model of black body radiation in the given range of temperatures. "
-        "Computed in CIELUV color space (LCH variant).");
+static QString pldiv_lightness_reference = QString(
+        "Perceptually linear, varying lightness.<br>"
+        "Computed in CIELUV/LCH color space.");
+
+static QString pldiv_saturation_reference = QString(
+        "Perceptually linear, varying saturation.<br>"
+        "Computed in CIELUV/LCH color space.");
+
+static QString plqual_hue_reference = QString(
+        "Perceptually linear, evenly distributed hue.<br>"
+        "Computed in CIELUV/LCH color space.");
 
 static QString cubehelix_reference = QString("Relevant paper: "
         "D. A. Green, "
@@ -543,9 +550,9 @@ void ColorMapBrewerQualitativeWidget::update()
         emit colorMapChanged();
 }
 
-/* ColorMapIsoluminantSequentialWidget */
+/* ColorMapPLSequentialLightnessWidget */
 
-ColorMapIsoluminantSequentialWidget::ColorMapIsoluminantSequentialWidget() :
+ColorMapPLSequentialLightnessWidget::ColorMapPLSequentialLightnessWidget() :
     _update_lock(false)
 {
     QGridLayout *layout = new QGridLayout;
@@ -557,92 +564,74 @@ ColorMapIsoluminantSequentialWidget::ColorMapIsoluminantSequentialWidget() :
     _n_spinbox->setSingleStep(1);
     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
 
-    QLabel* luminance_label = new QLabel("Luminance:");
-    layout->addWidget(luminance_label, 2, 0);
-    _luminance_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
-    layout->addWidget(_luminance_changer->slider, 2, 1, 1, 2);
-    layout->addWidget(_luminance_changer->spinbox, 2, 3);
-
     QLabel* saturation_label = new QLabel("Saturation:");
-    layout->addWidget(saturation_label, 3, 0);
+    layout->addWidget(saturation_label, 2, 0);
     _saturation_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
-    layout->addWidget(_saturation_changer->slider, 3, 1, 1, 2);
-    layout->addWidget(_saturation_changer->spinbox, 3, 3);
+    layout->addWidget(_saturation_changer->slider, 2, 1, 1, 2);
+    layout->addWidget(_saturation_changer->spinbox, 2, 3);
 
     QLabel* hue_label = new QLabel("Hue:");
-    layout->addWidget(hue_label, 4, 0);
+    layout->addWidget(hue_label, 3, 0);
     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
-    layout->addWidget(_hue_changer->slider, 4, 1, 1, 2);
-    layout->addWidget(_hue_changer->spinbox, 4, 3);
-
-    QLabel* divergence_label = new QLabel("Divergence:");
-    layout->addWidget(divergence_label, 5, 0);
-    ColorMapCombinedSliderSpinBox* divergence_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
-    layout->addWidget(divergence_changer->slider, 5, 1, 1, 2);
-    layout->addWidget(divergence_changer->spinbox, 5, 3);
-    hideWidgetButPreserveSize(divergence_label);
-    hideWidgetButPreserveSize(divergence_changer->slider);
-    hideWidgetButPreserveSize(divergence_changer->spinbox);
+    layout->addWidget(_hue_changer->slider, 3, 1, 1, 2);
+    layout->addWidget(_hue_changer->spinbox, 3, 3);
 
     layout->setColumnStretch(1, 1);
-    layout->addItem(new QSpacerItem(0, 0), 6, 0, 1, 4);
-    layout->setRowStretch(6, 1);
+    layout->addItem(new QSpacerItem(0, 0), 4, 0, 1, 4);
+    layout->setRowStretch(4, 1);
     setLayout(layout);
 
     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
-    connect(_luminance_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     reset();
 }
 
-ColorMapIsoluminantSequentialWidget::~ColorMapIsoluminantSequentialWidget()
+ColorMapPLSequentialLightnessWidget::~ColorMapPLSequentialLightnessWidget()
 {
 }
 
-void ColorMapIsoluminantSequentialWidget::reset()
+void ColorMapPLSequentialLightnessWidget::reset()
 {
     _update_lock = true;
     _n_spinbox->setValue(256);
-    _luminance_changer->setValue(ColorMap::IsoluminantSequentialDefaultLuminance);
-    _saturation_changer->setValue(ColorMap::IsoluminantSequentialDefaultSaturation);
-    _hue_changer->setValue(qRadiansToDegrees(ColorMap::IsoluminantSequentialDefaultHue));
+    _saturation_changer->setValue(ColorMap::PLSequentialLightnessDefaultSaturation);
+    _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLSequentialLightnessDefaultHue));
     _update_lock = false;
     update();
 }
 
-QVector<QColor> ColorMapIsoluminantSequentialWidget::colorMap() const
+QVector<QColor> ColorMapPLSequentialLightnessWidget::colorMap() const
 {
     int n;
-    float l, s, h;
-    parameters(n, l, s, h);
+    float s, h;
+    parameters(n, s, h);
     QVector<unsigned char> colormap(3 * n);
-    ColorMap::IsoluminantSequential(n, colormap.data(), l, s, h);
+    ColorMap::PLSequentialLightness(n, colormap.data(), s, h);
     return toQColor(colormap);
 }
 
-QString ColorMapIsoluminantSequentialWidget::reference() const
+QString ColorMapPLSequentialLightnessWidget::reference() const
 {
-    return isoluminant_seq_reference;
+    return plseq_lightness_reference;
 }
 
-void ColorMapIsoluminantSequentialWidget::parameters(int& n, float& luminance, float& saturation, float& hue) const
+void ColorMapPLSequentialLightnessWidget::parameters(int& n, float& saturation, float& hue) const
 {
     n = _n_spinbox->value();
-    luminance = _luminance_changer->value();
     saturation = _saturation_changer->value();
     hue = qDegreesToRadians(_hue_changer->value());
 }
 
-void ColorMapIsoluminantSequentialWidget::update()
+void ColorMapPLSequentialLightnessWidget::update()
 {
     if (!_update_lock)
         emit colorMapChanged();
 }
 
-/* ColorMapIsoluminantDivergingWidget */
+/* ColorMapPLSequentialSaturationWidget */
 
-ColorMapIsoluminantDivergingWidget::ColorMapIsoluminantDivergingWidget() :
+ColorMapPLSequentialSaturationWidget::ColorMapPLSequentialSaturationWidget() :
     _update_lock(false)
 {
     QGridLayout *layout = new QGridLayout;
@@ -654,11 +643,11 @@ ColorMapIsoluminantDivergingWidget::ColorMapIsoluminantDivergingWidget() :
     _n_spinbox->setSingleStep(1);
     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
 
-    QLabel* luminance_label = new QLabel("Luminance:");
-    layout->addWidget(luminance_label, 2, 0);
-    _luminance_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
-    layout->addWidget(_luminance_changer->slider, 2, 1, 1, 2);
-    layout->addWidget(_luminance_changer->spinbox, 2, 3);
+    QLabel* lightness_label = new QLabel("Lightness:");
+    layout->addWidget(lightness_label, 2, 0);
+    _lightness_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
+    layout->addWidget(_lightness_changer->slider, 2, 1, 1, 2);
+    layout->addWidget(_lightness_changer->spinbox, 2, 3);
 
     QLabel* saturation_label = new QLabel("Saturation:");
     layout->addWidget(saturation_label, 3, 0);
@@ -672,74 +661,65 @@ ColorMapIsoluminantDivergingWidget::ColorMapIsoluminantDivergingWidget() :
     layout->addWidget(_hue_changer->slider, 4, 1, 1, 2);
     layout->addWidget(_hue_changer->spinbox, 4, 3);
 
-    QLabel* divergence_label = new QLabel("Divergence:");
-    layout->addWidget(divergence_label, 5, 0);
-    _divergence_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
-    layout->addWidget(_divergence_changer->slider, 5, 1, 1, 2);
-    layout->addWidget(_divergence_changer->spinbox, 5, 3);
-
     layout->setColumnStretch(1, 1);
-    layout->addItem(new QSpacerItem(0, 0), 6, 0, 1, 4);
-    layout->setRowStretch(6, 1);
+    layout->addItem(new QSpacerItem(0, 0), 5, 0, 1, 4);
+    layout->setRowStretch(5, 1);
     setLayout(layout);
 
     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
-    connect(_luminance_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_lightness_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
-    connect(_divergence_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     reset();
 }
 
-ColorMapIsoluminantDivergingWidget::~ColorMapIsoluminantDivergingWidget()
+ColorMapPLSequentialSaturationWidget::~ColorMapPLSequentialSaturationWidget()
 {
 }
 
-void ColorMapIsoluminantDivergingWidget::reset()
+void ColorMapPLSequentialSaturationWidget::reset()
 {
     _update_lock = true;
-    _n_spinbox->setValue(257);
-    _luminance_changer->setValue(ColorMap::IsoluminantDivergingDefaultLuminance);
-    _saturation_changer->setValue(ColorMap::IsoluminantDivergingDefaultSaturation);
-    _hue_changer->setValue(qRadiansToDegrees(ColorMap::IsoluminantDivergingDefaultHue));
-    _divergence_changer->setValue(qRadiansToDegrees(ColorMap::IsoluminantDivergingDefaultDivergence));
+    _n_spinbox->setValue(256);
+    _lightness_changer->setValue(ColorMap::PLSequentialSaturationDefaultLightness);
+    _saturation_changer->setValue(ColorMap::PLSequentialSaturationDefaultSaturation);
+    _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLSequentialSaturationDefaultHue));
     _update_lock = false;
     update();
 }
 
-QVector<QColor> ColorMapIsoluminantDivergingWidget::colorMap() const
+QVector<QColor> ColorMapPLSequentialSaturationWidget::colorMap() const
 {
     int n;
-    float l, s, h, d;
-    parameters(n, l, s, h, d);
+    float l, s, h;
+    parameters(n, l, s, h);
     QVector<unsigned char> colormap(3 * n);
-    ColorMap::IsoluminantDiverging(n, colormap.data(), l, s, h, d);
+    ColorMap::PLSequentialSaturation(n, colormap.data(), l, s, h);
     return toQColor(colormap);
 }
 
-QString ColorMapIsoluminantDivergingWidget::reference() const
+QString ColorMapPLSequentialSaturationWidget::reference() const
 {
-    return isoluminant_div_reference;
+    return plseq_saturation_reference;
 }
 
-void ColorMapIsoluminantDivergingWidget::parameters(int& n, float& luminance, float& saturation, float& hue, float& divergence) const
+void ColorMapPLSequentialSaturationWidget::parameters(int& n, float& lightness, float& saturation, float& hue) const
 {
     n = _n_spinbox->value();
-    luminance = _luminance_changer->value();
+    lightness = _lightness_changer->value();
     saturation = _saturation_changer->value();
     hue = qDegreesToRadians(_hue_changer->value());
-    divergence = qDegreesToRadians(_divergence_changer->value());
 }
 
-void ColorMapIsoluminantDivergingWidget::update()
+void ColorMapPLSequentialSaturationWidget::update()
 {
     if (!_update_lock)
         emit colorMapChanged();
 }
 
-/* ColorMapIsoluminantQualitativeWidget */
+/* ColorMapPLSequentialRainbowWidget */
 
-ColorMapIsoluminantQualitativeWidget::ColorMapIsoluminantQualitativeWidget() :
+ColorMapPLSequentialRainbowWidget::ColorMapPLSequentialRainbowWidget() :
     _update_lock(false)
 {
     QGridLayout *layout = new QGridLayout;
@@ -751,11 +731,188 @@ ColorMapIsoluminantQualitativeWidget::ColorMapIsoluminantQualitativeWidget() :
     _n_spinbox->setSingleStep(1);
     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
 
-    QLabel* luminance_label = new QLabel("Luminance:");
-    layout->addWidget(luminance_label, 2, 0);
-    _luminance_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
-    layout->addWidget(_luminance_changer->slider, 2, 1, 1, 2);
-    layout->addWidget(_luminance_changer->spinbox, 2, 3);
+    QLabel* hue_label = new QLabel("Hue:");
+    layout->addWidget(hue_label, 2, 0);
+    _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
+    layout->addWidget(_hue_changer->slider, 2, 1, 1, 2);
+    layout->addWidget(_hue_changer->spinbox, 2, 3);
+
+    QLabel* rotations_label = new QLabel("Rotations:");
+    layout->addWidget(rotations_label, 3, 0);
+    _rotations_changer = new ColorMapCombinedSliderSpinBox(-5.0f, +5.0f, 0.1f);
+    layout->addWidget(_rotations_changer->slider, 3, 1, 1, 2);
+    layout->addWidget(_rotations_changer->spinbox, 3, 3);
+
+    QLabel* saturation_label = new QLabel("Saturation:");
+    layout->addWidget(saturation_label, 4, 0);
+    _saturation_changer = new ColorMapCombinedSliderSpinBox(0.0f, 5.0f, 0.1f);
+    layout->addWidget(_saturation_changer->slider, 4, 1, 1, 2);
+    layout->addWidget(_saturation_changer->spinbox, 4, 3);
+
+    layout->setColumnStretch(1, 1);
+    layout->addItem(new QSpacerItem(0, 0), 5, 0, 1, 4);
+    layout->setRowStretch(5, 1);
+    setLayout(layout);
+
+    connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
+    connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_rotations_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    reset();
+}
+
+ColorMapPLSequentialRainbowWidget::~ColorMapPLSequentialRainbowWidget()
+{
+}
+
+void ColorMapPLSequentialRainbowWidget::reset()
+{
+    _update_lock = true;
+    _n_spinbox->setValue(256);
+    _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLSequentialRainbowDefaultHue));
+    _rotations_changer->setValue(ColorMap::PLSequentialRainbowDefaultRotations);
+    _saturation_changer->setValue(ColorMap::PLSequentialRainbowDefaultSaturation);
+    _update_lock = false;
+    update();
+}
+
+QVector<QColor> ColorMapPLSequentialRainbowWidget::colorMap() const
+{
+    int n;
+    float h, r, s;
+    parameters(n, h, r, s);
+    QVector<unsigned char> colormap(3 * n);
+    ColorMap::PLSequentialRainbow(n, colormap.data(), h, r, s);
+    return toQColor(colormap);
+}
+
+QString ColorMapPLSequentialRainbowWidget::reference() const
+{
+    return plseq_rainbow_reference;
+}
+
+void ColorMapPLSequentialRainbowWidget::parameters(int& n, float& hue,
+        float& rotations, float& saturation) const
+{
+    n = _n_spinbox->value();
+    hue = qDegreesToRadians(_hue_changer->value());
+    rotations = _rotations_changer->value();
+    saturation = _saturation_changer->value();
+}
+
+void ColorMapPLSequentialRainbowWidget::update()
+{
+    if (!_update_lock)
+        emit colorMapChanged();
+}
+
+/* ColorMapPLSequentialBlackBodyWidget */
+
+ColorMapPLSequentialBlackBodyWidget::ColorMapPLSequentialBlackBodyWidget() :
+    _update_lock(false)
+{
+    QGridLayout *layout = new QGridLayout;
+
+    QLabel* n_label = new QLabel("Colors:");
+    layout->addWidget(n_label, 1, 0);
+    _n_spinbox = new QSpinBox();
+    _n_spinbox->setRange(2, 10240);
+    _n_spinbox->setSingleStep(1);
+    layout->addWidget(_n_spinbox, 1, 1, 1, 3);
+
+    QLabel* temperature_label = new QLabel("Temperature (K):");
+    layout->addWidget(temperature_label, 2, 0);
+    _temperature_changer = new ColorMapCombinedSliderSpinBox(250.0f, 20000.0f, 100.0f);
+    layout->addWidget(_temperature_changer->slider, 2, 1, 1, 2);
+    layout->addWidget(_temperature_changer->spinbox, 2, 3);
+
+    QLabel* range_label = new QLabel("Range (K):");
+    layout->addWidget(range_label, 3, 0);
+    _range_changer = new ColorMapCombinedSliderSpinBox(0.0f, 20000.0f, 100.0f);
+    layout->addWidget(_range_changer->slider, 3, 1, 1, 2);
+    layout->addWidget(_range_changer->spinbox, 3, 3);
+
+    QLabel* saturation_label = new QLabel("Saturation:");
+    layout->addWidget(saturation_label, 4, 0);
+    _saturation_changer = new ColorMapCombinedSliderSpinBox(0.0f, 5.0f, 0.1f);
+    layout->addWidget(_saturation_changer->slider, 4, 1, 1, 2);
+    layout->addWidget(_saturation_changer->spinbox, 4, 3);
+
+    layout->setColumnStretch(1, 1);
+    layout->addItem(new QSpacerItem(0, 0), 5, 0, 1, 4);
+    layout->setRowStretch(5, 1);
+    setLayout(layout);
+
+    connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
+    connect(_temperature_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_range_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    reset();
+}
+
+ColorMapPLSequentialBlackBodyWidget::~ColorMapPLSequentialBlackBodyWidget()
+{
+}
+
+void ColorMapPLSequentialBlackBodyWidget::reset()
+{
+    _update_lock = true;
+    _n_spinbox->setValue(256);
+    _temperature_changer->setValue(ColorMap::PLSequentialBlackBodyDefaultTemperature);
+    _range_changer->setValue(ColorMap::PLSequentialBlackBodyDefaultRange);
+    _saturation_changer->setValue(ColorMap::PLSequentialBlackBodyDefaultSaturation);
+    _update_lock = false;
+    update();
+}
+
+QVector<QColor> ColorMapPLSequentialBlackBodyWidget::colorMap() const
+{
+    int n;
+    float t, r, s;
+    parameters(n, t, r, s);
+    QVector<unsigned char> colormap(3 * n);
+    ColorMap::PLSequentialBlackBody(n, colormap.data(), t, r, s);
+    return toQColor(colormap);
+}
+
+QString ColorMapPLSequentialBlackBodyWidget::reference() const
+{
+    return plseq_blackbody_reference;
+}
+
+void ColorMapPLSequentialBlackBodyWidget::parameters(int& n, float& temperature, float& range, float& saturation) const
+{
+    n = _n_spinbox->value();
+    temperature = _temperature_changer->value();
+    range = _range_changer->value();
+    saturation = _saturation_changer->value();
+}
+
+void ColorMapPLSequentialBlackBodyWidget::update()
+{
+    if (!_update_lock)
+        emit colorMapChanged();
+}
+
+/* ColorMapPLDivergingLightnessWidget */
+
+ColorMapPLDivergingLightnessWidget::ColorMapPLDivergingLightnessWidget() :
+    _update_lock(false)
+{
+    QGridLayout *layout = new QGridLayout;
+
+    QLabel* n_label = new QLabel("Colors:");
+    layout->addWidget(n_label, 1, 0);
+    _n_spinbox = new QSpinBox();
+    _n_spinbox->setRange(2, 1024);
+    _n_spinbox->setSingleStep(1);
+    layout->addWidget(_n_spinbox, 1, 1, 1, 3);
+
+    QLabel* lightness_label = new QLabel("Lightness:");
+    layout->addWidget(lightness_label, 2, 0);
+    _lightness_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
+    layout->addWidget(_lightness_changer->slider, 2, 1, 1, 2);
+    layout->addWidget(_lightness_changer->spinbox, 2, 3);
 
     QLabel* saturation_label = new QLabel("Saturation:");
     layout->addWidget(saturation_label, 3, 0);
@@ -771,12 +928,9 @@ ColorMapIsoluminantQualitativeWidget::ColorMapIsoluminantQualitativeWidget() :
 
     QLabel* divergence_label = new QLabel("Divergence:");
     layout->addWidget(divergence_label, 5, 0);
-    ColorMapCombinedSliderSpinBox* divergence_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
-    layout->addWidget(divergence_changer->slider, 5, 1, 1, 2);
-    layout->addWidget(divergence_changer->spinbox, 5, 3);
-    hideWidgetButPreserveSize(divergence_label);
-    hideWidgetButPreserveSize(divergence_changer->slider);
-    hideWidgetButPreserveSize(divergence_changer->spinbox);
+    _divergence_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
+    layout->addWidget(_divergence_changer->slider, 5, 1, 1, 2);
+    layout->addWidget(_divergence_changer->spinbox, 5, 3);
 
     layout->setColumnStretch(1, 1);
     layout->addItem(new QSpacerItem(0, 0), 6, 0, 1, 4);
@@ -784,59 +938,62 @@ ColorMapIsoluminantQualitativeWidget::ColorMapIsoluminantQualitativeWidget() :
     setLayout(layout);
 
     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
-    connect(_luminance_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_lightness_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_divergence_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     reset();
 }
 
-ColorMapIsoluminantQualitativeWidget::~ColorMapIsoluminantQualitativeWidget()
+ColorMapPLDivergingLightnessWidget::~ColorMapPLDivergingLightnessWidget()
 {
 }
 
-void ColorMapIsoluminantQualitativeWidget::reset()
+void ColorMapPLDivergingLightnessWidget::reset()
 {
     _update_lock = true;
-    _n_spinbox->setValue(9);
-    _luminance_changer->setValue(ColorMap::IsoluminantQualitativeDefaultLuminance);
-    _saturation_changer->setValue(ColorMap::IsoluminantQualitativeDefaultSaturation);
-    _hue_changer->setValue(qRadiansToDegrees(ColorMap::IsoluminantQualitativeDefaultHue));
+    _n_spinbox->setValue(257);
+    _lightness_changer->setValue(ColorMap::PLDivergingLightnessDefaultLightness);
+    _saturation_changer->setValue(ColorMap::PLDivergingLightnessDefaultSaturation);
+    _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLDivergingLightnessDefaultHue));
+    _divergence_changer->setValue(qRadiansToDegrees(ColorMap::PLDivergingLightnessDefaultDivergence));
     _update_lock = false;
     update();
 }
 
-QVector<QColor> ColorMapIsoluminantQualitativeWidget::colorMap() const
+QVector<QColor> ColorMapPLDivergingLightnessWidget::colorMap() const
 {
     int n;
-    float l, s, h;
-    parameters(n, l, s, h);
+    float l, s, h, d;
+    parameters(n, l, s, h, d);
     QVector<unsigned char> colormap(3 * n);
-    ColorMap::IsoluminantQualitative(n, colormap.data(), l, s, h);
+    ColorMap::PLDivergingLightness(n, colormap.data(), l, s, h, d);
     return toQColor(colormap);
 }
 
-QString ColorMapIsoluminantQualitativeWidget::reference() const
+QString ColorMapPLDivergingLightnessWidget::reference() const
 {
-    return isoluminant_qual_reference;
+    return pldiv_lightness_reference;
 }
 
-void ColorMapIsoluminantQualitativeWidget::parameters(int& n, float& luminance, float& saturation, float& hue) const
+void ColorMapPLDivergingLightnessWidget::parameters(int& n, float& lightness, float& saturation, float& hue, float& divergence) const
 {
     n = _n_spinbox->value();
-    luminance = _luminance_changer->value();
+    lightness = _lightness_changer->value();
     saturation = _saturation_changer->value();
     hue = qDegreesToRadians(_hue_changer->value());
+    divergence = qDegreesToRadians(_divergence_changer->value());
 }
 
-void ColorMapIsoluminantQualitativeWidget::update()
+void ColorMapPLDivergingLightnessWidget::update()
 {
     if (!_update_lock)
         emit colorMapChanged();
 }
 
-/* ColorMapUniformRainbowWidget */
+/* ColorMapPLDivergingSaturationWidget */
 
-ColorMapUniformRainbowWidget::ColorMapUniformRainbowWidget() :
+ColorMapPLDivergingSaturationWidget::ColorMapPLDivergingSaturationWidget() :
     _update_lock(false)
 {
     QGridLayout *layout = new QGridLayout;
@@ -848,84 +1005,92 @@ ColorMapUniformRainbowWidget::ColorMapUniformRainbowWidget() :
     _n_spinbox->setSingleStep(1);
     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
 
+    QLabel* lightness_label = new QLabel("Lightness:");
+    layout->addWidget(lightness_label, 2, 0);
+    _lightness_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
+    layout->addWidget(_lightness_changer->slider, 2, 1, 1, 2);
+    layout->addWidget(_lightness_changer->spinbox, 2, 3);
+
+    QLabel* saturation_label = new QLabel("Saturation:");
+    layout->addWidget(saturation_label, 3, 0);
+    _saturation_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
+    layout->addWidget(_saturation_changer->slider, 3, 1, 1, 2);
+    layout->addWidget(_saturation_changer->spinbox, 3, 3);
+
     QLabel* hue_label = new QLabel("Hue:");
-    layout->addWidget(hue_label, 2, 0);
+    layout->addWidget(hue_label, 4, 0);
     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
-    layout->addWidget(_hue_changer->slider, 2, 1, 1, 2);
-    layout->addWidget(_hue_changer->spinbox, 2, 3);
-
-    QLabel* rotations_label = new QLabel("Rotations:");
-    layout->addWidget(rotations_label, 3, 0);
-    _rotations_changer = new ColorMapCombinedSliderSpinBox(-5.0f, +5.0f, 0.1f);
-    layout->addWidget(_rotations_changer->slider, 3, 1, 1, 2);
-    layout->addWidget(_rotations_changer->spinbox, 3, 3);
+    layout->addWidget(_hue_changer->slider, 4, 1, 1, 2);
+    layout->addWidget(_hue_changer->spinbox, 4, 3);
 
-    QLabel* saturation_label = new QLabel("Saturation:");
-    layout->addWidget(saturation_label, 4, 0);
-    _saturation_changer = new ColorMapCombinedSliderSpinBox(0.0f, 5.0f, 0.1f);
-    layout->addWidget(_saturation_changer->slider, 4, 1, 1, 2);
-    layout->addWidget(_saturation_changer->spinbox, 4, 3);
+    QLabel* divergence_label = new QLabel("Divergence:");
+    layout->addWidget(divergence_label, 5, 0);
+    _divergence_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
+    layout->addWidget(_divergence_changer->slider, 5, 1, 1, 2);
+    layout->addWidget(_divergence_changer->spinbox, 5, 3);
 
     layout->setColumnStretch(1, 1);
-    layout->addItem(new QSpacerItem(0, 0), 5, 0, 1, 4);
-    layout->setRowStretch(5, 1);
+    layout->addItem(new QSpacerItem(0, 0), 6, 0, 1, 4);
+    layout->setRowStretch(6, 1);
     setLayout(layout);
 
     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
-    connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
-    connect(_rotations_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_lightness_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_divergence_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     reset();
 }
 
-ColorMapUniformRainbowWidget::~ColorMapUniformRainbowWidget()
+ColorMapPLDivergingSaturationWidget::~ColorMapPLDivergingSaturationWidget()
 {
 }
 
-void ColorMapUniformRainbowWidget::reset()
+void ColorMapPLDivergingSaturationWidget::reset()
 {
     _update_lock = true;
-    _n_spinbox->setValue(256);
-    _hue_changer->setValue(qRadiansToDegrees(ColorMap::UniformRainbowDefaultHue));
-    _rotations_changer->setValue(ColorMap::UniformRainbowDefaultRotations);
-    _saturation_changer->setValue(ColorMap::UniformRainbowDefaultSaturation);
+    _n_spinbox->setValue(257);
+    _lightness_changer->setValue(ColorMap::PLDivergingSaturationDefaultLightness);
+    _saturation_changer->setValue(ColorMap::PLDivergingSaturationDefaultSaturation);
+    _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLDivergingSaturationDefaultHue));
+    _divergence_changer->setValue(qRadiansToDegrees(ColorMap::PLDivergingSaturationDefaultDivergence));
     _update_lock = false;
     update();
 }
 
-QVector<QColor> ColorMapUniformRainbowWidget::colorMap() const
+QVector<QColor> ColorMapPLDivergingSaturationWidget::colorMap() const
 {
     int n;
-    float h, r, s;
-    parameters(n, h, r, s);
+    float l, s, h, d;
+    parameters(n, l, s, h, d);
     QVector<unsigned char> colormap(3 * n);
-    ColorMap::UniformRainbow(n, colormap.data(), h, r, s);
+    ColorMap::PLDivergingSaturation(n, colormap.data(), l, s, h, d);
     return toQColor(colormap);
 }
 
-QString ColorMapUniformRainbowWidget::reference() const
+QString ColorMapPLDivergingSaturationWidget::reference() const
 {
-    return uniformrainbow_reference;
+    return pldiv_saturation_reference;
 }
 
-void ColorMapUniformRainbowWidget::parameters(int& n, float& hue,
-        float& rotations, float& saturation) const
+void ColorMapPLDivergingSaturationWidget::parameters(int& n, float& lightness, float& saturation, float& hue, float& divergence) const
 {
     n = _n_spinbox->value();
-    hue = qDegreesToRadians(_hue_changer->value());
-    rotations = _rotations_changer->value();
+    lightness = _lightness_changer->value();
     saturation = _saturation_changer->value();
+    hue = qDegreesToRadians(_hue_changer->value());
+    divergence = qDegreesToRadians(_divergence_changer->value());
 }
 
-void ColorMapUniformRainbowWidget::update()
+void ColorMapPLDivergingSaturationWidget::update()
 {
     if (!_update_lock)
         emit colorMapChanged();
 }
 
-/* ColorMapBlackBodyWidget */
+/* ColorMapPLQualitativeHueWidget */
 
-ColorMapBlackBodyWidget::ColorMapBlackBodyWidget() :
+ColorMapPLQualitativeHueWidget::ColorMapPLQualitativeHueWidget() :
     _update_lock(false)
 {
     QGridLayout *layout = new QGridLayout;
@@ -933,27 +1098,27 @@ ColorMapBlackBodyWidget::ColorMapBlackBodyWidget() :
     QLabel* n_label = new QLabel("Colors:");
     layout->addWidget(n_label, 1, 0);
     _n_spinbox = new QSpinBox();
-    _n_spinbox->setRange(2, 10240);
+    _n_spinbox->setRange(2, 1024);
     _n_spinbox->setSingleStep(1);
     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
 
-    QLabel* temperature_label = new QLabel("Temperature (K):");
-    layout->addWidget(temperature_label, 2, 0);
-    _temperature_changer = new ColorMapCombinedSliderSpinBox(250.0f, 20000.0f, 100.0f);
-    layout->addWidget(_temperature_changer->slider, 2, 1, 1, 2);
-    layout->addWidget(_temperature_changer->spinbox, 2, 3);
-
-    QLabel* range_label = new QLabel("Range (K):");
-    layout->addWidget(range_label, 3, 0);
-    _range_changer = new ColorMapCombinedSliderSpinBox(0.0f, 20000.0f, 100.0f);
-    layout->addWidget(_range_changer->slider, 3, 1, 1, 2);
-    layout->addWidget(_range_changer->spinbox, 3, 3);
+    QLabel* lightness_label = new QLabel("Lightness:");
+    layout->addWidget(lightness_label, 2, 0);
+    _lightness_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
+    layout->addWidget(_lightness_changer->slider, 2, 1, 1, 2);
+    layout->addWidget(_lightness_changer->spinbox, 2, 3);
 
     QLabel* saturation_label = new QLabel("Saturation:");
-    layout->addWidget(saturation_label, 4, 0);
-    _saturation_changer = new ColorMapCombinedSliderSpinBox(0.0f, 5.0f, 0.1f);
-    layout->addWidget(_saturation_changer->slider, 4, 1, 1, 2);
-    layout->addWidget(_saturation_changer->spinbox, 4, 3);
+    layout->addWidget(saturation_label, 3, 0);
+    _saturation_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
+    layout->addWidget(_saturation_changer->slider, 3, 1, 1, 2);
+    layout->addWidget(_saturation_changer->spinbox, 3, 3);
+
+    QLabel* hue_label = new QLabel("Hue:");
+    layout->addWidget(hue_label, 4, 0);
+    _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
+    layout->addWidget(_hue_changer->slider, 4, 1, 1, 2);
+    layout->addWidget(_hue_changer->spinbox, 4, 3);
 
     layout->setColumnStretch(1, 1);
     layout->addItem(new QSpacerItem(0, 0), 5, 0, 1, 4);
@@ -961,51 +1126,51 @@ ColorMapBlackBodyWidget::ColorMapBlackBodyWidget() :
     setLayout(layout);
 
     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
-    connect(_temperature_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
-    connect(_range_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_lightness_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
+    connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
     reset();
 }
 
-ColorMapBlackBodyWidget::~ColorMapBlackBodyWidget()
+ColorMapPLQualitativeHueWidget::~ColorMapPLQualitativeHueWidget()
 {
 }
 
-void ColorMapBlackBodyWidget::reset()
+void ColorMapPLQualitativeHueWidget::reset()
 {
     _update_lock = true;
-    _n_spinbox->setValue(256);
-    _temperature_changer->setValue(ColorMap::BlackBodyDefaultTemperature);
-    _range_changer->setValue(ColorMap::BlackBodyDefaultRange);
-    _saturation_changer->setValue(ColorMap::BlackBodyDefaultSaturation);
+    _n_spinbox->setValue(9);
+    _lightness_changer->setValue(ColorMap::PLQualitativeHueDefaultLightness);
+    _saturation_changer->setValue(ColorMap::PLQualitativeHueDefaultSaturation);
+    _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLQualitativeHueDefaultHue));
     _update_lock = false;
     update();
 }
 
-QVector<QColor> ColorMapBlackBodyWidget::colorMap() const
+QVector<QColor> ColorMapPLQualitativeHueWidget::colorMap() const
 {
     int n;
-    float t, r, s;
-    parameters(n, t, r, s);
+    float l, s, h;
+    parameters(n, l, s, h);
     QVector<unsigned char> colormap(3 * n);
-    ColorMap::BlackBody(n, colormap.data(), t, r, s);
+    ColorMap::PLQualitativeHue(n, colormap.data(), l, s, h);
     return toQColor(colormap);
 }
 
-QString ColorMapBlackBodyWidget::reference() const
+QString ColorMapPLQualitativeHueWidget::reference() const
 {
-    return blackbody_reference;
+    return plqual_hue_reference;
 }
 
-void ColorMapBlackBodyWidget::parameters(int& n, float& temperature, float& range, float& saturation) const
+void ColorMapPLQualitativeHueWidget::parameters(int& n, float& lightness, float& saturation, float& hue) const
 {
     n = _n_spinbox->value();
-    temperature = _temperature_changer->value();
-    range = _range_changer->value();
+    lightness = _lightness_changer->value();
     saturation = _saturation_changer->value();
+    hue = qDegreesToRadians(_hue_changer->value());
 }
 
-void ColorMapBlackBodyWidget::update()
+void ColorMapPLQualitativeHueWidget::update()
 {
     if (!_update_lock)
         emit colorMapChanged();
index aa52422..ac42732 100644 (file)
@@ -160,115 +160,159 @@ public:
             float& contrast, float& saturation, float& brightness) const;
 };
 
-class ColorMapIsoluminantSequentialWidget : public ColorMapWidget
+class ColorMapPLSequentialLightnessWidget : public ColorMapWidget
 {
 Q_OBJECT
 private:
     bool _update_lock;
     QSpinBox* _n_spinbox;
-    ColorMapCombinedSliderSpinBox* _luminance_changer;
     ColorMapCombinedSliderSpinBox* _saturation_changer;
     ColorMapCombinedSliderSpinBox* _hue_changer;
 private slots:
     void update();
 
 public:
-    ColorMapIsoluminantSequentialWidget();
-    ~ColorMapIsoluminantSequentialWidget();
+    ColorMapPLSequentialLightnessWidget();
+    ~ColorMapPLSequentialLightnessWidget();
 
     void reset() override;
     QVector<QColor> colorMap() const override;
     QString reference() const override;
-    void parameters(int& n, float& luminance, float& saturation, float& hue) const;
+    void parameters(int& n, float& saturation, float& hue) const;
 };
 
-class ColorMapIsoluminantDivergingWidget : public ColorMapWidget
+class ColorMapPLSequentialSaturationWidget : public ColorMapWidget
 {
 Q_OBJECT
 private:
     bool _update_lock;
     QSpinBox* _n_spinbox;
-    ColorMapCombinedSliderSpinBox* _luminance_changer;
+    ColorMapCombinedSliderSpinBox* _lightness_changer;
     ColorMapCombinedSliderSpinBox* _saturation_changer;
     ColorMapCombinedSliderSpinBox* _hue_changer;
-    ColorMapCombinedSliderSpinBox* _divergence_changer;
 private slots:
     void update();
 
 public:
-    ColorMapIsoluminantDivergingWidget();
-    ~ColorMapIsoluminantDivergingWidget();
+    ColorMapPLSequentialSaturationWidget();
+    ~ColorMapPLSequentialSaturationWidget();
 
     void reset() override;
     QVector<QColor> colorMap() const override;
     QString reference() const override;
-    void parameters(int& n, float& luminance, float& saturation, float& hue, float& divergence) const;
+    void parameters(int& n, float& lightness, float& saturation, float& hue) const;
 };
 
-class ColorMapIsoluminantQualitativeWidget : public ColorMapWidget
+class ColorMapPLSequentialRainbowWidget : public ColorMapWidget
 {
 Q_OBJECT
 private:
     bool _update_lock;
     QSpinBox* _n_spinbox;
-    ColorMapCombinedSliderSpinBox* _luminance_changer;
-    ColorMapCombinedSliderSpinBox* _saturation_changer;
     ColorMapCombinedSliderSpinBox* _hue_changer;
+    ColorMapCombinedSliderSpinBox* _rotations_changer;
+    ColorMapCombinedSliderSpinBox* _saturation_changer;
 private slots:
     void update();
 
 public:
-    ColorMapIsoluminantQualitativeWidget();
-    ~ColorMapIsoluminantQualitativeWidget();
+    ColorMapPLSequentialRainbowWidget();
+    ~ColorMapPLSequentialRainbowWidget();
 
     void reset() override;
     QVector<QColor> colorMap() const override;
     QString reference() const override;
-    void parameters(int& n, float& luminance, float& saturation, float& hue) const;
+    void parameters(int& n, float& hue, float& rotations, float& saturation) const;
 };
 
-class ColorMapUniformRainbowWidget : public ColorMapWidget
+class ColorMapPLSequentialBlackBodyWidget : public ColorMapWidget
 {
 Q_OBJECT
 private:
     bool _update_lock;
     QSpinBox* _n_spinbox;
+    ColorMapCombinedSliderSpinBox* _temperature_changer;
+    ColorMapCombinedSliderSpinBox* _range_changer;
+    ColorMapCombinedSliderSpinBox* _saturation_changer;
+private slots:
+    void update();
+
+public:
+    ColorMapPLSequentialBlackBodyWidget();
+    ~ColorMapPLSequentialBlackBodyWidget();
+
+    void reset() override;
+    QVector<QColor> colorMap() const override;
+    QString reference() const override;
+    void parameters(int& n, float& temperature, float& range, float& saturation) const;
+};
+
+class ColorMapPLDivergingLightnessWidget : public ColorMapWidget
+{
+Q_OBJECT
+private:
+    bool _update_lock;
+    QSpinBox* _n_spinbox;
+    ColorMapCombinedSliderSpinBox* _lightness_changer;
+    ColorMapCombinedSliderSpinBox* _saturation_changer;
     ColorMapCombinedSliderSpinBox* _hue_changer;
-    ColorMapCombinedSliderSpinBox* _rotations_changer;
+    ColorMapCombinedSliderSpinBox* _divergence_changer;
+private slots:
+    void update();
+
+public:
+    ColorMapPLDivergingLightnessWidget();
+    ~ColorMapPLDivergingLightnessWidget();
+
+    void reset() override;
+    QVector<QColor> colorMap() const override;
+    QString reference() const override;
+    void parameters(int& n, float& lightness, float& saturation, float& hue, float& divergence) const;
+};
+
+class ColorMapPLDivergingSaturationWidget : public ColorMapWidget
+{
+Q_OBJECT
+private:
+    bool _update_lock;
+    QSpinBox* _n_spinbox;
+    ColorMapCombinedSliderSpinBox* _lightness_changer;
     ColorMapCombinedSliderSpinBox* _saturation_changer;
+    ColorMapCombinedSliderSpinBox* _hue_changer;
+    ColorMapCombinedSliderSpinBox* _divergence_changer;
 private slots:
     void update();
 
 public:
-    ColorMapUniformRainbowWidget();
-    ~ColorMapUniformRainbowWidget();
+    ColorMapPLDivergingSaturationWidget();
+    ~ColorMapPLDivergingSaturationWidget();
 
     void reset() override;
     QVector<QColor> colorMap() const override;
     QString reference() const override;
-    void parameters(int& n, float& hue, float& rotations, float& saturation) const;
+    void parameters(int& n, float& lightness, float& saturation, float& hue, float& divergence) const;
 };
 
-class ColorMapBlackBodyWidget : public ColorMapWidget
+class ColorMapPLQualitativeHueWidget : public ColorMapWidget
 {
 Q_OBJECT
 private:
     bool _update_lock;
     QSpinBox* _n_spinbox;
-    ColorMapCombinedSliderSpinBox* _temperature_changer;
-    ColorMapCombinedSliderSpinBox* _range_changer;
+    ColorMapCombinedSliderSpinBox* _lightness_changer;
     ColorMapCombinedSliderSpinBox* _saturation_changer;
+    ColorMapCombinedSliderSpinBox* _hue_changer;
 private slots:
     void update();
 
 public:
-    ColorMapBlackBodyWidget();
-    ~ColorMapBlackBodyWidget();
+    ColorMapPLQualitativeHueWidget();
+    ~ColorMapPLQualitativeHueWidget();
 
     void reset() override;
     QVector<QColor> colorMap() const override;
     QString reference() const override;
-    void parameters(int& n, float& temperature, float& range, float& saturation) const;
+    void parameters(int& n, float& lightness, float& saturation, float& hue) const;
 };
 
 class ColorMapCubeHelixWidget : public ColorMapWidget
diff --git a/gui.cpp b/gui.cpp
index 74065bd..6597cf3 100644 (file)
--- a/gui.cpp
+++ b/gui.cpp
@@ -46,22 +46,26 @@ GUI::GUI()
     _brewerseq_widget = new ColorMapBrewerSequentialWidget;
     _brewerdiv_widget = new ColorMapBrewerDivergingWidget;
     _brewerqual_widget = new ColorMapBrewerQualitativeWidget;
-    _isolumseq_widget = new ColorMapIsoluminantSequentialWidget;
-    _isolumdiv_widget = new ColorMapIsoluminantDivergingWidget;
-    _isolumqual_widget = new ColorMapIsoluminantQualitativeWidget;
-    _unirainbow_widget = new ColorMapUniformRainbowWidget;
-    _blackbody_widget = new ColorMapBlackBodyWidget;
+    _plseq_lightness_widget = new ColorMapPLSequentialLightnessWidget;
+    _plseq_saturation_widget = new ColorMapPLSequentialSaturationWidget;
+    _plseq_rainbow_widget = new ColorMapPLSequentialRainbowWidget;
+    _plseq_blackbody_widget = new ColorMapPLSequentialBlackBodyWidget;
+    _pldiv_lightness_widget = new ColorMapPLDivergingLightnessWidget;
+    _pldiv_saturation_widget = new ColorMapPLDivergingSaturationWidget;
+    _plqual_hue_widget = new ColorMapPLQualitativeHueWidget;
     _cubehelix_widget = new ColorMapCubeHelixWidget;
     _moreland_widget = new ColorMapMorelandWidget;
     _mcnames_widget = new ColorMapMcNamesWidget;
     connect(_brewerseq_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
     connect(_brewerdiv_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
     connect(_brewerqual_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
-    connect(_isolumseq_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
-    connect(_isolumdiv_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
-    connect(_isolumqual_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
-    connect(_unirainbow_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
-    connect(_blackbody_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
+    connect(_plseq_lightness_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
+    connect(_plseq_saturation_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
+    connect(_plseq_rainbow_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
+    connect(_plseq_blackbody_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
+    connect(_pldiv_lightness_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
+    connect(_pldiv_saturation_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
+    connect(_plqual_hue_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
     connect(_cubehelix_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
     connect(_moreland_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
     connect(_mcnames_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
@@ -73,22 +77,24 @@ GUI::GUI()
     _category_widget = new QTabWidget();
     _category_seq_widget = new QTabWidget();
     _category_seq_widget->addTab(_brewerseq_widget, "Brewer-like");
-    _category_seq_widget->addTab(_isolumseq_widget, "Isoluminant");
-    _category_seq_widget->addTab(_blackbody_widget, "Black Body");
-    _category_seq_widget->addTab(_unirainbow_widget, "Uniform Rainbow");
+    _category_seq_widget->addTab(_plseq_lightness_widget, "PL Lightness");
+    _category_seq_widget->addTab(_plseq_saturation_widget, "PL Saturation");
+    _category_seq_widget->addTab(_plseq_rainbow_widget, "PL Rainbow");
+    _category_seq_widget->addTab(_plseq_blackbody_widget, "PL Black Body");
     _category_seq_widget->addTab(_cubehelix_widget, "CubeHelix");
     //_category_seq_widget->addTab(_mcnames_widget, "McNames");
     connect(_category_seq_widget, SIGNAL(currentChanged(int)), this, SLOT(update()));
     _category_widget->addTab(_category_seq_widget, "Sequential");
     _category_div_widget = new QTabWidget();
     _category_div_widget->addTab(_brewerdiv_widget, "Brewer-like");
-    _category_div_widget->addTab(_isolumdiv_widget, "Isoluminant");
+    _category_div_widget->addTab(_pldiv_lightness_widget, "PL Lightness");
+    _category_div_widget->addTab(_pldiv_saturation_widget, "PL Saturation");
     _category_div_widget->addTab(_moreland_widget, "Moreland");
     connect(_category_div_widget, SIGNAL(currentChanged(int)), this, SLOT(update()));
     _category_widget->addTab(_category_div_widget, "Diverging");
     _category_qual_widget = new QTabWidget();
     _category_qual_widget->addTab(_brewerqual_widget, "Brewer-like");
-    _category_qual_widget->addTab(_isolumqual_widget, "Isoluminant");
+    _category_qual_widget->addTab(_plqual_hue_widget, "PL Hue");
     connect(_category_qual_widget, SIGNAL(currentChanged(int)), this, SLOT(update()));
     _category_widget->addTab(_category_qual_widget, "Qualitative");
     connect(_category_widget, SIGNAL(currentChanged(int)), this, SLOT(update()));
diff --git a/gui.hpp b/gui.hpp
index c569a0a..3fb23f9 100644 (file)
--- a/gui.hpp
+++ b/gui.hpp
@@ -30,11 +30,13 @@ class ColorMapWidget;
 class ColorMapBrewerSequentialWidget;
 class ColorMapBrewerDivergingWidget;
 class ColorMapBrewerQualitativeWidget;
-class ColorMapIsoluminantSequentialWidget;
-class ColorMapIsoluminantDivergingWidget;
-class ColorMapIsoluminantQualitativeWidget;
-class ColorMapUniformRainbowWidget;
-class ColorMapBlackBodyWidget;
+class ColorMapPLSequentialLightnessWidget;
+class ColorMapPLSequentialSaturationWidget;
+class ColorMapPLSequentialRainbowWidget;
+class ColorMapPLSequentialBlackBodyWidget;
+class ColorMapPLDivergingLightnessWidget;
+class ColorMapPLDivergingSaturationWidget;
+class ColorMapPLQualitativeHueWidget;
 class ColorMapCubeHelixWidget;
 class ColorMapMorelandWidget;
 class ColorMapMcNamesWidget;
@@ -54,11 +56,13 @@ private:
     ColorMapBrewerSequentialWidget* _brewerseq_widget;
     ColorMapBrewerDivergingWidget* _brewerdiv_widget;
     ColorMapBrewerQualitativeWidget* _brewerqual_widget;
-    ColorMapIsoluminantSequentialWidget* _isolumseq_widget;
-    ColorMapIsoluminantDivergingWidget* _isolumdiv_widget;
-    ColorMapIsoluminantQualitativeWidget* _isolumqual_widget;
-    ColorMapUniformRainbowWidget* _unirainbow_widget;
-    ColorMapBlackBodyWidget* _blackbody_widget;
+    ColorMapPLSequentialLightnessWidget *_plseq_lightness_widget;
+    ColorMapPLSequentialSaturationWidget *_plseq_saturation_widget;
+    ColorMapPLSequentialRainbowWidget *_plseq_rainbow_widget;
+    ColorMapPLSequentialBlackBodyWidget *_plseq_blackbody_widget;
+    ColorMapPLDivergingLightnessWidget *_pldiv_lightness_widget;
+    ColorMapPLDivergingSaturationWidget *_pldiv_saturation_widget;
+    ColorMapPLQualitativeHueWidget *_plqual_hue_widget;
     ColorMapCubeHelixWidget* _cubehelix_widget;
     ColorMapMorelandWidget* _moreland_widget;
     ColorMapMcNamesWidget* _mcnames_widget;