Path: blob/devel/ElmerGUI/Application/vtkpost/surface.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 surface *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 "surface.h"46#include "timestep.h"4748#include <vtkUnstructuredGrid.h>49#include <vtkPointData.h>50#include <vtkFloatArray.h>51#include <vtkGeometryFilter.h>52#include <vtkClipPolyData.h>53#include <vtkPlane.h>54#include <vtkPolyDataNormals.h>55#include <vtkDataSetMapper.h>56#include <vtkProperty.h>57#include <vtkActor.h>5859using namespace std;6061Surface::Surface(QWidget *parent)62: QDialog(parent)63{64ui.setupUi(this);6566connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancelButtonClicked()));67connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyButtonClicked()));68connect(ui.okButton, SIGNAL(clicked()), this, SLOT(okButtonClicked()));69connect(ui.surfaceCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(surfaceSelectionChanged(int)));70connect(ui.keepLimits, SIGNAL(stateChanged(int)), this, SLOT(keepLimitsSlot(int)));7172setWindowIcon(QIcon(":/icons/Mesh3D.png"));7374ui.cancelButton->setIcon(QIcon::fromTheme("dialog-error-round"));75ui.applyButton->setIcon(QIcon::fromTheme("view-refresh"));76ui.okButton->setIcon(QIcon::fromTheme("dialog-accept"));7778setNullColor(Qt::blue);79connect(ui.nullColorButton, SIGNAL(clicked()), this, SLOT(nullColorButtonClicked()));80}8182Surface::~Surface()83{84}8586void Surface::cancelButtonClicked()87{88emit(hideSurfaceSignal());89close();90}9192void Surface::applyButtonClicked()93{94emit(drawSurfaceSignal());95}9697void Surface::okButtonClicked()98{99applyButtonClicked();100close();101}102103void Surface::populateWidgets(VtkPost* vtkPost)104{105this->scalarField = vtkPost->GetScalarField();106this->scalarFields = vtkPost->GetScalarFields();107108QString name = ui.surfaceCombo->currentText();109110ui.surfaceCombo->clear();111112for(int i = 0; i < scalarFields; i++) {113ScalarField *sf = &scalarField[i];114QString name = sf->name;115ui.surfaceCombo->addItem(sf->name);116}117118this->SetFieldName(name);119120surfaceSelectionChanged(ui.surfaceCombo->currentIndex());121}122123void Surface::surfaceSelectionChanged(int newIndex)124{125ScalarField *sf = &this->scalarField[newIndex];126if(!ui.keepLimits->isChecked()) {127ui.minEdit->setText(QString::number(sf->minVal));128ui.maxEdit->setText(QString::number(sf->maxVal));129}130131if(ui.surfaceCombo->currentIndex() == 0 ){ // i.e. Null field132ui.nullColorLabel->show();133ui.nullColorButton->show();134ui.minEdit->setEnabled(false);135ui.maxEdit->setEnabled(false);136ui.minLabel->setEnabled(false);137ui.maxLabel->setEnabled(false);138ui.keepLimits->setEnabled(false);139}else{140ui.nullColorLabel->hide();141ui.nullColorButton->hide();142ui.minEdit->setEnabled(true);143ui.maxEdit->setEnabled(true);144ui.minLabel->setEnabled(true);145ui.maxLabel->setEnabled(true);146ui.keepLimits->setEnabled(true);147}148}149150void Surface::keepLimitsSlot(int state)151{152if(state == 0)153surfaceSelectionChanged(ui.surfaceCombo->currentIndex());154}155156void Surface::draw(VtkPost* vtkPost, TimeStep* timeStep)157{158int surfaceIndex = ui.surfaceCombo->currentIndex();159QString surfaceName = ui.surfaceCombo->currentText();160double minVal = ui.minEdit->text().toDouble();161double maxVal = ui.maxEdit->text().toDouble();162bool useNormals = ui.useNormals->isChecked();163int featureAngle = ui.featureAngle->value();164double opacity = ui.opacitySpin->value() / 100.0;165bool useClip = ui.clipPlane->isChecked();166useClip |= vtkPost->GetClipAll();167168ScalarField* sf = &scalarField[surfaceIndex];169int maxDataSteps = sf->values / vtkPost->NofNodes();170int step = timeStep->ui.timeStep->value();171if(step > maxDataSteps) step = maxDataSteps;172if(step > timeStep->maxSteps) step = timeStep->maxSteps;173int offset = vtkPost->NofNodes() * (step-1);174175// Scalars:176//---------177vtkPost->GetSurfaceGrid()->GetPointData()->RemoveArray("Surface");178vtkFloatArray* scalars = vtkFloatArray::New();179scalars->SetNumberOfComponents(1);180scalars->SetNumberOfTuples(vtkPost->NofNodes());181scalars->SetName("Surface");182for(int i = 0; i < vtkPost->NofNodes(); i++)183scalars->SetComponent(i, 0, sf->value[i + offset]);184vtkPost->GetSurfaceGrid()->GetPointData()->AddArray(scalars);185186// Convert from vtkUnstructuredGrid to vtkPolyData:187//-------------------------------------------------188vtkGeometryFilter* filter = vtkGeometryFilter::New();189190#if VTK_MAJOR_VERSION <= 5191filter->SetInput(vtkPost->GetSurfaceGrid());192#else193filter->SetInputData(vtkPost->GetSurfaceGrid());194#endif195#if VTK_MAJOR_VERSION <= 5196filter->GetOutput()->ReleaseDataFlagOn();197#else198filter->ReleaseDataFlagOn();199#endif200201// Apply the clip plane:202//-----------------------203vtkClipPolyData *clipper = vtkClipPolyData::New();204205if(useClip) {206clipper->SetInputConnection(filter->GetOutputPort());207clipper->SetClipFunction(vtkPost->GetClipPlane());208clipper->GenerateClipScalarsOn();209clipper->GenerateClippedOutputOn();210}211212// Normals:213//---------214vtkPolyDataNormals *normals = vtkPolyDataNormals::New();215216if(useNormals) {217if(useClip) {218normals->SetInputConnection(clipper->GetOutputPort());219} else {220normals->SetInputConnection(filter->GetOutputPort());221}222normals->SetFeatureAngle(featureAngle);223}224225// Mapper:226//--------227vtkDataSetMapper *mapper = vtkDataSetMapper::New();228229if(useNormals) {230mapper->SetInputConnection(normals->GetOutputPort());231} else {232if(useClip) {233mapper->SetInputConnection(clipper->GetOutputPort());234} else {235#if VTK_MAJOR_VERSION <= 5236mapper->SetInput(vtkPost->GetSurfaceGrid());237#else238mapper->SetInputData(vtkPost->GetSurfaceGrid());239#endif240}241}242243mapper->SetScalarModeToUsePointFieldData();244mapper->SelectColorArray("Surface");245mapper->ScalarVisibilityOn();246mapper->SetScalarRange(minVal, maxVal);247mapper->SetResolveCoincidentTopologyToPolygonOffset();248mapper->InterpolateScalarsBeforeMappingOn();249//mapper->SetLookupTable(vtkPost->GetCurrentLut());250mapper->SetLookupTable(vtkPost->GetLut("Surface"));251// mapper->ImmediateModeRenderingOn();252if(ui.surfaceCombo->currentIndex() == 0 ){ // i.e. Null field253mapper->SetScalarRange(0, 1);254double h = nullColor.hueF();255double s = nullColor.saturationF();256double v = nullColor.valueF();257int nColor =128;258vtkLookupTable* nullLut = vtkLookupTable::New();259nullLut->SetHueRange(h, h);260nullLut->SetSaturationRange(s, s);261nullLut->SetValueRange(v, v);262nullLut->SetNumberOfColors(nColor);263nullLut->Build();264mapper->SetLookupTable(nullLut);265nullLut->Delete();266}267268// Actor:269//--------270vtkPost->GetSurfaceActor()->SetMapper(mapper);271vtkPost->GetSurfaceActor()->GetProperty()->SetOpacity(opacity);272vtkPost->SetCurrentSurfaceName(sf->name);273274// Clean up:275//-----------276mapper->Delete();277normals->Delete();278clipper->Delete();279filter->Delete();280scalars->Delete();281}282283// Public slots:284//---------------285QString Surface::GetFieldName()286{287return ui.surfaceCombo->currentText();288}289290bool Surface::SetFieldName(QString name)291{292for(int i = 0; i < ui.surfaceCombo->count(); i++) {293if(ui.surfaceCombo->itemText(i) == name) {294ui.surfaceCombo->setCurrentIndex(i);295return true;296}297}298return false;299}300301void Surface::SetMinVal(double f)302{303ui.minEdit->setText(QString::number(f));304}305306void Surface::SetMaxVal(double f)307{308ui.maxEdit->setText(QString::number(f));309}310311void Surface::KeepLimits(bool b)312{313ui.keepLimits->setChecked(b);314}315316void Surface::SetComputeNormals(bool b)317{318ui.useNormals->setChecked(b);319}320321void Surface::SetFeatureAngle(int n)322{323ui.featureAngle->setValue(n);324}325326void Surface::SetOpacity(int n)327{328ui.opacitySpin->setValue(n);329}330331void Surface::SetClipPlane(bool b)332{333ui.clipPlane->setChecked(b);334}335336void Surface::nullColorButtonClicked()337{338setNullColor(QColorDialog::getColor(nullColor));339}340341void Surface::setNullColor(QColor color){342if(!color.isValid()) return;343344nullColor = color;345346QPalette plt(ui.nullColorLabel->palette());347plt.setColor(QPalette::WindowText, nullColor);348ui.nullColorLabel->setPalette(plt);349}350351