mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
1922 lines
59 KiB
C++
1922 lines
59 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkScatterPlotMatrix.cxx
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
|
|
#include "vtkScatterPlotMatrix.h"
|
|
|
|
#include "vtkTable.h"
|
|
#include "vtkFloatArray.h"
|
|
#include "vtkIntArray.h"
|
|
#include "vtkChartXY.h"
|
|
#include "vtkPlot.h"
|
|
#include "vtkAxis.h"
|
|
#include "vtkContextMouseEvent.h"
|
|
#include "vtkStdString.h"
|
|
#include "vtkStringArray.h"
|
|
#include "vtkNew.h"
|
|
#include "vtkPen.h"
|
|
#include "vtkMathUtilities.h"
|
|
#include "vtkAnnotationLink.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkBrush.h"
|
|
#include "vtkPlotPoints.h"
|
|
#include "vtkPlotPoints3D.h"
|
|
#include "vtkCommand.h"
|
|
#include "vtkTextProperty.h"
|
|
#include "vtkContextScene.h"
|
|
#include "vtkRenderWindowInteractor.h"
|
|
#include "vtkCallbackCommand.h"
|
|
#include "vtkVectorOperators.h"
|
|
#include "vtkTooltipItem.h"
|
|
|
|
#include "vtkChartXYZ.h"
|
|
|
|
// STL includes
|
|
#include <map>
|
|
#include <cassert>
|
|
#include <vector>
|
|
|
|
class vtkScatterPlotMatrix::PIMPL
|
|
{
|
|
public:
|
|
PIMPL() : VisibleColumnsModified(true), BigChart(NULL),
|
|
AnimationCallbackInitialized(false), TimerId(0),
|
|
TimerCallbackInitialized(false)
|
|
{
|
|
pimplChartSetting* scatterplotSettings = new pimplChartSetting();
|
|
scatterplotSettings->BackgroundBrush->SetColor(255, 255, 255, 255);
|
|
this->ChartSettings[vtkScatterPlotMatrix::SCATTERPLOT] =
|
|
scatterplotSettings;
|
|
pimplChartSetting* histogramSettings = new pimplChartSetting();
|
|
histogramSettings->BackgroundBrush->SetColor(127, 127, 127, 102);
|
|
histogramSettings->PlotPen->SetColor(255, 255, 255, 255);
|
|
histogramSettings->ShowAxisLabels = true;
|
|
this->ChartSettings[vtkScatterPlotMatrix::HISTOGRAM] = histogramSettings;
|
|
pimplChartSetting* activeplotSettings = new pimplChartSetting();
|
|
activeplotSettings->BackgroundBrush->SetColor(255, 255, 255, 255);
|
|
activeplotSettings->ShowAxisLabels = true;
|
|
this->ChartSettings[vtkScatterPlotMatrix::ACTIVEPLOT] = activeplotSettings;
|
|
activeplotSettings->MarkerSize = 8.0;
|
|
this->SelectedChartBGBrush->SetColor(0, 204, 0, 102);
|
|
this->SelectedRowColumnBGBrush->SetColor(204, 0, 0, 102);
|
|
this->TooltipItem = vtkSmartPointer<vtkTooltipItem>::New();
|
|
}
|
|
|
|
~PIMPL()
|
|
{
|
|
delete this->ChartSettings[vtkScatterPlotMatrix::SCATTERPLOT];
|
|
delete this->ChartSettings[vtkScatterPlotMatrix::HISTOGRAM];
|
|
delete this->ChartSettings[vtkScatterPlotMatrix::ACTIVEPLOT];
|
|
}
|
|
|
|
// Store columns settings such as axis range, title, number of tick marks.
|
|
class ColumnSetting
|
|
{
|
|
public:
|
|
ColumnSetting() : min(0), max(0), nTicks(0), title("?!?")
|
|
{
|
|
}
|
|
|
|
double min;
|
|
double max;
|
|
int nTicks;
|
|
std::string title;
|
|
};
|
|
|
|
class pimplChartSetting
|
|
{
|
|
public:
|
|
pimplChartSetting()
|
|
{
|
|
this->PlotPen->SetColor(0, 0, 0, 255);
|
|
this->MarkerStyle = vtkPlotPoints::CIRCLE;
|
|
this->MarkerSize = 3.0;
|
|
this->AxisColor.Set(0, 0, 0, 255);
|
|
this->GridColor.Set(242, 242, 242, 255);
|
|
this->LabelNotation = vtkAxis::STANDARD_NOTATION;
|
|
this->LabelPrecision = 2;
|
|
this->TooltipNotation = vtkAxis::STANDARD_NOTATION;
|
|
this->TooltipPrecision = 2;
|
|
this->ShowGrid = true;
|
|
this->ShowAxisLabels = false;
|
|
this->LabelFont = vtkSmartPointer<vtkTextProperty>::New();
|
|
this->LabelFont->SetFontFamilyToArial();
|
|
this->LabelFont->SetFontSize(12);
|
|
this->LabelFont->SetColor(0.0, 0.0, 0.0);
|
|
this->LabelFont->SetOpacity(1.0);
|
|
}
|
|
~pimplChartSetting() {}
|
|
|
|
int MarkerStyle;
|
|
float MarkerSize;
|
|
vtkColor4ub AxisColor;
|
|
vtkColor4ub GridColor;
|
|
int LabelNotation;
|
|
int LabelPrecision;
|
|
int TooltipNotation;
|
|
int TooltipPrecision;
|
|
bool ShowGrid;
|
|
bool ShowAxisLabels;
|
|
vtkSmartPointer<vtkTextProperty> LabelFont;
|
|
vtkNew<vtkBrush> BackgroundBrush;
|
|
vtkNew<vtkPen> PlotPen;
|
|
vtkNew<vtkBrush> PlotBrush;
|
|
};
|
|
|
|
void UpdateAxis(vtkAxis* axis, pimplChartSetting* setting,
|
|
bool updateLabel = true)
|
|
{
|
|
if(axis && setting)
|
|
{
|
|
axis->GetPen()->SetColor(setting->AxisColor);
|
|
axis->GetGridPen()->SetColor(setting->GridColor);
|
|
axis->SetGridVisible(setting->ShowGrid);
|
|
if (updateLabel)
|
|
{
|
|
vtkTextProperty *prop = setting->LabelFont.GetPointer();
|
|
axis->SetNotation(setting->LabelNotation);
|
|
axis->SetPrecision(setting->LabelPrecision);
|
|
axis->SetLabelsVisible(setting->ShowAxisLabels);
|
|
axis->GetLabelProperties()->SetFontSize(prop->GetFontSize());
|
|
axis->GetLabelProperties()->SetColor(prop->GetColor());
|
|
axis->GetLabelProperties()->SetOpacity(prop->GetOpacity());
|
|
axis->GetLabelProperties()->SetFontFamilyAsString(
|
|
prop->GetFontFamilyAsString());
|
|
axis->GetLabelProperties()->SetBold(prop->GetBold());
|
|
axis->GetLabelProperties()->SetItalic(prop->GetItalic());
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateChart(vtkChart* chart, pimplChartSetting* setting)
|
|
{
|
|
if(chart && setting)
|
|
{
|
|
vtkPlot *plot = chart->GetPlot(0);
|
|
if (plot)
|
|
{
|
|
plot->SetTooltipNotation(setting->TooltipNotation);
|
|
plot->SetTooltipPrecision(setting->TooltipPrecision);
|
|
}
|
|
}
|
|
}
|
|
|
|
vtkNew<vtkTable> Histogram;
|
|
bool VisibleColumnsModified;
|
|
vtkWeakPointer<vtkChart> BigChart;
|
|
vtkNew<vtkAnnotationLink> Link;
|
|
|
|
// Settings for the charts in the scatter plot matrix.
|
|
std::map<int, pimplChartSetting*> ChartSettings;
|
|
typedef std::map<int, pimplChartSetting*>::iterator chartIterator;
|
|
|
|
// Axis ranges for the columns in the scatter plot matrix.
|
|
std::map<std::string, ColumnSetting> ColumnSettings;
|
|
|
|
vtkNew<vtkBrush> SelectedRowColumnBGBrush;
|
|
vtkNew<vtkBrush> SelectedChartBGBrush;
|
|
std::vector<vtkVector2i> AnimationPath;
|
|
std::vector<vtkVector2i>::iterator AnimationIter;
|
|
vtkRenderWindowInteractor* Interactor;
|
|
vtkNew<vtkCallbackCommand> AnimationCallback;
|
|
bool AnimationCallbackInitialized;
|
|
unsigned long int TimerId;
|
|
bool TimerCallbackInitialized;
|
|
int AnimationPhase;
|
|
float CurrentAngle;
|
|
float IncAngle;
|
|
float FinalAngle;
|
|
vtkVector2i NextActivePlot;
|
|
|
|
vtkNew<vtkChartXYZ> BigChart3D;
|
|
vtkNew<vtkAxis> TestAxis; // Used to get ranges/numer of ticks
|
|
vtkSmartPointer<vtkTooltipItem> TooltipItem;
|
|
vtkSmartPointer<vtkStringArray> IndexedLabelsArray;
|
|
};
|
|
|
|
namespace
|
|
{
|
|
|
|
// This is just here for now - quick and dirty historgram calculations...
|
|
bool PopulateHistograms(vtkTable *input, vtkTable *output, vtkStringArray *s,
|
|
int NumberOfBins)
|
|
{
|
|
// The output table will have the twice the number of columns, they will be
|
|
// the x and y for input column. This is the bin centers, and the population.
|
|
for (vtkIdType i = 0; i < s->GetNumberOfTuples(); ++i)
|
|
{
|
|
double minmax[2] = { 0.0, 0.0 };
|
|
vtkStdString name(s->GetValue(i));
|
|
vtkDataArray *in =
|
|
vtkDataArray::SafeDownCast(input->GetColumnByName(name.c_str()));
|
|
if (in)
|
|
{
|
|
// The bin values are the centers, extending +/- half an inc either side
|
|
in->GetRange(minmax);
|
|
if (minmax[0] == minmax[1])
|
|
{
|
|
minmax[1] = minmax[0] + 1.0;
|
|
}
|
|
double inc = (minmax[1] - minmax[0]) / (NumberOfBins) * 1.001;
|
|
double halfInc = inc / 2.0;
|
|
vtkSmartPointer<vtkFloatArray> extents =
|
|
vtkFloatArray::SafeDownCast(
|
|
output->GetColumnByName(vtkStdString(name + "_extents").c_str()));
|
|
if (!extents)
|
|
{
|
|
extents = vtkSmartPointer<vtkFloatArray>::New();
|
|
extents->SetName(vtkStdString(name + "_extents").c_str());
|
|
}
|
|
extents->SetNumberOfTuples(NumberOfBins);
|
|
float *centers = static_cast<float *>(extents->GetVoidPointer(0));
|
|
double min = minmax[0] - 0.0005 * inc + halfInc;
|
|
for (int j = 0; j < NumberOfBins; ++j)
|
|
{
|
|
extents->SetValue(j, min + j * inc);
|
|
}
|
|
vtkSmartPointer<vtkIntArray> populations =
|
|
vtkIntArray::SafeDownCast(
|
|
output->GetColumnByName(vtkStdString(name + "_pops").c_str()));
|
|
if (!populations)
|
|
{
|
|
populations = vtkSmartPointer<vtkIntArray>::New();
|
|
populations->SetName(vtkStdString(name + "_pops").c_str());
|
|
}
|
|
populations->SetNumberOfTuples(NumberOfBins);
|
|
int *pops = static_cast<int *>(populations->GetVoidPointer(0));
|
|
for (int k = 0; k < NumberOfBins; ++k)
|
|
{
|
|
pops[k] = 0;
|
|
}
|
|
for (vtkIdType j = 0; j < in->GetNumberOfTuples(); ++j)
|
|
{
|
|
double v(0.0);
|
|
in->GetTuple(j, &v);
|
|
for (int k = 0; k < NumberOfBins; ++k)
|
|
{
|
|
if (vtkMathUtilities::FuzzyCompare(v, double(centers[k]), halfInc))
|
|
{
|
|
++pops[k];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
output->AddColumn(extents.GetPointer());
|
|
output->AddColumn(populations.GetPointer());
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool MoveColumn(vtkStringArray* visCols, int fromCol, int toCol)
|
|
{
|
|
if(!visCols || visCols->GetNumberOfTuples() == 0
|
|
|| fromCol == toCol || fromCol == (toCol-1) || fromCol < 0 || toCol < 0)
|
|
{
|
|
return false;
|
|
}
|
|
int numCols = visCols->GetNumberOfTuples();
|
|
if( fromCol >= numCols || toCol > numCols)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::vector<vtkStdString> newVisCols;
|
|
vtkIdType c;
|
|
if(toCol == numCols)
|
|
{
|
|
for(c=0; c<numCols; c++)
|
|
{
|
|
if(c!=fromCol)
|
|
{
|
|
newVisCols.push_back(visCols->GetValue(c));
|
|
}
|
|
}
|
|
// move the fromCol to the end
|
|
newVisCols.push_back(visCols->GetValue(fromCol));
|
|
}
|
|
// insert the fromCol before toCol
|
|
else if(fromCol < toCol)
|
|
{
|
|
// move Cols in the middle up
|
|
for(c=0; c<fromCol; c++)
|
|
{
|
|
newVisCols.push_back(visCols->GetValue(c));
|
|
}
|
|
for(c=fromCol+1; c<numCols; c++)
|
|
{
|
|
if(c == toCol)
|
|
{
|
|
newVisCols.push_back(visCols->GetValue(fromCol));
|
|
}
|
|
newVisCols.push_back(visCols->GetValue(c));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(c=0; c<toCol; c++)
|
|
{
|
|
newVisCols.push_back(visCols->GetValue(c));
|
|
}
|
|
newVisCols.push_back(visCols->GetValue(fromCol));
|
|
for(c=toCol; c<numCols; c++)
|
|
{
|
|
if(c != fromCol)
|
|
{
|
|
newVisCols.push_back(visCols->GetValue(c));
|
|
}
|
|
}
|
|
}
|
|
|
|
// repopulate the visCols
|
|
vtkIdType visId=0;
|
|
std::vector<vtkStdString>::iterator arrayIt;
|
|
for(arrayIt=newVisCols.begin(); arrayIt!=newVisCols.end(); ++arrayIt)
|
|
{
|
|
visCols->SetValue(visId++, *arrayIt);
|
|
}
|
|
return true;
|
|
}
|
|
} // End of anonymous namespace
|
|
|
|
vtkStandardNewMacro(vtkScatterPlotMatrix)
|
|
|
|
vtkScatterPlotMatrix::vtkScatterPlotMatrix()
|
|
: NumberOfBins(10), NumberOfFrames(25)
|
|
{
|
|
this->Private = new PIMPL;
|
|
this->TitleProperties = vtkSmartPointer<vtkTextProperty>::New();
|
|
this->TitleProperties->SetFontSize(12);
|
|
this->SelectionMode = vtkContextScene::SELECTION_NONE;
|
|
}
|
|
|
|
vtkScatterPlotMatrix::~vtkScatterPlotMatrix()
|
|
{
|
|
delete this->Private;
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::Update()
|
|
{
|
|
if (this->Private->VisibleColumnsModified)
|
|
{
|
|
// We need to handle layout changes due to modified visibility.
|
|
// Build up our histograms data before updating the layout.
|
|
PopulateHistograms(this->Input.GetPointer(),
|
|
this->Private->Histogram.GetPointer(),
|
|
this->VisibleColumns.GetPointer(),
|
|
this->NumberOfBins);
|
|
this->UpdateLayout();
|
|
this->Private->VisibleColumnsModified = false;
|
|
}
|
|
}
|
|
|
|
bool vtkScatterPlotMatrix::Paint(vtkContext2D *painter)
|
|
{
|
|
this->Update();
|
|
return Superclass::Paint(painter);
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetScene(vtkContextScene *scene)
|
|
{
|
|
// The internal axis shouldn't be a child as it isn't rendered with the
|
|
// chart, but it does need access to the scene.
|
|
this->Private->TestAxis->SetScene(scene);
|
|
|
|
this->Superclass::SetScene(scene);
|
|
}
|
|
|
|
bool vtkScatterPlotMatrix::SetActivePlot(const vtkVector2i &pos)
|
|
{
|
|
if (pos.GetX() + pos.GetY() + 1 < this->Size.GetX() && pos.GetX() < this->Size.GetX() &&
|
|
pos.GetY() < this->Size.GetY())
|
|
{
|
|
// The supplied index is valid (in the lower quadrant).
|
|
this->ActivePlot = pos;
|
|
|
|
// Invoke an interaction event, to let observers know something changed.
|
|
this->InvokeEvent(vtkCommand::AnnotationChangedEvent);
|
|
|
|
// set background colors for plots
|
|
if (this->GetChart(this->ActivePlot)->GetPlot(0))
|
|
{
|
|
int plotCount = this->GetSize().GetX();
|
|
for (int i = 0; i < plotCount; ++i)
|
|
{
|
|
for (int j = 0; j < plotCount; ++j)
|
|
{
|
|
if (this->GetPlotType(i, j) == SCATTERPLOT)
|
|
{
|
|
vtkChartXY *chart =
|
|
vtkChartXY::SafeDownCast(this->GetChart(vtkVector2i(i, j)));
|
|
|
|
if (pos[0] == i && pos[1] == j)
|
|
{
|
|
// set the new active chart background color to light green
|
|
chart->SetBackgroundBrush(
|
|
this->Private->SelectedChartBGBrush.GetPointer());
|
|
}
|
|
else if (pos[0] == i || pos[1] == j)
|
|
{
|
|
// set background color for all other charts in the selected
|
|
// chart's row and column to light red
|
|
chart->SetBackgroundBrush(
|
|
this->Private->SelectedRowColumnBGBrush.GetPointer());
|
|
}
|
|
else
|
|
{
|
|
// set all else to white
|
|
chart->SetBackgroundBrush(
|
|
this->Private->ChartSettings[SCATTERPLOT]
|
|
->BackgroundBrush.GetPointer());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (this->Private->BigChart)
|
|
{
|
|
vtkPlot *plot = this->Private->BigChart->GetPlot(0);
|
|
vtkStdString column = this->GetColumnName(pos.GetX());
|
|
vtkStdString row = this->GetRowName(pos.GetY());
|
|
if (!plot)
|
|
{
|
|
plot = this->Private->BigChart->AddPlot(vtkChart::POINTS);
|
|
vtkChart *active = this->GetChart(this->ActivePlot);
|
|
vtkChartXY *xy = vtkChartXY::SafeDownCast(this->Private->BigChart);
|
|
if (xy)
|
|
{
|
|
// Set plot corner, and axis visibility
|
|
xy->SetPlotCorner(plot, 2);
|
|
xy->SetAutoAxes(false);
|
|
xy->GetAxis(vtkAxis::TOP)->SetVisible(true);
|
|
xy->GetAxis(vtkAxis::RIGHT)->SetVisible(true);
|
|
xy->GetAxis(vtkAxis::BOTTOM)->SetLabelsVisible(false);
|
|
xy->GetAxis(vtkAxis::BOTTOM)->SetGridVisible(false);
|
|
xy->GetAxis(vtkAxis::BOTTOM)->SetTicksVisible(false);
|
|
xy->GetAxis(vtkAxis::BOTTOM)->SetVisible(true);
|
|
xy->GetAxis(vtkAxis::LEFT)->SetLabelsVisible(false);
|
|
xy->GetAxis(vtkAxis::LEFT)->SetGridVisible(false);
|
|
xy->GetAxis(vtkAxis::LEFT)->SetTicksVisible(false);
|
|
xy->GetAxis(vtkAxis::LEFT)->SetVisible(true);
|
|
|
|
// set labels array
|
|
if(this->Private->IndexedLabelsArray)
|
|
{
|
|
plot->SetIndexedLabels(this->Private->IndexedLabelsArray);
|
|
plot->SetTooltipLabelFormat("%i");
|
|
}
|
|
}
|
|
if (xy && active)
|
|
{
|
|
vtkAxis *a = active->GetAxis(vtkAxis::BOTTOM);
|
|
xy->GetAxis(vtkAxis::TOP)->SetUnscaledRange(
|
|
a->GetUnscaledMinimum(), a->GetUnscaledMaximum());
|
|
a = active->GetAxis(vtkAxis::LEFT);
|
|
xy->GetAxis(vtkAxis::RIGHT)->SetUnscaledRange(
|
|
a->GetUnscaledMinimum(), a->GetUnscaledMaximum());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->Private->BigChart->ClearPlots();
|
|
plot = this->Private->BigChart->AddPlot(vtkChart::POINTS);
|
|
vtkChartXY *xy = vtkChartXY::SafeDownCast(this->Private->BigChart);
|
|
if (xy)
|
|
{
|
|
xy->SetPlotCorner(plot, 2);
|
|
}
|
|
|
|
// set labels array
|
|
if(this->Private->IndexedLabelsArray)
|
|
{
|
|
plot->SetIndexedLabels(this->Private->IndexedLabelsArray);
|
|
plot->SetTooltipLabelFormat("%i");
|
|
}
|
|
}
|
|
plot->SetInputData(this->Input.GetPointer(), column, row);
|
|
plot->SetPen(this->Private->ChartSettings[ACTIVEPLOT]
|
|
->PlotPen.GetPointer());
|
|
this->ApplyAxisSetting(this->Private->BigChart.GetPointer(), column, row);
|
|
|
|
// Set marker size and style.
|
|
vtkPlotPoints *plotPoints = vtkPlotPoints::SafeDownCast(plot);
|
|
plotPoints->SetMarkerSize(this->Private->ChartSettings[ACTIVEPLOT]
|
|
->MarkerSize);
|
|
plotPoints->SetMarkerStyle(this->Private->ChartSettings[ACTIVEPLOT]
|
|
->MarkerStyle);
|
|
// Set background color.
|
|
this->Private->BigChart->SetBackgroundBrush(
|
|
this->Private->ChartSettings[ACTIVEPLOT]
|
|
->BackgroundBrush.GetPointer());
|
|
this->Private->BigChart->GetAxis(vtkAxis::TOP)->SetTitle(
|
|
this->VisibleColumns->GetValue(pos.GetX()));
|
|
this->Private->BigChart->GetAxis(vtkAxis::RIGHT)->SetTitle(
|
|
this->VisibleColumns->GetValue(this->GetSize().GetX() - pos.GetY() - 1));
|
|
// Calculate the ideal range.
|
|
//this->Private->BigChart->RecalculateBounds();
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
vtkVector2i vtkScatterPlotMatrix::GetActivePlot()
|
|
{
|
|
return this->ActivePlot;
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::UpdateAnimationPath(const vtkVector2i& newActivePos)
|
|
{
|
|
this->Private->AnimationPath.clear();
|
|
if (newActivePos[0] != this->ActivePlot[0] ||
|
|
newActivePos[1] != this->ActivePlot[1])
|
|
{
|
|
if (newActivePos[1] >= this->ActivePlot[1])
|
|
{
|
|
// x direction first
|
|
if (this->ActivePlot[0]>newActivePos[0])
|
|
{
|
|
for(int r = this->ActivePlot[0] - 1; r >= newActivePos[0]; r--)
|
|
{
|
|
this->Private->AnimationPath.push_back(vtkVector2i(r,
|
|
this->ActivePlot[1]));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int r = this->ActivePlot[0] + 1; r <= newActivePos[0]; r++)
|
|
{
|
|
this->Private->AnimationPath.push_back(vtkVector2i(r,
|
|
this->ActivePlot[1]));
|
|
}
|
|
}
|
|
// then y direction
|
|
for (int c = this->ActivePlot[1] + 1; c <= newActivePos[1]; c++)
|
|
{
|
|
this->Private->AnimationPath.push_back(vtkVector2i(newActivePos[0], c));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// y direction first
|
|
for (int c = this->ActivePlot[1] - 1; c >= newActivePos[1]; c--)
|
|
{
|
|
this->Private->AnimationPath.push_back(vtkVector2i(this->ActivePlot[0],
|
|
c));
|
|
}
|
|
// then x direction
|
|
if (this->ActivePlot[0]>newActivePos[0])
|
|
{
|
|
for (int r = this->ActivePlot[0] - 1; r >= newActivePos[0]; r--)
|
|
{
|
|
this->Private->AnimationPath.push_back(vtkVector2i(r,
|
|
newActivePos[1]));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int r = this->ActivePlot[0] + 1; r <= newActivePos[0]; r++)
|
|
{
|
|
this->Private->AnimationPath.push_back(vtkVector2i(r, newActivePos[1]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::StartAnimation(vtkRenderWindowInteractor* interactor)
|
|
{
|
|
// Start a simple repeating timer to advance along the path until completion.
|
|
if (!this->Private->TimerCallbackInitialized && interactor)
|
|
{
|
|
if (!this->Private->AnimationCallbackInitialized)
|
|
{
|
|
this->Private->AnimationCallback->SetClientData(this);
|
|
this->Private->AnimationCallback->SetCallback(
|
|
vtkScatterPlotMatrix::ProcessEvents);
|
|
interactor->AddObserver(vtkCommand::TimerEvent,
|
|
this->Private->AnimationCallback.GetPointer(),
|
|
0);
|
|
this->Private->Interactor = interactor;
|
|
this->Private->AnimationCallbackInitialized = true;
|
|
}
|
|
this->Private->TimerCallbackInitialized = true;
|
|
// This defines the interval at which the animation will proceed. 25Hz?
|
|
this->Private->TimerId = interactor->CreateRepeatingTimer(1000 / 50);
|
|
this->Private->AnimationIter = this->Private->AnimationPath.begin();
|
|
this->Private->AnimationPhase = 0;
|
|
}
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::AdvanceAnimation()
|
|
{
|
|
// The animation has several phases, and we must track where we are.
|
|
|
|
// 1: Remove decoration from the big chart.
|
|
// 2: Set three dimensions to plot in the BigChart3D.
|
|
// 3: Make BigChart inivisible, and BigChart3D visible.
|
|
// 4: Rotate between the two dimensions we are transitioning between.
|
|
// -> Loop from start to end angle to complete the effect.
|
|
// 5: Make the new dimensionality active, update BigChart.
|
|
// 5: Make BigChart3D invisible and BigChart visible.
|
|
// 6: Stop the timer.
|
|
this->InvokeEvent(vtkCommand::AnimationCueTickEvent);
|
|
switch (this->Private->AnimationPhase)
|
|
{
|
|
case 0: // Remove decoration from the big chart, load up the 3D chart
|
|
{
|
|
this->Private->NextActivePlot = *this->Private->AnimationIter;
|
|
vtkChartXYZ *chart = this->Private->BigChart3D.GetPointer();
|
|
chart->SetVisible(false);
|
|
chart->SetAutoRotate(true);
|
|
chart->SetDecorateAxes(false);
|
|
chart->SetFitToScene(false);
|
|
|
|
int yColumn = this->GetSize().GetY() - this->ActivePlot.GetY() - 1;
|
|
bool isX = false;
|
|
int zColumn = 0;
|
|
|
|
vtkRectf size = this->Private->BigChart->GetSize();
|
|
float zSize;
|
|
this->Private->FinalAngle = 90.0;
|
|
this->Private->IncAngle = this->Private->FinalAngle / this->NumberOfFrames;
|
|
|
|
if (this->Private->NextActivePlot.GetY() == this->ActivePlot.GetY())
|
|
{
|
|
// Horizontal move.
|
|
zColumn = this->Private->NextActivePlot.GetX();
|
|
isX = false;
|
|
if (this->ActivePlot.GetX() < zColumn)
|
|
{
|
|
this->Private->IncAngle *= 1.0;
|
|
zSize = size.GetWidth();
|
|
}
|
|
else
|
|
{
|
|
this->Private->IncAngle *= -1.0;
|
|
zSize = -size.GetWidth();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Vertical move.
|
|
zColumn = this->GetSize().GetY() - this->Private->NextActivePlot.GetY() - 1;
|
|
isX = true;
|
|
if (this->GetSize().GetY() - this->ActivePlot.GetY() - 1 < zColumn)
|
|
{
|
|
this->Private->IncAngle *= -1.0;
|
|
zSize = size.GetHeight();
|
|
}
|
|
else
|
|
{
|
|
this->Private->IncAngle *= 1.0;
|
|
zSize = -size.GetHeight();
|
|
}
|
|
}
|
|
chart->SetAroundX(isX);
|
|
chart->SetGeometry(size);
|
|
|
|
vtkStdString names[3];
|
|
names[0] = this->VisibleColumns->GetValue(this->ActivePlot.GetX());
|
|
names[1] = this->VisibleColumns->GetValue(yColumn);
|
|
names[2] = this->VisibleColumns->GetValue(zColumn);
|
|
|
|
// Setup the 3D chart
|
|
this->Private->BigChart3D->ClearPlots();
|
|
vtkNew<vtkPlotPoints3D> scatterPlot3D;
|
|
scatterPlot3D->SetInputData(
|
|
this->Input.GetPointer(), names[0], names[1], names[2]);
|
|
this->Private->BigChart3D->AddPlot(scatterPlot3D.GetPointer());
|
|
|
|
// Set the z axis up so that it ends in the right orientation.
|
|
chart->GetAxis(2)->SetPoint2(0, zSize);
|
|
// Now set the ranges for the three axes.
|
|
for (int i = 0; i < 3; ++i)
|
|
{
|
|
PIMPL::ColumnSetting &settings = this->Private->ColumnSettings[names[i]];
|
|
chart->GetAxis(i)->SetUnscaledRange(settings.min, settings.max);
|
|
}
|
|
chart->RecalculateTransform();
|
|
this->GetScene()->SetDirty(true);
|
|
++this->Private->AnimationPhase;
|
|
return;
|
|
}
|
|
case 1: // Make BigChart invisible, and BigChart3D visible.
|
|
this->Private->BigChart->SetVisible(false);
|
|
this->AddItem(this->Private->BigChart3D.GetPointer());
|
|
this->Private->BigChart3D->SetVisible(true);
|
|
this->GetScene()->SetDirty(true);
|
|
++this->Private->AnimationPhase;
|
|
this->Private->CurrentAngle = 0.0;
|
|
return;
|
|
case 2: // Rotation of the 3D chart from start to end angle.
|
|
if (fabs(this->Private->CurrentAngle) < (this->Private->FinalAngle - 0.001))
|
|
{
|
|
this->Private->CurrentAngle += this->Private->IncAngle;
|
|
this->Private->BigChart3D->SetAngle(this->Private->CurrentAngle);
|
|
}
|
|
else
|
|
{
|
|
++this->Private->AnimationPhase;
|
|
}
|
|
this->GetScene()->SetDirty(true);
|
|
return;
|
|
case 3: // Transition to new dimensionality, update the big chart.
|
|
this->SetActivePlot(this->Private->NextActivePlot);
|
|
this->Private->BigChart->Update();
|
|
this->GetScene()->SetDirty(true);
|
|
++this->Private->AnimationPhase;
|
|
break;
|
|
case 4:
|
|
this->GetScene()->SetDirty(true);
|
|
++this->Private->AnimationIter;
|
|
// Clean up - we are done.
|
|
this->Private->AnimationPhase = 0;
|
|
if (this->Private->AnimationIter == this->Private->AnimationPath.end())
|
|
{
|
|
this->Private->BigChart->SetVisible(true);
|
|
this->RemoveItem(this->Private->BigChart3D.GetPointer());
|
|
this->Private->BigChart3D->SetVisible(false);
|
|
this->Private->Interactor->DestroyTimer(this->Private->TimerId);
|
|
this->Private->TimerId = 0;
|
|
this->Private->TimerCallbackInitialized = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::ProcessEvents(vtkObject *, unsigned long event,
|
|
void *clientData, void *callerData)
|
|
{
|
|
vtkScatterPlotMatrix *self =
|
|
reinterpret_cast<vtkScatterPlotMatrix *>(clientData);
|
|
switch (event)
|
|
{
|
|
case vtkCommand::TimerEvent:
|
|
{
|
|
// We must filter the events to ensure we actually get the timer event we
|
|
// created. I would love signals and slots...
|
|
int timerId = *reinterpret_cast<int *>(callerData); // Seems to work.
|
|
if (self->Private->TimerCallbackInitialized &&
|
|
timerId == static_cast<int>(self->Private->TimerId))
|
|
{
|
|
self->AdvanceAnimation();
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
vtkAnnotationLink* vtkScatterPlotMatrix::GetAnnotationLink()
|
|
{
|
|
return this->Private->Link.GetPointer();
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetInput(vtkTable *table)
|
|
{
|
|
if(table && table->GetNumberOfRows() == 0)
|
|
{
|
|
// do nothing if the table is emtpy
|
|
return;
|
|
}
|
|
|
|
if (this->Input != table)
|
|
{
|
|
// Set the input, then update the size of the scatter plot matrix, set
|
|
// their inputs and all the other stuff needed.
|
|
this->Input = table;
|
|
this->SetSize(vtkVector2i(0, 0));
|
|
this->Modified();
|
|
|
|
if (table == NULL)
|
|
{
|
|
this->SetColumnVisibilityAll(true);
|
|
return;
|
|
}
|
|
int n = static_cast<int>(this->Input->GetNumberOfColumns());
|
|
this->SetColumnVisibilityAll(true);
|
|
this->SetSize(vtkVector2i(n, n));
|
|
}
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetColumnVisibility(const vtkStdString &name,
|
|
bool visible)
|
|
{
|
|
if (visible)
|
|
{
|
|
for (vtkIdType i = 0; i < this->VisibleColumns->GetNumberOfTuples(); ++i)
|
|
{
|
|
if (this->VisibleColumns->GetValue(i) == name)
|
|
{
|
|
// Already there, nothing more needs to be done
|
|
return;
|
|
}
|
|
}
|
|
// Add the column to the end of the list if it is a numeric column
|
|
if (this->Input && this->Input->GetColumnByName(name.c_str()) &&
|
|
vtkDataArray::SafeDownCast(this->Input->GetColumnByName(name.c_str())))
|
|
{
|
|
this->VisibleColumns->InsertNextValue(name);
|
|
this->Private->VisibleColumnsModified = true;
|
|
this->SetSize(vtkVector2i(0, 0));
|
|
this->SetSize(vtkVector2i(this->VisibleColumns->GetNumberOfTuples(),
|
|
this->VisibleColumns->GetNumberOfTuples()));
|
|
this->Modified();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Remove the value if present
|
|
for (vtkIdType i = 0; i < this->VisibleColumns->GetNumberOfTuples(); ++i)
|
|
{
|
|
if (this->VisibleColumns->GetValue(i) == name)
|
|
{
|
|
// Move all the later elements down by one, and reduce the size
|
|
while (i < this->VisibleColumns->GetNumberOfTuples() - 1)
|
|
{
|
|
this->VisibleColumns->SetValue(i,
|
|
this->VisibleColumns->GetValue(i + 1));
|
|
++i;
|
|
}
|
|
this->VisibleColumns->SetNumberOfTuples(
|
|
this->VisibleColumns->GetNumberOfTuples() - 1);
|
|
this->SetSize(vtkVector2i(0, 0));
|
|
this->SetSize(vtkVector2i(this->VisibleColumns->GetNumberOfTuples(),
|
|
this->VisibleColumns->GetNumberOfTuples()));
|
|
if (this->ActivePlot.GetX() + this->ActivePlot.GetY() + 1 >=
|
|
this->VisibleColumns->GetNumberOfTuples())
|
|
{
|
|
this->ActivePlot.Set(0, this->VisibleColumns->GetNumberOfTuples() - 1);
|
|
}
|
|
this->Private->VisibleColumnsModified = true;
|
|
this->Modified();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::InsertVisibleColumn(const vtkStdString &name,
|
|
int index)
|
|
{
|
|
if(!this->Input || !this->Input->GetColumnByName(name.c_str()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Check if the column is already in the list. If yes,
|
|
// we may need to rearrange the order of the columns.
|
|
vtkIdType currIdx = -1;
|
|
vtkIdType numCols = this->VisibleColumns->GetNumberOfTuples();
|
|
for (vtkIdType i = 0; i < numCols; ++i)
|
|
{
|
|
if (this->VisibleColumns->GetValue(i) == name)
|
|
{
|
|
currIdx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(currIdx > 0 && currIdx == index)
|
|
{
|
|
//This column is already there.
|
|
return;
|
|
}
|
|
|
|
if(currIdx < 0)
|
|
{
|
|
this->VisibleColumns->SetNumberOfTuples(numCols+1);
|
|
if(index >= numCols)
|
|
{
|
|
this->VisibleColumns->SetValue(numCols, name);
|
|
}
|
|
else // move all the values after index down 1
|
|
{
|
|
vtkIdType startidx = numCols;
|
|
vtkIdType idx = (index < 0) ? 0 : index;
|
|
while (startidx > idx)
|
|
{
|
|
this->VisibleColumns->SetValue(startidx,
|
|
this->VisibleColumns->GetValue(startidx-1));
|
|
startidx--;
|
|
}
|
|
this->VisibleColumns->SetValue(idx, name);
|
|
}
|
|
this->Private->VisibleColumnsModified = true;
|
|
}
|
|
else // need to rearrange table columns
|
|
{
|
|
vtkIdType toIdx = (index < 0) ? 0 : index;
|
|
toIdx = toIdx>numCols ? numCols : toIdx;
|
|
this->Private->VisibleColumnsModified =
|
|
MoveColumn(this->VisibleColumns.GetPointer(), currIdx, toIdx);
|
|
}
|
|
|
|
this->Update();
|
|
}
|
|
|
|
bool vtkScatterPlotMatrix::GetColumnVisibility(const vtkStdString &name)
|
|
{
|
|
for (vtkIdType i = 0; i < this->VisibleColumns->GetNumberOfTuples(); ++i)
|
|
{
|
|
if (this->VisibleColumns->GetValue(i) == name)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetColumnVisibilityAll(bool visible)
|
|
{
|
|
if (visible && this->Input)
|
|
{
|
|
vtkIdType n = this->Input->GetNumberOfColumns();
|
|
this->VisibleColumns->SetNumberOfTuples(n);
|
|
for (vtkIdType i = 0; i < n; ++i)
|
|
{
|
|
this->VisibleColumns->SetValue(i, this->Input->GetColumnName(i));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->SetSize(vtkVector2i(0, 0));
|
|
this->VisibleColumns->SetNumberOfTuples(0);
|
|
}
|
|
|
|
this->Private->VisibleColumnsModified = true;
|
|
}
|
|
|
|
vtkStringArray* vtkScatterPlotMatrix::GetVisibleColumns()
|
|
{
|
|
return this->VisibleColumns.GetPointer();
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetVisibleColumns(vtkStringArray* visColumns)
|
|
{
|
|
if(!visColumns || visColumns->GetNumberOfTuples() == 0)
|
|
{
|
|
this->SetSize(vtkVector2i(0, 0));
|
|
this->VisibleColumns->SetNumberOfTuples(0);
|
|
}
|
|
else
|
|
{
|
|
this->VisibleColumns->SetNumberOfTuples(
|
|
visColumns->GetNumberOfTuples());
|
|
this->VisibleColumns->DeepCopy(visColumns);
|
|
}
|
|
this->Private->VisibleColumnsModified = true;
|
|
this->Update();
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetNumberOfBins(int numberOfBins)
|
|
{
|
|
if (this->NumberOfBins != numberOfBins)
|
|
{
|
|
this->NumberOfBins = numberOfBins;
|
|
if (this->Input)
|
|
{
|
|
PopulateHistograms(this->Input.GetPointer(),
|
|
this->Private->Histogram.GetPointer(),
|
|
this->VisibleColumns.GetPointer(),
|
|
this->NumberOfBins);
|
|
}
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetPlotColor(int plotType, const vtkColor4ub& color)
|
|
{
|
|
if(plotType >= 0 && plotType < NOPLOT)
|
|
{
|
|
if (plotType == ACTIVEPLOT || plotType == SCATTERPLOT)
|
|
{
|
|
this->Private->ChartSettings[plotType]->PlotPen->SetColor(color);
|
|
}
|
|
else
|
|
{
|
|
this->Private->ChartSettings[HISTOGRAM]->PlotBrush->SetColor(color);
|
|
}
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetPlotMarkerStyle(int plotType, int style)
|
|
{
|
|
if(plotType >= 0 && plotType < NOPLOT &&
|
|
style != this->Private->ChartSettings[plotType]->MarkerStyle)
|
|
{
|
|
this->Private->ChartSettings[plotType]->MarkerStyle = style;
|
|
|
|
if (plotType == ACTIVEPLOT)
|
|
{
|
|
vtkChart *chart = this->Private->BigChart;
|
|
if (chart)
|
|
{
|
|
vtkPlotPoints *plot = vtkPlotPoints::SafeDownCast(chart->GetPlot(0));
|
|
if (plot)
|
|
{
|
|
plot->SetMarkerStyle(style);
|
|
}
|
|
}
|
|
this->Modified();
|
|
}
|
|
else if (plotType == SCATTERPLOT)
|
|
{
|
|
int plotCount = this->GetSize().GetX();
|
|
for (int i = 0; i < plotCount - 1; ++i)
|
|
{
|
|
for(int j = 0; j < plotCount - 1; ++j)
|
|
{
|
|
if(this->GetPlotType(i, j) == SCATTERPLOT &&
|
|
this->GetChart(vtkVector2i(i, j)))
|
|
{
|
|
vtkChart *chart = this->GetChart(vtkVector2i(i, j));
|
|
vtkPlotPoints *plot = vtkPlotPoints::SafeDownCast(chart->GetPlot(0));
|
|
if (plot)
|
|
{
|
|
plot->SetMarkerStyle(style);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this->Modified();
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetPlotMarkerSize(int plotType, float size)
|
|
{
|
|
if(plotType >= 0 && plotType < NOPLOT &&
|
|
size != this->Private->ChartSettings[plotType]->MarkerSize)
|
|
{
|
|
this->Private->ChartSettings[plotType]->MarkerSize = size;
|
|
|
|
if (plotType == ACTIVEPLOT)
|
|
{
|
|
// update marker size on current active plot
|
|
vtkChart *chart = this->Private->BigChart;
|
|
if(chart)
|
|
{
|
|
vtkPlotPoints *plot = vtkPlotPoints::SafeDownCast(chart->GetPlot(0));
|
|
if (plot)
|
|
{
|
|
plot->SetMarkerSize(size);
|
|
}
|
|
}
|
|
this->Modified();
|
|
}
|
|
else if (plotType == SCATTERPLOT)
|
|
{
|
|
int plotCount = this->GetSize().GetX();
|
|
|
|
for(int i = 0; i < plotCount - 1; i++)
|
|
{
|
|
for(int j = 0; j < plotCount - 1; j++)
|
|
{
|
|
if(this->GetPlotType(i, j) == SCATTERPLOT &&
|
|
this->GetChart(vtkVector2i(i, j)))
|
|
{
|
|
vtkChart *chart = this->GetChart(vtkVector2i(i, j));
|
|
vtkPlotPoints *plot = vtkPlotPoints::SafeDownCast(chart
|
|
->GetPlot(0));
|
|
if (plot)
|
|
{
|
|
plot->SetMarkerSize(size);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this->Modified();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool vtkScatterPlotMatrix::Hit(const vtkContextMouseEvent &)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool vtkScatterPlotMatrix::MouseMoveEvent(const vtkContextMouseEvent &)
|
|
{
|
|
// Eat the event, don't do anything for now...
|
|
return true;
|
|
}
|
|
|
|
bool vtkScatterPlotMatrix::MouseButtonPressEvent(const vtkContextMouseEvent &)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool vtkScatterPlotMatrix::MouseButtonReleaseEvent(
|
|
const vtkContextMouseEvent &mouse)
|
|
{
|
|
// Check we are not currently already animating
|
|
if (this->Private->TimerCallbackInitialized)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Work out which scatter plot was clicked - make that one the active plot.
|
|
vtkVector2i pos = this->GetChartIndex(mouse.GetPos());
|
|
|
|
if(pos.GetX() == -1 || pos.GetX() + pos.GetY() + 1 >= this->Size.GetX())
|
|
{
|
|
// We didn't click a chart in the bottom-left triangle of the matrix.
|
|
return true;
|
|
}
|
|
|
|
// If the left button was used, hyperjump, if the right was used full path.
|
|
if (mouse.GetButton() == vtkContextMouseEvent::LEFT_BUTTON)
|
|
{
|
|
if (this->NumberOfFrames == 0)
|
|
{
|
|
this->SetActivePlot(pos);
|
|
return true;
|
|
}
|
|
this->Private->AnimationPath.clear();
|
|
bool horizontalFirst = pos[0] > this->ActivePlot[0] ? false : true;
|
|
if (horizontalFirst)
|
|
{
|
|
if (pos[0] != this->ActivePlot[0])
|
|
{
|
|
this->Private->AnimationPath.push_back(vtkVector2i(pos[0],
|
|
this->ActivePlot[1]));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pos[1] != this->ActivePlot[1])
|
|
{
|
|
this->Private->AnimationPath.push_back(vtkVector2i(this->ActivePlot[0],
|
|
pos[1]));
|
|
}
|
|
}
|
|
if ((this->Private->AnimationPath.size() == 1 &&
|
|
this->Private->AnimationPath.back() != pos) ||
|
|
(this->Private->AnimationPath.size() == 0 && this->ActivePlot != pos))
|
|
{
|
|
this->Private->AnimationPath.push_back(pos);
|
|
}
|
|
if (this->Private->AnimationPath.size() > 0)
|
|
{
|
|
this->InvokeEvent(vtkCommand::CreateTimerEvent);
|
|
this->StartAnimation(mouse.GetInteractor());
|
|
}
|
|
}
|
|
else if (mouse.GetButton() == vtkContextMouseEvent::RIGHT_BUTTON)
|
|
{
|
|
if (this->NumberOfFrames == 0)
|
|
{
|
|
this->SetActivePlot(pos);
|
|
return true;
|
|
}
|
|
this->UpdateAnimationPath(pos);
|
|
if (this->Private->AnimationPath.size() > 0)
|
|
{
|
|
this->InvokeEvent(vtkCommand::CreateTimerEvent);
|
|
this->StartAnimation(mouse.GetInteractor());
|
|
}
|
|
else
|
|
{
|
|
this->SetActivePlot(pos);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetNumberOfFrames(int frames)
|
|
{
|
|
this->NumberOfFrames = frames;
|
|
}
|
|
|
|
int vtkScatterPlotMatrix::GetNumberOfFrames()
|
|
{
|
|
return this->NumberOfFrames;
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::ClearAnimationPath()
|
|
{
|
|
this->Private->AnimationPath.clear();
|
|
}
|
|
|
|
vtkIdType vtkScatterPlotMatrix::GetNumberOfAnimationPathElements()
|
|
{
|
|
return static_cast<vtkIdType>(this->Private->AnimationPath.size());
|
|
}
|
|
|
|
vtkVector2i vtkScatterPlotMatrix::GetAnimationPathElement(vtkIdType i)
|
|
{
|
|
return this->Private->AnimationPath.at(i);
|
|
}
|
|
|
|
bool vtkScatterPlotMatrix::AddAnimationPath(const vtkVector2i &move)
|
|
{
|
|
vtkVector2i pos = this->ActivePlot;
|
|
if (this->Private->AnimationPath.size())
|
|
{
|
|
pos = this->Private->AnimationPath.back();
|
|
}
|
|
if (move.GetX() != pos.GetX() && move.GetY() != pos.GetY())
|
|
{
|
|
// Can only move in x or y, not both. Do not append the element.
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
this->Private->AnimationPath.push_back(move);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool vtkScatterPlotMatrix::BeginAnimationPath(vtkRenderWindowInteractor* interactor)
|
|
{
|
|
if (interactor && this->Private->AnimationPath.size())
|
|
{
|
|
this->StartAnimation(interactor);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
int vtkScatterPlotMatrix::GetPlotType(const vtkVector2i &pos)
|
|
{
|
|
int plotCount = this->GetSize().GetX();
|
|
|
|
if(pos.GetX() + pos.GetY() + 1 < plotCount)
|
|
{
|
|
return SCATTERPLOT;
|
|
}
|
|
else if(pos.GetX() + pos.GetY() + 1 == plotCount)
|
|
{
|
|
return HISTOGRAM;
|
|
}
|
|
else if(pos.GetX() == pos.GetY() &&
|
|
pos.GetX() == static_cast<int>(plotCount / 2.0) + plotCount % 2)
|
|
{
|
|
return ACTIVEPLOT;
|
|
}
|
|
else
|
|
{
|
|
return NOPLOT;
|
|
}
|
|
}
|
|
|
|
int vtkScatterPlotMatrix::GetPlotType(int row, int column)
|
|
{
|
|
return this->GetPlotType(vtkVector2i(row, column));
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::UpdateAxes()
|
|
{
|
|
if (!this->Input)
|
|
{
|
|
return;
|
|
}
|
|
// We need to iterate through all visible columns and set up the axis ranges.
|
|
vtkAxis *axis(this->Private->TestAxis.GetPointer());
|
|
axis->SetPoint1(0, 0);
|
|
axis->SetPoint2(0, 200);
|
|
for (vtkIdType i = 0; i < this->VisibleColumns->GetNumberOfTuples(); ++i)
|
|
{
|
|
double range[2] = { 0, 0 };
|
|
std::string name(this->VisibleColumns->GetValue(i));
|
|
vtkDataArray *arr =
|
|
vtkDataArray::SafeDownCast(this->Input->GetColumnByName(name.c_str()));
|
|
if (arr)
|
|
{
|
|
PIMPL::ColumnSetting settings;
|
|
arr->GetRange(range);
|
|
// Apply a little padding either side of the ranges.
|
|
range[0] = range[0] - (0.01 * range[0]);
|
|
range[1] = range[1] + (0.01 * range[1]);
|
|
axis->SetUnscaledRange(range);
|
|
axis->AutoScale();
|
|
settings.min = axis->GetUnscaledMinimum();
|
|
settings.max = axis->GetUnscaledMaximum();
|
|
settings.nTicks = axis->GetNumberOfTicks();
|
|
settings.title = name;
|
|
this->Private->ColumnSettings[name] = settings;
|
|
}
|
|
else
|
|
{
|
|
vtkDebugMacro(<< "No valid data array available. " << name);
|
|
}
|
|
}
|
|
}
|
|
|
|
vtkStdString vtkScatterPlotMatrix::GetColumnName(int column)
|
|
{
|
|
assert(column < this->VisibleColumns->GetNumberOfTuples());
|
|
return this->VisibleColumns->GetValue(column);
|
|
}
|
|
|
|
vtkStdString vtkScatterPlotMatrix::GetRowName(int row)
|
|
{
|
|
assert(row < this->VisibleColumns->GetNumberOfTuples());
|
|
return this->VisibleColumns->GetValue(this->Size.GetY() - row - 1);
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::ApplyAxisSetting(vtkChart *chart,
|
|
const vtkStdString &x,
|
|
const vtkStdString &y)
|
|
{
|
|
PIMPL::ColumnSetting &xSettings = this->Private->ColumnSettings[x];
|
|
PIMPL::ColumnSetting &ySettings = this->Private->ColumnSettings[y];
|
|
vtkAxis *axis = chart->GetAxis(vtkAxis::BOTTOM);
|
|
axis->SetUnscaledRange(xSettings.min, xSettings.max);
|
|
axis->SetBehavior(vtkAxis::FIXED);
|
|
axis = chart->GetAxis(vtkAxis::TOP);
|
|
axis->SetUnscaledRange(xSettings.min, xSettings.max);
|
|
axis->SetBehavior(vtkAxis::FIXED);
|
|
axis = chart->GetAxis(vtkAxis::LEFT);
|
|
axis->SetUnscaledRange(ySettings.min, ySettings.max);
|
|
axis->SetBehavior(vtkAxis::FIXED);
|
|
axis = chart->GetAxis(vtkAxis::RIGHT);
|
|
axis->SetUnscaledRange(ySettings.min, ySettings.max);
|
|
axis->SetBehavior(vtkAxis::FIXED);
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::UpdateLayout()
|
|
{
|
|
// We want scatter plots on the lower-left triangle, then histograms along
|
|
// the diagonal and a big plot in the top-right. The basic layout is,
|
|
//
|
|
// 3 H +++
|
|
// 2 S H +++
|
|
// 1 S S H
|
|
// 0 S S S H
|
|
// 0 1 2 3
|
|
//
|
|
// Where the indices are those of the columns. The indices of the charts
|
|
// originate in the bottom-left. S = scatter plot, H = histogram and + is the
|
|
// big chart.
|
|
int n = this->Size.GetX();
|
|
this->UpdateAxes();
|
|
this->Private->BigChart3D->SetAnnotationLink(this->Private->Link.GetPointer());
|
|
for (int i = 0; i < n; ++i)
|
|
{
|
|
vtkStdString column = this->GetColumnName(i);
|
|
for (int j = 0; j < n; ++j)
|
|
{
|
|
vtkStdString row = this->GetRowName(j);
|
|
vtkVector2i pos(i, j);
|
|
if (this->GetPlotType(pos) == SCATTERPLOT)
|
|
{
|
|
vtkChart* chart = this->GetChart(pos);
|
|
this->ApplyAxisSetting(chart, column, row);
|
|
chart->ClearPlots();
|
|
chart->SetInteractive(false);
|
|
chart->SetAnnotationLink(this->Private->Link.GetPointer());
|
|
// Lower-left triangle - scatter plots.
|
|
chart->SetActionToButton(vtkChart::PAN, -1);
|
|
chart->SetActionToButton(vtkChart::ZOOM, -1);
|
|
chart->SetActionToButton(vtkChart::SELECT, -1);
|
|
vtkPlot *plot = chart->AddPlot(vtkChart::POINTS);
|
|
plot->SetInputData(this->Input.GetPointer(), column, row);
|
|
plot->SetPen(this->Private->ChartSettings[SCATTERPLOT]
|
|
->PlotPen.GetPointer());
|
|
// set plot marker size and style
|
|
vtkPlotPoints *plotPoints = vtkPlotPoints::SafeDownCast(plot);
|
|
plotPoints->SetMarkerSize(this->Private->ChartSettings[SCATTERPLOT]
|
|
->MarkerSize);
|
|
plotPoints->SetMarkerStyle(this->Private->ChartSettings[SCATTERPLOT]
|
|
->MarkerStyle);
|
|
}
|
|
else if (this->GetPlotType(pos) == HISTOGRAM)
|
|
{
|
|
// We are on the diagonal - need a histogram plot.
|
|
vtkChart* chart = this->GetChart(pos);
|
|
chart->SetInteractive(false);
|
|
this->ApplyAxisSetting(chart, column, row);
|
|
chart->ClearPlots();
|
|
vtkPlot *plot = chart->AddPlot(vtkChart::BAR);
|
|
plot->SetPen(this->Private->ChartSettings[HISTOGRAM]
|
|
->PlotPen.GetPointer());
|
|
plot->SetBrush(this->Private->ChartSettings[HISTOGRAM]
|
|
->PlotBrush.GetPointer());
|
|
vtkStdString name(this->VisibleColumns->GetValue(i));
|
|
plot->SetInputData(this->Private->Histogram.GetPointer(),
|
|
name + "_extents", name + "_pops");
|
|
vtkAxis *axis = chart->GetAxis(vtkAxis::TOP);
|
|
axis->SetTitle(name);
|
|
axis->SetLabelsVisible(false);
|
|
// Show the labels on the right for populations of bins.
|
|
axis = chart->GetAxis(vtkAxis::RIGHT);
|
|
axis->SetLabelsVisible(true);
|
|
axis->SetBehavior(vtkAxis::AUTO);
|
|
axis->AutoScale();
|
|
// Set the plot corner to the top-right
|
|
vtkChartXY *xy = vtkChartXY::SafeDownCast(chart);
|
|
if (xy)
|
|
{
|
|
xy->SetBarWidthFraction(1.0);
|
|
xy->SetPlotCorner(plot, 2);
|
|
}
|
|
|
|
// set background color to light gray
|
|
xy->SetBackgroundBrush(this->Private->ChartSettings[HISTOGRAM]
|
|
->BackgroundBrush.GetPointer());
|
|
}
|
|
else if (this->GetPlotType(pos) == ACTIVEPLOT)
|
|
{
|
|
// This big plot in the top-right
|
|
this->Private->BigChart = this->GetChart(pos);
|
|
this->Private->BigChart->SetAnnotationLink(
|
|
this->Private->Link.GetPointer());
|
|
this->Private->BigChart->AddObserver(
|
|
vtkCommand::SelectionChangedEvent, this,
|
|
&vtkScatterPlotMatrix::BigChartSelectionCallback);
|
|
|
|
// set tooltip item
|
|
vtkChartXY *chartXY =
|
|
vtkChartXY::SafeDownCast(this->Private->BigChart.GetPointer());
|
|
if(chartXY)
|
|
{
|
|
chartXY->SetTooltip(this->Private->TooltipItem);
|
|
}
|
|
|
|
this->SetChartSpan(pos, vtkVector2i(n - i, n - j));
|
|
this->SetActivePlot(vtkVector2i(0, n - 2));
|
|
}
|
|
// Only show bottom axis label for bottom plots
|
|
if (j > 0)
|
|
{
|
|
vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::BOTTOM);
|
|
axis->SetTitle("");
|
|
axis->SetLabelsVisible(false);
|
|
axis->SetBehavior(vtkAxis::FIXED);
|
|
}
|
|
else
|
|
{
|
|
vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::BOTTOM);
|
|
axis->SetTitle(this->VisibleColumns->GetValue(i));
|
|
axis->SetLabelsVisible(false);
|
|
this->AttachAxisRangeListener(axis);
|
|
}
|
|
// Only show the left axis labels for left-most plots
|
|
if (i > 0)
|
|
{
|
|
vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::LEFT);
|
|
axis->SetTitle("");
|
|
axis->SetLabelsVisible(false);
|
|
axis->SetBehavior(vtkAxis::FIXED);
|
|
}
|
|
else
|
|
{
|
|
vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::LEFT);
|
|
axis->SetTitle(this->VisibleColumns->GetValue(n - j - 1));
|
|
axis->SetLabelsVisible(false);
|
|
this->AttachAxisRangeListener(axis);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::AttachAxisRangeListener(vtkAxis* axis)
|
|
{
|
|
axis->AddObserver(vtkChart::UpdateRange, this,
|
|
&vtkScatterPlotMatrix::AxisRangeForwarderCallback);
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::AxisRangeForwarderCallback(vtkObject*,
|
|
unsigned long, void*)
|
|
{
|
|
// Only set on the end axes, and propagated to all other matching axes.
|
|
double r[2];
|
|
int n = this->GetSize().GetX() - 1;
|
|
for (int i = 0; i < n; ++i)
|
|
{
|
|
this->GetChart(vtkVector2i(i, 0))
|
|
->GetAxis(vtkAxis::BOTTOM)
|
|
->GetUnscaledRange(r);
|
|
for (int j = 1; j < n - i; ++j)
|
|
{
|
|
this->GetChart(vtkVector2i(i, j))
|
|
->GetAxis(vtkAxis::BOTTOM)
|
|
->SetUnscaledRange(r);
|
|
}
|
|
this->GetChart(vtkVector2i(i, n-i))
|
|
->GetAxis(vtkAxis::TOP)
|
|
->SetUnscaledRange(r);
|
|
this->GetChart(vtkVector2i(0, i))
|
|
->GetAxis(vtkAxis::LEFT)
|
|
->GetUnscaledRange(r);
|
|
for (int j = 1; j < n - i; ++j)
|
|
{
|
|
this->GetChart(vtkVector2i(j, i))
|
|
->GetAxis(vtkAxis::LEFT)
|
|
->SetUnscaledRange(r);
|
|
}
|
|
}
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::BigChartSelectionCallback(vtkObject*,
|
|
unsigned long event, void*)
|
|
{
|
|
// forward the SelectionChangedEvent from the Big Chart plot
|
|
this->InvokeEvent(event);
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetTitle(const vtkStdString& title)
|
|
{
|
|
if (this->Title != title)
|
|
{
|
|
this->Title = title;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
vtkStdString vtkScatterPlotMatrix::GetTitle()
|
|
{
|
|
return this->Title;
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetTitleProperties(vtkTextProperty *prop)
|
|
{
|
|
if (this->TitleProperties != prop)
|
|
{
|
|
this->TitleProperties = prop;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
vtkTextProperty* vtkScatterPlotMatrix::GetTitleProperties()
|
|
{
|
|
return this->TitleProperties.GetPointer();
|
|
}
|
|
|
|
void vtkScatterPlotMatrix::SetAxisLabelProperties(int plotType,
|
|
vtkTextProperty *prop)
|
|
{
|
|
if (plotType >= 0 && plotType < vtkScatterPlotMatrix::NOPLOT &&
|
|
this->Private->ChartSettings[plotType]->LabelFont != prop)
|
|
{
|
|
this->Private->ChartSettings[plotType]->LabelFont = prop;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
vtkTextProperty* vtkScatterPlotMatrix::GetAxisLabelProperties(int plotType)
|
|
{
|
|
if (plotType >= 0 && plotType < vtkScatterPlotMatrix::NOPLOT)
|
|
{
|
|
return this->Private->ChartSettings[plotType]->LabelFont.GetPointer();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetBackgroundColor(int plotType,
|
|
const vtkColor4ub& color)
|
|
{
|
|
if (plotType >= 0 && plotType < vtkScatterPlotMatrix::NOPLOT)
|
|
{
|
|
this->Private->ChartSettings[plotType]->BackgroundBrush->SetColor(color);
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetAxisColor(int plotType,
|
|
const vtkColor4ub& color)
|
|
{
|
|
if (plotType >= 0 && plotType < vtkScatterPlotMatrix::NOPLOT)
|
|
{
|
|
this->Private->ChartSettings[plotType]->AxisColor = color;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetGridVisibility(int plotType, bool visible)
|
|
{
|
|
if(plotType!= NOPLOT)
|
|
{
|
|
this->Private->ChartSettings[plotType]->ShowGrid = visible;
|
|
// How to update
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetGridColor(int plotType,
|
|
const vtkColor4ub& color)
|
|
{
|
|
if (plotType >= 0 && plotType < vtkScatterPlotMatrix::NOPLOT)
|
|
{
|
|
this->Private->ChartSettings[plotType]->GridColor = color;
|
|
// How to update
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetAxisLabelVisibility(int plotType, bool visible)
|
|
{
|
|
if(plotType!= NOPLOT)
|
|
{
|
|
this->Private->ChartSettings[plotType]->ShowAxisLabels = visible;
|
|
// How to update
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetAxisLabelNotation(int plotType, int notation)
|
|
{
|
|
if(plotType!= NOPLOT)
|
|
{
|
|
this->Private->ChartSettings[plotType]->LabelNotation = notation;
|
|
// How to update
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetAxisLabelPrecision(int plotType, int precision)
|
|
{
|
|
if(plotType!= NOPLOT)
|
|
{
|
|
this->Private->ChartSettings[plotType]->LabelPrecision = precision;
|
|
// How to update
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetTooltipNotation(int plotType, int notation)
|
|
{
|
|
if(plotType!= NOPLOT)
|
|
{
|
|
this->Private->ChartSettings[plotType]->TooltipNotation = notation;
|
|
// How to update
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetTooltipPrecision(int plotType, int precision)
|
|
{
|
|
if(plotType!= NOPLOT)
|
|
{
|
|
this->Private->ChartSettings[plotType]->TooltipPrecision = precision;
|
|
// How to update
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetScatterPlotSelectedRowColumnColor(
|
|
const vtkColor4ub& color)
|
|
{
|
|
this->Private->SelectedRowColumnBGBrush->SetColor(color);
|
|
this->Modified();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetScatterPlotSelectedActiveColor(
|
|
const vtkColor4ub& color)
|
|
{
|
|
this->Private->SelectedChartBGBrush->SetColor(color);
|
|
this->Modified();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::UpdateChartSettings(int plotType)
|
|
{
|
|
if (plotType == HISTOGRAM)
|
|
{
|
|
int plotCount = this->GetSize().GetX();
|
|
|
|
for(int i = 0; i < plotCount; i++)
|
|
{
|
|
vtkChart *chart = this->GetChart(vtkVector2i(i, plotCount - i - 1));
|
|
this->Private->UpdateAxis(chart->GetAxis(vtkAxis::TOP),
|
|
this->Private->ChartSettings[HISTOGRAM]);
|
|
this->Private->UpdateAxis(chart->GetAxis(vtkAxis::RIGHT),
|
|
this->Private->ChartSettings[HISTOGRAM]);
|
|
this->Private->UpdateChart(chart, this->Private->ChartSettings[HISTOGRAM]);
|
|
}
|
|
}
|
|
else if (plotType == SCATTERPLOT)
|
|
{
|
|
int plotCount = this->GetSize().GetX();
|
|
|
|
for (int i = 0; i < plotCount - 1; i++)
|
|
{
|
|
for (int j = 0; j < plotCount - 1; j++)
|
|
{
|
|
if (this->GetPlotType(i, j) == SCATTERPLOT)
|
|
{
|
|
vtkChart *chart = this->GetChart(vtkVector2i(i, j));
|
|
bool updateleft = i==0 ? true : false;
|
|
bool updatebottom = j==0 ? true : false;
|
|
this->Private->UpdateAxis(chart->GetAxis(vtkAxis::LEFT),
|
|
this->Private->ChartSettings[SCATTERPLOT], updateleft);
|
|
this->Private->UpdateAxis(chart->GetAxis(vtkAxis::BOTTOM),
|
|
this->Private->ChartSettings[SCATTERPLOT], updatebottom);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (plotType == ACTIVEPLOT && this->Private->BigChart)
|
|
{
|
|
this->Private->UpdateAxis(this->Private->BigChart->GetAxis(vtkAxis::TOP),
|
|
this->Private->ChartSettings[ACTIVEPLOT]);
|
|
this->Private->UpdateAxis(this->Private->BigChart->GetAxis(vtkAxis::RIGHT),
|
|
this->Private->ChartSettings[ACTIVEPLOT]);
|
|
this->Private->UpdateChart(this->Private->BigChart,
|
|
this->Private->ChartSettings[ACTIVEPLOT]);
|
|
this->Private->BigChart->SetSelectionMode(this->SelectionMode);
|
|
}
|
|
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetSelectionMode(int selMode)
|
|
{
|
|
if (this->SelectionMode == selMode ||
|
|
selMode < vtkContextScene::SELECTION_NONE ||
|
|
selMode > vtkContextScene::SELECTION_TOGGLE)
|
|
{
|
|
return;
|
|
}
|
|
this->SelectionMode = selMode;
|
|
if(this->Private->BigChart)
|
|
{
|
|
this->Private->BigChart->SetSelectionMode(selMode);
|
|
}
|
|
|
|
this->Modified();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::UpdateSettings()
|
|
{
|
|
|
|
// TODO: Should update the Scatter plot title
|
|
|
|
this->UpdateChartSettings(ACTIVEPLOT);
|
|
this->UpdateChartSettings(HISTOGRAM);
|
|
this->UpdateChartSettings(SCATTERPLOT);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkScatterPlotMatrix::GetGridVisibility(int plotType)
|
|
{
|
|
assert(plotType != NOPLOT);
|
|
return this->Private->ChartSettings[plotType]->ShowGrid;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkColor4ub vtkScatterPlotMatrix::GetBackgroundColor(int plotType)
|
|
{
|
|
assert(plotType != NOPLOT);
|
|
return this->Private->ChartSettings[plotType]->BackgroundBrush
|
|
->GetColorObject();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkColor4ub vtkScatterPlotMatrix::GetAxisColor(int plotType)
|
|
{
|
|
assert(plotType != NOPLOT);
|
|
return this->Private->ChartSettings[plotType]->AxisColor;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkColor4ub vtkScatterPlotMatrix::GetGridColor(int plotType)
|
|
{
|
|
assert(plotType != NOPLOT);
|
|
return this->Private->ChartSettings[plotType]->GridColor;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkScatterPlotMatrix::GetAxisLabelVisibility(int plotType)
|
|
{
|
|
assert(plotType != NOPLOT);
|
|
return this->Private->ChartSettings[plotType]->ShowAxisLabels;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkScatterPlotMatrix::GetAxisLabelNotation(int plotType)
|
|
{
|
|
assert(plotType != NOPLOT);
|
|
return this->Private->ChartSettings[plotType]->LabelNotation;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkScatterPlotMatrix::GetAxisLabelPrecision(int plotType)
|
|
{
|
|
assert(plotType != NOPLOT);
|
|
return this->Private->ChartSettings[plotType]->LabelPrecision;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkScatterPlotMatrix::GetTooltipNotation(int plotType)
|
|
{
|
|
assert(plotType != NOPLOT);
|
|
return this->Private->ChartSettings[plotType]->TooltipNotation;
|
|
}
|
|
|
|
int vtkScatterPlotMatrix::GetTooltipPrecision(int plotType)
|
|
{
|
|
assert(plotType != NOPLOT);
|
|
return this->Private->ChartSettings[plotType]->TooltipPrecision;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetTooltip(vtkTooltipItem *tooltip)
|
|
{
|
|
if(tooltip != this->Private->TooltipItem)
|
|
{
|
|
this->Private->TooltipItem = tooltip;
|
|
this->Modified();
|
|
|
|
vtkChartXY *chartXY =
|
|
vtkChartXY::SafeDownCast(this->Private->BigChart.GetPointer());
|
|
|
|
if(chartXY)
|
|
{
|
|
chartXY->SetTooltip(tooltip);
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkTooltipItem* vtkScatterPlotMatrix::GetTooltip() const
|
|
{
|
|
return this->Private->TooltipItem;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::SetIndexedLabels(vtkStringArray *labels)
|
|
{
|
|
if(labels != this->Private->IndexedLabelsArray)
|
|
{
|
|
this->Private->IndexedLabelsArray = labels;
|
|
this->Modified();
|
|
|
|
if(this->Private->BigChart)
|
|
{
|
|
vtkPlot *plot = this->Private->BigChart->GetPlot(0);
|
|
|
|
if(plot)
|
|
{
|
|
plot->SetIndexedLabels(labels);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkStringArray* vtkScatterPlotMatrix::GetIndexedLabels() const
|
|
{
|
|
return this->Private->IndexedLabelsArray;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkColor4ub vtkScatterPlotMatrix::GetScatterPlotSelectedRowColumnColor()
|
|
{
|
|
return this->Private->SelectedRowColumnBGBrush->GetColorObject();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkColor4ub vtkScatterPlotMatrix::GetScatterPlotSelectedActiveColor()
|
|
{
|
|
return this->Private->SelectedChartBGBrush->GetColorObject();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkChart * vtkScatterPlotMatrix::GetMainChart()
|
|
{
|
|
return this->Private->BigChart.GetPointer();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkScatterPlotMatrix::PrintSelf(ostream &os, vtkIndent indent)
|
|
{
|
|
Superclass::PrintSelf(os, indent);
|
|
|
|
os << indent << "NumberOfBins: " << this->NumberOfBins << endl;
|
|
os << indent << "Title: " << this->Title << endl;
|
|
os << indent << "SelectionMode: " << this->SelectionMode << endl;
|
|
}
|