OGS
VtkVisPipelineView.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 <vtkDataSetMapper.h>
8#include <vtkProp3D.h>
9
10#include <QAbstractItemModel>
11#include <QContextMenuEvent>
12#include <QFileDialog>
13#include <QHeaderView>
14#include <QMenu>
15#include <QMessageBox>
16#include <QSettings>
17
19#include "Base/OGSError.h"
21#include "MeshLib/Mesh.h"
23#include "VtkVisImageItem.h"
24#include "VtkVisPipeline.h"
25#include "VtkVisPipelineItem.h"
26#include "VtkVisPointSetItem.h"
27
28// image to mesh conversion
29#include <vtkDataObject.h>
30#include <vtkGenericDataObjectReader.h>
31#include <vtkImageData.h>
32#include <vtkSmartPointer.h>
33#include <vtkTransformFilter.h>
34#include <vtkUnstructuredGrid.h>
35#include <vtkUnstructuredGridAlgorithm.h>
36#include <vtkXMLUnstructuredGridReader.h>
37
39#include "VtkGeoImageSource.h"
40
42 : QTreeView(parent)
43{
44 this->setItemsExpandable(false);
45 auto* checkboxDelegate = new CheckboxDelegate(this);
46 this->setItemDelegateForColumn(1, checkboxDelegate);
47 this->header()->setStretchLastSection(true);
48 this->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
49}
50
51void VtkVisPipelineView::setModel(QAbstractItemModel* model)
52{
53 QTreeView::setModel(model);
54
55 // Move Visible checkbox to the left.
56 // This is done here because at constructor time there aren't any sections.
57 this->header()->moveSection(1, 0);
58}
59
60void VtkVisPipelineView::contextMenuEvent(QContextMenuEvent* event)
61{
62 QModelIndex index = selectionModel()->currentIndex();
63 if (index.isValid())
64 {
65 // check object type
66 VtkVisPipelineItem* item = static_cast<VtkVisPipelineItem*>(
67 static_cast<VtkVisPipeline*>(this->model())
68 ->getItem(this->selectionModel()->currentIndex()));
69 int objectType =
70 item->algorithm()->GetOutputDataObject(0)->GetDataObjectType();
71 VtkAlgorithmProperties* vtkProps = item->getVtkProperties();
72 bool isSourceItem =
73 !(this->selectionModel()->currentIndex().parent().isValid());
74
75 QMenu menu;
76 QAction* addFilterAction = menu.addAction("Add filter...");
77
78 if (objectType == VTK_IMAGE_DATA)
79 {
80 // this exception is needed as image object are only displayed in
81 // the vis-pipeline
82 isSourceItem = false;
83 QAction* saveRasterAction = menu.addAction("Save Raster...");
84 connect(saveRasterAction, SIGNAL(triggered()), this,
85 SLOT(writeRaster()));
86 QAction* addMeshingAction =
87 menu.addAction("Convert Raster to Mesh...");
88 connect(addMeshingAction, SIGNAL(triggered()), this,
90 }
91 else
92 {
93 QAction* addLUTAction = menu.addAction("Add color table...");
94 connect(addLUTAction, SIGNAL(triggered()), this,
95 SLOT(addColorTable()));
96 }
97
98 if (objectType == VTK_UNSTRUCTURED_GRID)
99 {
100 QAction* addConvertToMeshAction =
101 menu.addAction("Convert to Mesh...");
102 connect(addConvertToMeshAction, SIGNAL(triggered()), this,
103 SLOT(convertVTKToOGSMesh()));
104 }
105 menu.addSeparator();
106 QAction* exportVtkAction = menu.addAction("Export as VTK");
107
108 if (!isSourceItem || vtkProps->IsRemovable())
109 {
110 menu.addSeparator();
111 QAction* removeAction = menu.addAction("Remove");
112 connect(removeAction, SIGNAL(triggered()), this,
114 }
115
116 connect(addFilterAction, SIGNAL(triggered()), this,
117 SLOT(addPipelineFilterItem()));
118 connect(exportVtkAction, SIGNAL(triggered()), this,
120
121 menu.exec(event->globalPos());
122 }
123}
124
126{
127 QSettings settings;
128 QModelIndex idx = this->selectionModel()->currentIndex();
129 QString filename = QFileDialog::getSaveFileName(
130 this, "Export object to vtk-file",
131 settings.value("lastExportedFileDirectory").toString(),
132 "VTK file (*.*)");
133 if (!filename.isEmpty())
134 {
135 static_cast<VtkVisPipelineItem*>(
136 static_cast<VtkVisPipeline*>(this->model())->getItem(idx))
137 ->writeToFile(filename.toStdString());
138 QDir dir = QDir(filename);
139 settings.setValue("lastExportedFileDirectory", dir.absolutePath());
140 }
141}
142
144{
145 emit requestRemovePipelineItem(selectionModel()->currentIndex());
146}
147
149{
150 emit requestAddPipelineFilterItem(selectionModel()->currentIndex());
151}
152
154{
156 if (dlg.exec() != QDialog::Accepted)
157 {
158 return;
159 }
160
161 vtkSmartPointer<vtkAlgorithm> algorithm =
162 static_cast<VtkVisPipelineItem*>(
163 static_cast<VtkVisPipeline*>(this->model())
164 ->getItem(this->selectionModel()->currentIndex()))
165 ->algorithm();
166
167 vtkSmartPointer<VtkGeoImageSource> imageSource =
168 VtkGeoImageSource::SafeDownCast(algorithm);
169
170 auto const raster = VtkGeoImageSource::convertToRaster(imageSource);
171 if (!raster)
172 {
173 OGSError::box("Image could not be converted to a raster.");
174 return;
175 }
176
178 *raster, dlg.getElementSelection(), dlg.getIntensitySelection(),
179 dlg.getArrayName());
180 if (mesh)
181 {
182 mesh->setName(dlg.getMeshName());
183 emit meshAdded(mesh.release());
184 }
185 else
186 {
187 OGSError::box("Error creating mesh.");
188 }
189}
190
192{
193 QModelIndex const index = this->selectionModel()->currentIndex();
194 static_cast<VtkVisImageItem*>(
195 static_cast<VtkVisPipeline*>(this->model())->getItem(index))
196 ->writeAsRaster();
197}
198
200{
201 VtkVisPipelineItem* item = static_cast<VtkVisPipelineItem*>(
202 static_cast<VtkVisPipeline*>(this->model())
203 ->getItem(this->selectionModel()->currentIndex()));
204 vtkSmartPointer<vtkAlgorithm> algorithm = item->algorithm();
205
206 vtkUnstructuredGrid* grid(nullptr);
207 vtkUnstructuredGridAlgorithm* ugAlg =
208 vtkUnstructuredGridAlgorithm::SafeDownCast(algorithm);
209 if (ugAlg)
210 {
211 grid = ugAlg->GetOutput();
212 }
213 else
214 {
215 // for old filetypes
216 vtkGenericDataObjectReader* dataReader =
217 vtkGenericDataObjectReader::SafeDownCast(algorithm);
218 if (dataReader)
219 {
220 grid = vtkUnstructuredGrid::SafeDownCast(dataReader->GetOutput());
221 }
222 else
223 {
224 // for new filetypes
225 vtkXMLUnstructuredGridReader* xmlReader =
226 vtkXMLUnstructuredGridReader::SafeDownCast(algorithm);
227 grid = vtkUnstructuredGrid::SafeDownCast(xmlReader->GetOutput());
228 }
229 }
230 MeshLib::Mesh* mesh =
232 mesh->setName(item->data(0).toString().toStdString());
233 emit meshAdded(mesh);
234}
235
236void VtkVisPipelineView::selectionChanged(const QItemSelection& selected,
237 const QItemSelection& deselected)
238{
239 QTreeView::selectionChanged(selected, deselected);
240
241 if (selected.empty())
242 {
243 return;
244 }
245
246 QModelIndex index = *selected.indexes().begin();
247 if (index.isValid())
248 {
249 auto* item = static_cast<VtkVisPipelineItem*>(index.internalPointer());
250 emit actorSelected(item->actor());
251 emit itemSelected(item);
252 if (item->transformFilter())
253 {
254 emit dataObjectSelected(vtkDataObject::SafeDownCast(
255 item->transformFilter()->GetOutputDataObject(0)));
256 }
257 }
258 else
259 {
260 emit actorSelected(nullptr);
261 emit itemSelected(nullptr);
262 emit dataObjectSelected(nullptr);
263 }
264}
265
266void VtkVisPipelineView::selectItem(vtkProp3D* actor)
267{
268 this->selectItem(
269 static_cast<VtkVisPipeline*>(this->model())->getIndex(actor));
270}
271
272void VtkVisPipelineView::selectItem(const QModelIndex& index)
273{
274 if (!index.isValid())
275 {
276 return;
277 }
278
279 QItemSelectionModel* selectionModel = this->selectionModel();
280 selectionModel->clearSelection();
281 selectionModel->select(index, QItemSelectionModel::Select);
282}
283
285{
286 VtkVisPipelineItem* item(static_cast<VtkVisPipelineItem*>(
287 static_cast<VtkVisPipeline*>(this->model())
288 ->getItem(this->selectionModel()->currentIndex())));
289 const QString array_name = item->GetActiveAttribute();
290
291 QSettings settings;
292 QString filename = QFileDialog::getOpenFileName(
293 this, "Select color table",
294 settings.value("lastOpenedLutFileDirectory").toString(),
295 "Color table files (*.xml);;");
296 QFileInfo fi(filename);
297
298 if (fi.suffix().toLower() == "xml")
299 {
300 auto* pointSetItem = dynamic_cast<VtkVisPointSetItem*>(item);
301 if (pointSetItem)
302 {
303 VtkAlgorithmProperties* props = pointSetItem->getVtkProperties();
304 if (props)
305 {
306 props->SetLookUpTable(array_name, filename);
307 item->SetActiveAttribute(array_name);
308 emit requestViewUpdate();
309 }
310 }
311 else
312 {
313 QMessageBox::warning(nullptr,
314 "Color lookup table could not be applied.",
315 "Color lookup tables can only be applied to "
316 "VtkVisPointSetItem.");
317 }
318 QDir dir = QDir(filename);
319 settings.setValue("lastOpenedLutFileDirectory", dir.absolutePath());
320 }
321}
CheckboxDelegate modifies a model view to display boolean values as checkboxes.
A dialog for specifying the parameters to construct a mesh based on a raster.
std::string getMeshName() const
MeshLib::MeshElemType getElementSelection() const
std::string getArrayName() const
MeshLib::UseIntensityAs getIntensitySelection() const
void setName(const std::string &name)
Changes the name of the mesh.
Definition Mesh.h:109
static MeshLib::Mesh * convertUnstructuredGrid(vtkUnstructuredGrid *grid, bool const compute_element_neighbors=false, std::string const &mesh_name="vtkUnstructuredGrid")
Converts a vtkUnstructuredGrid object to a Mesh.
static std::unique_ptr< MeshLib::Mesh > convert(GeoLib::Raster const &raster, MeshLib::MeshElemType elem_type, MeshLib::UseIntensityAs intensity_type, std::string const &array_name="Colour")
static void box(const QString &e)
Definition OGSError.cpp:13
TreeItem * getItem(const QModelIndex &index) const
Contains properties for the visualization of objects as VtkVisPipelineItems.
void SetLookUpTable(const QString &array_name, vtkLookupTable *lut)
Sets a colour lookup table for the given scalar array of the VtkVisPipelineItem.
bool IsRemovable() const
Is this algorithm removable from the pipeline (view).
static std::optional< GeoLib::Raster > convertToRaster(VtkGeoImageSource *const source)
An item in the VtkVisPipeline containing an image to be visualized.
bool writeAsRaster()
Allows writing this item's source object as an ASCII raster file.
An item in the VtkVisPipeline containing a graphic object to be visualized.
vtkAlgorithm * algorithm() const
Returns the algorithm object.
VtkAlgorithmProperties * getVtkProperties() const
Returns the VtkAlgorithmProperties.
virtual QString GetActiveAttribute() const
int writeToFile(const std::string &filename) const
Writes this algorithm's vtkDataSet (i.e. vtkPolyData or vtkUnstructuredGrid) to a vtk-file.
QVariant data(int column) const override
virtual void SetActiveAttribute(const QString &str)
void setModel(QAbstractItemModel *model) override
Overridden to set model specific header properties.
VtkVisPipelineView(QWidget *parent=nullptr)
Constructor.
void requestRemovePipelineItem(QModelIndex)
void meshAdded(MeshLib::Mesh *)
void dataObjectSelected(vtkDataObject *)
void requestAddPipelineFilterItem(QModelIndex)
void exportSelectedPipelineItemAsVtk()
Exports the currently selected item as a VTK file.
void convertVTKToOGSMesh()
Calls the conversion method for making a vtk grid an ogs mesh.
void actorSelected(vtkProp3D *)
void selectItem(vtkProp3D *actor)
void addColorTable()
Adds a color lookup table to the current scalar array of the selected pipeline item.
void itemSelected(VtkVisPipelineItem *)
void contextMenuEvent(QContextMenuEvent *event) override
Creates a menu on right-clicking on an item.
void showImageToMeshConversionDialog()
Calls the dialog to.
void writeRaster()
Calls the conversion method for saving this as an *.asc-file.
void addPipelineFilterItem()
Sends a requestAddPipelineFilterItem() signal to add a filter.
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override
Emits itemSelected() signals when an items was selected.
VtkVisPipeline manages the VTK visualization. It is a TreeModel and provides functions for adding and...
An item in the VtkVisPipeline containing a point set object to be visualized.