Path: blob/devel/ElmerGUI/Application/vtkpost/streamline.cpp
3203 views
/*****************************************************************************1* *2* Elmer, A Finite Element Software for Multiphysical Problems *3* *4* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland *5* *6* This program is free software; you can redistribute it and/or *7* modify it under the terms of the GNU General Public License *8* as published by the Free Software Foundation; either version 2 *9* of the License, or (at your option) any later version. *10* *11* This program is distributed in the hope that it will be useful, *12* but WITHOUT ANY WARRANTY; without even the implied warranty of *13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *14* GNU General Public License for more details. *15* *16* You should have received a copy of the GNU General Public License *17* along with this program (in file fem/GPL-2); if not, write to the *18* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *19* Boston, MA 02110-1301, USA. *20* *21*****************************************************************************/2223/*****************************************************************************24* *25* ElmerGUI streamline *26* *27*****************************************************************************28* *29* Authors: Mikko Lyly, Juha Ruokolainen and Peter R�back *30* Email: [email protected] *31* Web: http://www.csc.fi/elmer *32* Address: CSC - IT Center for Science Ltd. *33* Keilaranta 14 *34* 02101 Espoo, Finland *35* *36* Original Date: 15 Mar 2008 *37* *38*****************************************************************************/3940#include <QtGui>41#include <QColorDialog>42#include <iostream>43#include "epmesh.h"44#include "vtkpost.h"45#include "streamline.h"46#include "timestep.h"4748#include <vtkUnstructuredGrid.h>49#include <vtkFloatArray.h>50#include <vtkPointData.h>51#include <vtkPointSource.h>52#include <vtkLineSource.h>5354#if VTK_MAJOR_VERSION <= 755#include <vtkStreamLine.h>56#else57#include <vtkStreamTracer.h>58#endif5960#include <vtkRungeKutta4.h>61#include <vtkRibbonFilter.h>62#include <vtkPolyDataMapper.h>63#include <vtkProperty.h>64#include <vtkLookupTable.h>65#include <vtkActor.h>6667using namespace std;6869StreamLine::StreamLine(QWidget *parent)70: QDialog(parent)71{72ui.setupUi(this);7374connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancelButtonClicked()));75connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyButtonClicked()));76connect(ui.okButton, SIGNAL(clicked()), this, SLOT(okButtonClicked()));77connect(ui.colorCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(colorSelectionChanged(int)));78connect(ui.keepLimits, SIGNAL(stateChanged(int)), this, SLOT(keepLimitsSlot(int)));7980setWindowIcon(QIcon(":/icons/Mesh3D.png"));8182ui.cancelButton->setIcon(QIcon::fromTheme("dialog-error-round"));83ui.applyButton->setIcon(QIcon::fromTheme("view-refresh"));84ui.okButton->setIcon(QIcon::fromTheme("dialog-accept"));8586#if VTK_MAJOR_VERSION >= 887ui.propagLabel->setText(QString("Max propagation:"));88ui.stepLabel->setText(QString("Max integ. step:"));89ui.integStepLabel->setText(QString("Initial integ. step:"));90ui.threadsLabel->setText(QString("Max step:"));91ui.threads->setValue(2000);92#endif9394setNullColor(Qt::blue);95connect(ui.nullColorButton, SIGNAL(clicked()), this, SLOT(nullColorButtonClicked()));96}9798StreamLine::~StreamLine()99{100}101102void StreamLine::applyButtonClicked()103{104emit(drawStreamLineSignal());105}106107void StreamLine::cancelButtonClicked()108{109emit(hideStreamLineSignal());110close();111}112113void StreamLine::okButtonClicked()114{115applyButtonClicked();116close();117}118119void StreamLine::populateWidgets(VtkPost* vtkPost)120{121this->scalarField = vtkPost->GetScalarField();122this->scalarFields = vtkPost->GetScalarFields();123124ui.vectorCombo->clear();125126int index = -1;127for(int i = 0; i < scalarFields; i++) {128ScalarField *sf = &scalarField[i];129QString name = sf->name;130if((index = name.indexOf("_x")) >= 0) {131ui.vectorCombo->addItem(name.mid(0, index));132}133}134135QString name = ui.colorCombo->currentText();136137ui.colorCombo->clear();138139for(int i = 0; i < scalarFields; i++) {140ScalarField *sf = &scalarField[i];141ui.colorCombo->addItem(sf->name);142}143144this->SetColorName(name);145146colorSelectionChanged(ui.colorCombo->currentIndex());147}148149void StreamLine::colorSelectionChanged(int newIndex)150{151ScalarField *sf = &this->scalarField[newIndex];152if(!ui.keepLimits->isChecked()) {153ui.minVal->setText(QString::number(sf->minVal));154ui.maxVal->setText(QString::number(sf->maxVal));155}156if(ui.colorCombo->currentIndex() == 0 ){ // i.e. Null field157ui.nullColorLabel->show();158ui.nullColorButton->show();159ui.minVal->setEnabled(false);160ui.maxVal->setEnabled(false);161ui.minLabel->setEnabled(false);162ui.maxLabel->setEnabled(false);163ui.keepLimits->setEnabled(false);164}else{165ui.nullColorLabel->hide();166ui.nullColorButton->hide();167ui.minVal->setEnabled(true);168ui.maxVal->setEnabled(true);169ui.minLabel->setEnabled(true);170ui.maxLabel->setEnabled(true);171ui.keepLimits->setEnabled(true);172}173}174175void StreamLine::keepLimitsSlot(int state)176{177if(state == 0)178colorSelectionChanged(ui.colorCombo->currentIndex());179}180181void StreamLine::draw(VtkPost* vtkPost, TimeStep* timeStep)182{183184QString vectorName = ui.vectorCombo->currentText();185186if(vectorName.isEmpty()) return;187188int i, j, index = -1;189for(i = 0; i < scalarFields; i++) {190ScalarField* sf = &scalarField[i];191QString name = sf->name;192if((j = name.indexOf("_x")) >= 0) {193if(vectorName == name.mid(0, j)) {194index = i;195break;196}197}198}199200if(index < 0) return;201202// Controls:203double propagationTime = ui.propagationTime->text().toDouble();204double stepLength = ui.stepLength->text().toDouble();205double integStepLength = ui.integStepLength->text().toDouble();206int threads = ui.threads->value();207bool useSurfaceGrid = ui.useSurfaceGrid->isChecked();208bool lineSource = ui.lineSource->isChecked();209bool sphereSource = ui.sphereSource->isChecked();210bool pickSource = ui.pickSource->isChecked();211bool forward = ui.forward->isChecked();212bool backward = ui.backward->isChecked();213214if(!(forward || backward)) return;215216// Color:217int colorIndex = ui.colorCombo->currentIndex();218QString colorName = ui.colorCombo->currentText();219double minVal = ui.minVal->text().toDouble();220double maxVal = ui.maxVal->text().toDouble();221222// Appearance:223bool drawRibbon = ui.drawRibbon->isChecked();224int ribbonWidth = ui.ribbonWidth->value();225int lineWidth = ui.lineWidth->text().toInt();226227// Line source:228double startX = ui.startX->text().toDouble();229double startY = ui.startY->text().toDouble();230double startZ = ui.startZ->text().toDouble();231double endX = ui.endX->text().toDouble();232double endY = ui.endY->text().toDouble();233double endZ = ui.endZ->text().toDouble();234int lines = ui.lines->value();235bool drawRake = ui.rake->isChecked();236int rakeWidth = ui.rakeWidth->value();237238ScalarField* sf_x = &scalarField[index + 0];239ScalarField* sf_y = &scalarField[index + 1];240ScalarField* sf_z = &scalarField[index + 2];241int maxDataStepVector = sf_x->values / vtkPost->NofNodes();242int step = timeStep->ui.timeStep->value();243if(step > maxDataStepVector) step = maxDataStepVector;244if(step > timeStep->maxSteps) step = timeStep->maxSteps;245int vectorOffset = vtkPost->NofNodes() * (step-1);246247ScalarField* sf = &scalarField[colorIndex];248int maxDataStepColor = sf->values / vtkPost->NofNodes();249step = timeStep->ui.timeStep->value();250if(step > maxDataStepColor) step = maxDataStepColor;251if(step > timeStep->maxSteps) step = timeStep->maxSteps;252int colorOffset = vtkPost->NofNodes() * (step-1);253254// Sphere source:255double centerX = ui.centerX->text().toDouble();256double centerY = ui.centerY->text().toDouble();257double centerZ = ui.centerZ->text().toDouble();258double radius = ui.radius->text().toDouble();259int points = ui.points->value();260261// Pick source:262double* currentPickPosition = vtkPost->GetCurrentPickPosition();263double pickX = currentPickPosition[0];264double pickY = currentPickPosition[1];265double pickZ = currentPickPosition[2];266267// Choose the grid:268//------------------269vtkUnstructuredGrid* grid = NULL;270if(useSurfaceGrid)271grid = vtkPost->GetSurfaceGrid();272else273grid = vtkPost->GetVolumeGrid();274275if(!grid) return;276277if(grid->GetNumberOfCells() < 1) return;278279// Vector data:280//-------------281grid->GetPointData()->RemoveArray("VectorData");282vtkFloatArray* vectorData = vtkFloatArray::New();283vectorData->SetNumberOfComponents(3);284vectorData->SetNumberOfTuples(vtkPost->NofNodes());285vectorData->SetName("VectorData");286for(int i = 0; i < vtkPost->NofNodes(); i++) {287double val_x = sf_x->value[i + vectorOffset];288double val_y = sf_y->value[i + vectorOffset];289double val_z = sf_z->value[i + vectorOffset];290vectorData->SetComponent(i,0,val_x);291vectorData->SetComponent(i,1,val_y);292vectorData->SetComponent(i,2,val_z);293}294grid->GetPointData()->AddArray(vectorData);295296// Color data:297//-------------298grid->GetPointData()->RemoveArray("StreamLineColor");299vtkFloatArray* vectorColor = vtkFloatArray::New();300vectorColor->SetNumberOfComponents(1);301vectorColor->SetNumberOfTuples(vtkPost->NofNodes());302vectorColor->SetName("StreamLineColor");303for(int i = 0; i < vtkPost->NofNodes(); i++)304vectorColor->SetComponent(i, 0, sf->value[i + colorOffset]);305grid->GetPointData()->AddArray(vectorColor);306307// Generate stream lines:308//-----------------------309grid->GetPointData()->SetActiveVectors("VectorData");310grid->GetPointData()->SetActiveScalars("StreamLineColor");311vtkPointSource* point = vtkPointSource::New();312vtkLineSource* line = vtkLineSource::New();313if(lineSource) {314line->SetPoint1(startX, startY, startZ);315line->SetPoint2(endX, endY, endZ);316line->SetResolution(lines);317} else {318if(sphereSource) {319point->SetCenter(centerX, centerY, centerZ);320point->SetRadius(radius);321point->SetNumberOfPoints(points);322point->SetDistributionToUniform();323} else {324point->SetCenter(pickX, pickY, pickZ);325point->SetRadius(0.0);326point->SetNumberOfPoints(1);327}328}329330#if VTK_MAJOR_VERSION <= 7331vtkStreamLine* streamer = vtkStreamLine::New();332#else333vtkStreamTracer* streamer = vtkStreamTracer::New();334#endif335336337vtkRungeKutta4* integrator = vtkRungeKutta4::New();338339#if VTK_MAJOR_VERSION <= 5340streamer->SetInput(grid);341#else342streamer->SetInputData(grid);343#endif344345if(lineSource) {346#if VTK_MAJOR_VERSION <= 5347streamer->SetSource(line->GetOutput());348#else349streamer->SetSourceConnection(line->GetOutputPort());350#endif351} else {352#if VTK_MAJOR_VERSION <= 5353streamer->SetSource(point->GetOutput());354#else355streamer->SetSourceConnection(point->GetOutputPort());356#endif357}358359streamer->SetIntegrator(integrator);360361#if VTK_MAJOR_VERSION <= 7362streamer->SetMaximumPropagationTime(propagationTime);363streamer->SetIntegrationStepLength(integStepLength);364365if(forward && backward) {366streamer->SetIntegrationDirectionToIntegrateBothDirections();367} else if(forward) {368streamer->SetIntegrationDirectionToForward();369} else {370streamer->SetIntegrationDirectionToBackward();371}372streamer->SetStepLength(stepLength);373streamer->SetNumberOfThreads(threads);374375#else376streamer->SetMaximumPropagation(propagationTime);377streamer->SetInitialIntegrationStep(stepLength);378379if(forward && backward) {380streamer->SetIntegrationDirectionToBoth();381} else if(forward) {382streamer->SetIntegrationDirectionToForward();383} else {384streamer->SetIntegrationDirectionToBackward();385}386streamer->SetMaximumIntegrationStep(integStepLength);387streamer->SetMaximumNumberOfSteps(threads);388389#endif390391vtkRibbonFilter* ribbon = vtkRibbonFilter::New();392393if(drawRibbon) {394double length = grid->GetLength();395ribbon->SetInputConnection(streamer->GetOutputPort());396ribbon->SetWidth(ribbonWidth * length / 1000.0);397ribbon->SetWidthFactor(5);398}399400vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();401402mapper->ScalarVisibilityOn();403mapper->SetScalarRange(minVal, maxVal);404405if(drawRibbon) {406mapper->SetInputConnection(ribbon->GetOutputPort());407} else {408mapper->SetInputConnection(streamer->GetOutputPort());409}410411mapper->SetColorModeToMapScalars();412mapper->InterpolateScalarsBeforeMappingOn();413//mapper->SetLookupTable(vtkPost->GetCurrentLut());414mapper->SetLookupTable(vtkPost->GetLut("Streamline"));415if(ui.colorCombo->currentIndex() == 0 ){ // i.e. Null field416mapper->SetScalarRange(0, 1);417double h = nullColor.hueF();418double s = nullColor.saturationF();419double v = nullColor.valueF();420int nColor =128;421vtkLookupTable* nullLut = vtkLookupTable::New();422nullLut->SetHueRange(h, h);423nullLut->SetSaturationRange(s, s);424nullLut->SetValueRange(v, v);425nullLut->SetNumberOfColors(nColor);426nullLut->Build();427mapper->SetLookupTable(nullLut);428nullLut->Delete();429}430vtkPost->GetStreamLineActor()->SetMapper(mapper);431432if(!drawRibbon)433vtkPost->GetStreamLineActor()->GetProperty()->SetLineWidth(lineWidth);434435vtkPost->SetCurrentStreamLineName(colorName);436437// Clean up:438//----------439line->Delete();440point->Delete();441vectorData->Delete();442vectorColor->Delete();443integrator->Delete();444streamer->Delete();445ribbon->Delete();446mapper->Delete();447}448449// Public slots:450//---------------451QString StreamLine::GetFieldName()452{453return ui.vectorCombo->currentText();454}455456QString StreamLine::GetColorName()457{458return ui.colorCombo->currentText();459}460461bool StreamLine::SetFieldName(QString name)462{463for(int i = 0; i < ui.vectorCombo->count(); i++) {464if(ui.vectorCombo->itemText(i) == name) {465ui.vectorCombo->setCurrentIndex(i);466return true;467}468}469return false;470}471472bool StreamLine::SetColorName(QString name)473{474for(int i = 0; i < ui.colorCombo->count(); i++) {475if(ui.colorCombo->itemText(i) == name) {476ui.colorCombo->setCurrentIndex(i);477return true;478}479}480return false;481}482483void StreamLine::SetMaxTime(double f)484{485ui.propagationTime->setText(QString::number(f));486}487488void StreamLine::SetStepLength(double f)489{490ui.stepLength->setText(QString::number(f));491}492493void StreamLine::SetThreads(int n)494{495ui.threads->setValue(n);496}497498void StreamLine::UseSurfaceMesh(bool b)499{500ui.useSurfaceGrid->setChecked(b);501}502503void StreamLine::UseVolumeMesh(bool b)504{505ui.useVolumeGrid->setChecked(b);506}507508void StreamLine::IntegrateForwards(bool b)509{510ui.forward->setChecked(b);511}512513void StreamLine::IntegrateBackwards(bool b)514{515ui.backward->setChecked(b);516}517518void StreamLine::SetIntegStepLength(double f)519{520ui.integStepLength->setText(QString::number(f));521}522523void StreamLine::SetMinColorVal(double f)524{525ui.minVal->setText(QString::number(f));526}527528void StreamLine::SetMaxColorVal(double f)529{530ui.maxVal->setText(QString::number(f));531}532533void StreamLine::KeepColorLimits(bool b)534{535ui.keepLimits->setChecked(b);536}537538void StreamLine::DrawLines(bool b)539{540ui.drawLines->setChecked(b);541}542543void StreamLine::DrawRibbons(bool b)544{545ui.drawRibbon->setChecked(b);546}547548void StreamLine::SetLineWidth(int n)549{550ui.lineWidth->setValue(n);551}552553void StreamLine::SetRibbonWidth(int n)554{555ui.ribbonWidth->setValue(n);556}557558void StreamLine::UseSphereSource(bool b)559{560ui.sphereSource->setChecked(b);561}562563void StreamLine::UseLineSource(bool b)564{565ui.lineSource->setChecked(b);566}567568void StreamLine::UsePointSource(bool b)569{570ui.pickSource->setChecked(b);571}572573void StreamLine::SetSphereSourceX(double f)574{575ui.centerX->setText(QString::number(f));576}577578void StreamLine::SetSphereSourceY(double f)579{580ui.centerY->setText(QString::number(f));581}582583void StreamLine::SetSphereSourceZ(double f)584{585ui.centerZ->setText(QString::number(f));586}587588void StreamLine::SetSphereSourceRadius(double f)589{590ui.radius->setText(QString::number(f));591}592593void StreamLine::SetSphereSourcePoints(int n)594{595ui.points->setValue(n);596}597598void StreamLine::SetLineSourceStartX(double f)599{600ui.startX->setText(QString::number(f));601}602603void StreamLine::SetLineSourceStartY(double f)604{605ui.startY->setText(QString::number(f));606}607608void StreamLine::SetLineSourceStartZ(double f)609{610ui.startZ->setText(QString::number(f));611}612613void StreamLine::SetLineSourceEndX(double f)614{615ui.endX->setText(QString::number(f));616}617618void StreamLine::SetLineSourceEndY(double f)619{620ui.endY->setText(QString::number(f));621}622623void StreamLine::SetLineSourceEndZ(double f)624{625ui.endZ->setText(QString::number(f));626}627628void StreamLine::SetLineSourcePoints(int n)629{630ui.lines->setValue(n);631}632633void StreamLine::nullColorButtonClicked()634{635setNullColor(QColorDialog::getColor(nullColor));636}637638void StreamLine::setNullColor(QColor color){639if(!color.isValid()) return;640641nullColor = color;642643QPalette plt(ui.nullColorLabel->palette());644plt.setColor(QPalette::WindowText, nullColor);645ui.nullColorLabel->setPalette(plt);646}647648649