Path: blob/devel/ElmerGUI/Application/vtkpost/isosurface.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 isosurface *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 <QVector>43#include <iostream>44#include "epmesh.h"45#include "vtkpost.h"46#include "isosurface.h"47#include "timestep.h"4849#include <vtkUnstructuredGrid.h>50#include <vtkPointData.h>51#include <vtkFloatArray.h>52#include <vtkContourFilter.h>53#include <vtkClipPolyData.h>54#include <vtkPolyDataNormals.h>55#include <vtkDataSetMapper.h>56#include <vtkPlane.h>57#include <vtkLookupTable.h>58#include <vtkProperty.h>59#include <vtkActor.h>6061using namespace std;6263IsoSurface::IsoSurface(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.contoursCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(contoursSelectionChanged(int)));72connect(ui.colorCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(colorSelectionChanged(int)));73connect(ui.keepContourLimits, SIGNAL(stateChanged(int)), this, SLOT(keepContourLimitsSlot(int)));74connect(ui.keepColorLimits, SIGNAL(stateChanged(int)), this, SLOT(keepColorLimitsSlot(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}8586IsoSurface::~IsoSurface()87{88}8990void IsoSurface::applyButtonClicked()91{92emit(drawIsoSurfaceSignal());93}9495void IsoSurface::cancelButtonClicked()96{97emit(hideIsoSurfaceSignal());98close();99}100101void IsoSurface::okButtonClicked()102{103emit(drawIsoSurfaceSignal());104close();105}106107void IsoSurface::populateWidgets(VtkPost* vtkPost)108{109this->scalarField = vtkPost->GetScalarField();110this->scalarFields = vtkPost->GetScalarFields();111112QString contoursName = ui.contoursCombo->currentText();113QString colorName = ui.colorCombo->currentText();114115ui.contoursCombo->clear();116ui.colorCombo->clear();117118for(int i = 0; i < scalarFields; i++) {119ScalarField *sf = &scalarField[i];120ui.contoursCombo->addItem(sf->name);121ui.colorCombo->addItem(sf->name);122}123124this->SetFieldName(contoursName);125this->SetColorName(colorName);126127contoursSelectionChanged(ui.contoursCombo->currentIndex());128colorSelectionChanged(ui.colorCombo->currentIndex());129130ui.contourList->clear();131}132133void IsoSurface::contoursSelectionChanged(int newIndex)134{135ScalarField *sf = &this->scalarField[newIndex];136if(!ui.keepContourLimits->isChecked()) {137ui.contoursMinEdit->setText(QString::number(sf->minVal));138ui.contoursMaxEdit->setText(QString::number(sf->maxVal));139}140}141142void IsoSurface::colorSelectionChanged(int newIndex)143{144ScalarField *sf = &this->scalarField[newIndex];145if(!ui.keepColorLimits->isChecked()) {146ui.colorMinEdit->setText(QString::number(sf->minVal));147ui.colorMaxEdit->setText(QString::number(sf->maxVal));148}149if(ui.colorCombo->currentIndex() == 0 ){ // i.e. Null field150ui.nullColorLabel->show();151ui.nullColorButton->show();152ui.colorMinEdit->setEnabled(false);153ui.colorMaxEdit->setEnabled(false);154ui.colorMinLabel->setEnabled(false);155ui.colorMaxLabel->setEnabled(false);156ui.keepColorLimits->setEnabled(false);157}else{158ui.nullColorLabel->hide();159ui.nullColorButton->hide();160ui.colorMinEdit->setEnabled(true);161ui.colorMaxEdit->setEnabled(true);162ui.colorMinLabel->setEnabled(true);163ui.colorMaxLabel->setEnabled(true);164ui.keepColorLimits->setEnabled(true);165}166}167168void IsoSurface::keepContourLimitsSlot(int state)169{170if(state == 0)171contoursSelectionChanged(ui.contoursCombo->currentIndex());172}173174void IsoSurface::keepColorLimitsSlot(int state)175{176if(state == 0)177colorSelectionChanged(ui.colorCombo->currentIndex());178}179180void IsoSurface::draw(VtkPost* vtkPost, TimeStep* timeStep)181{182int contourIndex = ui.contoursCombo->currentIndex();183QString contourName = ui.contoursCombo->currentText();184int contours = ui.contoursSpin->value() + 1;185double contourMinVal = ui.contoursMinEdit->text().toDouble();186double contourMaxVal = ui.contoursMaxEdit->text().toDouble();187bool useNormals = ui.normalsCheck->isChecked();188int colorIndex = ui.colorCombo->currentIndex();189QString colorName = ui.colorCombo->currentText();190double colorMinVal = ui.colorMinEdit->text().toDouble();191double colorMaxVal = ui.colorMaxEdit->text().toDouble();192int featureAngle = ui.featureAngle->value();193double opacity = ui.opacitySpin->value() / 100.0;194bool useClip = ui.clipPlane->isChecked();195useClip |= vtkPost->GetClipAll();196197// contour list:198QString contourListText = ui.contourList->text().trimmed();199QStringList contourList = contourListText.split(";");200int contourValues = contourList.count();201202#if WITH_QT6203vector<double> contourValue;204for(int i = 0; i < contourValues; i++)205contourValue.push_back(contourList.at(i).toDouble());206sort(contourValue.begin(), contourValue.end());207#else208QVector<double> contourValue(contourValues);209for(int i = 0; i < contourValues; i++)210contourValue[i] = contourList.at(i).toDouble();211qSort(contourValue);212#endif213214bool useListValues = false;215if(!contourListText.isEmpty())216useListValues = true;217218ScalarField* sf = &scalarField[contourIndex];219int maxDataStepContour = sf->values / vtkPost->NofNodes();220int step = timeStep->ui.timeStep->value();221if(step > maxDataStepContour) step = maxDataStepContour;222if(step > timeStep->maxSteps) step = timeStep->maxSteps;223int contourOffset = vtkPost->NofNodes() * (step-1);224225sf = &scalarField[colorIndex];226int maxDataStepColor = sf->values / vtkPost->NofNodes();227step = timeStep->ui.timeStep->value();228if(step > maxDataStepColor) step = maxDataStepColor;229if(step > timeStep->maxSteps) step = timeStep->maxSteps;230int colorOffset = vtkPost->NofNodes() * (step-1);231232if(contourName == "Null") return;233234// Scalars:235//----------236vtkPost->GetVolumeGrid()->GetPointData()->RemoveArray("IsoSurface");237vtkFloatArray* contourArray = vtkFloatArray::New();238sf = &scalarField[contourIndex];239contourArray->SetNumberOfComponents(1);240contourArray->SetNumberOfTuples(vtkPost->NofNodes());241contourArray->SetName("IsoSurface");242for(int i = 0; i < vtkPost->NofNodes(); i++)243contourArray->SetComponent(i, 0, sf->value[i + contourOffset]);244vtkPost->GetVolumeGrid()->GetPointData()->AddArray(contourArray);245246vtkPost->GetVolumeGrid()->GetPointData()->RemoveArray("IsoSurfaceColor");247vtkFloatArray* colorArray = vtkFloatArray::New();248sf = &scalarField[colorIndex];249colorArray->SetName("IsoSurfaceColor");250colorArray->SetNumberOfComponents(1);251colorArray->SetNumberOfTuples(vtkPost->NofNodes());252for(int i = 0; i < vtkPost->NofNodes(); i++)253colorArray->SetComponent(i, 0, sf->value[i + colorOffset]);254vtkPost->GetVolumeGrid()->GetPointData()->AddArray(colorArray);255256// Isosurfaces:257//--------------258vtkContourFilter* iso = vtkContourFilter::New();259vtkPost->GetVolumeGrid()->GetPointData()->SetActiveScalars("IsoSurface");260#if VTK_MAJOR_VERSION <= 5261iso->SetInput(vtkPost->GetVolumeGrid());262#else263iso->SetInputData(vtkPost->GetVolumeGrid());264#endif265iso->ComputeScalarsOn();266if(useListValues) {267iso->SetNumberOfContours(contourValues);268for(int i = 0; i < contourValues; i++)269iso->SetValue(i, contourValue[i]);270} else {271iso->GenerateValues(contours, contourMinVal, contourMaxVal);272}273274// Apply the clip plane:275//-----------------------276vtkClipPolyData* clipper = vtkClipPolyData::New();277278if(useClip) {279clipper->SetInputConnection(iso->GetOutputPort());280clipper->SetClipFunction(vtkPost->GetClipPlane());281clipper->GenerateClipScalarsOn();282clipper->GenerateClippedOutputOn();283}284285// Normals:286//---------287vtkPolyDataNormals* normals = vtkPolyDataNormals::New();288289if(useNormals) {290if(useClip) {291normals->SetInputConnection(clipper->GetOutputPort());292} else {293normals->SetInputConnection(iso->GetOutputPort());294}295normals->SetFeatureAngle(featureAngle);296}297298// Mapper:299//--------300vtkDataSetMapper* mapper = vtkDataSetMapper::New();301302if(useNormals) {303mapper->SetInputConnection(normals->GetOutputPort());304} else {305if(useClip) {306mapper->SetInputConnection(clipper->GetOutputPort());307} else {308mapper->SetInputConnection(iso->GetOutputPort());309}310}311312mapper->ScalarVisibilityOn();313mapper->SelectColorArray("IsoSurfaceColor");314mapper->SetScalarModeToUsePointFieldData();315mapper->SetScalarRange(colorMinVal, colorMaxVal);316mapper->InterpolateScalarsBeforeMappingOn();317//mapper->SetLookupTable(vtkPost->GetCurrentLut());318mapper->SetLookupTable(vtkPost->GetLut("Isosurface"));319// mapper->ImmediateModeRenderingOn();320if(ui.colorCombo->currentIndex() == 0 ){ // i.e. Null field321mapper->SetScalarRange(0, 1);322double h = nullColor.hueF();323double s = nullColor.saturationF();324double v = nullColor.valueF();325int nColor =128;326vtkLookupTable* nullLut = vtkLookupTable::New();327nullLut->SetHueRange(h, h);328nullLut->SetSaturationRange(s, s);329nullLut->SetValueRange(v, v);330nullLut->SetNumberOfColors(nColor);331nullLut->Build();332mapper->SetLookupTable(nullLut);333nullLut->Delete();334}335336// Actor:337//--------338vtkPost->GetIsoSurfaceActor()->SetMapper(mapper);339vtkPost->GetIsoSurfaceActor()->GetProperty()->SetOpacity(opacity);340vtkPost->SetCurrentIsoSurfaceName(colorName);341342// Clean up:343//----------344mapper->Delete();345normals->Delete();346clipper->Delete();347iso->Delete();348colorArray->Delete();349contourArray->Delete();350}351352// Public slots:353//---------------354QString IsoSurface::GetFieldName()355{356return ui.contoursCombo->currentText();357}358359QString IsoSurface::GetColorName()360{361return ui.colorCombo->currentText();362}363364bool IsoSurface::SetFieldName(QString name)365{366for(int i = 0; i < ui.contoursCombo->count(); i++) {367if(ui.contoursCombo->itemText(i) == name) {368ui.contoursCombo->setCurrentIndex(i);369return true;370}371}372return false;373}374375bool IsoSurface::SetColorName(QString name)376{377for(int i = 0; i < ui.colorCombo->count(); i++) {378if(ui.colorCombo->itemText(i) == name) {379ui.colorCombo->setCurrentIndex(i);380return true;381}382}383return false;384}385386void IsoSurface::SetMinFieldVal(double f)387{388ui.contoursMinEdit->setText(QString::number(f));389}390391void IsoSurface::SetMaxFieldVal(double f)392{393ui.contoursMaxEdit->setText(QString::number(f));394}395396void IsoSurface::SetContours(int n)397{398ui.contoursSpin->setValue(n);399}400401void IsoSurface::SetContourValues(QString values)402{403ui.contourList->setText(values);404}405406void IsoSurface::KeepFieldLimits(bool b)407{408ui.keepContourLimits->setChecked(b);409}410411void IsoSurface::SetMinColorVal(double f)412{413ui.colorMinEdit->setText(QString::number(f));414}415416void IsoSurface::SetMaxColorVal(double f)417{418ui.colorMaxEdit->setText(QString::number(f));419}420421void IsoSurface::KeepColorLimits(bool b)422{423ui.keepColorLimits->setChecked(b);424}425426void IsoSurface::ComputeNormals(bool b)427{428ui.normalsCheck->setChecked(b);429}430431void IsoSurface::UseClipPlane(bool b)432{433ui.clipPlane->setChecked(b);434}435436void IsoSurface::SetFeatureAngle(int n)437{438ui.featureAngle->setValue(n);439}440441void IsoSurface::SetOpacity(int n)442{443ui.opacitySpin->setValue(n);444}445446void IsoSurface::nullColorButtonClicked()447{448setNullColor(QColorDialog::getColor(nullColor));449}450451void IsoSurface::setNullColor(QColor color){452if(!color.isValid()) return;453454nullColor = color;455456QPalette plt(ui.nullColorLabel->palette());457plt.setColor(QPalette::WindowText, nullColor);458ui.nullColorLabel->setPalette(plt);459}460461462