Path: blob/devel/ElmerGUI/Application/vtkpost/vector.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 vector *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 "vector.h"46#include "timestep.h"4748#include <vtkPolyDataNormals.h>49#include <vtkUnstructuredGrid.h>50#include <vtkPointData.h>51#include <vtkFloatArray.h>52#include <vtkGlyph3D.h>53#include <vtkArrowSource.h>54#include <vtkPolyDataMapper.h>55#include <vtkLookupTable.h>56#include <vtkActor.h>57#include <vtkClipPolyData.h>58#include <vtkPlane.h>59#include <vtkMaskPoints.h>6061using namespace std;6263Vector::Vector(QWidget *parent)64: QDialog(parent)65{66ui.setupUi(this);6768connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancelButtonClicked()));69connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyButtonClicked()));70connect(ui.okButton, SIGNAL(clicked()), this, SLOT(okButtonClicked()));71connect(ui.colorCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(colorSelectionChanged(int)));72connect(ui.thresholdCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(thresholdSelectionChanged(int)));73connect(ui.keepLimits, SIGNAL(stateChanged(int)), this, SLOT(keepLimitsSlot(int)));74connect(ui.keepThresholdLimits, SIGNAL(stateChanged(int)), this, SLOT(keepThresholdLimitsSlot(int)));7576setWindowIcon(QIcon(":/icons/Mesh3D.png"));7778ui.cancelButton->setIcon(QIcon::fromTheme("dialog-error-round"));79ui.applyButton->setIcon(QIcon::fromTheme("view-refresh"));80ui.okButton->setIcon(QIcon::fromTheme("dialog-accept"));8182setNullColor(Qt::blue);83connect(ui.nullColorButton, SIGNAL(clicked()), this, SLOT(nullColorButtonClicked()));84}8586Vector::~Vector()87{88}8990void Vector::applyButtonClicked()91{92emit(drawVectorSignal());93}9495void Vector::cancelButtonClicked()96{97emit(hideVectorSignal());98close();99}100101void Vector::okButtonClicked()102{103emit(drawVectorSignal());104close();105}106107void Vector::populateWidgets(VtkPost *vtkPost)108{109this->scalarField = vtkPost->GetScalarField();110this->scalarFields = vtkPost->GetScalarFields();111112// Arrow:113//-------114ui.vectorCombo->clear();115116int index = -1;117for(int i = 0; i < scalarFields; i++) {118ScalarField *sf = &scalarField[i];119QString name = sf->name;120if((index = name.indexOf("_x")) >= 0) {121ui.vectorCombo->addItem(name.mid(0, index));122}123}124125// Color:126//-------127QString name = ui.colorCombo->currentText();128129ui.colorCombo->clear();130131for(int i = 0; i < scalarFields; i++) {132ScalarField *sf = &scalarField[i];133ui.colorCombo->addItem(sf->name);134}135136this->SetColorName(name);137138colorSelectionChanged(ui.colorCombo->currentIndex());139140// Threshold:141//-----------142name = ui.thresholdCombo->currentText();143144ui.thresholdCombo->clear();145146for(int i = 0; i < scalarFields; i++) {147ScalarField *sf = &scalarField[i];148ui.thresholdCombo->addItem(sf->name);149}150151this->SetThresholdName(name);152153thresholdSelectionChanged(ui.thresholdCombo->currentIndex());154}155156void Vector::colorSelectionChanged(int newIndex)157{158ScalarField *sf = &this->scalarField[newIndex];159if(!ui.keepLimits->isChecked()) {160ui.minVal->setText(QString::number(sf->minVal));161ui.maxVal->setText(QString::number(sf->maxVal));162}163if(ui.colorCombo->currentIndex() == 0 ){ // i.e. Null field164ui.nullColorLabel->show();165ui.nullColorButton->show();166ui.minVal->setEnabled(false);167ui.maxVal->setEnabled(false);168ui.minLabel->setEnabled(false);169ui.maxLabel->setEnabled(false);170ui.keepLimits->setEnabled(false);171}else{172ui.nullColorLabel->hide();173ui.nullColorButton->hide();174ui.minVal->setEnabled(true);175ui.maxVal->setEnabled(true);176ui.minLabel->setEnabled(true);177ui.maxLabel->setEnabled(true);178ui.keepLimits->setEnabled(true);179}180}181182void Vector::thresholdSelectionChanged(int newIndex)183{184ScalarField *sf = &this->scalarField[newIndex];185if(!ui.keepThresholdLimits->isChecked()) {186ui.thresholdMin->setText(QString::number(sf->minVal));187ui.thresholdMax->setText(QString::number(sf->maxVal));188}189}190191void Vector::keepLimitsSlot(int state)192{193if(state == 0)194colorSelectionChanged(ui.colorCombo->currentIndex());195}196197void Vector::keepThresholdLimitsSlot(int state)198{199if(state == 0)200thresholdSelectionChanged(ui.thresholdCombo->currentIndex());201}202203void Vector::draw(VtkPost* vtkPost, TimeStep* timeStep)204{205QString vectorName = ui.vectorCombo->currentText();206207if(vectorName.isEmpty()) return;208209int i, j, index = -1;210for(i = 0; i < scalarFields; i++) {211ScalarField *sf = &scalarField[i];212QString name = sf->name;213if((j = name.indexOf("_x")) >= 0) {214if(vectorName == name.mid(0, j)) {215index = i;216break;217}218}219}220221if(index < 0) return;222223int colorIndex = ui.colorCombo->currentIndex();224QString colorName = ui.colorCombo->currentText();225double minVal = ui.minVal->text().toDouble();226double maxVal = ui.maxVal->text().toDouble();227int quality = ui.qualitySpin->value();228double scaleMultiplier = ui.scaleSpin->value() / 100.0;229bool scaleByMagnitude = ui.scaleByMagnitude->isChecked();230bool useClip = ui.useClip->isChecked();231useClip |= vtkPost->GetClipAll();232bool useNormals = ui.useNormals->isChecked();233int everyNth = ui.everyNth->value();234bool randomMode = ui.randomMode->isChecked();235bool useThreshold = ui.useThreshold->isChecked();236int thresholdIndex = ui.thresholdCombo->currentIndex();237double thresholdMin = ui.thresholdMin->text().toDouble();238double thresholdMax = ui.thresholdMax->text().toDouble();239240ScalarField* sf_x = &scalarField[index + 0];241ScalarField* sf_y = &scalarField[index + 1];242ScalarField* sf_z = &scalarField[index + 2];243int maxDataStepsVector = sf_x->values / vtkPost->NofNodes();244int step = timeStep->ui.timeStep->value();245if(step > maxDataStepsVector) step = maxDataStepsVector;246if(step > timeStep->maxSteps) step = timeStep->maxSteps;247int vectorOffset = vtkPost->NofNodes() * (step-1);248249ScalarField* sf = &scalarField[colorIndex];250int maxDataStepsColor = sf->values / vtkPost->NofNodes();251step = timeStep->ui.timeStep->value();252if(step > maxDataStepsColor) step = maxDataStepsColor;253if(step > timeStep->maxSteps) step = timeStep->maxSteps;254int colorOffset = vtkPost->NofNodes() * (step-1);255256ScalarField* sf_threshold = &scalarField[thresholdIndex];257int maxDataStepsThreshold = sf_threshold->values / vtkPost->NofNodes();258step = timeStep->ui.timeStep->value();259if(step > maxDataStepsThreshold) step = maxDataStepsThreshold;260if(step > timeStep->maxSteps) step = timeStep->maxSteps;261int thresholdOffset = vtkPost->NofNodes() * (step-1);262263// Vector data:264//-------------265vtkPost->GetVolumeGrid()->GetPointData()->RemoveArray("VectorData");266vtkFloatArray* vectorData = vtkFloatArray::New();267vectorData->SetNumberOfComponents(3);268vectorData->SetNumberOfTuples(vtkPost->NofNodes());269vectorData->SetName("VectorData");270double scaleFactor = 0.0;271for(int i = 0; i < vtkPost->NofNodes(); i++) {272double val_x = sf_x->value[i + vectorOffset];273double val_y = sf_y->value[i + vectorOffset];274double val_z = sf_z->value[i + vectorOffset];275276if(useThreshold) {277double thresholdVal = sf_threshold->value[i + thresholdOffset];278if((thresholdVal < thresholdMin) || (thresholdVal > thresholdMax)) {279val_x = 0; val_y = 0; val_z = 0;280}281}282283double absval = sqrt(val_x*val_x + val_y*val_y + val_z*val_z);284if(absval > scaleFactor) scaleFactor = absval;285286vectorData->SetComponent(i, 0, val_x);287vectorData->SetComponent(i, 1, val_y);288vectorData->SetComponent(i, 2, val_z);289}290vtkPost->GetVolumeGrid()->GetPointData()->AddArray(vectorData);291292// Size of volume grid:293//---------------------294double length = vtkPost->GetVolumeGrid()->GetLength();295if ( scaleByMagnitude )296scaleFactor = scaleFactor * 100.0 / length;297else298scaleFactor = 100.0 / length;299300// Color data:301//-------------302vtkPost->GetVolumeGrid()->GetPointData()->RemoveArray("VectorColor");303vtkFloatArray* vectorColor = vtkFloatArray::New();304vectorColor->SetNumberOfComponents(1);305vectorColor->SetNumberOfTuples(vtkPost->NofNodes());306vectorColor->SetName("VectorColor");307for(int i = 0; i < vtkPost->NofNodes(); i++)308vectorColor->SetComponent(i, 0, sf->value[i + colorOffset]);309vtkPost->GetVolumeGrid()->GetPointData()->AddArray(vectorColor);310311// Mask points:312//-------------313vtkMaskPoints* maskPoints = vtkMaskPoints::New();314#if VTK_MAJOR_VERSION <= 5315maskPoints->SetInput(vtkPost->GetVolumeGrid());316#else317maskPoints->SetInputData(vtkPost->GetVolumeGrid());318#endif319if(randomMode) {320maskPoints->RandomModeOn();321} else {322maskPoints->RandomModeOff();323}324maskPoints->SetOnRatio(everyNth);325326// Glyphs:327//---------328vtkPost->GetVolumeGrid()->GetPointData()->SetActiveVectors("VectorData");329vtkGlyph3D* glyph = vtkGlyph3D::New();330vtkArrowSource* arrow = vtkArrowSource::New();331arrow->SetTipResolution(quality);332arrow->SetShaftResolution(quality);333glyph->SetInputConnection(maskPoints->GetOutputPort());334glyph->SetSourceConnection(arrow->GetOutputPort());335glyph->SetVectorModeToUseVector();336337glyph->SetScaleFactor(scaleMultiplier/scaleFactor);338if ( scaleByMagnitude )339glyph->SetScaleModeToScaleByVector();340else341glyph->SetScaleModeToDataScalingOff();342343glyph->SetColorModeToColorByScale();344345vtkClipPolyData* clipper = vtkClipPolyData::New();346347if(useClip) {348clipper->SetInputConnection(glyph->GetOutputPort());349clipper->SetClipFunction(vtkPost->GetClipPlane());350clipper->GenerateClipScalarsOn();351clipper->GenerateClippedOutputOn();352}353354vtkPolyDataNormals *normals = vtkPolyDataNormals::New();355356if(useNormals) {357if(useClip) {358normals->SetInputConnection(clipper->GetOutputPort());359} else {360normals->SetInputConnection(glyph->GetOutputPort());361}362normals->SetFeatureAngle(80.0);363}364365366vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();367368if ( useNormals ) {369mapper->SetInputConnection(normals->GetOutputPort());370} else {371if(useClip) {372mapper->SetInputConnection(clipper->GetOutputPort());373} else {374mapper->SetInputConnection(glyph->GetOutputPort());375}376}377mapper->SetScalarModeToUsePointFieldData();378mapper->ScalarVisibilityOn();379mapper->SetScalarRange(minVal, maxVal);380mapper->SelectColorArray("VectorColor");381mapper->InterpolateScalarsBeforeMappingOn();382//mapper->SetLookupTable(vtkPost->GetCurrentLut());383mapper->SetLookupTable(vtkPost->GetLut("Vector"));384// mapper->ImmediateModeRenderingOn();385if(ui.colorCombo->currentIndex() == 0 ){ // i.e. Null field386mapper->SetScalarRange(0, 1);387double h = nullColor.hueF();388double s = nullColor.saturationF();389double v = nullColor.valueF();390int nColor =128;391vtkLookupTable* nullLut = vtkLookupTable::New();392nullLut->SetHueRange(h, h);393nullLut->SetSaturationRange(s, s);394nullLut->SetValueRange(v, v);395nullLut->SetNumberOfColors(nColor);396nullLut->Build();397mapper->SetLookupTable(nullLut);398nullLut->Delete();399}400401vtkPost->GetVectorActor()->SetMapper(mapper);402vtkPost->SetCurrentVectorName(colorName);403404maskPoints->Delete();405normals->Delete();406mapper->Delete();407clipper->Delete();408arrow->Delete();409glyph->Delete();410vectorColor->Delete();411vectorData->Delete();412}413414// Public slots:415//---------------416QString Vector::GetFieldName()417{418return ui.vectorCombo->currentText();419}420421QString Vector::GetColorName()422{423return ui.colorCombo->currentText();424}425426QString Vector::GetThresholdName()427{428return ui.thresholdCombo->currentText();429}430431bool Vector::SetFieldName(QString name)432{433for(int i = 0; i < ui.vectorCombo->count(); i++) {434if(ui.vectorCombo->itemText(i) == name) {435ui.vectorCombo->setCurrentIndex(i);436return true;437}438}439return false;440}441442bool Vector::SetColorName(QString name)443{444for(int i = 0; i < ui.colorCombo->count(); i++) {445if(ui.colorCombo->itemText(i) == name) {446ui.colorCombo->setCurrentIndex(i);447return true;448}449}450return false;451}452453bool Vector::SetThresholdName(QString name)454{455for(int i = 0; i < ui.thresholdCombo->count(); i++) {456if(ui.thresholdCombo->itemText(i) == name) {457ui.thresholdCombo->setCurrentIndex(i);458return true;459}460}461return false;462}463464void Vector::SetLength(int n)465{466ui.scaleSpin->setValue(n);467}468469void Vector::SetQuality(int n)470{471ui.qualitySpin->setValue(n);472}473474void Vector::SetEveryNth(int n)475{476ui.everyNth->setValue(n);477}478479void Vector::SetClipPlane(bool b)480{481ui.useClip->setChecked(b);482}483484void Vector::ComputeNormals(bool b)485{486ui.useNormals->setChecked(b);487}488489void Vector::SetRandomMode(bool b)490{491ui.randomMode->setChecked(b);492}493494void Vector::ScaleByMagnitude(bool b)495{496ui.scaleByMagnitude->setChecked(b);497}498499void Vector::SetMinColorVal(double f)500{501ui.minVal->setText(QString::number(f));502}503504void Vector::SetMaxColorVal(double f)505{506ui.maxVal->setText(QString::number(f));507}508509void Vector::KeepColorLimits(bool b)510{511ui.keepLimits->setChecked(b);512}513514void Vector::SetMinThresholdVal(double f)515{516ui.thresholdMin->setText(QString::number(f));517}518519void Vector::SetMaxThresholdVal(double f)520{521ui.thresholdMax->setText(QString::number(f));522}523524void Vector::UseThreshold(bool b)525{526ui.useThreshold->setChecked(b);527}528529void Vector::KeepThresholdLimits(bool b)530{531ui.keepThresholdLimits->setChecked(b);532}533534void Vector::nullColorButtonClicked()535{536setNullColor(QColorDialog::getColor(nullColor));537}538539void Vector::setNullColor(QColor color){540if(!color.isValid()) return;541542nullColor = color;543544QPalette plt(ui.nullColorLabel->palette());545plt.setColor(QPalette::WindowText, nullColor);546ui.nullColorLabel->setPalette(plt);547}548549