1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkApplyColors.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   Copyright 2008 Sandia Corporation.
17   Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
18   the U.S. Government retains certain rights in this software.
19 -------------------------------------------------------------------------*/
20 #include "vtkApplyColors.h"
21 
22 #include "vtkAnnotation.h"
23 #include "vtkAnnotationLayers.h"
24 #include "vtkCellData.h"
25 #include "vtkConvertSelection.h"
26 #include "vtkDataSet.h"
27 #include "vtkGraph.h"
28 #include "vtkIdTypeArray.h"
29 #include "vtkInformation.h"
30 #include "vtkInformationVector.h"
31 #include "vtkObjectFactory.h"
32 #include "vtkPointData.h"
33 #include "vtkScalarsToColors.h"
34 #include "vtkSmartPointer.h"
35 #include "vtkTable.h"
36 #include "vtkUnsignedCharArray.h"
37 
38 vtkStandardNewMacro(vtkApplyColors);
39 vtkCxxSetObjectMacro(vtkApplyColors, PointLookupTable, vtkScalarsToColors);
40 vtkCxxSetObjectMacro(vtkApplyColors, CellLookupTable, vtkScalarsToColors);
41 
vtkApplyColors()42 vtkApplyColors::vtkApplyColors()
43 {
44   this->PointLookupTable = nullptr;
45   this->CellLookupTable = nullptr;
46   this->DefaultPointColor[0] = 0.0;
47   this->DefaultPointColor[1] = 0.0;
48   this->DefaultPointColor[2] = 0.0;
49   this->DefaultPointOpacity = 1.0;
50   this->DefaultCellColor[0] = 0.0;
51   this->DefaultCellColor[1] = 0.0;
52   this->DefaultCellColor[2] = 0.0;
53   this->DefaultCellOpacity = 1.0;
54   this->SelectedPointColor[0] = 0.0;
55   this->SelectedPointColor[1] = 0.0;
56   this->SelectedPointColor[2] = 0.0;
57   this->SelectedPointOpacity = 1.0;
58   this->SelectedCellColor[0] = 0.0;
59   this->SelectedCellColor[1] = 0.0;
60   this->SelectedCellColor[2] = 0.0;
61   this->SelectedCellOpacity = 1.0;
62   this->SetNumberOfInputPorts(2);
63   this->SetInputArrayToProcess(
64     0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_VERTICES, vtkDataSetAttributes::SCALARS);
65   this->SetInputArrayToProcess(
66     1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_EDGES, vtkDataSetAttributes::SCALARS);
67   this->ScalePointLookupTable = true;
68   this->ScaleCellLookupTable = true;
69   this->UsePointLookupTable = false;
70   this->UseCellLookupTable = false;
71   this->PointColorOutputArrayName = nullptr;
72   this->CellColorOutputArrayName = nullptr;
73   this->SetPointColorOutputArrayName("vtkApplyColors color");
74   this->SetCellColorOutputArrayName("vtkApplyColors color");
75   this->UseCurrentAnnotationColor = false;
76 }
77 
~vtkApplyColors()78 vtkApplyColors::~vtkApplyColors()
79 {
80   this->SetPointLookupTable(nullptr);
81   this->SetCellLookupTable(nullptr);
82   this->SetPointColorOutputArrayName(nullptr);
83   this->SetCellColorOutputArrayName(nullptr);
84 }
85 
FillInputPortInformation(int port,vtkInformation * info)86 int vtkApplyColors::FillInputPortInformation(int port, vtkInformation* info)
87 {
88   if (port == 0)
89   {
90     info->Remove(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE());
91     info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
92     info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGraph");
93     info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable");
94   }
95   else if (port == 1)
96   {
97     info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkAnnotationLayers");
98     info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
99   }
100   return 1;
101 }
102 
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)103 int vtkApplyColors::RequestData(vtkInformation* vtkNotUsed(request),
104   vtkInformationVector** inputVector, vtkInformationVector* outputVector)
105 {
106   // get the info objects
107   vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
108   vtkInformation* layersInfo = inputVector[1]->GetInformationObject(0);
109   vtkInformation* outInfo = outputVector->GetInformationObject(0);
110 
111   if (!this->PointColorOutputArrayName || !this->CellColorOutputArrayName)
112   {
113     vtkErrorMacro("Point and cell array names must be valid");
114     return 0;
115   }
116 
117   // get the input and output
118   vtkDataObject* input = inInfo->Get(vtkDataObject::DATA_OBJECT());
119   vtkAnnotationLayers* layers = nullptr;
120   if (layersInfo)
121   {
122     layers = vtkAnnotationLayers::SafeDownCast(layersInfo->Get(vtkDataObject::DATA_OBJECT()));
123   }
124   vtkDataObject* output = outInfo->Get(vtkDataObject::DATA_OBJECT());
125 
126   output->ShallowCopy(input);
127 
128   vtkGraph* graph = vtkGraph::SafeDownCast(output);
129   vtkDataSet* dataSet = vtkDataSet::SafeDownCast(output);
130   vtkTable* table = vtkTable::SafeDownCast(output);
131 
132   // initialize color arrays
133   vtkSmartPointer<vtkUnsignedCharArray> colorArr1 = vtkSmartPointer<vtkUnsignedCharArray>::New();
134   colorArr1->SetName(this->PointColorOutputArrayName);
135   colorArr1->SetNumberOfComponents(4);
136   if (graph)
137   {
138     colorArr1->SetNumberOfTuples(graph->GetNumberOfVertices());
139     graph->GetVertexData()->AddArray(colorArr1);
140   }
141   else if (dataSet)
142   {
143     colorArr1->SetNumberOfTuples(dataSet->GetNumberOfPoints());
144     dataSet->GetPointData()->AddArray(colorArr1);
145   }
146   else
147   {
148     colorArr1->SetNumberOfTuples(table->GetNumberOfRows());
149     table->AddColumn(colorArr1);
150   }
151   vtkSmartPointer<vtkUnsignedCharArray> colorArr2 = vtkSmartPointer<vtkUnsignedCharArray>::New();
152   colorArr2->SetName(this->CellColorOutputArrayName);
153   colorArr2->SetNumberOfComponents(4);
154   if (graph)
155   {
156     colorArr2->SetNumberOfTuples(graph->GetNumberOfEdges());
157     graph->GetEdgeData()->AddArray(colorArr2);
158   }
159   else if (dataSet)
160   {
161     colorArr2->SetNumberOfTuples(dataSet->GetNumberOfCells());
162     dataSet->GetCellData()->AddArray(colorArr2);
163   }
164 
165   unsigned char pointColor[4];
166   pointColor[0] = static_cast<unsigned char>(255 * this->DefaultPointColor[0]);
167   pointColor[1] = static_cast<unsigned char>(255 * this->DefaultPointColor[1]);
168   pointColor[2] = static_cast<unsigned char>(255 * this->DefaultPointColor[2]);
169   pointColor[3] = static_cast<unsigned char>(255 * this->DefaultPointOpacity);
170   vtkAbstractArray* arr1 = nullptr;
171   if (this->PointLookupTable && this->UsePointLookupTable)
172   {
173     arr1 = this->GetInputAbstractArrayToProcess(0, inputVector);
174   }
175   this->ProcessColorArray(
176     colorArr1, this->PointLookupTable, arr1, pointColor, this->ScalePointLookupTable);
177 
178   unsigned char cellColor[4];
179   cellColor[0] = static_cast<unsigned char>(255 * this->DefaultCellColor[0]);
180   cellColor[1] = static_cast<unsigned char>(255 * this->DefaultCellColor[1]);
181   cellColor[2] = static_cast<unsigned char>(255 * this->DefaultCellColor[2]);
182   cellColor[3] = static_cast<unsigned char>(255 * this->DefaultCellOpacity);
183   vtkAbstractArray* arr2 = nullptr;
184   if (this->CellLookupTable && this->UseCellLookupTable)
185   {
186     arr2 = this->GetInputAbstractArrayToProcess(1, inputVector);
187   }
188   this->ProcessColorArray(
189     colorArr2, this->CellLookupTable, arr2, cellColor, this->ScaleCellLookupTable);
190 
191   if (layers)
192   {
193     vtkSmartPointer<vtkIdTypeArray> list1 = vtkSmartPointer<vtkIdTypeArray>::New();
194     vtkSmartPointer<vtkIdTypeArray> list2 = vtkSmartPointer<vtkIdTypeArray>::New();
195     unsigned char annColor[4] = { 0, 0, 0, 0 };
196     unsigned char prev[4] = { 0, 0, 0, 0 };
197     unsigned int numAnnotations = layers->GetNumberOfAnnotations();
198     for (unsigned int a = 0; a < numAnnotations; ++a)
199     {
200       vtkAnnotation* ann = layers->GetAnnotation(a);
201       if (ann->GetInformation()->Has(vtkAnnotation::ENABLE()) &&
202         ann->GetInformation()->Get(vtkAnnotation::ENABLE()) == 0)
203       {
204         continue;
205       }
206       list1->Initialize();
207       list2->Initialize();
208       vtkSelection* sel = ann->GetSelection();
209       bool hasColor = false;
210       bool hasOpacity = false;
211       if (ann->GetInformation()->Has(vtkAnnotation::COLOR()))
212       {
213         hasColor = true;
214         double* color = ann->GetInformation()->Get(vtkAnnotation::COLOR());
215         annColor[0] = static_cast<unsigned char>(255 * color[0]);
216         annColor[1] = static_cast<unsigned char>(255 * color[1]);
217         annColor[2] = static_cast<unsigned char>(255 * color[2]);
218       }
219       if (ann->GetInformation()->Has(vtkAnnotation::OPACITY()))
220       {
221         hasOpacity = true;
222         double opacity = ann->GetInformation()->Get(vtkAnnotation::OPACITY());
223         annColor[3] = static_cast<unsigned char>(255 * opacity);
224       }
225       if (!hasColor && !hasOpacity)
226       {
227         continue;
228       }
229       if (graph)
230       {
231         vtkConvertSelection::GetSelectedVertices(sel, graph, list1);
232         vtkConvertSelection::GetSelectedEdges(sel, graph, list2);
233       }
234       else if (dataSet)
235       {
236         vtkConvertSelection::GetSelectedPoints(sel, dataSet, list1);
237         vtkConvertSelection::GetSelectedCells(sel, dataSet, list2);
238       }
239       else
240       {
241         vtkConvertSelection::GetSelectedRows(sel, table, list1);
242       }
243       vtkIdType numIds = list1->GetNumberOfTuples();
244       unsigned char curColor[4];
245       for (vtkIdType i = 0; i < numIds; ++i)
246       {
247         if (list1->GetValue(i) >= colorArr1->GetNumberOfTuples())
248         {
249           continue;
250         }
251         colorArr1->GetTypedTuple(list1->GetValue(i), prev);
252         if (hasColor)
253         {
254           curColor[0] = annColor[0];
255           curColor[1] = annColor[1];
256           curColor[2] = annColor[2];
257         }
258         else
259         {
260           curColor[0] = prev[0];
261           curColor[1] = prev[1];
262           curColor[2] = prev[2];
263         }
264         if (hasOpacity)
265         {
266           // Combine opacities
267           curColor[3] = static_cast<unsigned char>((prev[3] / 255.0) * annColor[3]);
268         }
269         else
270         {
271           curColor[3] = prev[3];
272         }
273         colorArr1->SetTypedTuple(list1->GetValue(i), curColor);
274       }
275       numIds = list2->GetNumberOfTuples();
276       for (vtkIdType i = 0; i < numIds; ++i)
277       {
278         if (list2->GetValue(i) >= colorArr2->GetNumberOfTuples())
279         {
280           continue;
281         }
282         colorArr2->GetTypedTuple(list2->GetValue(i), prev);
283         if (hasColor)
284         {
285           curColor[0] = annColor[0];
286           curColor[1] = annColor[1];
287           curColor[2] = annColor[2];
288         }
289         else
290         {
291           curColor[0] = prev[0];
292           curColor[1] = prev[1];
293           curColor[2] = prev[2];
294         }
295         if (hasOpacity)
296         {
297           // Combine opacities
298           curColor[3] = static_cast<unsigned char>((prev[3] / 255.0) * annColor[3]);
299         }
300         else
301         {
302           curColor[3] = prev[3];
303         }
304         colorArr2->SetTypedTuple(list2->GetValue(i), curColor);
305       }
306     }
307     if (vtkAnnotation* ann = layers->GetCurrentAnnotation())
308     {
309       vtkSelection* selection = ann->GetSelection();
310       list1 = vtkSmartPointer<vtkIdTypeArray>::New();
311       list2 = vtkSmartPointer<vtkIdTypeArray>::New();
312       unsigned char color1[4] = { 0, 0, 0, 255 };
313       unsigned char color2[4] = { 0, 0, 0, 255 };
314       if (this->UseCurrentAnnotationColor)
315       {
316         if (ann->GetInformation()->Has(vtkAnnotation::COLOR()))
317         {
318           double* color = ann->GetInformation()->Get(vtkAnnotation::COLOR());
319           color1[0] = static_cast<unsigned char>(255 * color[0]);
320           color1[1] = static_cast<unsigned char>(255 * color[1]);
321           color1[2] = static_cast<unsigned char>(255 * color[2]);
322         }
323         if (ann->GetInformation()->Has(vtkAnnotation::OPACITY()))
324         {
325           double opacity = ann->GetInformation()->Get(vtkAnnotation::OPACITY());
326           color1[3] = static_cast<unsigned char>(255 * opacity);
327         }
328         for (int c = 0; c < 4; ++c)
329         {
330           color2[c] = color1[c];
331         }
332       }
333       else
334       {
335         color1[0] = static_cast<unsigned char>(255 * this->SelectedPointColor[0]);
336         color1[1] = static_cast<unsigned char>(255 * this->SelectedPointColor[1]);
337         color1[2] = static_cast<unsigned char>(255 * this->SelectedPointColor[2]);
338         color1[3] = static_cast<unsigned char>(255 * this->SelectedPointOpacity);
339         color2[0] = static_cast<unsigned char>(255 * this->SelectedCellColor[0]);
340         color2[1] = static_cast<unsigned char>(255 * this->SelectedCellColor[1]);
341         color2[2] = static_cast<unsigned char>(255 * this->SelectedCellColor[2]);
342         color2[3] = static_cast<unsigned char>(255 * this->SelectedCellOpacity);
343       }
344       if (graph)
345       {
346         vtkConvertSelection::GetSelectedVertices(selection, graph, list1);
347         vtkConvertSelection::GetSelectedEdges(selection, graph, list2);
348       }
349       else if (dataSet)
350       {
351         vtkConvertSelection::GetSelectedPoints(selection, dataSet, list1);
352         vtkConvertSelection::GetSelectedCells(selection, dataSet, list2);
353       }
354       else
355       {
356         vtkConvertSelection::GetSelectedRows(selection, table, list1);
357       }
358       vtkIdType numIds = list1->GetNumberOfTuples();
359       for (vtkIdType i = 0; i < numIds; ++i)
360       {
361         if (list1->GetValue(i) >= colorArr1->GetNumberOfTuples())
362         {
363           continue;
364         }
365         colorArr1->SetTypedTuple(list1->GetValue(i), color1);
366       }
367       numIds = list2->GetNumberOfTuples();
368       for (vtkIdType i = 0; i < numIds; ++i)
369       {
370         if (list2->GetValue(i) >= colorArr2->GetNumberOfTuples())
371         {
372           continue;
373         }
374         colorArr2->SetTypedTuple(list2->GetValue(i), color2);
375       }
376     }
377   } // end if (layers)
378 
379   return 1;
380 }
381 
ProcessColorArray(vtkUnsignedCharArray * colorArr,vtkScalarsToColors * lut,vtkAbstractArray * arr,unsigned char color[4],bool scaleToArray)382 void vtkApplyColors::ProcessColorArray(vtkUnsignedCharArray* colorArr, vtkScalarsToColors* lut,
383   vtkAbstractArray* arr, unsigned char color[4], bool scaleToArray)
384 {
385   if (lut && arr)
386   {
387     // If scaling is on, use data min/max.
388     // Otherwise, use the lookup table range.
389     const double* rng = lut->GetRange();
390     double minVal = rng[0];
391     double maxVal = rng[1];
392     if (scaleToArray)
393     {
394       minVal = VTK_DOUBLE_MAX;
395       maxVal = VTK_DOUBLE_MIN;
396       for (vtkIdType i = 0; i < colorArr->GetNumberOfTuples(); ++i)
397       {
398         double val = arr->GetVariantValue(i).ToDouble();
399         if (val > maxVal)
400         {
401           maxVal = val;
402         }
403         if (val < minVal)
404         {
405           minVal = val;
406         }
407       }
408     }
409 
410     // Map the data values through the lookup table.
411     double scale = 1.0;
412     if (minVal != maxVal)
413     {
414       scale = (rng[1] - rng[0]) / (maxVal - minVal);
415     }
416     unsigned char myColor[4] = { 0, 0, 0, 0 };
417     for (vtkIdType i = 0; i < colorArr->GetNumberOfTuples(); ++i)
418     {
419       double val = arr->GetVariantValue(i).ToDouble();
420       const unsigned char* mappedColor = lut->MapValue(rng[0] + scale * (val - minVal));
421       myColor[0] = mappedColor[0];
422       myColor[1] = mappedColor[1];
423       myColor[2] = mappedColor[2];
424       // Combine the opacity of the lookup table with the
425       // default color opacity.
426       myColor[3] = static_cast<unsigned char>((color[3] / 255.0) * mappedColor[3]);
427       colorArr->SetTypedTuple(i, myColor);
428     }
429   }
430   else
431   {
432     // If no lookup table, use default color.
433     for (vtkIdType i = 0; i < colorArr->GetNumberOfTuples(); ++i)
434     {
435       colorArr->SetTypedTuple(i, color);
436     }
437   }
438 }
439 
GetMTime()440 vtkMTimeType vtkApplyColors::GetMTime()
441 {
442   vtkMTimeType mtime = Superclass::GetMTime();
443   if (this->PointLookupTable && this->PointLookupTable->GetMTime() > mtime)
444   {
445     mtime = this->PointLookupTable->GetMTime();
446   }
447   if (this->CellLookupTable && this->CellLookupTable->GetMTime() > mtime)
448   {
449     mtime = this->CellLookupTable->GetMTime();
450   }
451   return mtime;
452 }
453 
PrintSelf(ostream & os,vtkIndent indent)454 void vtkApplyColors::PrintSelf(ostream& os, vtkIndent indent)
455 {
456   this->Superclass::PrintSelf(os, indent);
457   os << indent << "PointLookupTable: " << (this->PointLookupTable ? "" : "(none)") << endl;
458   if (this->PointLookupTable)
459   {
460     this->PointLookupTable->PrintSelf(os, indent.GetNextIndent());
461   }
462   os << indent << "CellLookupTable: " << (this->CellLookupTable ? "" : "(none)") << endl;
463   if (this->CellLookupTable)
464   {
465     this->CellLookupTable->PrintSelf(os, indent.GetNextIndent());
466   }
467   os << indent << "DefaultPointColor: " << this->DefaultPointColor[0] << ","
468      << this->DefaultPointColor[1] << "," << this->DefaultPointColor[2] << endl;
469   os << indent << "DefaultPointOpacity: " << this->DefaultPointOpacity << endl;
470   os << indent << "DefaultCellColor: " << this->DefaultCellColor[0] << ","
471      << this->DefaultCellColor[1] << "," << this->DefaultCellColor[2] << endl;
472   os << indent << "DefaultCellOpacity: " << this->DefaultCellOpacity << endl;
473   os << indent << "SelectedPointColor: " << this->SelectedPointColor[0] << ","
474      << this->SelectedPointColor[1] << "," << this->SelectedPointColor[2] << endl;
475   os << indent << "SelectedPointOpacity: " << this->SelectedPointOpacity << endl;
476   os << indent << "SelectedCellColor: " << this->SelectedCellColor[0] << ","
477      << this->SelectedCellColor[1] << "," << this->SelectedCellColor[2] << endl;
478   os << indent << "SelectedCellOpacity: " << this->SelectedCellOpacity << endl;
479   os << indent << "ScalePointLookupTable: " << (this->ScalePointLookupTable ? "on" : "off") << endl;
480   os << indent << "ScaleCellLookupTable: " << (this->ScaleCellLookupTable ? "on" : "off") << endl;
481   os << indent << "UsePointLookupTable: " << (this->UsePointLookupTable ? "on" : "off") << endl;
482   os << indent << "UseCellLookupTable: " << (this->UseCellLookupTable ? "on" : "off") << endl;
483   os << indent << "PointColorOutputArrayName: "
484      << (this->PointColorOutputArrayName ? this->PointColorOutputArrayName : "(none)") << endl;
485   os << indent << "CellColorOutputArrayName: "
486      << (this->CellColorOutputArrayName ? this->CellColorOutputArrayName : "(none)") << endl;
487   os << indent << "UseCurrentAnnotationColor: " << (this->UseCurrentAnnotationColor ? "on" : "off")
488      << endl;
489 }
490