1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkColorSeries.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #include "vtkColorSeries.h"
17 
18 #include "vtkLookupTable.h"
19 #include "vtkObjectFactory.h"
20 
21 #include <sstream>
22 #include <vector>
23 
24 //------------------------------------------------------------------------------
25 class vtkColorSeriesPalette
26 {
27 public:
28   std::vector<vtkColor3ub> Colors;
29   vtkStdString Name;
30 };
31 
32 //------------------------------------------------------------------------------
33 class vtkColorSeries::Private
34 {
35 public:
36   Private();
37 
38   void SetScheme(int idx);
39   int SetSchemeByName(const vtkStdString& name, bool& modified);
40 
41   std::vector<vtkColorSeriesPalette> Palettes; // All palettes
42   int Palette;                                 // Currently-selected entry in Palettes
43   std::vector<vtkColor3ub>* Colors;            // Pointer to colors in current scheme
44 };
45 
46 //------------------------------------------------------------------------------
vtkColor3ubFromHex3(vtkTypeUInt32 hex)47 inline vtkColor3ub vtkColor3ubFromHex3(vtkTypeUInt32 hex)
48 {
49   int b = hex & 0xff;
50   hex >>= 8;
51   int g = hex & 0xff;
52   hex >>= 8;
53   int r = hex & 0xff;
54   return vtkColor3ub(r, g, b);
55 }
56 
57 //------------------------------------------------------------------------------
Private()58 vtkColorSeries::Private::Private()
59 {
60   this->Palettes.resize(vtkColorSeries::CUSTOM);
61   // clang-format off
62   vtkTypeUInt32 colors[] = {
63     // Original vtkColorSeries palettes, not part of the Brewer schemes
64     vtkColorSeries::SPECTRUM,
65     0x000000, 0xE41A1C, 0x377EB8, 0x4DAF4A, 0x984EA3, 0xFF7F00, 0xA65628,
66     vtkColorSeries::WARM,
67     0x791717, 0xB50101, 0xEF4719, 0xF98324, 0xFFB400, 0xFFE506,
68     vtkColorSeries::COOL,
69     0x75B101, 0x588029, 0x50D7BF, 0x1C95CD, 0x3B68AB, 0x9A68FF, 0x5F3380,
70     vtkColorSeries::BLUES,
71     0x3B68AB, 0x1C95CD, 0x4ED9EA, 0x739AD5, 0x423DA9, 0x505487, 0x102A52,
72     vtkColorSeries::WILD_FLOWER,
73     0x1C95CD, 0x3B68AB, 0x663EB7, 0xA254CF, 0xDE61CE, 0xDC6195, 0x3D1052,
74     vtkColorSeries::CITRUS,
75     0x657C37, 0x75B101, 0xB2BA30, 0xFFE506, 0xFFB400, 0xF98324,
76 
77 /*
78 The following palettes are colors from www.ColorBrewer2.org by
79 Cynthia A. Brewer, Geography, Pennsylvania State University.
80 Use the sentence above or the following bibliography entry to credit her:
81 
82 + Brewer, Cynthia A. and Mark Harrower and Andy Woodruff and David Heyman,
83   2010. http://ColorBrewer2.org, accessed 2010-Nov-9.
84 
85 The color schemes below are copyright under the following license, excerpted
86 from http://www.personal.psu.edu/cab38/ColorBrewer/ColorBrewer_updates.html
87 on August 13, 2012:
88 
89     Apache-Style Software License for ColorBrewer software and
90     ColorBrewer Color Schemes
91 
92     Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania
93     State University.
94 
95     Licensed under the Apache License, Version 2.0 (the "License"); you may not
96     use this file except in compliance with the License.
97     You may obtain a copy of the License at
98 
99     http://www.apache.org/licenses/LICENSE-2.0
100 
101     Unless required by applicable law or agreed to in writing, software
102     distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
103     WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
104     License for the specific language governing permissions and limitations
105     under the License.
106 
107 This text from my earlier Apache License Version 1.1 also remains in place for
108 guidance on attribution and permissions:
109 
110     Redistribution and use in source and binary forms, with or without
111     modification, are permitted provided that the following conditions are met:
112     1. Redistributions as source code must retain the above copyright notice,
113        this list of conditions and the following disclaimer.
114     2. The end-user documentation included with the redistribution, if any, must
115        include the following acknowledgment:
116        "This product includes color specifications and designs developed by
117        Cynthia Brewer (http://colorbrewer.org/)."
118        Alternately, this acknowledgment may appear in the software itself, if
119        and wherever such third-party acknowledgments normally appear.
120     4. The name "ColorBrewer" must not be used to endorse or promote products
121        derived from this software without prior written permission. For written
122        permission, please contact Cynthia Brewer at cbrewer@psu.edu.
123     5. Products derived from this software may not be called "ColorBrewer", nor
124        may "ColorBrewer" appear in their name, without prior written permission
125        of Cynthia Brewer.
126 */
127     // Diverging
128     //   Purple-Orange
129     vtkColorSeries::BREWER_DIVERGING_PURPLE_ORANGE_11,
130     0x7F3B08, 0xB35806, 0xE08214, 0xFDB863, 0xFEE0B6, 0xF7F7F7, 0xD8DAEB, 0xB2ABD2, 0x8073AC, 0x542788, 0x2D004B,
131     vtkColorSeries::BREWER_DIVERGING_PURPLE_ORANGE_10,
132     0x7F3B08, 0xB35806, 0xE08214, 0xFDB863, 0xFEE0B6, 0xD8DAEB, 0xB2ABD2, 0x8073AC, 0x542788, 0x2D004B,
133     vtkColorSeries::BREWER_DIVERGING_PURPLE_ORANGE_9,
134     0xB35806, 0xE08214, 0xFDB863, 0xFEE0B6, 0xF7F7F7, 0xD8DAEB, 0xB2ABD2, 0x8073AC, 0x542788,
135     vtkColorSeries::BREWER_DIVERGING_PURPLE_ORANGE_8,
136     0xB35806, 0xE08214, 0xFDB863, 0xFEE0B6, 0xD8DAEB, 0xB2ABD2, 0x8073AC, 0x542788,
137     vtkColorSeries::BREWER_DIVERGING_PURPLE_ORANGE_7,
138     0xB35806, 0xF1A340, 0xFEE0B6, 0xF7F7F7, 0xD8DAEB, 0x998EC3, 0x542788,
139     vtkColorSeries::BREWER_DIVERGING_PURPLE_ORANGE_6,
140     0xB35806, 0xF1A340, 0xFEE0B6, 0xD8DAEB, 0x998EC3, 0x542788,
141     vtkColorSeries::BREWER_DIVERGING_PURPLE_ORANGE_5,
142     0xE66101, 0xFDB863, 0xF7F7F7, 0xB2ABD2, 0x5E3C99,
143     vtkColorSeries::BREWER_DIVERGING_PURPLE_ORANGE_4,
144     0xE66101, 0xFDB863, 0xB2ABD2, 0x5E3C99,
145     vtkColorSeries::BREWER_DIVERGING_PURPLE_ORANGE_3,
146     0xF1A340, 0xF7F7F7, 0x998EC3,
147     //   Spectral
148     vtkColorSeries::BREWER_DIVERGING_SPECTRAL_11,
149     0x9E0142, 0xD53E4F, 0xF46D43, 0xFDAE61, 0xFEE08B, 0xFFFFBF, 0xE6F598, 0xABDDA4, 0x66C2A5, 0x3288BD, 0x5E4FA2,
150     vtkColorSeries::BREWER_DIVERGING_SPECTRAL_10,
151     0x9E0142, 0xD53E4F, 0xF46D43, 0xFDAE61, 0xFEE08B, 0xE6F598, 0xABDDA4, 0x66C2A5, 0x3288BD, 0x5E4FA2,
152     vtkColorSeries::BREWER_DIVERGING_SPECTRAL_9,
153     0xD53E4F, 0xF46D43, 0xFDAE61, 0xFEE08B, 0xFFFFBF, 0xE6F598, 0xABDDA4, 0x66C2A5, 0x3288BD,
154     vtkColorSeries::BREWER_DIVERGING_SPECTRAL_8,
155     0xD53E4F, 0xF46D43, 0xFDAE61, 0xFEE08B, 0xE6F598, 0xABDDA4, 0x66C2A5, 0x3288BD,
156     vtkColorSeries::BREWER_DIVERGING_SPECTRAL_7,
157     0xD53E4F, 0xFC8D59, 0xFEE08B, 0xFFFFBF, 0xE6F598, 0x99D594, 0x3288BD,
158     vtkColorSeries::BREWER_DIVERGING_SPECTRAL_6,
159     0xD53E4F, 0xFC8D59, 0xFEE08B, 0xE6F598, 0x99D594, 0x3288BD,
160     vtkColorSeries::BREWER_DIVERGING_SPECTRAL_5,
161     0xD7191C, 0xFDAE61, 0xFFFFBF, 0xABDDA4, 0x2B83BA,
162     vtkColorSeries::BREWER_DIVERGING_SPECTRAL_4,
163     0xD7191C, 0xFDAE61, 0xABDDA4, 0x2B83BA,
164     vtkColorSeries::BREWER_DIVERGING_SPECTRAL_3,
165     0xFC8D59, 0xFFFFBF, 0x99D594,
166     //   Brown-Blue-Green
167     vtkColorSeries::BREWER_DIVERGING_BROWN_BLUE_GREEN_11,
168     0x543005, 0x8C510A, 0xBF812D, 0xDFC27D, 0xF6E8C3, 0xF5F5F5, 0xC7EAE5, 0x80CDC1, 0x35978F, 0x01665E, 0x003C30,
169     vtkColorSeries::BREWER_DIVERGING_BROWN_BLUE_GREEN_10,
170     0x543005, 0x8C510A, 0xBF812D, 0xDFC27D, 0xF6E8C3, 0xC7EAE5, 0x80CDC1, 0x35978F, 0x01665E, 0x003C30,
171     vtkColorSeries::BREWER_DIVERGING_BROWN_BLUE_GREEN_9,
172     0x8C510A, 0xBF812D, 0xDFC27D, 0xF6E8C3, 0xF5F5F5, 0xC7EAE5, 0x80CDC1, 0x35978F, 0x01665E,
173     vtkColorSeries::BREWER_DIVERGING_BROWN_BLUE_GREEN_8,
174     0x8C510A, 0xBF812D, 0xDFC27D, 0xF6E8C3, 0xC7EAE5, 0x80CDC1, 0x35978F, 0x01665E,
175     vtkColorSeries::BREWER_DIVERGING_BROWN_BLUE_GREEN_7,
176     0x8C510A, 0xD8B365, 0xF6E8C3, 0xF5F5F5, 0xC7EAE5, 0x5AB4AC, 0x01665E,
177     vtkColorSeries::BREWER_DIVERGING_BROWN_BLUE_GREEN_6,
178     0x8C510A, 0xD8B365, 0xF6E8C3, 0xC7EAE5, 0x5AB4AC, 0x01665E,
179     vtkColorSeries::BREWER_DIVERGING_BROWN_BLUE_GREEN_5,
180     0xA6611A, 0xDFC27D, 0xF5F5F5, 0x80CDC1, 0x018571,
181     vtkColorSeries::BREWER_DIVERGING_BROWN_BLUE_GREEN_4,
182     0xA6611A, 0xDFC27D, 0x80CDC1, 0x018571,
183     vtkColorSeries::BREWER_DIVERGING_BROWN_BLUE_GREEN_3,
184     0xD8B365, 0xF5F5F5, 0x5AB4AC,
185     // Sequential Palettes
186     //   Blue-Green
187     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_GREEN_9,
188     0xF7FCFD, 0xE5F5F9, 0xCCECE6, 0x99D8C9, 0x66C2A4, 0x41AE76, 0x238B45, 0x006D2C, 0x00441B,
189     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_GREEN_8,
190     0xF7FCFD, 0xE5F5F9, 0xCCECE6, 0x99D8C9, 0x66C2A4, 0x41AE76, 0x238B45, 0x005824,
191     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_GREEN_7,
192     0xEDF8FB, 0xCCECE6, 0xCCECE6, 0x66C2A4, 0x41AE76, 0x238B45, 0x005824,
193     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_GREEN_6,
194     0xEDF8FB, 0xCCECE6, 0x99D8C9, 0x66C2A4, 0x2CA25F, 0x006D2C,
195     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_GREEN_5,
196     0xEDF8FB, 0xB2E2E2, 0x66C2A4, 0x2CA25F, 0x006D2C,
197     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_GREEN_4,
198     0xEDF8FB, 0xB2E2E2, 0x66C2A4, 0x238B45,
199     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_GREEN_3,
200     0xE5F5F9, 0x99D8C9, 0x2CA25F,
201     //   Yellow-Orange-Brown
202     vtkColorSeries::BREWER_SEQUENTIAL_YELLOW_ORANGE_BROWN_9,
203     0xFFFFE5, 0xFFF7BC, 0xFEE391, 0xFEC44F, 0xFE9929, 0xEC7014, 0xCC4C02, 0x993404, 0x662506,
204     vtkColorSeries::BREWER_SEQUENTIAL_YELLOW_ORANGE_BROWN_8,
205     0xFFFFE5, 0xFFF7BC, 0xFEE391, 0xFEC44F, 0xFE9929, 0xEC7014, 0xCC4C02, 0x8C2D04,
206     vtkColorSeries::BREWER_SEQUENTIAL_YELLOW_ORANGE_BROWN_7,
207     0xFFFFD4, 0xFEE391, 0xFEC44F, 0xFE9929, 0xEC7014, 0xCC4C02, 0x8C2D04,
208     vtkColorSeries::BREWER_SEQUENTIAL_YELLOW_ORANGE_BROWN_6,
209     0xFFFFD4, 0xFEE391, 0xFEC44F, 0xFE9929, 0xD95F0E, 0x993404,
210     vtkColorSeries::BREWER_SEQUENTIAL_YELLOW_ORANGE_BROWN_5,
211     0xFFFFD4, 0xFED98E, 0xFE9929, 0xD95F0E, 0x993404,
212     vtkColorSeries::BREWER_SEQUENTIAL_YELLOW_ORANGE_BROWN_4,
213     0xFFFFD4, 0xFED98E, 0xFE9929, 0xCC4C02,
214     vtkColorSeries::BREWER_SEQUENTIAL_YELLOW_ORANGE_BROWN_3,
215     0xFFF7BC, 0xFEC44F, 0xD95F0E,
216     //   Blue-Purple
217     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_PURPLE_9,
218     0xF7FCFD, 0xE0ECF4, 0xBFD3E6, 0x9EBCDA, 0x8C96C6, 0x8C6BB1, 0x88419D, 0x810F7C, 0x4D004B,
219     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_PURPLE_8,
220     0xF7FCFD, 0xE0ECF4, 0xBFD3E6, 0x9EBCDA, 0x8C96C6, 0x8C6BB1, 0x88419D, 0x6E016B,
221     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_PURPLE_7,
222     0xEDF8FB, 0xBFD3E6, 0x9EBCDA, 0x8C96C6, 0x8C6BB1, 0x88419D, 0x6E016B,
223     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_PURPLE_6,
224     0xEDF8FB, 0xBFD3E6, 0x9EBCDA, 0x8C96C6, 0x8856A7, 0x810F7C,
225     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_PURPLE_5,
226     0xEDF8FB, 0xB3CDE3, 0x8C96C6, 0x8856A7, 0x810F7C,
227     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_PURPLE_4,
228     0xEDF8FB, 0xB3CDE3, 0x8C96C6, 0x88419D,
229     vtkColorSeries::BREWER_SEQUENTIAL_BLUE_PURPLE_3,
230     0xE0ECF4, 0x9EBCDA, 0x8856A7,
231     // Qualitative Palettes
232     //   Accent
233     vtkColorSeries::BREWER_QUALITATIVE_ACCENT,
234     0x7FC97F, 0xBEAED4, 0xFDC086, 0xFFFF99, 0x386CB0, 0xF0027F, 0xBF5B17, 0x666666,
235     //   Dark2
236     vtkColorSeries::BREWER_QUALITATIVE_DARK2,
237     0x1B9E77, 0xD95F02, 0x7570B3, 0xE7298A, 0x66A61E, 0xE6AB02, 0xA6761D, 0x666666,
238     //   Set2
239     vtkColorSeries::BREWER_QUALITATIVE_SET2,
240     0x66C2A5, 0xFC8D62, 0x8DA0CB, 0xE78AC3, 0xA6D854, 0xFFD92F, 0xE5C494, 0xB3B3B3,
241     //   Pastel2
242     vtkColorSeries::BREWER_QUALITATIVE_PASTEL2,
243     0xB3E2CD, 0xFDCDAC, 0xCBD5E8, 0xF4CAE4, 0xE6F5C9, 0xFFF2AE, 0xF1E2CC, 0xCCCCCC,
244     //   Pastel1
245     vtkColorSeries::BREWER_QUALITATIVE_PASTEL1,
246     0xFBB4AE, 0xB3CDE3, 0xCCEBC5, 0xDECBE4, 0xFED9A6, 0xFFFFCC, 0xE5D8BD, 0xFDDAEC, 0xF2F2F2,
247     //   Set1
248     vtkColorSeries::BREWER_QUALITATIVE_SET1,
249     0xE41A1C, 0x377EB8, 0x4DAF4A, 0x984EA3, 0xFF7F00, 0xFFFF33, 0xA65628, 0xF781BF, 0x999999,
250     //   Paired
251     vtkColorSeries::BREWER_QUALITATIVE_PAIRED,
252     0xA6CEE3, 0x1F78B4, 0xB2DF8A, 0x33A02C, 0xFB9A99, 0xE31A1C, 0xFDBF6F, 0xFF7F00, 0xCAB2D6, 0x6A3D9A, 0xFFFF99,
253     //   Set3
254     vtkColorSeries::BREWER_QUALITATIVE_SET3,
255     0x8DD3C7, 0xFFFFB3, 0xBEBADA, 0xFB8072, 0x80B1D3, 0xFDB462, 0xB3DE69, 0xFCCDE5, 0xD9D9D9, 0xBC80BD, 0xCCEBC5, 0xFFED6F,
256   };
257   // clang-format on
258   const char* names[] = {
259     "Spectrum",
260     "Warm",
261     "Cool",
262     "Blues",
263     "Wild Flower",
264     "Citrus",
265 
266     "Brewer Diverging Purple-Orange",
267     "Brewer Diverging Spectral",
268     "Brewer Diverging Brown-Blue-Green",
269 
270     "Brewer Sequential Blue-Green",
271     "Brewer Sequential Yellow-Orange-Brown",
272     "Brewer Sequential Blue-Purple",
273 
274     "Brewer Qualitative Accent",
275     "Brewer Qualitative Dark2",
276     "Brewer Qualitative Set2",
277     "Brewer Qualitative Pastel2",
278     "Brewer Qualitative Pastel1",
279     "Brewer Qualitative Set1",
280     "Brewer Qualitative Paired",
281     "Brewer Qualitative Set3",
282   };
283   int sizes[][2] = {
284     { 7, 7 },
285     { 6, 6 },
286     { 7, 7 },
287     { 7, 7 },
288     { 7, 7 },
289     { 6, 6 },
290 
291     { 11, 3 },
292     { 11, 3 },
293     { 11, 3 },
294     { 9, 3 },
295     { 9, 3 },
296     { 9, 3 },
297     { 8, 8 },
298     { 8, 8 },
299     { 8, 8 },
300     { 8, 8 },
301     { 9, 9 },
302     { 9, 9 },
303     { 11, 11 },
304     { 12, 12 },
305   };
306   vtkTypeUInt32* color = colors;
307   vtkColorSeriesPalette* pal;
308   for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); ++i)
309   {
310     int start = sizes[i][0];
311     int stop = sizes[i][1];
312     int step = start > stop ? -1 : 1;
313     for (int n = start; n != stop + step; n += step)
314     {
315       int paletteIndex = *(color++);
316       pal = &(this->Palettes[paletteIndex]);
317       std::ostringstream os;
318       os << names[i];
319       if (start != stop)
320       {
321         os << " (" << n << ")";
322       }
323       pal->Name = os.str();
324       for (int j = 0; j < n; ++j)
325       {
326         pal->Colors.push_back(vtkColor3ubFromHex3(*(color++)));
327       }
328     }
329   }
330   this->Colors = nullptr;
331   this->Palette = vtkColorSeries::SPECTRUM;
332   this->Colors = &(this->Palettes[this->Palette].Colors);
333 }
334 
335 //------------------------------------------------------------------------------
SetScheme(int idx)336 void vtkColorSeries::Private::SetScheme(int idx)
337 {
338   this->Colors = &(this->Palettes[idx].Colors);
339   this->Palette = idx;
340 }
341 
342 //------------------------------------------------------------------------------
SetSchemeByName(const vtkStdString & name,bool & modified)343 int vtkColorSeries::Private::SetSchemeByName(const vtkStdString& name, bool& modified)
344 {
345   modified = false;
346   int idx = 0;
347   std::vector<vtkColorSeriesPalette>::iterator it;
348   for (it = this->Palettes.begin(); it != this->Palettes.end(); ++it, ++idx)
349   {
350     if (it->Name == name)
351     {
352       this->SetScheme(idx);
353       return idx;
354     }
355   }
356   // OK, we could not find such a palette. Create one.
357   modified = true;
358   vtkColorSeriesPalette blank;
359   blank.Name = name;
360   idx = static_cast<int>(this->Palettes.size());
361   this->Palettes.push_back(blank);
362   this->SetScheme(idx);
363   return idx;
364 }
365 
366 //------------------------------------------------------------------------------
367 //------------------------------------------------------------------------------
368 vtkStandardNewMacro(vtkColorSeries);
369 
370 //------------------------------------------------------------------------------
vtkColorSeries()371 vtkColorSeries::vtkColorSeries()
372 {
373   this->Storage = new vtkColorSeries::Private;
374   this->SetColorScheme(vtkColorSeries::SPECTRUM);
375 }
376 
377 //------------------------------------------------------------------------------
~vtkColorSeries()378 vtkColorSeries::~vtkColorSeries()
379 {
380   delete this->Storage;
381   this->Storage = nullptr;
382 }
383 
384 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)385 void vtkColorSeries::PrintSelf(ostream& os, vtkIndent indent)
386 {
387   this->Superclass::PrintSelf(os, indent);
388   int pidx = this->Storage->Palette;
389   vtkColorSeriesPalette* palette = &(this->Storage->Palettes[pidx]);
390   os << indent << "ColorScheme: " << pidx << endl
391      << indent
392      << "ColorSchemeName : " << (palette->Name.empty() ? "(empty)" : palette->Name.c_str()) << endl;
393 }
394 
395 //------------------------------------------------------------------------------
SetColorScheme(int scheme)396 void vtkColorSeries::SetColorScheme(int scheme)
397 {
398   if (this->Storage->Palette == scheme)
399   {
400     return;
401   }
402 
403   if (scheme < 0 || scheme >= this->GetNumberOfColorSchemes())
404   {
405     vtkWarningMacro(<< "Scheme " << scheme << " out of range. Ignoring.");
406     return;
407   }
408 
409   this->Storage->SetScheme(scheme);
410   this->Modified();
411 }
412 
413 //------------------------------------------------------------------------------
SetColorSchemeByName(const vtkStdString & schemeName)414 int vtkColorSeries::SetColorSchemeByName(const vtkStdString& schemeName)
415 {
416   bool modified;
417   int index = this->Storage->SetSchemeByName(schemeName, modified);
418   if (modified)
419   {
420     this->Modified();
421   }
422   return index;
423 }
424 
425 //------------------------------------------------------------------------------
GetNumberOfColorSchemes() const426 int vtkColorSeries::GetNumberOfColorSchemes() const
427 {
428   return static_cast<int>(this->Storage->Palettes.size());
429 }
430 
431 //------------------------------------------------------------------------------
GetColorSchemeName() const432 vtkStdString vtkColorSeries::GetColorSchemeName() const
433 {
434   return this->Storage->Palettes[this->Storage->Palette].Name;
435 }
436 
437 //------------------------------------------------------------------------------
SetColorSchemeName(const vtkStdString & name)438 void vtkColorSeries::SetColorSchemeName(const vtkStdString& name)
439 {
440   // Ignore empty names
441   // TODO: Should we prohibit duplicate names? If not,
442   // how about searching backwards through palettes in
443   // SetColorSchemeByName() so users can override
444   // system defaults?
445   if (name.empty())
446   {
447     return;
448   }
449 
450   this->CopyOnWrite();
451   if (this->Storage->Palettes[this->Storage->Palette].Name != name)
452   {
453     this->Storage->Palettes[this->Storage->Palette].Name = name;
454     this->Modified();
455   }
456 }
457 
458 //------------------------------------------------------------------------------
GetColorScheme() const459 int vtkColorSeries::GetColorScheme() const
460 {
461   return this->Storage->Palette;
462 }
463 
464 //------------------------------------------------------------------------------
GetNumberOfColors() const465 int vtkColorSeries::GetNumberOfColors() const
466 {
467   return static_cast<int>(this->Storage->Colors->size());
468 }
469 
470 //------------------------------------------------------------------------------
SetNumberOfColors(int numColors)471 void vtkColorSeries::SetNumberOfColors(int numColors)
472 {
473   this->CopyOnWrite();
474   this->Storage->Colors->resize(numColors);
475 }
476 
477 //------------------------------------------------------------------------------
GetColor(int index) const478 vtkColor3ub vtkColorSeries::GetColor(int index) const
479 {
480   if (index >= 0 && index < static_cast<int>(this->Storage->Colors->size()))
481   {
482     return (*this->Storage->Colors)[index];
483   }
484   else
485   {
486     return vtkColor3ub(0, 0, 0);
487   }
488 }
489 
490 //------------------------------------------------------------------------------
GetColorRepeating(int index) const491 vtkColor3ub vtkColorSeries::GetColorRepeating(int index) const
492 {
493   vtkColor3ub color;
494   int numColors = this->GetNumberOfColors();
495   // If we have an empty palette, index % numColors generates a divide-by-zero
496   // fault, and if it did return a valid value, looking up the resulting color
497   // would be an access violation. So, be careful here:
498   color = numColors ? (*this->Storage->Colors)[index % numColors] : vtkColor3ub(0, 0, 0);
499   return color;
500 }
501 
502 //------------------------------------------------------------------------------
SetColor(int index,const vtkColor3ub & color)503 void vtkColorSeries::SetColor(int index, const vtkColor3ub& color)
504 {
505   if (index >= 0 && index < static_cast<int>(this->Storage->Colors->size()))
506   {
507     this->CopyOnWrite();
508     (*this->Storage->Colors)[index] = color;
509     this->Modified();
510   }
511 }
512 
513 //------------------------------------------------------------------------------
AddColor(const vtkColor3ub & color)514 void vtkColorSeries::AddColor(const vtkColor3ub& color)
515 {
516   this->CopyOnWrite();
517   this->Storage->Colors->push_back(color);
518   this->Modified();
519 }
520 
521 //------------------------------------------------------------------------------
InsertColor(int index,const vtkColor3ub & color)522 void vtkColorSeries::InsertColor(int index, const vtkColor3ub& color)
523 {
524   if (index >= 0 && index < static_cast<int>(this->Storage->Colors->size()))
525   {
526     this->CopyOnWrite();
527     this->Storage->Colors->insert(this->Storage->Colors->begin() + index, color);
528     this->Modified();
529   }
530 }
531 
532 //------------------------------------------------------------------------------
RemoveColor(int index)533 void vtkColorSeries::RemoveColor(int index)
534 {
535   if (index >= 0 && index < static_cast<int>(this->Storage->Colors->size()))
536   {
537     this->CopyOnWrite();
538     this->Storage->Colors->erase(this->Storage->Colors->begin() + index);
539     this->Modified();
540   }
541 }
542 
543 //------------------------------------------------------------------------------
ClearColors()544 void vtkColorSeries::ClearColors()
545 {
546   this->CopyOnWrite();
547   this->Storage->Colors->clear();
548   this->Modified();
549 }
550 
551 //------------------------------------------------------------------------------
DeepCopy(vtkColorSeries * colors)552 void vtkColorSeries::DeepCopy(vtkColorSeries* colors)
553 {
554   if (!colors)
555   {
556     return;
557   }
558 
559   this->Storage->Palettes = colors->Storage->Palettes;
560   this->Storage->Palette = colors->Storage->Palette;
561   this->Storage->Colors = &(this->Storage->Palettes[this->Storage->Palette].Colors);
562   this->Modified();
563 }
564 
565 //------------------------------------------------------------------------------
BuildLookupTable(vtkLookupTable * lkup,int lutIndexing)566 void vtkColorSeries::BuildLookupTable(vtkLookupTable* lkup, int lutIndexing)
567 {
568   if (lkup)
569   {
570     lkup->SetNumberOfTableValues(this->GetNumberOfColors());
571     lkup->SetIndexedLookup((lutIndexing == ORDINAL) ? 0 : 1);
572     for (int i = 0; i < this->GetNumberOfColors(); ++i)
573     {
574       vtkColor3ub colr = this->GetColor(i);
575       lkup->SetTableValue(
576         i, colr.GetRed() / 255., colr.GetGreen() / 255., colr.GetBlue() / 255., 1.);
577     }
578   }
579 }
580 
581 //------------------------------------------------------------------------------
CreateLookupTable(int lutIndexing)582 vtkLookupTable* vtkColorSeries::CreateLookupTable(int lutIndexing)
583 {
584   vtkLookupTable* lkup = vtkLookupTable::New();
585   this->BuildLookupTable(lkup, lutIndexing);
586   return lkup;
587 }
588 
589 //------------------------------------------------------------------------------
CopyOnWrite()590 void vtkColorSeries::CopyOnWrite()
591 {
592   // If the current scheme is predefined, copy it to a new, custom scheme.
593   int prevScheme = this->Storage->Palette;
594   if (prevScheme < CUSTOM)
595   {
596     int nextScheme = static_cast<int>(this->Storage->Palettes.size());
597     vtkColorSeriesPalette blank;
598     blank.Name = this->Storage->Palettes[prevScheme].Name + " copy";
599     this->Storage->Palettes.push_back(blank);
600     this->Storage->SetScheme(nextScheme);
601     *this->Storage->Colors = this->Storage->Palettes[prevScheme].Colors;
602     this->Modified();
603   }
604 }
605