OGS
VtkVisPointSetItem.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4// ** INCLUDES **
6
7#include <vtkActor.h>
8#include <vtkCellData.h>
9#include <vtkDataSetMapper.h>
10#include <vtkImageAlgorithm.h>
11#include <vtkLookupTable.h>
12#include <vtkPointData.h>
13#include <vtkProperty.h>
14#include <vtkRenderer.h>
15#include <vtkSmartPointer.h>
16#include <vtkTransform.h>
17#include <vtkTransformFilter.h>
18
19#include <QObject>
20#include <QRegExp>
21#include <QSettings>
22#include <QStringList>
23#include <limits>
24
25#include "BaseLib/FileTools.h"
26#include "BaseLib/Logging.h"
28#include "QVtkDataSetMapper.h"
31#include "VtkCompositeFilter.h"
33
34// export test
35#include <vtkDataSetAttributes.h>
36#include <vtkPolyDataAlgorithm.h>
37#include <vtkTriangleFilter.h>
38#include <vtkTubeFilter.h>
39#include <vtkUnstructuredGridAlgorithm.h>
40#include <vtkXMLPolyDataWriter.h>
41#include <vtkXMLUnstructuredGridWriter.h>
42
44 vtkAlgorithm* algorithm, TreeItem* parentItem,
45 const QList<QVariant> data /*= QList<QVariant>()*/)
47 _mapper(nullptr),
48 _transformFilter(nullptr),
49 _onPointData(true),
51{
52 auto* visParentItem = dynamic_cast<VtkVisPipelineItem*>(parentItem);
53 if (parentItem->parentItem())
54 {
55 // special case if parent is image but child is not (e.g.
56 // Image2BarChartFilter)
57 if (dynamic_cast<vtkImageAlgorithm*>(visParentItem->algorithm()))
58 {
59 _algorithm->SetInputConnection(
60 visParentItem->algorithm()->GetOutputPort());
61 }
62 else
63 {
64 auto* pointSetItem = dynamic_cast<VtkVisPointSetItem*>(parentItem);
65 if (pointSetItem)
66 {
67 _algorithm->SetInputConnection(
68 pointSetItem->transformFilter()->GetOutputPort());
69 }
70 }
71 }
72}
73
76 const QList<QVariant> data /*= QList<QVariant>()*/)
78 _mapper(nullptr),
79 _transformFilter(nullptr),
80 _onPointData(true),
82{
83}
84
91{
92 return _vtkProps->GetActiveAttribute();
93}
94
95void VtkVisPointSetItem::Initialize(vtkRenderer* renderer)
96{
97 // TODO vtkTransformFilter creates a new copy of the point coordinates which
98 // conflicts with VtkMappedMeshSource. Find a workaround!
99 _transformFilter = vtkTransformFilter::New();
100 vtkSmartPointer<vtkTransform> transform =
101 vtkSmartPointer<vtkTransform>::New();
102 transform->Identity();
103 _transformFilter->SetTransform(transform);
104
105 auto* parentItem = dynamic_cast<VtkVisPipelineItem*>(this->parentItem());
106 if (parentItem)
107 {
108 _transformFilter->SetInputConnection(_algorithm->GetOutputPort());
109 }
110 else
111 {
112 _algorithm->Update();
113 _transformFilter->SetInputDataObject(
114 _algorithm->GetOutputDataObject(0));
115 }
116 _transformFilter->Update();
117
118 _renderer = renderer;
120 _mapper->InterpolateScalarsBeforeMappingOff();
121 _mapper->SetColorModeToMapScalars();
122
123 _mapper->SetInputConnection(_transformFilter->GetOutputPort());
124 _actor = vtkActor::New();
125 static_cast<vtkActor*>(_actor)->SetMapper(_mapper);
126 _renderer->AddActor(_actor);
127
128 // Determine the right pre-set properties
129 // Order is: _algorithm, _compositeFilter, create a new one with props
130 // copied from parent
131 auto* vtkProps = dynamic_cast<VtkAlgorithmProperties*>(_algorithm);
132 if (!vtkProps)
133 {
134 vtkProps = dynamic_cast<VtkAlgorithmProperties*>(_compositeFilter);
135
136 // Copy properties from parent or create a new VtkAlgorithmProperties
137 if (!vtkProps)
138 {
139 auto* parentItem =
140 dynamic_cast<VtkVisPipelineItem*>(this->parentItem());
141 while (parentItem)
142 {
143 VtkAlgorithmProperties* parentProps = nullptr;
144 if (dynamic_cast<VtkVisPointSetItem*>(parentItem))
145 {
146 parentProps = dynamic_cast<VtkVisPointSetItem*>(parentItem)
148 }
149 if (parentProps)
150 {
151 vtkProps =
152 new VtkAlgorithmProperties(); // TODO memory leak?
153 vtkProps->SetScalarVisibility(
154 parentProps->GetScalarVisibility());
155 vtkProps->SetTexture(parentProps->GetTexture());
156 vtkProps->SetActiveAttribute(
157 parentProps->GetActiveAttribute());
158 parentItem = nullptr;
159 }
160 else
161 {
162 parentItem = dynamic_cast<VtkVisPipelineItem*>(
163 parentItem->parentItem());
164 }
165 }
166
167 // Has no parents
168 if (!vtkProps)
169 {
170 vtkProps = new VtkAlgorithmProperties(); // TODO memory leak?
171 }
172 }
173 }
174 _vtkProps = vtkProps;
175
176 if (vtkProps->GetActiveAttribute().length() == 0)
177 {
178 // Get first scalar and set it to active
179 QStringList arrayNames = this->getScalarArrayNames();
180 if (arrayNames.length() > 0)
181 {
182 vtkProps->SetActiveAttribute(arrayNames[0]);
183 }
184 else
185 {
186 vtkProps->SetActiveAttribute("Solid Color");
187 }
188 }
189 this->setVtkProperties(vtkProps);
190 this->SetActiveAttribute(vtkProps->GetActiveAttribute());
191
192 // Set global backface culling
193 QSettings settings;
194 bool backfaceCulling = settings.value("globalCullBackfaces", 0).toBool();
195 this->setBackfaceCulling(backfaceCulling);
196
197 // Set the correct threshold range
198 if (dynamic_cast<VtkCompositeThresholdFilter*>(this->_compositeFilter))
199 {
200 double range[2];
201 this->GetRangeForActiveAttribute(range);
202 QList<QVariant> thresholdRangeList;
203 thresholdRangeList.push_back(range[0]);
204 thresholdRangeList.push_back(range[1]);
205 dynamic_cast<VtkCompositeFilter*>(this->_compositeFilter)
206 ->SetUserVectorProperty("Range", thresholdRangeList);
207 }
208
209 // Show edges on meshes
210 if (dynamic_cast<MeshLib::VtkMappedMeshSource*>(this->_algorithm))
211 {
212 _vtkProps->GetProperties()->SetEdgeVisibility(1);
213 }
214}
215
217{
218 _mapper->SetScalarVisibility(on);
219}
220
222{
223 QObject::connect(vtkProps, SIGNAL(ScalarVisibilityChanged(bool)), _mapper,
224 SLOT(SetScalarVisibility(bool)));
225
226 auto* actor = dynamic_cast<vtkActor*>(_actor);
227 if (actor)
228 {
229 if (vtkProps->GetTexture() != nullptr)
230 {
231 vtkProps->SetScalarVisibility(false);
232 actor->GetProperty()->SetColor(1, 1, 1); // don't colorise textures
233 actor->SetTexture(vtkProps->GetTexture());
234 }
235 else
236 {
237 vtkSmartPointer<vtkProperty> itemProperty =
238 vtkProps->GetProperties();
239 actor->SetProperty(itemProperty);
240 }
241
242 if (!vtkProps->GetScalarVisibility())
243 {
244 vtkProps->SetScalarVisibility(false);
245 }
246 }
247}
248
250 const std::string& filename) const
251{
252 std::string file_name_cpy(filename);
253 auto* algPD = dynamic_cast<vtkPolyDataAlgorithm*>(algorithm);
254 if (algPD)
255 {
256 vtkSmartPointer<vtkXMLPolyDataWriter> pdWriter =
257 vtkSmartPointer<vtkXMLPolyDataWriter>::New();
258 pdWriter->SetInputData(algPD->GetOutputDataObject(0));
259 if (BaseLib::getFileExtension(filename) != ".vtp")
260 {
261 file_name_cpy.append(".vtp");
262 }
263 pdWriter->SetFileName(file_name_cpy.c_str());
264 return pdWriter->Write();
265 }
266
267 auto* algUG = dynamic_cast<vtkUnstructuredGridAlgorithm*>(algorithm);
268 if (algUG)
269 {
270 vtkSmartPointer<vtkXMLUnstructuredGridWriter> ugWriter =
271 vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New();
272 ugWriter->SetInputData(algUG->GetOutputDataObject(0));
273 if (BaseLib::getFileExtension(filename) != ".vtu")
274 {
275 file_name_cpy.append(".vtu");
276 }
277 ugWriter->SetFileName(file_name_cpy.c_str());
278 return ugWriter->Write();
279 }
280
281 WARN("VtkVisPipelineItem::writeToFile(): Unknown data type.");
282 return 0;
283}
284
286{
287 // Get type by identifier
288 if (name.contains(QRegExp("^P-")))
289 {
290 _onPointData = true;
291 }
292 else if (name.contains(QRegExp("^C-")))
293 {
294 _onPointData = false;
295 }
296 else if (name.contains("Solid Color"))
297 {
298 _vtkProps->SetActiveAttribute("Solid Color");
299 _mapper->ScalarVisibilityOff();
300 return;
301 }
302 else
303 {
304 return;
305 }
306
307 // Remove type identifier
308 _activeArrayName = QString(name).remove(0, 2).toStdString();
309
310 vtkDataSet* dataSet =
311 vtkDataSet::SafeDownCast(this->_algorithm->GetOutputDataObject(0));
312 if (!dataSet)
313 {
314 return;
315 }
316
317 double range[2];
319 if (_onPointData)
320 {
321 vtkPointData* pointData = dataSet->GetPointData();
322 if (pointData)
323 {
324 _algorithm->SetInputArrayToProcess(
325 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS,
326 _activeArrayName.c_str());
327 _mapper->SetScalarModeToUsePointFieldData();
328 }
329 }
330 else
331 {
332 vtkCellData* cellData = dataSet->GetCellData();
333 if (cellData)
334 {
335 _algorithm->SetInputArrayToProcess(
336 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS,
337 _activeArrayName.c_str());
338 _mapper->SetScalarModeToUseCellFieldData();
339 }
340 }
341
342 _vtkProps->SetActiveAttribute(name);
343
344 _mapper->ScalarVisibilityOn();
345 _mapper->UseLookupTableScalarRangeOn();
346
347 auto* mapper = dynamic_cast<QVtkDataSetMapper*>(_mapper);
348 if (mapper)
349 {
350 // Create a default color table when there is no lookup table for this
351 // attribute
352 vtkLookupTable* lut = _vtkProps->GetLookupTable(name);
353 if (lut == nullptr)
354 {
355 // std::cout << "Creating new lookup table for: " <<
356 // name.toStdString() << std::endl;
357 lut = vtkLookupTable::New(); // is not a memory leak, gets deleted
358 // in VtkAlgorithmProperties
359 lut->SetTableRange(range);
360 _vtkProps->SetLookUpTable(name, lut);
361 }
362 _mapper->SetLookupTable(lut);
363 }
364 _mapper->SelectColorArray(_activeArrayName.c_str());
365}
366
368 std::string& name)
369{
370 bool arrayFound = false;
371 for (int i = 0; i < data->GetNumberOfArrays() && !arrayFound; i++)
372 {
373 std::string arrayName = data->GetArrayName(i);
374 if (arrayName == name)
375 {
376 arrayFound = true;
377 }
378 }
379 if (arrayFound)
380 {
381 // TODO Necessary? Currently this function is not called
382 data->SetActiveAttribute(name.c_str(), vtkDataSetAttributes::SCALARS);
383 return true;
384 }
385
386 return false;
387}
388
389void VtkVisPointSetItem::setScale(double x, double y, double z) const
390{
391 if (this->transformFilter())
392 {
393 auto* transform =
394 static_cast<vtkTransform*>(this->_transformFilter->GetTransform());
395 double* trans = transform->GetPosition();
396 transform->Identity();
397 transform->Scale(x, y, z);
398 transform->Translate(trans[0] / x, trans[1] / y, trans[2] / z);
399 this->transformFilter()->Modified();
400 }
401}
402
403void VtkVisPointSetItem::setTranslation(double x, double y, double z) const
404{
405 if (this->transformFilter())
406 {
407 auto* transform =
408 static_cast<vtkTransform*>(this->_transformFilter->GetTransform());
409 double* scale = transform->GetScale();
410 transform->Identity();
411 transform->Scale(scale);
412 transform->Translate(x, y, z);
413 this->transformFilter()->Modified();
414 }
415}
416
418{
419 return _transformFilter;
420}
421
423{
424 static_cast<vtkActor*>(this->_actor)
425 ->GetProperty()
426 ->SetBackfaceCulling(static_cast<int>(enable));
427}
428
430{
431 vtkDataSet* dataSet =
432 vtkDataSet::SafeDownCast(this->_algorithm->GetOutputDataObject(0));
433 if (dataSet && _activeArrayName.length() > 0)
434 {
435 if (_onPointData)
436 {
437 vtkPointData* pointData = dataSet->GetPointData();
438 if (pointData)
439 {
440 pointData->GetArray(_activeArrayName.c_str())->GetRange(range);
441 }
442 }
443 else
444 {
445 vtkCellData* cellData = dataSet->GetCellData();
446 cellData->GetArray(_activeArrayName.c_str())->GetRange(range);
447 }
448 }
449}
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
VtkMappedMeshSource is a source class to transform OGS meshes into complete vtkUnstructuredGrids....
Simply wraps vtkDataSetMapper as a Qt object to enable slot connections.
static QVtkDataSetMapper * New()
Create new objects with New() because of VTKs reference counting.
TreeItem * parentItem() const
Definition TreeItem.cpp:104
TreeItem(QList< QVariant > data, TreeItem *parent)
Definition TreeItem.cpp:12
Contains properties for the visualization of objects as VtkVisPipelineItems.
bool GetScalarVisibility() const
Returns the scalar visibility.
void SetScalarVisibility(bool on)
Sets the scalar visibility.
vtkTexture * GetTexture()
Returns a texture (if one has been assigned).
QString GetActiveAttribute() const
Returns the desired active attribute.
vtkProperty * GetProperties() const
Returns the vtk properties.
Is used to combine several filter in one VtkVisPipelineItem. You can use vtk filter and custom filter...
Visualises only parts of meshes that are above/below/within given thresholds. In init() the threshold...
vtkProp3D * actor() const
Returns the actor as vtkProp3D.
QStringList getScalarArrayNames() const
Returns a list of array names prefixed with P- or C- for point and cell data.
vtkAlgorithm * algorithm() const
Returns the algorithm object.
VtkAlgorithmProperties * _vtkProps
The active VtkAlgorithmProperties. From algorithm, compositeFilter, or copied from parent.
VtkVisPipelineItem(vtkAlgorithm *algorithm, TreeItem *parentItem, const QList< QVariant > data=QList< QVariant >())
Constructor for a source/filter object.
vtkAlgorithm * _algorithm
VtkCompositeFilter * _compositeFilter
VtkAlgorithmProperties * getVtkProperties() const
Returns the VtkAlgorithmProperties.
QVariant data(int column) const override
VtkCompositeFilter * compositeFilter() const
Returns the composite filter.
void setTranslation(double x, double y, double z) const override
Translates the item in visualisation-space.
void GetRangeForActiveAttribute(double range[2]) const
Get the scalar range for the active attribute.
VtkVisPointSetItem(vtkAlgorithm *algorithm, TreeItem *parentItem, const QList< QVariant > data=QList< QVariant >())
Constructor for a source/filter object.
void SetActiveAttribute(const QString &name) override
Sets the selected attribute array for the visualisation of the data set.
bool activeAttributeExists(vtkDataSetAttributes *data, std::string &name)
Checks if the selected attribute actually exists for the data set.
int callVTKWriter(vtkAlgorithm *algorithm, const std::string &filename) const override
Selects the appropriate VTK-Writer object and writes the object to a file with the given name.
void SetScalarVisibility(bool on)
void setVtkProperties(VtkAlgorithmProperties *vtkProps)
Sets pre-set properties on vtkActor and on vtkMapper.
void setBackfaceCulling(bool enable) const override
Enables / disables backface culling.
QVtkDataSetMapper * _mapper
void setScale(double x, double y, double z) const override
Scales the data in visualisation-space.
QString GetActiveAttribute() const override
Gets the last selected attribute.
vtkTransformFilter * _transformFilter
vtkAlgorithm * transformFilter() const override
void Initialize(vtkRenderer *renderer) override
Initializes vtkMapper and vtkActor necessary for visualization of the item and sets the item's proper...
std::string getFileExtension(const std::string &path)