Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/Application/vtkpost/vector.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 vector *
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 <iostream>
44
#include "epmesh.h"
45
#include "vtkpost.h"
46
#include "vector.h"
47
#include "timestep.h"
48
49
#include <vtkPolyDataNormals.h>
50
#include <vtkUnstructuredGrid.h>
51
#include <vtkPointData.h>
52
#include <vtkFloatArray.h>
53
#include <vtkGlyph3D.h>
54
#include <vtkArrowSource.h>
55
#include <vtkPolyDataMapper.h>
56
#include <vtkLookupTable.h>
57
#include <vtkActor.h>
58
#include <vtkClipPolyData.h>
59
#include <vtkPlane.h>
60
#include <vtkMaskPoints.h>
61
62
using namespace std;
63
64
Vector::Vector(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.colorCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(colorSelectionChanged(int)));
73
connect(ui.thresholdCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(thresholdSelectionChanged(int)));
74
connect(ui.keepLimits, SIGNAL(stateChanged(int)), this, SLOT(keepLimitsSlot(int)));
75
connect(ui.keepThresholdLimits, SIGNAL(stateChanged(int)), this, SLOT(keepThresholdLimitsSlot(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
Vector::~Vector()
88
{
89
}
90
91
void Vector::applyButtonClicked()
92
{
93
emit(drawVectorSignal());
94
}
95
96
void Vector::cancelButtonClicked()
97
{
98
emit(hideVectorSignal());
99
close();
100
}
101
102
void Vector::okButtonClicked()
103
{
104
emit(drawVectorSignal());
105
close();
106
}
107
108
void Vector::populateWidgets(VtkPost *vtkPost)
109
{
110
this->scalarField = vtkPost->GetScalarField();
111
this->scalarFields = vtkPost->GetScalarFields();
112
113
// Arrow:
114
//-------
115
ui.vectorCombo->clear();
116
117
int index = -1;
118
for(int i = 0; i < scalarFields; i++) {
119
ScalarField *sf = &scalarField[i];
120
QString name = sf->name;
121
if((index = name.indexOf("_x")) >= 0) {
122
ui.vectorCombo->addItem(name.mid(0, index));
123
}
124
}
125
126
// Color:
127
//-------
128
QString name = ui.colorCombo->currentText();
129
130
ui.colorCombo->clear();
131
132
for(int i = 0; i < scalarFields; i++) {
133
ScalarField *sf = &scalarField[i];
134
ui.colorCombo->addItem(sf->name);
135
}
136
137
this->SetColorName(name);
138
139
colorSelectionChanged(ui.colorCombo->currentIndex());
140
141
// Threshold:
142
//-----------
143
name = ui.thresholdCombo->currentText();
144
145
ui.thresholdCombo->clear();
146
147
for(int i = 0; i < scalarFields; i++) {
148
ScalarField *sf = &scalarField[i];
149
ui.thresholdCombo->addItem(sf->name);
150
}
151
152
this->SetThresholdName(name);
153
154
thresholdSelectionChanged(ui.thresholdCombo->currentIndex());
155
}
156
157
void Vector::colorSelectionChanged(int newIndex)
158
{
159
ScalarField *sf = &this->scalarField[newIndex];
160
if(!ui.keepLimits->isChecked()) {
161
ui.minVal->setText(QString::number(sf->minVal));
162
ui.maxVal->setText(QString::number(sf->maxVal));
163
}
164
if(ui.colorCombo->currentIndex() == 0 ){ // i.e. Null field
165
ui.nullColorLabel->show();
166
ui.nullColorButton->show();
167
ui.minVal->setEnabled(false);
168
ui.maxVal->setEnabled(false);
169
ui.minLabel->setEnabled(false);
170
ui.maxLabel->setEnabled(false);
171
ui.keepLimits->setEnabled(false);
172
}else{
173
ui.nullColorLabel->hide();
174
ui.nullColorButton->hide();
175
ui.minVal->setEnabled(true);
176
ui.maxVal->setEnabled(true);
177
ui.minLabel->setEnabled(true);
178
ui.maxLabel->setEnabled(true);
179
ui.keepLimits->setEnabled(true);
180
}
181
}
182
183
void Vector::thresholdSelectionChanged(int newIndex)
184
{
185
ScalarField *sf = &this->scalarField[newIndex];
186
if(!ui.keepThresholdLimits->isChecked()) {
187
ui.thresholdMin->setText(QString::number(sf->minVal));
188
ui.thresholdMax->setText(QString::number(sf->maxVal));
189
}
190
}
191
192
void Vector::keepLimitsSlot(int state)
193
{
194
if(state == 0)
195
colorSelectionChanged(ui.colorCombo->currentIndex());
196
}
197
198
void Vector::keepThresholdLimitsSlot(int state)
199
{
200
if(state == 0)
201
thresholdSelectionChanged(ui.thresholdCombo->currentIndex());
202
}
203
204
void Vector::draw(VtkPost* vtkPost, TimeStep* timeStep)
205
{
206
QString vectorName = ui.vectorCombo->currentText();
207
208
if(vectorName.isEmpty()) return;
209
210
int i, j, index = -1;
211
for(i = 0; i < scalarFields; i++) {
212
ScalarField *sf = &scalarField[i];
213
QString name = sf->name;
214
if((j = name.indexOf("_x")) >= 0) {
215
if(vectorName == name.mid(0, j)) {
216
index = i;
217
break;
218
}
219
}
220
}
221
222
if(index < 0) return;
223
224
int colorIndex = ui.colorCombo->currentIndex();
225
QString colorName = ui.colorCombo->currentText();
226
double minVal = ui.minVal->text().toDouble();
227
double maxVal = ui.maxVal->text().toDouble();
228
int quality = ui.qualitySpin->value();
229
double scaleMultiplier = ui.scaleSpin->value() / 100.0;
230
bool scaleByMagnitude = ui.scaleByMagnitude->isChecked();
231
bool useClip = ui.useClip->isChecked();
232
useClip |= vtkPost->GetClipAll();
233
bool useNormals = ui.useNormals->isChecked();
234
int everyNth = ui.everyNth->value();
235
bool randomMode = ui.randomMode->isChecked();
236
bool useThreshold = ui.useThreshold->isChecked();
237
int thresholdIndex = ui.thresholdCombo->currentIndex();
238
double thresholdMin = ui.thresholdMin->text().toDouble();
239
double thresholdMax = ui.thresholdMax->text().toDouble();
240
241
ScalarField* sf_x = &scalarField[index + 0];
242
ScalarField* sf_y = &scalarField[index + 1];
243
ScalarField* sf_z = &scalarField[index + 2];
244
int maxDataStepsVector = sf_x->values / vtkPost->NofNodes();
245
int step = timeStep->ui.timeStep->value();
246
if(step > maxDataStepsVector) step = maxDataStepsVector;
247
if(step > timeStep->maxSteps) step = timeStep->maxSteps;
248
int vectorOffset = vtkPost->NofNodes() * (step-1);
249
250
ScalarField* sf = &scalarField[colorIndex];
251
int maxDataStepsColor = sf->values / vtkPost->NofNodes();
252
step = timeStep->ui.timeStep->value();
253
if(step > maxDataStepsColor) step = maxDataStepsColor;
254
if(step > timeStep->maxSteps) step = timeStep->maxSteps;
255
int colorOffset = vtkPost->NofNodes() * (step-1);
256
257
ScalarField* sf_threshold = &scalarField[thresholdIndex];
258
int maxDataStepsThreshold = sf_threshold->values / vtkPost->NofNodes();
259
step = timeStep->ui.timeStep->value();
260
if(step > maxDataStepsThreshold) step = maxDataStepsThreshold;
261
if(step > timeStep->maxSteps) step = timeStep->maxSteps;
262
int thresholdOffset = vtkPost->NofNodes() * (step-1);
263
264
// Vector data:
265
//-------------
266
vtkPost->GetVolumeGrid()->GetPointData()->RemoveArray("VectorData");
267
vtkFloatArray* vectorData = vtkFloatArray::New();
268
vectorData->SetNumberOfComponents(3);
269
vectorData->SetNumberOfTuples(vtkPost->NofNodes());
270
vectorData->SetName("VectorData");
271
double scaleFactor = 0.0;
272
for(int i = 0; i < vtkPost->NofNodes(); i++) {
273
double val_x = sf_x->value[i + vectorOffset];
274
double val_y = sf_y->value[i + vectorOffset];
275
double val_z = sf_z->value[i + vectorOffset];
276
277
if(useThreshold) {
278
double thresholdVal = sf_threshold->value[i + thresholdOffset];
279
if((thresholdVal < thresholdMin) || (thresholdVal > thresholdMax)) {
280
val_x = 0; val_y = 0; val_z = 0;
281
}
282
}
283
284
double absval = sqrt(val_x*val_x + val_y*val_y + val_z*val_z);
285
if(absval > scaleFactor) scaleFactor = absval;
286
287
vectorData->SetComponent(i, 0, val_x);
288
vectorData->SetComponent(i, 1, val_y);
289
vectorData->SetComponent(i, 2, val_z);
290
}
291
vtkPost->GetVolumeGrid()->GetPointData()->AddArray(vectorData);
292
293
// Size of volume grid:
294
//---------------------
295
double length = vtkPost->GetVolumeGrid()->GetLength();
296
if ( scaleByMagnitude )
297
scaleFactor = scaleFactor * 100.0 / length;
298
else
299
scaleFactor = 100.0 / length;
300
301
// Color data:
302
//-------------
303
vtkPost->GetVolumeGrid()->GetPointData()->RemoveArray("VectorColor");
304
vtkFloatArray* vectorColor = vtkFloatArray::New();
305
vectorColor->SetNumberOfComponents(1);
306
vectorColor->SetNumberOfTuples(vtkPost->NofNodes());
307
vectorColor->SetName("VectorColor");
308
for(int i = 0; i < vtkPost->NofNodes(); i++)
309
vectorColor->SetComponent(i, 0, sf->value[i + colorOffset]);
310
vtkPost->GetVolumeGrid()->GetPointData()->AddArray(vectorColor);
311
312
// Mask points:
313
//-------------
314
vtkMaskPoints* maskPoints = vtkMaskPoints::New();
315
#if VTK_MAJOR_VERSION <= 5
316
maskPoints->SetInput(vtkPost->GetVolumeGrid());
317
#else
318
maskPoints->SetInputData(vtkPost->GetVolumeGrid());
319
#endif
320
if(randomMode) {
321
maskPoints->RandomModeOn();
322
} else {
323
maskPoints->RandomModeOff();
324
}
325
maskPoints->SetOnRatio(everyNth);
326
327
// Glyphs:
328
//---------
329
vtkPost->GetVolumeGrid()->GetPointData()->SetActiveVectors("VectorData");
330
vtkGlyph3D* glyph = vtkGlyph3D::New();
331
vtkArrowSource* arrow = vtkArrowSource::New();
332
arrow->SetTipResolution(quality);
333
arrow->SetShaftResolution(quality);
334
glyph->SetInputConnection(maskPoints->GetOutputPort());
335
glyph->SetSourceConnection(arrow->GetOutputPort());
336
glyph->SetVectorModeToUseVector();
337
338
glyph->SetScaleFactor(scaleMultiplier/scaleFactor);
339
if ( scaleByMagnitude )
340
glyph->SetScaleModeToScaleByVector();
341
else
342
glyph->SetScaleModeToDataScalingOff();
343
344
glyph->SetColorModeToColorByScale();
345
346
vtkClipPolyData* clipper = vtkClipPolyData::New();
347
348
if(useClip) {
349
clipper->SetInputConnection(glyph->GetOutputPort());
350
clipper->SetClipFunction(vtkPost->GetClipPlane());
351
clipper->GenerateClipScalarsOn();
352
clipper->GenerateClippedOutputOn();
353
}
354
355
vtkPolyDataNormals *normals = vtkPolyDataNormals::New();
356
357
if(useNormals) {
358
if(useClip) {
359
normals->SetInputConnection(clipper->GetOutputPort());
360
} else {
361
normals->SetInputConnection(glyph->GetOutputPort());
362
}
363
normals->SetFeatureAngle(80.0);
364
}
365
366
367
vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
368
369
if ( useNormals ) {
370
mapper->SetInputConnection(normals->GetOutputPort());
371
} else {
372
if(useClip) {
373
mapper->SetInputConnection(clipper->GetOutputPort());
374
} else {
375
mapper->SetInputConnection(glyph->GetOutputPort());
376
}
377
}
378
mapper->SetScalarModeToUsePointFieldData();
379
mapper->ScalarVisibilityOn();
380
mapper->SetScalarRange(minVal, maxVal);
381
mapper->SelectColorArray("VectorColor");
382
mapper->InterpolateScalarsBeforeMappingOn();
383
//mapper->SetLookupTable(vtkPost->GetCurrentLut());
384
mapper->SetLookupTable(vtkPost->GetLut("Vector"));
385
// mapper->ImmediateModeRenderingOn();
386
if(ui.colorCombo->currentIndex() == 0 ){ // i.e. Null field
387
mapper->SetScalarRange(0, 1);
388
double h = nullColor.hueF();
389
double s = nullColor.saturationF();
390
double v = nullColor.valueF();
391
int nColor =128;
392
vtkLookupTable* nullLut = vtkLookupTable::New();
393
nullLut->SetHueRange(h, h);
394
nullLut->SetSaturationRange(s, s);
395
nullLut->SetValueRange(v, v);
396
nullLut->SetNumberOfColors(nColor);
397
nullLut->Build();
398
mapper->SetLookupTable(nullLut);
399
nullLut->Delete();
400
}
401
402
vtkPost->GetVectorActor()->SetMapper(mapper);
403
vtkPost->SetCurrentVectorName(colorName);
404
405
maskPoints->Delete();
406
normals->Delete();
407
mapper->Delete();
408
clipper->Delete();
409
arrow->Delete();
410
glyph->Delete();
411
vectorColor->Delete();
412
vectorData->Delete();
413
}
414
415
// Public slots:
416
//---------------
417
QString Vector::GetFieldName()
418
{
419
return ui.vectorCombo->currentText();
420
}
421
422
QString Vector::GetColorName()
423
{
424
return ui.colorCombo->currentText();
425
}
426
427
QString Vector::GetThresholdName()
428
{
429
return ui.thresholdCombo->currentText();
430
}
431
432
bool Vector::SetFieldName(QString name)
433
{
434
for(int i = 0; i < ui.vectorCombo->count(); i++) {
435
if(ui.vectorCombo->itemText(i) == name) {
436
ui.vectorCombo->setCurrentIndex(i);
437
return true;
438
}
439
}
440
return false;
441
}
442
443
bool Vector::SetColorName(QString name)
444
{
445
for(int i = 0; i < ui.colorCombo->count(); i++) {
446
if(ui.colorCombo->itemText(i) == name) {
447
ui.colorCombo->setCurrentIndex(i);
448
return true;
449
}
450
}
451
return false;
452
}
453
454
bool Vector::SetThresholdName(QString name)
455
{
456
for(int i = 0; i < ui.thresholdCombo->count(); i++) {
457
if(ui.thresholdCombo->itemText(i) == name) {
458
ui.thresholdCombo->setCurrentIndex(i);
459
return true;
460
}
461
}
462
return false;
463
}
464
465
void Vector::SetLength(int n)
466
{
467
ui.scaleSpin->setValue(n);
468
}
469
470
void Vector::SetQuality(int n)
471
{
472
ui.qualitySpin->setValue(n);
473
}
474
475
void Vector::SetEveryNth(int n)
476
{
477
ui.everyNth->setValue(n);
478
}
479
480
void Vector::SetClipPlane(bool b)
481
{
482
ui.useClip->setChecked(b);
483
}
484
485
void Vector::ComputeNormals(bool b)
486
{
487
ui.useNormals->setChecked(b);
488
}
489
490
void Vector::SetRandomMode(bool b)
491
{
492
ui.randomMode->setChecked(b);
493
}
494
495
void Vector::ScaleByMagnitude(bool b)
496
{
497
ui.scaleByMagnitude->setChecked(b);
498
}
499
500
void Vector::SetMinColorVal(double f)
501
{
502
ui.minVal->setText(QString::number(f));
503
}
504
505
void Vector::SetMaxColorVal(double f)
506
{
507
ui.maxVal->setText(QString::number(f));
508
}
509
510
void Vector::KeepColorLimits(bool b)
511
{
512
ui.keepLimits->setChecked(b);
513
}
514
515
void Vector::SetMinThresholdVal(double f)
516
{
517
ui.thresholdMin->setText(QString::number(f));
518
}
519
520
void Vector::SetMaxThresholdVal(double f)
521
{
522
ui.thresholdMax->setText(QString::number(f));
523
}
524
525
void Vector::UseThreshold(bool b)
526
{
527
ui.useThreshold->setChecked(b);
528
}
529
530
void Vector::KeepThresholdLimits(bool b)
531
{
532
ui.keepThresholdLimits->setChecked(b);
533
}
534
535
void Vector::nullColorButtonClicked()
536
{
537
setNullColor(QColorDialog::getColor(nullColor));
538
}
539
540
void Vector::setNullColor(QColor color){
541
if(!color.isValid()) return;
542
543
nullColor = color;
544
545
QPalette plt(ui.nullColorLabel->palette());
546
plt.setColor(QPalette::WindowText, nullColor);
547
ui.nullColorLabel->setPalette(plt);
548
}
549