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