Skip to content

Commit

Permalink
ENH: ctkVTKChartView now supports Parallel Coordinates chart
Browse files Browse the repository at this point in the history
The chart() function has been converted to xyChart(). Therefore,
chart() should be deprecated in the future.
  • Loading branch information
spyridon97 committed Apr 13, 2023
1 parent cd194ff commit d94b999
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 45 deletions.
173 changes: 129 additions & 44 deletions Libs/Visualization/VTK/Widgets/ctkVTKChartView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@

// VTK includes
#include <vtkAxis.h>
#include <vtkChart.h>
#include <vtkChartXY.h>
#include <vtkContext2D.h>
#include <vtkContextMouseEvent.h>
#include <vtkContextScene.h>
#include <vtkContextView.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkOpenGLContextDevice2D.h>
#include <vtkChartParallelCoordinates.h>
#include <vtkPlot.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
Expand All @@ -53,12 +55,13 @@ class ctkVTKChartViewPrivate
ctkVTKChartViewPrivate(ctkVTKChartView& object);
void init();
void chartBounds(double* bounds)const;
void setChartType(int chartType);

#ifdef CTK_USE_QVTKOPENGLWIDGET
vtkSmartPointer<vtkGenericOpenGLRenderWindow> RenderWindow;
#endif
vtkSmartPointer<vtkContextView> ContextView;
vtkSmartPointer<vtkChartXY> Chart;
vtkSmartPointer<vtkChart> Chart;
double UserBounds[8];
mutable double OldBounds[8];
};
Expand All @@ -74,14 +77,61 @@ ctkVTKChartViewPrivate::ctkVTKChartViewPrivate(ctkVTKChartView& object)
#ifdef CTK_USE_QVTKOPENGLWIDGET
this->RenderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
#endif
this->Chart = vtkSmartPointer<vtkChartXY>::New();
this->setChartType(ctkVTKChartView::ChartTypes::XYChart);
}

// ----------------------------------------------------------------------------
void ctkVTKChartViewPrivate::setChartType(int chartType)
{
if (this->ContextView->GetScene()->GetNumberOfItems() > 0)
{
this->ContextView->GetScene()->RemoveItem(this->Chart);
}
switch (chartType)
{
case ctkVTKChartView::ChartTypes::XYChart:
this->Chart = vtkSmartPointer<vtkChartXY>::New();
break;
case ctkVTKChartView::ChartTypes::ParallelCoordinatesChart:
this->Chart = vtkSmartPointer<vtkChartParallelCoordinates>::New();
break;
case ctkVTKChartView::ChartTypes::UnknownChart:
default:
qWarning() << "ctkVTKChartViewPrivate::setChartType - Unknown chart type: " << chartType;
return;
}
this->ContextView->GetScene()->AddItem(this->Chart);
this->UserBounds[0] = this->UserBounds[2] = this->UserBounds[4] = this->UserBounds[6] = 0.;
this->UserBounds[1] = this->UserBounds[3] = this->UserBounds[5] = this->UserBounds[7] = -1.;
this->OldBounds[0] = this->OldBounds[2] = this->OldBounds[4] = this->OldBounds[6] = 0.;
this->OldBounds[1] = this->OldBounds[3] = this->OldBounds[5] = this->OldBounds[7] = -1.;
}

// ----------------------------------------------------------------------------
int ctkVTKChartView::chartType()const
{
Q_D(const ctkVTKChartView);
if (d->Chart->IsA("vtkChartXY"))
{
return ctkVTKChartView::ChartTypes::XYChart;
}
else if (d->Chart->IsA("vtkChartParallelCoordinates"))
{
return ctkVTKChartView::ChartTypes::ParallelCoordinatesChart;
}
else
{
return ctkVTKChartView::ChartTypes::UnknownChart;
}
}

// ----------------------------------------------------------------------------
void ctkVTKChartView::setChartType(int type)
{
Q_D(ctkVTKChartView);
d->setChartType(type);
}

