1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkParallelCoordinatesHistogramRepresentation.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 2009 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 "vtkParallelCoordinatesHistogramRepresentation.h"
21 //------------------------------------------------------------------------------
22 #include "vtkActor2D.h"
23 #include "vtkArrayIteratorIncludes.h"
24 #include "vtkCellArray.h"
25 #include "vtkCellData.h"
26 #include "vtkComputeHistogram2DOutliers.h"
27 #include "vtkDoubleArray.h"
28 #include "vtkExtractHistogram2D.h"
29 #include "vtkExtractSelectedPolyDataIds.h"
30 #include "vtkFloatArray.h"
31 #include "vtkIdList.h"
32 #include "vtkIdTypeArray.h"
33 #include "vtkImageData.h"
34 #include "vtkImageGaussianSmooth.h"
35 #include "vtkImageMedian3D.h"
36 #include "vtkInformation.h"
37 #include "vtkInformationVector.h"
38 #include "vtkLookupTable.h"
39 #include "vtkMath.h"
40 #include "vtkMultiBlockDataSet.h"
41 #include "vtkObjectFactory.h"
42 #include "vtkPairwiseExtractHistogram2D.h"
43 #include "vtkPointData.h"
44 #include "vtkPoints.h"
45 #include "vtkPolyData.h"
46 #include "vtkPolyDataMapper2D.h"
47 #include "vtkPropCollection.h"
48 #include "vtkProperty2D.h"
49 #include "vtkRenderView.h"
50 #include "vtkRenderer.h"
51 #include "vtkSCurveSpline.h"
52 #include "vtkSelection.h"
53 #include "vtkSelectionNode.h"
54 #include "vtkStringArray.h"
55 #include "vtkTable.h"
56 #include "vtkUnsignedIntArray.h"
57 #include "vtkViewTheme.h"
58 //------------------------------------------------------------------------------
59 vtkStandardNewMacro(vtkParallelCoordinatesHistogramRepresentation);
60 //------------------------------------------------------------------------------
vtkParallelCoordinatesHistogramRepresentation()61 vtkParallelCoordinatesHistogramRepresentation::vtkParallelCoordinatesHistogramRepresentation()
62 {
63 this->SetNumberOfInputPorts(vtkParallelCoordinatesHistogramRepresentation::NUM_INPUT_PORTS);
64
65 this->UseHistograms = 0;
66 this->HistogramLookupTableRange[0] = 0.0;
67 this->HistogramLookupTableRange[1] = -1.0;
68
69 this->HistogramFilter = vtkSmartPointer<vtkPairwiseExtractHistogram2D>::New();
70 this->HistogramFilter->SetInputData(this->InputArrayTable);
71
72 this->HistogramLookupTable = vtkSmartPointer<vtkLookupTable>::New();
73 this->HistogramLookupTable->SetAlphaRange(0, 1);
74 this->HistogramLookupTable->SetHueRange(1, 1);
75 this->HistogramLookupTable->SetValueRange(1, 1);
76 this->HistogramLookupTable->SetSaturationRange(0, 0);
77 this->HistogramLookupTable->ForceBuild();
78
79 this->PlotMapper->SetScalarModeToUseCellData();
80 this->PlotMapper->UseLookupTableScalarRangeOn();
81 this->PlotMapper->SetLookupTable(this->HistogramLookupTable);
82 this->PlotMapper->ScalarVisibilityOff();
83
84 this->ShowOutliers = 0;
85
86 this->OutlierFilter = vtkSmartPointer<vtkComputeHistogram2DOutliers>::New();
87 this->OutlierFilter->SetInputData(
88 vtkComputeHistogram2DOutliers::INPUT_TABLE_DATA, this->InputArrayTable);
89 // this->HistogramFilter->GetOutputPort(vtkPairwiseExtractHistogram2D::REORDERED_INPUT));
90 this->OutlierFilter->SetInputConnection(
91 vtkComputeHistogram2DOutliers::INPUT_HISTOGRAMS_MULTIBLOCK,
92 this->HistogramFilter->GetOutputPort(vtkPairwiseExtractHistogram2D::HISTOGRAM_IMAGE));
93
94 this->OutlierData = vtkSmartPointer<vtkPolyData>::New();
95 this->OutlierActor = vtkSmartPointer<vtkActor2D>::New();
96 this->OutlierActor->GetProperty()->SetColor(1, 1, 1);
97 this->OutlierMapper = vtkSmartPointer<vtkPolyDataMapper2D>::New();
98 this->OutlierMapper.TakeReference(
99 this->InitializePlotMapper(this->OutlierData, this->OutlierActor));
100
101 this->SetHistogramLookupTableRange(0, 10);
102 this->SetPreferredNumberOfOutliers(100);
103 this->SetNumberOfHistogramBins(10, 10);
104
105 // Apply default theme
106 // you would think that calling this in the superclass would take care of it,
107 // but it turns out that the superclass constructor will only call its own
108 // version there. So I have to call it again to make sure that the local
109 // version gets called.
110 vtkViewTheme* theme = vtkViewTheme::New();
111 theme->SetCellOpacity(1.0);
112 theme->SetCellColor(1.0, 1.0, 1.0);
113 theme->SetEdgeLabelColor(1.0, .8, .3);
114 this->ApplyViewTheme(theme);
115 theme->Delete();
116 }
117 //------------------------------------------------------------------------------
118 vtkParallelCoordinatesHistogramRepresentation::~vtkParallelCoordinatesHistogramRepresentation() =
119 default;
120 //------------------------------------------------------------------------------
121 // Histogram quad color is defined by theme->CellColor
ApplyViewTheme(vtkViewTheme * theme)122 void vtkParallelCoordinatesHistogramRepresentation::ApplyViewTheme(vtkViewTheme* theme)
123 {
124 this->Superclass::ApplyViewTheme(theme);
125
126 double* c = theme->GetCellColor();
127 double hsv[3] = { 0, 0, 0 };
128 vtkMath::RGBToHSV(c, hsv);
129 this->HistogramLookupTable->SetHueRange(hsv[0], hsv[0]);
130 this->HistogramLookupTable->SetSaturationRange(hsv[1], hsv[1]);
131 this->HistogramLookupTable->SetValueRange(hsv[2], hsv[2]);
132 this->HistogramLookupTable->ForceBuild();
133 }
134 //------------------------------------------------------------------------------
135 // Make sure all of the histogram/outlier stuff is up-to-date. Also, if not using
136 // histograms, make sure that lookup table for the plot data mapper is
137 // disabled, since that's the behavior for the parent class.
ComputeDataProperties()138 int vtkParallelCoordinatesHistogramRepresentation::ComputeDataProperties()
139 {
140 if (!this->Superclass::ComputeDataProperties())
141 return 0;
142
143 if (this->UseHistograms)
144 {
145 this->GetHistogramImage(0);
146 this->SetHistogramLookupTableRange(0, this->HistogramFilter->GetMaximumBinCount());
147 this->HistogramLookupTable->SetRange(
148 this->HistogramLookupTableRange[0], this->HistogramLookupTableRange[1]);
149 this->PlotMapper->ScalarVisibilityOn();
150 }
151 else
152 {
153 this->PlotMapper->ScalarVisibilityOff();
154 }
155
156 if (this->ShowOutliers)
157 {
158 this->OutlierActor->VisibilityOn();
159 }
160 else
161 {
162 this->OutlierActor->VisibilityOff();
163 }
164
165 return 1;
166 }
167 //------------------------------------------------------------------------------
168 // outliers have the same properties as plot lines.
UpdatePlotProperties(vtkStringArray * inputTitles)169 int vtkParallelCoordinatesHistogramRepresentation::UpdatePlotProperties(vtkStringArray* inputTitles)
170 {
171 if (!this->Superclass::UpdatePlotProperties(inputTitles))
172 return 0;
173
174 this->OutlierActor->GetProperty()->SetOpacity(this->LineOpacity);
175 this->OutlierActor->GetProperty()->SetColor(this->LineColor);
176
177 return 1;
178 }
179 //------------------------------------------------------------------------------
RequestData(vtkInformation * request,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)180 int vtkParallelCoordinatesHistogramRepresentation::RequestData(
181 vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
182 {
183 // do everything the superclass does
184 // * histogram quad computation happens automatically since this
185 // class overrides the plotting functions.
186 if (!this->Superclass::RequestData(request, inputVector, outputVector))
187 return 0;
188
189 // but also show outliers
190 if (this->ShowOutliers)
191 {
192 vtkTable* outlierTable = this->GetOutlierData();
193
194 if (this->UseCurves)
195 {
196 vtkParallelCoordinatesRepresentation::PlaceCurves(this->OutlierData, outlierTable, nullptr);
197 }
198 else
199 {
200 vtkParallelCoordinatesRepresentation::PlaceLines(this->OutlierData, outlierTable, nullptr);
201 }
202 }
203
204 this->BuildTime.Modified();
205
206 return 1;
207 }
208 //------------------------------------------------------------------------------
AddToView(vtkView * view)209 bool vtkParallelCoordinatesHistogramRepresentation::AddToView(vtkView* view)
210 {
211 this->Superclass::AddToView(view);
212 vtkRenderView* rv = vtkRenderView::SafeDownCast(view);
213 if (rv)
214 {
215 rv->GetRenderer()->AddActor(this->OutlierActor);
216
217 // not sure what these are for
218 // rv->RegisterProgress(...);
219 return true;
220 }
221 return false;
222 }
223 //------------------------------------------------------------------------------
RemoveFromView(vtkView * view)224 bool vtkParallelCoordinatesHistogramRepresentation::RemoveFromView(vtkView* view)
225 {
226 this->Superclass::RemoveFromView(view);
227 vtkRenderView* rv = vtkRenderView::SafeDownCast(view);
228 if (rv)
229 {
230 rv->GetRenderer()->RemoveActor(this->OutlierActor);
231
232 // not sure what these are for
233 // rv->UnRegisterProgress(this->OutlineMapper);
234 return true;
235 }
236 return false;
237 }
238 //------------------------------------------------------------------------------
239 // redirect the line plotting function to the histogram plotting function,
240 // if histograms are enabled
PlaceLines(vtkPolyData * polyData,vtkTable * data,vtkIdTypeArray * idsToPlot)241 int vtkParallelCoordinatesHistogramRepresentation::PlaceLines(
242 vtkPolyData* polyData, vtkTable* data, vtkIdTypeArray* idsToPlot)
243 {
244 if (this->UseHistograms)
245 {
246 return this->PlaceHistogramLineQuads(polyData);
247 }
248 else
249 {
250 return this->Superclass::PlaceLines(polyData, data, idsToPlot);
251 }
252 }
253 //------------------------------------------------------------------------------
254 // redirect the line plotting function to the histogram plotting function,
255 // if histograms are enabled
PlaceCurves(vtkPolyData * polyData,vtkTable * data,vtkIdTypeArray * idsToPlot)256 int vtkParallelCoordinatesHistogramRepresentation::PlaceCurves(
257 vtkPolyData* polyData, vtkTable* data, vtkIdTypeArray* idsToPlot)
258 {
259 if (this->UseHistograms)
260 {
261 return this->PlaceHistogramCurveQuads(polyData);
262 }
263 else
264 {
265 return this->Superclass::PlaceCurves(polyData, data, idsToPlot);
266 }
267 }
268 //------------------------------------------------------------------------------
269 // this is a bit tricky. This class plots selections as lines, regardless
270 // of whether or not histograms are enabled. That means it needs to explicitly
271 // call the superclass plotting functions on the selection so that the
272 // histogram plotting functions don't get used.
PlaceSelection(vtkPolyData * polyData,vtkTable * data,vtkSelectionNode * selectionNode)273 int vtkParallelCoordinatesHistogramRepresentation::PlaceSelection(
274 vtkPolyData* polyData, vtkTable* data, vtkSelectionNode* selectionNode)
275 {
276 vtkIdTypeArray* selectedIds = vtkArrayDownCast<vtkIdTypeArray>(selectionNode->GetSelectionList());
277 if (!selectedIds)
278 return 1;
279
280 if (this->UseCurves)
281 {
282 this->Superclass::PlaceCurves(polyData, data, selectedIds);
283 }
284 else
285 {
286 this->Superclass::PlaceLines(polyData, data, selectedIds);
287 }
288
289 return 1;
290 }
291 //------------------------------------------------------------------------------
PlaceHistogramLineQuads(vtkPolyData * polyData)292 int vtkParallelCoordinatesHistogramRepresentation::PlaceHistogramLineQuads(vtkPolyData* polyData)
293 {
294 // figure out how many samples there are by looking at each of the
295 // histograms and counting the bins.
296 int numberOfQuads = 0;
297 for (int i = 0; i < this->NumberOfAxes - 1; i++)
298 {
299 vtkImageData* histogram = this->GetHistogramImage(i);
300 if (histogram)
301 numberOfQuads += histogram->GetPointData()->GetScalars()->GetNumberOfTuples();
302 }
303
304 if (this->UseCurves)
305 numberOfQuads *= this->CurveResolution;
306
307 this->AllocatePolyData(polyData, 0, 0, 0, 0, numberOfQuads, numberOfQuads * 4, numberOfQuads, 0);
308
309 vtkPoints* points = polyData->GetPoints();
310 float* pointsp = vtkArrayDownCast<vtkFloatArray>(points->GetData())->GetPointer(0);
311
312 vtkDoubleArray* scalars = vtkArrayDownCast<vtkDoubleArray>(polyData->GetCellData()->GetScalars());
313 double* scalarsp = scalars->GetPointer(
314 0); // vtkArrayDownCast<vtkDoubleArray>(polyData->GetCellData()->GetScalars());
315
316 // for each histogram, draw a quad for each bin.
317 vtkIdType ptId = 0;
318 // vtkIdType quadId=0;
319 for (int pos = 0; pos < this->NumberOfAxes - 1; pos++)
320 {
321 int dims[3] = { 0, 0, 0 };
322 double spacing[3] = { 0, 0, 0 };
323 vtkImageData* image = this->GetHistogramImage(pos);
324 if (!image)
325 continue;
326 image->GetDimensions(dims);
327 image->GetSpacing(spacing);
328
329 double binWidth[] = { (this->YMax - this->YMin) / static_cast<double>(dims[0]),
330 (this->YMax - this->YMin) / static_cast<double>(dims[1]) };
331
332 double x1[3] = { 0., 0., 0. };
333 double x2[3] = { 0., 0., 0. };
334 x1[0] = this->Xs[pos];
335 x2[0] = this->Xs[pos + 1];
336
337 // for each bin, draw a quad
338 for (int y = 0; y < dims[1]; y++)
339 {
340 x2[1] = this->YMin + y * binWidth[1];
341
342 for (int x = 0; x < dims[0]; x++)
343 {
344 x1[1] = this->YMin + x * binWidth[0];
345
346 // the number of rows that fit into this bin
347 double v = image->GetScalarComponentAsDouble(x, y, 0, 0);
348
349 *(pointsp++) = x1[0];
350 *(pointsp++) = x1[1] + binWidth[0];
351 *(pointsp++) = 0.;
352 ptId++;
353 *(pointsp++) = x1[0];
354 *(pointsp++) = x1[1];
355 *(pointsp++) = 0.;
356 ptId++;
357 *(pointsp++) = x2[0];
358 *(pointsp++) = x2[1];
359 *(pointsp++) = 0.;
360 ptId++;
361 *(pointsp++) = x2[0];
362 *(pointsp++) = x2[1] + binWidth[1];
363 *(pointsp++) = 0.;
364 ptId++;
365 // points->SetPoint(ptId++, x1[0], x1[1]+binWidth[0], 0.);
366 // points->SetPoint(ptId++, x1[0], x1[1], 0.);
367 // points->SetPoint(ptId++, x2[0], x2[1], 0.);
368 // points->SetPoint(ptId++, x2[0], x2[1]+binWidth[1], 0.);
369
370 // scalars used for lookup table mapping. More rows
371 // in a bin means bright quad.
372 // scalars->SetTuple1(quadId++,v);
373 *(scalarsp++) = v; //->SetTuple1(quadId++,v);
374 }
375 }
376 }
377
378 polyData->Modified();
379 return 1;
380 }
381 //------------------------------------------------------------------------------
PlaceHistogramCurveQuads(vtkPolyData * polyData)382 int vtkParallelCoordinatesHistogramRepresentation::PlaceHistogramCurveQuads(vtkPolyData* polyData)
383 {
384 // figure out how many samples there are by looking at each of the
385 // histograms and counting the bins.
386 int numberOfStrips = 0;
387 for (int i = 0; i < this->NumberOfAxes - 1; i++)
388 {
389 vtkImageData* histogram = this->GetHistogramImage(i);
390 if (histogram)
391 numberOfStrips += histogram->GetPointData()->GetScalars()->GetNumberOfTuples();
392 }
393
394 int numberOfPointsPerStrip = this->CurveResolution * 2;
395
396 this->AllocatePolyData(polyData, 0, 0, numberOfStrips, numberOfPointsPerStrip, 0,
397 numberOfStrips * numberOfPointsPerStrip, numberOfStrips, 0);
398
399 vtkPoints* points = polyData->GetPoints();
400 float* pointsp = vtkArrayDownCast<vtkFloatArray>(points->GetData())->GetPointer(0);
401
402 vtkDoubleArray* scalars = vtkArrayDownCast<vtkDoubleArray>(polyData->GetCellData()->GetScalars());
403 double* scalarsp = scalars->GetPointer(0);
404
405 // build the default spline
406 vtkSmartPointer<vtkDoubleArray> defSplineValues = vtkSmartPointer<vtkDoubleArray>::New();
407 this->BuildDefaultSCurve(defSplineValues, this->CurveResolution);
408
409 vtkIdType ptId = 0;
410 // vtkIdType stripId = 0;
411 for (int pos = 0; pos < this->NumberOfAxes - 1; pos++)
412 {
413 int dims[3] = { 0, 0, 0 };
414 double spacing[3] = { 0, 0, 0 };
415 vtkImageData* image = this->GetHistogramImage(pos);
416 if (!image)
417 continue;
418 image->GetDimensions(dims);
419 image->GetSpacing(spacing);
420
421 double binWidth[] = { (this->YMax - this->YMin) / static_cast<double>(dims[0]),
422 (this->YMax - this->YMin) / static_cast<double>(dims[1]) };
423
424 double x1[3] = { 0., 0., 0. };
425 double x2[3] = { 0., 0., 0. };
426 double xc[3] = { 0., 0., 0. };
427 double w = 0.0;
428
429 x1[0] = this->Xs[pos];
430 x2[0] = this->Xs[pos + 1];
431
432 double dx = (x2[0] - x1[0]) / static_cast<double>(this->CurveResolution - 1);
433 double dw = binWidth[1] - binWidth[0];
434
435 for (int y = 0; y < dims[1]; y++)
436 {
437 x2[1] = this->YMin + y * binWidth[1];
438
439 for (int x = 0; x < dims[0]; x++)
440 {
441 x1[1] = this->YMin + x * binWidth[0];
442
443 double v = image->GetScalarComponentAsDouble(x, y, 0, 0);
444 double dy = x2[1] - x1[1];
445
446 for (int c = 0; c < this->CurveResolution; c++)
447 {
448 xc[0] = this->Xs[pos] + dx * c;
449 xc[1] = defSplineValues->GetValue(c) * dy +
450 x1[1]; // spline->Evaluate(x1[0]);//spline->Evaluate(x1[0]);
451 w = defSplineValues->GetValue(c) * dw + binWidth[0]; // bwspline->Evaluate(x1[0]);
452
453 // points->SetPoint(ptId++, xc[0], xc[1]+w, 0.);
454 // points->SetPoint(ptId++, xc[0], xc[1], 0.);
455 *(pointsp++) = xc[0];
456 *(pointsp++) = xc[1] + w;
457 *(pointsp++) = 0.0;
458 ptId++;
459 *(pointsp++) = xc[0];
460 *(pointsp++) = xc[1];
461 *(pointsp++) = 0.0;
462 ptId++;
463 }
464
465 *(scalarsp++) = v; //->SetTuple1(stripId++,v);
466 }
467 }
468 }
469
470 polyData->Modified();
471 return 1;
472 }
473 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)474 void vtkParallelCoordinatesHistogramRepresentation::PrintSelf(ostream& os, vtkIndent indent)
475 {
476 this->Superclass::PrintSelf(os, indent);
477 os << "UseHistograms: " << this->UseHistograms << endl;
478 os << "HistogramLookupTableRange: " << this->HistogramLookupTableRange[0] << ","
479 << this->HistogramLookupTableRange[1] << endl;
480 os << "NumberOfHistogramBins: " << this->NumberOfHistogramBins[0] << ","
481 << this->NumberOfHistogramBins[1] << endl;
482 os << "ShowOutliers: " << this->ShowOutliers << endl;
483 os << "PreferredNumberOfOutliers: " << this->PreferredNumberOfOutliers << endl;
484 }
485 //------------------------------------------------------------------------------
SwapAxisPositions(int position1,int position2)486 int vtkParallelCoordinatesHistogramRepresentation::SwapAxisPositions(int position1, int position2)
487 {
488 if (this->Superclass::SwapAxisPositions(position1, position2))
489 {
490 this->HistogramFilter->Modified();
491 if (this->ShowOutliers)
492 this->OutlierFilter->Modified();
493
494 return 1;
495 }
496
497 return 0;
498 }
499 //------------------------------------------------------------------------------
SetRangeAtPosition(int position,double range[2])500 int vtkParallelCoordinatesHistogramRepresentation::SetRangeAtPosition(int position, double range[2])
501 {
502 if (this->Superclass::SetRangeAtPosition(position, range))
503 {
504 this->HistogramFilter->SetCustomColumnRange(position, range);
505 this->HistogramFilter->Modified();
506
507 if (ShowOutliers)
508 this->OutlierFilter->Modified();
509
510 return 1;
511 }
512 return 0;
513 }
514 //------------------------------------------------------------------------------
SetUseHistograms(vtkTypeBool use)515 void vtkParallelCoordinatesHistogramRepresentation::SetUseHistograms(vtkTypeBool use)
516 {
517 if (use && this->UseHistograms != use)
518 {
519 this->HistogramFilter->Modified();
520
521 if (this->ShowOutliers)
522 this->OutlierFilter->Modified();
523 }
524
525 this->UseHistograms = use;
526 this->Modified();
527 }
528 //------------------------------------------------------------------------------
SetShowOutliers(vtkTypeBool show)529 void vtkParallelCoordinatesHistogramRepresentation::SetShowOutliers(vtkTypeBool show)
530 {
531 if (show && this->ShowOutliers != show)
532 {
533 this->HistogramFilter->Modified();
534 this->OutlierFilter->Modified();
535 }
536
537 this->ShowOutliers = show;
538 this->Modified();
539 }
540 //------------------------------------------------------------------------------
SetPreferredNumberOfOutliers(int num)541 void vtkParallelCoordinatesHistogramRepresentation::SetPreferredNumberOfOutliers(int num)
542 {
543 if (num >= 0)
544 {
545 this->PreferredNumberOfOutliers = num;
546 this->OutlierFilter->SetPreferredNumberOfOutliers(num);
547 this->Modified();
548 }
549 }
550 //------------------------------------------------------------------------------
SetNumberOfHistogramBins(int nx,int ny)551 void vtkParallelCoordinatesHistogramRepresentation::SetNumberOfHistogramBins(int nx, int ny)
552 {
553 if (nx > 0 && ny > 0)
554 {
555 this->NumberOfHistogramBins[0] = nx;
556 this->NumberOfHistogramBins[1] = ny;
557
558 this->HistogramFilter->SetNumberOfBins(nx, ny);
559
560 this->Modified();
561 }
562 }
563 //------------------------------------------------------------------------------
SetNumberOfHistogramBins(int * n)564 void vtkParallelCoordinatesHistogramRepresentation::SetNumberOfHistogramBins(int* n)
565 {
566 this->SetNumberOfHistogramBins(n[0], n[1]);
567 }
568 //------------------------------------------------------------------------------
GetHistogramImage(int idx)569 vtkImageData* vtkParallelCoordinatesHistogramRepresentation::GetHistogramImage(int idx)
570 {
571 return this->HistogramFilter->GetOutputHistogramImage(idx);
572 }
573 //------------------------------------------------------------------------------
GetOutlierData()574 vtkTable* vtkParallelCoordinatesHistogramRepresentation::GetOutlierData()
575 {
576 return this->OutlierFilter->GetOutputTable();
577 }
578