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