Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/Application/vtkpost/isosurface.cpp
3203 views
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 isosurface *
27
* *
28
*****************************************************************************
29
* *
30
* Authors: Mikko Lyly, Juha Ruokolainen and Peter R�back *
31
* Email: [email protected] *
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 <QColorDialog>
43
#include <QVector>
44
#include <iostream>
45
#include "epmesh.h"
46
#include "vtkpost.h"
47
#include "isosurface.h"
48
#include "timestep.h"
49
50
#include <vtkUnstructuredGrid.h>
51
#include <vtkPointData.h>
52
#include <vtkFloatArray.h>
53
#include <vtkContourFilter.h>
54
#include <vtkClipPolyData.h>
55
#include <vtkPolyDataNormals.h>
56
#include <vtkDataSetMapper.h>
57
#include <vtkPlane.h>
58
#include <vtkLookupTable.h>
59
#include <vtkProperty.h>
60
#include <vtkActor.h>
61
62
using namespace std;
63
64
IsoSurface::IsoSurface(QWidget *parent)
65
: QDialog(parent)
66
{
67
ui.setupUi(this);
68
69
connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancelButtonClicked()));
70
connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyButtonClicked()));
71
connect(ui.okButton, SIGNAL(clicked()), this, SLOT(okButtonClicked()));
72
connect(ui.contoursCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(contoursSelectionChanged(int)));
73
connect(ui.colorCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(colorSelectionChanged(int)));
74
connect(ui.keepContourLimits, SIGNAL(stateChanged(int)), this, SLOT(keepContourLimitsSlot(int)));
75
connect(ui.keepColorLimits, SIGNAL(stateChanged(int)), this, SLOT(keepColorLimitsSlot(int)));
76
77
setWindowIcon(QIcon(":/icons/Mesh3D.png"));
78
79
ui.cancelButton->setIcon(QIcon::fromTheme("dialog-error-round"));
80
ui.applyButton->setIcon(QIcon::fromTheme("view-refresh"));
81
ui.okButton->setIcon(QIcon::fromTheme("dialog-accept"));
82
83
setNullColor(Qt::blue);
84
connect(ui.nullColorButton, SIGNAL(clicked()), this, SLOT(nullColorButtonClicked()));
85
}
86
87
IsoSurface::~IsoSurface()
88
{
89
}
90
91
void IsoSurface::applyButtonClicked()
92
{
93
emit(drawIsoSurfaceSignal());
94
}
95
96
void IsoSurface::cancelButtonClicked()
97
{
98
emit(hideIsoSurfaceSignal());
99
close();
100
}
101
102
void IsoSurface::okButtonClicked()
103
{
104
emit(drawIsoSurfaceSignal());
105
close();
106
}
107
108
void IsoSurface::populateWidgets(VtkPost* vtkPost)
109
{
110
this->scalarField = vtkPost->GetScalarField();
111
this->scalarFields = vtkPost->GetScalarFields();
112
113
QString contoursName = ui.contoursCombo->currentText();
114
QString colorName = ui.colorCombo->currentText();
115
116
ui.contoursCombo->clear();
117
ui.colorCombo->clear();
118
119
for(int i = 0; i < scalarFields; i++) {
120
ScalarField *sf = &scalarField[i];
121
ui.contoursCombo->addItem(sf->name);
122
ui.colorCombo->addItem(sf->name);
123
}
124
125
this->SetFieldName(contoursName);
126
this->SetColorName(colorName);
127
128
contoursSelectionChanged(ui.contoursCombo->currentIndex());
129
colorSelectionChanged(ui.colorCombo->currentIndex());
130
131
ui.contourList->clear();
132
}
133
134
void IsoSurface::contoursSelectionChanged(int newIndex)
135
{
136
ScalarField *sf = &this->scalarField[newIndex];
137
if(!ui.keepContourLimits->isChecked()) {
138
ui.contoursMinEdit->setText(QString::number(sf->minVal));
139
ui.contoursMaxEdit->setText(QString::number(sf->maxVal));
140
}
141
}
142
143
void IsoSurface::colorSelectionChanged(int newIndex)
144
{
145
ScalarField *sf = &this->scalarField[newIndex];
146
if(!ui.keepColorLimits->isChecked()) {
147
ui.colorMinEdit->setText(QString::number(sf->minVal));
148
ui.colorMaxEdit->setText(QString::number(sf->maxVal));
149
}
150
if(ui.colorCombo->currentIndex() == 0 ){ // i.e. Null field
151
ui.nullColorLabel->show();
152
ui.nullColorButton->show();
153
ui.colorMinEdit->setEnabled(false);
154
ui.colorMaxEdit->setEnabled(false);
155
ui.colorMinLabel->setEnabled(false);
156
ui.colorMaxLabel->setEnabled(false);
157
ui.keepColorLimits->setEnabled(false);
158
}else{
159
ui.nullColorLabel->hide();
160
ui.nullColorButton->hide();
161
ui.colorMinEdit->setEnabled(true);
162
ui.colorMaxEdit->setEnabled(true);
163
ui.colorMinLabel->setEnabled(true);
164
ui.colorMaxLabel->setEnabled(true);
165
ui.keepColorLimits->setEnabled(true);
166
}
167
}
168
169
void IsoSurface::keepContourLimitsSlot(int state)
170
{
171
if(state == 0)
172
contoursSelectionChanged(ui.contoursCombo->currentIndex());
173
}
174
175
void IsoSurface::keepColorLimitsSlot(int state)
176
{
177
if(state == 0)
178
colorSelectionChanged(ui.colorCombo->currentIndex());
179
}
180
181
void IsoSurface::draw(VtkPost* vtkPost, TimeStep* timeStep)
182
{
183
int contourIndex = ui.contoursCombo->currentIndex();
184
QString contourName = ui.contoursCombo->currentText();
185
int contours = ui.contoursSpin->value() + 1;
186
double contourMinVal = ui.contoursMinEdit->text().toDouble();
187
double contourMaxVal = ui.contoursMaxEdit->text().toDouble();
188
bool useNormals = ui.normalsCheck->isChecked();
189
int colorIndex = ui.colorCombo->currentIndex();
190
QString colorName = ui.colorCombo->currentText();
191
double colorMinVal = ui.colorMinEdit->text().toDouble();
192
double colorMaxVal = ui.colorMaxEdit->text().toDouble();
193
int featureAngle = ui.featureAngle->value();
194
double opacity = ui.opacitySpin->value() / 100.0;
195
bool useClip = ui.clipPlane->isChecked();
196
useClip |= vtkPost->GetClipAll();
197
198
// contour list:
199
QString contourListText = ui.contourList->text().trimmed();
200
QStringList contourList = contourListText.split(";");
201
int contourValues = contourList.count();
202
203
#if WITH_QT6
204
vector<double> contourValue;
205
for(int i = 0; i < contourValues; i++)
206
contourValue.push_back(contourList.at(i).toDouble());
207
sort(contourValue.begin(), contourValue.end());
208
#else
209
QVector<double> contourValue(contourValues);
210
for(int i = 0; i < contourValues; i++)
211
contourValue[i] = contourList.at(i).toDouble();
212
qSort(contourValue);
213
#endif
214
215
bool useListValues = false;
216
if(!contourListText.isEmpty())
217
useListValues = true;
218
219
ScalarField* sf = &scalarField[contourIndex];
220
int maxDataStepContour = sf->values / vtkPost->NofNodes();
221
int step = timeStep->ui.timeStep->value();
222
if(step > maxDataStepContour) step = maxDataStepContour;
223
if(step > timeStep->maxSteps) step = timeStep->maxSteps;
224
int contourOffset = vtkPost->NofNodes() * (step-1);
225
226
sf = &scalarField[colorIndex];
227
int maxDataStepColor = sf->values / vtkPost->NofNodes();
228
step = timeStep->ui.timeStep->value();
229
if(step > maxDataStepColor) step = maxDataStepColor;
230
if(step > timeStep->maxSteps) step = timeStep->maxSteps;
231
int colorOffset = vtkPost->NofNodes() * (step-1);
232
233
if(contourName == "Null") return;
234
235
// Scalars:
236
//----------
237
vtkPost->GetVolumeGrid()->GetPointData()->RemoveArray("IsoSurface");
238
vtkFloatArray* contourArray = vtkFloatArray::New();
239
sf = &scalarField[contourIndex];
240
contourArray->SetNumberOfComponents(1);
241
contourArray->SetNumberOfTuples(vtkPost->NofNodes());
242
contourArray->SetName("IsoSurface");
243
for(int i = 0; i < vtkPost->NofNodes(); i++)
244
contourArray->SetComponent(i, 0, sf->value[i + contourOffset]);
245
vtkPost->GetVolumeGrid()->GetPointData()->AddArray(contourArray);
246
247
vtkPost->GetVolumeGrid()->GetPointData()->RemoveArray("IsoSurfaceColor");
248
vtkFloatArray* colorArray = vtkFloatArray::New();
249
sf = &scalarField[colorIndex];
250
colorArray->SetName("IsoSurfaceColor");
251
colorArray->SetNumberOfComponents(1);
252
colorArray->SetNumberOfTuples(vtkPost->NofNodes());
253
for(int i = 0; i < vtkPost->NofNodes(); i++)
254
colorArray->SetComponent(i, 0, sf->value[i + colorOffset]);
255
vtkPost->GetVolumeGrid()->GetPointData()->AddArray(colorArray);
256
257
// Isosurfaces:
258
//--------------
259
vtkContourFilter* iso = vtkContourFilter::New();
260
vtkPost->GetVolumeGrid()->GetPointData()->SetActiveScalars("IsoSurface");
261
#if VTK_MAJOR_VERSION <= 5
262
iso->SetInput(vtkPost->GetVolumeGrid());
263
#else
264
iso->SetInputData(vtkPost->GetVolumeGrid());
265
#endif
266
iso->ComputeScalarsOn();
267
if(useListValues) {
268
iso->SetNumberOfContours(contourValues);
269
for(int i = 0; i < contourValues; i++)
270
iso->SetValue(i, contourValue[i]);
271
} else {
272
iso->GenerateValues(contours, contourMinVal, contourMaxVal);
273
}
274
275
// Apply the clip plane:
276
//-----------------------
277
vtkClipPolyData* clipper = vtkClipPolyData::New();
278
279
if(useClip) {
280
clipper->SetInputConnection(iso->GetOutputPort());
281
clipper->SetClipFunction(vtkPost->GetClipPlane());
282
clipper->GenerateClipScalarsOn();
283
clipper->GenerateClippedOutputOn();
284
}
285
286
// Normals:
287
//---------
288
vtkPolyDataNormals* normals = vtkPolyDataNormals::New();
289
290
if(useNormals) {
291
if(useClip) {
292
normals->SetInputConnection(clipper->GetOutputPort());
293
} else {
294
normals->SetInputConnection(iso->GetOutputPort());
295
}
296
normals->SetFeatureAngle(featureAngle);
297
}
298
299
// Mapper:
300
//--------
301
vtkDataSetMapper* mapper = vtkDataSetMapper::New();
302
303
if(useNormals) {
304
mapper->SetInputConnection(normals->GetOutputPort());
305
} else {
306
if(useClip) {
307
mapper->SetInputConnection(clipper->GetOutputPort());
308
} else {
309
mapper->SetInputConnection(iso->GetOutputPort());
310
}
311
}
312
313
mapper->ScalarVisibilityOn();
314
mapper->SelectColorArray("IsoSurfaceColor");
315
mapper->SetScalarModeToUsePointFieldData();
316
mapper->SetScalarRange(colorMinVal, colorMaxVal);
317
mapper->InterpolateScalarsBeforeMappingOn();
318
//mapper->SetLookupTable(vtkPost->GetCurrentLut());
319
mapper->SetLookupTable(vtkPost->GetLut("Isosurface"));
320
// mapper->ImmediateModeRenderingOn();
321
if(ui.colorCombo->currentIndex() == 0 ){ // i.e. Null field
322
mapper->SetScalarRange(0, 1);
323
double h = nullColor.hueF();
324
double s = nullColor.saturationF();
325
double v = nullColor.valueF();
326
int nColor =128;
327
vtkLookupTable* nullLut = vtkLookupTable::New();
328
nullLut->SetHueRange(h, h);
329
nullLut->SetSaturationRange(s, s);
330
nullLut->SetValueRange(v, v);
331
nullLut->SetNumberOfColors(nColor);
332
nullLut->Build();
333
mapper->SetLookupTable(nullLut);
334
nullLut->Delete();
335
}
336
337
// Actor:
338
//--------
339
vtkPost->GetIsoSurfaceActor()->SetMapper(mapper);
340
vtkPost->GetIsoSurfaceActor()->GetProperty()->SetOpacity(opacity);
341
vtkPost->SetCurrentIsoSurfaceName(colorName);
342
343
// Clean up:
344
//----------
345
mapper->Delete();
346
normals->Delete();
347
clipper->Delete();
348
iso->Delete();
349
colorArray->Delete();
350
contourArray->Delete();
351
}
352
353
// Public slots:
354
//---------------
355
QString IsoSurface::GetFieldName()
356
{
357
return ui.contoursCombo->currentText();
358
}
359
360
QString IsoSurface::GetColorName()
361
{
362
return ui.colorCombo->currentText();
363
}
364
365
bool IsoSurface::SetFieldName(QString name)
366
{
367
for(int i = 0; i < ui.contoursCombo->count(); i++) {
368
if(ui.contoursCombo->itemText(i) == name) {
369
ui.contoursCombo->setCurrentIndex(i);
370
return true;
371
}
372
}
373
return false;
374
}
375
376
bool IsoSurface::SetColorName(QString name)
377
{
378
for(int i = 0; i < ui.colorCombo->count(); i++) {
379
if(ui.colorCombo->itemText(i) == name) {
380
ui.colorCombo->setCurrentIndex(i);
381
return true;
382
}
383
}
384
return false;
385
}
386
387
void IsoSurface::SetMinFieldVal(double f)
388
{
389
ui.contoursMinEdit->setText(QString::number(f));
390
}
391
392
void IsoSurface::SetMaxFieldVal(double f)
393
{
394
ui.contoursMaxEdit->setText(QString::number(f));
395
}
396
397
void IsoSurface::SetContours(int n)
398
{
399
ui.contoursSpin->setValue(n);
400
}
401
402
void IsoSurface::SetContourValues(QString values)
403
{
404
ui.contourList->setText(values);
405
}
406
407
void IsoSurface::KeepFieldLimits(bool b)
408
{
409
ui.keepContourLimits->setChecked(b);
410
}
411
412
void IsoSurface::SetMinColorVal(double f)
413
{
414
ui.colorMinEdit->setText(QString::number(f));
415
}
416
417
void IsoSurface::SetMaxColorVal(double f)
418
{
419
ui.colorMaxEdit->setText(QString::number(f));
420
}
421
422
void IsoSurface::KeepColorLimits(bool b)
423
{
424
ui.keepColorLimits->setChecked(b);
425
}
426
427
void IsoSurface::ComputeNormals(bool b)
428
{
429
ui.normalsCheck->setChecked(b);
430
}
431
432
void IsoSurface::UseClipPlane(bool b)
433
{
434
ui.clipPlane->setChecked(b);
435
}
436
437
void IsoSurface::SetFeatureAngle(int n)
438
{
439
ui.featureAngle->setValue(n);
440
}
441
442
void IsoSurface::SetOpacity(int n)
443
{
444
ui.opacitySpin->setValue(n);
445
}
446
447
void IsoSurface::nullColorButtonClicked()
448
{
449
setNullColor(QColorDialog::getColor(nullColor));
450
}
451
452
void IsoSurface::setNullColor(QColor color){
453
if(!color.isValid()) return;
454
455
nullColor = color;
456
457
QPalette plt(ui.nullColorLabel->palette());
458
plt.setColor(QPalette::WindowText, nullColor);
459
ui.nullColorLabel->setPalette(plt);
460
}
461
462