// ----------------------------------------------------------------------------
void ctkVTKChartViewPrivate::init()
{
Expand Down Expand Up @@ -118,9 +168,9 @@ void ctkVTKChartViewPrivate::init()
this->Chart->SetActionToButton(vtkChart::PAN, vtkContextMouseEvent::MIDDLE_BUTTON);
this->Chart->SetActionToButton(vtkChart::SELECT, vtkContextMouseEvent::RIGHT_BUTTON);

q->qvtkConnect(q->chart()->GetAxis(vtkAxis::BOTTOM),vtkCommand::ModifiedEvent,
q->qvtkConnect(q->abstractChart()->GetAxis(vtkAxis::BOTTOM),vtkCommand::ModifiedEvent,
q, SIGNAL(extentChanged()));
q->qvtkConnect(q->chart()->GetAxis(vtkAxis::LEFT),vtkCommand::ModifiedEvent,
q->qvtkConnect(q->abstractChart()->GetAxis(vtkAxis::LEFT),vtkCommand::ModifiedEvent,
q, SIGNAL(extentChanged()));

}
Expand All @@ -135,53 +185,68 @@ void ctkVTKChartViewPrivate::chartBounds(double* bounds)const
Q_Q(const ctkVTKChartView);
bounds[0] = bounds[2] = bounds[4] = bounds[6] = VTK_DOUBLE_MAX;
bounds[1] = bounds[3] = bounds[5] = bounds[7] = VTK_DOUBLE_MIN;
vtkChartXY* chart = q->chart();
vtkChart* chart = q->abstractChart();
vtkChartXY* chartXY = vtkChartXY::SafeDownCast(chart);
const vtkIdType plotCount = chart->GetNumberOfPlots();
for (vtkIdType i = 0; i < plotCount; ++i)
{
vtkPlot* plot = chart->GetPlot(i);

int corner = chart->GetPlotCorner(plot);
double plotBounds[4];
plot->GetBounds(plotBounds);
switch (corner)
if (chartXY)
{
// bottom left
case 0:
int corner = chartXY->GetPlotCorner(plot);
double plotBounds[4];
plot->GetBounds(plotBounds);
switch (corner)
{
// bottom left
case 0:
// x
bounds[2] = bounds[2] > plotBounds[0] ? plotBounds[0] : bounds[2];
bounds[3] = bounds[3] < plotBounds[1] ? plotBounds[1] : bounds[3];
// y
bounds[0] = bounds[0] > plotBounds[2] ? plotBounds[2] : bounds[0];
bounds[1] = bounds[1] < plotBounds[3] ? plotBounds[3] : bounds[1];
break;
// bottom right
case 1:
// x
bounds[2] = bounds[2] > plotBounds[0] ? plotBounds[0] : bounds[2];
bounds[3] = bounds[3] < plotBounds[1] ? plotBounds[1] : bounds[3];
// y
bounds[4] = bounds[4] > plotBounds[2] ? plotBounds[2] : bounds[4];
bounds[5] = bounds[5] < plotBounds[3] ? plotBounds[3] : bounds[5];
break;
// top right
case 2:
// x
bounds[6] = bounds[6] > plotBounds[0] ? plotBounds[0] : bounds[6];
bounds[7] = bounds[7] < plotBounds[1] ? plotBounds[1] : bounds[7];
// y
bounds[4] = bounds[4] > plotBounds[2] ? plotBounds[2] : bounds[4];
bounds[5] = bounds[5] < plotBounds[3] ? plotBounds[3] : bounds[5];
break;
// top left
case 3:
// x
bounds[6] = bounds[6] > plotBounds[0] ? plotBounds[0] : bounds[6];
bounds[7] = bounds[7] < plotBounds[1] ? plotBounds[1] : bounds[7];
// y
bounds[0] = bounds[0] > plotBounds[2] ? plotBounds[2] : bounds[1];
bounds[1] = bounds[0] < plotBounds[3] ? plotBounds[3] : bounds[1];
break;
}
}
else
{
double plotBounds[4];
plot->GetBounds(plotBounds);
// x
bounds[2] = bounds[2] > plotBounds[0] ? plotBounds[0] : bounds[2];
bounds[3] = bounds[3] < plotBounds[1] ? plotBounds[1] : bounds[3];
// y
bounds[0] = bounds[0] > plotBounds[2] ? plotBounds[2] : bounds[0];
bounds[1] = bounds[1] < plotBounds[3] ? plotBounds[3] : bounds[1];
break;
// bottom right
case 1:
// x
bounds[2] = bounds[2] > plotBounds[0] ? plotBounds[0] : bounds[2];
bounds[3] = bounds[3] < plotBounds[1] ? plotBounds[1] : bounds[3];
// y
bounds[4] = bounds[4] > plotBounds[2] ? plotBounds[2] : bounds[4];
bounds[5] = bounds[5] < plotBounds[3] ? plotBounds[3] : bounds[5];
break;
// top right
case 2:
// x
bounds[6] = bounds[6] > plotBounds[0] ? plotBounds[0] : bounds[6];
bounds[7] = bounds[7] < plotBounds[1] ? plotBounds[1] : bounds[7];
// y
bounds[4] = bounds[4] > plotBounds[2] ? plotBounds[2] : bounds[4];
bounds[5] = bounds[5] < plotBounds[3] ? plotBounds[3] : bounds[5];
break;
// top left
case 3:
// x
bounds[6] = bounds[6] > plotBounds[0] ? plotBounds[0] : bounds[6];
bounds[7] = bounds[7] < plotBounds[1] ? plotBounds[1] : bounds[7];
// y
bounds[0] = bounds[0] > plotBounds[2] ? plotBounds[2] : bounds[1];
bounds[1] = bounds[0] < plotBounds[3] ? plotBounds[3] : bounds[1];
break;
}
}
}
Expand Down Expand Up @@ -221,12 +286,32 @@ QString ctkVTKChartView::title()const
}

