Skip to content

Commit

Permalink
ENH: Add Parallel Coordinates support to ctkVTKChartView
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 authored and jcfr committed Jul 12, 2023
1 parent 491614f commit 49d73d0
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 45 deletions.
174 changes: 130 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,62 @@ 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);
emit chartTypeChanged(type);
}

// ----------------------------------------------------------------------------
void ctkVTKChartViewPrivate::init()
{
Expand Down Expand Up @@ -118,9 +169,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 +186,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 +287,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 +398,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 +421,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 +472,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 +487,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
24 changes: 23 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 Expand Up @@ -100,6 +120,8 @@ public Q_SLOTS:
/// Fired anytime an axis is modified.
void extentChanged();

void chartTypeChanged(int chartType);

protected:
QScopedPointer<ctkVTKChartViewPrivate> d_ptr;

Expand Down

0 comments on commit 49d73d0

Please sign in to comment.