Commit 8a373c36 authored by LE BRETON Come's avatar LE BRETON Come

Displays iso(lines-surfaces). Need to adjust the controls.

parent c4fad44b
......@@ -20,6 +20,7 @@
#include <dtkVisualization/dtkVisualizationView3D>
#include <dtkVisualization/dtkVisualizationDecoratorScalarColorMap>
#include <dtkVisualization/dtkVisualizationDecoratorScalarIsoline>
#include <dtkVisualization/dtkVisualizationVTKReader>
......@@ -150,11 +151,19 @@ void dtkVisualizationViewer::importDataSet(const QString& path)
}
vtkDataSet *dataset = dtkVisualizationVTKReader(path);
dtkVisualizationDecoratorScalarColorMap* decorator = new dtkVisualizationDecoratorScalarColorMap;
decorator->setCanvas(view_3d);
QVariant data = dtk::variantFromValue(dataset);
decorator->setData(data);
decorator->render();
dtkVisualizationDecoratorScalarColorMap *decorator_scalar_color_map = new dtkVisualizationDecoratorScalarColorMap;
decorator_scalar_color_map->setCanvas(view_3d);
decorator_scalar_color_map->setData(data);
dtkVisualizationDecoratorScalarIsoline *decorator_scalar_isoline = new dtkVisualizationDecoratorScalarIsoline;
decorator_scalar_isoline->setCanvas(view_3d);
decorator_scalar_isoline->setData(data);
(*decorator_scalar_color_map) << decorator_scalar_isoline;
decorator_scalar_color_map->render();
}
void dtkVisualizationViewer::setRopeSource(QWidget *source)
......
......@@ -36,7 +36,7 @@ protected:
void draw(void) override;
public:
void setData(const QVariant&) override;
void setData(const QVariant&) override;
void setCanvas(dtkVisualizationCanvas *) override;
public:
......
......@@ -13,6 +13,34 @@
// Code:
#include "dtkVisualizationDecoratorScalarIsoline.h"
#include "dtkVisualizationCanvas.h"
#include "dtkVisualizationView2D.h"
#include <dtkVisualizationWidgets/dtkVisualizationWidgetsClutEditor>
#include <dtkWidgets/dtkWidgetsOverlayPane>
#include <dtkWidgets/dtkWidgetsOverlayPaneItem>
#include <dtkLog>
#include <QColor>
#include <vtkActor.h>
#include <vtkColorTransferFunction.h>
#include <vtkContourFilter.h>
#include <vtkLookupTable.h>
#include <vtkCellData.h>
#include <vtkDataSet.h>
#include <vtkPolyDataMapper.h>
#include <vtkLookupTable.h>
#include <vtkPiecewiseFunction.h>
#include <vtkPointData.h>
#include <vtkProperty.h>
#include <vtkRendererCollection.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkScalarBarActor.h>
#include <vtkSmartPointer.h>
// ///////////////////////////////////////////////////////////////////
// dtkVisualizationDecoratorScalarIsolinePrivate declaration
......@@ -21,36 +49,359 @@
class dtkVisualizationDecoratorScalarIsolinePrivate
{
public:
enum Support {
Point,
Cell
};
public:
QStringList eligible_field_names;
QString current_field_name;
public:
vtkDataSet *dataset = nullptr;
public:
vtkSmartPointer<vtkActor> actor;
vtkSmartPointer<vtkPolyDataMapper> mapper;
vtkSmartPointer<vtkPiecewiseFunction> opacity;
vtkSmartPointer<vtkScalarBarActor> scalar_bar;
public:
vtkSmartPointer<vtkContourFilter> isolines;
QHash<QString, QPair<double, double>> isolines_ranges;
// int scalar_iso_count;
public:
QHash<QString, vtkSmartPointer<vtkColorTransferFunction>> color_transfer_functions;
QHash<QString, vtkSmartPointer<vtkPiecewiseFunction>> opacity_functions;
QHash<QString, QPair<double, double>> ranges;
QHash<QString, Support> supports;
};
// ///////////////////////////////////////////////////////////////////
// dtkVisualizationDecoratorScalarIsoline implementation
// ///////////////////////////////////////////////////////////////////
dtkVisualizationDecoratorScalarIsoline::dtkVisualizationDecoratorScalarIsoline(void) : d(new dtkVisualizationDecoratorScalarIsolinePrivate)
dtkVisualizationDecoratorScalarIsoline::dtkVisualizationDecoratorScalarIsoline(void): d(new dtkVisualizationDecoratorScalarIsolinePrivate())
{
d->isolines = vtkSmartPointer<vtkContourFilter>::New();
d->mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
d->mapper->SetInputConnection(d->isolines->GetOutputPort());
d->mapper->SetColorModeToMapScalars();
d->mapper->SetScalarVisibility(true);
d->actor = vtkSmartPointer<vtkActor>::New();
d->actor->SetMapper(d->mapper);
d->actor->SetVisibility(true);
}
dtkVisualizationDecoratorScalarIsoline::~dtkVisualizationDecoratorScalarIsoline(void)
{
d->dataset = nullptr;
delete d;
d = nullptr;
}
void dtkVisualizationDecoratorScalarIsoline::setData(const QVariant& v)
void dtkVisualizationDecoratorScalarIsoline::draw(void)
{
dtkVisualizationDecorator::setData(v);
if (!d->dataset || d->current_field_name.isEmpty()) {
dtkWarn() << Q_FUNC_INFO << "Set dataset and field name before updating actor.";
return;
}
if(!this->canvas()) {
dtkWarn() << Q_FUNC_INFO << "No canvas was set, call setCanvas to call draw on a canvas.";
return;
}
Q_ASSERT(this->canvas()->renderer());
if (!d->scalar_bar) {
d->scalar_bar = vtkSmartPointer<vtkScalarBarActor>::New();
d->scalar_bar->SetWidth(0.08);
d->scalar_bar->SetHeight(0.6);
d->scalar_bar->SetVisibility(true);
this->canvas()->renderer()->AddActor2D(d->scalar_bar);
}
d->scalar_bar->SetLookupTable(d->color_transfer_functions[d->current_field_name]);
d->scalar_bar->SetTitle(qPrintable(d->current_field_name));
d->scalar_bar->Modified();
d->actor->Modified();
if (this->canvas()->interactor()) {
this->canvas()->interactor()->Render();
}
}
void dtkVisualizationDecoratorScalarIsoline::setData(const QVariant& data)
{
vtkDataSet *dataset = data.value<vtkDataSet *>();
if (!dataset) {
dtkWarn() << Q_FUNC_INFO << "vtkDataSet is expected. Input data is not stored.";
return;
}
dtkVisualizationDecorator::setData(data);
d->dataset = dataset;
d->current_field_name.clear();
d->eligible_field_names.clear();
d->color_transfer_functions.clear();
d->opacity_functions.clear();
d->ranges.clear();
d->supports.clear();
vtkIdType number_of_point_arrays = d->dataset->GetPointData()->GetNumberOfArrays();
for (vtkIdType i = 0; i < number_of_point_arrays; ++i) {
if (d->dataset->GetPointData()->GetArray(i)->GetNumberOfComponents() == 1) {
QString field_name = QString::fromUtf8(d->dataset->GetPointData()->GetArrayName(i));
d->eligible_field_names << field_name;
d->supports[field_name] = dtkVisualizationDecoratorScalarIsolinePrivate::Support::Point;
d->dataset->GetPointData()->SetActiveScalars(qPrintable(field_name));
double *range = static_cast<vtkDataArray *>(d->dataset->GetPointData()->GetScalars())->GetRange();
d->ranges[field_name] = qMakePair(range[0], range[1]);
vtkSmartPointer<vtkColorTransferFunction> color_function = vtkSmartPointer<vtkColorTransferFunction>::New();
QColor black = QColor(0., 0., 0., 255);
double node = 0. * range[1] + (1. - 0.) * range[0];
color_function->AddRGBPoint(node, black.red(), black.green(), black.blue());
QColor white = QColor(1., 1., 1., 255);
node = 1. * range[1] + (1. - 1.) * range[0];
color_function->AddRGBPoint(node, white.red(), white.green(), white.blue());
color_function->Build();
d->color_transfer_functions[field_name] = color_function;
vtkSmartPointer<vtkPiecewiseFunction> opacity_function = vtkSmartPointer<vtkPiecewiseFunction>::New();
opacity_function->RemoveAllPoints();
opacity_function->AddPoint(0, 0.);
opacity_function->AddPoint(255, 1.);
d->opacity_functions[field_name] = opacity_function;
}
}
vtkIdType number_of_cell_arrays = d->dataset->GetCellData()->GetNumberOfArrays();
for (vtkIdType i = 0; i < number_of_cell_arrays; ++i) {
if (d->dataset->GetCellData()->GetArray(i)->GetNumberOfComponents() == 1) {
QString field_name = QString::fromUtf8(d->dataset->GetCellData()->GetArrayName(i));
d->eligible_field_names << field_name;
d->supports[field_name] = dtkVisualizationDecoratorScalarIsolinePrivate::Support::Cell;
d->dataset->GetCellData()->SetActiveScalars(qPrintable(field_name));
double *range = static_cast<vtkDataArray *>(d->dataset->GetCellData()->GetScalars())->GetRange();
d->ranges[field_name] = qMakePair(range[0], range[1]);
vtkSmartPointer<vtkColorTransferFunction> color_function = vtkSmartPointer<vtkColorTransferFunction>::New();
QColor black = QColor(0., 0., 0., 255);
color_function->AddRGBPoint(range[0], black.red(), black.green(), black.blue());
QColor white = QColor(1., 1., 1., 255);
color_function->AddRGBPoint(range[1], white.red(), white.green(), white.blue());
color_function->Build();
d->color_transfer_functions[field_name] = color_function;
vtkSmartPointer<vtkPiecewiseFunction> opacity_function = vtkSmartPointer<vtkPiecewiseFunction>::New();
opacity_function->RemoveAllPoints();
opacity_function->AddPoint(0, 0.);
opacity_function->AddPoint(255, 1.);
d->opacity_functions[field_name] = opacity_function;
}
}
if (d->eligible_field_names.size() > 0) {
d->eligible_field_names.sort();
this->setCurrentFieldName(d->eligible_field_names.first());
}
d->isolines->SetInputData(d->dataset);
// d->isolines->GenerateValues(d->scalar_iso_count, d->scalar_iso_range[0], d->scalar_iso_range[1]);
d->isolines->GenerateValues(10, 0, 100);
d->isolines->Update();
d->mapper->Modified();
}
void dtkVisualizationDecoratorScalarIsoline::setCanvas(dtkVisualizationCanvas *canvas)
{
dtkVisualizationDecorator::setCanvas(canvas);
dtkVisualizationView2D *old = dynamic_cast<dtkVisualizationView2D *>(this->canvas());
if (old) {
old->renderer()->RemoveActor(d->actor);
}
dtkVisualizationView2D *view = dynamic_cast<dtkVisualizationView2D *>(canvas);
if (!view) {
qWarning() << Q_FUNC_INFO << "View 2D or view 3D expected as canvas. Canvas is reset to nullptr.";
dtkVisualizationDecorator::setCanvas(nullptr);
return;
}
dtkVisualizationDecorator::setCanvas(view);
view->renderer()->AddActor(d->actor);
dtkWidgetsOverlayPane *canvas_pane = canvas->overlay();
canvas_pane->setBound(500);
dtkVisualizationWidgetsClutEditor *clut_editor = new dtkVisualizationWidgetsClutEditor;
dtkWidgetsOverlayPaneItem *pane_item = new dtkWidgetsOverlayPaneItem;
pane_item->setTitle("Scalar Color Map");
pane_item->addWidget(clut_editor);
canvas_pane->addWidget(pane_item);
connect(this, &dtkVisualizationDecoratorScalarIsoline::currentRangeChanged, [=] (double min, double max) {
clut_editor->blockSignals(true);
clut_editor->setRange(min, max);
clut_editor->blockSignals(false);
});
connect(this, &dtkVisualizationDecoratorScalarIsoline::currentColorTransferFunctionChanged, [=] (vtkColorTransferFunction *color_transfer_function) {
clut_editor->blockSignals(true);
clut_editor->setColorTransferFunction(color_transfer_function);
clut_editor->blockSignals(false);
});
connect(clut_editor, &dtkVisualizationWidgetsClutEditor::updated, [=] () {
this->blockSignals(true);
this->setCurrentColorTransferFunction(reinterpret_cast<vtkColorTransferFunction *>(clut_editor->colorTransferFunction()));
this->blockSignals(false);
});
}
void dtkVisualizationDecoratorScalarIsoline::draw(void)
QStringList dtkVisualizationDecoratorScalarIsoline::eligibleFieldNames(void)
{
return d->eligible_field_names;
}
QString dtkVisualizationDecoratorScalarIsoline::currentFieldName(void)
{
return d->current_field_name;
}
QPair<double, double> dtkVisualizationDecoratorScalarIsoline::currentRange(void)
{
return d->ranges[d->current_field_name];
}
vtkSmartPointer<vtkColorTransferFunction> dtkVisualizationDecoratorScalarIsoline::currentColorTransferFunction(void)
{
return d->color_transfer_functions[d->current_field_name];
}
vtkSmartPointer<vtkPiecewiseFunction> dtkVisualizationDecoratorScalarIsoline::currentOpacityTransferFunction(void)
{
return d->opacity_functions[d->current_field_name];
}
bool dtkVisualizationDecoratorScalarIsoline::setCurrentFieldName(const QString& scalar_field_name)
{
if (scalar_field_name.isEmpty()) {
dtkWarn() << Q_FUNC_INFO << "Scalar field name is empty, nothing is done.";
return false;
}
if (!d->dataset) {
dtkWarn() << Q_FUNC_INFO << "Before calling setScalarFieldName, setDataSet must be called.";
return false;
}
if(!d->eligible_field_names.contains(scalar_field_name)) {
dtkWarn() << Q_FUNC_INFO << "The field name :" << scalar_field_name << "that was specified doesn't match any of the eligible scalar field names";
return false;
}
d->current_field_name = scalar_field_name;
vtkSmartPointer<vtkColorTransferFunction> color_function = d->color_transfer_functions[d->current_field_name];
if (d->supports[d->current_field_name] == dtkVisualizationDecoratorScalarIsolinePrivate::Support::Point) {
d->dataset->GetPointData()->SetActiveScalars(qPrintable(d->current_field_name));
} else if (d->supports[d->current_field_name] == dtkVisualizationDecoratorScalarIsolinePrivate::Support::Cell) {
d->dataset->GetCellData()->SetActiveScalars(qPrintable(d->current_field_name));
}
const QPair<double, double>& range = d->ranges[d->current_field_name];
d->mapper->SetLookupTable(d->color_transfer_functions[d->current_field_name]);
d->mapper->SelectColorArray(qPrintable(d->current_field_name));
d->mapper->SetScalarRange(range.first, range.second);
d->mapper->SetLookupTable(color_function);
d->mapper->Modified();
d->actor->Modified();
if(d->scalar_bar) {
d->scalar_bar->SetLookupTable(d->color_transfer_functions[d->current_field_name]);
d->scalar_bar->Modified();
}
emit this->currentFieldNameChanged(d->current_field_name);
emit this->currentColorTransferFunctionChanged(color_function);
emit this->currentRangeChanged(range.first, range.second);
return true;
}
void dtkVisualizationDecoratorScalarIsoline::setCurrentColorTransferFunction(vtkSmartPointer<vtkColorTransferFunction> color_function)
{
if (d->current_field_name.isEmpty()) {
return;
}
d->color_transfer_functions[d->current_field_name] = color_function;
d->mapper->SetLookupTable(color_function);
d->mapper->Modified();
d->actor->Modified();
d->scalar_bar->SetLookupTable(color_function);
d->scalar_bar->Modified();
if (this->canvas() && this->canvas()->interactor()) {
this->canvas()->interactor()->Render();
}
emit this->currentColorTransferFunctionChanged(color_function);
}
void dtkVisualizationDecoratorScalarIsoline::setCurrentOpacityTransferFunction(vtkSmartPointer<vtkPiecewiseFunction> opacity_function)
{
if (d->current_field_name.isEmpty()) {
return;
}
d->opacity_functions[d->current_field_name] = opacity_function;
//Need to be implemented, probably requires modifying the lut...
if (this->canvas() && this->canvas()->interactor()) {
this->canvas()->interactor()->Render();
}
emit this->currentOpacityFunctionChanged(d->opacity_functions[d->current_field_name]);
}
void dtkVisualizationDecoratorScalarIsoline::setCurrentRange(double min, double max)
{
if (d->current_field_name.isEmpty()) {
return;
}
d->ranges[d->current_field_name] = qMakePair(min, max);
d->mapper->SetScalarRange(min, max);
d->mapper->Modified();
d->actor->Modified();
if (this->canvas() && this->canvas()->interactor()) {
this->canvas()->interactor()->Render();
}
emit this->currentRangeChanged(min, max);
}
//
......
......@@ -16,25 +16,51 @@
#include <dtkVisualizationExport>
#include <QtCore>
#include "dtkVisualizationDecorator.h"
#include <vtkSmartPointer.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
// ///////////////////////////////////////////////////////////////////
// dtkVisualizationDecoratorScalarIsoline declaration
// ///////////////////////////////////////////////////////////////////
class DTKVISUALIZATION_EXPORT dtkVisualizationDecoratorScalarIsoline : public dtkVisualizationDecorator
{
Q_OBJECT
public:
dtkVisualizationDecoratorScalarIsoline(void);
~dtkVisualizationDecoratorScalarIsoline(void);
public:
void setData(const QVariant&) override;
void setData(const QVariant&) override;
void setCanvas(dtkVisualizationCanvas *) override;
protected:
void draw(void) override;
public:
QStringList eligibleFieldNames(void);
QString currentFieldName(void);
QPair<double, double> currentRange(void);
vtkSmartPointer<vtkColorTransferFunction> currentColorTransferFunction(void);
vtkSmartPointer<vtkPiecewiseFunction> currentOpacityTransferFunction(void);
public:
bool setCurrentFieldName(const QString&);
void setCurrentColorTransferFunction(vtkSmartPointer<vtkColorTransferFunction>);
void setCurrentOpacityTransferFunction(vtkSmartPointer<vtkPiecewiseFunction>);
void setCurrentRange(double min, double max);
signals:
void currentFieldNameChanged(const QString&);
void currentColorTransferFunctionChanged(vtkColorTransferFunction *);
void currentOpacityFunctionChanged(vtkPiecewiseFunction *);
void currentRangeChanged(double, double);
protected:
class dtkVisualizationDecoratorScalarIsolinePrivate *d = nullptr;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment