From 0e4383a997de8229a3d051da0c216fb46c3885bc Mon Sep 17 00:00:00 2001 From: Thibaud Kloczko Date: Tue, 17 Dec 2019 23:52:02 +0100 Subject: [PATCH 1/2] Add decorator for curved glyphs. To be merged with streamtracer decorator. --- .../dtkVisualizationViewer.cpp | 2 + src/dtkVisualization/CMakeLists.txt | 3 + src/dtkVisualization/dtkVisualization | 1 + ...tkVisualizationDecoratorVectorCurvedGlyphs | 1 + ...sualizationDecoratorVectorCurvedGlyphs.cpp | 509 ++++++++++++++++++ ...VisualizationDecoratorVectorCurvedGlyphs.h | 40 ++ 6 files changed, 556 insertions(+) create mode 100644 src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs create mode 100644 src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.cpp create mode 100644 src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.h diff --git a/app/dtkVisualizationViewer/dtkVisualizationViewer.cpp b/app/dtkVisualizationViewer/dtkVisualizationViewer.cpp index 77c2e6a..47a6636 100644 --- a/app/dtkVisualizationViewer/dtkVisualizationViewer.cpp +++ b/app/dtkVisualizationViewer/dtkVisualizationViewer.cpp @@ -306,6 +306,7 @@ void dtkVisualizationViewer::importDataSet(const QString& path) dtkVisualizationDecoratorSlices *decorator_slices = new dtkVisualizationDecoratorSlices; dtkVisualizationDecoratorSnapshot *decorator_snapshot = new dtkVisualizationDecoratorSnapshot; dtkVisualizationDecoratorVectorGlyphs *decorator_vector_glyphs = new dtkVisualizationDecoratorVectorGlyphs; + dtkVisualizationDecoratorVectorCurvedGlyphs *decorator_vector_curved_glyphs = new dtkVisualizationDecoratorVectorCurvedGlyphs; dtkVisualizationDecoratorVectorStreamlines *decorator_vector_streamlines = new dtkVisualizationDecoratorVectorStreamlines; dtkVisualizationDecoratorVectorStreamTracer *decorator_vector_streamtracer = new dtkVisualizationDecoratorVectorStreamTracer; dtkVisualizationDecoratorVolume *decorator_volume = new dtkVisualizationDecoratorVolume; @@ -317,6 +318,7 @@ void dtkVisualizationViewer::importDataSet(const QString& path) << decorator_scalar_isolines << decorator_scalar_glyphs << decorator_vector_glyphs + << decorator_vector_curved_glyphs << decorator_vector_streamlines << decorator_vector_streamtracer << decorator_volume diff --git a/src/dtkVisualization/CMakeLists.txt b/src/dtkVisualization/CMakeLists.txt index 97df36e..84263ed 100644 --- a/src/dtkVisualization/CMakeLists.txt +++ b/src/dtkVisualization/CMakeLists.txt @@ -51,6 +51,8 @@ set(${PROJECT_NAME}_HEADERS dtkVisualizationDecoratorSlices.h dtkVisualizationDecoratorSnapshot dtkVisualizationDecoratorSnapshot.h + dtkVisualizationDecoratorVectorCurvedGlyphs + dtkVisualizationDecoratorVectorCurvedGlyphs.h dtkVisualizationDecoratorVectorGlyphs dtkVisualizationDecoratorVectorGlyphs.h dtkVisualizationDecoratorVectorStreamlines @@ -106,6 +108,7 @@ set(${PROJECT_NAME}_SOURCES dtkVisualizationDecoratorScalarIsolines.cpp dtkVisualizationDecoratorSlices.cpp dtkVisualizationDecoratorSnapshot.cpp + dtkVisualizationDecoratorVectorCurvedGlyphs.cpp dtkVisualizationDecoratorVectorGlyphs.cpp dtkVisualizationDecoratorVectorStreamlines.cpp dtkVisualizationDecoratorVectorStreamTracer.cpp diff --git a/src/dtkVisualization/dtkVisualization b/src/dtkVisualization/dtkVisualization index 538ff1d..84c60c0 100644 --- a/src/dtkVisualization/dtkVisualization +++ b/src/dtkVisualization/dtkVisualization @@ -14,6 +14,7 @@ #include "dtkVisualizationDecoratorScalarGlyphs.h" #include "dtkVisualizationDecoratorSlices.h" #include "dtkVisualizationDecoratorSnapshot.h" +#include "dtkVisualizationDecoratorVectorCurvedGlyphs.h" #include "dtkVisualizationDecoratorVectorGlyphs.h" #include "dtkVisualizationDecoratorVectorStreamlines.h" #include "dtkVisualizationDecoratorVectorStreamTracer.h" diff --git a/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs b/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs new file mode 100644 index 0000000..a88659e --- /dev/null +++ b/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs @@ -0,0 +1 @@ +#include "dtkVisualizationDecoratorVectorCurvedGlyphs.h" diff --git a/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.cpp b/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.cpp new file mode 100644 index 0000000..c0c245f --- /dev/null +++ b/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.cpp @@ -0,0 +1,509 @@ +// dtkVisualizationDecoratorVectorCurvedGlyphs.cpp +// + +#include "dtkVisualizationDecoratorVectorCurvedGlyphs.h" + +#include "dtkVisualizationDecoratorWithClut_p.h" +#include "dtkVisualizationMetaType.h" +#include "dtkVisualizationView2D.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ///////////////////////////////////////////////////////////////// +// dtkCurvedGlyphsObserver +// ///////////////////////////////////////////////////////////////// + +class dtkVisualizationDecoratorCurvedGlyphsSphereObserver : public vtkCommand +{ +private: + dtkVisualizationDecoratorCurvedGlyphsSphereObserver(void) { + }; + +public: + static dtkVisualizationDecoratorCurvedGlyphsSphereObserver *New(void) + { + return new dtkVisualizationDecoratorCurvedGlyphsSphereObserver; + }; + + void Execute(vtkObject *caller, unsigned long event, void *) override + { + if (event == vtkCommand::InteractionEvent) { + source_sphere->GetPolyData(source_data); + stream_tracer->SetSourceData(source_data); + stream_tracer->Modified(); + } + }; + +public: + vtkSmartPointer source_data; + vtkSmartPointer source_sphere; + vtkSmartPointer stream_tracer; +}; + +// /////////////////////////////////////////////////////////////////// +// dtkVisualizationDecoratorVectorCurvedGlyphsPrivate declaration +// /////////////////////////////////////////////////////////////////// + +class dtkVisualizationDecoratorVectorCurvedGlyphsPrivate +{ +public: + vtkSmartPointer source_sphere_observer; + vtkSmartPointer source_sphere_widget; + vtkSmartPointer source_data; + vtkSmartPointer source_sphere; + +public: + vtkSmartPointer streamtracer; + vtkSmartPointer contours; + vtkSmartPointer source_arrows; + vtkSmartPointer glyphs; + vtkSmartPointer arrows_mapper; + vtkSmartPointer arrows_actor; + vtkSmartPointer curves_stream; + vtkSmartPointer curves_tube; + vtkSmartPointer curves_clip; + vtkSmartPointer curves_mapper; + vtkSmartPointer curves_actor; + +public: + QCheckBox *show_actor_cb = nullptr; + QCheckBox *show_source_actor_cb = nullptr; + +public: + QComboBox *cb_integrator_type = nullptr; + QSpinBox *sp_integrator_max_steps = nullptr; + QSpinBox *sp_resolution = nullptr; + QDoubleSpinBox *sp_integrator_max_lengths = nullptr; + +public: + QDoubleSpinBox *sp_radius = nullptr; +}; + +// /////////////////////////////////////////////////////////////////// +// dtkVisualizationDecoratorVectorCurvedGlyphs implementation +// /////////////////////////////////////////////////////////////////// + +dtkVisualizationDecoratorVectorCurvedGlyphs::dtkVisualizationDecoratorVectorCurvedGlyphs(void): dtkVisualizationDecoratorWithClut(), d(new dtkVisualizationDecoratorVectorCurvedGlyphsPrivate()) +{ + + d->source_data = vtkSmartPointer ::New(); + + d->source_sphere = vtkSmartPointer::New(); + d->source_sphere->SetPhiResolution(7); + d->source_sphere->SetThetaResolution(7); + d->source_sphere->SetRadius(1.0); + d->source_sphere->GetPolyData(d->source_data); + d->source_sphere->SetRepresentationToWireframe(); + d->source_sphere->RadialLineOff(); + + d->source_sphere_widget = vtkSmartPointer::New(); + d->source_sphere_widget->SetEnabled(false); + d->source_sphere_widget->SetRepresentation(d->source_sphere); + + d->streamtracer = vtkSmartPointer::New(); + d->streamtracer->SetSourceData(d->source_data); + + d->streamtracer->SetIntegrationDirectionToBoth(); + d->streamtracer->SetIntegratorTypeToRungeKutta45(); + d->streamtracer->SetIntegrationStepUnit(vtkStreamTracer::Units::LENGTH_UNIT); + d->streamtracer->SetInitialIntegrationStep(0.2); + d->streamtracer->SetMinimumIntegrationStep(0.01); + d->streamtracer->SetMaximumIntegrationStep(0.5); + + d->streamtracer->SetMaximumNumberOfSteps(2000); + d->streamtracer->SetMaximumPropagation(20); // To be set as the maximum size of the dataset + d->streamtracer->SetTerminalSpeed(1.e-12); + d->streamtracer->SetMaximumError(1.e-6); + d->streamtracer->SetComputeVorticity(false); + + d->contours = vtkSmartPointer::New(); + d->contours->SetInputConnection(d->streamtracer->GetOutputPort()); + d->contours->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "IntegrationTime"); + d->contours->ComputeNormalsOff(); + d->contours->ComputeGradientsOff(); + d->contours->ComputeScalarsOn(); + + d->source_arrows = vtkSmartPointer::New(); + d->source_arrows->SetInputConnection(d->contours->GetOutputPort()); + d->source_arrows->SetTipLength(1); + d->source_arrows->SetTipRadius(0.2); + + d->glyphs = vtkSmartPointer::New(); + d->glyphs->SetSourceConnection(d->source_arrows->GetOutputPort()); + d->glyphs->SetInputConnection(d->contours->GetOutputPort()); + d->glyphs->SetVectorModeToUseVector(); + d->glyphs->SetScaleModeToDataScalingOff(); + d->glyphs->OrientOn(); + d->glyphs->SetScaleFactor(1.); + + d->arrows_mapper = vtkSmartPointer::New(); + d->arrows_mapper->SetInputConnection(d->glyphs->GetOutputPort()); + d->arrows_mapper->SetScalarModeToUsePointFieldData(); + + d->arrows_actor = vtkSmartPointer::New(); + d->arrows_actor->SetMapper(d->arrows_mapper); + + d->curves_stream = vtkSmartPointer::New(); + d->curves_stream->SetSourceConnection(d->contours->GetOutputPort()); + + d->curves_stream->SetIntegrationDirectionToBackward(); + d->curves_stream->SetIntegratorTypeToRungeKutta45(); + d->curves_stream->SetIntegrationStepUnit(vtkStreamTracer::Units::LENGTH_UNIT); + d->curves_stream->SetInitialIntegrationStep(0.2); + d->curves_stream->SetMinimumIntegrationStep(0.01); + d->curves_stream->SetMaximumIntegrationStep(0.5); + + d->curves_stream->SetMaximumNumberOfSteps(200); + d->curves_stream->SetMaximumPropagation(2); // To be set as the maximum size of the dataset + d->curves_stream->SetTerminalSpeed(1.e-12); + d->curves_stream->SetMaximumError(1.e-6); + d->curves_stream->SetComputeVorticity(false); + + d->curves_tube = vtkSmartPointer::New(); + d->curves_tube->SetInputConnection(d->curves_stream->GetOutputPort()); + d->curves_tube->SetNumberOfSides(8); + d->curves_tube->SetRadius(.02); + d->curves_tube->SetVaryRadius(0); + + d->curves_mapper = vtkSmartPointer::New(); + d->curves_mapper->SetInputConnection(d->curves_tube->GetOutputPort()); + d->curves_mapper->SetScalarModeToUsePointFieldData(); + + d->curves_actor = vtkSmartPointer::New(); + d->curves_actor->SetMapper(d->curves_mapper); + + d->source_sphere_observer = vtkSmartPointer::New(); + d->source_sphere_observer->source_data = d->source_data; + d->source_sphere_observer->source_sphere = d->source_sphere; + d->source_sphere_observer->stream_tracer = d->streamtracer; + + d->source_sphere_widget->AddObserver(vtkCommand::InteractionEvent, d->source_sphere_observer); + + ////////// + // Inspectors creation and setup + + d->show_actor_cb = new QCheckBox; + d->show_source_actor_cb = new QCheckBox; + + d->cb_integrator_type = new QComboBox; + d->cb_integrator_type->addItem(QStringLiteral("RK2")); + d->cb_integrator_type->addItem(QStringLiteral("RK4")); + d->cb_integrator_type->addItem(QStringLiteral("RK45")); + d->cb_integrator_type->setCurrentIndex(0); + + d->sp_resolution = new QSpinBox; + d->sp_resolution->setMaximum(1000); + d->sp_resolution->setValue(50); + d->sp_resolution->setKeyboardTracking(false); + + d->sp_integrator_max_steps = new QSpinBox; + d->sp_integrator_max_steps->setMaximum(999999); + d->sp_integrator_max_steps->setValue(2000); + d->sp_integrator_max_steps->setKeyboardTracking(false); + + d->sp_integrator_max_lengths = new QDoubleSpinBox; + d->sp_integrator_max_lengths->setMaximum(9999999); + d->sp_integrator_max_lengths->setValue(20); + d->sp_integrator_max_lengths->setKeyboardTracking(false); + + d->sp_radius = new QDoubleSpinBox; + + d->show_source_actor_cb->setChecked(true); + d->sp_radius->setValue(1.0); + d->sp_radius->setSingleStep(0.1); + d->sp_radius->setDecimals(4); + d->sp_radius->setKeyboardTracking(false); + + ////////// + // Inspectors connections + + connect(d->show_actor_cb, &QCheckBox::stateChanged, [=] (int state) + { + this->saveSettings("visibility",state == Qt::Checked); + this->setVisibility(state == Qt::Checked); + this->draw(); + }); + + connect(d->show_source_actor_cb, &QCheckBox::stateChanged, [=] (int state) + { + d->source_sphere_widget->SetEnabled(state == Qt::Checked); + this->draw(); + }); + + connect(d->cb_integrator_type, QOverload::of(&QComboBox::currentIndexChanged), [=] (int id) + { + d->streamtracer->SetIntegratorType(id); + this->draw(); + }); + + connect(d->sp_resolution, QOverload::of(&QSpinBox::valueChanged), [=] (int val) + { + int sqrt_val = std::round(std::sqrt(val)); + d->source_sphere->SetPhiResolution(sqrt_val); + d->source_sphere->SetThetaResolution(sqrt_val); + this->touch(); + this->draw(); + }); + + connect(d->sp_integrator_max_steps, QOverload::of(&QSpinBox::valueChanged), [=] (int val) + { + d->streamtracer->SetMaximumNumberOfSteps(val); + this->draw(); + }); + + connect(d->sp_integrator_max_lengths, QOverload::of(&QDoubleSpinBox::valueChanged), [=] (double val) + { + d->streamtracer->SetMaximumPropagation(val); + this->draw(); + }); + + connect(d->sp_radius, QOverload::of(&QDoubleSpinBox::valueChanged), [=] (double val) + { + d->curves_tube->SetRadius(val); + this->draw(); + }); + + this->setObjectName("Vector Curved Glyphs"); + + d->show_actor_cb->setObjectName("Display"); + d->show_source_actor_cb->setObjectName("Display Source"); + d->cb_integrator_type->setObjectName("Integrator Type"); + d->sp_integrator_max_steps->setObjectName("Maximum Steps"); + d->sp_integrator_max_lengths->setObjectName("Maximum Streamline Length"); + d->sp_radius->setObjectName("Tube Radius"); + d->sp_resolution->setObjectName("Resolution"); + + d_func()->inspectors << d->show_actor_cb << d->show_source_actor_cb + << d_func()->field_components + << d->cb_integrator_type << d->sp_integrator_max_steps + << d->sp_integrator_max_lengths << d->sp_radius << d->sp_resolution; + +} + +dtkVisualizationDecoratorVectorCurvedGlyphs::~dtkVisualizationDecoratorVectorCurvedGlyphs(void) +{ + dtkVisualizationDecoratorVectorCurvedGlyphs::unsetCanvas(); + + delete d; + + d = nullptr; +} + +void dtkVisualizationDecoratorVectorCurvedGlyphs::restoreSettings(void) +{ + if (this->objectName().isEmpty()) { + return; + } + dtkVisualizationDecoratorWithClut::restoreSettings(); + d->arrows_actor->SetVisibility(d_func()->default_visibility); + d->curves_actor->SetVisibility(d_func()->default_visibility); + d->show_actor_cb->blockSignals(true); + d->show_actor_cb->setChecked(d_func()->default_visibility); + d->show_actor_cb->blockSignals(false); +} + +void dtkVisualizationDecoratorVectorCurvedGlyphs::setData(const QVariant& data) +{ + vtkDataSet *dataset = data.value(); + if (!dataset) { + dtkWarn() << Q_FUNC_INFO << "vtkDataSet is expected. Input data is not stored."; + return; + } + + d_func()->clear(); + d_func()->retrieveVectorPoints(dataset); + d_func()->retrieveVectorCells(dataset); + + if (!this->isDecorating()) { + dtkWarn() << Q_FUNC_INFO << "vtkDataSet has no field to decorate. Nothing is done."; + d_func()->clear(); + return; + } + + d_func()->dataset = dataset; + this->restoreSettings(); + + double bounds[6]; + double center[3]; + dataset->GetBounds(bounds); + dataset->GetCenter(center); + double pos1[3]; pos1[0] = bounds[0]; pos1[1] = bounds[1]; pos1[2] = bounds[2]; + double pos2[3]; pos2[0] = bounds[3]; pos2[1] = bounds[4]; pos2[2] = bounds[5]; + vtkBoundingBox box; + box.SetBounds(bounds); + d->sp_integrator_max_lengths->setValue(box.GetDiagonalLength()); + d->sp_radius->setValue(box.GetDiagonalLength()/500.0); + + d->source_sphere->SetCenter(center); + d->source_sphere->SetRadius(box.GetDiagonalLength()/20.0); + d->source_sphere->Modified(); + + d->streamtracer->SetInputData(dataset); + d->streamtracer->Modified(); + + d->curves_stream->SetInputData(dataset); + d->curves_stream->Modified(); + + d_func()->sortEligibleFields(); + this->setCurrentFieldName(d_func()->current_field_name); + + if (this->canvas()) { + this->canvas()->renderer()->AddActor(d->arrows_actor); + this->canvas()->renderer()->AddActor(d->curves_actor); + d->source_sphere_widget->SetInteractor(this->canvas()->renderer()->GetRenderWindow()->GetInteractor()); + d->source_sphere_widget->On(); + } + + d_func()->enableScalarBar(); +} + +void dtkVisualizationDecoratorVectorCurvedGlyphs::setCanvas(dtkVisualizationCanvas *canvas) +{ + this->unsetCanvas(); + + d_func()->view = dynamic_cast(canvas); + if (!d_func()->view) { + qWarning() << Q_FUNC_INFO << "View 2D or view 3D expected as canvas. Canvas is reset to nullptr."; + return; + } + + if (this->isDecorating()) { + d_func()->view->renderer()->AddActor(d->arrows_actor); + d_func()->view->renderer()->AddActor(d->curves_actor); + d->source_sphere_widget->SetInteractor(this->canvas()->renderer()->GetRenderWindow()->GetInteractor()); + if (!d_func()->default_visibility) { + d_func()->default_visibility = true; + } else { + d->source_sphere_widget->On(); + } + } + + d_func()->enableScalarBar(); +} + +void dtkVisualizationDecoratorVectorCurvedGlyphs::unsetCanvas(void) +{ + if (d_func()->view) { + d->source_sphere_widget->Off(); + d->source_sphere_widget->SetInteractor(nullptr); + d_func()->view->renderer()->RemoveActor(d->arrows_actor); + d_func()->view->renderer()->RemoveActor(d->curves_actor); + } + + d_func()->disableScalarBar(); + + d_func()->view = nullptr; +} + +void dtkVisualizationDecoratorVectorCurvedGlyphs::touch() +{ + dtkVisualizationDecoratorWithClut::touch(); + + d->source_sphere->GetPolyData(d->source_data); + d->streamtracer->SetSourceData(d->source_data); + d->streamtracer->Modified(); + + auto&& range = d_func()->ranges[d_func()->current_field_name]; + + d->contours->GenerateValues(23, range[0], range[1]); + d->contours->Modified(); + d->curves_stream->Modified(); + +} + +void dtkVisualizationDecoratorVectorCurvedGlyphs::setVisibility(bool visible) +{ + dtkVisualizationDecoratorWithClut::setVisibility(visible); + d->arrows_actor->SetVisibility(visible); + d->curves_actor->SetVisibility(visible); + if (visible) { + d->source_sphere_widget->SetEnabled(d->show_source_actor_cb->isChecked()); + } else { + d->show_source_actor_cb->setChecked(false); + } +} + +bool dtkVisualizationDecoratorVectorCurvedGlyphs::setCurrentFieldName(const QString& field_name) +{ + if (field_name.isEmpty()) { + dtkWarn() << Q_FUNC_INFO << "Field name is empty, nothing is done."; + return false; + } + + if (!d_func()->dataset) { + dtkWarn() << Q_FUNC_INFO << "Before calling setCurrentFieldName, setDataSet must be called."; + return false; + } + + if(!d_func()->eligible_field_names.contains(field_name)) { + dtkWarn() << Q_FUNC_INFO << "The field name :" << field_name << "that was specified doesn't match any of the eligible scalar field names"; + return false; + } + + d_func()->current_field_name = field_name; + + using Support = dtkVisualizationDecoratorWithClut::Support; + int support = d_func()->supports[field_name]; + if(support == Support::Point) { + d->streamtracer->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, qPrintable(field_name)); + d->curves_stream->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, qPrintable(field_name)); + + } else if(support == Support::Cell) { + d->streamtracer->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, qPrintable(field_name)); + d->curves_stream->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, qPrintable(field_name)); + } + d->streamtracer->Modified(); + + return dtkVisualizationDecoratorWithClut::setCurrentFieldName(field_name); +} + +void dtkVisualizationDecoratorVectorCurvedGlyphs::setColorMap(const QMap& new_colormap) +{ + dtkVisualizationDecoratorWithClut::setColorMap(new_colormap); + + d->arrows_mapper->SetLookupTable(d_func()->color_function); + d->curves_mapper->SetLookupTable(d_func()->color_function); + if (d->glyphs->GetOutput()->GetPointData()->GetVectors()) { + d->arrows_mapper->SelectColorArray(d->glyphs->GetOutput()->GetPointData()->GetVectors()->GetName()); + } else { + d->arrows_mapper->SelectColorArray(qPrintable(d_func()->current_field_name)); + } + d->curves_mapper->SelectColorArray(qPrintable(d_func()->current_field_name)); + auto&& range = d_func()->ranges[d_func()->current_field_name]; + d->arrows_mapper->SetScalarRange(range[0], range[1]); + d->arrows_mapper->Modified(); + d->curves_mapper->SetScalarRange(range[0], range[1]); + d->curves_mapper->Modified(); +} + +// +// dtkVisualizationDecoratorVectorCurvedGlyphs.cpp ends here diff --git a/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.h b/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.h new file mode 100644 index 0000000..bd3669a --- /dev/null +++ b/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.h @@ -0,0 +1,40 @@ +// dtkVisualizationDecoratorVectorCurvedGlyphs.h +// + +#pragma once + +#include + +#include "dtkVisualizationDecoratorWithClut.h" + +class DTKVISUALIZATION_EXPORT dtkVisualizationDecoratorVectorCurvedGlyphs : public dtkVisualizationDecoratorWithClut +{ + Q_OBJECT + +public: + dtkVisualizationDecoratorVectorCurvedGlyphs(void); + ~dtkVisualizationDecoratorVectorCurvedGlyphs(void); + +public: + void setData(const QVariant&) override; + void setCanvas(dtkVisualizationCanvas *) override; + void unsetCanvas(void) override; + void touch(void) override; + +protected: + void restoreSettings(void) override; + bool setCurrentFieldName(const QString&) override; + void setColorMap(const QMap&) override; + +public: + void setVisibility(bool visible) override; + +protected: + bool isCurrentFieldUniform(void); + +protected: + class dtkVisualizationDecoratorVectorCurvedGlyphsPrivate *d = nullptr; +}; + +// +// dtkVisualizationDecoratorVectorCurvedGlyphs.h ends here -- GitLab From 60938e65d156c4da66a461aaebb729045d93c0c2 Mon Sep 17 00:00:00 2001 From: Thibaud Kloczko Date: Fri, 20 Dec 2019 16:34:49 +0100 Subject: [PATCH 2/2] Fix glyph problems. --- ...sualizationDecoratorVectorCurvedGlyphs.cpp | 44 +++++++------- .../dtkVisualizationDecoratorVectorGlyphs.cpp | 60 ++++++++----------- ...sualizationDecoratorVectorStreamTracer.cpp | 6 ++ .../dtkVisualizationDecoratorWithClut.cpp | 26 +++++--- .../dtkVisualizationDecoratorWithClut_p.h | 2 + 5 files changed, 72 insertions(+), 66 deletions(-) diff --git a/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.cpp b/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.cpp index c0c245f..dc7b314 100644 --- a/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.cpp +++ b/src/dtkVisualization/dtkVisualizationDecoratorVectorCurvedGlyphs.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -85,8 +85,7 @@ public: vtkSmartPointer streamtracer; vtkSmartPointer contours; vtkSmartPointer source_arrows; - vtkSmartPointer glyphs; - vtkSmartPointer arrows_mapper; + vtkSmartPointer glyphs_mapper; vtkSmartPointer arrows_actor; vtkSmartPointer curves_stream; vtkSmartPointer curves_tube; @@ -157,20 +156,18 @@ dtkVisualizationDecoratorVectorCurvedGlyphs::dtkVisualizationDecoratorVectorCurv d->source_arrows->SetTipLength(1); d->source_arrows->SetTipRadius(0.2); - d->glyphs = vtkSmartPointer::New(); - d->glyphs->SetSourceConnection(d->source_arrows->GetOutputPort()); - d->glyphs->SetInputConnection(d->contours->GetOutputPort()); - d->glyphs->SetVectorModeToUseVector(); - d->glyphs->SetScaleModeToDataScalingOff(); - d->glyphs->OrientOn(); - d->glyphs->SetScaleFactor(1.); - - d->arrows_mapper = vtkSmartPointer::New(); - d->arrows_mapper->SetInputConnection(d->glyphs->GetOutputPort()); - d->arrows_mapper->SetScalarModeToUsePointFieldData(); + d->glyphs_mapper = vtkSmartPointer::New(); + d->glyphs_mapper->SetSourceConnection(d->source_arrows->GetOutputPort()); + d->glyphs_mapper->SetInputConnection(d->contours->GetOutputPort()); + d->glyphs_mapper->SetOrientationModeToDirection(); + d->glyphs_mapper->SetScalarModeToUsePointFieldData(); + d->glyphs_mapper->SetScaleMode(vtkGlyph3DMapper::ScaleModes::NO_DATA_SCALING); + d->glyphs_mapper->OrientOn(); + d->glyphs_mapper->ScalingOn(); + d->glyphs_mapper->SetScaleFactor(1.); d->arrows_actor = vtkSmartPointer::New(); - d->arrows_actor->SetMapper(d->arrows_mapper); + d->arrows_actor->SetMapper(d->glyphs_mapper); d->curves_stream = vtkSmartPointer::New(); d->curves_stream->SetSourceConnection(d->contours->GetOutputPort()); @@ -482,6 +479,11 @@ bool dtkVisualizationDecoratorVectorCurvedGlyphs::setCurrentFieldName(const QStr d->curves_stream->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, qPrintable(field_name)); } d->streamtracer->Modified(); + d->curves_stream->Modified(); + + d->glyphs_mapper->SetOrientationArray(qPrintable(field_name)); + d->glyphs_mapper->SetScaleArray(qPrintable(field_name)); + d->glyphs_mapper->Modified(); return dtkVisualizationDecoratorWithClut::setCurrentFieldName(field_name); } @@ -490,17 +492,13 @@ void dtkVisualizationDecoratorVectorCurvedGlyphs::setColorMap(const QMaparrows_mapper->SetLookupTable(d_func()->color_function); + d->glyphs_mapper->SetLookupTable(d_func()->color_function); d->curves_mapper->SetLookupTable(d_func()->color_function); - if (d->glyphs->GetOutput()->GetPointData()->GetVectors()) { - d->arrows_mapper->SelectColorArray(d->glyphs->GetOutput()->GetPointData()->GetVectors()->GetName()); - } else { - d->arrows_mapper->SelectColorArray(qPrintable(d_func()->current_field_name)); - } + d->glyphs_mapper->SelectColorArray(qPrintable(d_func()->current_field_name)); d->curves_mapper->SelectColorArray(qPrintable(d_func()->current_field_name)); auto&& range = d_func()->ranges[d_func()->current_field_name]; - d->arrows_mapper->SetScalarRange(range[0], range[1]); - d->arrows_mapper->Modified(); + d->glyphs_mapper->SetScalarRange(range[0], range[1]); + d->glyphs_mapper->Modified(); d->curves_mapper->SetScalarRange(range[0], range[1]); d->curves_mapper->Modified(); } diff --git a/src/dtkVisualization/dtkVisualizationDecoratorVectorGlyphs.cpp b/src/dtkVisualization/dtkVisualizationDecoratorVectorGlyphs.cpp index 787ae77..fefee33 100644 --- a/src/dtkVisualization/dtkVisualizationDecoratorVectorGlyphs.cpp +++ b/src/dtkVisualization/dtkVisualizationDecoratorVectorGlyphs.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -34,14 +34,13 @@ class dtkVisualizationDecoratorVectorGlyphsPrivate { public: - vtkSmartPointer mapper; vtkSmartPointer actor; public: vtkSmartPointer source_arrow; vtkSmartPointer cell_centers; vtkSmartPointer mask_points; - vtkSmartPointer glyphs; + vtkSmartPointer glyphs_mapper; public: QCheckBox *show_actor_cb = nullptr; @@ -63,20 +62,19 @@ dtkVisualizationDecoratorVectorGlyphs::dtkVisualizationDecoratorVectorGlyphs(voi d->mask_points->RandomModeOff(); d->mask_points->SetOnRatio(2); // 1 => all points are taken then no masking - d->glyphs = vtkSmartPointer::New(); - d->glyphs->SetInputConnection(d->mask_points->GetOutputPort()); - d->glyphs->SetSourceConnection(d->source_arrow->GetOutputPort()); - d->glyphs->SetVectorModeToUseVector(); - d->glyphs->SetScaleModeToScaleByVector(); - d->glyphs->OrientOn(); - d->glyphs->SetScaleFactor(0.1); - - d->mapper = vtkSmartPointer::New(); - d->mapper->SetInputConnection(d->glyphs->GetOutputPort()); - d->mapper->SetScalarModeToUsePointFieldData(); + d->glyphs_mapper = vtkSmartPointer::New(); + d->glyphs_mapper->SetInputConnection(d->mask_points->GetOutputPort()); + d->glyphs_mapper->SetSourceConnection(d->source_arrow->GetOutputPort()); + d->glyphs_mapper->SetColorModeToMapScalars(); + d->glyphs_mapper->SetOrientationModeToDirection(); + d->glyphs_mapper->SetScalarModeToUsePointFieldData(); + d->glyphs_mapper->SetScaleMode(vtkGlyph3DMapper::ScaleModes::SCALE_BY_MAGNITUDE); + d->glyphs_mapper->OrientOn(); + d->glyphs_mapper->ScalingOn(); + d->glyphs_mapper->SetScaleFactor(0.1); d->actor = vtkSmartPointer::New(); - d->actor->SetMapper(d->mapper); + d->actor->SetMapper(d->glyphs_mapper); ////////// // Inspectors creation @@ -101,7 +99,7 @@ dtkVisualizationDecoratorVectorGlyphs::dtkVisualizationDecoratorVectorGlyphs(voi // Inspectors connections connect(d->show_actor_cb, &QCheckBox::stateChanged, [=] (int state) { - this->saveSettings("visibility",state == Qt::Checked); + this->saveSettings("visibility", state == Qt::Checked); this->setVisibility(state == Qt::Checked); this->draw(); }); @@ -115,7 +113,7 @@ dtkVisualizationDecoratorVectorGlyphs::dtkVisualizationDecoratorVectorGlyphs(voi connect(d->glyphs_scale_factor_sb, QOverload::of(&QDoubleSpinBox::valueChanged), [=] (double value) { this->blockSignals(true); - d->glyphs->SetScaleFactor(value); + d->glyphs_mapper->SetScaleFactor(value); this->blockSignals(false); this->draw(); }); @@ -203,7 +201,7 @@ void dtkVisualizationDecoratorVectorGlyphs::setCanvas(dtkVisualizationCanvas *ca return; } - if (d->glyphs->GetInput()) { + if (d->glyphs_mapper->GetInput()) { d_func()->view->renderer()->AddActor(d->actor); } @@ -250,15 +248,16 @@ bool dtkVisualizationDecoratorVectorGlyphs::setCurrentFieldName(const QString& f int support = d_func()->supports[field_name]; if(support == Support::Point) { d->mask_points->SetInputData(d_func()->dataset); - d->mask_points->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, qPrintable(field_name)); - d->glyphs->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, qPrintable(field_name)); } else if(support == Support::Cell) { + d->cell_centers->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, qPrintable(field_name)); d->mask_points->SetInputConnection(d->cell_centers->GetOutputPort()); - d->mask_points->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, qPrintable(field_name)); - d->glyphs->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, qPrintable(field_name)); } + d->mask_points->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, qPrintable(field_name)); d->mask_points->Modified(); - d->glyphs->Modified(); + + d->glyphs_mapper->SetOrientationArray(qPrintable(field_name)); + d->glyphs_mapper->SetScaleArray(qPrintable(field_name)); + d->glyphs_mapper->Modified(); return dtkVisualizationDecoratorWithClut::setCurrentFieldName(field_name); } @@ -267,18 +266,11 @@ void dtkVisualizationDecoratorVectorGlyphs::setColorMap(const QMapmapper->SetLookupTable(d_func()->color_function); - - // The output polydata from the glyph filter hardcodes the name of the array containing vector magnitude - // To avoid the same hardcode, one uses GetPointData()->GetScalars()->GetName() instead. - if (d->glyphs->GetOutput()->GetPointData()->GetVectors()) { - d->mapper->SelectColorArray(d->glyphs->GetOutput()->GetPointData()->GetVectors()->GetName()); - } else { - d->mapper->SelectColorArray(qPrintable(d_func()->current_field_name)); - } + d->glyphs_mapper->SetLookupTable(d_func()->color_function); + d->glyphs_mapper->SelectColorArray(qPrintable(d_func()->current_field_name)); auto&& range = d_func()->ranges[d_func()->current_field_name]; - d->mapper->SetScalarRange(range[0], range[1]); - d->mapper->Modified(); + d->glyphs_mapper->SetScalarRange(range[0], range[1]); + d->glyphs_mapper->Modified(); } // diff --git a/src/dtkVisualization/dtkVisualizationDecoratorVectorStreamTracer.cpp b/src/dtkVisualization/dtkVisualizationDecoratorVectorStreamTracer.cpp index 26b7fb6..1b382ad 100644 --- a/src/dtkVisualization/dtkVisualizationDecoratorVectorStreamTracer.cpp +++ b/src/dtkVisualization/dtkVisualizationDecoratorVectorStreamTracer.cpp @@ -394,8 +394,14 @@ void dtkVisualizationDecoratorVectorStreamTracer::setData(const QVariant& data) double pos2[3]; pos2[0] = bounds[3]; pos2[1] = bounds[4]; pos2[2] = bounds[5]; vtkBoundingBox box; box.SetBounds(bounds); + d->sp_integrator_max_lengths->blockSignals(true); d->sp_integrator_max_lengths->setValue(box.GetDiagonalLength()); + d->streamtracer->SetMaximumPropagation(box.GetDiagonalLength()); + d->sp_integrator_max_lengths->blockSignals(false); + d->sp_radius->blockSignals(true); d->sp_radius->setValue(box.GetDiagonalLength()/500.0); + d->tube_filter->SetRadius(box.GetDiagonalLength()/500.0); + d->sp_radius->blockSignals(false); d->source_sphere->SetCenter(center); d->source_sphere->SetRadius(box.GetDiagonalLength()/20.0); diff --git a/src/dtkVisualization/dtkVisualizationDecoratorWithClut.cpp b/src/dtkVisualization/dtkVisualizationDecoratorWithClut.cpp index 17052c5..e7ade39 100644 --- a/src/dtkVisualization/dtkVisualizationDecoratorWithClut.cpp +++ b/src/dtkVisualization/dtkVisualizationDecoratorWithClut.cpp @@ -54,7 +54,7 @@ dtkVisualizationDecoratorWithClutPrivate::dtkVisualizationDecoratorWithClutPriva this->fields_box = new QComboBox; this->field_components = new QComboBox; - this->field_components->addItem("None"); + this->field_components->addItem("Uniform"); this->field_components->addItem("Magnitude"); this->field_components->addItem("X"); this->field_components->addItem("Y"); @@ -275,7 +275,6 @@ void dtkVisualizationDecoratorWithClutPrivate::updateRange(void) case Kind::Vector: if (component_id > -2) { - switch (this->supports[this->current_field_name]) { case Support::Point: this->dataset->GetPointData()->GetArray(qPrintable(this->current_field_name))->Modified(); @@ -359,9 +358,12 @@ dtkVisualizationDecoratorWithClut::dtkVisualizationDecoratorWithClut(void): dtkV this->saveSettings("field_name", field_name); this->touch(); }); - connect(d->field_components, QOverload::of(&QComboBox::currentIndexChanged), [=] (int component_id) { - this->touch(); - }); + connect(d->field_components, QOverload::of(&QComboBox::currentIndexChanged), [=] (int component_id) + { + d->current_field_component = component_id; + this->saveSettings("field_component", component_id); + this->touch(); + }); connect(d->min_range, &QLineEdit::editingFinished, [=] () { d->fixed_range->blockSignals(true); @@ -417,6 +419,16 @@ void dtkVisualizationDecoratorWithClut::restoreSettings(void) settings.beginGroup("canvas"); d->default_visibility = settings.value(name+"_visibility", true).toBool(); d->default_field_name = settings.value(name+"_field_name").toString(); + + if(!d->eligible_field_names.contains(d->default_field_name)) { + d->default_field_name = QString(); + } + + d->default_field_component = settings.value(name+"_field_component").toInt(); + d->field_components->blockSignals(true); + d->field_components->setCurrentIndex(d->default_field_component); + d->field_components->blockSignals(false); + d->default_color_map = settings.value(name+"_colormap", "inferno").toString(); d->default_show_scalar_bar = settings.value(name+"_show_scalarbar", false).toBool(); double range_min = settings.value(name+"_range_min", -1.).toDouble(); @@ -503,8 +515,6 @@ bool dtkVisualizationDecoratorWithClut::setCurrentFieldName(const QString& field d->scalar_bar->SetTitle(qPrintable(this->objectName()+"/"+d->current_field_name)); d->scalar_bar->Modified(); - this->touch(); - return true; } @@ -522,8 +532,6 @@ void dtkVisualizationDecoratorWithClut::setCurrentRange(double min, double max) auto&& range = d->ranges[field_name]; range[0] = min; range[1] = max; - - this->touch(); } void dtkVisualizationDecoratorWithClut::setColorMap(const QMap& new_colormap) diff --git a/src/dtkVisualization/dtkVisualizationDecoratorWithClut_p.h b/src/dtkVisualization/dtkVisualizationDecoratorWithClut_p.h index 1269f78..8c24470 100644 --- a/src/dtkVisualization/dtkVisualizationDecoratorWithClut_p.h +++ b/src/dtkVisualization/dtkVisualizationDecoratorWithClut_p.h @@ -76,7 +76,9 @@ public: public: QStringList eligible_field_names; QString current_field_name; + int current_field_component; QString default_field_name; + int default_field_component; QString default_color_map; bool default_visibility; bool default_show_scalar_bar; -- GitLab