// ----------------------------------------------------------------------------
vtkChartXY* ctkVTKChartView::chart()const
vtkChart* ctkVTKChartView::abstractChart()const
{
Q_D(const ctkVTKChartView);
return d->Chart;
}

// ----------------------------------------------------------------------------
vtkChartParallelCoordinates* ctkVTKChartView::parallelCoordinatesChart()const
{
Q_D(const ctkVTKChartView);
return vtkChartParallelCoordinates::SafeDownCast(d->Chart);
}

// ----------------------------------------------------------------------------
vtkChartXY* ctkVTKChartView::xyChart()const
{
Q_D(const ctkVTKChartView);
return vtkChartXY::SafeDownCast(d->Chart);
}

// ----------------------------------------------------------------------------
vtkChartXY* ctkVTKChartView::chart()const
{
return this->xyChart();
}

// ----------------------------------------------------------------------------
vtkContextScene* ctkVTKChartView::scene()const
{
Expand Down Expand Up @@ -312,7 +397,7 @@ void ctkVTKChartView::chartExtent(double* extent)const
}
extent[0] = extent[2] = extent[4] = extent[6] = VTK_DOUBLE_MAX;
extent[1] = extent[3] = extent[5] = extent[7] = VTK_DOUBLE_MIN;
vtkChartXY* chart = this->chart();
vtkChart* chart = this->abstractChart();
vtkAxis* axis = chart->GetAxis(vtkAxis::BOTTOM);
extent[0] = qMin(axis->GetMinimum(), extent[0]);
extent[1] = qMax(axis->GetMaximum(), extent[1]);
Expand All @@ -335,7 +420,7 @@ void ctkVTKChartView::setChartUserExtent(double* userExtent)
qCritical() << Q_FUNC_INFO << ": Invalid user extent";
return;
}
vtkChartXY* chart = this->chart();
vtkChart* chart = this->abstractChart();
vtkAxis* axis = chart->GetAxis(vtkAxis::BOTTOM);
axis->SetRange(userExtent[0], userExtent[1]);
axis = chart->GetAxis(vtkAxis::LEFT);
Expand Down Expand Up @@ -386,7 +471,7 @@ void ctkVTKChartView::chartUserBounds(double* bounds)const
// ----------------------------------------------------------------------------
void ctkVTKChartView::setAxesToChartBounds()
{
vtkChartXY* chart = this->chart();
vtkChart* chart = this->abstractChart();
double bounds[8];
this->chartBounds(bounds);
for (int i = 0; i < chart->GetNumberOfAxes(); ++i)
Expand All @@ -401,7 +486,7 @@ void ctkVTKChartView::setAxesToChartBounds()
// ----------------------------------------------------------------------------
void ctkVTKChartView::boundAxesToChartBounds()
{
vtkChartXY* chart = this->chart();
vtkChart* chart = this->abstractChart();
double bounds[8];
this->chartBounds(bounds);
for (int i = 0; i < chart->GetNumberOfAxes(); ++i)
Expand Down
22 changes: 21 additions & 1 deletion Libs/Visualization/VTK/Widgets/ctkVTKChartView.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
class ctkVTKChartViewPrivate;

// VTK includes
class vtkChart;
class vtkChartParallelCoordinates;
class vtkChartXY;
class vtkContextScene;
class vtkPlot;
Expand All @@ -38,7 +40,7 @@ class CTK_VISUALIZATION_VTK_WIDGETS_EXPORT ctkVTKChartView : public ctkVTKOpenGL
Q_OBJECT
QVTK_OBJECT
Q_PROPERTY(QString title READ title WRITE setTitle)

Q_PROPERTY(int chartType READ chartType WRITE setChartType)
public:
typedef ctkVTKOpenGLNativeWidget Superclass;
ctkVTKChartView(QWidget* parent = 0);
Expand All @@ -58,9 +60,27 @@ class CTK_VISUALIZATION_VTK_WIDGETS_EXPORT ctkVTKChartView : public ctkVTKOpenGL

/// Utility function that returns the view chart. It can be used for customizing
/// the chart display options (axes, legend...)
Q_INVOKABLE vtkChart* abstractChart()const;
Q_INVOKABLE vtkChartParallelCoordinates* parallelCoordinatesChart()const;
Q_INVOKABLE vtkChartXY* xyChart()const;
Q_INVOKABLE vtkChartXY* chart()const;
Q_INVOKABLE vtkContextScene* scene()const;

/// Enumerated values for charType
enum ChartTypes
{
UnknownChart = 0,
XYChart = 1,
ParallelCoordinatesChart = 2,
NumberOfChartTypes
};
Q_ENUM(ChartTypes)

/// Set/Get the type of the chart, XYChart is the default
/// The string names as the same as the ChartTypes enum
Q_INVOKABLE int chartType() const;
Q_INVOKABLE void setChartType(int type);

/// Title that appears inside the view
QString title()const;
void setTitle(const QString& title);
Expand Down

0 comments on commit d94b999

Please sign in to comment.