1 /*****************************************************************************
2 * *
3 * Elmer, A Finite Element Software for Multiphysical Problems *
4 * *
5 * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland *
6 * *
7 * This program is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU General Public License *
9 * as published by the Free Software Foundation; either version 2 *
10 * of the License, or (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program (in file fem/GPL-2); if not, write to the *
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, USA. *
21 * *
22 *****************************************************************************/
23
24 /*****************************************************************************
25 * *
26 * ElmerGUI surface *
27 * *
28 *****************************************************************************
29 * *
30 * Authors: Mikko Lyly, Juha Ruokolainen and Peter R�back *
31 * Email: Juha.Ruokolainen@csc.fi *
32 * Web: http://www.csc.fi/elmer *
33 * Address: CSC - IT Center for Science Ltd. *
34 * Keilaranta 14 *
35 * 02101 Espoo, Finland *
36 * *
37 * Original Date: 15 Mar 2008 *
38 * *
39 *****************************************************************************/
40
41 #include <QtGui>
42 #include <iostream>
43 #include "epmesh.h"
44 #include "vtkpost.h"
45 #include "surface.h"
46 #include "timestep.h"
47
48 #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 <vtkLookupTable.h>
57 #include <vtkProperty.h>
58 #include <vtkActor.h>
59
60 using namespace std;
61
Surface(QWidget * parent)62 Surface::Surface(QWidget *parent)
63 : QDialog(parent)
64 {
65 ui.setupUi(this);
66
67 connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancelButtonClicked()));
68 connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyButtonClicked()));
69 connect(ui.okButton, SIGNAL(clicked()), this, SLOT(okButtonClicked()));
70 connect(ui.surfaceCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(surfaceSelectionChanged(int)));
71 connect(ui.keepLimits, SIGNAL(stateChanged(int)), this, SLOT(keepLimitsSlot(int)));
72
73 setWindowIcon(QIcon(":/icons/Mesh3D.png"));
74 }
75
~Surface()76 Surface::~Surface()
77 {
78 }
79
cancelButtonClicked()80 void Surface::cancelButtonClicked()
81 {
82 emit(hideSurfaceSignal());
83 close();
84 }
85
applyButtonClicked()86 void Surface::applyButtonClicked()
87 {
88 emit(drawSurfaceSignal());
89 }
90
okButtonClicked()91 void Surface::okButtonClicked()
92 {
93 applyButtonClicked();
94 close();
95 }
96
populateWidgets(VtkPost * vtkPost)97 void Surface::populateWidgets(VtkPost* vtkPost)
98 {
99 this->scalarField = vtkPost->GetScalarField();
100 this->scalarFields = vtkPost->GetScalarFields();
101
102 QString name = ui.surfaceCombo->currentText();
103
104 ui.surfaceCombo->clear();
105
106 for(int i = 0; i < scalarFields; i++) {
107 ScalarField *sf = &scalarField[i];
108 QString name = sf->name;
109 ui.surfaceCombo->addItem(sf->name);
110 }
111
112 this->SetFieldName(name);
113
114 surfaceSelectionChanged(ui.surfaceCombo->currentIndex());
115 }
116
surfaceSelectionChanged(int newIndex)117 void Surface::surfaceSelectionChanged(int newIndex)
118 {
119 ScalarField *sf = &this->scalarField[newIndex];
120 if(!ui.keepLimits->isChecked()) {
121 ui.minEdit->setText(QString::number(sf->minVal));
122 ui.maxEdit->setText(QString::number(sf->maxVal));
123 }
124 }
125
keepLimitsSlot(int state)126 void Surface::keepLimitsSlot(int state)
127 {
128 if(state == 0)
129 surfaceSelectionChanged(ui.surfaceCombo->currentIndex());
130 }
131
draw(VtkPost * vtkPost,TimeStep * timeStep)132 void Surface::draw(VtkPost* vtkPost, TimeStep* timeStep)
133 {
134 int surfaceIndex = ui.surfaceCombo->currentIndex();
135 QString surfaceName = ui.surfaceCombo->currentText();
136 double minVal = ui.minEdit->text().toDouble();
137 double maxVal = ui.maxEdit->text().toDouble();
138 bool useNormals = ui.useNormals->isChecked();
139 int featureAngle = ui.featureAngle->value();
140 double opacity = ui.opacitySpin->value() / 100.0;
141 bool useClip = ui.clipPlane->isChecked();
142 useClip |= vtkPost->GetClipAll();
143
144 ScalarField* sf = &scalarField[surfaceIndex];
145 int maxDataSteps = sf->values / vtkPost->NofNodes();
146 int step = timeStep->ui.timeStep->value();
147 if(step > maxDataSteps) step = maxDataSteps;
148 if(step > timeStep->maxSteps) step = timeStep->maxSteps;
149 int offset = vtkPost->NofNodes() * (step-1);
150
151 // Scalars:
152 //---------
153 vtkPost->GetSurfaceGrid()->GetPointData()->RemoveArray("Surface");
154 vtkFloatArray* scalars = vtkFloatArray::New();
155 scalars->SetNumberOfComponents(1);
156 scalars->SetNumberOfTuples(vtkPost->NofNodes());
157 scalars->SetName("Surface");
158 for(int i = 0; i < vtkPost->NofNodes(); i++)
159 scalars->SetComponent(i, 0, sf->value[i + offset]);
160 vtkPost->GetSurfaceGrid()->GetPointData()->AddArray(scalars);
161
162 // Convert from vtkUnstructuredGrid to vtkPolyData:
163 //-------------------------------------------------
164 vtkGeometryFilter* filter = vtkGeometryFilter::New();
165
166 #if VTK_MAJOR_VERSION <= 5
167 filter->SetInput(vtkPost->GetSurfaceGrid());
168 #else
169 filter->SetInputData(vtkPost->GetSurfaceGrid());
170 #endif
171 #if VTK_MAJOR_VERSION <= 5
172 filter->GetOutput()->ReleaseDataFlagOn();
173 #else
174 filter->ReleaseDataFlagOn();
175 #endif
176
177 // Apply the clip plane:
178 //-----------------------
179 vtkClipPolyData *clipper = vtkClipPolyData::New();
180
181 if(useClip) {
182 clipper->SetInputConnection(filter->GetOutputPort());
183 clipper->SetClipFunction(vtkPost->GetClipPlane());
184 clipper->GenerateClipScalarsOn();
185 clipper->GenerateClippedOutputOn();
186 }
187
188 // Normals:
189 //---------
190 vtkPolyDataNormals *normals = vtkPolyDataNormals::New();
191
192 if(useNormals) {
193 if(useClip) {
194 normals->SetInputConnection(clipper->GetOutputPort());
195 } else {
196 normals->SetInputConnection(filter->GetOutputPort());
197 }
198 normals->SetFeatureAngle(featureAngle);
199 }
200
201 // Mapper:
202 //--------
203 vtkDataSetMapper *mapper = vtkDataSetMapper::New();
204
205 if(useNormals) {
206 mapper->SetInputConnection(normals->GetOutputPort());
207 } else {
208 if(useClip) {
209 mapper->SetInputConnection(clipper->GetOutputPort());
210 } else {
211 #if VTK_MAJOR_VERSION <= 5
212 mapper->SetInput(vtkPost->GetSurfaceGrid());
213 #else
214 mapper->SetInputData(vtkPost->GetSurfaceGrid());
215 #endif
216 }
217 }
218
219 mapper->SetScalarModeToUsePointFieldData();
220 mapper->SelectColorArray("Surface");
221 mapper->ScalarVisibilityOn();
222 mapper->SetScalarRange(minVal, maxVal);
223 mapper->SetResolveCoincidentTopologyToPolygonOffset();
224 //mapper->SetLookupTable(vtkPost->GetCurrentLut());
225 mapper->SetLookupTable(vtkPost->GetLut("Surface"));
226 // mapper->ImmediateModeRenderingOn();
227
228 // Actor:
229 //--------
230 vtkPost->GetSurfaceActor()->SetMapper(mapper);
231 vtkPost->GetSurfaceActor()->GetProperty()->SetOpacity(opacity);
232 vtkPost->SetCurrentSurfaceName(sf->name);
233
234 // Clean up:
235 //-----------
236 mapper->Delete();
237 normals->Delete();
238 clipper->Delete();
239 filter->Delete();
240 scalars->Delete();
241 }
242
243 // Public slots:
244 //---------------
GetFieldName()245 QString Surface::GetFieldName()
246 {
247 return ui.surfaceCombo->currentText();
248 }
249
SetFieldName(QString name)250 bool Surface::SetFieldName(QString name)
251 {
252 for(int i = 0; i < ui.surfaceCombo->count(); i++) {
253 if(ui.surfaceCombo->itemText(i) == name) {
254 ui.surfaceCombo->setCurrentIndex(i);
255 return true;
256 }
257 }
258 return false;
259 }
260
SetMinVal(double f)261 void Surface::SetMinVal(double f)
262 {
263 ui.minEdit->setText(QString::number(f));
264 }
265
SetMaxVal(double f)266 void Surface::SetMaxVal(double f)
267 {
268 ui.maxEdit->setText(QString::number(f));
269 }
270
KeepLimits(bool b)271 void Surface::KeepLimits(bool b)
272 {
273 ui.keepLimits->setChecked(b);
274 }
275
SetComputeNormals(bool b)276 void Surface::SetComputeNormals(bool b)
277 {
278 ui.useNormals->setChecked(b);
279 }
280
SetFeatureAngle(int n)281 void Surface::SetFeatureAngle(int n)
282 {
283 ui.featureAngle->setValue(n);
284 }
285
SetOpacity(int n)286 void Surface::SetOpacity(int n)
287 {
288 ui.opacitySpin->setValue(n);
289 }
290
SetClipPlane(bool b)291 void Surface::SetClipPlane(bool b)
292 {
293 ui.clipPlane->setChecked(b);
294 }
295