diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b8266403419fce02ed28582dee377539d33e6a5..88fdb47082f914fb0058d180b9a41345a6fc8dc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,15 +3,6 @@ IF (NOT VTK_FOUND) ENDIF (NOT VTK_FOUND) INCLUDE( ${VTK_USE_FILE} ) -# Find libgeotiff -FIND_PACKAGE( LibGeoTiff ) -IF(libgeotiff_FOUND) - ADD_DEFINITIONS(-Dlibgeotiff_FOUND) -ENDIF() # libgeotiff_FOUND -IF(NOT MSVC) - FIND_PACKAGE( LibTiff ) -ENDIF() # NOT MSVC - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /ZI /Od /Ob0") # Add subprojects @@ -24,7 +15,7 @@ ADD_SUBDIRECTORY( VtkAct ) IF (OGS_USE_OPENSG) ADD_SUBDIRECTORY( OpenSG ) ENDIF (OGS_USE_OPENSG) -IF(VRPN_FOUND) +IF(VRPN_FOUND AND OGS_USE_VRPN) ADD_SUBDIRECTORY( Vrpn ) ENDIF() ADD_SUBDIRECTORY( Gui ) diff --git a/DataView/CMakeLists.txt b/DataView/CMakeLists.txt index 4d4bbf31177c9cf4fc37862bdb0e33f3dfd53d94..edbd1f6634475afcdec3ee44fc92c733d5000ee3 100644 --- a/DataView/CMakeLists.txt +++ b/DataView/CMakeLists.txt @@ -2,9 +2,12 @@ set( SOURCES ColorTableModel.cpp ColorTableView.cpp + CondFromRasterDialog.cpp + ConditionWriterDialog.cpp DatabaseConnection.cpp DataView.cpp DBConnectionDialog.cpp + DirectConditionGenerator.cpp ElementTreeModel.cpp FEMConditionSetupDialog.cpp GEOModels.cpp @@ -12,6 +15,7 @@ set( SOURCES GeoTreeModel.cpp GeoTreeView.cpp GMSHPrefsDialog.cpp + LinearEditDialog.cpp LineEditDialog.cpp ListPropertiesDialog.cpp ModellingTabWidget.cpp @@ -22,11 +26,12 @@ set( SOURCES MshModel.cpp MshQualitySelectionDialog.cpp MshTabWidget.cpp + NetCdfConfigureDialog.cpp NewProcessDialog.cpp - OGSRaster.cpp ProcessModel.cpp ProcessView.cpp QueryResultsDialog.cpp + SelectMeshDialog.cpp SetNameDialog.cpp StationTabWidget.cpp StationTreeModel.cpp @@ -37,7 +42,8 @@ set( SOURCES set( MOC_HEADERS ColorTableModel.h ColorTableView.h - CondItem.h + CondFromRasterDialog.h + ConditionWriterDialog.h DatabaseConnection.h DataView.h DBConnectionDialog.h @@ -48,6 +54,7 @@ set( MOC_HEADERS GeoTreeModel.h GeoTreeView.h GMSHPrefsDialog.h + LinearEditDialog.h LineEditDialog.h ListPropertiesDialog.h ModellingTabWidget.h @@ -55,10 +62,12 @@ set( MOC_HEADERS MshModel.h MshQualitySelectionDialog.h MshTabWidget.h + NetCdfConfigureDialog.h NewProcessDialog.h ProcessModel.h ProcessView.h QueryResultsDialog.h + SelectMeshDialog.h SetNameDialog.h StationTabWidget.h StationTreeModel.h @@ -68,28 +77,33 @@ set( MOC_HEADERS # Header files set( HEADERS BaseItem.h - ProcessItem.h + CondItem.h + DirectConditionGenerator.h CondObjectListItem.h GeoObjectListItem.h GeoTreeItem.h ModelTreeItem.h MshItem.h MshLayerMapper.h - OGSRaster.h + ProcessItem.h ) # UI files set( UIS + CondFromRaster.ui + ConditionWriter.ui DatabaseResultView.ui DBConnection.ui FEMConditionSetup.ui GeoTabWidgetBase.ui GMSHPrefs.ui + LinearEdit.ui LineEdit.ui ModellingTabWidgetBase.ui MshEdit.ui MshQualitySelection.ui MshTabWidgetBase.ui + NetCdfConfigure.ui NewProcess.ui StationTabWidgetBase.ui ) @@ -116,28 +130,24 @@ qt4_wrap_cpp( MOC_SOURCES ${MOC_HEADERS} ) # Include the headers which are generated by uic and moc # and include additional header include_directories( - . ${CMAKE_BINARY_DIR}/Qt/Base ${CMAKE_BINARY_DIR}/Qt/DataView ${CMAKE_BINARY_DIR}/Qt/DataView/DiagramView ${CMAKE_BINARY_DIR}/Qt/DataView/StratView - ../../Base - ../../MathLib - ../../GEO - ../../MSH - ../../FEM - ../../FileIO - ../Base - ./DiagramView - ./StratView - ../VtkVis - ${CMAKE_SOURCE_DIR} + + ${CMAKE_SOURCE_DIR}/Base + ${CMAKE_SOURCE_DIR}/MathLib + ${CMAKE_SOURCE_DIR}/GEO + ${CMAKE_SOURCE_DIR}/MSH + ${CMAKE_SOURCE_DIR}/FEM + ${CMAKE_SOURCE_DIR}/FileIO + ${CMAKE_SOURCE_DIR}/Qt/Base + ${CMAKE_SOURCE_DIR}/Qt/DataView + ${CMAKE_SOURCE_DIR}/Qt/DataView/DiagramView + ${CMAKE_SOURCE_DIR}/Qt/DataView/StratView + ${CMAKE_SOURCE_DIR}/Qt/VtkVis ) -if (OGS_COMPILE_QVTK) - include_directories(${CMAKE_BINARY_DIR}/Qt/QVTK ../QVTK) -endif (OGS_COMPILE_QVTK) - IF(VRPN_FOUND) INCLUDE_DIRECTORIES( ../Vrpn ${VRPN_INCLUDE_DIRS} ) ENDIF() diff --git a/DataView/CondFromRaster.ui b/DataView/CondFromRaster.ui new file mode 100644 index 0000000000000000000000000000000000000000..44be4ff9166939d0cbe2ef50b03111ca2f471f0d --- /dev/null +++ b/DataView/CondFromRaster.ui @@ -0,0 +1,241 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>CondFromRaster</class> + <widget class="QDialog" name="CondFromRaster"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>340</width> + <height>230</height> + </rect> + </property> + <property name="windowTitle"> + <string>Create Boundary Conditions from Raster Files</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="meshLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Mesh</string> + </property> + </widget> + </item> + <item row="0" column="1" colspan="3"> + <widget class="QComboBox" name="meshBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="rasterLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Raster</string> + </property> + </widget> + </item> + <item row="4" column="1" colspan="2"> + <widget class="QLineEdit" name="rasterEdit"/> + </item> + <item row="4" column="3"> + <widget class="QPushButton" name="selectButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>30</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="7" column="2" colspan="2"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="6" column="0" colspan="4"> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Calculation method</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0" colspan="3"> + <widget class="QRadioButton" name="directButton"> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>Use raster values directly</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="3"> + <widget class="QRadioButton" name="integrateButton"> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>Integrate over mesh elements</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="scalingLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Scaling</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="scalingEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>70</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>70</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>(Note: Normalization is 1 / Scaling)</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>CondFromRaster</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>CondFromRaster</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/DataView/CondFromRasterDialog.cpp b/DataView/CondFromRasterDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..babf1d87f4233514c9ab8a7269216eb50f0662cb --- /dev/null +++ b/DataView/CondFromRasterDialog.cpp @@ -0,0 +1,111 @@ +/** + * \file CondFromRasterDialog.cpp + * 2012/01/04 KR Initial implementation + */ + +#include "CondFromRasterDialog.h" + +#include <QFileDialog> +#include <QSettings> + +#include "DirectConditionGenerator.h" +#include "OGSError.h" +#include "StrictDoubleValidator.h" + +CondFromRasterDialog::CondFromRasterDialog(const std::map<std::string, MeshLib::CFEMesh*> &msh_map, QDialog* parent) + : QDialog(parent), _msh_map(msh_map) +{ + setupUi(this); + + this->scalingEdit->setEnabled(false); + _scale_validator = new StrictDoubleValidator(-1e+10, 1e+20, 5); + this->scalingEdit->setText("1.0"); + this->scalingEdit->setValidator (_scale_validator); + + for (std::map<std::string, MeshLib::CFEMesh*>::const_iterator it = _msh_map.begin(); + it != _msh_map.end(); ++it) + this->meshBox->addItem(QString::fromStdString(it->first)); + + this->directButton->setChecked(true); +} + +CondFromRasterDialog::~CondFromRasterDialog() +{ + delete _scale_validator; +} + +void CondFromRasterDialog::on_selectButton_pressed() +{ + QSettings settings("UFZ", "OpenGeoSys-5"); +#ifdef libgeotiff_FOUND + QString geotiffExtension(" *.tif"); +#else + QString geotiffExtension(""); +#endif + QString fileName = QFileDialog::getOpenFileName(this, "Select raster file", + settings.value("lastOpenedConditionsFileDirectory").toString(), QString( + "Raster files (*.asc *.grd);;") .arg(geotiffExtension)); + + if (!fileName.isEmpty()) + { + this->rasterEdit->setText(fileName); + + QDir dir = QDir(fileName); + settings.setValue("lastOpenedConditionsFileDirectory", dir.absolutePath()); + } +} + + +void CondFromRasterDialog::accept() +{ + std::string mesh_name (this->meshBox->currentText().toStdString()); + std::string raster_name (this->rasterEdit->text().toStdString()); + double scaling_factor = strtod(this->scalingEdit->text().toStdString().c_str(), 0); + std::vector< std::pair<size_t,double> > direct_values; + + if (mesh_name.empty()) + { + OGSError::box("No mesh selected."); + return; + } + if (raster_name.empty()) + { + OGSError::box("No raster selected."); + return; + } + + const MeshLib::CFEMesh* mesh = (_msh_map.find(mesh_name))->second; + //std::string direct_node_name(raster_name + ".txt"); + + if (this->directButton->isChecked()) + { + DirectConditionGenerator dcg; + direct_values = dcg.directToSurfaceNodes(*mesh, raster_name); + //dcg.writeToFile(direct_node_name); + } + else + { + if (scaling_factor <= 0) + { + OGSError::box("No valid scaling factor given."); + return; + } + MeshLib::CFEMesh* new_mesh = const_cast<MeshLib::CFEMesh*>(mesh); + DirectConditionGenerator dcg; + direct_values = dcg.directWithSurfaceIntegration(*new_mesh, raster_name, scaling_factor); + //dcg.writeToFile(direct_node_name); + } + //emit directNodesWritten(direct_node_name); + emit transmitDisValues(direct_values); + this->done(QDialog::Accepted); +} + +void CondFromRasterDialog::reject() +{ + this->done(QDialog::Rejected); +} + +void CondFromRasterDialog::on_integrateButton_toggled(bool isSelected) +{ + this->scalingEdit->setEnabled(isSelected); +} \ No newline at end of file diff --git a/DataView/CondFromRasterDialog.h b/DataView/CondFromRasterDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..0537113915df691b4529de2cc545babd799a1020 --- /dev/null +++ b/DataView/CondFromRasterDialog.h @@ -0,0 +1,47 @@ +/** + * \file CondFromRasterDialog.h + * 2012/01/04 KR Initial implementation + */ + +#ifndef CONDFROMRASTERDIALOG_H +#define CONDFROMRASTERDIALOG_H + +#include "ui_CondFromRaster.h" +#include <QDialog> + +#include "ProjectData.h" +#include "GridAdapter.h" + +class StrictDoubleValidator; + +/** + * \brief A dialog window for creating DIRECT boundary conditions from raster files + */ +class CondFromRasterDialog : public QDialog, private Ui_CondFromRaster +{ + Q_OBJECT + +public: + CondFromRasterDialog(const std::map<std::string, MeshLib::CFEMesh*> &msh_map, QDialog* parent = 0); + ~CondFromRasterDialog(void); + +private: + const std::map<std::string, MeshLib::CFEMesh*> _msh_map; + StrictDoubleValidator* _scale_validator; + +private slots: + void on_integrateButton_toggled(bool isSelected); + void on_selectButton_pressed(); + + /// Instructions if the OK-Button has been pressed. + void accept(); + + /// Instructions if the Cancel-Button has been pressed. + void reject(); + +signals: + void directNodesWritten(std::string); + void transmitDisValues(std::vector< std::pair<size_t,double> >); +}; + +#endif //CONDFROMRASTERDIALOG_H diff --git a/DataView/CondObjectListItem.h b/DataView/CondObjectListItem.h index 7f4934de393afccb30fc29ade99133fce0fe1da6..4ab7b837428804e9353b3cc74ef1830017d5d846 100644 --- a/DataView/CondObjectListItem.h +++ b/DataView/CondObjectListItem.h @@ -28,13 +28,14 @@ public: /// Constructor for the TreeItem specifying FEM Conditions. CondObjectListItem(const QList<QVariant> &data, TreeItem* parent, - const FEMCondition::CondType type, + FEMCondition* cond, const std::vector<GEOLIB::Point*>* points) - : TreeItem(data, parent), _vtkSource(VtkConditionSource::New()), _type(type), + : TreeItem(data, parent), _vtkSource(VtkConditionSource::New()), _type(cond->getCondType()), _cond_vec(new std::vector<FEMCondition*>) { + _cond_vec->push_back(cond); QString display_name = parent->data(0).toString().append(" - ").append( - QString::fromStdString(FEMCondition::condTypeToString(type))); + QString::fromStdString(FEMCondition::condTypeToString(_type))); static_cast<VtkConditionSource*>(_vtkSource)->setData( points, _cond_vec); static_cast<VtkConditionSource*>(_vtkSource)->SetName( display_name ); } diff --git a/DataView/ConditionWriter.ui b/DataView/ConditionWriter.ui new file mode 100644 index 0000000000000000000000000000000000000000..a7bd5995c644de73773b2ae1a59c3995c96f2706 --- /dev/null +++ b/DataView/ConditionWriter.ui @@ -0,0 +1,143 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ConditionWriter</class> + <widget class="QDialog" name="ConditionWriter"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>203</height> + </rect> + </property> + <property name="windowTitle"> + <string>Save FEM Conditions...</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <widget class="QLabel" name="geoLabel"> + <property name="text"> + <string>Geometry</string> + </property> + <property name="margin"> + <number>10</number> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="condTypeLabel"> + <property name="text"> + <string>Condition Type</string> + </property> + <property name="margin"> + <number>10</number> + </property> + </widget> + </item> + <item row="1" column="2" colspan="2"> + <widget class="QComboBox" name="geoBox"> + <item> + <property name="text"> + <string>All (XML files only)</string> + </property> + </item> + </widget> + </item> + <item row="2" column="2" colspan="2"> + <widget class="QComboBox" name="condTypeBox"> + <item> + <property name="text"> + <string>All (XML files only)</string> + </property> + </item> + <item> + <property name="text"> + <string>Boundary Conditions</string> + </property> + </item> + <item> + <property name="text"> + <string>Initial Conditions</string> + </property> + </item> + <item> + <property name="text"> + <string>Source Terms</string> + </property> + </item> + </widget> + </item> + <item row="4" column="2" colspan="2"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="fileNameLabel"> + <property name="text"> + <string>Filename</string> + </property> + <property name="margin"> + <number>10</number> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="QLineEdit" name="fileNameEdit"/> + </item> + <item row="3" column="3"> + <widget class="QPushButton" name="fileNameButton"> + <property name="maximumSize"> + <size> + <width>30</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>ConditionWriter</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>ConditionWriter</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/DataView/ConditionWriterDialog.cpp b/DataView/ConditionWriterDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3480132224faba04295bbb20e0cc84133233c75c --- /dev/null +++ b/DataView/ConditionWriterDialog.cpp @@ -0,0 +1,95 @@ +/** + * \file ConditionWriterDialog.cpp + * 2012/01/11 KR Initial implementation + */ + +#include "ConditionWriterDialog.h" +#include "FEMCondition.h" +#include "OGSError.h" + +#include <QFileDialog> +#include <QFileInfo> +#include <QSettings> + +ConditionWriterDialog::ConditionWriterDialog(const GEOLIB::GEOObjects *geo_objects, QDialog* parent) + : QDialog(parent) +{ + setupUi(this); + + std::vector<std::string> geo_names; + geo_objects->getGeometryNames(geo_names); + + for (size_t i=0; i<geo_names.size(); i++) + this->geoBox->addItem(QString::fromStdString(geo_names[i])); + +} + +ConditionWriterDialog::~ConditionWriterDialog() +{ +} + +void ConditionWriterDialog::on_fileNameButton_pressed() +{ + QString filetypes(""); + int geo_idx = this->geoBox->currentIndex(); + int cnd_idx = this->condTypeBox->currentIndex(); + if ((geo_idx == 0) || (cnd_idx == 0)) filetypes = "OpenGeoSys FEM Condition file (*.cnd)"; + else if ((geo_idx != 0) && (cnd_idx == 1)) filetypes = "OpenGeoSys FEM Condition file (*.cnd);;GeoSys Boundary Condition (*.bc)"; + else if ((geo_idx != 0) && (cnd_idx == 2)) filetypes = "OpenGeoSys FEM Condition file (*.cnd);;GeoSys Initial Condition (*.ic)"; + else if ((geo_idx != 0) && (cnd_idx == 3)) filetypes = "OpenGeoSys FEM Condition file (*.cnd);;GeoSys Source Condition (*.st)"; + + QSettings settings("UFZ", "OpenGeoSys-5"); + QString fileName = QFileDialog::getSaveFileName(this, "Select path", + settings.value("lastOpenedConditionsFileDirectory").toString(), filetypes); + + if (!fileName.isEmpty()) + { + this->fileNameEdit->setText(fileName); + + QDir dir = QDir(fileName); + settings.setValue("lastOpenedConditionsFileDirectory", dir.absolutePath()); + } +} + + +void ConditionWriterDialog::accept() +{ + const QString file_name = this->fileNameEdit->text(); + QFileInfo fi(file_name); + + if ((fi.suffix().toLower().compare("cnd") != 0) && + ((this->geoBox->currentIndex()==0) || (this->condTypeBox->currentIndex()==0))) + { + OGSError::box("Multiple geometries or multiple types of conditions\ncan only be saved to *.cnd files.","Inconsistent selection of parameters"); + } + else + { + QString geo_name = this->geoBox->currentText(); + if (this->geoBox->currentIndex() == 0) geo_name = ""; + + FEMCondition::CondType cond_type(FEMCondition::UNSPECIFIED);; + switch (this->condTypeBox->currentIndex()) + { + case 0: + cond_type = FEMCondition::UNSPECIFIED; break; + case 1: + cond_type = FEMCondition::BOUNDARY_CONDITION; break; + case 2: + cond_type = FEMCondition::INITIAL_CONDITION; break; + case 3: + cond_type = FEMCondition::SOURCE_TERM; break; + default: + std::cout << "Error in ConditionWriterDialog..." << std::endl; + } + + emit saveFEMConditionsRequested(geo_name, cond_type, file_name); + + this->done(QDialog::Accepted); + } +} + +void ConditionWriterDialog::reject() +{ + this->done(QDialog::Rejected); +} + diff --git a/DataView/ConditionWriterDialog.h b/DataView/ConditionWriterDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..399ee350dcf7c7687eb71983ec5ac76b68305d29 --- /dev/null +++ b/DataView/ConditionWriterDialog.h @@ -0,0 +1,40 @@ +/** + * \file ConditionWriterDialog.h + * 2012/01/11 KR Initial implementation + */ + +#ifndef CONDITIONWRITERDIALOG_H +#define CONDITIONWRITERDIALOG_H + +#include "ui_ConditionWriter.h" +#include <QDialog> + +#include "GEOObjects.h" +#include "FEMCondition.h" + +/** + * \brief A dialog window for creating DIRECT boundary conditions from raster files + */ +class ConditionWriterDialog : public QDialog, private Ui_ConditionWriter +{ + Q_OBJECT + +public: + ConditionWriterDialog(const GEOLIB::GEOObjects* geoObjects, QDialog* parent = 0); + ~ConditionWriterDialog(void); + +private slots: + void on_fileNameButton_pressed(); + + /// Instructions if the OK-Button has been pressed. + void accept(); + + /// Instructions if the Cancel-Button has been pressed. + void reject(); + +signals: + void saveFEMConditionsRequested(const QString&, const FEMCondition::CondType, const QString&); + +}; + +#endif //CONDITIONWRITERDIALOG_H diff --git a/DataView/DataView.cpp b/DataView/DataView.cpp index c12bc332e3031390d925abdb26c5ff0191003a25..c1802a5551b084bb91a9a4a3953b2edbf7133853 100644 --- a/DataView/DataView.cpp +++ b/DataView/DataView.cpp @@ -22,6 +22,7 @@ #include <QSettings> #include "MeshIO/OGSMeshIO.h" +#include "Writer.h" // necessary to avoid Linker Error in Windows DataView::DataView( QWidget* parent /*= 0*/ ) : QTreeView(parent) @@ -49,7 +50,8 @@ void DataView::addMeshAction() if (!fileName.isEmpty()) { std::string name = fileName.toStdString(); - MeshLib::CFEMesh* msh = FileIO::OGSMeshIO::loadMeshFromFile(name); + FileIO::OGSMeshIO meshIO; + MeshLib::CFEMesh* msh = meshIO.loadMeshFromFile(name); if (msh) static_cast<MshModel*>(this->model())->addMesh(msh, name); } @@ -80,13 +82,17 @@ void DataView::contextMenuEvent( QContextMenuEvent* event ) QAction* checkMeshAction = menu.addAction("Check mesh quality..."); QAction* saveMeshAction = menu.addAction("Save mesh..."); menu.addSeparator(); - QAction* directSTAction = menu.addAction("Load DIRECT source terms..."); + QMenu direct_cond_menu("DIRECT Conditions"); + menu.addMenu(&direct_cond_menu); + QAction* addDirectAction = direct_cond_menu.addAction("Add..."); + QAction* loadDirectAction = direct_cond_menu.addAction("Load..."); menu.addSeparator(); QAction* removeMeshAction = menu.addAction("Remove mesh"); connect(editMeshAction, SIGNAL(triggered()), this, SLOT(openMshEditDialog())); connect(checkMeshAction, SIGNAL(triggered()), this, SLOT(checkMeshQuality())); connect(saveMeshAction, SIGNAL(triggered()), this, SLOT(writeMeshToFile())); - connect(directSTAction, SIGNAL(triggered()), this, SLOT(loadDIRECTSourceTerms())); + connect(addDirectAction, SIGNAL(triggered()), this, SLOT(addDIRECTSourceTerms())); + connect(loadDirectAction, SIGNAL(triggered()), this, SLOT(loadDIRECTSourceTerms())); connect(removeMeshAction, SIGNAL(triggered()), this, SLOT(removeMesh())); menu.exec(event->globalPos()); } @@ -100,10 +106,8 @@ void DataView::openMshEditDialog() static_cast<MshModel*>(this->model())->getMesh(index)->getCFEMesh(); MshEditDialog meshEdit(mesh); - connect(&meshEdit, - SIGNAL(mshEditFinished(MeshLib::CFEMesh *, - std::string &)), model, - SLOT(addMesh(MeshLib::CFEMesh *, std::string &))); + connect(&meshEdit, SIGNAL(mshEditFinished(MeshLib::CFEMesh*, std::string &)), + model, SLOT(addMesh(MeshLib::CFEMesh*, std::string &))); meshEdit.exec(); } @@ -118,23 +122,18 @@ int DataView::writeMeshToFile() const QSettings settings("UFZ", "OpenGeoSys-5"); QString mshName = QString::fromStdString( static_cast<MshModel*>(this->model())->getMesh(index)->getName()); - std::string fileName = QFileDialog::getSaveFileName(NULL, "Save mesh as", - settings.value("lastOpenedFileDirectory").toString(), - "GeoSys mesh file (*.msh)").toStdString(); + QString fileName = QFileDialog::getSaveFileName(NULL, "Save mesh as", + settings.value("lastOpenedMeshFileDirectory").toString(), + "GeoSys mesh file (*.msh)"); - if (!fileName.empty()) + if (!fileName.isEmpty()) { - std::ofstream out (fileName.c_str()); - if (out.is_open()) - { - FileIO::OGSMeshIO::write (mesh, out); - out.close(); - return 1; - } - else - std::cout << - "MshTabWidget::saveMeshFile() - Could not create file..." << - std::endl; + FileIO::OGSMeshIO meshIO; + meshIO.setMesh(mesh); + meshIO.writeToFile(fileName.toStdString().c_str()); + QDir dir = QDir(fileName); + settings.setValue("lastOpenedMeshFileDirectory", dir.absolutePath()); + return 1; } else OGSError::box("No file name entered."); @@ -142,6 +141,14 @@ int DataView::writeMeshToFile() const return 0; } +void DataView::addDIRECTSourceTerms() +{ + QModelIndex index = this->selectionModel()->currentIndex(); + const GridAdapter* grid = static_cast<MshModel*>(this->model())->getMesh(index); + emit requestCondSetupDialog(grid->getName(), GEOLIB::INVALID, 0, false); +} + + void DataView::loadDIRECTSourceTerms() { QModelIndex index = this->selectionModel()->currentIndex(); diff --git a/DataView/DataView.h b/DataView/DataView.h index d4529b4a2c8104a37ad2479b2ff4586bab20ff2a..215320a91dc81d9c254802c8bfcade4a26d55ac3 100644 --- a/DataView/DataView.h +++ b/DataView/DataView.h @@ -6,6 +6,7 @@ #define DATAVIEW_H #include "Point.h" +#include "GeoType.h" #include <QTreeView> class GridAdapter; @@ -57,6 +58,8 @@ private slots: /// Adds a new mesh. void addMeshAction(); + void addDIRECTSourceTerms(); + void loadDIRECTSourceTerms(); /// Remove the currently selected mesh. @@ -75,6 +78,7 @@ private slots: signals: void qualityCheckRequested(VtkMeshSource*); + void requestCondSetupDialog(const std::string&, const GEOLIB::GEOTYPE, const size_t, bool on_points); void requestMeshRemoval(const QModelIndex&); void requestDIRECTSourceTerms(const std::string, const std::vector<GEOLIB::Point*>*); void saveMeshAction(); diff --git a/DataView/DatabaseConnection.cpp b/DataView/DatabaseConnection.cpp index 77ff0c5d8309d433947cdcebdc06154f0f62f07d..73cd556317a8073283658c8f9d42795f4530b3fb 100644 --- a/DataView/DatabaseConnection.cpp +++ b/DataView/DatabaseConnection.cpp @@ -173,22 +173,11 @@ bool DatabaseConnection::isConnected() } /** - * Loads a list of stations with a random colour + * Loads a list of stations. * \param listID The ID of the list that is requested * \return 1 if there were no errors, 0 and an error message otherwise. */ -int DatabaseConnection::loadStationList(const int &listID) -{ - return loadStationList(listID, GEOLIB::getRandomColor()); -} - -/** - * Loads a list of stations with a specified colour - * \param listID The ID of the list that is requested - * \param color The colour which will be assigned to the objects in the list - * \return 1 if there were no errors, 0 and an error message otherwise. - */ -int DatabaseConnection::loadStationList(int listID, const GEOLIB::Color* const color) +int DatabaseConnection::loadStationList(int listID) { if (_db.open()) { @@ -249,7 +238,7 @@ int DatabaseConnection::loadStationList(int listID, const GEOLIB::Color* const c stnQuery.value(2).toDouble(), stnQuery.value(3).toDouble(), stnQuery.value(4).toDouble()); - newStation->setColor(color); + stations->push_back(newStation); } @@ -259,7 +248,7 @@ int DatabaseConnection::loadStationList(int listID, const GEOLIB::Color* const c std::string temp_name (listName.toStdString()); if (!stations->empty()) - _geoObjects->addStationVec(stations, temp_name, color); + _geoObjects->addStationVec(stations, temp_name); _db.close(); //emit listLoaded(listName); diff --git a/DataView/DatabaseConnection.h b/DataView/DatabaseConnection.h index 4ca9409e70b3ace13d045856cb18065e8f687a99..06728a899bbba255cdb6d699f1fa689b1b4d8a3d 100644 --- a/DataView/DatabaseConnection.h +++ b/DataView/DatabaseConnection.h @@ -36,7 +36,6 @@ public: int getStationID(const int &listID, const double &x, const double &y); void getListSelection(); bool isConnected(); - int loadStationList(int listID, const GEOLIB::Color* const color); int loadValues(const int &listID, const int &stationID, const QDateTime &startDate, @@ -50,7 +49,7 @@ public slots: QString dbname, QString user, QString pass); - int loadStationList(const int &listID); + int loadStationList(int listID); int setConnection(QString protocol, QString hostname, QString dbname, diff --git a/DataView/DiagramView/CMakeLists.txt b/DataView/DiagramView/CMakeLists.txt index 03169b83987416dc1c9d876bf6e211c36bc4801b..a7f258c7ccc55968bfce55840349a64d89faf440 100644 --- a/DataView/DiagramView/CMakeLists.txt +++ b/DataView/DiagramView/CMakeLists.txt @@ -39,15 +39,14 @@ qt4_wrap_cpp( MOC_SOURCES ${MOC_HEADERS} ) # Include the headers which are generated by uic and moc # and include additional header include_directories( - . + ${CMAKE_SOURCE_DIR}/Qt/DataView/DiagramView ${CMAKE_BINARY_DIR}/Qt/DataView/DiagramView ${CMAKE_BINARY_DIR}/Qt/DataView - ../../../Base - ../../../GEO - ../../Base - ../../DataView - ../../../MathLib - ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/Base + ${CMAKE_SOURCE_DIR}/GEO + ${CMAKE_SOURCE_DIR}/Qt/Base + ${CMAKE_SOURCE_DIR}/Qt/DataView + ${CMAKE_SOURCE_DIR}/MathLib ) # Put moc files in a project folder diff --git a/DataView/DirectConditionGenerator.cpp b/DataView/DirectConditionGenerator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0c95548a28898212984daa99bdbfe012b309ca7 --- /dev/null +++ b/DataView/DirectConditionGenerator.cpp @@ -0,0 +1,157 @@ +/** + * \file DirectConditionGenerator.cpp + * 2012/01/04 KR Initial implementation + * + */ + +#include "DirectConditionGenerator.h" + +#include "VtkRaster.h" +#include "MshEditor.h" +#include "PointWithID.h" + +#include "fem_ele.h" + +const std::vector< std::pair<size_t,double> >& DirectConditionGenerator::directToSurfaceNodes(const MeshLib::CFEMesh &mesh, const std::string &filename) +{ + if (_direct_values.empty()) + { + double origin_x(0), origin_y(0), delta(0); + size_t imgwidth(0), imgheight(0); + + float* img = VtkRaster::loadDataFromASC(filename, origin_x, origin_y, imgwidth, imgheight, delta); + + const std::vector<GEOLIB::PointWithID*> surface_nodes ( MshEditor::getSurfaceNodes(mesh) ); + //std::vector<MeshLib::CNode*> nodes = mesh.nod_vector; + const size_t nNodes(surface_nodes.size()); + _direct_values.reserve(nNodes); + for (size_t i=0; i<nNodes; i++) + { + const double* coords (surface_nodes[i]->getData()); + + if (coords[0]>=origin_x && coords[0]<(origin_x+(delta*imgwidth)) && coords[1]>=origin_y && coords[1]<(origin_y+(delta*imgheight))) + { + int cell_x = static_cast<int>(floor((coords[0] - origin_x)/delta)); + int cell_y = static_cast<int>(floor((coords[1] - origin_y)/delta)); + + // if node outside of raster use raster boundary values + cell_x = (cell_x < 0) ? 0 : ((static_cast<size_t>(cell_x) > imgwidth) ? (imgwidth-1) : cell_x); + cell_y = (cell_y < 0) ? 0 : ((static_cast<size_t>(cell_y) > imgheight) ? (imgheight-1) : cell_y); + + size_t index = cell_y*imgwidth+cell_x; + if (fabs(img[index] + 9999) > std::numeric_limits<float>::min()) + _direct_values.push_back( std::pair<size_t, double>(surface_nodes[i]->getID(),img[index]) ); + } + } + + delete[] img; + + } + else + std::cout << "Error in DirectConditionGenerator::directToSurfaceNodes() - Data vector contains outdated values..." << std::endl; + + return _direct_values; +} + + +const std::vector< std::pair<size_t,double> >& DirectConditionGenerator::directWithSurfaceIntegration(MeshLib::CFEMesh &mesh, const std::string &filename, double scaling) +{ + double no_data_value (-9999); // TODO: get this from asc-reader! + + if (_direct_values.empty()) + { + mesh.MarkInterface_mHM_Hydro_3D(); // mark element faces on the surface + + double origin_x(0), origin_y(0), delta(0); + size_t imgwidth(0), imgheight(0); + double node_val[8] = {0,0,0,0,0,0,0,0}; // maximum possible number of nodes per face (just in case ...) + + FiniteElement::CElement* fem ( new FiniteElement::CElement(mesh.GetCoordinateFlag()) ); + + float* img; + if (filename.substr(filename.length()-3,3).compare("asc") == 0) + img = VtkRaster::loadDataFromASC(filename, origin_x, origin_y, imgwidth, imgheight, delta); + else if (filename.substr(filename.length()-3,3).compare("grd") == 0) + img = VtkRaster::loadDataFromSurfer(filename, origin_x, origin_y, imgwidth, imgheight, delta); + + const size_t nNodes(mesh.nod_vector.size()); + std::vector<double> val(nNodes, 0.0); + for(size_t i = 0; i < nNodes; i++) + mesh.nod_vector[i]->SetMark(false); + + // copied from CFEMesh::Precipitation2NeumannBC() by WW + size_t nFaces = mesh.face_vector.size(); + for(size_t i=0; i<nFaces; i++) + { + MeshLib::CElem* elem = mesh.face_vector[i]; + if (!elem->GetMark()) + continue; + + // if face is on the surface of the mesh + size_t nElemNodes = elem->GetNodesNumber(false); + for(size_t k=0; k<nElemNodes; k++) + node_val[k] = 0.0; + + // get values from the raster for all nodes of the face + for(size_t k=0; k<nElemNodes; k++) + { + double const* const pnt_k (elem->GetNode(k)->getData()); + int cell_x = static_cast<int>(floor((pnt_k[0] - origin_x) / delta)); + int cell_y = static_cast<int>(floor((pnt_k[1] - origin_y) / delta)); + + // if node outside of raster use raster boundary values + cell_x = (cell_x < 0) ? 0 : ((static_cast<size_t>(cell_x) > imgwidth) ? (imgwidth-1) : cell_x); + cell_y = (cell_y < 0) ? 0 : ((static_cast<size_t>(cell_y) > imgheight) ? (imgheight-1) : cell_y); + + node_val[k] = img[cell_y * imgwidth + cell_x]; + if (fabs(node_val[k] - no_data_value) < std::numeric_limits<double>::min()) + node_val[k] = 0.; + } + + // get area of the surface element face + elem->ComputeVolume(); + + // do the actual surface integration + fem->setOrder(mesh.getOrder() + 1); + fem->ConfigElement(elem); + fem->FaceIntegration(node_val); + + // add up the integrated values (nodes get values added for all faces they are part of) + for(size_t k=0; k<elem->GetNodesNumber(false); k++) + { + MeshLib::CNode* node = elem->GetNode(k); + node->SetMark(true); + val[node->GetIndex()] += node_val[k]; + } + } + + _direct_values.reserve(nNodes); + for(size_t k=0; k<nNodes; k++) + { + if (!mesh.nod_vector[k]->GetMark()) + continue; + // Assuming the unit of precipitation is mm/day + _direct_values.push_back( std::pair<size_t, double>(k, val[k] / scaling) ); + } + } + else + std::cout << "Error in DirectConditionGenerator::directWithSurfaceIntegration() - Data vector contains outdated values..." << std::endl; + + return _direct_values; +} + + +int DirectConditionGenerator::writeToFile(const std::string &name) const +{ + std::ofstream out( name.c_str(), std::ios::out ); + + if (out) + { + for (std::vector< std::pair<size_t,double> >::const_iterator it = _direct_values.begin(); it != _direct_values.end(); ++it) + out << it->first << "\t" << it->second << std::endl; + + out.close(); + } + return 0; +} + diff --git a/DataView/DirectConditionGenerator.h b/DataView/DirectConditionGenerator.h new file mode 100644 index 0000000000000000000000000000000000000000..e1839d73b324382360a189150723ab95cfbb8ff8 --- /dev/null +++ b/DataView/DirectConditionGenerator.h @@ -0,0 +1,30 @@ +/** + * \file DirectConditionGenerator.h + * 2012/01/04 KR Initial implementation + * + */ + +#ifndef DIRECTCONDITIONGENERATOR_H +#define DIRECTCONDITIONGENERATOR_H + +#include "msh_mesh.h" + +class DirectConditionGenerator +{ +public: + DirectConditionGenerator() {}; + ~DirectConditionGenerator() {}; + + const std::vector< std::pair<size_t,double> >& directToSurfaceNodes(const MeshLib::CFEMesh &mesh, const std::string &filename); + + const std::vector< std::pair<size_t,double> >& directWithSurfaceIntegration(MeshLib::CFEMesh &mesh, const std::string &filename, double scaling); + + int writeToFile(const std::string &name) const; + +private: + std::vector< std::pair<size_t,double> > _direct_values; + +}; + +#endif // DIRECTCONDITIONGENERATOR_H + diff --git a/DataView/ElementTreeModel.cpp b/DataView/ElementTreeModel.cpp index 9abe05670b53105883e595f9b5908fd106be439e..3b73f842ee06333131aa6749952c43dd570cdc14 100644 --- a/DataView/ElementTreeModel.cpp +++ b/DataView/ElementTreeModel.cpp @@ -54,13 +54,14 @@ void ElementTreeModel::setElement(const GridAdapter* grid, const size_t elem_ind TreeItem* nodeListItem = new TreeItem(nodeListData, elemItem); elemItem->appendChild(nodeListItem); - const std::vector<GEOLIB::Point*>* nodes = grid->getNodes(); + const std::vector<GEOLIB::Point*>* nodes_vec = grid->getNodes(); for (size_t i = 0; i < elem->nodes.size(); i++) { + const GEOLIB::Point* pnt = (*nodes_vec)[elem->nodes[i]]; QList<QVariant> nodeData; nodeData << "Node " + QString::number(elem->nodes[i]) << - QString::number((*(*nodes)[i])[0]) << QString::number((*(*nodes)[i])[1]) << - QString::number((*(*nodes)[i])[2]); + QString::number((*pnt)[0]) << QString::number((*pnt)[1]) << + QString::number((*pnt)[2]); TreeItem* nodeItem = new TreeItem(nodeData, nodeListItem); nodeListItem->appendChild(nodeItem); } diff --git a/DataView/FEMConditionSetup.ui b/DataView/FEMConditionSetup.ui index fbc20c328bdcf93c318c05da85cd7129c829d6ad..32c1e35e95008d8d90361c40bbf3d4c8eec0e917 100644 --- a/DataView/FEMConditionSetup.ui +++ b/DataView/FEMConditionSetup.ui @@ -15,7 +15,7 @@ </property> <layout class="QGridLayout" name="gridLayout"> <item row="1" column="0"> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="processTypeLabel"> <property name="text"> <string>Process Type</string> </property> @@ -25,7 +25,7 @@ </widget> </item> <item row="4" column="0"> - <widget class="QLabel" name="label_3"> + <widget class="QLabel" name="disTypeLabel"> <property name="text"> <string>Distribution Type</string> </property> @@ -35,7 +35,7 @@ </widget> </item> <item row="5" column="0"> - <widget class="QLabel" name="label_4"> + <widget class="QLabel" name="valueLabel"> <property name="text"> <string>Value</string> </property> @@ -48,16 +48,10 @@ <widget class="QComboBox" name="processTypeBox"/> </item> <item row="4" column="1"> - <widget class="QComboBox" name="disTypeBox"> - <item> - <property name="text"> - <string>Constant (Direchlet)</string> - </property> - </item> - </widget> + <widget class="QComboBox" name="disTypeBox"/> </item> <item row="3" column="0"> - <widget class="QLabel" name="label_5"> + <widget class="QLabel" name="pvTypeLabel"> <property name="text"> <string>Primary Variable</string> </property> @@ -96,7 +90,7 @@ </spacer> </item> <item row="2" column="0"> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="condTypeLabel"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> diff --git a/DataView/FEMConditionSetupDialog.cpp b/DataView/FEMConditionSetupDialog.cpp index 7bcb2b35988f5cd0998dbd78ee4a95bfd2741830..e2759021119210cf1c94b9ebfec197ec89685950 100644 --- a/DataView/FEMConditionSetupDialog.cpp +++ b/DataView/FEMConditionSetupDialog.cpp @@ -8,6 +8,9 @@ #include "FEMEnums.h" #include "ProjectData.h" #include "StrictDoubleValidator.h" +#include "StringTools.h" +#include "LinearEditDialog.h" +#include "CondFromRasterDialog.h" #include "BoundaryCondition.h" #include "InitialCondition.h" @@ -17,46 +20,76 @@ FEMConditionSetupDialog::FEMConditionSetupDialog(const std::string &associated_g const GEOLIB::GEOTYPE type, const std::string &geo_name, const GEOLIB::GeoObject* const geo_object, + bool on_points, QDialog* parent) -: QDialog(parent), _cond(associated_geometry, FEMCondition::UNSPECIFIED), _secondValueEdit(NULL), - _first_value_validator(NULL), _second_value_validator(NULL) +: QDialog(parent), _cond(associated_geometry, FEMCondition::UNSPECIFIED), _set_on_points(on_points), + _combobox(NULL), directButton(NULL), _mesh(NULL), _first_value_validator(NULL) { _cond.setGeoType(type); _cond.setGeoName(geo_name); _cond.setGeoObj(geo_object); setupUi(this); - setupDialog(); +} - +FEMConditionSetupDialog::FEMConditionSetupDialog(const FEMCondition &cond, QDialog* parent) + : QDialog(parent), _cond(cond), _set_on_points(false), _combobox(NULL), directButton(NULL), + _mesh(NULL), _first_value_validator(NULL) +{ + setupUi(this); + setupDialog(); + setValuesFromCond(); } -FEMConditionSetupDialog::FEMConditionSetupDialog(FEMCondition &cond, QDialog* parent) - : QDialog(parent), _cond(cond), _secondValueEdit(NULL), - _first_value_validator(NULL), _second_value_validator(NULL) +FEMConditionSetupDialog::FEMConditionSetupDialog(const std::string &name, const MeshLib::CFEMesh* mesh, QDialog* parent) +: QDialog(parent), _cond(name, FEMCondition::UNSPECIFIED), _set_on_points(false), _combobox(NULL), directButton(NULL), + _mesh(mesh), _first_value_validator(NULL) { + _cond.setGeoType(GEOLIB::INVALID); + _cond.setGeoName(name); + _cond.setGeoObj(NULL); + + setupUi(this); setupDialog(); } FEMConditionSetupDialog::~FEMConditionSetupDialog() { - delete _secondValueEdit; + delete _combobox; + delete directButton; delete _first_value_validator; - delete _second_value_validator; } void FEMConditionSetupDialog::setupDialog() { - if (_cond.getGeoType() == GEOLIB::POLYLINE) + if (_cond.getGeoType() != GEOLIB::INVALID) { - this->disTypeBox->addItem("Linear (Direchlet)"); - //this->disTypeBox->addItem("Linear (Neumann)"); + this->disTypeBox->addItem("Constant (Direchlet)"); + if (_cond.getGeoType() == GEOLIB::POLYLINE) + this->disTypeBox->addItem("Linear (Direchlet)"); + + if (this->_set_on_points) + { + _combobox = new QComboBox; + _combobox->addItem("Elevation"); + static_cast<QGridLayout*>(this->layout())->addWidget(_combobox,5,1) ; + } + else + { + _first_value_validator = new StrictDoubleValidator(-1e+10, 1e+10, 5); + this->firstValueEdit->setText("0"); + this->firstValueEdit->setValidator (_first_value_validator); + } + } + else // direct on mesh + { + this->disTypeBox->addItem("Direct"); + //static_cast<QGridLayout*>(this->layout())->removeWidget(this->firstValueEdit); + directButton = new QPushButton("Calculate Values"); + static_cast<QGridLayout*>(this->layout())->addWidget(directButton,5,1); + connect(this->directButton, SIGNAL(pressed()), this, SLOT(directButton_pressed())); } - _first_value_validator = new StrictDoubleValidator(-1e+10, 1e+10, 5); - _second_value_validator = new StrictDoubleValidator(-1e+10, 1e+10, 5); - this->firstValueEdit->setText("0"); - this->firstValueEdit->setValidator (_first_value_validator); const std::list<std::string> process_names = FiniteElement::getAllProcessNames(); for (std::list<std::string>::const_iterator it = process_names.begin(); it != process_names.end(); ++it) @@ -72,47 +105,89 @@ void FEMConditionSetupDialog::setupDialog() */ } +void FEMConditionSetupDialog::setValuesFromCond() +{ + QString pcs_type = QString::fromStdString(FiniteElement::convertProcessTypeToString(_cond.getProcessType())); + this->processTypeBox->setCurrentIndex(this->processTypeBox->findText(pcs_type)); + + QString pv_type = QString::fromStdString(FiniteElement::convertPrimaryVariableToString(_cond.getProcessPrimaryVariable())); + this->pvTypeBox->setCurrentIndex(this->pvTypeBox->findText(pv_type)); + + int idx(0); + if (_cond.getCondType() == FEMCondition::INITIAL_CONDITION) + this->condTypeBox->setCurrentIndex(1); + else if (_cond.getCondType() == FEMCondition::SOURCE_TERM) + { + this->condTypeBox->setCurrentIndex(2); + on_condTypeBox_currentIndexChanged(2); + } + + if (_cond.getGeoType() != GEOLIB::INVALID) + { + if (_cond.getProcessDistributionType() == FiniteElement::CONSTANT || _cond.getProcessDistributionType() == FiniteElement::CONSTANT_NEUMANN) + { + this->disTypeBox->setCurrentIndex(0); + this->firstValueEdit->setText(QString::number(_cond.getDisValues()[0])); + } + else + { + this->disTypeBox->setCurrentIndex(1); + directButton = new QPushButton(QString::number(static_cast<int>(_cond.getDisValues().size())) + " values"); + } + } + else // direct on mesh + { + size_t nValues (_cond.getDisValues().size()); + this->directButton->setText(QString::number(static_cast<int>(_cond.getDisValues().size())) + " values"); + } +} + + void FEMConditionSetupDialog::accept() { _cond.setProcessType(static_cast<FiniteElement::ProcessType>(this->processTypeBox->currentIndex() + 1)); _cond.setProcessPrimaryVariable(static_cast<FiniteElement::PrimaryVariable>(this->pvTypeBox->currentIndex() + 1)); - QString dis_type_text = this->disTypeBox->currentText(); - if (condTypeBox->currentIndex()>1) + if (_cond.getGeoType() != GEOLIB::INVALID) { - if (this->disTypeBox->currentIndex()>0) - _cond.setProcessDistributionType(FiniteElement::LINEAR_NEUMANN); - else - _cond.setProcessDistributionType(FiniteElement::CONSTANT_NEUMANN); + if (condTypeBox->currentIndex()>1) + { + if (this->disTypeBox->currentIndex()>0) + _cond.setProcessDistributionType(FiniteElement::LINEAR_NEUMANN); + else + { + _cond.setProcessDistributionType(FiniteElement::CONSTANT_NEUMANN); + _cond.setConstantDisValue(this->firstValueEdit->text().toDouble()); + } + } + else + { + if (this->disTypeBox->currentIndex()>0) + _cond.setProcessDistributionType(FiniteElement::LINEAR); + else + { + _cond.setProcessDistributionType(FiniteElement::CONSTANT); + _cond.setConstantDisValue(this->firstValueEdit->text().toDouble()); + } + } } - else + else // direct on mesh + _cond.setProcessDistributionType(FiniteElement::DIRECT); + if (_cond.getDisValues().size()==0) { - if (this->disTypeBox->currentIndex()>0) - _cond.setProcessDistributionType(FiniteElement::LINEAR); - else - _cond.setProcessDistributionType(FiniteElement::CONSTANT); + OGSError::box("No distribution values specified!"); + return; } - std::vector<double> dis_values; - dis_values.push_back(strtod(this->firstValueEdit->text().toStdString().c_str(), 0)); - if (this->_secondValueEdit) - dis_values.push_back(strtod(this->_secondValueEdit->text().toStdString().c_str(), 0)); - _cond.setDisValue(dis_values); - - FEMCondition* new_cond(NULL); - switch(this->condTypeBox->currentIndex()) + if (!_set_on_points) { - case 0: - new_cond = new BoundaryCondition(_cond); - break; - case 1: - new_cond = new InitialCondition(_cond); - break; - default: - new_cond = new SourceTerm(_cond); + std::vector<FEMCondition*> conditions; + conditions.push_back(this->typeCast(_cond)); + emit createFEMCondition(conditions); } + else + this->copyCondOnPoints(); - emit addFEMCondition(new_cond); this->done(QDialog::Accepted); } @@ -127,44 +202,134 @@ void FEMConditionSetupDialog::on_condTypeBox_currentIndexChanged(int index) //if (index==1) // this->geoNameBox->addItem("Domain"); // remove "Domain" if IC is unselected - if (index>1) // source terms selected + if (_cond.getGeoType() != GEOLIB::INVALID) { - while (this->disTypeBox->count()>0) - this->disTypeBox->removeItem(0); - this->disTypeBox->addItem("Constant (Neumann)"); - if (_cond.getGeoType() == GEOLIB::POLYLINE) - this->disTypeBox->addItem("Linear (Neumann)"); + if (index>1) // source terms selected + { + while (this->disTypeBox->count()>0) + this->disTypeBox->removeItem(0); + this->disTypeBox->addItem("Constant (Neumann)"); + if (_cond.getGeoType() == GEOLIB::POLYLINE) + this->disTypeBox->addItem("Linear (Neumann)"); + } + else + { + while (this->disTypeBox->count()>0) + this->disTypeBox->removeItem(0); + this->disTypeBox->addItem("Constant (Direchlet)"); + if (_cond.getGeoType() == GEOLIB::POLYLINE) + this->disTypeBox->addItem("Linear (Direchlet)"); + } + } +} + + +void FEMConditionSetupDialog::on_disTypeBox_currentIndexChanged(int index) +{ + if (index>0) // linear + { + static_cast<QGridLayout*>(this->layout())->removeWidget(this->firstValueEdit); + directButton = new QPushButton("Calculate Values"); + connect(this->directButton, SIGNAL(pressed()), this, SLOT(directButton_pressed())); + static_cast<QGridLayout*>(this->layout())->addWidget(directButton,5,1); + } + else // constant + { + static_cast<QGridLayout*>(this->layout())->removeWidget(this->directButton); + delete directButton; + directButton = NULL; + static_cast<QGridLayout*>(this->layout())->addWidget(this->firstValueEdit,5,1); + } + +} + +void FEMConditionSetupDialog::directButton_pressed() +{ + if (this->_mesh == NULL) + { + const GEOLIB::Polyline* line = dynamic_cast<const GEOLIB::Polyline*>(_cond.getGeoObj()); + const std::vector<size_t> nodes = _cond.getDisNodes(); + const std::vector<double> values = _cond.getDisValues(); + LinearEditDialog dlg(*line, nodes, values); + connect(&dlg, SIGNAL(transmitDisValues(std::vector< std::pair<size_t,double> >)), + this, SLOT(addDisValues(std::vector< std::pair<size_t,double> >))); + dlg.exec(); } else { - while (this->disTypeBox->count()>0) - this->disTypeBox->removeItem(0); - this->disTypeBox->addItem("Constant (Direchlet)"); - if (_cond.getGeoType() == GEOLIB::POLYLINE) - this->disTypeBox->addItem("Linear (Direchlet)"); + std::map<std::string, MeshLib::CFEMesh*> msh_map; + msh_map.insert( std::pair<std::string, MeshLib::CFEMesh*>(this->_cond.getGeoName(), const_cast<MeshLib::CFEMesh*>(this->_mesh)) ); + CondFromRasterDialog dlg(msh_map); + //connect(&dlg, SIGNAL(directNodesWritten(std::string)), this, SLOT(direct_path_changed(std::string))); + connect(&dlg, SIGNAL(transmitDisValues(std::vector< std::pair<size_t,double> >)), + this, SLOT(addDisValues(std::vector< std::pair<size_t,double> >))); + dlg.exec(); } } +void FEMConditionSetupDialog::addDisValues(std::vector< std::pair<size_t,double> > direct_values) +{ + _cond.setDisValues(direct_values); + this->directButton->setText(QString::number(direct_values.size()) + " values added"); + //this->directButton->setEnabled(false); +} -void FEMConditionSetupDialog::on_disTypeBox_currentIndexChanged(int index) +FEMCondition* FEMConditionSetupDialog::typeCast(const FEMCondition &cond) { - if (index>0) // linear + FEMCondition* new_cond(NULL); + switch(this->condTypeBox->currentIndex()) + { + case 0: + new_cond = new BoundaryCondition(cond); + break; + case 1: + new_cond = new InitialCondition(cond); + break; + default: + new_cond = new SourceTerm(cond); + } + return new_cond; +} + +void FEMConditionSetupDialog::copyCondOnPoints() +{ + std::vector<FEMCondition*> conditions; + if (_cond.getGeoType() == GEOLIB::POLYLINE) { - if (!_secondValueEdit) + const GEOLIB::Polyline* ply = dynamic_cast<const GEOLIB::Polyline*>(_cond.getGeoObj()); + size_t nPoints = ply->getNumberOfPoints(); + for (size_t i=0; i<nPoints; i++) { - _secondValueEdit = new QLineEdit("0"); - _secondValueEdit->setValidator(_second_value_validator); - static_cast<QGridLayout*>(this->layout())->addWidget(_secondValueEdit,5,1) ; + FEMCondition* cond = new FEMCondition(_cond); + cond->setGeoObj(NULL); + cond->setGeoType(GEOLIB::POINT); + cond->setGeoName(_cond.getAssociatedGeometryName() + "_Point" + number2str(ply->getPointID(i))); + cond->clearDisValues(); + cond->setConstantDisValue((*ply->getPoint(i))[2]); + conditions.push_back(this->typeCast(*cond)); } + emit createFEMCondition(conditions); } - else // constant + else if (_cond.getGeoType() == GEOLIB::SURFACE) { - if (_secondValueEdit) + const GEOLIB::Surface* sfc = dynamic_cast<const GEOLIB::Surface*>(_cond.getGeoObj()); + size_t nTriangles = sfc->getNTriangles(); + for (size_t i=0; i<nTriangles; i++) { - static_cast<QGridLayout*>(this->layout())->removeWidget(_secondValueEdit); - delete _secondValueEdit; - _secondValueEdit = NULL; - } + const GEOLIB::Triangle* tri = (*sfc)[i]; + for (size_t j=0; j<3; j++) + { + FEMCondition* cond = new FEMCondition(_cond); + cond->setGeoObj(NULL); + cond->setGeoType(GEOLIB::POINT); + cond->setGeoName(_cond.getAssociatedGeometryName() + "_Point" + number2str((*tri)[j])); + cond->clearDisValues(); + cond->setConstantDisValue((*tri->getPoint(j))[2]); + conditions.push_back(this->typeCast(*cond)); + } + } + emit createFEMCondition(conditions); } - + else + std::cout << "Error discerning GeoType ..." << std::endl; } diff --git a/DataView/FEMConditionSetupDialog.h b/DataView/FEMConditionSetupDialog.h index ea9c66c58b10d906bd46677a0b851ed1dc345a22..84453433e5bf1ad9c0f35485860439d45f77db5b 100644 --- a/DataView/FEMConditionSetupDialog.h +++ b/DataView/FEMConditionSetupDialog.h @@ -11,12 +11,17 @@ #include <QDialog> +class QComboBox; +class QPushButton; class StrictDoubleValidator; namespace GEOLIB { class GeoObject; } +namespace MeshLib { + class CFEMesh; +} /** * \brief A dialog window for adding FEM Conditions based @@ -32,19 +37,29 @@ public: const GEOLIB::GEOTYPE type, const std::string &geo_name, const GEOLIB::GeoObject* const geo_object, + bool on_points = false, QDialog* parent = 0); /// Constructor for editing an existing FEM condition. - FEMConditionSetupDialog(FEMCondition &cond, QDialog* parent = 0); + FEMConditionSetupDialog(const FEMCondition &cond, QDialog* parent = 0); + + /// Constructor for creating DIRECT FEM conditions on MeshNodes. + FEMConditionSetupDialog(const std::string &name, const MeshLib::CFEMesh* mesh, QDialog* parent = 0); + ~FEMConditionSetupDialog(void); private: + /// Sets layout of the dialog according to properties of the object void setupDialog(); + /// Inserts existing values if an existing FEMCondition is being edited + void setValuesFromCond(); FEMCondition _cond; - QLineEdit* _secondValueEdit; + bool _set_on_points; + QComboBox* _combobox; //needed for on_points & linear conds + QPushButton* directButton; // needed for direct conditions + const MeshLib::CFEMesh* _mesh; // needed for direct conditions StrictDoubleValidator* _first_value_validator; - StrictDoubleValidator* _second_value_validator; private slots: /// Instructions if the OK-Button has been pressed. @@ -57,8 +72,16 @@ private slots: void on_disTypeBox_currentIndexChanged(int index); + void directButton_pressed(); + + void addDisValues(std::vector< std::pair<size_t,double> > direct_values); + + void copyCondOnPoints(); + + FEMCondition* typeCast(const FEMCondition &cond); + signals: - void addFEMCondition(FEMCondition*); + void createFEMCondition(std::vector<FEMCondition*>); }; diff --git a/DataView/GEOModels.cpp b/DataView/GEOModels.cpp index c6f2079f0337702f47fe0236ca2e0a5e1c8ca0ec..ae9314fe023173411e81dfb729b633e01387e8b3 100644 --- a/DataView/GEOModels.cpp +++ b/DataView/GEOModels.cpp @@ -11,6 +11,8 @@ #include "GeoTreeModel.h" #include "StationTreeModel.h" +#include "StringTools.h" + #include "OGSError.h" GEOModels::GEOModels( QObject* parent /*= 0*/ ) : @@ -38,9 +40,10 @@ void GEOModels::removeGeometry(std::string geo_name, GEOLIB::GEOTYPE type) void GEOModels::addPointVec( std::vector<GEOLIB::Point*>* points, std::string &name, - std::map<std::string, size_t>* name_pnt_id_map ) + std::map<std::string, size_t>* name_pnt_id_map, + double eps) { - GEOObjects::addPointVec(points, name, name_pnt_id_map); + GEOObjects::addPointVec(points, name, name_pnt_id_map, eps); _geoModel->addPointList(QString::fromStdString(name), this->getPointVecObj(name)); emit geoDataAdded(_geoModel, name, GEOLIB::POINT); } @@ -68,10 +71,9 @@ bool GEOModels::removePointVec( const std::string &name ) } void GEOModels::addStationVec( std::vector<GEOLIB::Point*>* stations, - std::string &name, - const GEOLIB::Color* const color ) + std::string &name) { - GEOObjects::addStationVec(stations, name, color); + GEOObjects::addStationVec(stations, name); _stationModel->addStationList(QString::fromStdString(name), stations); emit stationVectorAdded(_stationModel, name); @@ -210,26 +212,40 @@ void GEOModels::connectPolylineSegments(const std::string &geoName, void GEOModels::addNameForElement(const std::string &geometry_name, const GEOLIB::GEOTYPE object_type, size_t id, std::string new_name) { - switch(object_type) { - case GEOLIB::POINT: - { - GEOLIB::PointVec* pnt_vec = this->getPointVecObj(geometry_name); - pnt_vec->setNameForElement(id, new_name); - break; - } - case GEOLIB::POLYLINE: - { - GEOLIB::PolylineVec* ply_vec = this->getPolylineVecObj(geometry_name); - ply_vec->setNameForElement(id, new_name); - break; - } - case GEOLIB::SURFACE: - { - GEOLIB::SurfaceVec* sfc_vec = this->getSurfaceVecObj(geometry_name); - sfc_vec->setNameForElement(id, new_name); - break; - } - default: - std::cout << "Error in GEOModels::addNameForElement() - Unknown GEOTYPE..." << std::endl; + if (object_type == GEOLIB::POINT) + this->getPointVecObj(geometry_name)->setNameForElement(id, new_name); + else if (object_type == GEOLIB::POLYLINE) + this->getPolylineVecObj(geometry_name)->setNameForElement(id, new_name); + else if (object_type == GEOLIB::SURFACE) + this->getSurfaceVecObj(geometry_name)->setNameForElement(id, new_name); + else + std::cout << "Error in GEOModels::addNameForElement() - Unknown GEOTYPE..." << std::endl; +} + +void GEOModels::addNameForObjectPoints(const std::string &geometry_name, const GEOLIB::GEOTYPE object_type, const std::string &geo_object_name, const std::string &new_name) +{ + const GEOLIB::GeoObject* obj = this->getGEOObject(geometry_name, object_type, geo_object_name); + GEOLIB::PointVec* pnt_vec = this->getPointVecObj(geometry_name); + if (object_type == GEOLIB::POLYLINE) + { + const GEOLIB::Polyline* ply = dynamic_cast<const GEOLIB::Polyline*>(obj); + size_t nPoints = ply->getNumberOfPoints(); + for (size_t i=0; i<nPoints; i++) + pnt_vec->setNameForElement(ply->getPointID(i), new_name + "_Point" + number2str(ply->getPointID(i))); } + else if (object_type == GEOLIB::SURFACE) + { + const GEOLIB::Surface* sfc = dynamic_cast<const GEOLIB::Surface*>(obj); + size_t nTriangles = sfc->getNTriangles(); + for (size_t i=0; i<nTriangles; i++) + { + const GEOLIB::Triangle* tri = (*sfc)[i]; + pnt_vec->setNameForElement((*tri)[0], new_name + "_Point" + number2str((*tri)[0])); + pnt_vec->setNameForElement((*tri)[1], new_name + "_Point" + number2str((*tri)[1])); + pnt_vec->setNameForElement((*tri)[2], new_name + "_Point" + number2str((*tri)[2])); + } + } + else + std::cout << "Error in GEOModels::addNameForElement() - Unknown GEOTYPE..." << std::endl; } + diff --git a/DataView/GEOModels.h b/DataView/GEOModels.h index 1396567f33bae3aaac6fd83fa1049c698933afb7..b90689c32c9cd83fa4051c64a14964b9050acbd8 100644 --- a/DataView/GEOModels.h +++ b/DataView/GEOModels.h @@ -43,15 +43,15 @@ public slots: virtual void addPointVec(std::vector<GEOLIB::Point*>* points, std::string &name, - std::map<std::string, size_t>* name_pnt_id_map = NULL); + std::map<std::string, size_t>* name_pnt_id_map = NULL, + double eps = sqrt(std::numeric_limits<double>::min())); virtual bool appendPointVec(const std::vector<GEOLIB::Point*> &points, const std::string &name, std::vector<size_t>* ids = NULL); virtual bool removePointVec(const std::string &name); virtual void addStationVec(std::vector<GEOLIB::Point*>* stations, - std::string &name, - const GEOLIB::Color* const color); + std::string &name); void filterStationVec(const std::string &name, const std::vector<PropertyBounds> &bounds); virtual bool removeStationVec(const std::string &name); @@ -72,8 +72,12 @@ public slots: const std::string &name); virtual bool removeSurfaceVec(const std::string &name); + /// Adds the name 'new_name' for the geo-object specified by the parameters void addNameForElement(const std::string &geometry_name, const GEOLIB::GEOTYPE object_type, size_t id, std::string new_name); + /// Adds a generic name to all points that are part of the specified geo-object + void addNameForObjectPoints(const std::string &geometry_name, const GEOLIB::GEOTYPE object_type, const std::string &geo_object_name, const std::string &new_name); + /// Calls all necessary functions to connect polyline-segments and update all views and windows. void connectPolylineSegments(const std::string &geoName, std::vector<size_t> indexlist, diff --git a/DataView/GMSHPrefsDialog.h b/DataView/GMSHPrefsDialog.h index 760490f9dc6035f93551b90b59283df994023f1e..98b9ce5c2aeaa1278386884e5bffbed3686f8432 100644 --- a/DataView/GMSHPrefsDialog.h +++ b/DataView/GMSHPrefsDialog.h @@ -45,7 +45,7 @@ private slots: void reject(); signals: - void requestMeshing(std::vector<std::string> const &, size_t, double, double, double, bool); + void requestMeshing(std::vector<std::string> &, size_t, double, double, double, bool); }; #endif //GMSHPREFSDIALOG_H diff --git a/DataView/GeoTreeModel.cpp b/DataView/GeoTreeModel.cpp index 95617c0ddd05d10d19f165c325d0d3c10f16ff90..3f48f3c4094b16432a3a6c94741789446822e0e1 100644 --- a/DataView/GeoTreeModel.cpp +++ b/DataView/GeoTreeModel.cpp @@ -212,7 +212,7 @@ void GeoTreeModel::addChildren(GeoObjectListItem* sfcList, { QList<QVariant> surface; std::string sfc_name(""); - sfc_name = surface_vec->getNameOfElementByID(i, sfc_name); + surface_vec->getNameOfElementByID(i, sfc_name); surface << "Surface " + QString::number(i) << QString::fromStdString(sfc_name) << "" << ""; const GEOLIB::Surface &sfc(*(*surfaces)[i]); diff --git a/DataView/GeoTreeView.cpp b/DataView/GeoTreeView.cpp index 0a9daab7211fc0c64c374da39f8f50724cb9d817..1623bc19bdc12b16a35f5179114786c23857f890 100644 --- a/DataView/GeoTreeView.cpp +++ b/DataView/GeoTreeView.cpp @@ -21,7 +21,7 @@ void GeoTreeView::updateView() { setAlternatingRowColors(true); //resizeColumnToContents(0); - setColumnWidth(1,150); + setColumnWidth(0,150); setColumnWidth(1,50); setColumnWidth(2,50); } @@ -87,15 +87,27 @@ void GeoTreeView::contextMenuEvent( QContextMenuEvent* event ) } else { + if (!item) // Otherwise sometimes it crashes when (unmotivated ;-) ) clicking in a treeview + return; + GeoObjectListItem* parent = dynamic_cast<GeoObjectListItem*>(item->parentItem()); // The current index refers to a geo-object if (parent != NULL) { - QAction* addCondAction = menu.addAction("Set as FEM condition..."); + QMenu* cond_menu = new QMenu("Set FEM Condition"); + menu.addMenu(cond_menu); + QAction* addCondAction = cond_menu->addAction("On object..."); + QAction* addCondPointAction = cond_menu->addAction("On all points..."); QAction* addNameAction = menu.addAction("Set name..."); - connect(addCondAction, SIGNAL(triggered()), this, SLOT(setElementAsCondition())); + connect(addCondAction, SIGNAL(triggered()), this, SLOT(setObjectAsCondition())); connect(addNameAction, SIGNAL(triggered()), this, SLOT(setNameForElement())); + + if (parent->getType() == GEOLIB::POINT) + addCondPointAction->setEnabled(false); + else + connect(addCondPointAction, SIGNAL(triggered()), this, SLOT(setObjectPointsAsCondition())); + } // The current index refers to the name of a geometry-object else if (item->childCount() > 0) @@ -104,12 +116,12 @@ void GeoTreeView::contextMenuEvent( QContextMenuEvent* event ) { QAction* saveAction = menu.addAction("Save geometry..."); QAction* addCNDAction = menu.addAction("Load FEM Conditions..."); - QAction* saveCondAction = menu.addAction("Save FEM conditions..."); + //QAction* saveCondAction = menu.addAction("Save FEM conditions..."); menu.addSeparator(); QAction* removeAction = menu.addAction("Remove geometry"); connect(saveAction, SIGNAL(triggered()), this, SLOT(writeToFile())); connect(addCNDAction, SIGNAL(triggered()), this, SLOT(loadFEMConditions())); - connect(saveCondAction, SIGNAL(triggered()), this, SLOT(saveFEMConditions())); + //connect(saveCondAction, SIGNAL(triggered()), this, SLOT(saveFEMConditions())); connect(removeAction, SIGNAL(triggered()), this, SLOT(removeList())); } } @@ -138,14 +150,14 @@ void GeoTreeView::removeList() emit listRemoved((item->data(0).toString()).toStdString(), GEOLIB::INVALID); } -void GeoTreeView::setElementAsCondition() +void GeoTreeView::setElementAsCondition(bool set_on_points) { const TreeItem* item = static_cast<GeoTreeModel*>(model())->getItem( this->selectionModel()->currentIndex()); const size_t id = item->row(); const GEOLIB::GEOTYPE type = static_cast<GeoObjectListItem*>(item->parentItem())->getType(); const std::string geometry_name = item->parentItem()->parentItem()->data(0).toString().toStdString(); - emit requestCondSetupDialog(geometry_name, type, id); + emit requestCondSetupDialog(geometry_name, type, id, set_on_points); } void GeoTreeView::setNameForElement() @@ -175,12 +187,13 @@ void GeoTreeView::loadFEMConditions() this->selectionModel()->currentIndex()); emit loadFEMCondFileRequested(item->data(0).toString().toStdString()); } - +/* void GeoTreeView::saveFEMConditions() { TreeItem* item = static_cast<GeoTreeModel*>(model())->getItem( this->selectionModel()->currentIndex()); QString fileName = QFileDialog::getSaveFileName(NULL, - "Save FEM Conditions as", "", "GeoSys FEM Condition file (*.cnd)"); + "Save FEM Conditions as", "", "OpenGeoSys FEM Condition file (*.cnd);; GeoSys Boundary Condition (*.bc);; GeoSys Initial Condition (*.ic);; GeoSys Source Condition (*.st)"); emit saveFEMConditionsRequested(item->data(0).toString(), fileName); } +*/ diff --git a/DataView/GeoTreeView.h b/DataView/GeoTreeView.h index 466289aa82a7da33f23bd647673b1e921fc0e830..376d2f9080b99b1a91bb569e3ad80867bd2290ed 100644 --- a/DataView/GeoTreeView.h +++ b/DataView/GeoTreeView.h @@ -38,6 +38,8 @@ protected slots: private: /// Actions to be taken after a right mouse click is performed in the station view. void contextMenuEvent( QContextMenuEvent* e ); + /// Calls a FEMConditionSetupDialog. + void setElementAsCondition(bool set_on_points = false); private slots: /// Allows to add FEM Conditions to a process @@ -45,16 +47,16 @@ private slots: void on_Clicked(QModelIndex idx); /// Calls a LineEditDialog. void connectPolylines(); - /// Calls a FEMConditionSetupDialog. - void setElementAsCondition(); /// Calls a SetNameDialog. void setNameForElement(); + void setObjectAsCondition() { setElementAsCondition(false); }; + void setObjectPointsAsCondition() { setElementAsCondition(true); }; /// Saves a geometry in a file. void writeToFile() const; /// Removes a whole geometry or parts of it. void removeList(); /// Saves FEM Conditions associated with the given geometry - void saveFEMConditions(); + //void saveFEMConditions(); signals: void geoItemSelected(const vtkPolyDataAlgorithm*, int); @@ -63,10 +65,10 @@ signals: void listRemoved(std::string name, GEOLIB::GEOTYPE); void loadFEMCondFileRequested(std::string); void saveToFileRequested(QString, QString) const; - void requestCondSetupDialog(const std::string&, const GEOLIB::GEOTYPE, const size_t); + void requestCondSetupDialog(const std::string&, const GEOLIB::GEOTYPE, const size_t, bool on_points); void requestLineEditDialog(const std::string&); void requestNameChangeDialog(const std::string&, const GEOLIB::GEOTYPE, const size_t); - void saveFEMConditionsRequested(QString, QString); + //void saveFEMConditionsRequested(QString, QString); }; #endif //GEOTREEVIEW_H diff --git a/DataView/LinearEdit.ui b/DataView/LinearEdit.ui new file mode 100644 index 0000000000000000000000000000000000000000..7806f69b3799d5d2571d0e832c15039fb657c8bb --- /dev/null +++ b/DataView/LinearEdit.ui @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LinearEdit</class> + <widget class="QDialog" name="LinearEdit"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>174</width> + <height>347</height> + </rect> + </property> + <property name="windowTitle"> + <string>Linear Edit</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QComboBox" name="comboBox"> + <item> + <property name="text"> + <string>Values</string> + </property> + </item> + <item> + <property name="text"> + <string>Elevation</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QTableWidget" name="tableWidget"> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <column> + <property name="text"> + <string>Value</string> + </property> + </column> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>LinearEdit</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>LinearEdit</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/DataView/LinearEditDialog.cpp b/DataView/LinearEditDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f23b82573f54f216f1f45be168496a4643164ba5 --- /dev/null +++ b/DataView/LinearEditDialog.cpp @@ -0,0 +1,68 @@ +/** + * \file LinearEditDialog.cpp + * 2012/04/17 KR Initial implementation + */ + +#include "LinearEditDialog.h" + +LinearEditDialog::LinearEditDialog(const GEOLIB::Polyline &line, const std::vector<size_t> &dis_nodes, const std::vector<double> &dis_values, QDialog* parent) + : QDialog(parent), _line(line) +{ + setupUi(this); + setupDialog(dis_nodes, dis_values); +} + +void LinearEditDialog::setupDialog(const std::vector<size_t> &dis_nodes, const std::vector<double> &dis_values) +{ + size_t nPoints(_line.getNumberOfPoints()); + this->tableWidget->setRowCount(nPoints); + QList<QString> indexlist; + + for (size_t i=0; i<nPoints; i++) + { + indexlist.push_back(QString::number(i)); + QTableWidgetItem *newItem = new QTableWidgetItem(""); + tableWidget->setItem(i, 0, newItem); + } + QStringList vHeaders(indexlist); + tableWidget->setVerticalHeaderLabels(vHeaders); + + size_t nValues (dis_values.size()); + for (size_t i=0; i<nValues; i++) + tableWidget->item(dis_nodes[i],0)->setText(QString::number(dis_values[i])); +} + +LinearEditDialog::~LinearEditDialog() +{ +} + +void LinearEditDialog::on_comboBox_currentIndexChanged(int index) +{ + if (index>0) //elevation + { + size_t nRows = tableWidget->rowCount(); + for (size_t i=0; i<nRows; i++) + tableWidget->item(i,0)->setText(QString::number(_line[i]->getData()[2])); + } +} + +void LinearEditDialog::accept() +{ + std::vector< std::pair<size_t,double> > linear_values; + + size_t nRows = tableWidget->rowCount(); + for (size_t i=0; i<nRows; i++) + { + QString row_text (tableWidget->item(i,0)->text()); + if (row_text.length()>0) + linear_values.push_back( std::pair<size_t, double>(i, row_text.toDouble()) ); + } + + emit transmitDisValues(linear_values); + this->done(QDialog::Accepted); +} + +void LinearEditDialog::reject() +{ + this->done(QDialog::Rejected); +} diff --git a/DataView/LinearEditDialog.h b/DataView/LinearEditDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..41fde93c1451361f9edc72a4e4950b592eb3cd60 --- /dev/null +++ b/DataView/LinearEditDialog.h @@ -0,0 +1,43 @@ +/** + * \file LinearEditDialog.h + * 2012/04/17 KR Initial implementation + */ + +#ifndef LINEAREDITDIALOG_H +#define LINEAREDITDIALOG_H + +#include "ui_LinearEdit.h" +#include <QDialog> + +#include "Polyline.h" + +/** + * \brief A dialog window for creating linear boundary conditions on polylines + */ +class LinearEditDialog : public QDialog, private Ui_LinearEdit +{ + Q_OBJECT + +public: + LinearEditDialog(const GEOLIB::Polyline &line, const std::vector<size_t> &dis_nodes, const std::vector<double> &dis_values, QDialog* parent = 0); + ~LinearEditDialog(void); + +private: + void setupDialog(const std::vector<size_t> &dis_nodes, const std::vector<double> &dis_values); + + const GEOLIB::Polyline _line; + +private slots: + void on_comboBox_currentIndexChanged(int index); + + /// Instructions if the OK-Button has been pressed. + void accept(); + + /// Instructions if the Cancel-Button has been pressed. + void reject(); + +signals: + void transmitDisValues(std::vector< std::pair<size_t,double> >); +}; + +#endif //LINEAREDITDIALOG_H diff --git a/DataView/MshEditDialog.cpp b/DataView/MshEditDialog.cpp index 43804784d9b7c4181c364d8f827658a4d96cc7a9..1337841ef936ed3fb529fe920631e34f0f958004 100644 --- a/DataView/MshEditDialog.cpp +++ b/DataView/MshEditDialog.cpp @@ -25,12 +25,13 @@ MshEditDialog::MshEditDialog(const MeshLib::CFEMesh* mesh, QDialog* parent) this->gridLayoutLayerMapping->setColumnStretch(2, 10); size_t nLayers = mesh->getNumberOfMeshLayers(); - if (nLayers == 0) - nLayers = 1; // adapt to old files where 2D meshes officially had "0" layers which makes no sense - for (size_t i = 0; i < nLayers; i++) + for (size_t i = 0; i <= nLayers+1; i++) { - QString text = (i) ? "Layer" + QString::number(i) : "Surface"; + QString text(""); + if (i==0) text="Surface"; + else if (i>nLayers) text="Layer" + QString::number(nLayers) + "-Bottom"; + else text="Layer" + QString::number(i) + "-Top"; QLabel* label = new QLabel(text); QLineEdit* edit = new QLineEdit(); QPushButton* button = new QPushButton("..."); @@ -44,12 +45,14 @@ MshEditDialog::MshEditDialog(const MeshLib::CFEMesh* mesh, QDialog* parent) this->gridLayoutLayerMapping->addWidget(_labels[i], i, 0); this->gridLayoutLayerMapping->addWidget(_edits[i], i, 1); this->gridLayoutLayerMapping->addWidget(_buttons[i], i, 2); + + if (nLayers==0) break; // don't add bottom layer if mesh contains only surface } _noDataDeleteBox = new QCheckBox("Remove mesh nodes at NoData values"); _noDataDeleteBox->setChecked(false); _noDataDeleteBox->setEnabled(false); - if (nLayers == 1) + if (nLayers == 0) { _noDataDeleteBox->setEnabled(true); this->gridLayoutLayerMapping->addWidget(_noDataDeleteBox, 2, 1); @@ -80,34 +83,39 @@ void MshEditDialog::accept() { case 0: { - int nLayers = atoi(this->editNLayers->text().toStdString().c_str()); - double thickness = - strtod(replaceString(",", ".", - this->editThickness->text().toStdString()). - c_str(), 0); - + const int nLayers = atoi(this->editNLayers->text().toStdString().c_str()); + const double thickness = strtod(replaceString(",", ".", this->editThickness->text().toStdString()).c_str(), 0); new_mesh = MshLayerMapper::CreateLayers(_msh, nLayers, thickness); break; } case 1: { - size_t nLayers = _msh->getNumberOfMeshLayers(); - if (nLayers == 0) - nLayers = 1; // adapt to old files where 2D meshes officially had "0" layers which makes no sense - - for (size_t i = 0; i < nLayers; i++) + new_mesh = new MeshLib::CFEMesh(*_msh); + const size_t nLayers = _msh->getNumberOfMeshLayers(); + if (nLayers==0) { - std::string imgPath ( this->_edits[i]->text().toStdString() ); + const std::string imgPath ( this->_edits[0]->text().toStdString() ); if (!imgPath.empty()) - new_mesh = MshLayerMapper::LayerMapping( - _msh, - imgPath, - nLayers, - i, - _noDataDeleteBox-> - isChecked()); + MshLayerMapper::LayerMapping(new_mesh, imgPath, nLayers, 0, _noDataDeleteBox->isChecked()); + } + else + { + for (size_t i = 1; i <= nLayers+1; i++) + { + const std::string imgPath ( this->_edits[i]->text().toStdString() ); + if (!imgPath.empty()) + { + int result = MshLayerMapper::LayerMapping(new_mesh, imgPath, nLayers, i-1, _noDataDeleteBox->isChecked()); + if (result==0) break; + } + } + } + if (nLayers>0 && this->_edits[0]->text().length()>0) + { + MeshLib::CFEMesh* final_mesh = MshLayerMapper::blendLayersWithSurface(new_mesh, nLayers, this->_edits[0]->text().toStdString()); + delete new_mesh; + new_mesh = final_mesh; } - //if (nLayers>1) MshLayerMapper::CheckLayerMapping(new_mesh, nLayers, 1); //TODO !!! break; } default: diff --git a/DataView/MshLayerMapper.cpp b/DataView/MshLayerMapper.cpp index f79cb3cb52518fc19a7558efc82908414edf42b5..31cdd370a68e1b6d45e10110ae7c87226289dfdf 100644 --- a/DataView/MshLayerMapper.cpp +++ b/DataView/MshLayerMapper.cpp @@ -4,9 +4,10 @@ */ #include "MshLayerMapper.h" -#include "OGSRaster.h" +#include "VtkRaster.h" #include "MshEditor.h" +#include "GridAdapter.h" #include "matrix_class.h" #include "msh_mesh.h" @@ -31,18 +32,22 @@ MeshLib::CFEMesh* MshLayerMapper::CreateLayers(const MeshLib::CFEMesh* mesh, } */ MeshLib::CFEMesh* new_mesh ( new MeshLib::CFEMesh() ); - size_t nNodes = mesh->nod_vector.size(); - size_t nElems = mesh->ele_vector.size(); + const size_t nNodes = mesh->nod_vector.size(); + const size_t nElems = mesh->ele_vector.size(); - for (size_t layer_id = 0; layer_id < nLayers; layer_id++) + for (size_t layer_id = 0; layer_id <= nLayers; layer_id++) { // add nodes for new layer size_t node_offset ( nNodes * layer_id ); -// TF unused variable double z_offset ( layer_id*thickness ); + const double z_offset ( layer_id*thickness ); for (size_t i = 0; i < nNodes; i++) - new_mesh->nod_vector.push_back(new MeshLib::CNode( node_offset + i, - mesh->nod_vector[i]-> - getData())); + { + const double* coords = mesh->nod_vector[i]->getData(); + new_mesh->nod_vector.push_back( new MeshLib::CNode(node_offset + i, + coords[0], + coords[1], + coords[2]-z_offset) ); + } if (layer_id > 0) // starting with the 2nd layer prism (or hex) elements can be created { @@ -50,35 +55,30 @@ MeshLib::CFEMesh* MshLayerMapper::CreateLayers(const MeshLib::CFEMesh* mesh, node_offset = (layer_id - 1) * nNodes; for (size_t i = 0; i < nElems; i++) { + const MeshLib::CElem* sfc_elem( mesh->ele_vector[i] ); MeshLib::CElem* elem( new MeshLib::CElem() ); - size_t nElemNodes = mesh->ele_vector[i]->getNodeIndices().Size(); - if (mesh->ele_vector[i]->GetElementType() == MshElemType::TRIANGLE) - elem->setElementProperties(MshElemType::PRISM); // extrude triangles to prism - else if (mesh->ele_vector[i]->GetElementType() == MshElemType::QUAD) - elem->setElementProperties(MshElemType::HEXAHEDRON); // extrude quads to hexes - else if (mesh->ele_vector[i]->GetElementType() == MshElemType::LINE) + size_t nElemNodes = sfc_elem->getNodeIndices().Size(); + if (sfc_elem->GetElementType() == MshElemType::TRIANGLE) + elem->setElementProperties(MshElemType::PRISM); // extrude triangles to prism + else if (sfc_elem->GetElementType() == MshElemType::QUAD) + elem->setElementProperties(MshElemType::HEXAHEDRON); // extrude quads to hexes + else if (sfc_elem->GetElementType() == MshElemType::LINE) continue; // line elements are ignored and not duplicated else { - std::cout << - "Error in MshLayerMapper::CreateLayers() - Method can only handle 2D mesh elements ..." - << std::endl; - std::cout << "Element " << i << " is of type \"" << - MshElemType2String(mesh->ele_vector[i]->GetElementType()) - << - "\"." << std::endl; + std::cout << "Error in MshLayerMapper::CreateLayers() - Method can only handle 2D mesh elements ..." << std::endl; + std::cout << "Element " << i << " is of type \"" << MshElemType2String(sfc_elem->GetElementType()) << "\"." << std::endl; delete new_mesh; return NULL; } - elem->SetPatchIndex(layer_id - 1); + elem->SetPatchIndex(nLayers - layer_id); elem->SetNodesNumber(2 * nElemNodes); elem->getNodeIndices().resize(2 * nElemNodes); for (size_t j = 0; j < nElemNodes; j++) { - long idx = mesh->ele_vector[i]->GetNodeIndex(j); - elem->SetNodeIndex(j, node_offset + idx); - elem->SetNodeIndex(j + nElemNodes, - node_offset + nNodes + idx); + long idx = sfc_elem->GetNodeIndex(j); + elem->SetNodeIndex(nElemNodes-j-1, node_offset + idx); + elem->SetNodeIndex(nElemNodes-j-1 + nElemNodes, node_offset + nNodes + idx); } new_mesh->ele_vector.push_back(elem); } @@ -88,103 +88,90 @@ MeshLib::CFEMesh* MshLayerMapper::CreateLayers(const MeshLib::CFEMesh* mesh, new_mesh->setNumberOfNodesFromNodesVectorSize (); new_mesh->setNumberOfMeshLayers(nLayers); - // HACK this crashes on linux systems probably because of uninitialised variables in the the element class new_mesh->ConstructGrid(); new_mesh->FillTransformMatrix(); return new_mesh; } -// KR, based on code by WW -MeshLib::CFEMesh* MshLayerMapper::LayerMapping(const MeshLib::CFEMesh* msh, +int MshLayerMapper::LayerMapping(MeshLib::CFEMesh* new_mesh, const std::string &rasterfile, const size_t nLayers, const size_t layer_id, bool removeNoDataValues) { - if (msh == NULL) - return NULL; - if (msh->getNumberOfMeshLayers() >= layer_id) + if (new_mesh == NULL) { - if (msh == NULL) - { - std::cout << - "Error in MshLayerMapper::LayerMapping() - Passed Mesh is NULL..." << - std::endl; - return NULL; - } - MeshLib::CFEMesh* new_mesh( new MeshLib::CFEMesh(*msh) ); + std::cout << + "Error in MshLayerMapper::LayerMapping() - Passed Mesh is NULL..." << + std::endl; + return 0; + } + if (new_mesh->getNumberOfMeshLayers() >= layer_id) + { double x0(0), y0(0), delta(1); size_t width(1), height(1); - double* elevation = OGSRaster::loadDataFromASC(QString::fromStdString( - rasterfile), x0, y0, width, - height, delta); + float* elevation = VtkRaster::loadDataFromASC(rasterfile, x0, y0, width,height, delta); if (elevation == NULL) { delete [] elevation; - return NULL; + return 0; } - std::pair<double, double> xDim(x0, x0 + width * delta); // extension in x-dimension - std::pair<double, double> yDim(y0, y0 + height * delta); // extension in y-dimension + const std::pair<double, double> xDim(x0, x0 + width * delta); // extension in x-dimension + const std::pair<double, double> yDim(y0, y0 + height * delta); // extension in y-dimension if (!meshFitsImage(new_mesh, xDim, yDim)) { delete [] elevation; - return NULL; + return 0; } - double locX[4]; - double locY[4]; - double locZ[4]; - - size_t nNodes = msh->nod_vector.size(); - size_t nNodesPerLayer = nNodes / nLayers; + const size_t nNodes = new_mesh->nod_vector.size(); + const size_t nNodesPerLayer = nNodes / (nLayers+1); - size_t firstNode = layer_id * nNodesPerLayer; - size_t lastNode = firstNode + nNodesPerLayer; + const size_t firstNode = layer_id * nNodesPerLayer; + const size_t lastNode = firstNode + nNodesPerLayer; std::vector<size_t> noData_nodes; - + const double half_delta = 0.5*delta; for(size_t i = firstNode; i < lastNode; i++) { - size_t xPos (static_cast<size_t>(floor( - (msh->nod_vector[i]->getData()[0] - - xDim.first) / delta))); - size_t yPos (static_cast<size_t>(floor( - (msh->nod_vector[i]->getData()[1] - - yDim.first) / delta))); - - locX[0] = xDim.first + xPos * delta; - locY[0] = yDim.first + yPos * delta; - locZ[0] = elevation[yPos * width + xPos]; - - locX[1] = xDim.first + (xPos + 1) * delta; - locY[1] = yDim.first + yPos * delta; - locZ[1] = elevation[yPos * width + (xPos + 1)]; - - locX[2] = xDim.first + (xPos + 1) * delta; - locY[2] = yDim.first + (yPos + 1) * delta; - locZ[2] = elevation[(yPos + 1) * width + (xPos + 1)]; - - locX[3] = xDim.first + xPos * delta; - locY[3] = yDim.first + (yPos + 1) * delta; - locZ[3] = elevation[(yPos + 1) * width + xPos]; - - bool noData(false); - for(size_t j = 0; j < 4; j++) - if(fabs(locZ[j] + 9999) < std::numeric_limits<double>::min()) - noData = true; - - if(!noData) + const double* coords = new_mesh->nod_vector[i]->getData(); + // position in raster + const double xPos ((coords[0] - xDim.first) / delta); + const double yPos ((coords[1] - yDim.first) / delta); + // raster cell index + const size_t xIdx (static_cast<size_t>(floor(xPos))); + const size_t yIdx (static_cast<size_t>(floor(yPos))); + + // deviation of mesh node from centre of raster cell ( in [-1:1) because it is normalised by delta/2 ) + const double xShift = (xPos-xIdx-half_delta)/half_delta; + const double yShift = (yPos-yIdx-half_delta)/half_delta; + + const int xShiftIdx = (xShift>=0) ? ceil(xShift) : floor(xShift); + const int yShiftIdx = (yShift>=0) ? ceil(yShift) : floor(yShift); + + // determining the neighbouring pixels that add weight to the interpolation + const size_t x_nb[4] = {0, xShiftIdx, xShiftIdx, 0}; + const size_t y_nb[4] = {0, 0, yShiftIdx, yShiftIdx}; + + double locZ[4]; + locZ[0] = elevation[2*(yIdx*width + xIdx)]; + if (fabs(locZ[0] + 9999) > std::numeric_limits<double>::min()) { - // Interpolate + for (size_t j=1; j<4; j++) + { + locZ[j] = elevation[2*((yIdx+y_nb[j])*width + (xIdx+x_nb[j]))]; + if (fabs(locZ[j] + 9999) < std::numeric_limits<double>::min()) + locZ[j]=locZ[0]; + } + double ome[4]; - double const* const coords (msh->nod_vector[i]->getData()); - double xi = 2.0 * (coords[0] - 0.5 * (locX[0] + locX[1])) / delta; - double eta = 2.0 * (coords[1] - 0.5 * (locY[1] + locY[2])) / delta; + double xi = 1-fabs(xShift); + double eta = 1-fabs(xShift); MPhi2D(ome, xi, eta); double z(0.0); @@ -195,14 +182,13 @@ MeshLib::CFEMesh* MshLayerMapper::LayerMapping(const MeshLib::CFEMesh* msh, } else { - //std::cout << "Warning: No elevation data available for node " << i << " (" << msh->nod_vector[i]->X() << ", " << msh->nod_vector[i]->Y() << ")." << std::endl; new_mesh->nod_vector[i]->SetZ(0); new_mesh->nod_vector[i]->SetMark(false); noData_nodes.push_back(i); } } - if ((nLayers == 1) && removeNoDataValues) + if ((nLayers == 0) && removeNoDataValues) { if (noData_nodes.size() < (new_mesh->nod_vector.size() - 2)) { @@ -226,17 +212,14 @@ MeshLib::CFEMesh* MshLayerMapper::LayerMapping(const MeshLib::CFEMesh* msh, std::cout << "Too many NoData values..." << std::endl; } - new_mesh->ConstructGrid(); - new_mesh->FillTransformMatrix(); - delete [] elevation; - return new_mesh; + return 1; } else std::cout << "Error in MshLayerMapper::LayerMapping() - Mesh has only " << - msh->getNumberOfMeshLayers() << " Layers, cannot assign layer " << layer_id << + new_mesh->getNumberOfMeshLayers() << " Layers, cannot assign layer " << layer_id << "..." << std::endl; - return NULL; + return 0; } // KR, based on code by WW (Note: this method has not been tested yet and will probably fail miserably!) @@ -273,345 +256,158 @@ bool MshLayerMapper::meshFitsImage(const MeshLib::CFEMesh* msh, return true; } -void MshLayerMapper::CheckLayerMapping(MeshLib::CFEMesh* mesh, const size_t nLayers, int integ) +MeshLib::CFEMesh* MshLayerMapper::blendLayersWithSurface(MeshLib::CFEMesh* mesh, const size_t nLayers, const std::string &dem_raster) { - double ref_dep = -999999999.0; - - size_t nNodesPerLayer = mesh->nod_vector.size() / (nLayers + 1); - - //18.02.2009 WW - if (integ) + // construct surface mesh from DEM + MeshLib::CFEMesh* dem = MshEditor::getMeshSurface(*mesh); + MshLayerMapper::LayerMapping(dem, dem_raster, 0, 0); + + const size_t nNodes = mesh->nod_vector.size(); + const size_t nNodesPerLayer = nNodes / (nLayers+1); + std::vector<bool> is_surface_node(nNodes, false); + std::vector<bool> nodes_below_surface(nNodes, false); + + // check if bottom layer nodes are below DEM + const size_t bottom_firstNode = nLayers * nNodesPerLayer; + const size_t bottom_lastNode = bottom_firstNode + nNodesPerLayer; + for(size_t i = bottom_firstNode; i < bottom_lastNode; i++) { - for (size_t i = 0; i < nNodesPerLayer; i++) - for (size_t k = 0; k < nLayers; k++) - { - MeshLib::CNode* node = mesh->nod_vector[k * nNodesPerLayer + i]; - if (k == 0) - node->SetBoundaryType('0'); // on the surface - else if (k == (nLayers - 1)) - node->SetBoundaryType('1'); // on the bottom - else - node->SetBoundaryType('I'); // interior node - } + nodes_below_surface[i]=true; + const double* coords = mesh->nod_vector[i]->getData(); + const double* dem_coords = dem->nod_vector[i-bottom_firstNode]->getData(); + if (coords[2] >= dem_coords[2]) + { + std::cout << "Warning: Node " << i << " (in bottom-layer) is above surface node " << (i-bottom_firstNode) << ". (" << coords[2] << " > " << dem_coords[2] << ")" << std::endl; + is_surface_node[i] = true; + } } - size_t flat(0); - for (size_t i = 0; i < nNodesPerLayer; i++) + // for all other layers: + // if node < dem-node: do nothing + // if node > dem-node: + // if first node above surface: map to dem and mark as surface node + // else remove node + for (int layer_id=nLayers-1; layer_id>=0; layer_id--) { - std::vector<long> tmp_connected_nodes; - flat = 0; + const size_t firstNode = layer_id * nNodesPerLayer; + const size_t lastNode = firstNode + nNodesPerLayer; - for (size_t k = 0; k < nLayers - 2; k++) // top layer is not checked + for(size_t i = firstNode; i < lastNode; i++) { - MeshLib::CNode* bNode = mesh->nod_vector[k * nNodesPerLayer + i]; // current node - MeshLib::CNode* tNode = mesh->nod_vector[(k + 1) * nNodesPerLayer + i]; // same node but one layer below - - if (!tNode->GetMark()) + if (is_surface_node[i+nNodesPerLayer]) + is_surface_node[i]=true; + else { - if (k == 0) - { - tmp_connected_nodes.clear(); - std::vector<size_t> const& connected_nodes ( - tNode->getConnectedNodes()); - const size_t n_connected_nodes (connected_nodes.size()); - for (size_t j = 0; j < n_connected_nodes; j++) - tmp_connected_nodes.push_back(connected_nodes[j]); - } - - tNode->SetZ(bNode->getData()[2]); // z coordinate changed to layer above - tNode->getConnectedNodes().clear(); - for (int j = k; j >= 0; j--) //WW/YW. 23.01.2009 + nodes_below_surface[i]=true; + MeshLib::CNode* node (mesh->nod_vector[i]); + const double* coords = node->getData(); + const double* dem_coords = dem->nod_vector[i-firstNode]->getData(); + if (coords[2] > dem_coords[2]) { - MeshLib::CNode* nNode = - mesh->nod_vector[j * nNodesPerLayer + i]; - if (nNode->GetMark()) - { - tNode->getConnectedNodes().push_back( - nNode->GetIndex()); - break; - } + const double new_coords[3] = { dem_coords[0], dem_coords[1], dem_coords[2] }; + node->SetCoordinates(new_coords); + is_surface_node[i] = true; } - flat++; - } - } - - //---- 27.01.2009. WW - if (flat == nLayers - 2 /*1*/) - { - MeshLib::CNode* bNode = mesh->nod_vector[nNodesPerLayer + i]; - bNode->SetMark(true); - bNode->getConnectedNodes().clear(); - for (size_t j = 0; j < tmp_connected_nodes.size(); j++) - bNode->getConnectedNodes().push_back(tmp_connected_nodes[j]); - - MeshLib::CNode* tNode = - mesh->nod_vector[(nLayers - 1) * nNodesPerLayer + i]; - tNode->SetMark(false); - bNode->SetZ(tNode->getData()[2]); - bNode->SetBoundaryType('1'); - // - for (size_t k = 1; k < nLayers; k++) - { - tNode = mesh->nod_vector[(k + 1) * nNodesPerLayer + i]; - tNode->SetZ(ref_dep); - tNode->getConnectedNodes().clear(); - tNode->getConnectedNodes().push_back(bNode->GetIndex()); } } } - std::vector<MeshLib::CElem*> new_elems; - std::vector<size_t> false_node_idx; - size_t nElems = mesh->ele_vector.size(); - for(size_t i = 0; i < nElems; i++) - { - MeshLib::CElem* elem = mesh->ele_vector[i]; - elem->SetMark(true); - - flat = 0; - for (size_t k = 0; k < 3; k++) //skip element when one node is marked ref_dep - - if ( fabs(elem->GetNode(k)->getData()[2] + ref_dep) < - std::numeric_limits<double>::min() || - fabs(elem->GetNode(k + 3)->getData()[2] + ref_dep) < - std::numeric_limits<double>::min() ) - { - flat = 1; - elem->SetMark(false); - break; - } - if (flat == 1) - continue; - - // If all nodes are okay, check if two z-values are identical - for (size_t k = 0; k < 3; k++) - if(fabs(elem->GetNode(k + - 3)->getData()[2] - elem->GetNode(k)->getData()[2]) < - std::numeric_limits<double>::min()) - false_node_idx.push_back(k); - - switch(false_node_idx.size()) - { - case 0: // everything okay, take the prism as it is - { - elem->SetMark(true); - break; - } - case 1: // one node of the prism is marked false, i.e. create two tetrahedron elements from the remaining 5 prism nodes - { - size_t a = false_node_idx[0]; - size_t b = (a + 2) % 3; - size_t c = (a + 1) % 3; - - if (elem->GetNode(a + 3)->GetBoundaryType() == '1') //24.02.2009. WW - elem->GetNode(a)->SetBoundaryType('1'); - - // create a new tetrahedron - MeshLib::CElem* new_elem( new MeshLib::CElem() ); - new_elem->SetMark(true); - new_elem->SetElementType(MshElemType::TETRAHEDRON); - new_elem->SetPatchIndex(elem->GetPatchIndex()); - new_elem->SetBoundaryType('I'); - new_elem->SetNodesNumber(4); - - Math_Group::vec<MeshLib::CNode*> nodes(4); - nodes[0] = mesh->nod_vector[elem->getNodeIndices()[a]]; - nodes[1] = mesh->nod_vector[elem->getNodeIndices()[b + 3]]; - nodes[2] = mesh->nod_vector[elem->getNodeIndices()[c + 3]]; - nodes[3] = mesh->nod_vector[elem->getNodeIndices()[c]]; - new_elem->SetNodes(nodes, true); - - new_elem->getNodeIndices().resize(4); - for (size_t k = 0; k < 4; k++) - new_elem->getNodeIndices()[k] = elem->GetNode(k)->GetIndex(); - new_elems.push_back(new_elem); - - // change prism-element to 2nd tetrahedron - elem->SetMark(true); - elem->SetElementType(MshElemType::TETRAHEDRON); - elem->SetNodesNumber(4); - - nodes[0] = mesh->nod_vector[elem->getNodeIndices()[b]]; - nodes[1] = mesh->nod_vector[elem->getNodeIndices()[a]]; - nodes[2] = mesh->nod_vector[elem->getNodeIndices()[c]]; - nodes[3] = mesh->nod_vector[elem->getNodeIndices()[b + 3]]; - elem->SetNodes(nodes, true); - - elem->getNodeIndices().resize(4); - for (size_t k = 0; k < 4; k++) - elem->getNodeIndices()[k] = elem->GetNode(k)->GetIndex(); - break; - } - case 2: // two nodes of the prism are marked false, i.e. create a tetrahedron element from the remaining 4 prism nodes - { - size_t a = false_node_idx[0]; - size_t b = (a + 2) % 3; - size_t c = (a + 1) % 3; - if (false_node_idx[1] == b) - a = c; - else if(false_node_idx[1] == c) - a = b; - - elem->SetMark(true); - elem->SetElementType(MshElemType::TETRAHEDRON); - elem->SetNodesNumber(4); - - Math_Group::vec<MeshLib::CNode*> nodes(4); - nodes[0] = mesh->nod_vector[elem->getNodeIndices()[b]]; - nodes[1] = mesh->nod_vector[elem->getNodeIndices()[a]]; - nodes[2] = mesh->nod_vector[elem->getNodeIndices()[c]]; - nodes[3] = mesh->nod_vector[elem->getNodeIndices()[a + 3]]; - elem->SetNodes(nodes, true); - - elem->getNodeIndices().resize(4); - for (size_t k = 0; k < 4; k++) - elem->getNodeIndices()[k] = elem->GetNode(k)->GetIndex(); - /* - //for j, l nodes if they becomes on top surface. 24.02.2009. WW - if (node_b->GetBoundaryType()=='1') - elem->nodes[0]->SetBoundaryType('1'); - if (node_t->GetBoundaryType()=='1') - elem->nodes[2]->SetBoundaryType('1'); - */ - break; - } - case 3: // three nodes of the prism is marked false, ditch the whole element - { - elem->SetMark(false); - break; - } - } - } - - // add the newly created elements to the elements vector - for(size_t i = 0; i < new_elems.size(); i++) - mesh->ele_vector.push_back(new_elems[i]); - - // correct indeces of elements and delete false elements - std::vector<MeshLib::CElem*>::iterator beg_e = mesh->ele_vector.begin( ), last_e; - long counter = 0; - while ( beg_e != mesh->ele_vector.end() ) + std::vector<GEOLIB::Point*> *nodes = new std::vector<GEOLIB::Point*>; + std::vector<int> node_index_map(nNodes, -1); + size_t node_count(0); + for (size_t j=0; j<nNodes; j++) { - last_e = beg_e++; - MeshLib::CElem* elem = *last_e; - if (elem->GetMark()) + if (nodes_below_surface[j]) { - elem->SetIndex(counter); - counter++; - /* KR unused variable - for (int j=0; j<elem->GetVertexNumber(); j++) - { - if (!elem->GetNode(j)->GetMark()) - { - MeshLib::CNode* node = mesh->nod_vector[elem->GetNode(j)->connected_nodes[0]]; - } - } - */ - } - else - { - delete elem; - beg_e = mesh->ele_vector.erase(last_e); - } - } - - // correct indeces of nodes and delete false nodes - counter = 0; - std::vector<MeshLib::CNode*>::iterator beg = mesh->nod_vector.begin( ), last; - while ( beg != mesh->nod_vector.end( ) ) - { - last = beg++; - MeshLib::CNode* node = *last; - if (node->GetMark()) - { - node->SetIndex(counter); - node->getConnectedElementIDs().clear(); - node->getConnectedNodes().clear(); - counter++; - } - else - { - delete node; - node = NULL; - beg = mesh->nod_vector.erase(last); - } + nodes->push_back(new GEOLIB::Point(mesh->nod_vector[j]->getData())); + node_index_map[j]=node_count++; + } } - // correct element indeces again after deleting nodes - nElems = mesh->ele_vector.size(); - for(size_t i = 0; i < nElems; i++) - for(int j = 0; j < mesh->ele_vector[i]->GetVertexNumber(); j++) - mesh->ele_vector[i]->getNodeIndices()[j] = - mesh->ele_vector[i]->GetNode(j)->GetIndex(); - - // delete elements if two of its nodes are identical (can this actually happen?????) - beg_e = mesh->ele_vector.begin(); - counter = 0; - bool flatf = false; - while ( beg_e != mesh->ele_vector.end( ) ) + const size_t nElems = mesh->ele_vector.size(); + std::vector<GridAdapter::Element*> *elements = new std::vector<GridAdapter::Element*>; + for (size_t j=0; j<nElems; j++) { - last_e = beg_e++; - MeshLib::CElem* elem = *last_e; - - //10.02.2009. WW !!!!!!!!!!!!!!!!!!!!!! - for (int j = 0; j < elem->GetVertexNumber(); j++) + const MeshLib::CElem* elem = mesh->ele_vector[j]; + + size_t count(0); + for (size_t i=0; i<6; i++) // check top surface of prism + if (nodes_below_surface[elem->GetNodeIndex(i)]) count++; + + if (count==6) // copy prism elements if all six nodes are valid { - flatf = false; - for (int k = j; k < elem->GetVertexNumber(); k++) - if (elem->GetNodeIndex(j) == elem->GetNodeIndex(k)) - { - flatf = true; - break; - } + GridAdapter::Element* prism = new GridAdapter::Element; + std::vector<size_t> elem_nodes; + for (size_t i=0; i<6; i++) + elem_nodes.push_back( node_index_map[elem->GetNodeIndex(i)] ); + prism->material = elem->GetPatchIndex(); + prism->type = MshElemType::PRISM; + prism->nodes = elem_nodes; + elements->push_back(prism); } - if (flatf) + else if (count==5) // change the current element to two tetrahedra if only five nodes are valid { - delete elem; - beg_e = mesh->ele_vector.erase(last_e); + GridAdapter::Element* tet1 = new GridAdapter::Element; + std::vector<size_t> elem_nodes; + if (nodes_below_surface[elem->GetNodeIndex(0)]) + elem_nodes.push_back( node_index_map[elem->GetNodeIndex(0)] ); + else + elem_nodes.push_back( node_index_map[elem->GetNodeIndex(1)] ); + for (size_t i=3; i<6; i++) + elem_nodes.push_back( node_index_map[elem->GetNodeIndex(i)] ); + tet1->material = elem->GetPatchIndex(); + tet1->type = MshElemType::TETRAHEDRON; + tet1->nodes = elem_nodes; + elements->push_back(tet1); + + GridAdapter::Element* tet2 = new GridAdapter::Element; + std::vector<size_t> elem_nodes2; + if (nodes_below_surface[elem->GetNodeIndex(0)]) + { + elem_nodes2.push_back( node_index_map[elem->GetNodeIndex(0)] ); + if (nodes_below_surface[elem->GetNodeIndex(1)]) + elem_nodes2.push_back( node_index_map[elem->GetNodeIndex(1)] ); + else + elem_nodes2.push_back( node_index_map[elem->GetNodeIndex(2)] ); + elem_nodes2.push_back( node_index_map[elem->GetNodeIndex(5)] ); + elem_nodes2.push_back( node_index_map[elem->GetNodeIndex(4)] ); + } + else + { + elem_nodes2.push_back( node_index_map[elem->GetNodeIndex(1)] ); + elem_nodes2.push_back( node_index_map[elem->GetNodeIndex(2)] ); + elem_nodes2.push_back( node_index_map[elem->GetNodeIndex(3)] ); + elem_nodes2.push_back( node_index_map[elem->GetNodeIndex(5)] ); + } + tet2->material = elem->GetPatchIndex(); + tet2->type = MshElemType::TETRAHEDRON; + tet2->nodes = elem_nodes2; + elements->push_back(tet2); } - else + else if (count==4) // change the current element to a tetrahedron if only four nodes are valid { - elem->SetIndex(counter); - counter++; - /* KR unused variable - for (int j=0; j<elem->GetVertexNumber(); j++) - { - if (!elem->GetNode(j)->GetMark()) - { - MeshLib::CNode* node = mesh->nod_vector[elem->GetNode(j)->connected_nodes[0]]; - } - } - */ - } - } + std::vector<size_t> elem_nodes; + for (size_t i=0; i<3; i++) + if (nodes_below_surface[elem->GetNodeIndex(i)]) + elem_nodes.push_back( node_index_map[elem->GetNodeIndex(i)] ); - mesh->ConnectedElements2Node(); - - // delete nodes that are not connected to any element (can this happen???) - counter = 0; - beg = mesh->nod_vector.begin( ); - while ( beg != mesh->nod_vector.end( ) ) - { - last = beg++; - MeshLib::CNode* node = *last; - if ( node->getConnectedElementIDs().empty() ) - { - delete node; - node = NULL; - beg = mesh->nod_vector.erase(last); - } - else - { - node->SetIndex(counter); - counter++; + if (elem_nodes.size()==1) // make sure than only one node is from the upper layer and three from the lower + { + for (size_t i=3; i<6; i++) + elem_nodes.push_back( node_index_map[elem->GetNodeIndex(i)] ); + GridAdapter::Element* tet = new GridAdapter::Element; + tet->material = elem->GetPatchIndex(); + tet->type = MshElemType::TETRAHEDRON; + tet->nodes = elem_nodes; + elements->push_back(tet); + } } + // else remove element, if less than four nodes are valid } - - nElems = mesh->ele_vector.size(); - for (size_t i = 0; i < nElems; i++) - for (int j = 0; j < mesh->ele_vector[i]->GetVertexNumber(); j++) - mesh->ele_vector[i]->getNodeIndices()[j] = - mesh->ele_vector[i]->GetNode(j)->GetIndex(); - - mesh->ConstructGrid(); + GridAdapter grid; + grid.setNodeVector(nodes); + grid.setElements(elements); + MeshLib::CFEMesh* struct_mesh = new MeshLib::CFEMesh(*grid.getCFEMesh()); + return struct_mesh; } + diff --git a/DataView/MshLayerMapper.h b/DataView/MshLayerMapper.h index da1efe476b5254899bf26d0f2bb08fa881174a31..daf3833971a427b881adc03d22191f9965e7d5a5 100644 --- a/DataView/MshLayerMapper.h +++ b/DataView/MshLayerMapper.h @@ -36,16 +36,14 @@ public: double thickness); /// Maps the z-values of nodes in the designated layer of the given mesh according to the given raster. - static MeshLib::CFEMesh* LayerMapping(const MeshLib::CFEMesh* msh, + static int LayerMapping(MeshLib::CFEMesh* msh, const std::string &rasterfile, const size_t nLayers, const size_t layer_id, bool removeNoDataValues = false); - /// \brief Checks for overlapping nodes between between layers and corrects these errors. - /// Note: this method has not been tested yet and will probably fail miserably! Please contact KR - /// if you intend to use it! - static void CheckLayerMapping(MeshLib::CFEMesh* mesh, const size_t nLayers, int integ); + /// Blends a mesh with the surface given by dem_raster. Nodes and elements above the surface are either removed or adapted to fit the surface. + static MeshLib::CFEMesh* blendLayersWithSurface(MeshLib::CFEMesh* mesh, const size_t nLayers, const std::string &dem_raster); private: /// Checks if the given mesh is within the dimensions given by xDim and yDim. diff --git a/DataView/MshModel.cpp b/DataView/MshModel.cpp index 1afa1fa25614974a1f887ed64d8a5d6aebd5a3fa..b508d2c056df50889bedaa996882861859d8a5c1 100644 --- a/DataView/MshModel.cpp +++ b/DataView/MshModel.cpp @@ -38,11 +38,22 @@ int MshModel::columnCount( const QModelIndex &parent /*= QModelIndex()*/ ) const void MshModel::addMesh(MeshLib::CFEMesh* mesh, std::string &name) { _project.addMesh(mesh, name); - this->addMeshObject(new GridAdapter(mesh), name); + GridAdapter* grid = new GridAdapter(mesh); + grid->setName(name); + this->addMeshObject(grid); } -void MshModel::addMeshObject(GridAdapter* mesh, std::string &name) +void MshModel::addMesh(GridAdapter* mesh) { + MeshLib::CFEMesh* ogsmesh( const_cast<MeshLib::CFEMesh*>(mesh->getCFEMesh()) ); + std::string msh_name = mesh->getName(); + _project.addMesh(ogsmesh, msh_name); + this->addMeshObject(mesh); +} + +void MshModel::addMeshObject(GridAdapter* mesh) +{ + std::string name(mesh->getName()); std::cout << "name: " << name << std::endl; QFileInfo fi(QString::fromStdString(name)); name = fi.baseName().toStdString(); @@ -56,17 +67,18 @@ void MshModel::addMeshObject(GridAdapter* mesh, std::string &name) // display elements const std::vector<GridAdapter::Element*>* elems = mesh->getElements(); - size_t nElems (elems->size()); + const size_t nElems (elems->size()); for (size_t i = 0; i < nElems; i++) { + const GridAdapter::Element* current_element = (*elems)[i]; QList<QVariant> elemData; elemData << "Element " + QString::number(i) << QString::fromStdString( - MshElemType2String((*elems)[i]->type)); + MshElemType2String(current_element->type)); QString nodestxt(""); - size_t nNodes((*elems)[i]->nodes.size()); + const size_t nNodes(current_element->nodes.size()); for (size_t j = 0; j < nNodes; j++) - nodestxt.append(QString::number((*elems)[i]->nodes[j]) + ", "); + nodestxt.append(QString::number(current_element->nodes[j]) + ", "); elemData << nodestxt.left(nodestxt.length() - 2); TreeItem* elem = new TreeItem(elemData, newMesh); @@ -121,7 +133,6 @@ bool MshModel::removeMesh(const QModelIndex &idx) return false; } - //std::cout << "MshModel::removeMesh() - Specified index does not exist." << std::endl; return false; } @@ -152,7 +163,7 @@ void MshModel::updateModel() if (this->getMesh(it->first) == NULL) // if GridAdapter does not yet exist, create one. { std::string name = it->first; - addMeshObject(new GridAdapter(it->second), name); + addMeshObject(new GridAdapter(it->second)); } } @@ -182,39 +193,4 @@ VtkMeshSource* MshModel::vtkSource(const std::string &name) const return NULL; } -/* - bool MshModel::isUniqueMeshName(std::string &name) - { - int count(0); - bool isUnique(false); - std::string cpName; - - while (!isUnique) - { - isUnique = true; - cpName = name; - - count++; - // If the original name already exists we start to add numbers to name for - // as long as it takes to make the name unique. - if (count>1) cpName = cpName + "-" + number2str(count); - - for (int i=0; i<_rootItem->childCount(); i++) - { - TreeItem* item = _rootItem->child(i); - if (item->data(0).toString().toStdString().compare(cpName) == 0) isUnique = false; - } - } - - // At this point cpName is a unique name and isUnique is true. - // If cpName is not the original name, "name" is changed and isUnique is set to false, - // indicating that a vector with the original name already exists. - if (count>1) - { - isUnique = false; - name = cpName; - } - return isUnique; - } - */ diff --git a/DataView/MshModel.h b/DataView/MshModel.h index 06890a0c89a79bf3b088786fdea4925c85e612cf..c64edaa90c49f83642af0be9ed97ed360d9e0d6f 100644 --- a/DataView/MshModel.h +++ b/DataView/MshModel.h @@ -30,7 +30,9 @@ public: public slots: /// Adds a new mesh - void addMesh(MeshLib::CFEMesh* mesh, std::string &name); + void addMesh(GridAdapter* mesh); + /// Adds a new mesh + void addMesh(MeshLib::CFEMesh* mesh, std::string &name); // needs only to be a slot for MshLayerMapper. Otherwise normal function would be okay. /// Returns the mesh with the given index. const GridAdapter* getMesh(const QModelIndex &idx) const; /// Returns the mesh with the given name. @@ -48,7 +50,7 @@ public slots: private: /// Adds the mesh to the GUI-Mesh-Model und -View - void addMeshObject(GridAdapter* mesh, std::string &name); + void addMeshObject(GridAdapter* mesh); /// Checks if the name of the mesh is already exists, if so it generates a unique name. //bool isUniqueMeshName(std::string &name); diff --git a/DataView/NetCdfConfigure.ui b/DataView/NetCdfConfigure.ui new file mode 100644 index 0000000000000000000000000000000000000000..18ed8e38a2c2432a7866174eb48ae6d19f9985e4 --- /dev/null +++ b/DataView/NetCdfConfigure.ui @@ -0,0 +1,801 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>NetCdfConfigure</class> + <widget class="QDialog" name="NetCdfConfigure"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>477</width> + <height>460</height> + </rect> + </property> + <property name="cursor"> + <cursorShape>SizeAllCursor</cursorShape> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Variable</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="comboBoxVariable"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + </widget> + </item> + <item row="1" column="0" colspan="3"> + <widget class="QGroupBox" name="groupBoxDimensions"> + <property name="minimumSize"> + <size> + <width>450</width> + <height>100</height> + </size> + </property> + <property name="title"> + <string>Dimensions for the Axis</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="3"> + <widget class="QDoubleSpinBox" name="doubleSpinBoxDim1End"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimumSize"> + <size> + <width>110</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>110</width> + <height>16777215</height> + </size> + </property> + <property name="wrapping"> + <bool>false</bool> + </property> + <property name="frame"> + <bool>true</bool> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="accelerated"> + <bool>false</bool> + </property> + <property name="maximum"> + <double>10000000.000000000000000</double> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QDoubleSpinBox" name="doubleSpinBoxDim1Start"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimumSize"> + <size> + <width>110</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="maximum"> + <double>10000000.000000000000000</double> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QDoubleSpinBox" name="doubleSpinBoxDim2Start"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimumSize"> + <size> + <width>110</width> + <height>0</height> + </size> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="maximum"> + <double>10000000.000000000000000</double> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="QDoubleSpinBox" name="doubleSpinBoxDim2End"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimumSize"> + <size> + <width>110</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>110</width> + <height>16777215</height> + </size> + </property> + <property name="font"> + <font> + <italic>false</italic> + </font> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="maximum"> + <double>10000000.000000000000000</double> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Value Start</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Value End</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="comboBoxDim1"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="comboBoxDim2"> + <property name="minimumSize"> + <size> + <width>80</width> + <height>0</height> + </size> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_4"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Lat</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_8"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Lon</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="8" column="2"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="8" column="0" colspan="2"> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="2"> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0" colspan="3"> + <widget class="QGroupBox" name="groupBox"> + <property name="minimumSize"> + <size> + <width>450</width> + <height>0</height> + </size> + </property> + <property name="title"> + <string>Other Dimensions</string> + </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="QLabel" name="label_9"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Time</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_10"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Others</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="comboBoxDim3"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>80</width> + <height>16777215</height> + </size> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="comboBoxDim4"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="minimumSize"> + <size> + <width>80</width> + <height>0</height> + </size> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="QSpinBox" name="spinBoxDim4"> + <property name="minimumSize"> + <size> + <width>110</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>110</width> + <height>16777215</height> + </size> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QDateTimeEdit" name="dateTimeEditDim3"> + <property name="minimumSize"> + <size> + <width>110</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>110</width> + <height>16777215</height> + </size> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="dateTime"> + <datetime> + <hour>0</hour> + <minute>0</minute> + <second>0</second> + <year>1900</year> + <month>1</month> + <day>1</day> + </datetime> + </property> + <property name="date"> + <date> + <year>1900</year> + <month>1</month> + <day>1</day> + </date> + </property> + <property name="maximumDateTime"> + <datetime> + <hour>23</hour> + <minute>59</minute> + <second>59</second> + <year>2200</year> + <month>12</month> + <day>31</day> + </datetime> + </property> + <property name="minimumDateTime"> + <datetime> + <hour>0</hour> + <minute>0</minute> + <second>0</second> + <year>1900</year> + <month>1</month> + <day>1</day> + </datetime> + </property> + <property name="displayFormat"> + <string>dd.MM.yyyy</string> + </property> + <property name="calendarPopup"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="3" column="3"> + <spacer name="horizontalSpacer_8"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="3"> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="3" column="0" colspan="3"> + <widget class="QGroupBox" name="groupBox_2"> + <property name="minimumSize"> + <size> + <width>450</width> + <height>0</height> + </size> + </property> + <property name="title"> + <string>Parameters</string> + </property> + <layout class="QGridLayout" name="gridLayout_5"> + <item row="0" column="0"> + <widget class="QLabel" name="label_5"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Resolution</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <spacer name="horizontalSpacer_9"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBoxResolution"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="decimals"> + <number>3</number> + </property> + <property name="minimum"> + <double>0.000000000000000</double> + </property> + <property name="maximum"> + <double>10000.000000000000000</double> + </property> + <property name="singleStep"> + <double>1.000000000000000</double> + </property> + <property name="value"> + <double>1.000000000000000</double> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>m</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="7" column="0" colspan="3"> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>Object</string> + </property> + <layout class="QGridLayout" name="gridLayout_6"> + <item row="0" column="0"> + <widget class="QLabel" name="label_12"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>Name</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="lineEditName"> + <property name="minimumSize"> + <size> + <width>220</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>110</width> + <height>16777215</height> + </size> + </property> + </widget> + </item> + <item row="0" column="2"> + <spacer name="horizontalSpacer_6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="4" column="0" colspan="3"> + <widget class="QGroupBox" name="groupBoxMesh"> + <property name="minimumSize"> + <size> + <width>450</width> + <height>50</height> + </size> + </property> + <property name="title"> + <string>Output</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="2"> + <widget class="QLabel" name="label_2"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Mesh Element Type</string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QComboBox" name="comboBoxMeshElemType"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <item> + <property name="text"> + <string>Quad</string> + </property> + </item> + <item> + <property name="text"> + <string>Triangle</string> + </property> + </item> + </widget> + </item> + <item row="2" column="2"> + <widget class="QLabel" name="label_3"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Use Intensity as</string> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="QComboBox" name="comboBoxUseIntensity"> + <item> + <property name="text"> + <string>Material</string> + </property> + </item> + <item> + <property name="text"> + <string>Evelation</string> + </property> + </item> + </widget> + </item> + <item row="1" column="0"> + <widget class="QRadioButton" name="radioMesh"> + <property name="text"> + <string>Mesh</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QRadioButton" name="radioImage"> + <property name="text"> + <string>Raster</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>50</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="1"> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>50</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="4"> + <spacer name="horizontalSpacer_7"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="4"> + <spacer name="horizontalSpacer_10"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>NetCdfConfigure</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>NetCdfConfigure</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/DataView/NetCdfConfigureDialog.cpp b/DataView/NetCdfConfigureDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ba643d1c63c610ec8324dfb5dad842c4e6aa341 --- /dev/null +++ b/DataView/NetCdfConfigureDialog.cpp @@ -0,0 +1,448 @@ +//file NetCDFConfigureDialog.cpp +//CH Initial implementation + +#include "NetCdfConfigureDialog.h" + +#include "VtkMeshConverter.h" +#include "GridAdapter.h" +#include "VtkGeoImageSource.h" +#include "VtkRaster.h" + +#include <QMessageBox> +#include <QSettings> + +#include <vtkImageImport.h> + +// Constructor +NetCdfConfigureDialog::NetCdfConfigureDialog(const std::string &fileName, QDialog* parent) + : QDialog(parent), _currentFile(new NcFile(fileName.c_str(), NcFile::ReadOnly)), + _currentInitialDateTime(QDateTime()), _currentMesh(NULL), _currentRaster(NULL), _currentPath(fileName) +{ + setupUi(this); + + setVariableSelect(); // set up variables of the file in the combobox + comboBoxVariable->setCurrentIndex(valueWithMaxDim()); //pre-select the variable with the biggest number of dimensions...valueWithMaxDim() + + _currentVar = _currentFile->get_var(comboBoxVariable->currentIndex()); + + setDimensionSelect(); + + lineEditName->setText(setName()); + + this->radioMesh->setChecked(true); + +} + +NetCdfConfigureDialog::~NetCdfConfigureDialog() +{ +} + +// Instructions if the OK-Button has been pressed. +void NetCdfConfigureDialog::accept() +{ + QMessageBox valueErrorBox; + if (_currentVar->num_dims() < 3){ + valueErrorBox.setText("Selected Variable has not enough dimensions."); + valueErrorBox.exec(); + }else if (doubleSpinBoxDim2Start->value() == doubleSpinBoxDim2Start->maximum()){ + valueErrorBox.setText("Lon has invalid extend."); + valueErrorBox.exec(); + }else if(doubleSpinBoxDim1Start->value() == doubleSpinBoxDim1Start->maximum()){ + valueErrorBox.setText("Lat has invalid extend."); + valueErrorBox.exec(); + }else{ + createDataObject(); + delete _currentFile; + this->done(QDialog::Accepted); + } +} + +// Instructions if the Cancel-Button has been pressed. +void NetCdfConfigureDialog::reject() +{ + delete _currentFile; + this->done(QDialog::Rejected); +} + +int NetCdfConfigureDialog::valueWithMaxDim() +{ + int idMaxDim = 0; + for (int i=0; i < _currentFile->num_dims(); i++) + { + if ((_currentFile->get_var(i)->num_dims()) > 0) idMaxDim = i + 1; + } + return idMaxDim; +} + +void NetCdfConfigureDialog::on_comboBoxVariable_currentIndexChanged(int id) +{ + _currentVar = _currentFile->get_var(id); + setDimensionSelect(); +} + +//set up x-axis/lat +void NetCdfConfigureDialog::on_comboBoxDim1_currentIndexChanged(int id) +{ + if (id == -1) id = 0; + double firstValue=0, lastValue=0; + size_t size = 0; + getDimEdges(id,size,firstValue,lastValue); + doubleSpinBoxDim1Start->setValue(firstValue); + doubleSpinBoxDim1End->setValue(lastValue); + doubleSpinBoxResolution->setValue(getResolution()); +} + +//set up y-axis/lon +void NetCdfConfigureDialog::on_comboBoxDim2_currentIndexChanged(int id) +{ + if (_currentVar->num_dims() > 1) + { + if (id == -1) id = 0; + double firstValue=0, lastValue=0; + size_t size = 0; + getDimEdges(id,size,firstValue,lastValue); + doubleSpinBoxDim2Start->setValue(firstValue); + doubleSpinBoxDim2End->setValue(lastValue); + } +} + +//set up time +void NetCdfConfigureDialog::on_comboBoxDim3_currentIndexChanged(int id) +{ + if (_currentVar->num_dims() > 2) + { + if (id == -1) id = 0; + double firstValue=0, lastValue=0; + size_t size = 0; + getDimEdges(id,size,firstValue,lastValue); + + QTime firstTime(0,0,0), lastTime(0,0,0); + int firstDaysToAdd = 0, lastDaysToAdd = 0; + + getDaysTime(firstValue,firstTime,firstDaysToAdd); + getDaysTime(lastValue,lastTime,lastDaysToAdd); + + QDate initialDate(1960,1,1); + QTime initialTime(0,0); + + QDateTime initialDateTime; + initialDateTime.setDate(initialDate); + initialDateTime.setTime(initialTime); + + QDateTime firstDateTime = initialDateTime.addDays(firstDaysToAdd); + firstDateTime.setTime(firstTime); + + QDateTime lastDateTime = initialDateTime.addDays(lastDaysToAdd); + lastDateTime.setTime(lastTime); + + dateTimeEditDim3->setDateTime(firstDateTime); + dateTimeEditDim3->setMinimumDateTime(firstDateTime); + dateTimeEditDim3->setMaximumDateTime(lastDateTime); + + _currentInitialDateTime = initialDateTime; + lineEditName->setText(setName()); + } +} + +//set up additional dimension +void NetCdfConfigureDialog::on_comboBoxDim4_currentIndexChanged(int id) +{ + if (_currentVar->num_dims() > 3) + { + if (id == -1) id = 0; + double firstValue=0, lastValue=0; + size_t size = 0; + getDimEdges(id,size,firstValue,lastValue); + spinBoxDim4->setValue(firstValue); + spinBoxDim4->setMinimum(firstValue); + spinBoxDim4->setMaximum(lastValue); + } +} + +void NetCdfConfigureDialog::setVariableSelect() +{ + for (int i=0; i<(_currentFile->num_vars()); i++) + { + NcVar *focusedVar = _currentFile->get_var(i); + if (focusedVar->num_dims() > 0) comboBoxVariable->addItem(focusedVar->name()); + } +} + +void NetCdfConfigureDialog::setDimensionSelect() +{ + comboBoxDim1->clear(); + comboBoxDim2->clear(); + comboBoxDim3->clear(); + comboBoxDim4->clear(); + for (int i=0; i < _currentVar->num_dims(); i++) //write dimension-names into selection-boxes + { + comboBoxDim1->addItem(_currentVar->get_dim(i)->name()); + comboBoxDim2->addItem(_currentVar->get_dim(i)->name()); + comboBoxDim3->addItem(_currentVar->get_dim(i)->name()); + comboBoxDim4->addItem(_currentVar->get_dim(i)->name()); + } + if (_currentVar->num_dims() < 4) + { + comboBoxDim4->setEnabled(false);comboBoxDim4->clear(); + spinBoxDim4->setEnabled(false);spinBoxDim4->setValue(0); + }else{ //pre-set dimension selection, typical for 4-d-nc-files: + comboBoxDim4->setEnabled(true); + spinBoxDim4->setEnabled(true); + comboBoxDim1->setCurrentIndex(2);on_comboBoxDim1_currentIndexChanged(2); + comboBoxDim2->setCurrentIndex(3);on_comboBoxDim2_currentIndexChanged(3); + comboBoxDim3->setCurrentIndex(0);on_comboBoxDim3_currentIndexChanged(0); + comboBoxDim4->setCurrentIndex(1);on_comboBoxDim4_currentIndexChanged(1); + } + if (_currentVar->num_dims() == 3) //pre-set dimension selection, typical for 3-d-nc-files: + { + comboBoxDim1->setCurrentIndex(1);on_comboBoxDim1_currentIndexChanged(1); + comboBoxDim2->setCurrentIndex(2);on_comboBoxDim2_currentIndexChanged(2); + comboBoxDim3->setCurrentIndex(0);on_comboBoxDim3_currentIndexChanged(0); + } + if (_currentVar->num_dims() < 3) + { + comboBoxDim3->setEnabled(false);comboBoxDim3->clear(); + dateTimeEditDim3->setEnabled(false);dateTimeEditDim3->setDateTime(_currentInitialDateTime); + + }else{ + comboBoxDim3->setEnabled(true); + dateTimeEditDim3->setEnabled(true); + } + if (_currentVar->num_dims() < 2) + { + comboBoxDim2->setEnabled(false);comboBoxDim2->clear(); + doubleSpinBoxDim2Start->setValue(0); doubleSpinBoxDim2End->setValue(0); + }else{ + comboBoxDim2->setEnabled(true); + } + +} + +void NetCdfConfigureDialog::getDimEdges(int dimId, size_t &size, double &firstValue, double &lastValue) +{ + if ((_currentFile->get_var(_currentVar->get_dim(dimId)->name())) != NULL) + { + NcVar *tmpVarOfDim = _currentFile->get_var(_currentVar->get_dim(dimId)->name()); + if ((tmpVarOfDim->num_dims()) == 1) + { + int sizeOfDim = tmpVarOfDim->get_dim(0)->size(); + size = sizeOfDim; + double arrayOfDimStart[1] = {0}; + size_t edgeOfArray[1] = {1}; + long edgeOrigin[1] = {0}; + tmpVarOfDim->set_cur(edgeOrigin); + tmpVarOfDim->get(arrayOfDimStart,edgeOfArray); + firstValue = arrayOfDimStart[0]; + double arrayOfDimEnd[1] = {0}; + edgeOrigin[0] = sizeOfDim - 1; + tmpVarOfDim->set_cur(edgeOrigin); + tmpVarOfDim->get(arrayOfDimEnd,edgeOfArray); + lastValue = arrayOfDimEnd[0]; + } + }else{ + size = 0; + firstValue = 0; + lastValue = 0; + } +} + +void NetCdfConfigureDialog::getDaysTime(double minSince, QTime &time, int &days) +{ + long tmpMin = (long) minSince; + long minuits = tmpMin % 60; + long tmpHours = tmpMin / 60; + long hours = tmpHours % 24; + days = (int) (tmpHours / 24); + time.setHMS(hours,minuits,0); +} + +long NetCdfConfigureDialog::convertDateToMinutes(QDateTime initialDateTime, QDate selectedDate, QTime selectedTime) +{ + int tmpInitialToSelectedDate = (selectedDate.daysTo(initialDateTime.date())); + long selectedDays = - tmpInitialToSelectedDate * 24 * 60; + long selectedMinutes = (selectedTime.hour() * 60) + selectedTime.minute() + selectedDays; + return selectedMinutes; +} + +int NetCdfConfigureDialog::getTimeStep() +{ + NcVar* timeVar = _currentFile->get_var(comboBoxDim2->currentIndex()); + + int datesToMinutes = convertDateToMinutes(_currentInitialDateTime,dateTimeEditDim3->date(),dateTimeEditDim3->time()); + + double timeArray[1] = {datesToMinutes}; + double currentTime = timeVar->get_index(timeArray); + if (currentTime < 0) currentTime=0; //if the value isn't found in the array, set it to 0 as default... + return currentTime; +} + +int NetCdfConfigureDialog::getDim4() +{ + NcVar* dim3Var = _currentFile->get_var(comboBoxDim4->currentIndex()); + double timeArray[1] = {spinBoxDim4->value()}; + double currentValueDim3 = dim3Var->get_index(timeArray); + if (currentValueDim3 < 0) currentValueDim3=0; //if the value isn't found in the array, set it to 0 as default... + return currentValueDim3; +} + +double NetCdfConfigureDialog::getResolution() +{ + if (comboBoxDim1->currentIndex() > -1) + { + NcVar *latVar = _currentFile->get_var(comboBoxDim1->currentIndex()); + double firstValue=0, lastValue=0; + size_t size=0; + getDimEdges(latVar->id(),size,firstValue,lastValue); + if (size < 2) + { + return 1; + } + else + { + double interval = fabs(lastValue-firstValue); + double resolution = (double)interval/(size-1); + return resolution; + } + } + else + { + return 0; + } +} + +void NetCdfConfigureDialog::createDataObject() +{ + size_t* length = new size_t[_currentVar->num_dims()]; + double originLon = 0, originLat = 0; + double lastLon = 0, lastLat = 0; + size_t sizeLon = 0, sizeLat = 0; + getDimEdges(comboBoxDim1->currentIndex(), sizeLat, originLat, lastLat); + getDimEdges(comboBoxDim2->currentIndex(), sizeLon, originLon, lastLon); + + for(int i=0; i < _currentVar->num_dims(); i++) length[i]=1; + + // set array edges: lat x lon + length[comboBoxDim1->currentIndex()]=sizeLat; + length[comboBoxDim2->currentIndex()]=sizeLon; + + // set up array + double* data_array = new double[sizeLat*sizeLon]; + for(size_t i=0; i < (sizeLat*sizeLon); i++) data_array[i]=0; + + //Time-Dimension: + if (_currentVar->num_dims() > 2) + { + long* newOrigin = new long[_currentVar->num_dims()]; + for (int i=0; i < _currentVar->num_dims(); i++) newOrigin[i]=0; + newOrigin[comboBoxDim3->currentIndex()] = getTimeStep(); //set origin to selected time + _currentVar->set_cur(newOrigin); + //Dimension 4: + if (_currentVar->num_dims() > 3) newOrigin[comboBoxDim4->currentIndex()] = getDim4(); //if there are is a 4th dimension + delete newOrigin; + } + + _currentVar->get(data_array,length); //create Array of Values + + for (size_t i=0; i < (sizeLat*sizeLon); i++) + { + //data_array[i] = data_array[i] - 273; // convert from kalvin to celsius + if (data_array[i] < -9999 ) data_array[i] = -9999; // all values < -10000, set to "no-value" + } + + double origin_x = (originLon < lastLon) ? originLon : lastLon; + double origin_y = (originLat < lastLat) ? originLat : lastLat; + double originNetCdf[3] = {origin_x, origin_y, 0}; + + double resolution = (doubleSpinBoxResolution->value()); + + if (originLat > lastLat) // reverse lines in vertical direction if the original file has its origin in the northwest corner + this->reverseNorthSouth(data_array, sizeLon, sizeLat); + + if (this->radioMesh->isChecked()) + { + MshElemType::type meshElemType = MshElemType::QUAD; + UseIntensityAs::type useIntensity = UseIntensityAs::MATERIAL; + if ((comboBoxMeshElemType->currentIndex()) == 1) + { + meshElemType = MshElemType::TRIANGLE; + }else{ + meshElemType = MshElemType::QUAD; + } + if ((comboBoxUseIntensity->currentIndex()) == 1) + { + useIntensity = UseIntensityAs::ELEVATION; + }else{ + useIntensity = UseIntensityAs::MATERIAL; + } + + _currentMesh = VtkMeshConverter::convertImgToMesh(data_array,originNetCdf,sizeLon,sizeLat,resolution,meshElemType,useIntensity); + } + else + { + vtkImageImport* image = VtkRaster::loadImageFromArray(data_array, originNetCdf[0], originNetCdf[1], sizeLon, sizeLat, resolution, -9999.0); + _currentRaster = VtkGeoImageSource::New(); + _currentRaster->setImage(image, QString::fromStdString(this->getName()), originNetCdf[0], originNetCdf[1], resolution); + } + + delete[] length; + delete[] data_array; +} + +QString NetCdfConfigureDialog::setName() +{ + std::string name; + name.append(_currentPath); + name.erase(0,name.find_last_of("/")+1); + name.erase(name.find_last_of(".")); + QString qstr = QString::fromStdString(name); + return qstr; +} + +std::string NetCdfConfigureDialog::getName() +{ + std::string name = (lineEditName->text()).toStdString(); + QString date = dateTimeEditDim3->date().toString(Qt::LocalDate); + name.append(" - ").append(date.toStdString()); + return name; +} + +void NetCdfConfigureDialog::reverseNorthSouth(double* data, size_t width, size_t height) +{ + double* cp_array = new double[width*height]; + + for (size_t i=0; i<height; i++) + { + for (size_t j=0; j<width; j++) + { + size_t old_index((width*height)-(width*(i+1))); + size_t new_index(width*i); + cp_array[new_index+j] = data[old_index+j]; + } + } + + size_t length(height*width); + for (size_t i=0; i<length; i++) + data[i] = cp_array[i]; + + delete[] cp_array; +} + +void NetCdfConfigureDialog::on_radioMesh_toggled(bool isTrue) +{ + if (isTrue) // output set to "mesh" + { + this->label_2->setEnabled(true); + this->label_3->setEnabled(true); + this->comboBoxMeshElemType->setEnabled(true); + this->comboBoxUseIntensity->setEnabled(true); + } + else // output set to "raster" + { + this->label_2->setEnabled(false); + this->label_3->setEnabled(false); + this->comboBoxMeshElemType->setEnabled(false); + this->comboBoxUseIntensity->setEnabled(false); + } +} + + diff --git a/DataView/NetCdfConfigureDialog.h b/DataView/NetCdfConfigureDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..debce10ad6ebec676030eb24b804cdc7de8987aa --- /dev/null +++ b/DataView/NetCdfConfigureDialog.h @@ -0,0 +1,58 @@ +//file NetCDFConfigureDialog.cpp +//CH Initial implementation + +#ifndef NETCDFCONFIGUREDIALOG_H +#define NETCDFCONFIGUREDIALOG_H + +#include <vtknetcdf/netcdfcpp.h> +#include <QDialog> +#include "ui_NetCdfConfigure.h" + +class GridAdapter; +class VtkGeoImageSource; + +class NetCdfConfigureDialog : public QDialog, private Ui_NetCdfConfigure +{ + Q_OBJECT + +public: + NetCdfConfigureDialog(const std::string &fileName, QDialog* parent = 0); + ~NetCdfConfigureDialog(void); + GridAdapter* getMesh() { return _currentMesh; }; + std::string getName(); + VtkGeoImageSource* getRaster() { return _currentRaster; }; + +private slots: + void accept(); + void reject(); + void on_comboBoxVariable_currentIndexChanged(int id); + void on_comboBoxDim1_currentIndexChanged(int id); + void on_comboBoxDim2_currentIndexChanged(int id); + void on_comboBoxDim3_currentIndexChanged(int id); + void on_comboBoxDim4_currentIndexChanged(int id); + void on_radioMesh_toggled(bool isTrue); + +private: + void setVariableSelect(); + void setDimensionSelect(); + void getDimEdges(int dimId,size_t &size, double &firstValue, double &lastValue); + void getDaysTime(double minSince, QTime &time, int &days); + long convertDateToMinutes(QDateTime initialDateTime,QDate selectedDate, QTime selectedTime); + void createDataObject(); + int valueWithMaxDim(); + int getTimeStep(); + int getDim4(); + double getResolution(); + QString setName(); + void reverseNorthSouth(double* data, size_t width, size_t height); + + NcFile *_currentFile; + NcVar *_currentVar; + QDateTime _currentInitialDateTime; + GridAdapter* _currentMesh; + VtkGeoImageSource* _currentRaster; + std::string _currentPath; +}; + +#endif //NETCDFCONFIGUREDIALOG_H + diff --git a/DataView/OGSRaster.cpp b/DataView/OGSRaster.cpp deleted file mode 100644 index b5727f52c5925b8917f370519d1d667253a5e214..0000000000000000000000000000000000000000 --- a/DataView/OGSRaster.cpp +++ /dev/null @@ -1,429 +0,0 @@ -/** - * \file OGSRaster.cpp - * 11/01/2010 KR Initial implementation - */ - -#include <cmath> -#include <iomanip> -#include <iostream> -#include <sstream> - -#include <QFileInfo> -#include <QImage> -#include <QPointF> - -#include "OGSError.h" -#include "OGSRaster.h" -#include "StringTools.h" - -#ifdef libgeotiff_FOUND -#include "geo_tiffp.h" -#include "xtiffio.h" -#endif - -bool OGSRaster::loadImage(const QString &fileName, QImage &raster, QPointF &origin, - double &scalingFactor, bool autoscale /* = true */, bool mirrorX /* = false */) -{ - QFileInfo fileInfo(fileName); - origin.setX(0); - origin.setY(0); - scalingFactor = 1; - - if (fileInfo.suffix().toLower() == "asc") - { - if (!loadImageFromASC(fileName, raster, origin, scalingFactor, autoscale)) - return false; - if (mirrorX) - raster = raster.transformed(QTransform(1, 0, 0, -1, 0, 0), Qt::FastTransformation); - } -#ifdef libgeotiff_FOUND - else if (fileInfo.suffix().toLower() == "tif") - { - if (!loadImageFromTIFF(fileName, raster, origin, scalingFactor)) - return false; - if (!mirrorX) - raster = raster.transformed(QTransform(1, 0, 0, -1, 0, 0), Qt::FastTransformation); - } -#endif - else if (!loadImageFromFile(fileName, raster)) - return false; - return true; -} - -bool OGSRaster::loadImageFromASC(const QString &fileName, - QImage &raster, - QPointF &origin, - double &cellsize, - bool autoscale) -{ - std::ifstream in( fileName.toStdString().c_str() ); - - if (!in.is_open()) - { - std::cout << "OGSRaster::loadImageFromASC() - Could not open file..." << std::endl; - return false; - } - - ascHeader header; - - if (readASCHeader(header, in)) - { - int index = 0, gVal; - double value, minVal = 65536, maxVal = 0; - double* pixVal (new double[header.ncols * header.nrows]); - QImage img(header.ncols, header.nrows, QImage::Format_ARGB32); - - std::string s; - // read the file into a double-array - for (int j = 0; j < header.nrows; j++) - { - index = j * header.ncols; - for (int i = 0; i < header.ncols; i++) - { - in >> s; - pixVal[index + i] = strtod(replaceString(",", ".", s).c_str(),0); - if (pixVal[index + i] != header.noData) - { // find intensity bounds but ignore noData values - minVal = (pixVal[index + i] < minVal) ? pixVal[index + i] : minVal; - maxVal = (pixVal[index + i] > maxVal) ? pixVal[index + i] : maxVal; - } - } - } - in.close(); - - // calculate scaling factor for contrast stretching - double scalingFactor = 255.0 / (maxVal - minVal); - - // write re-calculated image intensities to QImage - // the formula used for contrast adjustment is p_new = (value - minval) * (g_max-g_min)/(maxval-minval) - for (int j = 0; j < header.nrows; j++) - { - index = j * header.ncols; - for (int i = 0; i < header.ncols; i++) - { // scale intensities and set nodata values to zero (black) - if (pixVal[index + i] != header.noData) - { - value = pixVal[index + i]; - gVal = (autoscale) ? - static_cast<int> (floor((value -minVal) * scalingFactor)) : static_cast<int> (value); - //gVal = value; // saudi arabia - img.setPixel(i,j, qRgba(gVal, gVal, gVal, 255)); - } - else - img.setPixel(i,j, qRgba(0, 0, 0, 0)); - } - } - - delete [] pixVal; - origin.setX(header.x); - origin.setY(header.y); - cellsize = header.cellsize; - raster = img; - return true; - } - OGSError::box("Error reading file header."); - return false; -} - -bool OGSRaster::readASCHeader(ascHeader &header, std::ifstream &in) -{ - std::string line, tag, value; - - in >> tag; - if (tag.compare("ncols") == 0) - { - in >> value; - header.ncols = atoi(value.c_str()); - } - else - return false; - in >> tag; - if (tag.compare("nrows") == 0) - { - in >> value; - header.nrows = atoi(value.c_str()); - } - else - return false; - in >> tag; - if (tag.compare("xllcorner") == 0) - { - in >> value; - header.x = strtod(replaceString(",", ".", value).c_str(),0); - } - else - return false; - in >> tag; - if (tag.compare("yllcorner") == 0) - { - in >> value; - header.y = strtod(replaceString(",", ".", value).c_str(),0); - } - else - return false; - in >> tag; - if (tag.compare("cellsize") == 0) - { - in >> value; - header.cellsize = strtod(replaceString(",", ".", value).c_str(),0); - } - else - return false; - in >> tag; - if (tag.compare("NODATA_value") == 0) - { - in >> value; - header.noData = atoi(value.c_str()); - } - else - return false; - - // correct raster position by half a pixel for correct visualisation - // argh! wrong! correction has to happen in visualisation object, otherwise the actual data is wrong - //header.x = header.x + (header.cellsize / 2); - //header.y = header.y + (header.cellsize / 2); - - return true; -} - -double* OGSRaster::loadDataFromASC(const QString &fileName, - double &x0, - double &y0, - size_t &width, - size_t &height, - double &delta) -{ - std::ifstream in( fileName.toStdString().c_str() ); - - if (!in.is_open()) - { - std::cout << "OGSRaster::loadImageFromASC() - Could not open file..." << std::endl; - return NULL; - } - - ascHeader header; - - if (readASCHeader(header, in)) - { - x0 = header.x; - y0 = header.y; - width = header.ncols; - height = header.nrows; - delta = header.cellsize; - - double* values = new double[header.ncols * header.nrows]; - - int index(0); - std::string s(""); - // read the file into a double-array - for (int j = 0; j < header.nrows; j++) - { - index = (header.nrows - j - 1) * header.ncols; - for (int i = 0; i < header.ncols; i++) - { - in >> s; - values[index + i] = strtod(replaceString(",", ".", s).c_str(),0); - } - } - - in.close(); - return values; - } - return NULL; -} - -#ifdef libgeotiff_FOUND -bool OGSRaster::loadImageFromTIFF(const QString &fileName, - QImage &raster, - QPointF &origin, - double &cellsize) -{ - TIFF* tiff = XTIFFOpen(fileName.toStdString().c_str(), "r"); - - if (tiff) - { - GTIF* geoTiff = GTIFNew(tiff); - - if (geoTiff) - { - int imgWidth = 0, imgHeight = 0, nImages = 0, pntCount = 0; - double* pnts = 0; - - // get actual number of images in the tiff file - do { - nImages++; - } while (TIFFReadDirectory(tiff)); - if (nImages > 1) - std::cout << "OGSRaster::loadImageFromTIFF() - File contains " << - nImages << " images. This method is not tested for this case." << - std::endl; - - // get image size - TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &imgWidth); - TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &imgHeight); - - // get cellsize - // Note: GeoTiff allows anisotropic pixels. This is not supported here and equilateral pixels are assumed. - if (TIFFGetField(tiff, GTIFF_PIXELSCALE, &pntCount, &pnts)) - { - if (pnts[0] != pnts[1]) - std::cout << - "OGSRaster::loadImageFromTIFF() - Warning: Original raster data has anisotrop pixel size!" - << std::endl; - cellsize = pnts[0]; - } - - // get upper left point / origin - if (TIFFGetField(tiff, GTIFF_TIEPOINTS, &pntCount, &pnts)) - { - origin.setX(pnts[3]); - origin.setY(pnts[4] - (imgHeight * cellsize)); // the origin should be the lower left corner of the img - } - - // read pixel values - uint32* pixVal = - (uint32*) _TIFFmalloc(imgWidth * imgHeight * sizeof (uint32)); - if ((imgWidth > 0) && (imgHeight > 0)) - if (!TIFFReadRGBAImage(tiff, imgWidth, imgHeight, pixVal, 0)) - { - std::cout << - "OGSRaster::loadImageFromTIFF() - Error reading GeoTIFF file." - << std::endl; - _TIFFfree(pixVal); - GTIFFree(geoTiff); - XTIFFClose(tiff); - return false; - } - - // read colormap if it exists - uint16* cmap_red = NULL, * cmap_green = NULL, * cmap_blue = NULL; - int colormap_used = TIFFGetField(tiff, - TIFFTAG_COLORMAP, - &cmap_red, - &cmap_green, - &cmap_blue); - - int lineindex = 0, idx = 0; - QImage img(imgWidth, imgHeight, QImage::Format_ARGB32); - - int* pxl (new int[4]); - for (int j = 0; j < imgHeight; j++) - { - lineindex = j * imgWidth; - for (int i = 0; i < imgWidth; i++) - { // scale intensities and set nodata values to white (i.e. the background colour) - idx = TIFFGetR(pixVal[lineindex + i]); - if (colormap_used) - img.setPixel(i,j, - qRgba(cmap_red[idx] >> 8, - cmap_green[idx] >> 8, - cmap_blue[idx] >> 8, 255)); - else - { - //img.setPixel(i,j, qRgba(TIFFGetB(pixVal[idx]), TIFFGetG(pixVal[idx]), TIFFGetR(pixVal[idx]), TIFFGetA(pixVal[idx]))); - uint32toRGBA(pixVal[lineindex + i], pxl); - img.setPixel(i,j, - qRgba(pxl[0], pxl[1], pxl[2], pxl[3])); - } - } - } - delete [] pxl; - - raster = img; - - _TIFFfree(pixVal); - GTIFFree(geoTiff); - XTIFFClose(tiff); - return true; - } - - XTIFFClose(tiff); - std::cout << - "OGSRaster::loadImageFromTIFF() - File not recognised as GeoTIFF-Image." << - std::endl; - return false; - } - - std::cout << "OGSRaster::loadImageFromTIFF() - File not recognised as TIFF-Image." << - std::endl; - return false; -} -#endif - -bool OGSRaster::loadImageFromFile(const QString &fileName, QImage &raster) -{ - return raster.load(fileName); -} - -void OGSRaster::convertToGreyscale(QImage &raster, const int &min, const int &max) -{ - int value = 0; - double scalingFactor = 255.0 / (max - min); - - for (int i = 0; i < raster.width(); i++) - for (int j = 0; j < raster.height(); j++) - { - QRgb pix = raster.pixel(i,j); - value = - static_cast<int>(floor(((0.3 * qRed(pix) + 0.6 * qGreen(pix) + - 0.1 * - qBlue(pix)) - min) * scalingFactor)); - raster.setPixel(i, j, qRgb(value, value, value)); - } -} - -int* OGSRaster::getGreyscaleData(QImage &raster, const int &min, const int &max) -{ - int index = 0; - double scalingFactor = 255.0 / (max - min); - int* pixVal (new int[raster.height() * raster.width()]); - - for (int j = 0; j < raster.height(); j++) - { - index = j * raster.width(); - for (int i = 0; i < raster.width(); i++) - { - QRgb pix = raster.pixel(i,j); - pixVal[index + - i] = - static_cast<int>(floor(((0.3 * qRed(pix) + 0.6 * qGreen(pix) + - 0.1 * - qBlue(pix)) - min) * scalingFactor)); - } - } - return pixVal; -} - -int OGSRaster::getMaxValue(const QImage &raster) -{ - int value, maxVal = 0; - for (int i = 0; i < raster.width(); i++) - for (int j = 0; j < raster.height(); j++) - { - value = qGreen(raster.pixel(i,j)); - maxVal = (value > maxVal) ? value : maxVal; - } - return maxVal; -} - -int OGSRaster::getMinValue(const QImage &raster) -{ - int value, minVal = 65536; - for (int i = 0; i < raster.width(); i++) - for (int j = 0; j < raster.height(); j++) - { - value = qGreen(raster.pixel(i,j)); - minVal = (value < minVal) ? value : minVal; - } - return minVal; -} - -void OGSRaster::uint32toRGBA(const unsigned int s, int* p) -{ - p[3] = s / (256 * 256 * 256); - int r = s % (256 * 256 * 256); - p[2] = r / (256 * 256); - r %= (256 * 256); - p[1] = r / 256; - p[0] = r % 256; -} diff --git a/DataView/OGSRaster.h b/DataView/OGSRaster.h deleted file mode 100644 index c1fc6092d7be502f9682599d3bf7d9c663f5f5f0..0000000000000000000000000000000000000000 --- a/DataView/OGSRaster.h +++ /dev/null @@ -1,134 +0,0 @@ -/** - * \file OGSRaster.h - * 11/01/2010 KR Initial implementation - * - */ -#ifndef OGSRASTER_H -#define OGSRASTER_H - -#include <fstream> - -class QImage; -class QPointF; -class QString; - -/** - * \brief Loading of raster data such as images or ArcGIS-data. - * - * The OGSRaster class enables loading of raster data such as images or ArcGIS-data. Supported image formats are specified - * by the Qt class QPixmap. Georeferenced data can be imported via the GeoTIFF- or asc-format . - */ -class OGSRaster -{ - /// Data structure for the asc-file header. - struct ascHeader - { - int ncols; - int nrows; - double x; - double y; - double cellsize; - int noData; - }; - -public: - /** - * \brief Loads an image- or raster-file into an QImage. - * - * Public method for loading all data formats. Internally the method automatically differentiates between - * images and georeferenced files and then calls the appropriate method for reading the file. - * \param fileName Filename of the file that should be loaded. - * \param raster The QImage into which the raster data will be written. - * \param origin The upper left corner of the data set, the default value is (0,0). - * \param scalingFactor The size of each pixel in the image which is needed for re-scaling the data, the default value is 1. - * \param autoscale Determines if the histogram of the raster will be contrast-stretched to [0, 255]. If false, the streching process will be skipped. - * \param mirrorX Mirror around x-axis. - * \return True if the raster data was loaded correctly, false otherwise. - */ - static bool loadImage(const QString &fileName, - QImage &raster, - QPointF &origin, - double &scalingFactor, - bool autoscale = true, - bool mirrorX = false); - - /** - * \brief Loads an ASC file into a double array - * - * \param fileName Filename of the file that should be loaded. - * \param x0 The x-coordinate of the origin. - * \param y0 The y-coordinate of the origin. - * \param width The width of the image. - * \param height The height of the image - * \param delta The size of each pixel in the image which is needed for re-scaling the data. - * \return True if the raster data was loaded correctly, false otherwise. - */ - static double* loadDataFromASC(const QString &fileName, - double& x0, - double &y0, - size_t &width, - size_t &height, - double &delta); - - /// Converts raster to an 8 bit greyscale image that is contrast-stretched in [min:max]. - static void convertToGreyscale(QImage &raster, const int &min = 0, const int &max = 255); - - /// Returns an int-array containing the raster converted an 8 bit greyscale values that are contrast-stretched in [min:max]. - static int* getGreyscaleData(QImage &raster, const int &min = 0, const int &max = 255); - - /// Returns the maximum intensity of raster. - static int getMaxValue(const QImage &raster); - - /// Returns the minimum intensity of raster. - static int getMinValue(const QImage &raster); - -private: - /** - * Loads ArcGIS asc-files to a QPixmap object and automatically does a contrast stretching to adjust values to 8 bit greyscale images. - * \param fileName Filename of the file that should be loaded. - * \param raster The QPixmap into which the raster data will be written. - * \param origin The upper left corner of the data set - * \param scalingFactor - * \param autoscale - * \return True if the raster data was loaded correctly, false otherwise. - */ - static bool loadImageFromASC(const QString &fileName, - QImage &raster, - QPointF &origin, - double &scalingFactor, - bool autoscale = true); - - /** - * Loads ArcGIS asc-files to a QPixmap object and automatically does a contrast stretching to adjust values to 8 bit greyscale images. - * \param fileName Filename of the file that should be loaded. - * \param raster The QPixmap into which the raster data will be written. - * \param origin The upper left corner of the data set - * \param scalingFactor - * \return True if the raster data was loaded correctly, false otherwise. - */ -#ifdef libgeotiff_FOUND - static bool loadImageFromTIFF(const QString &fileName, - QImage &raster, - QPointF &origin, - double &scalingFactor); -#endif - - /** - * Loads image files into a QPixmap object. Since images are not geo-referenced no origin point will be returned. - * \param fileName Filename of the file that should be loaded. - * \param raster The QPixmap into which the raster data will be written. - * \return True if the raster data was loaded correctly, false otherwise. - */ - static bool loadImageFromFile(const QString &fileName, QImage &raster); - - /** - * Reads the header of an ArcGIS asc-file. - * \param header The ascHeader-object into which all the information will be written. - * \param in FileInputStream used for reading the data. - * \return True if the header could be read correctly, false otherwise. - */ - static bool readASCHeader(ascHeader &header, std::ifstream &in); - static void uint32toRGBA(const unsigned int s, int* p); -}; - -#endif //OGSRASTER_H diff --git a/DataView/ProcessModel.cpp b/DataView/ProcessModel.cpp index 773164ca21c8e33a93d7113e667e9de4cd54194e..806c6f7b179f19340c8d2fd69e362aac960468f8 100644 --- a/DataView/ProcessModel.cpp +++ b/DataView/ProcessModel.cpp @@ -48,57 +48,50 @@ void ProcessModel::addConditionItem(FEMCondition* c) CondObjectListItem* condParent = this->getCondParent(processParent, c->getCondType()); if (condParent == NULL) - condParent = this->createCondParent(processParent, c->getCondType(), c->getAssociatedGeometryName()); + condParent = this->createCondParent(processParent, c); + else + condParent->addCondition(c); - if (condParent) + QList<QVariant> condData; + condData << QString::fromStdString(c->getGeoName()) + << QString::fromStdString(c->getGeoTypeAsString()); + CondItem* condItem = new CondItem(condData, condParent, c); + condParent->appendChild(condItem); + // add information on primary variable + QList<QVariant> pvData; + pvData << QString::fromStdString(convertPrimaryVariableToString(c->getProcessPrimaryVariable())); + TreeItem* pvInfo = new TreeItem(pvData, condItem); + // add distribution information + QList<QVariant> disData; + disData << QString::fromStdString(convertDisTypeToString(c->getProcessDistributionType())); + std::vector<size_t> dis_nodes = c->getDisNodes(); + std::vector<double> dis_values = c->getDisValues(); + TreeItem* disInfo; + if (c->getProcessDistributionType() == FiniteElement::CONSTANT || + c->getProcessDistributionType() == FiniteElement::CONSTANT_NEUMANN) { - QList<QVariant> condData; - condData << QString::fromStdString(c->getGeoName()) - << QString::fromStdString(c->getGeoTypeAsString()); - CondItem* condItem = new CondItem(condData, condParent, c); - condParent->appendChild(condItem); - // add process information - //QList<QVariant> pcsData; - //pcsData << QString::fromStdString(convertProcessTypeToString(c->getProcessType())); - //TreeItem* pcsInfo = new TreeItem(pcsData, condItem); - // add information on primary variable - QList<QVariant> pvData; - pvData << QString::fromStdString(convertPrimaryVariableToString(c->getProcessPrimaryVariable())); - TreeItem* pvInfo = new TreeItem(pvData, condItem); - // add distribution information - QList<QVariant> disData; - disData << QString::fromStdString(convertDisTypeToString(c->getProcessDistributionType())); - std::vector<double> dis_value = c->getDisValue(); - TreeItem* disInfo; - if (c->getProcessDistributionType() == FiniteElement::CONSTANT || - c->getProcessDistributionType() == FiniteElement::CONSTANT_NEUMANN) - { - disData << dis_value[0]; - disInfo = new TreeItem(disData, condItem); - } - else + disData << dis_values[0]; + disInfo = new TreeItem(disData, condItem); + } + else + { + size_t nVals = dis_values.size(); + disData << static_cast<int>(nVals); + disInfo = new TreeItem(disData, condItem); + for (size_t i = 0; i < nVals; i++) { - size_t nVals = dis_value.size() / 2; - disData << static_cast<int>(nVals); - disInfo = new TreeItem(disData, condItem); - for (size_t i = 0; i < nVals; i++) - { - QList<QVariant> linData; - linData << dis_value[2 * i] << dis_value[2 * i + 1]; - TreeItem* linInfo = new TreeItem(linData, disInfo); - disInfo->appendChild(linInfo); - } + QList<QVariant> linData; + linData << static_cast<int>(dis_nodes[i]) << dis_values[i]; + TreeItem* linInfo = new TreeItem(linData, disInfo); + disInfo->appendChild(linInfo); } + } - //condItem->appendChild(pcsInfo); - condItem->appendChild(pvInfo); - condItem->appendChild(disInfo); + //condItem->appendChild(pcsInfo); + condItem->appendChild(pvInfo); + condItem->appendChild(disInfo); - condParent->addCondition(c); - reset(); - } - else - std::cout << "Error in ProcessModel::addConditionItem() - Parent object not found..." << std::endl; + reset(); } void ProcessModel::addCondition(FEMCondition* condition) @@ -237,19 +230,19 @@ CondObjectListItem* ProcessModel::getCondParent(TreeItem* parent, const FEMCondi return NULL; } -CondObjectListItem* ProcessModel::createCondParent(ProcessItem* parent, const FEMCondition::CondType cond_type, const std::string &geometry_name) +CondObjectListItem* ProcessModel::createCondParent(ProcessItem* parent, FEMCondition* cond) { - QString condType(QString::fromStdString(FEMCondition::condTypeToString(cond_type))); + QString condType(QString::fromStdString(FEMCondition::condTypeToString(cond->getCondType()))); QList<QVariant> condData; condData << condType << ""; - const std::vector<GEOLIB::Point*>* pnts = _project.getGEOObjects()->getPointVec(geometry_name); + const std::vector<GEOLIB::Point*>* pnts = _project.getGEOObjects()->getPointVec(cond->getAssociatedGeometryName()); if (pnts) { - CondObjectListItem* cond = new CondObjectListItem(condData, parent, cond_type, pnts); - parent->appendChild(cond); - emit conditionAdded(this, parent->getItem()->getProcessType(), cond_type); - return cond; + CondObjectListItem* cond_list = new CondObjectListItem(condData, parent, cond, pnts); + parent->appendChild(cond_list); + emit conditionAdded(this, parent->getItem()->getProcessType(), cond->getCondType()); + return cond_list; } return NULL; @@ -266,3 +259,11 @@ vtkPolyDataAlgorithm* ProcessModel::vtkSource(const FiniteElement::ProcessType p } return NULL; } + +void ProcessModel::replaceCondition(const QModelIndex &idx, FEMCondition* condition) +{ + // remove old condition + this->getItem(idx)->parentItem()->removeChildren(this->getItem(idx)->row(),1); + //add new condition + this->addCondition(condition); +} diff --git a/DataView/ProcessModel.h b/DataView/ProcessModel.h index 0970502eeae70eeacef6686e0014163937a9c191..ff445aaa2867f6be60f878cd5e64310fd527c553 100644 --- a/DataView/ProcessModel.h +++ b/DataView/ProcessModel.h @@ -56,6 +56,9 @@ public slots: /// Removes all processes from the model void removeAllProcesses(); + /// Remove the given TreeItem and replace it with another condition (this is used for editing FEMConditions) + void replaceCondition(const QModelIndex &idx, FEMCondition* condition); + private: /// Adds a new FEM condition to the condition tree model. void addConditionItem(FEMCondition* condition); @@ -64,7 +67,7 @@ private: //bool removeConditionItem(const QModelIndex &idx); /// Creates the TreeItem for one of the condition subtrees. - CondObjectListItem* createCondParent(ProcessItem* parent, const FEMCondition::CondType type, const std::string &geometry_name); + CondObjectListItem* createCondParent(ProcessItem* parent, FEMCondition* cond); /// Returns the subtree-item for a given type of condtion. CondObjectListItem* getCondParent(TreeItem* parent, const FEMCondition::CondType type) ; diff --git a/DataView/ProcessView.cpp b/DataView/ProcessView.cpp index d71ef1beab4d350321bc79ee7145bbe9673f2c88..c4e40d69fcd44396f158a868e1a37cc6b39b29d8 100644 --- a/DataView/ProcessView.cpp +++ b/DataView/ProcessView.cpp @@ -8,9 +8,11 @@ #include "ProcessItem.h" #include "CondObjectListItem.h" +#include "CondItem.h" #include "ProcessModel.h" #include "ProcessView.h" - +#include "FEMConditionSetupDialog.h" +#include "SelectMeshDialog.h" ProcessView::ProcessView(QWidget* parent) : QTreeView(parent) { @@ -40,28 +42,28 @@ void ProcessView::contextMenuEvent( QContextMenuEvent* event ) { Q_UNUSED(event); - ProcessItem* pcs_item = dynamic_cast<ProcessItem*>(static_cast<ProcessModel*>(this->model())-> - getItem(this->selectionModel()->currentIndex())); - CondObjectListItem* cond_item = - dynamic_cast<CondObjectListItem*>(static_cast<ProcessModel*>(this->model())-> - getItem(this->selectionModel()->currentIndex())); + const QModelIndex idx(this->selectionModel()->currentIndex()); + QMenu menu; - if (pcs_item || cond_item) + if (this->isProcessItem(idx)) + { + QAction* saveCondAction = menu.addAction("Save FEM Conditions..."); + QAction* removePCSAction = menu.addAction("Remove process"); + connect(saveCondAction, SIGNAL(triggered()), this, SLOT(saveConditions())); + connect(removePCSAction, SIGNAL(triggered()), this, SLOT(removeProcess())); + } + else if (this->isListItem(idx)) { - QMenu menu; - if (cond_item) - { - QAction* removeCondAction = menu.addAction("Remove conditions"); - connect(removeCondAction, SIGNAL(triggered()), this, SLOT(removeCondition())); - } - - if (pcs_item) - { - QAction* removePCSAction = menu.addAction("Remove process"); - connect(removePCSAction, SIGNAL(triggered()), this, SLOT(removeProcess())); - } - menu.exec(event->globalPos()); + QAction* removeCondAction = menu.addAction("Remove conditions"); + connect(removeCondAction, SIGNAL(triggered()), this, SLOT(removeCondition())); } + else if (this->isConditionItem(idx)) + { + QAction* editCondAction = menu.addAction("Edit condition"); + connect(editCondAction, SIGNAL(triggered()), this, SLOT(editCondition())); + } + + menu.exec(event->globalPos()); } void ProcessView::removeCondition() @@ -76,6 +78,29 @@ void ProcessView::removeCondition() } } +void ProcessView::editCondition() +{ + CondItem* item = dynamic_cast<CondItem*>(static_cast<ProcessModel*>(this->model())->getItem(this->selectionModel()->currentIndex())); + + if (item) + { + FEMConditionSetupDialog dlg(*(item->getItem())); + connect(&dlg, SIGNAL(createFEMCondition(std::vector<FEMCondition*>)), this, SLOT(replaceCondition(std::vector<FEMCondition*>))); + dlg.exec(); + } +} + +void ProcessView::replaceCondition(std::vector<FEMCondition*> conditions) +{ + static_cast<ProcessModel*>(this->model())->replaceCondition(this->selectionModel()->currentIndex(), conditions[0]); + this->reset(); +} + +void ProcessView::saveConditions() +{ + emit saveConditionsRequested(); +} + void ProcessView::removeProcess() { ProcessItem* item = dynamic_cast<ProcessItem*>(static_cast<ProcessModel*>(this->model())->getItem(this->selectionModel()->currentIndex())); @@ -86,3 +111,24 @@ void ProcessView::removeProcess() emit processRemoved(pcs_type); } } + +bool ProcessView::isProcessItem(const QModelIndex &idx) const +{ + ProcessItem* pcs_item = dynamic_cast<ProcessItem*>(static_cast<ProcessModel*>(this->model())->getItem(idx)); + if (pcs_item) return true; + return false; +} + +bool ProcessView::isListItem(const QModelIndex &idx) const +{ + CondObjectListItem* cond_item = dynamic_cast<CondObjectListItem*>(static_cast<ProcessModel*>(this->model())->getItem(idx)); + if (cond_item) return true; + return false; +} + +bool ProcessView::isConditionItem(const QModelIndex &idx) const +{ + CondObjectListItem* cond_item = dynamic_cast<CondObjectListItem*>(static_cast<ProcessModel*>(this->model())->getItem(idx.parent())); + if (cond_item) return true; + return false; +} \ No newline at end of file diff --git a/DataView/ProcessView.h b/DataView/ProcessView.h index d868fa21c75b9063f9be5e368bb6f93a3b126e94..ba378765217a246912f7c10a460e944bb29b7524 100644 --- a/DataView/ProcessView.h +++ b/DataView/ProcessView.h @@ -36,16 +36,24 @@ protected slots: private: /// Actions to be taken after a right mouse click is performed in the station view. void contextMenuEvent( QContextMenuEvent* e ); + bool isProcessItem(const QModelIndex &idx) const; + bool isListItem(const QModelIndex &idx) const; + bool isConditionItem(const QModelIndex &idx) const; private slots: void on_Clicked(QModelIndex idx); + void editCondition(); void removeCondition(); void removeProcess(); + void replaceCondition(std::vector<FEMCondition*> conditions); + void saveConditions(); signals: void conditionsRemoved(const FiniteElement::ProcessType, const std::string&, const FEMCondition::CondType); void itemSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected); void processRemoved(const FiniteElement::ProcessType); + void saveConditionsRequested(); }; #endif //PROCESSVIEW_H + diff --git a/DataView/SHPImportDialog.cpp b/DataView/SHPImportDialog.cpp index fa62d79785a0ac8d95df80d48c10a6a4154d8b7f..2a5ea954c0c293a2d0ab428fc94b91b41cddb243 100644 --- a/DataView/SHPImportDialog.cpp +++ b/DataView/SHPImportDialog.cpp @@ -112,7 +112,8 @@ void SHPImportDialog::setupDialog() void SHPImportDialog::accept() { - if (_listName->text().compare("") == 0) + QString list_name(_listName->text()); + if (list_name.compare("") == 0) { OGSError::box("Please insert a name for the data in this file."); return; @@ -122,20 +123,20 @@ void SHPImportDialog::accept() if (_fileType == 1 && _choice1->isChecked()) _shpInterface->readSHPFile(_filename, SHPInterface::POINT, - _listName->text().toStdString()); + list_name.toStdString()); if (_fileType == 1 && _choice2->isChecked()) _shpInterface->readSHPFile(_filename, SHPInterface::STATION, - _listName->text().toStdString()); + list_name.toStdString()); if (_fileType == 2 && _choice1->isChecked()) _shpInterface->readSHPFile(_filename, SHPInterface::POLYLINE, - _listName->text().toStdString()); + list_name.toStdString()); if (_fileType == 2 && _choice2->isChecked()) _shpInterface->readSHPFile(_filename, SHPInterface::POLYGON, - _listName->text().toStdString()); - emit shpLoaded(_listName->text()); + list_name.toStdString()); + emit shpLoaded(list_name); } this->done(QDialog::Accepted); } diff --git a/DataView/SelectMeshDialog.cpp b/DataView/SelectMeshDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d80b9820d6f1d2b5a03e8068feeab54d3304607 --- /dev/null +++ b/DataView/SelectMeshDialog.cpp @@ -0,0 +1,61 @@ +/** + * \file QComboBox.cpp + * 2012/04/20 KR Initial implementation + */ + +#include "SelectMeshDialog.h" +#include "GeoObject.h" + +#include <QDialogButtonBox> +#include <QLabel> +#include <QComboBox> +#include <QVBoxLayout> + +SelectMeshDialog::SelectMeshDialog(const GEOLIB::GeoObject* geo_object, const std::list<std::string> &msh_names, QDialog* parent) : + QDialog(parent), _geo_object(geo_object) +{ + setupDialog(msh_names); + show(); +} + +SelectMeshDialog::~SelectMeshDialog() +{ + delete _buttonBox; + delete _layout; + delete _msh_names; + delete _txt_label; +} + +void SelectMeshDialog::setupDialog(const std::list<std::string> &msh_names) +{ + _layout = new QVBoxLayout(this); + QString dialog_text("Select Mesh"); + _txt_label = new QLabel(this); + _txt_label->setText(dialog_text); + + + _msh_names = new QComboBox(); + for (std::list<std::string>::const_iterator it=msh_names.begin(); it != msh_names.end(); ++it) + _msh_names->addItem(QString::fromStdString(*it)); + + setWindowTitle("Select Mesh..."); + _layout->addWidget( _txt_label ); + _layout->addWidget( _msh_names ); + _buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(_buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(_buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + _layout->addWidget( _buttonBox ); + + setLayout(_layout); +} + +void SelectMeshDialog::accept() +{ + //emit requestNameChange(_parent_name, GEOLIB::convertGeoType(_object_type_name), _id, _new_name->text().toStdString()); + this->done(QDialog::Accepted); +} + +void SelectMeshDialog::reject() +{ + this->done(QDialog::Rejected); +} diff --git a/DataView/SelectMeshDialog.h b/DataView/SelectMeshDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..a64cf195e6d072529a1a3774cd8a21aa42e1dd10 --- /dev/null +++ b/DataView/SelectMeshDialog.h @@ -0,0 +1,57 @@ +/** + * \file SelectMeshDialog.h + * 2012/04/20 KR Initial implementation + */ + +#ifndef SELECTMESHDIALOG_H +#define SELECTMESHDIALOG_H + +#include <QDialog> + +namespace GEOLIB { + class GeoObject; +} + +class QDialogButtonBox; +class QLabel; +class QComboBox; +class QVBoxLayout; + +/** + * \brief Small dialog for setting a name for an object. + */ +class SelectMeshDialog : public QDialog +{ + Q_OBJECT + +public: + /// Constructor + SelectMeshDialog(const GEOLIB::GeoObject* geo_object, + const std::list<std::string> &msh_names, + QDialog* parent = 0); + ~SelectMeshDialog(); + + QDialogButtonBox* _buttonBox; /// The buttons used in this dialog. + +private: + /// Constructs a dialog window + void setupDialog(const std::list<std::string> &msh_names); + + QLabel* _txt_label; + QComboBox* _msh_names; + QVBoxLayout* _layout; + const GEOLIB::GeoObject* _geo_object; + + +private slots: + /// Instructions if the OK-Button has been pressed. + void accept(); + + /// Instructions if the Cancel-Button has been pressed. + void reject(); + +signals: + //void requestNameChange(const std::string&, const GEOLIB::GEOTYPE, size_t, std::string); +}; + +#endif //SELECTMESHDIALOG_H diff --git a/DataView/StationTreeView.cpp b/DataView/StationTreeView.cpp index 400765c85d4865b658d88134ccc2941732a0cb43..376b76a67a742ac6f428ca7852b086cfe7756519 100644 --- a/DataView/StationTreeView.cpp +++ b/DataView/StationTreeView.cpp @@ -62,6 +62,9 @@ void StationTreeView::contextMenuEvent( QContextMenuEvent* event ) QModelIndex index = this->selectionModel()->currentIndex(); ModelTreeItem* item = static_cast<ModelTreeItem*>(index.internalPointer()); + if (!item) // Otherwise sometimes it crashes when (unmotivated ;-) ) clicking in a treeview + return; + // The current index refers to a parent item (e.g. a listname) if (item->childCount() > 0) { diff --git a/DataView/StratView/CMakeLists.txt b/DataView/StratView/CMakeLists.txt index 4dfeb264fe07a6f81c967194c536db6e51222239..52172483f51b50c7e2d84c576d98e802371e4cd3 100644 --- a/DataView/StratView/CMakeLists.txt +++ b/DataView/StratView/CMakeLists.txt @@ -32,13 +32,12 @@ qt4_wrap_cpp( MOC_SOURCES ${MOC_HEADERS} ) # Include the headers which are generated by uic and moc # and include additional header include_directories( - . + ${CMAKE_SOURCE_DIR}/Qt/DataView/StratView ${CMAKE_BINARY_DIR}/Qt/DataView/StratView - ../../../Base - ../../../GEO - ../../../MathLib - ../../Base - ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/Base + ${CMAKE_SOURCE_DIR}/GEO + ${CMAKE_SOURCE_DIR}/MathLib + ${CMAKE_SOURCE_DIR}/Qt/Base ) # Put moc files in a project folder diff --git a/DataView/ncvalues.h b/DataView/ncvalues.h new file mode 100644 index 0000000000000000000000000000000000000000..fbf7747c71c211b3a5957df291e2f61adbd5a761 --- /dev/null +++ b/DataView/ncvalues.h @@ -0,0 +1,279 @@ +/********************************************************************* + * Copyright 1992, University Corporation for Atmospheric Research + * See netcdf/README file for copying and redistribution conditions. + * + * Purpose: interface for classes of typed arrays for netCDF + * + * $Header: /upc/share/CVS/netcdf-3/cxx/ncvalues.h,v 1.7 2006/07/26 21:12:06 russ Exp $ + *********************************************************************/ + +#ifndef Ncvalues_def +#define Ncvalues_def + +#include <iostream> +#include <sstream> +#include <limits.h> +#include <vtknetcdf/netcdf.h> + +// Documentation warned this might change and now it has, for +// consistency with C interface +typedef signed char ncbyte; + +#define NC_UNSPECIFIED ((nc_type)0) + +// C++ interface dates from before netcdf-3, still uses some netcdf-2 names +#ifdef NO_NETCDF_2 +#define NC_LONG NC_INT +#define FILL_LONG NC_FILL_INT +typedef int nclong; +#define NC_FATAL 1 +#define NC_VERBOSE 2 +#endif + +enum NcType +{ + ncNoType = NC_UNSPECIFIED, + ncByte = NC_BYTE, + ncChar = NC_CHAR, + ncShort = NC_SHORT, + ncInt = NC_INT, + ncLong = NC_LONG, // deprecated, someday want to use for 64-bit ints + ncFloat = NC_FLOAT, + ncDouble = NC_DOUBLE +}; + +#define ncBad_ncbyte ncBad_byte +static const ncbyte ncBad_byte = NC_FILL_BYTE; +static const char ncBad_char = NC_FILL_CHAR; +static const short ncBad_short = NC_FILL_SHORT; +static const nclong ncBad_nclong = FILL_LONG; // deprecated +static const int ncBad_int = NC_FILL_INT; +static const long ncBad_long = FILL_LONG; // deprecated +static const float ncBad_float = NC_FILL_FLOAT; +static const double ncBad_double = NC_FILL_DOUBLE; + +// macros to glue tokens together to form new names (used to be in generic.h) +#define name2(a,b) a ## b +#define declare(clas,t) name2(clas,declare)(t) +#define implement(clas,t) name2(clas,implement)(t) +// This is the same as the name2 macro, but we need to define our own +// version since rescanning something generated with the name2 macro +// won't necessarily cause name2 to be expanded again. +#define makename2(z, y) makename2_x(z, y) +#define makename2_x(z, y) z##y + +#define NcVal(TYPE) makename2(NcValues_,TYPE) + +#define NcValuesdeclare(TYPE) \ +class MSCPP_EXTRA NcVal(TYPE) : public NcValues \ +{ \ + public: \ + NcVal(TYPE)( void ); \ + NcVal(TYPE)(long Num); \ + NcVal(TYPE)(long Num, const TYPE* vals); \ + NcVal(TYPE)(const NcVal(TYPE)&); \ + virtual NcVal(TYPE)& operator=(const NcVal(TYPE)&); \ + virtual ~NcVal(TYPE)( void ); \ + virtual void* base( void ) const; \ + virtual int bytes_for_one( void ) const; \ + virtual ncbyte as_ncbyte( long n ) const; \ + virtual char as_char( long n ) const; \ + virtual short as_short( long n ) const; \ + virtual int as_int( long n ) const; \ + virtual int as_nclong( long n ) const; \ + virtual long as_long( long n ) const; \ + virtual float as_float( long n ) const; \ + virtual double as_double( long n ) const; \ + virtual char* as_string( long n ) const; \ + virtual int invalid( void ) const; \ + private: \ + TYPE* the_values; \ + std::ostream& print(std::ostream&) const; \ +}; + +#define NcTypeEnum(TYPE) makename2(_nc__,TYPE) +#define _nc__ncbyte ncByte +#define _nc__char ncChar +#define _nc__short ncShort +#define _nc__int ncInt +#define _nc__nclong ncLong +#define _nc__long ncLong +#define _nc__float ncFloat +#define _nc__double ncDouble +#define NcValuesimplement(TYPE) \ +NcVal(TYPE)::NcVal(TYPE)( void ) \ + : NcValues(NcTypeEnum(TYPE), 0), the_values(0) \ +{} \ + \ +NcVal(TYPE)::NcVal(TYPE)(long Num, const TYPE* vals) \ + : NcValues(NcTypeEnum(TYPE), Num) \ +{ \ + the_values = new TYPE[Num]; \ + for(int i = 0; i < Num; i++) \ + the_values[i] = vals[i]; \ +} \ + \ +NcVal(TYPE)::NcVal(TYPE)(long Num) \ + : NcValues(NcTypeEnum(TYPE), Num), the_values(new TYPE[Num]) \ +{} \ + \ +NcVal(TYPE)::NcVal(TYPE)(const NcVal(TYPE)& v) : \ + NcValues(v) \ +{ \ + delete[] the_values; \ + the_values = new TYPE[v.the_number]; \ + for(int i = 0; i < v.the_number; i++) \ + the_values[i] = v.the_values[i]; \ +} \ + \ +NcVal(TYPE)& NcVal(TYPE)::operator=(const NcVal(TYPE)& v) \ +{ \ + if ( &v != this) { \ + NcValues::operator=(v); \ + delete[] the_values; \ + the_values = new TYPE[v.the_number]; \ + for(int i = 0; i < v.the_number; i++) \ + the_values[i] = v.the_values[i]; \ + } \ + return *this; \ +} \ + \ +void* NcVal(TYPE)::base( void ) const \ +{ \ + return the_values; \ +} \ + \ +NcVal(TYPE)::~NcVal(TYPE)( void ) \ +{ \ + delete[] the_values; \ +} \ + \ +int NcVal(TYPE)::invalid( void ) const \ +{ \ + for(int i=0;i<the_number;i++) \ + if (the_values[i] == makename2(ncBad_,TYPE)) return 1; \ + return 0; \ +} \ + + +#define Ncbytes_for_one_implement(TYPE) \ +int NcVal(TYPE)::bytes_for_one( void ) const \ +{ \ + return sizeof(TYPE); \ +} + +#define as_ncbyte_implement(TYPE) \ +ncbyte NcVal(TYPE)::as_ncbyte( long n ) const \ +{ \ + if (the_values[n] < 0 || the_values[n] > UCHAR_MAX) \ + return ncBad_byte; \ + return (ncbyte) the_values[n]; \ +} + +#define as_char_implement(TYPE) \ +char NcVal(TYPE)::as_char( long n ) const \ +{ \ + if (the_values[n] < CHAR_MIN || the_values[n] > CHAR_MAX) \ + return ncBad_char; \ + return (char) the_values[n]; \ +} + +#define as_short_implement(TYPE) \ +short NcVal(TYPE)::as_short( long n ) const \ +{ \ + if (the_values[n] < SHRT_MIN || the_values[n] > SHRT_MAX) \ + return ncBad_short; \ + return (short) the_values[n]; \ +} + +#define NCINT_MIN INT_MIN +#define NCINT_MAX INT_MAX +#define as_int_implement(TYPE) \ +int NcVal(TYPE)::as_int( long n ) const \ +{ \ + if (the_values[n] < NCINT_MIN || the_values[n] > NCINT_MAX) \ + return ncBad_int; \ + return (int) the_values[n]; \ +} + +#define NCLONG_MIN INT_MIN +#define NCLONG_MAX INT_MAX +#define as_nclong_implement(TYPE) \ +nclong NcVal(TYPE)::as_nclong( long n ) const \ +{ \ + if (the_values[n] < NCLONG_MIN || the_values[n] > NCLONG_MAX) \ + return ncBad_nclong; \ + return (nclong) the_values[n]; \ +} + +#define as_long_implement(TYPE) \ +long NcVal(TYPE)::as_long( long n ) const \ +{ \ + if (the_values[n] < LONG_MIN || the_values[n] > LONG_MAX) \ + return ncBad_long; \ + return (long) the_values[n]; \ +} + +#define as_float_implement(TYPE) \ +inline float NcVal(TYPE)::as_float( long n ) const \ +{ \ + return (float) the_values[n]; \ +} + +#define as_double_implement(TYPE) \ +inline double NcVal(TYPE)::as_double( long n ) const \ +{ \ + return (double) the_values[n]; \ +} + +#define as_string_implement(TYPE) \ +char* NcVal(TYPE)::as_string( long n ) const \ +{ \ + char* s = new char[32]; \ + std::ostringstream ostr; \ + ostr << the_values[n]; \ + ostr.str().copy(s, std::string::npos); \ + s[ostr.str().length()] = 0; \ + return s; \ +} + +class MSCPP_EXTRA NcValues // ABC for value blocks +{ + public: + NcValues( void ); + NcValues(NcType, long); + virtual ~NcValues( void ); + virtual long num( void ); + virtual std::ostream& print(std::ostream&) const = 0; + virtual void* base( void ) const = 0; + virtual int bytes_for_one( void ) const = 0; + + // The following member functions provide conversions from the value + // type to a desired basic type. If the value is out of range, the + // default "fill-value" for the appropriate type is returned. + virtual ncbyte as_ncbyte( long n ) const = 0; // nth value as a byte + virtual char as_char( long n ) const = 0; // nth value as char + virtual short as_short( long n ) const = 0; // nth value as short + virtual int as_int( long n ) const = 0; // nth value as int + virtual int as_nclong( long n ) const = 0; // nth value as nclong + virtual long as_long( long n ) const = 0; // nth value as long + virtual float as_float( long n ) const = 0; // nth value as floating-point + virtual double as_double( long n ) const = 0; // nth value as double + virtual char* as_string( long n ) const = 0; // value as string + + protected: + NcType the_type; + long the_number; + friend std::ostream& operator<< (std::ostream&, const NcValues&); +}; + +declare(NcValues,ncbyte) +declare(NcValues,char) +declare(NcValues,short) +declare(NcValues,int) +declare(NcValues,nclong) +declare(NcValues,long) +declare(NcValues,float) +declare(NcValues,double) + +#endif \ No newline at end of file diff --git a/Gui/CMakeLists.txt b/Gui/CMakeLists.txt index 7c5479c8ad52fcbb33e4db658a0fe06bd5d262ab..749b63b7b8259e9d868650889803db5c7036ea7e 100644 --- a/Gui/CMakeLists.txt +++ b/Gui/CMakeLists.txt @@ -1,11 +1,17 @@ # Source files SET( SOURCES mainwindow.cpp + ${CMAKE_SOURCE_DIR}/UTL/FileConverter/OGSFileConverter/OGSFileConverter.cpp + ${CMAKE_SOURCE_DIR}/UTL/FileConverter/OGSFileConverter/FileListDialog.cpp + ${CMAKE_SOURCE_DIR}/UTL/FileConverter/OGSFileConverter/ConversionTools.cpp ) # Moc Header files SET( MOC_HEADERS mainwindow.h + ${CMAKE_SOURCE_DIR}/UTL/FileConverter/OGSFileConverter/OGSFileConverter.h + ${CMAKE_SOURCE_DIR}/UTL/FileConverter/OGSFileConverter/FileListDialog.h + ${CMAKE_SOURCE_DIR}/UTL/FileConverter/OGSFileConverter/ConversionTools.h ) # Header files @@ -16,6 +22,8 @@ SET( HEADERS # UI files SET( UIS mainwindow.ui + ${CMAKE_SOURCE_DIR}/UTL/FileConverter/OGSFileConverter/OGSFileConverter.ui + ${CMAKE_SOURCE_DIR}/UTL/FileConverter/OGSFileConverter/FileList.ui ) @@ -35,29 +43,26 @@ INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR}/Qt/DataView/DiagramView ${CMAKE_BINARY_DIR}/Qt/VtkVis ${CMAKE_BINARY_DIR}/Qt/VtkAct - ../../Base - ../../MathLib - ../../GEO - ../../FileIO - ../../MSH - ../../MSHGEOTOOLS - ../../FEM - ../Base - ../DataView - ../DataView/StratView - ../DataView/DiagramView - ../VtkVis - ../VtkAct + ${CMAKE_SOURCE_DIR}/Base + ${CMAKE_SOURCE_DIR}/MathLib + ${CMAKE_SOURCE_DIR}/GEO + ${CMAKE_SOURCE_DIR}/FileIO + ${CMAKE_SOURCE_DIR}/MSH + ${CMAKE_SOURCE_DIR}/MSHGEOTOOLS + ${CMAKE_SOURCE_DIR}/FEM + ${CMAKE_SOURCE_DIR}/Qt/Base + ${CMAKE_SOURCE_DIR}/Qt/DataView + ${CMAKE_SOURCE_DIR}/Qt/DataView/StratView + ${CMAKE_SOURCE_DIR}/Qt/DataView/DiagramView + ${CMAKE_SOURCE_DIR}/Qt/VtkVis + ${CMAKE_SOURCE_DIR}/Qt/VtkAct + ${CMAKE_SOURCE_DIR}/UTL/FileConverter/OGSFileConverter ) IF (Shapelib_FOUND) INCLUDE_DIRECTORIES( ${Shapelib_INCLUDE_DIR} ) ENDIF () # Shapelib_FOUND -if (OGS_COMPILE_QVTK) - INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/Qt/QVTK ../QVTK) -endif (OGS_COMPILE_QVTK) - # Put moc files in a project folder SOURCE_GROUP("UI Files" REGULAR_EXPRESSION "\\w*\\.ui") SOURCE_GROUP("Moc Files" REGULAR_EXPRESSION "moc_.*") @@ -87,6 +92,8 @@ TARGET_LINK_LIBRARIES( ogs-gui QVTK VtkVis VtkAct + vtkNetCDF + vtkNetCDF_cxx ) IF (Shapelib_FOUND) @@ -97,10 +104,6 @@ IF (libgeotiff_FOUND) TARGET_LINK_LIBRARIES( ogs-gui ${libgeotiff_LIBRARIES} ) ENDIF () # libgeotiff_FOUND -IF (libtiff_FOUND) - TARGET_LINK_LIBRARIES( ogs-gui ${libtiff_LIBRARIES} ) -ENDIF () # libtiff_FOUND - ADD_DEPENDENCIES ( ogs-gui VtkVis OGSProject ) IF(MSVC) @@ -115,12 +118,12 @@ ENDIF() # OGS_BUILD_INFO ### OpenSG support ### IF (OGS_USE_OPENSG) USE_OPENSG(ogs-gui) - INCLUDE_DIRECTORIES( ../OpenSG ) + INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/Qt/OpenSG ) TARGET_LINK_LIBRARIES( ogs-gui OgsOpenSG ) ENDIF (OGS_USE_OPENSG) IF(OGS_USE_VRPN) - INCLUDE_DIRECTORIES( ../Vrpn ${CMAKE_BINARY_DIR}/Qt/Vrpn ) + INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/Qt/Vrpn ${CMAKE_BINARY_DIR}/Qt/Vrpn ) TARGET_LINK_LIBRARIES( ogs-gui ${VRPN_LIBRARIES} OgsVrpn ) ENDIF() @@ -133,17 +136,17 @@ IF (OGS_VRED_PLUGIN) ADD_DEFINITIONS( -DBOOST_PYTHON_DYNAMIC_LIB ) - + INCLUDE_DIRECTORIES( #${VRED_DIR}/include/vred - ${VRED_DIR}/include/boost-1.34-vc8.0 - ${VRED_DIR}/include/python-2.52-vc8.0 - #${VRED_DIR}/include/zlib-1.23 - #${VRED_DIR}/include/OpenSG - #${VRED_DIR}/include/OpenSG/OpenSG + ${VRED_DIR}/include/boost-1.34-vc8.0 + ${VRED_DIR}/include/python-2.52-vc8.0 + #${VRED_DIR}/include/zlib-1.23 + #${VRED_DIR}/include/OpenSG + #${VRED_DIR}/include/OpenSG/OpenSG ) LINK_DIRECTORIES( ${VRED_DIR}/bin/WIN32 ) - + ADD_LIBRARY( ogs-gui-vred SHARED ${SOURCES} ${HEADERS} @@ -163,14 +166,13 @@ IF (OGS_VRED_PLUGIN) QtDataView StratView ${Shapelib_LIBRARIES} - ${libtiff_LIBRARIES} ${libgeotiff_LIBRARIES} QVTK VtkVis VtkAct #boost_python-vc80-mt-1_34_1 ) - + ADD_DEPENDENCIES ( ogs-gui-vred VtkVis OGSProject ) ENDIF (OGS_VRED_PLUGIN) @@ -180,20 +182,20 @@ ENDIF (OGS_VRED_PLUGIN) IF (OGS_PACKAGING) INSTALL (TARGETS ogs-gui RUNTIME DESTINATION bin COMPONENT ogs_gui) - + IF(MSVC) SET(OGS_GUI_EXE ${OGS_EXECUTABLE}-gui.exe) ELSE(MSVC) SET(OGS_GUI_EXE ${OGS_EXECUTABLE}-gui) ENDIF(MSVC) - + INCLUDE(GetPrerequisites) if (EXISTS ${OGS_GUI_EXE}) GET_PREREQUISITES(${OGS_GUI_EXE} OGS_GUI_DEPENDENCIES 1 1 "/usr/local/lib;/;${VTK_DIR};${OpenSG_LIBRARY_DIRS}" "") MESSAGE (STATUS "ogs-gui depends on:") FOREACH(DEPENDENCY ${OGS_GUI_DEPENDENCIES}) IF(NOT ${DEPENDENCY} STREQUAL "not") # Some bug on Linux? - message("${DEPENDENCY}") + message("${DEPENDENCY}") GP_RESOLVE_ITEM ("/" "${DEPENDENCY}" ${OGS_GUI_EXE} "/usr/local/lib;/;${VTK_DIR}" DEPENDENCY_PATH) SET (DEPENDENCY_PATHS ${DEPENDENCY_PATHS} ${DEPENDENCY_PATH}) ENDIF() diff --git a/Gui/mainwindow.cpp b/Gui/mainwindow.cpp index 4496f3822ccb5a2068489112f7a80cf08c8e8bbb..b79de50b70866cc81d44b52767257554e6e38561 100644 --- a/Gui/mainwindow.cpp +++ b/Gui/mainwindow.cpp @@ -16,12 +16,16 @@ //dialogs #include "DBConnectionDialog.h" +#include "CondFromRasterDialog.h" +#include "ConditionWriterDialog.h" #include "DiagramPrefsDialog.h" #include "FEMConditionSetupDialog.h" +#include "OGSFileConverter.h" #include "GMSHPrefsDialog.h" #include "LineEditDialog.h" #include "ListPropertiesDialog.h" #include "MshQualitySelectionDialog.h" +#include "NetCdfConfigureDialog.h" #include "NewProcessDialog.h" #include "SetNameDialog.h" #include "VisPrefsDialog.h" @@ -33,7 +37,7 @@ #include "DatabaseConnection.h" #include "OGSError.h" -#include "OGSRaster.h" +#include "VtkRaster.h" #include "RecentFiles.h" #include "TreeModelIterator.h" #include "VtkBGImageSource.h" @@ -41,15 +45,14 @@ #include "VtkVisPipeline.h" #include "VtkVisPipelineItem.h" -//test +// FEM Conditions #include "BoundaryCondition.h" #include "InitialCondition.h" -#include "MathIO/CRSIO.h" -#include "Raster.h" #include "SourceTerm.h" #include "rf_bc_new.h" #include "rf_ic_new.h" #include "rf_st_new.h" +#include "FEMIO/BoundaryConditionIO.h" // FileIO includes #include "FEFLOWInterface.h" @@ -71,6 +74,7 @@ // MSH #include "msh_mesh.h" +#include "MeshGrid.h" // MSHGEOTOOLS #include "ExtractMeshNodes.h" @@ -115,7 +119,7 @@ Problem* aproblem = NULL; using namespace FileIO; MainWindow::MainWindow(QWidget* parent /* = 0*/) - : QMainWindow(parent), _db (NULL), _project() + : QMainWindow(parent), _db (NULL), _project(), _import_files_menu(NULL) { setupUi(this); @@ -156,12 +160,12 @@ MainWindow::MainWindow(QWidget* parent /* = 0*/) this, SLOT(showLineEditDialog(const std::string &))); // open line edit dialog connect(geoTabWidget->treeView, SIGNAL(requestNameChangeDialog(const std::string&, const GEOLIB::GEOTYPE, size_t)), this, SLOT(showGeoNameDialog(const std::string&, const GEOLIB::GEOTYPE, size_t))); - connect(geoTabWidget->treeView, SIGNAL(requestCondSetupDialog(const std::string&, const GEOLIB::GEOTYPE, size_t)), - this, SLOT(showCondSetupDialog(const std::string&, const GEOLIB::GEOTYPE, size_t))); + connect(geoTabWidget->treeView, SIGNAL(requestCondSetupDialog(const std::string&, const GEOLIB::GEOTYPE, size_t, bool)), + this, SLOT(showCondSetupDialog(const std::string&, const GEOLIB::GEOTYPE, size_t, bool))); connect(geoTabWidget->treeView, SIGNAL(loadFEMCondFileRequested(std::string)), this, SLOT(loadFEMConditions(std::string))); // add FEM Conditions - connect(geoTabWidget->treeView, SIGNAL(saveFEMConditionsRequested(QString, QString)), - this, SLOT(writeFEMConditionsToFile(QString, QString))); + //connect(geoTabWidget->treeView, SIGNAL(saveFEMConditionsRequested(QString, QString)), + // this, SLOT(writeFEMConditionsToFile(QString, QString))); connect(_geoModels, SIGNAL(geoDataAdded(GeoTreeModel *, std::string, GEOLIB::GEOTYPE)), this, SLOT(updateDataViews())); connect(_geoModels, SIGNAL(geoDataRemoved(GeoTreeModel *, std::string, GEOLIB::GEOTYPE)), @@ -179,8 +183,10 @@ MainWindow::MainWindow(QWidget* parent /* = 0*/) _elementModel, SLOT(clearView())); connect(mshTabWidget->treeView, SIGNAL(qualityCheckRequested(VtkMeshSource*)), this, SLOT(showMshQualitySelectionDialog(VtkMeshSource*))); + connect(mshTabWidget->treeView, SIGNAL(requestCondSetupDialog(const std::string&, const GEOLIB::GEOTYPE, size_t, bool)), + this, SLOT(showCondSetupDialog(const std::string&, const GEOLIB::GEOTYPE, size_t, bool))); connect(mshTabWidget->treeView, SIGNAL(requestDIRECTSourceTerms(const std::string, const std::vector<GEOLIB::Point*>*)), - this, SLOT(loadDIRECTSourceTerms(const std::string, const std::vector<GEOLIB::Point*>*))); + this, SLOT(loadDIRECTSourceTermsFromASCII(const std::string, const std::vector<GEOLIB::Point*>*))); // Setup connections for process model to GUI connect(modellingTabWidget->treeView, SIGNAL(conditionsRemoved(const FiniteElement::ProcessType, const std::string&, const FEMCondition::CondType)), @@ -189,6 +195,8 @@ MainWindow::MainWindow(QWidget* parent /* = 0*/) _processModel, SLOT(removeProcess(const FiniteElement::ProcessType))); connect(modellingTabWidget, SIGNAL(requestNewProcess()), this, SLOT(showNewProcessDialog())); + connect(modellingTabWidget->treeView, SIGNAL(saveConditionsRequested()), + this, SLOT(showConditionWriterDialog())); // VisPipeline Connects connect(_geoModels, SIGNAL(geoDataAdded(GeoTreeModel *, std::string, GEOLIB::GEOTYPE)), @@ -249,9 +257,8 @@ MainWindow::MainWindow(QWidget* parent /* = 0*/) SIGNAL(elementPicked(const GridAdapter *, const size_t)), mshTabWidget->elementView, SLOT(updateView())); - connect(vtkVisTabWidget->vtkVisPipelineView, - SIGNAL(meshAdded(MeshLib::CFEMesh *, std::string &)), - _meshModels, SLOT(addMesh(MeshLib::CFEMesh *, std::string &))); + connect(vtkVisTabWidget->vtkVisPipelineView, SIGNAL(meshAdded(GridAdapter*)), + _meshModels, SLOT(addMesh(GridAdapter*))); // Stack the data dock widgets together tabifyDockWidget(geoDock, mshDock); @@ -273,7 +280,8 @@ MainWindow::MainWindow(QWidget* parent /* = 0*/) _screenGeometries.push_back(desktopWidget->availableGeometry((int)i)); // Setup import files menu - menu_File->insertMenu(action_Exit, createImportFilesMenu()); + _import_files_menu = createImportFilesMenu(); + menu_File->insertMenu(action_Exit, _import_files_menu); // Setup recent files menu RecentFiles* recentFiles = new RecentFiles(this, SLOT(openRecentFile()), @@ -368,6 +376,7 @@ MainWindow::MainWindow(QWidget* parent /* = 0*/) MainWindow::~MainWindow() { + delete _import_files_menu; delete _db; delete _vtkVisPipeline; delete _meshModels; @@ -429,12 +438,12 @@ void MainWindow::showVisDockWidget(bool show) void MainWindow::open() { QSettings settings("UFZ", "OpenGeoSys-5"); - QString fileName = QFileDialog::getOpenFileName( this, "Select data file to open",settings.value("lastOpenedFileDirectory").toString(), + QString fileName = QFileDialog::getOpenFileName( this, "Select data file to open",settings.value("lastOpenedOgsFileDirectory").toString(), "Geosys files (*.gsp *.gli *.gml *.msh *.stn);;Project files (*.gsp);;GeoSys FEM Conditions (*.cnd *.bc *.ic *.st);;GLI files (*.gli);;MSH files (*.msh);;STN files (*.stn);;All files (* *.*)"); if (!fileName.isEmpty()) { QDir dir = QDir(fileName); - settings.setValue("lastOpenedFileDirectory", dir.absolutePath()); + settings.setValue("lastOpenedOgsFileDirectory", dir.absolutePath()); loadFile(fileName); } } @@ -492,7 +501,7 @@ void MainWindow::save() { std::string schemaName(_fileFinder.getPath("OpenGeoSysProject.xsd")); XmlGspInterface xml(&_project, schemaName); - xml.writeFile(fileName); + xml.writeToFile(fileName.toStdString()); } else if (fi.suffix().toLower() == "geo") { @@ -501,13 +510,19 @@ void MainWindow::save() // 2. if "useStationsAsConstraints"-parameter is true, GMSH-Interface will also integrate all stations that are currently loaded // if "useSteinerPoints"-parameter is true, additional points will be inserted in large areas without information // 3. after the geo-file is created the merged geometry is deleted again as it is no longer needed - GMSHInterface gmsh_io(fileName.toStdString()); std::vector<std::string> names; this->_project.getGEOObjects()->getGeometryNames(names); std::string merge_name("MergedGeometry"); _geoModels->mergeGeometries (names, merge_name); - gmsh_io.writeGMSHInputFile(merge_name, - *(this->_project.getGEOObjects()), true, true); + names.clear(); + names.push_back(merge_name); + + double param1(0.5); // mesh density scaling on normal points + double param2(0.05); // mesh density scaling on station points + size_t param3(2); // points per leaf + GMSHInterface gmsh_io(*(this->_project.getGEOObjects()), true, FileIO::GMSH::AdaptiveMeshDensity, param1, param2, param3, names); + gmsh_io.writeToFile(fileName.toStdString()); + this->_project.getGEOObjects()->removeSurfaceVec(merge_name); this->_project.getGEOObjects()->removePolylineVec(merge_name); this->_project.getGEOObjects()->removePointVec(merge_name); @@ -539,9 +554,12 @@ void MainWindow::loadFile(const QString &fileName) QTime myTimer0; myTimer0.start(); #endif - // FileIO::readGLIFileV4 (fileName.toStdString(), _geoModels); std::string unique_name; - readGLIFileV4(fileName.toStdString(), _geoModels, unique_name); + std::vector<std::string> errors; + if (! readGLIFileV4(fileName.toStdString(), _geoModels, unique_name, errors)) { + for (size_t k(0); k<errors.size(); k++) + OGSError::box(QString::fromStdString(errors[k])); + } #ifndef NDEBUG std::cout << myTimer0.elapsed() << " ms" << std::endl; #endif @@ -591,10 +609,14 @@ void MainWindow::loadFile(const QString &fileName) // OpenGeoSys mesh files else if (fi.suffix().toLower() == "msh") { + FileIO::OGSMeshIO meshIO; std::string name = fileName.toStdString(); - MeshLib::CFEMesh* msh = FileIO::OGSMeshIO::loadMeshFromFile(name); + MeshLib::CFEMesh* msh = meshIO.loadMeshFromFile(name); if (msh) - _meshModels->addMesh(msh, name); + { + std::string mesh_name = fi.baseName().toStdString(); + _meshModels->addMesh(msh, mesh_name); + } else OGSError::box("Failed to load a mesh file."); } @@ -614,7 +636,7 @@ void MainWindow::loadFile(const QString &fileName) std::string name = fi.baseName().toStdString(); if (GMSInterface::readBoreholesFromGMS(boreholes, fileName.toStdString())) - _geoModels->addStationVec(boreholes, name, GEOLIB::getRandomColor()); + _geoModels->addStationVec(boreholes, name); else OGSError::box("Error reading GMS file."); } @@ -641,7 +663,7 @@ void MainWindow::loadFile(const QString &fileName) } // NetCDF files - // YW 07.2010 + // CH 01.2012 else if (fi.suffix().toLower() == "nc") { #ifndef NDEBUG @@ -650,17 +672,21 @@ void MainWindow::loadFile(const QString &fileName) std::cout << "NetCDF Read ...\n" << std::flush; #endif std::string name = fileName.toStdString(); - std::vector<GEOLIB::Point*>* pnt_vec = - new std::vector<GEOLIB::Point*>(); - /* Data dimensions. */ - size_t len_rlat, len_rlon; - FileIO::NetCDFInterface::readNetCDFData(name, pnt_vec, _geoModels, - len_rlat, len_rlon); - MeshLib::CFEMesh* mesh = FileIO::NetCDFInterface::createMeshFromPoints(pnt_vec, - len_rlat, - len_rlon); - //GridAdapter* grid = new GridAdapter(mesh); - _meshModels->addMesh(mesh, name); + GridAdapter* mesh; + + NetCdfConfigureDialog dlg(name); + dlg.exec(); + if (dlg.getMesh() != NULL) + { + mesh = dlg.getMesh(); + mesh->setName(dlg.getName()); + _meshModels->addMesh(mesh); + } + if (dlg.getRaster() != NULL) + { + _vtkVisPipeline->addPipelineItem(dlg.getRaster()); + } + #ifndef NDEBUG std::cout << myTimer.elapsed() << " ms" << std::endl; #endif @@ -813,17 +839,17 @@ void MainWindow::importRaster() QString geotiffExtension(""); #endif QString fileName = QFileDialog::getOpenFileName(this, "Select raster file to import", - settings.value("lastOpenedFileDirectory").toString(), QString( - "Raster files (*.asc *.bmp *.jpg *.png%1);;") .arg(geotiffExtension)); + settings.value("lastOpenedRasterFileDirectory").toString(), QString( + "Raster files (*.asc *.grd *.bmp *.jpg *.png%1);;") .arg(geotiffExtension)); if (!fileName.isEmpty()) { VtkGeoImageSource* geoImage = VtkGeoImageSource::New(); - geoImage->setImageFilename(fileName); + geoImage->readImage(fileName); _vtkVisPipeline->addPipelineItem(geoImage); QDir dir = QDir(fileName); - settings.setValue("lastOpenedFileDirectory", dir.absolutePath()); + settings.setValue("lastOpenedRasterFileDirectory", dir.absolutePath()); } } @@ -836,27 +862,24 @@ void MainWindow::importRasterAsPoly() QString geotiffExtension(""); #endif QString fileName = QFileDialog::getOpenFileName(this, "Select raster file to import", - settings.value("lastOpenedFileDirectory").toString(), QString( + settings.value("lastOpenedRasterFileDirectory").toString(), QString( "Raster files (*.asc *.bmp *.jpg *.png%1);;") .arg( geotiffExtension)); if (!fileName.isEmpty()) { QImage raster; - QPointF origin; - double scalingFactor; - OGSRaster::loadImage(fileName, raster, origin, scalingFactor, false); - //OGSRaster::loadImage(fileName, raster, origin, scalingFactor, true, true); - + double origin[2]; + double cellSize; + vtkImageAlgorithm* imageAlgorithm = VtkRaster::loadImage( + fileName.toStdString(), origin[0], origin[1], cellSize); VtkBGImageSource* bg = VtkBGImageSource::New(); - bg->SetOrigin(origin.x(), origin.y()); - bg->SetCellSize(scalingFactor); - bg->SetRaster(raster); + bg->SetRaster(imageAlgorithm, origin[0], origin[1], cellSize); bg->SetName(fileName); _vtkVisPipeline->addPipelineItem(bg); QDir dir = QDir(fileName); - settings.setValue("lastOpenedFileDirectory", dir.absolutePath()); + settings.setValue("lastOpenedRasterFileDirectory", dir.absolutePath()); } } @@ -865,7 +888,7 @@ void MainWindow::importShape() { QSettings settings("UFZ", "OpenGeoSys-5"); QString fileName = QFileDialog::getOpenFileName(this, "Select shape file to import", - settings.value("lastOpenedFileDirectory").toString(), + settings.value("lastOpenedShapeFileDirectory").toString(), "ESRI Shape files (*.shp );;"); QFileInfo fi(fileName); @@ -875,7 +898,7 @@ void MainWindow::importShape() dlg.exec(); QDir dir = QDir(fileName); - settings.setValue("lastOpenedFileDirectory", dir.absolutePath()); + settings.setValue("lastOpenedShapeFileDirectory", dir.absolutePath()); } } #endif @@ -916,10 +939,10 @@ void MainWindow::importTetGen() { QSettings settings("UFZ", "OpenGeoSys-5"); QString node_fname(QFileDialog::getOpenFileName(this, "Select TetGen node file", - settings.value("lastOpenedFileDirectory").toString(), + settings.value("lastOpenedTetgenFileDirectory").toString(), "TetGen node files (*.node);;")); QString element_fname(QFileDialog::getOpenFileName(this, "Select TetGen element file", - settings.value("lastOpenedFileDirectory").toString(), + settings.value("lastOpenedTetgenFileDirectory").toString(), "TetGen element files (*.ele);;")); if (!node_fname.isEmpty() && !element_fname.isEmpty()) { @@ -930,7 +953,7 @@ void MainWindow::importTetGen() _meshModels->addMesh(msh, name); } else OGSError::box("Failed to load a TetGen mesh."); - settings.setValue("lastOpenedFileDirectory", QDir(node_fname).absolutePath()); + settings.setValue("lastOpenedTetgenFileDirectory", QDir(node_fname).absolutePath()); } } @@ -939,8 +962,7 @@ void MainWindow::importVtk() QSettings settings("UFZ", "OpenGeoSys-5"); QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select VTK file(s) to import", - settings.value( - "lastOpenedFileDirectory"). + settings.value("lastOpenedVtkFileDirectory"). toString(), "VTK files (*.vtk *.vti *.vtr *.vts *.vtp *.vtu);;"); foreach(QString fileName, fileNames) { @@ -948,7 +970,7 @@ void MainWindow::importVtk() { _vtkVisPipeline->loadFromFile(fileName); QDir dir = QDir(fileName); - settings.setValue("lastOpenedFileDirectory", dir.absolutePath()); + settings.setValue("lastOpenedVtkFileDirectory", dir.absolutePath()); } } } @@ -997,14 +1019,11 @@ void MainWindow::showAddPipelineFilterItemDialog(QModelIndex parentIndex) dlg.exec(); } - void MainWindow::loadFEMConditions(std::string geoName) { QSettings settings("UFZ", "OpenGeoSys-5"); QString fileName = QFileDialog::getOpenFileName( this, "Select data file to open", - settings.value( - "lastOpenedFileDirectory"). - toString(), + settings.value("lastOpenedFileDirectory").toString(), "Geosys FEM condition files (*.cnd *.bc *.ic *.st);;All files (* *.*)"); QDir dir = QDir(fileName); settings.setValue("lastOpenedFileDirectory", dir.absolutePath()); @@ -1066,9 +1085,28 @@ void MainWindow::loadFEMConditionsFromFile(const QString &fileName, std::string } } } + this->addFEMConditions(conditions); +} + +void MainWindow::addFEMConditions(const std::vector<FEMCondition*> conditions) +{ if (!conditions.empty()) { - this->_processModel->addConditions(conditions); + for (size_t i = 0; i < conditions.size(); i++) + { + + if (conditions[i]->getProcessDistributionType() == FiniteElement::DIRECT) + { + std::vector<GEOLIB::Point*> *points = GEOLIB::PointVec::deepcopy(_meshModels->getMesh(conditions[i]->getAssociatedGeometryName())->getNodes()); + GEOLIB::PointVec pnt_vec("MeshNodes", points); + std::vector<GEOLIB::Point*> *cond_points = pnt_vec.getSubset(conditions[i]->getDisNodes()); + std::string geo_name = conditions[i]->getGeoName(); + this->_geoModels->addPointVec(cond_points, geo_name); + conditions[i]->setGeoName(geo_name); // this might have been changed upon inserting it into geo_objects + } + + this->_processModel->addCondition(conditions[i]); + } for (std::list<CBoundaryCondition*>::iterator it = bc_list.begin(); it != bc_list.end(); ++it) @@ -1083,36 +1121,106 @@ void MainWindow::loadFEMConditionsFromFile(const QString &fileName, std::string } } -void MainWindow::writeFEMConditionsToFile(QString geoName, QString fileName) +// Legacy function (only required for ascii st-files): reads values for 'direct' source terms +void MainWindow::loadDIRECTSourceTermsFromASCII(const std::string mshname, const std::vector<GEOLIB::Point*>* points) { - std::string schemaName(_fileFinder.getPath("OpenGeoSysCond.xsd")); - XmlCndInterface xml(&_project, schemaName); - xml.writeFile(fileName, geoName); + std::string geo_name(mshname); + + QSettings settings("UFZ", "OpenGeoSys-5"); + QString fileName = QFileDialog::getOpenFileName( this, "Select data file to open", + settings.value("lastOpenedFileDirectory").toString(), + "Geosys FEM condition files (*.st);;All files (* *.*)"); + QFileInfo fi(fileName); + std::string file_path = fi.absoluteDir().absolutePath().toStdString() + "/"; + + if (!fileName.isEmpty()) + { + std::string st_file_name (file_path); + STRead(st_file_name.append(fi.baseName().toStdString()), *_geoModels, geo_name); + + for (std::vector<CSourceTerm*>::const_iterator it = st_vector.begin(); it != st_vector.end(); + ++it) + { + if ((*it)->getProcessDistributionType() == FiniteElement::DIRECT) + { + CSourceTerm ast = **it; + SourceTerm* st = new SourceTerm(ast, mshname); + std::vector< std::pair<size_t, double> > node_values; + SourceTerm::getDirectNodeValues(file_path + (*it)->fname, node_values); + st->setGeoName(mshname); + st->setDisValues(node_values); + + std::vector<GEOLIB::Point*> *points2 = GEOLIB::PointVec::deepcopy(points); + GEOLIB::PointVec pnt_vec("MeshNodes", points2); + std::vector<GEOLIB::Point*> *cond_points = pnt_vec.getSubset(st->getDisNodes()); + std::string geometry_name = st->getGeoName(); + this->_geoModels->addPointVec(cond_points, geometry_name); + this->_processModel->addCondition(st); + } + } + } +} + +void MainWindow::writeFEMConditionsToFile(const QString &geoName, const FEMCondition::CondType type, const QString &fileName) +{ + QFileInfo fi(fileName); + if (fi.suffix().compare("cnd") == 0 ) + { + std::string schemaName(_fileFinder.getPath("OpenGeoSysCond.xsd")); + XmlCndInterface xml(&_project, schemaName); + xml.setNameForExport(geoName.toStdString()); + xml.setConditionType(type); + xml.writeToFile(fileName.toStdString()); + } + else + { + const std::vector<FEMCondition*> conds = _project.getConditions(); + for (size_t i=0; i<conds.size(); i++) + { + if ((conds[i]->getCondType() == type) && + (QString::fromStdString(conds[i]->getAssociatedGeometryName()) == geoName)) + { + if (type == FEMCondition::BOUNDARY_CONDITION) + bc_list.push_back(new CBoundaryCondition(static_cast<BoundaryCondition*>(conds[i]))); + else if (type == FEMCondition::INITIAL_CONDITION) + ic_vector.push_back(new CInitialCondition(static_cast<InitialCondition*>(conds[i]))); + else if (type == FEMCondition::SOURCE_TERM) + st_vector.push_back(new CSourceTerm(static_cast<SourceTerm*>(conds[i]))); + } + } + if (type == FEMCondition::BOUNDARY_CONDITION) + BCWrite(fileName.toStdString()); + else if (type == FEMCondition::INITIAL_CONDITION) + ICWrite(fileName.toStdString()); + else if (type == FEMCondition::SOURCE_TERM) + STWrite(fileName.toStdString()); + } } void MainWindow::writeGeometryToFile(QString gliName, QString fileName) { std::string schemaName(_fileFinder.getPath("OpenGeoSysGLI.xsd")); XmlGmlInterface xml(&_project, schemaName); - xml.writeFile(fileName, gliName); + xml.setNameForExport(gliName.toStdString()); + xml.writeToFile(fileName.toStdString()); } void MainWindow::writeStationListToFile(QString listName, QString fileName) { std::string schemaName(_fileFinder.getPath("OpenGeoSysSTN.xsd")); XmlStnInterface xml(&_project, schemaName); - xml.writeFile(fileName, listName); + xml.setNameForExport(listName.toStdString()); + xml.writeToFile(fileName.toStdString()); } void MainWindow::exportBoreholesToGMS(std::string listName, std::string fileName) { - const std::vector<GEOLIB::Point*>* stations(_geoModels->getStationVec( - listName)); + const std::vector<GEOLIB::Point*>* stations(_geoModels->getStationVec(listName)); GMSInterface::writeBoreholesToGMS(stations, fileName); } -void MainWindow::callGMSH(std::vector<std::string> const & selectedGeometries, +void MainWindow::callGMSH(std::vector<std::string> & selectedGeometries, size_t param1, double param2, double param3, double param4, bool delete_geo_file) { @@ -1133,21 +1241,24 @@ void MainWindow::callGMSH(std::vector<std::string> const & selectedGeometries, if (!fileName.isEmpty()) { - GMSHInterface gmsh_io(fileName.toStdString()); - - if (param4 == -1) // adaptive meshing selected - gmsh_io.writeAllDataToGMSHInputFile(*_geoModels, - selectedGeometries, - param1, - param2, - param3); - else // homogeneous meshing selected - gmsh_io.writeAllDataToGMSHInputFile(*_geoModels, - selectedGeometries, param4); + if (param4 == -1) { // adaptive meshing selected + GMSHInterface gmsh_io(*(static_cast<GEOLIB::GEOObjects*> (_geoModels)), true, + FileIO::GMSH::AdaptiveMeshDensity, param2, param3, param1, + selectedGeometries); + gmsh_io.setPrecision(20); + gmsh_io.writeToFile(fileName.toStdString()); + } else { // homogeneous meshing selected + GMSHInterface gmsh_io(*(static_cast<GEOLIB::GEOObjects*> (_geoModels)), true, + FileIO::GMSH::FixedMeshDensity, param4, param3, param1, + selectedGeometries); + gmsh_io.setPrecision(20); + gmsh_io.writeToFile(fileName.toStdString()); + } + if (system(NULL) != 0) // command processor available { - std::string gmsh_command("gmsh -2 "); + std::string gmsh_command("gmsh -2 -algo meshadapt "); std::string fname (fileName.toStdString()); gmsh_command += fname; size_t pos (fname.rfind (".")); @@ -1181,6 +1292,14 @@ void MainWindow::callGMSH(std::vector<std::string> const & selectedGeometries, } } +void MainWindow::showConditionWriterDialog() +{ + ConditionWriterDialog dlg(_geoModels); + connect(&dlg , SIGNAL(saveFEMConditionsRequested(const QString&, const FEMCondition::CondType, const QString&)), + this, SLOT(writeFEMConditionsToFile(const QString&, const FEMCondition::CondType, const QString&))); + dlg.exec(); +} + void MainWindow::showDiagramPrefsDialog(QModelIndex &index) { QString listName; @@ -1216,6 +1335,12 @@ void MainWindow::showDiagramPrefsDialog() } } +void MainWindow::showFileConverterDialog() +{ + OGSFileConverter dlg; + dlg.exec(); +} + void MainWindow::showGeoNameDialog(const std::string &geometry_name, const GEOLIB::GEOTYPE object_type, size_t id) { std::string old_name = this->_geoModels->getElementNameByID(geometry_name, object_type, id); @@ -1228,9 +1353,14 @@ void MainWindow::showGeoNameDialog(const std::string &geometry_name, const GEOLI id, this->_geoModels->getElementNameByID(geometry_name, object_type, id)); } -void MainWindow::showCondSetupDialog(const std::string &geometry_name, const GEOLIB::GEOTYPE object_type, size_t id) +void MainWindow::showCondSetupDialog(const std::string &geometry_name, const GEOLIB::GEOTYPE object_type, size_t id, bool on_points) { - std::string geo_name = this->_geoModels->getElementNameByID(geometry_name, object_type, id); + std::string geo_name(""); + if (object_type != GEOLIB::INVALID) + geo_name = this->_geoModels->getElementNameByID(geometry_name, object_type, id); + else + geo_name = geometry_name; // in this case this is actually the mesh name + if (geo_name.empty()) { this->showGeoNameDialog(geometry_name, object_type, id); @@ -1241,9 +1371,22 @@ void MainWindow::showCondSetupDialog(const std::string &geometry_name, const GEO OGSError::box("FEM Condition Setup cancelled."); else { - FEMConditionSetupDialog dlg(geometry_name, object_type, geo_name, this->_geoModels->getGEOObject(geometry_name, object_type, geo_name)); - connect(&dlg, SIGNAL(addFEMCondition(FEMCondition*)), this->_processModel, SLOT(addCondition(FEMCondition*))); - dlg.exec(); + if (on_points) + this->_geoModels->addNameForObjectPoints(geometry_name, object_type, geo_name, geometry_name); + + if (object_type != GEOLIB::INVALID) + { + FEMConditionSetupDialog dlg(geometry_name, object_type, geo_name, this->_geoModels->getGEOObject(geometry_name, object_type, geo_name), on_points); + connect(&dlg, SIGNAL(createFEMCondition(std::vector<FEMCondition*>)), this, SLOT(addFEMConditions(std::vector<FEMCondition*>))); + dlg.exec(); + } + else + { + const MeshLib::CFEMesh* mesh = _project.getMesh(geo_name); + FEMConditionSetupDialog dlg(geo_name, mesh); + connect(&dlg, SIGNAL(createFEMCondition(std::vector<FEMCondition*>)), this, SLOT(addFEMConditions(std::vector<FEMCondition*>))); + dlg.exec(); + } } } @@ -1266,8 +1409,8 @@ void MainWindow::showLineEditDialog(const std::string &geoName) void MainWindow::showGMSHPrefsDialog() { GMSHPrefsDialog dlg(_geoModels); - connect(&dlg, SIGNAL(requestMeshing(std::vector<std::string> const &, size_t, double, double, double, bool)), - this, SLOT(callGMSH(std::vector<std::string> const &, size_t, double, double, double, bool))); + connect(&dlg, SIGNAL(requestMeshing(std::vector<std::string> &, size_t, double, double, double, bool)), + this, SLOT(callGMSH(std::vector<std::string> &, size_t, double, double, double, bool))); dlg.exec(); } @@ -1286,22 +1429,28 @@ void MainWindow::showVisalizationPrefsDialog() void MainWindow::FEMTestStart() { - //FEMConditionSetupDialog* dlg = new FEMConditionSetupDialog(this->_project); - //dlg->exec(); - - // *** begin test TetGen read mesh - const std::string path ("/home/fischeth/Desktop/data/Ketzin/PSglobal/Tom/MSH/"); - std::string mesh_name ("ClosedSurface"); - std::string fname_nodes(path + mesh_name + ".1.node"); - std::string fname_elements(path + mesh_name + ".1.ele"); - - FileIO::TetGenInterface tetgen; - MeshLib::CFEMesh* mesh (tetgen.readTetGenMesh (fname_nodes, fname_elements)); - - if (mesh) - _meshModels->addMesh(mesh, mesh_name); - else - OGSError::box("Failed to load TetGen mesh file."); std::cout << "This is test functionality only..." << std::endl; +// std::map<std::string, MeshLib::CFEMesh*> const& mesh_map (_project.getMeshObjects()); +// +// std::string mesh_name(mesh_map.begin()->first); +// std::cout << "[Test] get mesh " << mesh_name << " ... " << std::flush; +// MeshLib::CFEMesh const*const mesh (_project.getMesh(mesh_name)); +// if (mesh) { +// std::cout << "done" << std::endl; +//#ifndef NDEBUG +// (mesh->getMeshGrid())->createMeshGridGeometry(_project.getGEOObjects()); +//#endif +//// std::cout << "[Test] writing mesh in TetGen file format ... " << std::flush; +//// FileIO::TetGenInterface tetgen_io; +//// tetgen_io.writeTetGenMesh(mesh_name+".node", mesh_name+".ele", mesh); +// std::cout << "done" << std::endl; +// } else { +// std::cout << "[Test] could not load mesh " << mesh_name << std::endl; +// } + + /* + CondFromRasterDialog dlg(_project.getMeshObjects()); + dlg.exec(); + */ } void MainWindow::showTrackingSettingsDialog() @@ -1526,45 +1675,3 @@ QString MainWindow::getLastUsedDir() return QDir::homePath(); } -void MainWindow::loadDIRECTSourceTerms(const std::string mshname, const std::vector<GEOLIB::Point*>* points) -{ - std::string geo_name(mshname); - - QSettings settings("UFZ", "OpenGeoSys-5"); - QString fileName = QFileDialog::getOpenFileName( this, "Select data file to open", - settings.value( - "lastOpenedFileDirectory"). - toString(), - "Geosys FEM condition files (*.st);;All files (* *.*)"); - QFileInfo fi(fileName); - QString name = fi.path() + "/"; - - if (!fileName.isEmpty()) - { - // create new geometry points vector by copying mesh nodes vector - std::vector<GEOLIB::Point*>* new_points = new std::vector<GEOLIB::Point*>; - //ignore name map because it makes things incredibly slow (and mesh-nodes cannot have names anyway, can they?) - //std::map<std::string, size_t>* name_pnt_id_map = new std::map<std::string, size_t>; - - for (size_t i = 0; i < points->size(); i++) - { - new_points->push_back(new GEOLIB::Point((*(*points)[i])[0], (*(*points)[i])[1], (*(*points)[i])[2])); - } - this->_geoModels->addPointVec(new_points, geo_name /*, name_pnt_id_map*/); - - STRead((name.append(fi.baseName())).toStdString(), *_geoModels, geo_name); - // access via st_vector (i.e. global vector from rf_st_new.h) - std::string file_path = fi.absoluteDir().absolutePath().toStdString(); - std::vector<FEMCondition*> conditions = SourceTerm::createDirectSourceTerms(st_vector, geo_name, file_path); - - // add boundary conditions to model - if (!conditions.empty()) - { - this->_processModel->addConditions(conditions); - for (size_t i = 0; i < st_vector.size(); i++) - delete st_vector[i]; - st_vector.clear(); - } - } -} - diff --git a/Gui/mainwindow.h b/Gui/mainwindow.h index 472346712001279583595483b2630e7998dc1f81..6da7ce35f6734a935df5bbb90105757d7a19480f 100644 --- a/Gui/mainwindow.h +++ b/Gui/mainwindow.h @@ -53,7 +53,7 @@ protected slots: /// Function calls for saving files. void save(); /// Function calls for generating GMSH files from the GUI - void callGMSH(std::vector<std::string> const & selectedGeometries, + void callGMSH(std::vector<std::string> & selectedGeometries, size_t param1, double param2, double param3, @@ -81,14 +81,16 @@ protected slots: void openRecentFile(); void about(); void showAddPipelineFilterItemDialog(QModelIndex parentIndex); + void showConditionWriterDialog(); /// Call dialog for creating or modifying FEM conditions. - void showCondSetupDialog(const std::string &geometry_name, const GEOLIB::GEOTYPE object_type, size_t id); + void showCondSetupDialog(const std::string &geometry_name, const GEOLIB::GEOTYPE object_type, size_t id, bool on_points = false); /// Allows setting the name for a geometric object void showGeoNameDialog(const std::string &geometry_name, const GEOLIB::GEOTYPE object_type, size_t id); /// Calls the diagram prefs dialog from the Tools menu. void showDiagramPrefsDialog(); /// Calls the diagram prefs dialog from the station list (i.e. for a specific station). void showDiagramPrefsDialog(QModelIndex &index); + void showFileConverterDialog(); void showLineEditDialog(const std::string &geoName); void showGMSHPrefsDialog(); void showMshQualitySelectionDialog(VtkMeshSource* mshSource); @@ -97,7 +99,8 @@ protected slots: void showVisalizationPrefsDialog(); void showTrackingSettingsDialog(); void updateDataViews(); - void writeFEMConditionsToFile(QString geoName, QString fileName); + void addFEMConditions(const std::vector<FEMCondition*> conditions); + void writeFEMConditionsToFile(const QString &geoName, const FEMCondition::CondType type, const QString &fileName); void writeGeometryToFile(QString listName, QString fileName); void writeStationListToFile(QString listName, QString fileName); @@ -110,7 +113,7 @@ protected slots: void startPresentationMode(); void quitPresentationMode(); - void loadDIRECTSourceTerms(const std::string name, const std::vector<GEOLIB::Point*>* points); //TODO put this in a better place + void loadDIRECTSourceTermsFromASCII(const std::string name, const std::vector<GEOLIB::Point*>* points); //TODO put this in a better place private: QMenu* createImportFilesMenu(); @@ -136,6 +139,8 @@ private: QList<QRect> _screenGeometries; QWidget* _vtkWidget; QByteArray _windowState; + QMenu* _import_files_menu; + #ifdef OGS_USE_VRPN TrackingSettingsWidget* _trackingSettingsWidget; #endif // OGS_USE_VRPN diff --git a/Gui/mainwindow.ui b/Gui/mainwindow.ui index aad1c105991f62899c39d6c5fe1b2ba399cc67bf..375d7f501435f867067bd03b14811458390a8845 100644 --- a/Gui/mainwindow.ui +++ b/Gui/mainwindow.ui @@ -127,6 +127,7 @@ <string>Tools</string> </property> <addaction name="actionMesh_Generation"/> + <addaction name="actionFile_Converter"/> <addaction name="actionDiagram_Viewer"/> <addaction name="actionFEM_Test"/> </widget> @@ -393,6 +394,11 @@ <string>About</string> </property> </action> + <action name="actionFile_Converter"> + <property name="text"> + <string>File Converter...</string> + </property> + </action> </widget> <layoutdefault spacing="6" margin="11"/> <customwidgets> @@ -611,6 +617,22 @@ </hint> </hints> </connection> + <connection> + <sender>actionFile_Converter</sender> + <signal>triggered()</signal> + <receiver>MainWindowClass</receiver> + <slot>showFileConverterDialog()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>400</x> + <y>372</y> + </hint> + </hints> + </connection> </connections> <slots> <slot>open()</slot> @@ -624,5 +646,6 @@ <slot>FEMTestStart()</slot> <slot>showDiagramPrefsDialog()</slot> <slot>about()</slot> + <slot>showFileConverterDialog()</slot> </slots> </ui> diff --git a/OpenSG/CMakeLists.txt b/OpenSG/CMakeLists.txt index 285f1faa2ecc11d518629f6877036b303ea251d5..76558c93482bec78e0a0b6cb89bed26b6bdddbb6 100644 --- a/OpenSG/CMakeLists.txt +++ b/OpenSG/CMakeLists.txt @@ -13,7 +13,7 @@ SET( HEADERS ### Include directories ### INCLUDE_DIRECTORIES( - . + ${CMAKE_SOURCE_DIR}/Qt/OpenSG ) ### Create the library ### diff --git a/OpenSG/vtkOsgConverter.cpp b/OpenSG/vtkOsgConverter.cpp index c35c76e2217589210a2c83bc4f70efb90f36d00a..5078fda13aa6722aac54f97cc51a317dfda496db 100644 --- a/OpenSG/vtkOsgConverter.cpp +++ b/OpenSG/vtkOsgConverter.cpp @@ -25,6 +25,9 @@ #include <vtkSmartPointer.h> #include <vtkTexture.h> #include <vtkUnsignedCharArray.h> +#include <vtkCellDataToPointData.h> +#include <vtkLookupTable.h> +#include <vtkDiscretizableColorTransferFunction.h> #include <OpenSG/OSGGeoFunctions.h> #include <OpenSG/OSGGroup.h> @@ -36,19 +39,20 @@ #include <OpenSG/OSGPolygonChunk.h> #include <OpenSG/OSGSimpleGeometry.h> #include <OpenSG/OSGTwoSidedLightingChunk.h> +#include <OpenSG/OSGTextureChunk.h> +#include <OpenSG/OSGGL.h> OSG_USING_NAMESPACE vtkOsgConverter::vtkOsgConverter(vtkActor* actor) : _actor(actor), - _verbose(false), + _verbose(true), _osgRoot(NullFC), _osgTransform(NullFC) { TransformPtr tptr; _osgRoot = makeCoredNode<osg::Transform>(&tptr); _osgTransform = tptr; - _mapper = _actor->GetMapper(); } vtkOsgConverter::~vtkOsgConverter(void) @@ -58,14 +62,15 @@ vtkOsgConverter::~vtkOsgConverter(void) bool vtkOsgConverter::WriteAnActor() { + vtkMapper* actorMapper = _actor->GetMapper(); // see if the actor has a mapper. it could be an assembly - if (_actor->GetMapper() == NULL) + if (actorMapper == NULL) return false; // dont export when not visible if (_actor->GetVisibility() == 0) return false; - vtkDataObject* inputDO = _actor->GetMapper()->GetInputDataObject(0, 0); + vtkDataObject* inputDO = actorMapper->GetInputDataObject(0, 0); if (inputDO == NULL) return false; @@ -90,30 +95,63 @@ bool vtkOsgConverter::WriteAnActor() else pd = static_cast<vtkPolyData*>(inputDO); + // Get the color range from actors lookup table + double range[2]; + vtkLookupTable* actorLut = static_cast<vtkLookupTable*>(actorMapper->GetLookupTable()); + actorLut->GetTableRange(range); + // Copy mapper to a new one vtkPolyDataMapper* pm = vtkPolyDataMapper::New(); + // Convert cell data to point data + // NOTE: Comment this out to export a mesh + if (actorMapper->GetScalarMode() == VTK_SCALAR_MODE_USE_CELL_DATA || + actorMapper->GetScalarMode() == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA) + { + vtkCellDataToPointData* cellDataToPointData = vtkCellDataToPointData::New(); + cellDataToPointData->PassCellDataOff(); + cellDataToPointData->SetInput(pd); + cellDataToPointData->Update(); + pd = cellDataToPointData->GetPolyDataOutput(); + cellDataToPointData->Delete(); + + pm->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_DATA); + } + else + pm->SetScalarMode(actorMapper->GetScalarMode()); + pm->SetInput(pd); - pm->SetScalarRange(_actor->GetMapper()->GetScalarRange()); - pm->SetScalarVisibility(_actor->GetMapper()->GetScalarVisibility()); - pm->SetLookupTable(_actor->GetMapper()->GetLookupTable()); - pm->SetScalarMode(_actor->GetMapper()->GetScalarMode()); + pm->SetScalarVisibility(actorMapper->GetScalarVisibility()); + + vtkLookupTable* lut = NULL; + // ParaView OpenSG Exporter + if (dynamic_cast<vtkDiscretizableColorTransferFunction*>(actorMapper->GetLookupTable())) + lut = actorLut; + // Clone the lut in OGS because otherwise the original lut gets destroyed + else + { + lut = vtkLookupTable::New(); + lut->DeepCopy(actorLut); + lut->Build(); + } + pm->SetLookupTable(lut); + pm->SetScalarRange(range); + pm->Update(); if(pm->GetScalarMode() == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA || pm->GetScalarMode() == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ) { - if(_actor->GetMapper()->GetArrayAccessMode() == VTK_GET_ARRAY_BY_ID ) - pm->ColorByArrayComponent(_actor->GetMapper()->GetArrayId(), - _actor->GetMapper()->GetArrayComponent()); + if(actorMapper->GetArrayAccessMode() == VTK_GET_ARRAY_BY_ID ) + pm->ColorByArrayComponent(actorMapper->GetArrayId(), + actorMapper->GetArrayComponent()); else - pm->ColorByArrayComponent(_actor->GetMapper()->GetArrayName(), - _actor->GetMapper()->GetArrayComponent()); + pm->ColorByArrayComponent(actorMapper->GetArrayName(), + actorMapper->GetArrayComponent()); } - _mapper = pm; - // vtkPoints* points = pd->GetPoints(); + vtkPointData* pntData = pd->GetPointData(); bool hasTexCoords = false; - vtkUnsignedCharArray* vtkColors = pm->MapScalars(1.0); + vtkUnsignedCharArray* vtkColors = pm->MapScalars(1.0); // ARRAY SIZES vtkIdType m_iNumPoints = pd->GetNumberOfPoints(); @@ -138,8 +176,6 @@ bool vtkOsgConverter::WriteAnActor() std::cout << " number of primitives: " << m_iNumGLPrimitives << std::endl; } - _mapper->Update(); - // NORMALS vtkDataArray* vtkNormals = NULL; int m_iNormalType = NOT_GIVEN; @@ -271,7 +307,7 @@ bool vtkOsgConverter::WriteAnActor() _osgTransform->setMatrix(m); endEditCP(_osgTransform); - _mapper->Update(); + //pm->Update(); // Get the converted OpenSG node NodePtr osgGeomNode = Node::create(); @@ -291,12 +327,11 @@ bool vtkOsgConverter::WriteAnActor() GeoTexCoords2dPtr osgTexCoords = GeoTexCoords2d::create(); //Rendering with OpenSG simple indexed geometry - if (((m_iNormalType == PER_VERTEX) || (m_iNormalType == NOT_GIVEN)) && - ((m_iColorType == PER_VERTEX) || (m_iColorType == NOT_GIVEN))) + if (((m_iNormalType == PER_VERTEX) || (m_iNormalType == NOT_GIVEN)) && + ((m_iColorType == PER_VERTEX) || (m_iColorType == NOT_GIVEN))) { if (_verbose) - std::cout << "Start ProcessGeometryNormalsAndColorsPerVertex()" << - std::endl; + std::cout << "Start ProcessGeometryNormalsAndColorsPerVertex()" << std::endl; //getting the vertices: beginEditCP(osgPoints); @@ -318,8 +353,7 @@ bool vtkOsgConverter::WriteAnActor() for (int i = 0; i < iNumNormals; i++) { aNormal = vtkNormals->GetTuple(i); - osgNormals->addValue(Vec3f(aNormal[0], aNormal[1], - aNormal[2])); + osgNormals->addValue(Vec3f(aNormal[0], aNormal[1], aNormal[2])); } } endEditCP(osgNormals); if (iNumNormals != m_iNumPoints) @@ -327,8 +361,7 @@ bool vtkOsgConverter::WriteAnActor() std::cout << "WARNING: CVtkActorToOpenSG::ProcessGeometryNormalsAndColorsPerVertex() number of normals" << std::endl; - std::cout << "should equal the number of vertices (points)!" << - std::endl << std::endl; + std::cout << "should equal the number of vertices (points)!" << std::endl << std::endl; } } @@ -353,8 +386,7 @@ bool vtkOsgConverter::WriteAnActor() std::cout << "WARNING: CVtkActorToOpenSG::ProcessGeometryNormalsAndColorsPerVertex() number of colors" << std::endl; - std::cout << "should equal the number of vertices (points)!" << - std::endl << std::endl; + std::cout << "should equal the number of vertices (points)!" << std::endl << std::endl; } } @@ -418,8 +450,7 @@ bool vtkOsgConverter::WriteAnActor() prim = 0; pCells = pd->GetStrips(); if (pCells->GetNumberOfCells() > 0) - for (pCells->InitTraversal(); pCells->GetNextCell(npts, pts); - prim++) + for (pCells->InitTraversal(); pCells->GetNextCell(npts, pts); prim++) { osgLengths->addValue(npts); osgTypes->addValue(GL_TRIANGLE_STRIP); @@ -464,36 +495,28 @@ bool vtkOsgConverter::WriteAnActor() if(m_iNumGLPolygons > 0) { if(m_iNumGLPolygons != m_iNumGLPrimitives) - std::cout << - "WARNING: vtkActor contains different kind of primitives" << - std::endl; + std::cout << "WARNING: vtkActor contains different kind of primitives" << std::endl; gl_primitive_type = GL_POLYGON; //osgConversionSuccess = this->ProcessGeometryNonIndexedCopyAttributes(GL_POLYGON, pd, osgGeometry); } else if(m_iNumGLLineStrips > 0) { if (m_iNumGLLineStrips != m_iNumGLPrimitives) - std::cout << - "WARNING: vtkActor contains different kind of primitives" << - std::endl; + std::cout << "WARNING: vtkActor contains different kind of primitives" << std::endl; gl_primitive_type = GL_LINE_STRIP; //osgConversionSuccess = this->ProcessGeometryNonIndexedCopyAttributes(GL_LINE_STRIP, pd osgGeometry); } else if(m_iNumGLTriStrips > 0) { if (m_iNumGLTriStrips != m_iNumGLPrimitives) - std::cout << - "WARNING: vtkActor contains different kind of primitives" << - std::endl; + std::cout << "WARNING: vtkActor contains different kind of primitives" << std::endl; gl_primitive_type = GL_TRIANGLE_STRIP; //osgConversionSuccess = this->ProcessGeometryNonIndexedCopyAttributes(GL_TRIANGLE_STRIP, pd osgGeometry); } else if (m_iNumGLPoints > 0) { if (m_iNumGLPoints != m_iNumGLPrimitives) - std::cout << - "WARNING: vtkActor contains different kind of primitives" << - std::endl; + std::cout << "WARNING: vtkActor contains different kind of primitives" << std::endl; gl_primitive_type = GL_POINTS; //osgConversionSuccess = this->ProcessGeometryNonIndexedCopyAttributes(GL_POINTS, pd osgGeometry); } @@ -512,9 +535,7 @@ bool vtkOsgConverter::WriteAnActor() { std::cout << "CVtkActorToOpenSG::ProcessGeometryNonIndexedCopyAttributes(int gl_primitive_type)" - << std::endl; - std::cout << - " was called with non implemented gl_primitive_type!" << std::endl; + << std::endl << " was called with non implemented gl_primitive_type!" << std::endl; } beginEditCP(osgTypes); @@ -539,50 +560,35 @@ bool vtkOsgConverter::WriteAnActor() unsigned char aColor[4]; aVertex = pd->GetPoint(pts[i]); - osgPoints->addValue(Vec3f(aVertex[0], - aVertex[1], - aVertex[2])); + osgPoints->addValue(Vec3f(aVertex[0], aVertex[1], aVertex[2])); if (m_iNormalType == PER_VERTEX) { aNormal = vtkNormals->GetTuple(pts[i]); - osgNormals->addValue(Vec3f(aNormal[ - 0 - ], - aNormal[1], aNormal[2])); + osgNormals->addValue(Vec3f(aNormal[0], aNormal[1], aNormal[2])); } else if (m_iNormalType == PER_CELL) { aNormal = vtkNormals->GetTuple(prim); - osgNormals->addValue(Vec3f(aNormal[ - 0 - ], - aNormal[1], aNormal[2])); + osgNormals->addValue(Vec3f(aNormal[0], aNormal[1], aNormal[2])); } if (m_iColorType == PER_VERTEX) { - vtkColors->GetTupleValue(pts[i], - aColor); - float r = ((float) aColor[0]) / - 255.0f; - float g = ((float) aColor[1]) / - 255.0f; - float b = ((float) aColor[2]) / - 255.0f; + vtkColors->GetTupleValue(pts[i], aColor); + float r = ((float) aColor[0]) / 255.0f; + float g = ((float) aColor[1]) / 255.0f; + float b = ((float) aColor[2]) / 255.0f; osgColors->addValue(Color3f(r, g, b)); } else if (m_iColorType == PER_CELL) { vtkColors->GetTupleValue(prim, aColor); - float r = ((float) aColor[0]) / - 255.0f; - float g = ((float) aColor[1]) / - 255.0f; - float b = ((float) aColor[2]) / - 255.0f; + float r = ((float) aColor[0]) / 255.0f; + float g = ((float) aColor[1]) / 255.0f; + float b = ((float) aColor[2]) / 255.0f; osgColors->addValue(Color3f(r, g, b)); } } @@ -609,8 +615,7 @@ bool vtkOsgConverter::WriteAnActor() { double texCoords[3]; vtkTexCoords->GetTuple(i, texCoords); - osgTexCoords->addValue(Vec2f(texCoords[0], - texCoords[1])); + osgTexCoords->addValue(Vec2f(texCoords[0], texCoords[1])); } } endEditCP(osgTexCoords); } @@ -681,6 +686,8 @@ bool vtkOsgConverter::WriteAnActor() _osgRoot->addChild(osgGeomNode); endEditCP(_osgRoot); + pm->Delete(); + return true; } @@ -735,7 +742,7 @@ TextureChunkPtr vtkOsgConverter::CreateTexture(vtkTexture* vtkTexture) { data = imgPointData->GetScalars(); if (_verbose) - std::cout << " found texture data in point data" << std::endl; + std::cout << " Found texture data in point data" << std::endl; } if (imgCellData != NULL) @@ -743,7 +750,7 @@ TextureChunkPtr vtkOsgConverter::CreateTexture(vtkTexture* vtkTexture) { data = imgCellData->GetScalars(); if (_verbose) - std::cout << " found texture data in cell data" << std::endl; + std::cout << " Found texture data in cell data" << std::endl; } if (data == NULL) @@ -785,6 +792,8 @@ TextureChunkPtr vtkOsgConverter::CreateTexture(vtkTexture* vtkTexture) osgImage->setDataType(Image::OSG_UINT8_IMAGEDATA); if (iImgComps == 1) osgImage->setPixelFormat(Image::OSG_L_PF); + else if (iImgComps == 2) + osgImage->setPixelFormat(Image::OSG_LA_PF); else if (iImgComps == 3) osgImage->setPixelFormat(Image::OSG_RGB_PF); else if (iImgComps == 4) @@ -807,8 +816,8 @@ TextureChunkPtr vtkOsgConverter::CreateTexture(vtkTexture* vtkTexture) if (_verbose) { std::cout << " Loading image with " << iImgDims[0] << " x " << iImgDims[1] << - " x " << iImgDims[2] << "pixels." << std::endl; - std::cout << " components: " << iImgComps << std::endl; + " x " << iImgDims[2] << " pixels." << std::endl; + std::cout << " Components: " << iImgComps << std::endl; std::cout << "End CreateTexture()" << std::endl; } @@ -840,11 +849,11 @@ ChunkMaterialPtr vtkOsgConverter::CreateMaterial(bool lit, bool hasTexCoords) if (_verbose) { std::cout << " Colors:" << std::endl; - std::cout << " diffuse " << diffuse << " * " << diffuseColor[0] << " " << + std::cout << " diffuse " << diffuse << " * " << diffuseColor[0] << " " << diffuseColor[1] << " " << diffuseColor[2] << std::endl; - std::cout << " ambient " << ambient << " * " << ambientColor[0] << " " << + std::cout << " ambient " << ambient << " * " << ambientColor[0] << " " << ambientColor[1] << " " << ambientColor[2] << std::endl; - std::cout << " specular " << specular << " * " << specularColor[0] << " " << + std::cout << " specular " << specular << " * " << specularColor[0] << " " << specularColor[1] << " " << specularColor[2] << std::endl; } @@ -929,12 +938,17 @@ ChunkMaterialPtr vtkOsgConverter::CreateMaterial(bool lit, bool hasTexCoords) std::cout << " Add TextureChunk" << std::endl; osgChunkMaterial->addChunk(osgTextureChunk); } + + // Per default EnvMode is set to GL_REPLACE which does not lit the surface + beginEditCP(osgTextureChunk); + osgTextureChunk->setEnvMode(GL_MODULATE); + endEditCP(osgTextureChunk); } } } endEditCP(osgChunkMaterial); if (_verbose) - std::cout << " End CreateMaterial()" << std::endl; + std::cout << "End CreateMaterial()" << std::endl; return osgChunkMaterial; } diff --git a/OpenSG/vtkOsgConverter.h b/OpenSG/vtkOsgConverter.h index ca24f736743d01a1d5d547333a35d50d31712649..a5f06c0bcbd77eaae927cb8dca730f3f9cd48fbe 100644 --- a/OpenSG/vtkOsgConverter.h +++ b/OpenSG/vtkOsgConverter.h @@ -43,7 +43,6 @@ protected: private: vtkActor* _actor; - vtkMapper* _mapper; enum {NOT_GIVEN, PER_VERTEX, PER_CELL}; bool _verbose; diff --git a/Vrpn/CMakeLists.txt b/Vrpn/CMakeLists.txt index 9350c491f3d3e31b32ef748490559405614bc6bc..aa5cdcf8abd2bacc7ecf57247d4219d80f48b5a8 100644 --- a/Vrpn/CMakeLists.txt +++ b/Vrpn/CMakeLists.txt @@ -36,10 +36,10 @@ Qt4_WRAP_CPP( MOC_SOURCES ${MOC_HEADERS} ) ### Include directories ### INCLUDE_DIRECTORIES( - . - ${CMAKE_BINARY_DIR}/Qt/Vrpn/ + ${CMAKE_SOURCE_DIR}/Qt/Vrpn + ${CMAKE_BINARY_DIR}/Qt/Vrpn ${VRPN_INCLUDE_DIRS} - ../VtkVis + ${CMAKE_SOURCE_DIR}/Qt/VtkVis ${CMAKE_BINARY_DIR}/Qt/VtkVis ) diff --git a/VtkAct/CMakeLists.txt b/VtkAct/CMakeLists.txt index 78ee2b9fdc164909eab97533b12a0be723ad459a..a8606e0be7275e698bbeca85bfc4974d6d97e2c7 100644 --- a/VtkAct/CMakeLists.txt +++ b/VtkAct/CMakeLists.txt @@ -12,7 +12,7 @@ set( MOC_HEADERS # Header files set( HEADERS - + ) # UI files @@ -30,16 +30,16 @@ source_group("Moc Files" REGULAR_EXPRESSION "moc_.*") qt4_wrap_cpp( MOC_SOURCES ${MOC_HEADERS} ) include_directories( - . + ${CMAKE_SOURCE_DIR}/Qt/VtkAct ${CMAKE_BINARY_DIR}/Qt/VtkAct - ../../Base - ../../FEM - ../../GEO - ../../FileIO - ../../FileIO/MeshIO - ../../MSH - ../../MathLib - ../VtkVis + ${CMAKE_SOURCE_DIR}/Base + ${CMAKE_SOURCE_DIR}/FEM + ${CMAKE_SOURCE_DIR}/GEO + ${CMAKE_SOURCE_DIR}/FileIO + ${CMAKE_SOURCE_DIR}/FileIO/MeshIO + ${CMAKE_SOURCE_DIR}/MSH + ${CMAKE_SOURCE_DIR}/MathLib + ${CMAKE_SOURCE_DIR}/Qt/VtkVis ) # Create the library diff --git a/VtkVis/CMakeLists.txt b/VtkVis/CMakeLists.txt index d98326dac0bd38de0799b7aad48ba2d3d78e6688..c62e60cb943fbe467fac0cc07050cddff67e865a 100644 --- a/VtkVis/CMakeLists.txt +++ b/VtkVis/CMakeLists.txt @@ -8,7 +8,6 @@ SET( SOURCES VtkAlgorithmPropertyCheckbox.cpp VtkAlgorithmPropertyLineEdit.cpp VtkAlgorithmPropertyVectorEdit.cpp - VtkApplyColorTableFilter.cpp VtkBGImageSource.cpp VtkColorByHeightFilter.cpp VtkColorLookupTable.cpp @@ -31,6 +30,7 @@ SET( SOURCES VtkMeshSource.cpp VtkPolylinesSource.cpp VtkPointsSource.cpp + VtkRaster.cpp VtkSelectionFilter.cpp VtkStationSource.cpp VtkSurfacesSource.cpp @@ -43,6 +43,7 @@ SET( SOURCES VtkVisPipelineView.cpp VtkVisPointSetItem.cpp VtkVisTabWidget.cpp + VtkAlgorithmProperties.cpp ) # Moc headers @@ -64,7 +65,6 @@ SET( MOC_HEADERS # Header files SET( HEADERS - VtkApplyColorTableFilter.h VtkBGImageSource.h VtkColorByHeightFilter.h VtkColorLookupTable.h @@ -87,6 +87,7 @@ SET( HEADERS VtkMeshSource.h VtkPolylinesSource.h VtkPointsSource.h + VtkRaster.h VtkSelectionFilter.h VtkStationSource.h VtkSurfacesSource.h @@ -125,17 +126,18 @@ QT4_WRAP_UI( UI_HEADERS ${UIS} ) QT4_WRAP_CPP( MOC_SOURCES ${MOC_HEADERS} ) INCLUDE_DIRECTORIES( - . - ../VtkAct + ${CMAKE_SOURCE_DIR}/Qt/VtkVis + ${CMAKE_SOURCE_DIR}/Qt/VtkAct ${CMAKE_BINARY_DIR}/Qt/VtkVis - ../../Base - ../../FEM - ../../GEO - ../../MathLib - ../../FileIO - ../../MSH - ../Base - ../DataView + ${CMAKE_SOURCE_DIR}/Base + ${CMAKE_SOURCE_DIR}/FEM + ${CMAKE_SOURCE_DIR}/GEO + ${CMAKE_SOURCE_DIR}/MathLib + ${CMAKE_SOURCE_DIR}/FileIO + ${CMAKE_SOURCE_DIR}/MSH + ${CMAKE_SOURCE_DIR}/Qt/Base + ${CMAKE_SOURCE_DIR}/Qt/DataView + ${CMAKE_BINARY_DIR}/Qt/DataView ) # Create the library @@ -147,13 +149,20 @@ ADD_LIBRARY( VtkVis STATIC ${UIS} ) +IF (libgeotiff_FOUND) + INCLUDE_DIRECTORIES( ${libgeotiff_INCLUDE_DIR} ${libgeotiff_INCLUDE_DIR}/libxtiff ${VTK_DIR}/../Utilities/vtktiff ) + TARGET_LINK_LIBRARIES( VtkVis ${libgeotiff_LIBRARIES} ) +ENDIF () # libgeotiff_FOUND + TARGET_LINK_LIBRARIES( VtkVis ${QT_LIBRARIES} QVTK ) +ADD_DEPENDENCIES(VtkVis QtDataView) + IF(OGS_USE_VRPN) - INCLUDE_DIRECTORIES(../Vrpn) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/Qt/Vrpn) ENDIF() # OGS_USE_VRPN IF (OGS_USE_OPENSG) USE_OPENSG(VtkVis) - INCLUDE_DIRECTORIES( ../OpenSG ) + INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/Qt/OpenSG ) ENDIF (OGS_USE_OPENSG) diff --git a/VtkVis/VisPrefs.ui b/VtkVis/VisPrefs.ui index 10601129dcfbd8dd9eab04d002c6abd576b2ad30..6641f0ffb83a09296e3eba089e147b998a386670 100644 --- a/VtkVis/VisPrefs.ui +++ b/VtkVis/VisPrefs.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>188</width> - <height>296</height> + <height>402</height> </rect> </property> <property name="windowTitle"> @@ -110,6 +110,25 @@ </layout> </widget> </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Rendering</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QCheckBox" name="cullBackfacesCheckBox"> + <property name="toolTip"> + <string>If enabled, all objects (such as triangles, quads) which normals are not pointing towards the view are not rendered.</string> + </property> + <property name="text"> + <string>Cull backfaces</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> <item> <widget class="QPushButton" name="closePushButton"> <property name="text"> diff --git a/VtkVis/VisPrefsDialog.cpp b/VtkVis/VisPrefsDialog.cpp index 3bfcd6210f14a2e7aaf938bb83e140fa687ca036..cc2fb388d06893d4ef39421e9f8cfe19ebf2bb4a 100644 --- a/VtkVis/VisPrefsDialog.cpp +++ b/VtkVis/VisPrefsDialog.cpp @@ -31,6 +31,7 @@ VisPrefsDialog::VisPrefsDialog(VtkVisPipeline* pipeline, superelevationLineEdit->setValidator(validator); QSettings settings("UFZ, OpenGeoSys-5"); superelevationLineEdit->setText(settings.value("globalSuperelevation", 1.0).toString()); + cullBackfacesCheckBox->setCheckState(Qt::CheckState(settings.value("globalCullBackfaces", 0).toInt())); } void VisPrefsDialog::on_bgColorButton_colorPicked( QColor color ) @@ -69,3 +70,12 @@ void VisPrefsDialog::on_loadShowAllCheckBox_stateChanged(int state) _visWidget->setShowAllOnLoad((bool)state); _vtkVisPipeline->resetCameraOnAddOrRemove((bool)state); } + +void VisPrefsDialog::on_cullBackfacesCheckBox_stateChanged(int state) +{ + _vtkVisPipeline->setGlobalBackfaceCulling((bool)state); + + QSettings settings("UFZ, OpenGeoSys-5"); + settings.setValue("globalCullBackfaces", state); +} + diff --git a/VtkVis/VisPrefsDialog.h b/VtkVis/VisPrefsDialog.h index a3b979d0e292875e5afc03c4b333ee8173fcc971..dd9fced3a2dac238211e4673ebda740263e44b15 100644 --- a/VtkVis/VisPrefsDialog.h +++ b/VtkVis/VisPrefsDialog.h @@ -26,21 +26,24 @@ public: QDialog* parent = NULL); protected slots: - /// Sets the background colour. + /// @brief Sets the background colour. void on_bgColorButton_colorPicked(QColor color); - /// Adds a light above the scene. + /// @brief Adds a light above the scene. void on_lightAboveBox_clicked(); - /// Adds a light below the scene. + /// @brief Adds a light below the scene. void on_lightBelowBox_clicked(); - /// Sets the given superelevation on all vis pipeline source objects + /// @brief Sets the given superelevation on all vis pipeline source objects void on_superelevationPushButton_pressed(); - /// + /// @brief void on_loadShowAllCheckBox_stateChanged(int state); + /// @brief Culls backfacing rendering primitives on all actors. + void on_cullBackfacesCheckBox_stateChanged(int state); + private: VtkVisPipeline* _vtkVisPipeline; VisualizationWidget* _visWidget; diff --git a/VtkVis/VisualizationWidget.cpp b/VtkVis/VisualizationWidget.cpp index 39c95d3cac8ac12b224babc19c607c51a40dcddd..7c258222682bbeaa42340abbd2f3302879f04590 100644 --- a/VtkVis/VisualizationWidget.cpp +++ b/VtkVis/VisualizationWidget.cpp @@ -161,6 +161,8 @@ VtkPickCallback* VisualizationWidget::vtkPickCallback() const } void VisualizationWidget::updateView() { + //QDialog box(0, Qt::WindowTitleHint); + //box.show(); vtkWidget->GetRenderWindow()->Render(); } diff --git a/VtkVis/VtkAlgorithmProperties.cpp b/VtkVis/VtkAlgorithmProperties.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7cc79c44e246e07c33777d50feefa4c5365e479e --- /dev/null +++ b/VtkVis/VtkAlgorithmProperties.cpp @@ -0,0 +1,99 @@ +/** + * \file VtkAlgorithmProperties.cpp + * 14/02/2012 LB Initial implementation + * + * Implementation of the VtkAlgorithmProperties class + */ + +// ** INCLUDES ** +#include "VtkAlgorithmProperties.h" + +#include <vtkProperty.h> +#include <vtkTexture.h> + +#include "VtkColorLookupTable.h" +#include "XmlIO/XmlLutReader.h" + +VtkAlgorithmProperties::VtkAlgorithmProperties(QObject* parent /*= NULL*/) + : QObject(parent) +{ + _property = vtkProperty::New(); + _texture = NULL; + _scalarVisibility = true; + _algorithmUserProperties = new QMap<QString, QVariant>; + _algorithmUserVectorProperties = new QMap<QString, QList<QVariant> >; + _activeAttributeName = ""; + _removable = true; +} + +VtkAlgorithmProperties::~VtkAlgorithmProperties() +{ + _property->Delete(); + if (_texture != NULL) _texture->Delete(); + + for (std::map<QString, vtkLookupTable*>::iterator it = _lut.begin(); + it != _lut.end(); ++it) + it->second->Delete(); + delete _algorithmUserProperties; + delete _algorithmUserVectorProperties; +} + +vtkLookupTable* VtkAlgorithmProperties::GetLookupTable(const QString& array_name) +{ + std::map<QString, vtkLookupTable*>::iterator it = _lut.find(array_name); + if (it != _lut.end()) + return it->second; + else + return NULL; +} + +void VtkAlgorithmProperties::SetLookUpTable(const QString &array_name, vtkLookupTable* lut) +{ + lut->Build(); + + if (array_name.length() > 0) + { + std::map<QString, vtkLookupTable*>::iterator it = _lut.find(array_name); + if (it != _lut.end()) + { + it->second->Delete(); + _lut.erase(it); + } + _lut.insert( std::pair<QString, vtkLookupTable*>(array_name, lut) ); + _activeAttributeName = array_name; + } +} + +void VtkAlgorithmProperties::SetLookUpTable(const QString &array_name, const QString &filename) +{ + VtkColorLookupTable* colorLookupTable = XmlLutReader::readFromFile(filename); + SetLookUpTable(array_name, colorLookupTable); +} + +void VtkAlgorithmProperties::SetScalarVisibility(bool on) +{ + _scalarVisibility = on; + emit ScalarVisibilityChanged(on); +} + +QVariant VtkAlgorithmProperties::GetUserProperty(QString name) const +{ + if (this->_algorithmUserProperties->contains(name)) + return this->_algorithmUserProperties->value(name); + else + { + std::cout << "Not a valid property: " << name.toStdString() << std::endl; + return QVariant(); + } +} + +QList<QVariant> VtkAlgorithmProperties::GetUserVectorProperty(QString name) const +{ + if (this->_algorithmUserVectorProperties->contains(name)) + return this->_algorithmUserVectorProperties->value(name); + else + { + std::cout << "Not a valid property: " << name.toStdString() << std::endl; + return QList<QVariant>(); + } +} diff --git a/VtkVis/VtkAlgorithmProperties.h b/VtkVis/VtkAlgorithmProperties.h index 0536f4f6c99c33f10e827b719e89828d54a54642..56e6d3e0c374fdb50dbfb4c1574d2a20ab040fd6 100644 --- a/VtkVis/VtkAlgorithmProperties.h +++ b/VtkVis/VtkAlgorithmProperties.h @@ -13,10 +13,11 @@ #include <QObject> #include <QString> #include <QVariant> -#include <vtkProperty.h> -#include <vtkTexture.h> -#include "VtkColorLookupTable.h" +class vtkProperty; +class vtkTexture; +class vtkLookupTable; + #define ogsUserPropertyMacro(name,type) \ virtual void Set ## name (type _arg) \ @@ -132,131 +133,76 @@ class VtkAlgorithmProperties : public QObject public: /// Constructor (sets default values) - VtkAlgorithmProperties(QObject* parent = NULL) - : QObject(parent) - { - _property = vtkProperty::New(); - _texture = NULL; - _scalarVisibility = true; - _algorithmUserProperties = new QMap<QString, QVariant>; - _algorithmUserVectorProperties = new QMap<QString, QList<QVariant> >; - _activeAttributeName = ""; - } + VtkAlgorithmProperties(QObject* parent = NULL); - virtual ~VtkAlgorithmProperties() - { - _property->Delete(); - if (_texture != NULL) _texture->Delete(); - - for (std::map<QString, vtkLookupTable*>::iterator it = _lut.begin(); it != _lut.end(); - ++it) - it->second->Delete(); - delete _algorithmUserProperties; - delete _algorithmUserVectorProperties; - } + virtual ~VtkAlgorithmProperties(); /// @brief Returns the vtk properties vtkProperty* GetProperties() const { return _property; } /// @brief Returns a texture (if one has been assigned). vtkTexture* GetTexture() { return _texture; } + /// @brief Sets a texture for the VtkVisPipelineItem. void SetTexture(vtkTexture* t) { _texture = t; } /// @brief Returns the colour lookup table (if one has been assigned). - vtkLookupTable* GetLookupTable(const QString& array_name) - { - std::map<QString, vtkLookupTable*>::iterator it = _lut.find(array_name); - if (it != _lut.end()) return it->second; - return NULL; - } + vtkLookupTable* GetLookupTable(const QString& array_name); /// @brief Sets a colour lookup table for the given scalar array of the VtkVisPipelineItem. - void SetLookUpTable(const QString array_name, vtkLookupTable* lut) - { - if (array_name.length() > 0) - { - std::map<QString, vtkLookupTable*>::iterator it = _lut.find(array_name); - if (it != _lut.end()) it->second->Delete(); - _lut.insert( std::pair<QString, vtkLookupTable*>(array_name, lut) ); - } - } + void SetLookUpTable(const QString &array_name, vtkLookupTable* lut); /// Loads a predefined color lookup table from a file for the specified scalar array. - void SetLookUpTable(const QString &array_name, const std::string &filename) - { - VtkColorLookupTable* colorLookupTable = VtkColorLookupTable::New(); - colorLookupTable->readFromFile(filename); - colorLookupTable->setInterpolationType(VtkColorLookupTable::NONE); - colorLookupTable->Build(); - SetLookUpTable(array_name, colorLookupTable); - } + void SetLookUpTable(const QString &array_name, const QString &filename); /// @brief Returns the scalar visibility. bool GetScalarVisibility() const { return _scalarVisibility; } + /// @brief Sets the scalar visibility. - void SetScalarVisibility(bool on) - { - _scalarVisibility = on; - emit ScalarVisibilityChanged(on); - } + void SetScalarVisibility(bool on); /// @brief Returns the name. This is set to the file path if it is a source algorithm. QString GetName() const { return _name; } + /// @brief Sets the name. void SetName(QString name) { _name = name; } + /// @brief Is this algorithm removable from the pipeline (view). + bool IsRemovable() const { return _removable; } + /// @brief Returns a map of user properties. - QMap<QString, QVariant>* GetAlgorithmUserProperties() const - { + QMap<QString, QVariant>* GetAlgorithmUserProperties() const { return _algorithmUserProperties; } /// @brief Returns a map of vector user properties. - QMap<QString, QList<QVariant> >* GetAlgorithmUserVectorProperties() const - { + QMap<QString, QList<QVariant> >* GetAlgorithmUserVectorProperties() const { return _algorithmUserVectorProperties; } /// @brief Sets a user property. This should be implemented by subclasses. - virtual void SetUserProperty(QString name, QVariant value) - { + virtual void SetUserProperty(QString name, QVariant value) { (*_algorithmUserProperties)[name] = value; } /// @brief Returns the value of a user property. - QVariant GetUserProperty(QString name) const - { - if (this->_algorithmUserProperties->contains(name)) - return this->_algorithmUserProperties->value(name); - else - { - std::cout << "Not a valid property: " << name.toStdString() << std::endl; - return QVariant(); - } - } + QVariant GetUserProperty(QString name) const; /// @brief Sets a vector user property. This should be implemented by subclasses. - virtual void SetUserVectorProperty(QString name, QList<QVariant> values) - { + virtual void SetUserVectorProperty(QString name, QList<QVariant> values) { (*_algorithmUserVectorProperties)[name] = values; } /// @brief Returns a list of values of a vector user property. - QList<QVariant> GetUserVectorProperty(QString name) const - { - if (this->_algorithmUserVectorProperties->contains(name)) - return this->_algorithmUserVectorProperties->value(name); - else - { - std::cout << "Not a valid property: " << name.toStdString() << std::endl; - return QList<QVariant>(); - } - } + QList<QVariant> GetUserVectorProperty(QString name) const; + + /// @brief Set the active attribute + void SetActiveAttribute(QString name) { _activeAttributeName = name; } /// @brief Returns the desired active attribute. QString GetActiveAttribute() const { return _activeAttributeName; } + protected: // Properties set on vtkActor @@ -270,6 +216,7 @@ protected: // Properties used in the GUI QString _name; QString _activeAttributeName; + bool _removable; QMap<QString, QVariant>* _algorithmUserProperties; QMap<QString, QList<QVariant> >* _algorithmUserVectorProperties; diff --git a/VtkVis/VtkApplyColorTableFilter.cpp b/VtkVis/VtkApplyColorTableFilter.cpp deleted file mode 100644 index 1f95f30467134a6c2e7b65b5f62e973540c31fee..0000000000000000000000000000000000000000 --- a/VtkVis/VtkApplyColorTableFilter.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/** - * \file VtkApplyColorTableFilter.cpp - * 21/10/2010 KR Initial implementation - * - */ - -// ** VTK INCLUDES ** -#include "vtkObjectFactory.h" -#include <vtkCellData.h> -#include <vtkInformation.h> -#include <vtkInformationVector.h> -#include <vtkLookupTable.h> -#include <vtkPointData.h> -#include <vtkPolyData.h> -#include <vtkSmartPointer.h> -#include <vtkStreamingDemandDrivenPipeline.h> - -#include "VtkApplyColorTableFilter.h" - -vtkStandardNewMacro(VtkApplyColorTableFilter); -vtkCxxSetObjectMacro(VtkApplyColorTableFilter, ColorLookupTable, vtkLookupTable); -vtkCxxRevisionMacro(VtkApplyColorTableFilter, "$Revision: 6575 $"); - -VtkApplyColorTableFilter::VtkApplyColorTableFilter() : ColorLookupTable(NULL) -{ - this->SetColorsOnCells(false); -} - -VtkApplyColorTableFilter::~VtkApplyColorTableFilter() -{ -} - -int VtkApplyColorTableFilter::RequestData( vtkInformation* request, - vtkInformationVector** inputVector, - vtkInformationVector* outputVector ) -{ - if (this->ColorLookupTable == NULL) - return 0; - - (void)request; - - vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); - vtkPolyData* input = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); - - vtkSmartPointer<vtkUnsignedCharArray> colorTable = this->ColorLookupTable->GetTable(); - vtkSmartPointer<vtkUnsignedCharArray> colorArray = - vtkSmartPointer<vtkUnsignedCharArray>::New(); - colorArray->SetNumberOfComponents(4); - colorArray->SetName("Colors"); - vtkSmartPointer<vtkUnsignedCharArray> scalars = - (!ColorsOnCells) ? vtkUnsignedCharArray::SafeDownCast( - input->GetPointData()->GetScalars()) - : vtkUnsignedCharArray::SafeDownCast(input->GetCellData()->GetScalars()); - int limit = (!ColorsOnCells) ? input->GetNumberOfPoints() : input->GetNumberOfCells(); - - for (int i = 0; i < limit; i++) - { - double* value = scalars->GetTuple(i); - unsigned char* rgba = new unsigned char[4]; - colorTable->GetTupleValue(static_cast<int>(value[0]), rgba); - colorArray->InsertNextTupleValue(rgba); - } - - vtkInformation* outInfo = outputVector->GetInformationObject(0); - vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); - output->CopyStructure(input); - output->GetPointData()->PassData(input->GetPointData()); - output->GetCellData()->PassData(input->GetCellData()); - if (!ColorsOnCells) - { - output->GetPointData()->AddArray(colorArray); - output->GetPointData()->SetActiveScalars("Colors"); - } - else - { - output->GetCellData()->AddArray(colorArray); - output->GetCellData()->SetActiveScalars("Colors"); - } - - this->ColorLookupTable->Build(); - - return 1; -} - -unsigned long VtkApplyColorTableFilter::GetMTime() -{ - unsigned long t1, t2; - - t1 = this->Superclass::GetMTime(); - if (this->ColorLookupTable) - { - t2 = this->ColorLookupTable->GetMTime(); - if (t2 > t1) - t1 = t2; - } - return t1; -} - -void VtkApplyColorTableFilter::PrintSelf( ostream& os, vtkIndent indent ) -{ - this->Superclass::PrintSelf(os, indent); - os << indent << "ColorsOnCells: " << this->ColorsOnCells << "\n"; - ColorLookupTable->PrintSelf(os, indent); -} diff --git a/VtkVis/VtkApplyColorTableFilter.h b/VtkVis/VtkApplyColorTableFilter.h deleted file mode 100644 index 0306842daa39faa1b234f49c9c126abfbc9862de..0000000000000000000000000000000000000000 --- a/VtkVis/VtkApplyColorTableFilter.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * \file VtkApplyColorTableFilter.h - * 21/10/2010 KR Initial implementation - * - */ - -#ifndef VTKAPPLYCOLORTABLEFILTER_H -#define VTKAPPLYCOLORTABLEFILTER_H - -// ** INCLUDES ** -#include "VtkAlgorithmProperties.h" -#include <vtkLookupTable.h> -#include <vtkPolyDataAlgorithm.h> - -/** - * \brief Applying a color table to a vtk object. - */ -class VtkApplyColorTableFilter : public vtkPolyDataAlgorithm, public VtkAlgorithmProperties -{ -public: - /// Create new objects with New() because of VTKs object reference counting. - static VtkApplyColorTableFilter* New(); - - vtkTypeRevisionMacro(VtkApplyColorTableFilter, vtkPolyDataAlgorithm); - - /// @brief Prints information about itself. - void PrintSelf(ostream& os, vtkIndent indent); - - /// Returns the underlying colour look up table object. - vtkGetObjectMacro(ColorLookupTable,vtkLookupTable); - - /// Sets the underlying colour look up table object. - virtual void SetColorLookupTable(vtkLookupTable*); - - /// @brief Colors the whole cell instead of interpolating colors between - /// the points in a cell. - ogsUserPropertyMacro(ColorsOnCells,bool); - - //void SetColorsOnPointsOn() { _colorsOnPoints = true; }; - //void SetColorsOnCellsOn() { _colorsOnPoints = false; }; - - virtual unsigned long GetMTime(); - - virtual void SetUserProperty(QString name, QVariant value) - { - if (name.compare("ColorsOnCells") == 0) - SetColorsOnCells(value.toBool()); - } - -protected: - VtkApplyColorTableFilter(); - ~VtkApplyColorTableFilter(); - - /// Computes the unstructured grid data object. - int RequestData(vtkInformation* request, - vtkInformationVector** inputVector, - vtkInformationVector* outputVector); - -private: - vtkLookupTable* ColorLookupTable; - //bool _colorsOnPoints; -}; - -#endif // VTKAPPLYCOLORTABLEFILTER_H diff --git a/VtkVis/VtkBGImageSource.cpp b/VtkVis/VtkBGImageSource.cpp index 4f5cd20bce8e60565179991e673fc09d5e8604a6..4755c9445ca2e28a57129a9c8f4a0344f4c03fb5 100644 --- a/VtkVis/VtkBGImageSource.cpp +++ b/VtkVis/VtkBGImageSource.cpp @@ -8,15 +8,17 @@ #include "VtkBGImageSource.h" #include "VtkVisHelper.h" -#include <QImage> - -#include "vtkObjectFactory.h" +#include <vtkImageAlgorithm.h> +#include <vtkObjectFactory.h> #include <vtkInformation.h> #include <vtkInformationVector.h> #include <vtkPlaneSource.h> #include <vtkSmartPointer.h> #include <vtkStreamingDemandDrivenPipeline.h> #include <vtkTexture.h> +#include <vtkImageData.h> +#include <vtkPointData.h> +#include <vtkImageShiftScale.h> vtkStandardNewMacro(VtkBGImageSource); vtkCxxRevisionMacro(VtkBGImageSource, "$Revision$"); @@ -29,19 +31,36 @@ VtkBGImageSource::~VtkBGImageSource() { } -void VtkBGImageSource::SetImage(vtkTexture* texture) +void VtkBGImageSource::SetRaster(vtkImageAlgorithm *img, double x0, double y0, double scalingFactor) { + double range[2]; + img->Update(); + img->GetOutput()->GetPointData()->GetScalars()->GetRange(range); + vtkSmartPointer<vtkImageShiftScale> scale = vtkSmartPointer<vtkImageShiftScale>::New(); + scale->SetInputConnection(img->GetOutputPort()); + scale->SetShift(-range[0]); + scale->SetScale(255.0/(range[1]-range[0])); + scale->SetOutputScalarTypeToUnsignedChar(); + scale->Update(); + + vtkImageData* imageData = scale->GetOutput(); + int dims[3]; + imageData->GetDimensions(dims); + vtkTexture* texture = vtkTexture::New(); + texture->InterpolateOff(); + texture->RepeatOff(); + // texture->EdgeClampOn(); // does not work + texture->SetInput(imageData); this->SetTexture(texture); -} -void VtkBGImageSource::SetRaster(QImage &img) -{ - vtkTexture* texture = VtkVisHelper::QImageToVtkTexture(img); + _origin = std::pair<float, float>(static_cast<float>(x0), static_cast<float>(y0)); + _cellsize = scalingFactor; + vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New(); plane->SetOrigin( _origin.first, _origin.second, -1 ); - plane->SetPoint1( _origin.first + img.width() * _cellsize, _origin.second, -1 ); - plane->SetPoint2( _origin.first,_origin.second + img.height() * _cellsize, -1 ); + plane->SetPoint1( _origin.first + dims[0] * _cellsize, _origin.second, -1 ); + plane->SetPoint2( _origin.first,_origin.second + dims[1] * _cellsize, -1 ); this->SetInputConnection(0, plane->GetOutputPort(0)); this->SetTexture(texture); diff --git a/VtkVis/VtkBGImageSource.h b/VtkVis/VtkBGImageSource.h index 8767b4260088aba8ddc366d547da2c7442b32bd8..336b55c07cce151d4a92ac11f42f76be0227e396 100644 --- a/VtkVis/VtkBGImageSource.h +++ b/VtkVis/VtkBGImageSource.h @@ -12,7 +12,7 @@ #include "VtkAlgorithmProperties.h" -class QImage; +class vtkImageAlgorithm; /** * \brief Uses an image source to create a plane in the 3D with the given @@ -26,21 +26,8 @@ public: vtkTypeRevisionMacro(VtkBGImageSource, vtkTextureMapToPlane); - /// Sets the surfaces vector - void SetImage(vtkTexture* texture); - - /// Sets the cellsize (i.e. the actual dimension of a pixel) - void SetCellSize(double c) { _cellsize = c; } - /// Sets the raster/image to be used as a texture map - void SetRaster(QImage &img); - - /// Sets the geo-referenced origin of the image (i.e. the lower left corner) - virtual void SetOrigin(double x, double y, double z = 0.0) { _origin.first = x; - _origin.second = y; - (void)z; } - virtual void SetOrigin(double* pos) { _origin.first = pos[0]; - _origin.second = pos[1]; } + void SetRaster(vtkImageAlgorithm *img, double x0, double y0, double scalingFactor); virtual void SetUserProperty(QString name, QVariant value); diff --git a/VtkVis/VtkColorLookupTable.cpp b/VtkVis/VtkColorLookupTable.cpp index 42ff65f70270f3ae4b87fe9ce2a7d7977b8a67ba..6ec612ca6c9dc320e7a0b62a063556d8ab504330 100644 --- a/VtkVis/VtkColorLookupTable.cpp +++ b/VtkVis/VtkColorLookupTable.cpp @@ -16,7 +16,6 @@ vtkCxxRevisionMacro(VtkColorLookupTable, "$Revision$"); VtkColorLookupTable::VtkColorLookupTable() : _type(VtkColorLookupTable::LINEAR) { - this->SetNumberOfTableValues(256); } VtkColorLookupTable::~VtkColorLookupTable() @@ -43,67 +42,38 @@ unsigned char VtkColorLookupTable::expInterpolation(unsigned char a, void VtkColorLookupTable::Build() { + double range[2]; + this->GetTableRange(range); + const double interval = range[1]-range[0]; + this->SetNumberOfTableValues(ceil(interval)+1); +// const vtkIdType nColours = this->GetNumberOfTableValues(); if (!_dict.empty()) { // make sure that color map starts with the first color in the dictionary - unsigned char* startcolor = new unsigned char[4]; - startcolor[0] = _dict.begin()->second[0]; - startcolor[1] = _dict.begin()->second[1]; - startcolor[2] = _dict.begin()->second[2]; - startcolor[3] = _dict.begin()->second[3]; + unsigned char startcolor[4] = { 0, 0 , 0 , 0 }; std::pair<size_t, unsigned char*> lastValue(0, startcolor); size_t nextIndex(0); - // make sure that color map ends with the last color in the dictionary - std::map<double, unsigned char*>::iterator lastitr = _dict.end(); - --lastitr; - if (lastitr->first != 1) + for (std::map<double, unsigned char*>::const_iterator it = _dict.begin(); it != _dict.end(); ++it) { - unsigned char* lastcolor = new unsigned char[4]; - for (size_t i = 0; i < 4; i++) - lastcolor[i] = lastitr->second[i]; - _dict.insert( std::pair<double, unsigned char*>(1.0, lastcolor) ); - } - - for (std::map<double, unsigned char*>::const_iterator it = _dict.begin(); - it != _dict.end(); ++it) - { - //unsigned char rgba[4]; - //rgba[0] = (*it->second)[0]; rgba[1] = (*it->second)[1]; rgba[2] = (*it->second)[2]; rgba[3] = 255; + double val = (it->first < range[0]) ? range[0] : ((it->first > range[1]) ? range[1] : it->first); + nextIndex = static_cast<size_t>( floor(val-range[0]) ); - nextIndex = - static_cast<size_t>( floor(it->first * this->GetNumberOfTableValues()) ); - if (nextIndex >= static_cast<size_t>(this->GetNumberOfTableValues())) - nextIndex--; // this happens for the very last colour this->SetTableValue(nextIndex, it->second); - if ( nextIndex - lastValue.first > 1 ) + if ( nextIndex - lastValue.first > 0 ) for (size_t i = lastValue.first + 1; i < nextIndex; i++) { unsigned char int_rgba[4]; - int_rgba[3] = 255; - double pos = - (i - - lastValue.first) / - (static_cast<double>(nextIndex - lastValue.first)); + double pos = (i - lastValue.first) / (static_cast<double>(nextIndex - lastValue.first)); if (_type == VtkColorLookupTable::LINEAR) for (size_t j = 0; j < 3; j++) - int_rgba[j] = - linInterpolation( - (lastValue.second)[j], - (it->second)[j], - pos); + int_rgba[j] = linInterpolation( (lastValue.second)[j], (it->second)[j], pos); else if (_type == VtkColorLookupTable::EXPONENTIAL) for (size_t j = 0; j < 3; j++) - int_rgba[j] = - expInterpolation( - (lastValue.second)[j], - (it->second)[j], - 0.2, - pos); + int_rgba[j] = expInterpolation((lastValue.second)[j], (it->second)[j], 0.2, pos); else // no interpolation - for (size_t j = 0; j < 3; j++) int_rgba[j] = (lastValue.second)[j]; @@ -118,19 +88,6 @@ void VtkColorLookupTable::Build() vtkLookupTable::Build(); } -void VtkColorLookupTable::readFromFile(const std::string &filename) -{ - std::map<std::string, GEOLIB::Color*> colors; - GEOLIB::readColorLookupTable(colors, filename); - this->SetNumberOfTableValues(colors.size()); - - for (std::map<std::string, GEOLIB::Color*>::iterator it = colors.begin(); it != colors.end(); - ++it) - this->SetTableValue( static_cast<vtkIdType>(strtod( it->first.c_str(), - 0 )), (*(it->second))[0], - (*(it->second))[1], (*(it->second))[2], 255 ); -} - void VtkColorLookupTable::writeToFile(const std::string &filename) { std::cout << "Writing color table to " << filename << "...."; @@ -196,31 +153,21 @@ void VtkColorLookupTable::GetTableValue(vtkIdType indx, unsigned char rgba[4]) void VtkColorLookupTable::setColor(double pos, unsigned char rgba[4]) { - if (pos >= 0 && pos <= 1) - { - unsigned char* dict_rgba = new unsigned char[4]; - for (size_t i = 0; i < 4; i++) - dict_rgba[i] = rgba[i]; - _dict.insert( std::pair<double, unsigned char*>(pos, dict_rgba) ); - } - else - std::cout << "ColorLookupTable::setValue() - Error: pos should be in [0,1]" << - std::endl; + unsigned char* dict_rgba = new unsigned char[4]; + for (size_t i = 0; i < 4; i++) + dict_rgba[i] = rgba[i]; + _dict.insert( std::pair<double, unsigned char*>(pos, dict_rgba) ); } void VtkColorLookupTable::getColor(vtkIdType indx, unsigned char rgba[4]) const { indx = - ((indx < - this->TableRange[0]) ? static_cast<vtkIdType>(this->TableRange[0]) : (indx >= - this - -> - TableRange[1] ? static_cast<vtkIdType>(this->TableRange[1]) - 1 : indx)); + ((indx < this->TableRange[0]) + ? static_cast<vtkIdType>(this->TableRange[0]) + : (indx >=this->TableRange[1] ? static_cast<vtkIdType>(this->TableRange[1]) - 1 : indx)); indx = - static_cast<size_t>( floor( (indx - - this->TableRange[0]) * - (this->NumberOfColors / - (this->TableRange[1] - this->TableRange[0])) ) ); + static_cast<size_t>( floor( (indx - this->TableRange[0]) * + (this->NumberOfColors / (this->TableRange[1] - this->TableRange[0])) ) ); unsigned char* _rgba; _rgba = this->Table->GetPointer(indx * 4); diff --git a/VtkVis/VtkColorLookupTable.h b/VtkVis/VtkColorLookupTable.h index 15b66d3b11d4b327ab8be209bd7da11ab1450505..fd0d35c00a0c2365134604250f4af355f11b528d 100644 --- a/VtkVis/VtkColorLookupTable.h +++ b/VtkVis/VtkColorLookupTable.h @@ -65,7 +65,7 @@ public: void setInterpolationType(VtkColorLookupTable::LUTType type) { _type = type; } /// Imports a color table from a file. - void readFromFile(const std::string &filename); + //void readFromFile(const std::string &filename); /// Exports a color table to a file. void writeToFile(const std::string &filename); diff --git a/VtkVis/VtkCompositeColorByHeightFilter.cpp b/VtkVis/VtkCompositeColorByHeightFilter.cpp index a4e0457f2a60bf049a3c0fdde1180f9dd3bc2e7a..bde566997cc4bc30d9fb20287cce79c60cb3d903 100644 --- a/VtkVis/VtkCompositeColorByHeightFilter.cpp +++ b/VtkVis/VtkCompositeColorByHeightFilter.cpp @@ -44,10 +44,10 @@ void VtkCompositeColorByHeightFilter::init() unsigned char c[4] = { 255, 255, 0, 255 }; // yellow unsigned char d[4] = { 255, 0, 0, 255 }; // red //unsigned char e[4] = { 255, 255, 255, 255 }; // white - heightFilter->GetColorLookupTable()->setColor(0.0, a); - heightFilter->GetColorLookupTable()->setColor(0.2, b); // green at about 150m - heightFilter->GetColorLookupTable()->setColor(0.6, c); // yellow at about 450m and changing to red from then on - heightFilter->GetColorLookupTable()->setColor(1.0, d); + heightFilter->GetColorLookupTable()->setColor(-35, a); + heightFilter->GetColorLookupTable()->setColor(150, b); // green at about 150m + heightFilter->GetColorLookupTable()->setColor(450, c); // yellow at about 450m and changing to red from then on + heightFilter->GetColorLookupTable()->setColor(800, d); //heightFilter->GetColorLookupTable()->setColor(1.0, e); heightFilter->Update(); diff --git a/VtkVis/VtkCompositeColormapToImageFilter.cpp b/VtkVis/VtkCompositeColormapToImageFilter.cpp index 72a3c55bef7e6656ac4b05e2dbae274253f7afe9..6eace8d14c2755a314fd497867ead1ad3c0be4c9 100644 --- a/VtkVis/VtkCompositeColormapToImageFilter.cpp +++ b/VtkVis/VtkCompositeColormapToImageFilter.cpp @@ -9,9 +9,17 @@ #include "VtkCompositeColormapToImageFilter.h" #include <vtkImageMapToColors.h> +#include <vtkImageData.h> #include <vtkLookupTable.h> +#include <vtkPointData.h> #include <vtkSmartPointer.h> +#include <QSettings> +#include <QFileDialog> + +#include "VtkColorLookupTable.h" +#include "XmlIO/XmlLutReader.h" + VtkCompositeColormapToImageFilter::VtkCompositeColormapToImageFilter( vtkAlgorithm* inputAlgorithm ) : VtkCompositeFilter(inputAlgorithm) { @@ -27,13 +35,36 @@ void VtkCompositeColormapToImageFilter::init() this->_inputDataObjectType = VTK_IMAGE_DATA; this->_outputDataObjectType = VTK_IMAGE_DATA; - vtkSmartPointer<vtkLookupTable> colormap = vtkSmartPointer<vtkLookupTable>::New(); - colormap->SetTableRange(0, 100); - colormap->SetHueRange(0.0, 0.666); + vtkSmartPointer<VtkColorLookupTable> colormap; + + QWidget* parent = 0; + QSettings settings("UFZ", "OpenGeoSys-5"); + QString fileName = QFileDialog::getOpenFileName(parent, + "Select color lookup table", + settings.value("lastOpenedLookupTableFileDirectory"). + toString(), + "Lookup table XML files (*.xml);;"); + double range[2]; + dynamic_cast<vtkImageAlgorithm*>(_inputAlgorithm)->GetOutput()->GetPointData()->GetScalars()->GetRange(range); + + if (!fileName.length()==0) + { + colormap = XmlLutReader::readFromFile(fileName); + settings.setValue("lastOpenedLookupTableFileDirectory", fileName); + } + else + { + colormap = vtkSmartPointer<VtkColorLookupTable>::New(); + colormap->SetTableRange(range[0], range[1]); + colormap->SetHueRange(0.0, 0.666); + } colormap->SetNumberOfTableValues(256); + colormap->Build(); + + colormap->GetTableRange(range); QList<QVariant> tableRangeList; - tableRangeList.push_back(0); - tableRangeList.push_back(100); + tableRangeList.push_back(range[0]); + tableRangeList.push_back(range[1]); QList<QVariant> hueRangeList; hueRangeList.push_back(0.0); hueRangeList.push_back(0.666); @@ -58,8 +89,7 @@ void VtkCompositeColormapToImageFilter::SetUserProperty( QString name, QVariant if (name.compare("PassAlphaToOutput") == 0) map->SetPassAlphaToOutput(value.toBool()); else if (name.compare("NumberOfColors") == 0) - static_cast<vtkLookupTable*>(map->GetLookupTable())->SetNumberOfTableValues( - value.toInt()); + static_cast<vtkLookupTable*>(map->GetLookupTable())->SetNumberOfTableValues(value.toInt()); } void VtkCompositeColormapToImageFilter::SetUserVectorProperty( QString name, QList<QVariant> values ) @@ -71,7 +101,6 @@ void VtkCompositeColormapToImageFilter::SetUserVectorProperty( QString name, QLi static_cast<vtkLookupTable*>(map->GetLookupTable())->SetTableRange( values[0].toInt(), values[1].toInt()); else if (name.compare("HueRange") == 0) - static_cast<vtkLookupTable*>(map->GetLookupTable())->SetHueRange(values[0].toDouble( - ), - values[1].toDouble()); + static_cast<vtkLookupTable*>(map->GetLookupTable())->SetHueRange(values[0].toDouble(), + values[1].toDouble()); } diff --git a/VtkVis/VtkCompositeContourFilter.cpp b/VtkVis/VtkCompositeContourFilter.cpp index 2aeba6dbc7bc19bd464ec1b44fc0484b9bde4843..399a227dea4cda46154338e5cfc670e9775533a8 100644 --- a/VtkVis/VtkCompositeContourFilter.cpp +++ b/VtkVis/VtkCompositeContourFilter.cpp @@ -11,6 +11,8 @@ #include <vtkSmartPointer.h> #include <vtkUnstructuredGrid.h> +#include <limits> + VtkCompositeContourFilter::VtkCompositeContourFilter( vtkAlgorithm* inputAlgorithm ) : VtkCompositeFilter(inputAlgorithm) { @@ -31,14 +33,19 @@ void VtkCompositeContourFilter::init() vtkContourFilter* contour = vtkContourFilter::New(); contour->SetInputConnection(_inputAlgorithm->GetOutputPort()); + // Setting the threshold to min / max values to ensure that the whole data + // is first processed. This is needed for correct lookup table generation. + const double dMin = std::numeric_limits<double>::min(); + const double dMax = std::numeric_limits<double>::max(); + // Sets a filter vector property which will be user editable - contour->GenerateValues(10, 0, 100); + contour->GenerateValues(10, dMin, dMax); // Create a list for the ThresholdBetween (vector) property. QList<QVariant> contourRangeList; // Insert the values (same values as above) - contourRangeList.push_back(0); - contourRangeList.push_back(100); + contourRangeList.push_back(dMin); + contourRangeList.push_back(dMax); // Put that list in the property map (*_algorithmUserVectorProperties)["Range"] = contourRangeList; diff --git a/VtkVis/VtkCompositeContourFilter.h b/VtkVis/VtkCompositeContourFilter.h index e3810de045b92a35830e2a0bf07e0a78db34824f..9ec22dacaaf28176ec7712560f1e97b409233eb6 100644 --- a/VtkVis/VtkCompositeContourFilter.h +++ b/VtkVis/VtkCompositeContourFilter.h @@ -9,6 +9,8 @@ #include "VtkCompositeFilter.h" /// @brief Visualisation of contour-lines/-planes within dense scalar fields. +/// In init() the threshold is first set to double min / max values. Set the +/// threshold later on via SetUserVectorProperty() to the actual data range. class VtkCompositeContourFilter : public VtkCompositeFilter { public: diff --git a/VtkVis/VtkCompositeFilter.cpp b/VtkVis/VtkCompositeFilter.cpp index 22cdf0ef9c4af7b080ef21cca6e25d1ebbd787ca..b650f8eede0fd2af6ef759d08cbc5fd6a8ecdf16 100644 --- a/VtkVis/VtkCompositeFilter.cpp +++ b/VtkVis/VtkCompositeFilter.cpp @@ -8,7 +8,7 @@ // ** INCLUDES ** #include "VtkCompositeFilter.h" -#include "VtkCompositeImageToCylindersFilter.h" +#include <vtkAlgorithm.h> #include <QMapIterator> #include <QString> diff --git a/VtkVis/VtkCompositeFilter.h b/VtkVis/VtkCompositeFilter.h index 460b81e80defcfd5ed43003edf979f8be744f924..a83e098b16757f8e4a6b39ac3187646defb48a82 100644 --- a/VtkVis/VtkCompositeFilter.h +++ b/VtkVis/VtkCompositeFilter.h @@ -8,6 +8,8 @@ #include "VtkAlgorithmProperties.h" +class vtkAlgorithm; + /// @brief Is used to combine several filter in one VtkVisPipelineItem. You can /// use vtk filter and custom filter. To subclass this you have to implement the /// init() function. There you combine the filters. Make sure to set the members diff --git a/VtkVis/VtkCompositeImageToCylindersFilter.cpp b/VtkVis/VtkCompositeImageToCylindersFilter.cpp index 5cd54c57ff238bfcea687470034d93a4536a499e..f482ffbe622f3551a118751253cbdd5995c9a314 100644 --- a/VtkVis/VtkCompositeImageToCylindersFilter.cpp +++ b/VtkVis/VtkCompositeImageToCylindersFilter.cpp @@ -8,7 +8,6 @@ // ** INCLUDES ** #include "VtkCompositeImageToCylindersFilter.h" -#include "VtkApplyColorTableFilter.h" #include "VtkImageDataToLinePolyDataFilter.h" #include <vtkLookupTable.h> @@ -35,37 +34,33 @@ void VtkCompositeImageToCylindersFilter::init() this->_outputDataObjectType = VTK_POLY_DATA; _lineFilter = VtkImageDataToLinePolyDataFilter::New(); - //lineFilter = VtkImageDataToLinePolyDataFilter::New(); _lineFilter->SetInputConnection(_inputAlgorithm->GetOutputPort()); _lineFilter->SetLengthScaleFactor(1); (*_algorithmUserProperties)["LengthScaleFactor"] = 1.0; _lineFilter->Update(); - //vtkPointData* pointData = _lineFilter->GetOutput()->GetPointData(); - //pointData->GetArray(0)->SetName("Colors"); + double range[2]; + // The data is always on points + vtkDataSet::SafeDownCast(_lineFilter->GetOutputDataObject(0))->GetPointData()->GetScalars()->GetRange(range); - vtkSmartPointer<vtkLookupTable> colormap = vtkSmartPointer<vtkLookupTable>::New(); - colormap->SetTableRange(0, 100); + vtkLookupTable* colormap = vtkLookupTable::New(); + colormap->SetTableRange(range[0], range[1]); colormap->SetHueRange(0.0, 0.666); colormap->SetNumberOfTableValues(256); colormap->ForceBuild(); QList<QVariant> tableRangeList; - tableRangeList.push_back(0); - tableRangeList.push_back(100); + tableRangeList.push_back(range[0]); + tableRangeList.push_back(range[1]); QList<QVariant> hueRangeList; hueRangeList.push_back(0.0); hueRangeList.push_back(0.666); (*_algorithmUserVectorProperties)["TableRange"] = tableRangeList; (*_algorithmUserVectorProperties)["HueRange"] = hueRangeList; - this->SetLookUpTable("Colours", colormap); - - _ctf = VtkApplyColorTableFilter::New(); - _ctf->SetInputConnection(_lineFilter->GetOutputPort()); - _ctf->SetColorLookupTable(colormap); + this->SetLookUpTable("P-Colors", colormap); vtkTubeFilter* tubeFilter = vtkTubeFilter::New(); - tubeFilter->SetInputConnection(_ctf->GetOutputPort()); + tubeFilter->SetInputConnection(_lineFilter->GetOutputPort()); tubeFilter->CappingOn(); tubeFilter->SetNumberOfSides(6); tubeFilter->SetRadius(_lineFilter->GetImageSpacing() * 0.25); @@ -86,8 +81,11 @@ void VtkCompositeImageToCylindersFilter::SetUserProperty( QString name, QVariant // VtkImageDataToLinePolyDataFilter is equal to _firstAlgorithm // vtkTubeFilter is equal _outputAlgorithm if (name.compare("NumberOfColors") == 0) - static_cast<vtkLookupTable*>(_ctf->GetColorLookupTable())->SetNumberOfTableValues( - value.toInt()); + { + vtkLookupTable* lut = this->GetLookupTable("P-Colors"); + if(lut) + lut->SetNumberOfTableValues(value.toInt()); + } else if (name.compare("NumberOfSides") == 0) static_cast<vtkTubeFilter*>(_outputAlgorithm)->SetNumberOfSides(value.toInt()); else if (name.compare("Capping") == 0) @@ -105,17 +103,20 @@ void VtkCompositeImageToCylindersFilter::SetUserVectorProperty( QString name, _lineFilter->SetUserVectorProperty(name, values); if (name.compare("TableRange") == 0) - static_cast<vtkLookupTable*>(_ctf->GetColorLookupTable())->SetTableRange( - values[0].toInt(), - values[1].toInt()); + { + vtkLookupTable* lut = this->GetLookupTable("P-Colors"); + if(lut) + lut->SetTableRange(values[0].toDouble(), values[1].toDouble()); + } else if (name.compare("HueRange") == 0) - static_cast<vtkLookupTable*>(_ctf->GetColorLookupTable())->SetHueRange( - values[0].toDouble(), - values[1].toDouble()); + { + vtkLookupTable* lut = this->GetLookupTable("P-Colors"); + if(lut) + lut->SetHueRange(values[0].toDouble(), values[1].toDouble()); + } } VtkCompositeImageToCylindersFilter::~VtkCompositeImageToCylindersFilter() { _lineFilter->Delete(); - _ctf->Delete(); } diff --git a/VtkVis/VtkCompositeImageToCylindersFilter.h b/VtkVis/VtkCompositeImageToCylindersFilter.h index 0bb4e65b50afeb035fddd464047473ed107af32b..b696fee158dc22466f7c298334d86e5fde262ca5 100644 --- a/VtkVis/VtkCompositeImageToCylindersFilter.h +++ b/VtkVis/VtkCompositeImageToCylindersFilter.h @@ -9,7 +9,6 @@ #include "VtkCompositeFilter.h" class VtkImageDataToLinePolyDataFilter; -class VtkApplyColorTableFilter; /// @brief Creates cylinders that stand on top of the image with the length /// of the corresponding first sub-pixel value (the red value). Useful to @@ -28,7 +27,6 @@ public: private: VtkImageDataToLinePolyDataFilter* _lineFilter; - VtkApplyColorTableFilter* _ctf; }; #endif // VTKCOMPOSITEIMAGETOCYLINDERSFILTER_H diff --git a/VtkVis/VtkCompositeLineToTubeFilter.cpp b/VtkVis/VtkCompositeLineToTubeFilter.cpp index 971d4ab38b1d50e68aee50ed102c1b81fc9cc749..8eb9efa1d985f3257aeb2c0d47c1a75e27b5c0b0 100644 --- a/VtkVis/VtkCompositeLineToTubeFilter.cpp +++ b/VtkVis/VtkCompositeLineToTubeFilter.cpp @@ -37,11 +37,14 @@ void VtkCompositeLineToTubeFilter::init() int default_number_of_sides(8); vtkTubeFilter* tubes = vtkTubeFilter::New(); tubes->SetInputConnection(0, mergePoints->GetOutputPort(0)); + + //tubes->SetInputArrayToProcess(1,0,0,vtkDataObject::FIELD_ASSOCIATION_CELLS,"StationValue"); + //tubes->SetVaryRadiusToVaryRadiusByScalar(); // KR radius changes with scalar + tubes->SetInputArrayToProcess(1,0,0,vtkDataObject::FIELD_ASSOCIATION_CELLS,"Stratigraphies"); tubes->SetRadius(default_radius); tubes->SetNumberOfSides(default_number_of_sides); tubes->SetCapping(1); - //tubes->SetVaryRadiusToVaryRadiusByScalar(); // KR radius changes with scalar (*_algorithmUserProperties)["Radius"] = default_radius; (*_algorithmUserProperties)["NumberOfSides"] = default_number_of_sides; diff --git a/VtkVis/VtkCompositePointToGlyphFilter.cpp b/VtkVis/VtkCompositePointToGlyphFilter.cpp index 10f9e3bf83e4262049dbadefbeae988299c905a1..7a520ab5177fbb778870b6ca344cc570cf6a6aa8 100644 --- a/VtkVis/VtkCompositePointToGlyphFilter.cpp +++ b/VtkVis/VtkCompositePointToGlyphFilter.cpp @@ -57,7 +57,7 @@ void VtkCompositePointToGlyphFilter::init() glyphFilter->SetSource(_glyphSource->GetOutput()); glyphFilter->SetInputConnection(_inputAlgorithm->GetOutputPort()); //(*_algorithmUserProperties)["ScaleMode"] = 0; - (*_algorithmUserProperties)["ScaleFactor"] = 1.0; + //(*_algorithmUserProperties)["ScaleFactor"] = 1.0; //(*_algorithmUserProperties)["ColorMode"] = glyphFilter->GetColorMode(); //(*_algorithmUserProperties)["VectorMode"] = glyphFilter->GetVectorMode(); //(*_algorithmUserProperties)["Orient"] = glyphFilter->GetOrient(); diff --git a/VtkVis/VtkCompositeSelectionFilter.cpp b/VtkVis/VtkCompositeSelectionFilter.cpp index 21d20f3e6b604ff9dba7c8427a3dfb671b774633..9d902bc82628700f00f116a53b0d3ceb7fa7ebfd 100644 --- a/VtkVis/VtkCompositeSelectionFilter.cpp +++ b/VtkVis/VtkCompositeSelectionFilter.cpp @@ -8,6 +8,7 @@ // ** INCLUDES ** #include "VtkCompositeSelectionFilter.h" #include "VtkSelectionFilter.h" +#include "VtkColorLookupTable.h" #include <vtkDataSetSurfaceFilter.h> #include <vtkSmartPointer.h> diff --git a/VtkVis/VtkCompositeSelectionFilter.h b/VtkVis/VtkCompositeSelectionFilter.h index 45a33409e4381c3ae923daf75d2396ec85be89d0..ff76d6df863e0aa3f6ca29050766279f2e6c91f8 100644 --- a/VtkVis/VtkCompositeSelectionFilter.h +++ b/VtkVis/VtkCompositeSelectionFilter.h @@ -8,6 +8,10 @@ #include "VtkCompositeFilter.h" +#include <vector> + +class VtkColorLookupTable; + /// @brief This filter colors the input by the points z-value. class VtkCompositeSelectionFilter : public VtkCompositeFilter { diff --git a/VtkVis/VtkCompositeTextureOnSurfaceFilter.cpp b/VtkVis/VtkCompositeTextureOnSurfaceFilter.cpp index 44d27b7537dafe0ec3e28563e76d6eb891d0dc03..30b79d59b9484aef582e55f93d8f0d455a78923d 100644 --- a/VtkVis/VtkCompositeTextureOnSurfaceFilter.cpp +++ b/VtkVis/VtkCompositeTextureOnSurfaceFilter.cpp @@ -11,13 +11,17 @@ #include <vtkDataSetSurfaceFilter.h> #include <vtkSmartPointer.h> #include <vtkUnstructuredGrid.h> - -#include "OGSRaster.h" +#include "VtkGeoImageSource.h" +#include "VtkRaster.h" +#include "NetCdfConfigureDialog.h" #include <QFileDialog> #include <QFileInfo> #include <QSettings> +//#include "VtkCompositeColormapToImageFilter.h" + + VtkCompositeTextureOnSurfaceFilter::VtkCompositeTextureOnSurfaceFilter( vtkAlgorithm* inputAlgorithm ) : VtkCompositeFilter(inputAlgorithm) @@ -52,25 +56,41 @@ void VtkCompositeTextureOnSurfaceFilter::init() "Select raster file to apply as texture", settings.value("lastOpenedTextureFileDirectory"). toString(), - "Raster files (*.asc *.bmp *.jpg *.png *.tif);;"); + "Raster files (*.asc *.grd *.bmp *.jpg *.png *.tif);;NetCDF files (*.nc);;"); QFileInfo fi(fileName); if ((fi.suffix().toLower() == "asc") || (fi.suffix().toLower() == "tif") || - (fi.suffix().toLower() == "png") || + (fi.suffix().toLower() == "png") || (fi.suffix().toLower() == "grd") || (fi.suffix().toLower() == "jpg") || (fi.suffix().toLower() == "bmp")) { - QImage img; - QPointF origin; - double scalingFactor = 0; - - OGSRaster::loadImage(fileName, img, origin, scalingFactor); - std::pair<float, float> org(origin.x(), origin.y()); - surface->SetRaster(img, org, scalingFactor); + double x0(0), y0(0), scalingFactor(1); + std::string name = fileName.toStdString(); + vtkImageAlgorithm* image = VtkRaster::loadImage(name, x0, y0, scalingFactor); + surface->SetRaster(image, x0, y0, scalingFactor); surface->Update(); QDir dir = QDir(fileName); settings.setValue("lastOpenedTextureFileDirectory", dir.absolutePath()); } + else if (fi.suffix().toLower() == "nc") + { + NetCdfConfigureDialog dlg(fileName.toStdString().c_str()); + dlg.exec(); + if (dlg.getRaster() != NULL) + { + VtkGeoImageSource* image = dlg.getRaster(); + double origin[3]; + image->GetOutput()->GetOrigin(origin); + double spacing[3]; + image->GetOutput()->GetSpacing(spacing); +/* + VtkCompositeColormapToImageFilter* cm = new VtkCompositeColormapToImageFilter(image); + vtkImageAlgorithm* img = dynamic_cast<vtkImageAlgorithm*>(cm->GetOutputAlgorithm()); +*/ + surface->SetRaster(image, origin[0], origin[1], spacing[0]); + surface->Update(); + } + } else std::cout << "VtkCompositeTextureOnSurfaceFilter.init() - Error reading texture file..." << diff --git a/VtkVis/VtkCompositeThresholdFilter.cpp b/VtkVis/VtkCompositeThresholdFilter.cpp index ebe174ac33d593696f8b109b0f21c03a88fc4d1a..d3448d6dfc62d532af16d605c1dbd3817df20220 100644 --- a/VtkVis/VtkCompositeThresholdFilter.cpp +++ b/VtkVis/VtkCompositeThresholdFilter.cpp @@ -11,10 +11,11 @@ #include <vtkCellData.h> #include <vtkThreshold.h> #include <vtkUnstructuredGrid.h> - #include <vtkIntArray.h> #include <vtkSmartPointer.h> +#include <limits> + VtkCompositeThresholdFilter::VtkCompositeThresholdFilter( vtkAlgorithm* inputAlgorithm ) : VtkCompositeFilter(inputAlgorithm) { @@ -35,25 +36,23 @@ void VtkCompositeThresholdFilter::init() vtkThreshold* threshold = vtkThreshold::New(); threshold->SetInputConnection(_inputAlgorithm->GetOutputPort()); - // TODO: Initalisation - //vtkDataArray* activeScalar = vtkDataSet::SafeDownCast(threshold->GetInput())->GetCellData()->GetArray(0); - //threshold->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_CELLS, activeScalar->GetName()); - //threshold->SetComponentModeToUseSelected(); - -//double* range = threshold->GetOutput()->GetScalarRange(); -//std::cout << range[0] << ", " << range[1] << std::endl; + // Note: There is no need to select the input array because it is + // automatically selected. // Sets a filter property which will be user editable threshold->SetSelectedComponent(0); - // Sets a filter vector property which will be user editable - threshold->ThresholdBetween(0, 100); + // Setting the threshold to min / max values to ensure that the whole data + // is first processed. This is needed for correct lookup table generation. + const double dMin = std::numeric_limits<double>::min(); + const double dMax = std::numeric_limits<double>::max(); + threshold->ThresholdBetween(dMin, dMax); // Create a list for the ThresholdBetween (vector) property. QList<QVariant> thresholdRangeList; // Insert the values (same values as above) - thresholdRangeList.push_back(0); - thresholdRangeList.push_back(100); + thresholdRangeList.push_back(dMin); + thresholdRangeList.push_back(dMax); // Put that list in the property map (*_algorithmUserVectorProperties)["Threshold Between"] = thresholdRangeList; @@ -80,17 +79,7 @@ void VtkCompositeThresholdFilter::SetUserVectorProperty( QString name, QList<QVa // Use the same name as in init() if (name.compare("Threshold Between") == 0) - //double* range = dynamic_cast<vtkUnstructuredGridAlgorithm*>(_outputAlgorithm)->GetOutput()->GetScalarRange(); - //std::cout << range[0] << ", " << range[1] << std::endl; // Set the vector property on the algorithm static_cast<vtkThreshold*>(_outputAlgorithm)->ThresholdBetween( - values[0].toInt(), values[1].toInt()); + values[0].toDouble(), values[1].toDouble()); } -/* - void VtkCompositeThresholdFilter::SetScalarRangeOnItem( double min, double max ) - { - _item->SetScalarRange(min, max); - emit requestViewUpdate(); - } - - */ diff --git a/VtkVis/VtkCompositeThresholdFilter.h b/VtkVis/VtkCompositeThresholdFilter.h index 54bbc963a1f44be93376096c91d51ccc53dfb48d..acdfe7c460c45d26013bd0a378f1f6fee0bd832b 100644 --- a/VtkVis/VtkCompositeThresholdFilter.h +++ b/VtkVis/VtkCompositeThresholdFilter.h @@ -9,6 +9,8 @@ #include "VtkCompositeFilter.h" /// @brief Visualises only parts of meshes that are above/below/within given thresholds. +/// In init() the threshold is first set to double min / max values. Set the +/// threshold later on via SetUserVectorProperty() to the actual data range. class VtkCompositeThresholdFilter : public VtkCompositeFilter { public: diff --git a/VtkVis/VtkConditionSource.cpp b/VtkVis/VtkConditionSource.cpp index ed36f7df52ca2b01c91f991d30286d2174404a8b..1d26f5f595d410cd0f5536f14401cc8f07c5ddc5 100644 --- a/VtkVis/VtkConditionSource.cpp +++ b/VtkVis/VtkConditionSource.cpp @@ -19,6 +19,7 @@ #include <vtkPolygon.h> #include <vtkSmartPointer.h> #include <vtkStreamingDemandDrivenPipeline.h> +#include <vtkProperty.h> #include <vtkLookupTable.h> @@ -41,6 +42,7 @@ VtkConditionSource::~VtkConditionSource() void VtkConditionSource::setData(const std::vector<GEOLIB::Point*>* points, const std::vector<FEMCondition*>* conds) { + _removable = false; // From VtkAlgorithmProperties _points = points; _cond_vec = conds; } @@ -62,17 +64,7 @@ int VtkConditionSource::RequestData( vtkInformation* request, (void)request; (void)inputVector; - if ( _points ) - { - if (_points->empty()) - { - std::cout << - "ERROR in VtkConditionSource::RequestData : Size of point vector is 0" << - std::endl; - return 0; - } - } - else + if (this->_points->empty() || this->_cond_vec->empty()) return 0; vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New(); @@ -95,7 +87,7 @@ int VtkConditionSource::RequestData( vtkInformation* request, if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0) return 1; - + /* size_t n_pnts = _points->size(); double value(-9999); if (!_cond_vec->empty()) @@ -111,12 +103,14 @@ int VtkConditionSource::RequestData( vtkInformation* request, distypes->InsertNextValue(0); scalars->InsertNextValue(value); } - + */ + vtkIdType pnt_id = 0; size_t nCond = _cond_vec->size(); for (size_t n = 0; n < nCond; n++) { FiniteElement::DistributionType type = (*_cond_vec)[n]->getProcessDistributionType(); - const std::vector<double> dis_values = (*_cond_vec)[n]->getDisValue(); + const std::vector<size_t> dis_nodes = (*_cond_vec)[n]->getDisNodes(); + const std::vector<double> dis_values = (*_cond_vec)[n]->getDisValues(); vtkIdType dis_type_value(0); std::map<FiniteElement::DistributionType, vtkIdType>::const_iterator it(_dis_type_map.find(type)); @@ -129,6 +123,7 @@ int VtkConditionSource::RequestData( vtkInformation* request, if ((*_cond_vec)[n]->getGeoType() == GEOLIB::POINT) { + /* size_t nPoints = _points->size(); const GEOLIB::Point* pnt = static_cast<const GEOLIB::Point*>((*_cond_vec)[n]->getGeoObj()); @@ -138,45 +133,59 @@ int VtkConditionSource::RequestData( vtkInformation* request, { id = static_cast<int>(i); //(this->getIndex(i, newPoints, scalars, idx_map)); vtkIdType vtk_id = static_cast<vtkIdType>(id); - newVerts->InsertNextCell(1, &vtk_id); - if (type == FiniteElement::CONSTANT) - scalars->SetValue(id, dis_values[0]); - distypes->SetValue(id, dis_type_value); + */ + const GEOLIB::Point* pnt = static_cast<const GEOLIB::Point*>((*_cond_vec)[n]->getGeoObj()); + newPoints->InsertNextPoint(pnt->getData()); + + newVerts->InsertNextCell(1, &pnt_id); + if (type == FiniteElement::CONSTANT || type == FiniteElement::CONSTANT_NEUMANN) + scalars->InsertNextValue(dis_values[0]); + else scalars->InsertNextValue(0); + distypes->InsertNextValue(dis_type_value); + pnt_id++; + /* break; } if (id == -1) std::cout << "Error in VtkConditionSource::RequestData() - Point object not found ..." << std::endl; + */ } else if ((*_cond_vec)[n]->getGeoType() == GEOLIB::POLYLINE) { - const GEOLIB::Polyline* ply = - static_cast<const GEOLIB::Polyline*>((*_cond_vec)[n]->getGeoObj()); + const GEOLIB::Polyline* ply = static_cast<const GEOLIB::Polyline*>((*_cond_vec)[n]->getGeoObj()); const int nPoints = ply->getNumberOfPoints(); newLines->InsertNextCell(nPoints); + double value (0); for (int i = 0; i < nPoints; i++) { - size_t pnt_id = ply->getPointID(i); //this->getIndex(ply->getPointID(i), newPoints, scalars, idx_map); + size_t point_index = ply->getPointID(i); + + newPoints->InsertNextPoint((*_points)[point_index]->getData()); newLines->InsertCellPoint(pnt_id); - distypes->SetValue(pnt_id, dis_type_value); + distypes->InsertNextValue(dis_type_value); - if (type == FiniteElement::CONSTANT) - scalars->SetValue(pnt_id, dis_values[0]); - else if (type == FiniteElement::LINEAR) + if (type == FiniteElement::CONSTANT || type == FiniteElement::CONSTANT_NEUMANN) + scalars->InsertNextValue(dis_values[0]); + else if (type == FiniteElement::LINEAR || type == FiniteElement::LINEAR_NEUMANN) { - for (size_t j = 0; j < dis_values.size(); j += 2) - if (static_cast<size_t>(dis_values[j]) == pnt_id) - //if (this->getIndex(static_cast<size_t>(dis_values[j]), newPoints, scalars, idx_map) == pnt_id) - { - scalars->SetValue(pnt_id, dis_values[j + 1]); - break; - } + for (size_t j = 0; j < dis_values.size(); j ++) + { + if (static_cast<int>(dis_nodes[j]) == i) + value = dis_values[j]; + } + scalars->InsertNextValue(value); } + else + scalars->InsertNextValue(0); + pnt_id++; } } else if ((*_cond_vec)[n]->getGeoType() == GEOLIB::SURFACE) { + std::vector<int> point_idx_map(_points->size(), -1); + const GEOLIB::Surface* sfc = static_cast<const GEOLIB::Surface*>((*_cond_vec)[n]->getGeoObj()); @@ -190,23 +199,31 @@ int VtkConditionSource::RequestData( vtkInformation* request, const GEOLIB::Triangle* triangle = (*sfc)[i]; for (size_t j = 0; j < 3; j++) { - size_t pnt_id = (*triangle)[j]; //this->getIndex((*triangle)[j], newPoints, scalars, idx_map); - aPolygon->GetPointIds()->SetId(j, pnt_id); - distypes->SetValue(pnt_id, dis_type_value); + size_t point_index ((*triangle)[j]); - if (type == FiniteElement::CONSTANT) - scalars->SetValue(pnt_id, dis_values[0]); - else if (type == FiniteElement::LINEAR) + if (point_idx_map[point_index] == -1) { - for (size_t k = 0; k < dis_values.size(); k += 2) - if (static_cast<size_t>(dis_values[j]) == - pnt_id) - //if (this->getIndex(static_cast<size_t>(dis_values[j]), newPoints, scalars, idx_map) == pnt_id) - { - scalars->SetValue(pnt_id,dis_values[j + 1]); - break; - } + point_idx_map[point_index] = pnt_id; + newPoints->InsertNextPoint((*_points)[point_index]->getData()); + aPolygon->GetPointIds()->SetId(j, pnt_id); + distypes->InsertNextValue(dis_type_value); + + if (type == FiniteElement::CONSTANT || type == FiniteElement::CONSTANT_NEUMANN) + scalars->InsertNextValue(dis_values[0]); + else if (type == FiniteElement::LINEAR || type == FiniteElement::LINEAR_NEUMANN) + { + for (size_t k = 0; k < dis_values.size(); k++) + if (static_cast<size_t>(dis_nodes[j]) == point_index) + { + scalars->InsertNextValue(dis_values[j]); + break; + } + } + else scalars->InsertNextValue(0); + pnt_id++; } + else + aPolygon->GetPointIds()->SetId(j, static_cast<vtkIdType>(point_idx_map[point_index])); } newPolys->InsertNextCell(aPolygon); @@ -217,12 +234,14 @@ int VtkConditionSource::RequestData( vtkInformation* request, else if ((*_cond_vec)[n]->getGeoType() == GEOLIB::INVALID) { size_t nValues = dis_values.size(); - for (size_t i=0; i<nValues; i+=2) + for (size_t i=0; i<nValues; i++) { - vtkIdType vtk_id = static_cast<vtkIdType>(dis_values[i]); - newVerts->InsertNextCell(1, &vtk_id); - scalars->SetValue(vtk_id, dis_values[i+1]); - distypes->SetValue(vtk_id, dis_type_value); + //vtkIdType pid = newPoints->InsertNextPoint((*_points)[dis_nodes[i]]->getData()); + vtkIdType pid = newPoints->InsertNextPoint((*_points)[i]->getData()); + newVerts->InsertNextCell(1, &pid); + scalars->InsertNextValue(dis_values[i]); + distypes->InsertNextValue(dis_type_value); + pnt_id++; } } // draw a bounding box in case of of the conditions is "domain" diff --git a/VtkVis/VtkGeoImageSource.cpp b/VtkVis/VtkGeoImageSource.cpp index a2481baecab40ef3aee824d64cff971fec40dc48..1ee5e8dd0d46c0b81e81871914f2fc328796a5ea 100644 --- a/VtkVis/VtkGeoImageSource.cpp +++ b/VtkVis/VtkGeoImageSource.cpp @@ -8,19 +8,17 @@ // ** INCLUDES ** #include "VtkGeoImageSource.h" -#include "OGSRaster.h" +//#include "OGSRaster.h" +#include "VtkRaster.h" #include <vtkFloatArray.h> #include <vtkImageChangeInformation.h> #include <vtkImageData.h> +#include <vtkImageImport.h> #include <vtkImageShiftScale.h> #include <vtkObjectFactory.h> #include <vtkPointData.h> -#include <vtkQImageToImageSource.h> - -#include <QImage> -#include <QPointF> -#include <QString> +#include <vtkIntArray.h> vtkStandardNewMacro(VtkGeoImageSource); @@ -51,22 +49,13 @@ void vtkSimpleImageFilterExampleExecute(vtkImageData* input, } VtkGeoImageSource::VtkGeoImageSource() +: _imageSource(NULL), _x0(0), _y0(0), _z0(0), _spacing(1) { - _imageSource = vtkQImageToImageSource::New(); - _imageInfo = vtkImageChangeInformation::New(); - _imageShift = vtkImageShiftScale::New(); - - _imageInfo->SetInputConnection(_imageSource->GetOutputPort()); - _imageShift->SetInputConnection(_imageInfo->GetOutputPort()); - _imageShift->SetOutputScalarTypeToUnsignedChar(); - this->SetInputConnection(_imageShift->GetOutputPort()); } VtkGeoImageSource::~VtkGeoImageSource() { - _imageSource->Delete(); - _imageInfo->Delete(); - _imageShift->Delete(); + if(_imageSource) _imageSource->Delete(); } void VtkGeoImageSource::PrintSelf(ostream& os, vtkIndent indent) @@ -74,52 +63,43 @@ void VtkGeoImageSource::PrintSelf(ostream& os, vtkIndent indent) this->Superclass::PrintSelf(os, indent); } -void VtkGeoImageSource::setImageFilename(QString filename) +void VtkGeoImageSource::readImage(const QString &filename) { - QImage* raster = new QImage; - QPointF origin; - double spacing; - OGSRaster::loadImage(filename, *raster, origin, spacing); - this->setImage(*raster); - delete raster; - // correct raster position by half a pixel for correct visualisation - this->setOrigin(origin.x()+(spacing/2.0), origin.y()+(spacing/2.0), -10.0); - this->setSpacing(spacing); - this->SetName(filename); + this->setImage(VtkRaster::loadImage(filename.toStdString(), _x0, _y0, _spacing), filename, _x0, _y0, _spacing); } -vtkImageData* VtkGeoImageSource::getImageData() +void VtkGeoImageSource::setImage(vtkImageAlgorithm* image, const QString &name, double x0, double y0, double spacing) { - return this->_imageSource->GetImageDataInput(0); -} + this->_imageSource = image; + this->SetInputConnection(_imageSource->GetOutputPort()); + this->SetName(name); + _x0 = x0; _y0 = y0; _z0 = -10; _spacing = spacing; -std::pair<double, double> VtkGeoImageSource::getOrigin() -{ - double* origin = this->_imageInfo->GetOutputOrigin(); - std::pair<double, double> p(origin[0], origin[1]); - return p; + this->GetOutput()->SetOrigin(_x0, _y0, _z0); + this->GetOutput()->SetSpacing(_spacing, _spacing, _spacing); } -double VtkGeoImageSource::getSpacing() +vtkImageData* VtkGeoImageSource::getImageData() { - double* spacing = this->_imageInfo->GetOutputSpacing(); - return spacing[0]; + return this->_imageSource->GetImageDataInput(0); } -void VtkGeoImageSource::setImage(QImage& image) +void VtkGeoImageSource::getOrigin(double origin[3]) const { - _imageSource->SetQImage(&image); - _imageSource->Update(); // crashes otherwise + origin[0] = this->_x0; + origin[1] = this->_y0; + origin[2] = this->_z0; } -void VtkGeoImageSource::setOrigin(double x, double y, double z) +double VtkGeoImageSource::getSpacing() const { - _imageInfo->SetOutputOrigin(x, y, z); + return this->_spacing; } -void VtkGeoImageSource::setSpacing(double spacing) +void VtkGeoImageSource::getRange(double range[2]) { - _imageInfo->SetOutputSpacing(spacing, spacing, spacing); + this->_imageSource->Update(); + _imageSource->GetOutput()->GetPointData()->GetArray(0)->GetRange(range); } void VtkGeoImageSource::SimpleExecute(vtkImageData* input, vtkImageData* output) @@ -137,41 +117,6 @@ void VtkGeoImageSource::SimpleExecute(vtkImageData* input, vtkImageData* output) vtkGenericWarningMacro("Execute: Unknown input ScalarType"); return; } - -/* - // Create normals - vtkFloatArray* normals = vtkFloatArray::New(); - int numPoints = input->GetNumberOfPoints(); - normals->SetNumberOfComponents(3); - normals->Allocate(3*numPoints); - float normal[3] = {0.f, 0.f, 1.f}; - - // vector data - std::cout << input->GetScalarTypeAsString() << std::endl; - vtkFloatArray* vectors = vtkFloatArray::New(); - vectors->SetNumberOfComponents(3); - vectors->Allocate(3*numPoints); - int numScalarComponents = input->GetNumberOfScalarComponents(); - - for (int i = 0; i < numPoints; i++) - { - normals->InsertTuple(i, normal); - float vector[3]; - vector[0] = 1; - vector[1] = 1; - vector[2] = ((unsigned char*)inPtr)[i * numScalarComponents] * 0.1; - //std::cout << vector[2] << " "; - vectors->InsertTuple(i, vector); - } - - normals->SetName("Normals"); - output->GetPointData()->SetNormals(normals); - normals->Delete(); - - vectors->SetName("Vectors"); - output->GetPointData()->SetVectors(vectors); - vectors->Delete(); - */ } void VtkGeoImageSource::SetUserProperty( QString name, QVariant value ) diff --git a/VtkVis/VtkGeoImageSource.h b/VtkVis/VtkGeoImageSource.h index c21e175c6c7599f5cdaa56e7687043698fcb485b..3e12f7ab926d623b3bb5e8c21f8d4aaf5eb65c8d 100644 --- a/VtkVis/VtkGeoImageSource.h +++ b/VtkVis/VtkGeoImageSource.h @@ -13,10 +13,10 @@ class QString; class QPointF; class QImage; class vtkQImageToImageSource; -class vtkImageChangeInformation; class vtkImageShiftScale; class vtkImageData; + class VtkGeoImageSource : public vtkSimpleImageToImageFilter, public VtkAlgorithmProperties { public: @@ -28,19 +28,23 @@ public: /// @brief Prints information about itself. void PrintSelf(ostream& os, vtkIndent indent); + /// @brief Returns the ImageData object. vtkImageData* getImageData(); - std::pair<double, double> getOrigin(); - - double getSpacing(); + /// @brief Reads an image from file. + void readImage(const QString &filename); - void setImageFilename(QString filename); + /// @brief Imports an existing image object. + void setImage(vtkImageAlgorithm* img, const QString &name, double x0, double y0, double spacing); - void setImage(QImage& image); + /// @brief Returns the origin in world coordinates. + void getOrigin(double origin[3]) const; - void setOrigin(double x, double y, double z); + /// @brief Returns the scalar data range. + void getRange(double range[2]); - void setSpacing(double spacing); + /// @brief Returns the spacing betweeen two pixels. + double getSpacing() const; virtual void SetUserProperty(QString name, QVariant value); @@ -58,9 +62,9 @@ private: VtkGeoImageSource(const VtkGeoImageSource&); // Not implemented. void operator=(const VtkGeoImageSource&); // Not implemented - vtkQImageToImageSource* _imageSource; - vtkImageChangeInformation* _imageInfo; - vtkImageShiftScale* _imageShift; + vtkImageAlgorithm* _imageSource; + + double _x0, _y0, _z0, _spacing; }; #endif // VTKGEOIMAGESOURCE_H diff --git a/VtkVis/VtkImageDataToLinePolyDataFilter.cpp b/VtkVis/VtkImageDataToLinePolyDataFilter.cpp index 5a2b79485f6ad71774058f53788bddc02eab1b99..a83e0bd5d2e4c174913da5b70227afcd9a8cc003 100644 --- a/VtkVis/VtkImageDataToLinePolyDataFilter.cpp +++ b/VtkVis/VtkImageDataToLinePolyDataFilter.cpp @@ -54,10 +54,14 @@ int VtkImageDataToLinePolyDataFilter::RequestData(vtkInformation*, void* inScalarPtr = input->GetScalarPointer(); int numScalarComponents = input->GetNumberOfScalarComponents(); + double spacing[3]; input->GetSpacing(spacing); this->ImageSpacing = spacing[0]; + int dimensions[3]; + input->GetDimensions(dimensions); + // Skip execution if there are no points vtkIdType numPts = input->GetNumberOfPoints(); if (numPts < 1) @@ -84,14 +88,25 @@ int VtkImageDataToLinePolyDataFilter::RequestData(vtkInformation*, vtkPointData* outPD = output->GetPointData(); outPD->CopyAllocate(inPD, numPts * 16, numPts); + // Compute scaling factor that max height is 0.1 * longest image dimension + double range[2]; + inPD->GetArray(0)->GetRange(range); + float scalingFactor = (std::max(dimensions[0], dimensions[1]) * spacing[0] * 0.1) + / std::max(range[0], range[1]); + double dir[3] = {0, 0, 1}; // Traverse all points creating another point with scalar distance in Z direction for (vtkIdType ptId = 0; ptId < numPts; ++ptId) { + // Skip translucent pixels + float opacity = ((float*)inScalarPtr)[ptId * numScalarComponents + 1]; + if (opacity < 0.00000001f) + continue; + // Compute length of the new line (scalar * LengthScaleFactor) - float length = ((unsigned char*)inScalarPtr)[ptId * numScalarComponents] - * this->LengthScaleFactor; + float length = ((float*)inScalarPtr)[ptId * numScalarComponents] + * scalingFactor * this->LengthScaleFactor; //float length = (((unsigned char*)inScalarPtr)[ptId * numScalarComponents]* this->LengthScaleFactor > 50000) ? 50000 : ((unsigned char*)inScalarPtr)[ptId * numScalarComponents]* this->LengthScaleFactor; // Skip this line if length is zero @@ -126,7 +141,7 @@ int VtkImageDataToLinePolyDataFilter::RequestData(vtkInformation*, // Store the new set of points in the output output->SetPoints(newPts); - output->GetPointData()->GetArray(0)->SetName("Colours"); + output->GetPointData()->GetArray(0)->SetName("Colors"); // Avoid keeping extra memory around output->Squeeze(); diff --git a/VtkVis/VtkImageDataToLinePolyDataFilter.h b/VtkVis/VtkImageDataToLinePolyDataFilter.h index 18792b5d1999ddca8f57f4b66725b6eb608c137e..cddf808d5c356302e7f5bb8b3aa5e0288f0ec97c 100644 --- a/VtkVis/VtkImageDataToLinePolyDataFilter.h +++ b/VtkVis/VtkImageDataToLinePolyDataFilter.h @@ -13,8 +13,9 @@ class vtkInformation; class vtkInformationVector; /// @brief Creates lines that stand on top of the image with the length -/// of the corresponding first sub-pixel value (the red value). Used by -/// VtkCompositeImageDataToCylindersFilter. +/// of the corresponding first sub-pixel value (the grey or red value). +/// The maximum height is 0.1 * longest image dimension. +/// Used by VtkCompositeImageDataToCylindersFilter. class VtkImageDataToLinePolyDataFilter : public vtkPolyDataAlgorithm, public VtkAlgorithmProperties { public: diff --git a/VtkVis/VtkMeshConverter.cpp b/VtkVis/VtkMeshConverter.cpp index 413125ddade58035ae5c8db39aac6a7d1e350d2f..143a244a053901b1ee3cf64134a64b0faed5e06f 100644 --- a/VtkVis/VtkMeshConverter.cpp +++ b/VtkVis/VtkMeshConverter.cpp @@ -18,11 +18,12 @@ #include <vtkCell.h> #include <vtkCellData.h> #include <vtkUnstructuredGrid.h> +#include <vtkFloatArray.h> -MeshLib::CFEMesh* VtkMeshConverter::convertImgToMesh(vtkImageData* img, - const std::pair<double,double> &origin, - const double &scalingFactor, +GridAdapter* VtkMeshConverter::convertImgToMesh(vtkImageData* img, + const double origin[3], + const double scalingFactor, MshElemType::type elem_type, UseIntensityAs::type intensity_type) { @@ -32,8 +33,8 @@ MeshLib::CFEMesh* VtkMeshConverter::convertImgToMesh(vtkImageData* img, return NULL; } - vtkSmartPointer<vtkUnsignedCharArray> pixelData = vtkSmartPointer<vtkUnsignedCharArray>( - vtkUnsignedCharArray::SafeDownCast(img->GetPointData()->GetScalars())); + vtkSmartPointer<vtkFloatArray> pixelData = vtkSmartPointer<vtkFloatArray>( + vtkFloatArray::SafeDownCast(img->GetPointData()->GetScalars())); int* dims = img->GetDimensions(); const size_t imgHeight = dims[0]; @@ -44,7 +45,7 @@ MeshLib::CFEMesh* VtkMeshConverter::convertImgToMesh(vtkImageData* img, bool* visNodes(new bool[incWidth * incHeight]); int* node_idx_map(new int[incWidth * incHeight]); - for (size_t j = 0; j < incWidth; j++) + for (size_t j = 0; j < incHeight; j++) { pixVal[j]=0; visNodes[j]=false; @@ -56,9 +57,26 @@ MeshLib::CFEMesh* VtkMeshConverter::convertImgToMesh(vtkImageData* img, { const size_t img_idx = i * imgHeight + j; const size_t index = (i+1) * incHeight + j; - const double* colour = pixelData->GetTuple4(img_idx); - pixVal[index] = 0.3 * colour[0] + 0.6 * colour[1] + 0.1 * colour[2]; - visNodes[index] = (colour[3] > 0); + int nTuple = pixelData->GetNumberOfComponents(); + double* colour; + if (nTuple == 2) //Grey+Alpha + { + colour = pixelData->GetTuple2(img_idx); + pixVal[index] = colour[0]; + + } + else if (nTuple == 4) //RGBA + { + colour = pixelData->GetTuple4(img_idx); + pixVal[index] = 0.3 * colour[0] + 0.6 * colour[1] + 0.1 * colour[2]; + } + else + { + std::cout << "Unsupported pixel composition!" << std::endl; + return NULL; + } + + visNodes[index] = (colour[nTuple-1] > 0); node_idx_map[index]=-1; } pixVal[(i+2)*incHeight-1]=0; @@ -66,7 +84,7 @@ MeshLib::CFEMesh* VtkMeshConverter::convertImgToMesh(vtkImageData* img, node_idx_map[(i+2)*incHeight-1]=-1; } - MeshLib::CFEMesh* mesh = constructMesh(pixVal, node_idx_map, visNodes, origin, imgHeight, imgWidth, scalingFactor, elem_type, intensity_type); + GridAdapter* mesh = constructMesh(pixVal, node_idx_map, visNodes, origin, imgHeight, imgWidth, scalingFactor, elem_type, intensity_type); delete [] pixVal; delete [] visNodes; @@ -75,8 +93,8 @@ MeshLib::CFEMesh* VtkMeshConverter::convertImgToMesh(vtkImageData* img, return mesh; } -MeshLib::CFEMesh* VtkMeshConverter::convertImgToMesh(const double* img, - const std::pair<double,double> &origin, +GridAdapter* VtkMeshConverter::convertImgToMesh(const double* img, + const double origin[3], const size_t imgHeight, const size_t imgWidth, const double &scalingFactor, @@ -89,7 +107,9 @@ MeshLib::CFEMesh* VtkMeshConverter::convertImgToMesh(const double* img, bool* visNodes(new bool[incWidth * incHeight]); int* node_idx_map(new int[incWidth * incHeight]); - for (size_t j = 0; j < incWidth; j++) + double noDataValue = getExistingValue(img, imgWidth*imgHeight); + + for (size_t j = 0; j < imgHeight; j++) { pixVal[j]=0; visNodes[j]=false; @@ -101,8 +121,17 @@ MeshLib::CFEMesh* VtkMeshConverter::convertImgToMesh(const double* img, { const size_t img_idx = i * imgHeight + j; const size_t index = (i+1) * incHeight + j; - pixVal[index] = img[img_idx]; - visNodes[index] = 1; + if (img[img_idx] == -9999) + { + visNodes[index] = false; + pixVal[index] = noDataValue; + } + else + { + pixVal[index] = img[img_idx]; + visNodes[index] = true; + } + node_idx_map[index]=-1; } pixVal[(i+2)*incHeight-1]=0; @@ -110,7 +139,7 @@ MeshLib::CFEMesh* VtkMeshConverter::convertImgToMesh(const double* img, node_idx_map[(i+2)*incHeight-1]=-1; } - MeshLib::CFEMesh* mesh = constructMesh(pixVal, node_idx_map, visNodes, origin, imgHeight, imgWidth, scalingFactor, elem_type, intensity_type); + GridAdapter* mesh = constructMesh(pixVal, node_idx_map, visNodes, origin, imgHeight, imgWidth, scalingFactor, elem_type, intensity_type); delete [] pixVal; delete [] visNodes; @@ -119,10 +148,10 @@ MeshLib::CFEMesh* VtkMeshConverter::convertImgToMesh(const double* img, return mesh; } -MeshLib::CFEMesh* VtkMeshConverter::constructMesh(const double* pixVal, +GridAdapter* VtkMeshConverter::constructMesh(const double* pixVal, int* node_idx_map, const bool* visNodes, - const std::pair<double,double> &origin, + const double origin[3], const size_t &imgHeight, const size_t &imgWidth, const double &scalingFactor, @@ -131,10 +160,10 @@ MeshLib::CFEMesh* VtkMeshConverter::constructMesh(const double* pixVal, { const size_t incHeight = imgHeight+1; const size_t incWidth = imgWidth+1; - MeshLib::CFEMesh* mesh(new MeshLib::CFEMesh()); + GridAdapter* grid = new GridAdapter(); size_t node_idx_count(0); - const double x_offset(origin.first - scalingFactor/2.0); - const double y_offset(origin.second - scalingFactor/2.0); + const double x_offset(origin[0] - scalingFactor/2.0); + const double y_offset(origin[1] - scalingFactor/2.0); for (size_t i = 0; i < incWidth; i++) for (size_t j = 0; j < incHeight; j++) @@ -150,13 +179,9 @@ MeshLib::CFEMesh* VtkMeshConverter::constructMesh(const double* pixVal, if (set_node) { double zValue = (intensity_type == UseIntensityAs::ELEVATION) ? pixVal[index] : 0.0; - const double coords[3] = { x_offset + (scalingFactor * j), - y_offset + (scalingFactor * i), - zValue }; - - MeshLib::CNode* node(new MeshLib::CNode(node_idx_count)); - node->SetCoordinates(coords); - mesh->nod_vector.push_back(node); + grid->addNode(new GEOLIB::Point(x_offset + (scalingFactor * j), + y_offset + (scalingFactor * i), + zValue)); node_idx_map[index] = node_idx_count; node_idx_count++; } @@ -172,45 +197,45 @@ MeshLib::CFEMesh* VtkMeshConverter::constructMesh(const double* pixVal, const int mat = (intensity_type != UseIntensityAs::MATERIAL) ? 0 : static_cast<int>(pixVal[index+incHeight]); if (elem_type == MshElemType::TRIANGLE) { - mesh->ele_vector.push_back(createElement(elem_type, mat, node_idx_map[index], node_idx_map[index + 1], - node_idx_map[index + incHeight])); // upper left triangle - mesh->ele_vector.push_back(createElement(elem_type, mat, node_idx_map[index + 1], - node_idx_map[index + incHeight + 1], - node_idx_map[index + incHeight])); // lower right triangle + grid->addElement(createElement(elem_type, mat, node_idx_map[index], node_idx_map[index + 1], + node_idx_map[index + incHeight])); // upper left triangle + grid->addElement(createElement(elem_type, mat, node_idx_map[index + 1], + node_idx_map[index + incHeight + 1], + node_idx_map[index + incHeight])); // lower right triangle } if (elem_type == MshElemType::QUAD) { - mesh->ele_vector.push_back(createElement(elem_type, mat, node_idx_map[index], node_idx_map[index + 1], - node_idx_map[index + incHeight + 1], - node_idx_map[index + incHeight])); + grid->addElement(createElement(elem_type, mat, node_idx_map[index], node_idx_map[index + 1], + node_idx_map[index + incHeight + 1], + node_idx_map[index + incHeight])); } } } - mesh->ConstructGrid(); - return mesh; + return grid; } -MeshLib::CElem* VtkMeshConverter::createElement(MshElemType::type t, int mat, size_t node1, size_t node2, size_t node3, size_t node4) +GridAdapter::Element* VtkMeshConverter::createElement(MshElemType::type t, int mat, size_t node1, size_t node2, size_t node3, size_t node4) { - MeshLib::CElem* elem(new MeshLib::CElem); - elem->setElementProperties(t); - elem->SetNodeIndex(0, node1); - elem->SetNodeIndex(1, node2); - elem->SetNodeIndex(2, node3); + GridAdapter::Element* elem = new GridAdapter::Element(); + elem->material = mat; + elem->type = t; + std::vector<size_t> nodes; + nodes.push_back(node1); + nodes.push_back(node2); + nodes.push_back(node3); if (t == MshElemType::QUAD) - elem->SetNodeIndex(3, node4); - elem->SetPatchIndex(mat); - elem->InitializeMembers(); + nodes.push_back(node4); + elem->nodes = nodes; return elem; } -MeshLib::CFEMesh* VtkMeshConverter::convertUnstructuredGrid(vtkUnstructuredGrid* grid) +GridAdapter* VtkMeshConverter::convertUnstructuredGrid(vtkUnstructuredGrid* grid) { if (!grid) return NULL; - MeshLib::CFEMesh* mesh(new MeshLib::CFEMesh()); + GridAdapter* mesh = new GridAdapter(); const size_t nNodes = grid->GetPoints()->GetNumberOfPoints(); const size_t nElems = grid->GetNumberOfCells(); @@ -220,8 +245,7 @@ MeshLib::CFEMesh* VtkMeshConverter::convertUnstructuredGrid(vtkUnstructuredGrid* for (size_t i = 0; i < nNodes; i++) { coords = grid->GetPoints()->GetPoint(i); - MeshLib::CNode* node(new MeshLib::CNode(i, coords[0], coords[1], coords[2])); - mesh->nod_vector.push_back(node); + mesh->addNode(new GEOLIB::Point(coords[0], coords[1], coords[2])); } // set mesh elements @@ -229,7 +253,7 @@ MeshLib::CFEMesh* VtkMeshConverter::convertUnstructuredGrid(vtkUnstructuredGrid* vtkDataArray* scalars = grid->GetCellData()->GetScalars("MaterialIDs"); for (size_t i = 0; i < nElems; i++) { - MeshLib::CElem* elem(new MeshLib::CElem()); + GridAdapter::Element* elem = new GridAdapter::Element(); MshElemType::type elem_type = MshElemType::INVALID; int cell_type = grid->GetCellType(i); @@ -250,29 +274,34 @@ MeshLib::CFEMesh* VtkMeshConverter::convertUnstructuredGrid(vtkUnstructuredGrid* if (elem_type != MshElemType::INVALID) { - //elem->SetElementType(elem_type); - elem->setElementProperties(elem_type); + elem->type = elem_type; if (scalars) - elem->SetPatchIndex(static_cast<int>(scalars->GetComponent(i,0))); // HACK the name of the correct scalar array of the vtk file should probably be passed as an argument?! + elem->material = static_cast<int>(scalars->GetComponent(i,0)); } else { - std::cout << - "Error in GridAdapter::convertUnstructuredGrid() - Unknown mesh element type ..." - << std::endl; + std::cout << "Error in GridAdapter::convertUnstructuredGrid() - Unknown mesh element type ..." << std::endl; return NULL; } cell = grid->GetCell(i); size_t nElemNodes = cell->GetNumberOfPoints(); - elem->SetNodesNumber(nElemNodes); - elem->getNodeIndices().resize(nElemNodes); - + std::vector<size_t> nodes; for (size_t j = 0; j < nElemNodes; j++) - elem->SetNodeIndex(j, cell->GetPointId(j)); + nodes.push_back(cell->GetPointId(j)); - mesh->ele_vector.push_back(elem); + elem->nodes = nodes; + mesh->addElement(elem); } - mesh->ConstructGrid(); return mesh; } + +double VtkMeshConverter::getExistingValue(const double* img, size_t length) +{ + for (size_t i=0; i<length; i++) + { + if (img[i] != -9999) + return img[i]; + } + return -9999; +} diff --git a/VtkVis/VtkMeshConverter.h b/VtkVis/VtkMeshConverter.h index 30f82d3defc90250789d5f130da3370a887f659c..ee748168c85afd81d1ecb60fcadf4085c1c4dd37 100644 --- a/VtkVis/VtkMeshConverter.h +++ b/VtkVis/VtkMeshConverter.h @@ -7,18 +7,13 @@ #ifndef VTKMESHCONVERTER_H #define VTKMESHCONVERTER_H -// ** INCLUDES ** -#include "msh_mesh.h" +//#include <utility> +//#include "MSHEnums.h" +#include "GridAdapter.h" class vtkImageData; // For conversion from Image to QuadMesh class vtkUnstructuredGrid; // For conversion vom vtk to ogs mesh -namespace MeshLib -{ -class CFEMesh; -class CNode; -} - /// Selection of possible interpretations for intensities struct UseIntensityAs { @@ -37,47 +32,49 @@ class VtkMeshConverter public: /** * Converts greyscale image to a mesh - * \parelem_type defines if elements of the new mesh should be triangles or quads (or hexes for 3D) + * \param elem_type defines if elements of the new mesh should be triangles or quads (or hexes for 3D) * \param intensity_type defines how image intensities are interpreted */ - static MeshLib::CFEMesh* convertImgToMesh(vtkImageData* img, - const std::pair<double,double> &origin, - const double &scalingFactor, - MshElemType::type elem_type, - UseIntensityAs::type intensity_type); + static GridAdapter* convertImgToMesh(vtkImageData* img, + const double origin[3], + const double scalingFactor, + MshElemType::type elem_type, + UseIntensityAs::type intensity_type); /** * Converts double array with raster values to a mesh - * \parelem_type defines if elements of the new mesh should be triangles or quads (or hexes for 3D) + * \param elem_type defines if elements of the new mesh should be triangles or quads (or hexes for 3D) * \param intensity_type defines how image intensities are interpreted */ - static MeshLib::CFEMesh* convertImgToMesh(const double* img, - const std::pair<double,double> &origin, - const size_t imgHeight, - const size_t imgWidth, - const double &scalingFactor, - MshElemType::type elem_type, - UseIntensityAs::type intensity_type); + static GridAdapter* convertImgToMesh(const double* img, + const double origin[3], + const size_t imgHeight, + const size_t imgWidth, + const double &scalingFactor, + MshElemType::type elem_type, + UseIntensityAs::type intensity_type); /// Converts a vtkUnstructuredGrid object to a CFEMesh - static MeshLib::CFEMesh* convertUnstructuredGrid(vtkUnstructuredGrid* grid); + static GridAdapter* convertUnstructuredGrid(vtkUnstructuredGrid* grid); private: /// Does the actual mesh generation based on the data given to the public methods. - static MeshLib::CFEMesh* constructMesh(const double* pixVal, - int* node_idx_map, - const bool* visNodes, - const std::pair<double,double> &origin, - const size_t &imgHeight, - const size_t &imgWidth, - const double &scalingFactor, - MshElemType::type elem_type, - UseIntensityAs::type intensity_type); + static GridAdapter* constructMesh(const double* pixVal, + int* node_idx_map, + const bool* visNodes, + const double origin[3], + const size_t &imgHeight, + const size_t &imgWidth, + const double &scalingFactor, + MshElemType::type elem_type, + UseIntensityAs::type intensity_type); /// Creates a mesh element based on the given data. - static MeshLib::CElem* createElement(MshElemType::type t, int mat, + static GridAdapter::Element* createElement(MshElemType::type t, int mat, size_t node1, size_t node2, size_t node3, size_t node4 = 0); + + static double getExistingValue(const double* img, size_t length); }; #endif // VTKMESHCONVERTER_H diff --git a/VtkVis/VtkMeshSource.cpp b/VtkVis/VtkMeshSource.cpp index c561268cba6993c80d36334dd73576f161d3fdb5..e98c1e9ef726dbd4f3a44e24d1a947eee37c9299 100644 --- a/VtkVis/VtkMeshSource.cpp +++ b/VtkVis/VtkMeshSource.cpp @@ -18,6 +18,7 @@ #include <vtkStreamingDemandDrivenPipeline.h> #include <vtkUnsignedCharArray.h> #include <vtkUnstructuredGrid.h> +#include <vtkProperty.h> // OGS Cell Types #include <vtkHexahedron.h> @@ -32,10 +33,9 @@ vtkCxxRevisionMacro(VtkMeshSource, "$Revision$"); VtkMeshSource::VtkMeshSource() : _matName("MaterialIDs") { + _removable = false; // From VtkAlgorithmProperties this->SetNumberOfInputPorts(0); - //this->SetColorByMaterial(true); - const GEOLIB::Color* c = GEOLIB::getRandomColor(); vtkProperty* vtkProps = GetProperties(); vtkProps->SetColor((*c)[0] / 255.0,(*c)[1] / 255.0,(*c)[2] / 255.0); @@ -93,9 +93,9 @@ int VtkMeshSource::RequestData( vtkInformation* request, const std::vector<GEOLIB::Point*>* nodes = _grid->getNodes(); const std::vector<GridAdapter::Element*>* elems = _grid->getElements(); - size_t nPoints = nodes->size(); - size_t nElems = elems->size(); - size_t nElemNodes = 0; + const size_t nPoints = nodes->size(); + const size_t nElems = elems->size(); + //size_t nElemNodes = 0; if (nPoints == 0 || nElems == 0) return 0; @@ -118,14 +118,15 @@ int VtkMeshSource::RequestData( vtkInformation* request, vtkSmartPointer<vtkIntArray> materialIDs = vtkSmartPointer<vtkIntArray>::New(); materialIDs->SetName(_matName); materialIDs->SetNumberOfComponents(1); - //materialIDs->SetNumberOfTuples(nElems); + materialIDs->SetNumberOfTuples(nElems); // Generate mesh elements for (size_t i = 0; i < nElems; i++) { vtkCell* newCell; + const GridAdapter::Element* elem = (*elems)[i]; - switch ((*elems)[i]->type) + switch (elem->type) { case MshElemType::TRIANGLE: newCell = vtkTriangle::New(); @@ -149,11 +150,11 @@ int VtkMeshSource::RequestData( vtkInformation* request, return 0; } - materialIDs->InsertNextValue((*elems)[i]->material); + materialIDs->InsertValue(i,(elem->material)); - nElemNodes = (*elems)[i]->nodes.size(); + const size_t nElemNodes (elem->nodes.size()); for (size_t j = 0; j < nElemNodes; j++) - newCell->GetPointIds()->SetId(j, (*elems)[i]->nodes[nElemNodes - 1 - j]); + newCell->GetPointIds()->SetId(j, elem->nodes[nElemNodes - 1 - j]); output->InsertNextCell(newCell->GetCellType(), newCell->GetPointIds()); newCell->Delete(); diff --git a/VtkVis/VtkPointsSource.cpp b/VtkVis/VtkPointsSource.cpp index 7f108aa8d21bb26a6f74ed2cfa45955bc696b98b..1850908209cb56d60e3f998407674890f81c6ef9 100644 --- a/VtkVis/VtkPointsSource.cpp +++ b/VtkVis/VtkPointsSource.cpp @@ -18,6 +18,7 @@ #include <vtkSmartPointer.h> #include <vtkStreamingDemandDrivenPipeline.h> #include <vtkCellData.h> +#include <vtkProperty.h> vtkStandardNewMacro(VtkPointsSource); vtkCxxRevisionMacro(VtkPointsSource, "$Revision$"); @@ -25,6 +26,7 @@ vtkCxxRevisionMacro(VtkPointsSource, "$Revision$"); VtkPointsSource::VtkPointsSource() : _points(NULL) { + _removable = false; // From VtkAlgorithmProperties this->SetNumberOfInputPorts(0); const GEOLIB::Color* c = GEOLIB::getRandomColor(); diff --git a/VtkVis/VtkPolylinesSource.cpp b/VtkVis/VtkPolylinesSource.cpp index b8d880c9dcb6af80acd0e717c538d1fc931acc88..cc3aa88873de51a6fc16a9f8718d7dcc17187239 100644 --- a/VtkVis/VtkPolylinesSource.cpp +++ b/VtkVis/VtkPolylinesSource.cpp @@ -18,6 +18,7 @@ #include <vtkPolyData.h> #include <vtkSmartPointer.h> #include <vtkStreamingDemandDrivenPipeline.h> +#include <vtkProperty.h> vtkStandardNewMacro(VtkPolylinesSource); vtkCxxRevisionMacro(VtkPolylinesSource, "$Revision$"); @@ -25,6 +26,7 @@ vtkCxxRevisionMacro(VtkPolylinesSource, "$Revision$"); VtkPolylinesSource::VtkPolylinesSource() : _polylines(NULL) { + _removable = false; // From VtkAlgorithmProperties this->SetNumberOfInputPorts(0); const GEOLIB::Color* c = GEOLIB::getRandomColor(); diff --git a/VtkVis/VtkRaster.cpp b/VtkVis/VtkRaster.cpp new file mode 100644 index 0000000000000000000000000000000000000000..529d64ca3cdd3e7f1e166211686e0f19399a2624 --- /dev/null +++ b/VtkVis/VtkRaster.cpp @@ -0,0 +1,516 @@ +/** + * \file VtkRaster.cpp + * 2012/02/01 KR Initial implementation + */ + +#include "VtkRaster.h" + +#include <cmath> +#include <iomanip> +#include <iostream> +#include <sstream> + +#include <QFileInfo> + +#include "StringTools.h" + +#include <vtkFloatArray.h> +#include <vtkPointData.h> + +#include <vtkImageAlgorithm.h> +#include <vtkImageData.h> +#include <vtkImageImport.h> +#include <vtkImageReader2.h> +#include <vtkPNGReader.h> +#include <vtkJPEGReader.h> +#include <vtkBMPReader.h> + +#ifdef libgeotiff_FOUND +#include "geo_tiffp.h" +#include "xtiffio.h" +#endif + +vtkImageAlgorithm* VtkRaster::loadImage(const std::string &fileName, + double& x0, double& y0, double& delta) +{ + QFileInfo fileInfo(QString::fromStdString(fileName)); + + if (fileInfo.suffix().toLower() == "asc" || fileInfo.suffix().toLower() == "grd") + return loadImageFromASC(fileName, x0, y0, delta); +#ifdef libgeotiff_FOUND + else if ((fileInfo.suffix().toLower() == "tif") || (fileInfo.suffix().toLower() == "tiff")) + return loadImageFromTIFF(fileName, x0, y0, delta); +#endif + else + return loadImageFromFile(fileName); +} + +vtkImageImport* VtkRaster::loadImageFromASC(const std::string &fileName, + double& x0, double& y0, double& delta) +{ + size_t width(0), height(0); + float* data; + + if (fileName.substr(fileName.length()-3, 3).compare("asc") == 0) + data = loadDataFromASC(fileName, x0, y0, width, height, delta); + else + data = loadDataFromSurfer(fileName, x0, y0, width, height, delta); + + vtkImageImport* image = vtkImageImport::New(); + image->SetDataSpacing(delta, delta,delta); + image->SetDataOrigin(x0+(delta/2.0), y0+(delta/2.0), 0); // translate whole mesh by half a pixel in x and y + image->SetWholeExtent(0, width-1, 0, height-1, 0, 0); + image->SetDataExtent(0, width-1, 0, height-1, 0, 0); + image->SetDataExtentToWholeExtent(); + image->SetDataScalarTypeToFloat(); + image->SetNumberOfScalarComponents(2); + image->SetImportVoidPointer(data, 0); + image->Update(); + + return image; +} + +vtkImageImport* VtkRaster::loadImageFromArray(double* data_array, double &x0, double &y0, size_t &width, size_t &height, double &delta, double noData) +{ + const size_t length = height*width; + float* data = new float[length*2]; + float max_val=noData; + for (size_t j=0; j<length; j++) + { + data[j*2] = static_cast<float>(data_array[j]); + max_val = (data[j*2]>max_val) ? data[j*2] : max_val; + } + for (size_t j=0; j<length; j++) + { + if (data[j*2]==noData) + { + data[j*2] = max_val; + data[j*2+1] = 0; + } + else + { + //data[j*2] = max_val-data[j*2];//delete; + data[j*2+1] = max_val; + } + } + + vtkImageImport* image = vtkImageImport::New(); + image->SetDataSpacing(delta, delta, delta); + image->SetDataOrigin(x0+(delta/2.0), y0+(delta/2.0), 0); // translate whole mesh by half a pixel in x and y + image->SetWholeExtent(0, width-1, 0, height-1, 0, 0); + image->SetDataExtent(0, width-1, 0, height-1-1, 0, 0); + image->SetDataExtentToWholeExtent(); + image->SetDataScalarTypeToFloat(); + image->SetNumberOfScalarComponents(2); + image->SetImportVoidPointer(data, 0); + image->Update(); + + return image; +} + + +bool VtkRaster::readASCHeader(ascHeader &header, std::ifstream &in) +{ + std::string line, tag, value; + + in >> tag; + if (tag.compare("ncols") == 0) + { + in >> value; + header.ncols = atoi(value.c_str()); + } + else + return false; + in >> tag; + if (tag.compare("nrows") == 0) + { + in >> value; + header.nrows = atoi(value.c_str()); + } + else + return false; + in >> tag; + if (tag.compare("xllcorner") == 0) + { + in >> value; + header.x = strtod(replaceString(",", ".", value).c_str(),0); + } + else + return false; + in >> tag; + if (tag.compare("yllcorner") == 0) + { + in >> value; + header.y = strtod(replaceString(",", ".", value).c_str(),0); + } + else + return false; + in >> tag; + if (tag.compare("cellsize") == 0) + { + in >> value; + header.cellsize = strtod(replaceString(",", ".", value).c_str(),0); + } + else + return false; + in >> tag; + if (tag.compare("NODATA_value") == 0) + { + in >> value; + header.noData = value.c_str(); + } + else + return false; + + // correct raster position by half a pixel for correct visualisation + // argh! wrong! correction has to happen in visualisation object, otherwise the actual data is wrong + //header.x = header.x + (header.cellsize / 2); + //header.y = header.y + (header.cellsize / 2); + + return true; +} + +float* VtkRaster::loadDataFromASC(const std::string &fileName, + double &x0, + double &y0, + size_t &width, + size_t &height, + double &delta) +{ + std::ifstream in( fileName.c_str() ); + + if (!in.is_open()) + { + std::cout << "VtkRaster::loadImageFromASC() - Could not open file..." << std::endl; + return NULL; + } + + ascHeader header; + + if (readASCHeader(header, in)) + { + x0 = header.x; + y0 = header.y; + width = header.ncols; + height = header.nrows; + delta = header.cellsize; + + float* values = new float[header.ncols * header.nrows * 2]; + + int col_index(0); + int noData = atoi(header.noData.c_str()); + float max_val = noData; + std::string s(""); + // read the file into a double-array + for (int j = 0; j < header.nrows; j++) + { + col_index = (header.nrows - j - 1) * header.ncols; + for (int i = 0; i < header.ncols; i++) + { + in >> s; + size_t index = 2*(col_index+i); + values[index] = static_cast<float>(strtod(replaceString(",", ".", s).c_str(),0)); + if (values[index] > max_val) + max_val = values[index]; + } + } + + // shift noData values into normal pixel-range and set transparancy values for all pixels + size_t nPixels = header.ncols * header.nrows; + for (size_t j = 0; j < nPixels; j++) + { + if (values[j*2] == noData) + { + values[j*2] = max_val; + values[j*2+1] = 0; + } + else + values[j*2+1] = max_val; + } + + in.close(); + return values; + } + return NULL; +} + +bool VtkRaster::readSurferHeader(ascHeader &header, std::ifstream &in) +{ + std::string line, tag, value; + double min, max; + + in >> tag; + + if (tag.compare("DSAA") != 0) + { + std::cout << "Error in readSurferHeader() - No Surfer file..." << std::endl; + return false; + } + else + { + in >> header.ncols >> header.nrows; + in >> min >> max; + header.x = min; + header.cellsize = (max-min)/(double)header.ncols; + + in >> min >> max; + header.y = min; + + if (ceil((max-min)/(double)header.nrows) == ceil(header.cellsize)) + header.cellsize = ceil(header.cellsize); + else + { + std::cout << "Error in readSurferHeader() - Anisotropic cellsize detected..." << std::endl; + return 0; + } + in >> min >> max; // ignore min- and max-values + + header.noData = "1.70141E+038"; + } + + return true; +} + +float* VtkRaster::loadDataFromSurfer(const std::string &fileName, + double &x0, + double &y0, + size_t &width, + size_t &height, + double &delta) +{ + std::ifstream in( fileName.c_str() ); + + if (!in.is_open()) + { + std::cout << "VtkRaster::loadImageFromSurfer() - Could not open file..." << std::endl; + return NULL; + } + + ascHeader header; + + if (readSurferHeader(header, in)) + { + x0 = header.x; + y0 = header.y; + width = header.ncols; + height = header.nrows; + delta = header.cellsize; + + float* values = new float[header.ncols * header.nrows * 2]; + + int col_index(0); + int noData = -9999; + float max_val = noData; + std::string s(""); + // read the file into a double-array + for (int j = 0; j < header.nrows; j++) + { + col_index = j * header.ncols; + for (int i = 0; i < header.ncols; i++) + { + in >> s; + if (s.compare(header.noData) == 0) + s = "-9999"; + size_t index = 2*(col_index+i); + values[index] = static_cast<float>(strtod(replaceString(",", ".", s).c_str(),0)); + if (values[index] > max_val) + max_val = values[index]; + } + } + + // shift noData values into normal pixel-range and set transparancy values for all pixels + size_t nPixels = header.ncols * header.nrows; + for (size_t j = 0; j < nPixels; j++) + { + if (values[j*2] == noData) + { + values[j*2] = max_val; + values[j*2+1] = 0; + } + else + values[j*2+1] = max_val; + } + + in.close(); + return values; + } + return NULL; +} + +#ifdef libgeotiff_FOUND +vtkImageImport* VtkRaster::loadImageFromTIFF(const std::string &fileName, + double &x0, double &y0, + double &cellsize) +{ + TIFF* tiff = XTIFFOpen(fileName.c_str(), "r"); + + if (tiff) + { + GTIF* geoTiff = GTIFNew(tiff); + + if (geoTiff) + { + int imgWidth = 0, imgHeight = 0, nImages = 0, pntCount = 0; + double* pnts = 0; + + // get actual number of images in the tiff file + do { + nImages++; + } while (TIFFReadDirectory(tiff)); + if (nImages > 1) + std::cout << "VtkRaster::loadImageFromTIFF() - File contains " << + nImages << " images. This method is not tested for this case." << + std::endl; + + // get image size + TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &imgWidth); + TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &imgHeight); + + // get cellsize + // Note: GeoTiff allows anisotropic pixels. This is not supported here and equilateral pixels are assumed. + if (TIFFGetField(tiff, GTIFF_PIXELSCALE, &pntCount, &pnts)) + { + if (pnts[0] != pnts[1]) + std::cout << + "VtkRaster::loadImageFromTIFF() - Warning: Original raster data has anisotrop pixel size!" + << std::endl; + cellsize = pnts[0]; + } + + // get upper left point / origin + if (TIFFGetField(tiff, GTIFF_TIEPOINTS, &pntCount, &pnts)) + { + x0 = pnts[3]; + y0 = pnts[4] - (imgHeight * cellsize); // the origin should be the lower left corner of the img + } + + // read pixel values + uint32* pixVal = + (uint32*) _TIFFmalloc(imgWidth * imgHeight * sizeof (uint32)); + if ((imgWidth > 0) && (imgHeight > 0)) + if (!TIFFReadRGBAImage(tiff, imgWidth, imgHeight, pixVal, 0)) + { + std::cout << + "VtkRaster::loadImageFromTIFF() - Error reading GeoTIFF file." + << std::endl; + _TIFFfree(pixVal); + GTIFFree(geoTiff); + XTIFFClose(tiff); + return false; + } + + // check for colormap + uint16 photometric; + TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric); + // read colormap + uint16* cmap_red = NULL, * cmap_green = NULL, * cmap_blue = NULL; + int colormap_used = TIFFGetField(tiff, + TIFFTAG_COLORMAP, + &cmap_red, + &cmap_green, + &cmap_blue); + + float* data = new float[imgWidth * imgHeight * 4]; + int* pxl (new int[4]); + for (int j = 0; j < imgHeight; j++) + { + int lineindex = j * imgWidth; + for (int i = 0; i < imgWidth; i++) + { // scale intensities and set nodata values to white (i.e. the background colour) + size_t pxl_idx(lineindex+i); + size_t pos = 4 * (pxl_idx); + if (photometric==1) + { + int idx = TIFFGetR(pixVal[pxl_idx]); + data[pos] = cmap_red[idx] >> 8; + data[pos+1] = cmap_green[idx] >> 8; + data[pos+2] = cmap_blue[idx] >> 8; + data[pos+3] = 1; + } + else + { + data[pos] = TIFFGetR(pixVal[pxl_idx]); + data[pos+1] = TIFFGetG(pixVal[pxl_idx]); + data[pos+2] = TIFFGetB(pixVal[pxl_idx]); + data[pos+3] = TIFFGetA(pixVal[pxl_idx]); + } + } + } + delete [] pxl; + + // set transparency values according to maximum pixel value + if (photometric==1) + { + float max_val(0); + size_t nPixels = 4*imgWidth*imgHeight; + for (size_t j = 0; j < nPixels; j++) + if (data[j]>max_val) + max_val = data[j]; + + for (size_t j = 0; j < nPixels; j+=4) + data[j+3] = max_val; + } + + vtkImageImport* image = vtkImageImport::New(); + image->SetDataOrigin(x0, y0, 0); + image->SetDataSpacing(cellsize, cellsize, cellsize); + image->SetWholeExtent(0, imgWidth-1, 0, imgHeight-1, 0, 0); + image->SetDataExtent(0, imgWidth-1, 0, imgHeight-1, 0, 0); + image->SetDataExtentToWholeExtent(); + image->SetDataScalarTypeToFloat(); + image->SetNumberOfScalarComponents(4); + image->SetImportVoidPointer(data, 0); + image->Update(); + + _TIFFfree(pixVal); + GTIFFree(geoTiff); + XTIFFClose(tiff); + return image; + } + + XTIFFClose(tiff); + std::cout << + "VtkRaster::loadImageFromTIFF() - File not recognised as GeoTIFF-Image." << + std::endl; + return NULL; + } + + std::cout << "VtkRaster::loadImageFromTIFF() - File not recognised as TIFF-Image." << + std::endl; + return NULL; +} +#endif + +vtkImageReader2* VtkRaster::loadImageFromFile(const std::string &fileName) +{ + QString file_name (QString::fromStdString(fileName)); + QFileInfo fi(file_name); + vtkImageReader2* image(NULL); + + if (fi.suffix().toLower() == "png") + image = vtkPNGReader::New(); + else if ((fi.suffix().toLower() == "jpg") || (fi.suffix().toLower() == "jpeg")) + image = vtkJPEGReader::New(); + else if (fi.suffix().toLower() == "bmp") + image = vtkBMPReader::New(); + else + { + std::cout << "VtkRaster::readImageFromFile() - File format not support, please convert to BMP, JPG, PNG or TIFF..." << std::endl; + return NULL; + } + + image->SetFileName(fileName.c_str()); + image->GetOutput()->SetScalarTypeToFloat(); + image->Update(); + return image; +} + +void VtkRaster::uint32toRGBA(const unsigned int s, int* p) +{ + p[3] = s / (256 * 256 * 256); + int r = s % (256 * 256 * 256); + p[2] = r / (256 * 256); + r %= (256 * 256); + p[1] = r / 256; + p[0] = r % 256; +} diff --git a/VtkVis/VtkRaster.h b/VtkVis/VtkRaster.h new file mode 100644 index 0000000000000000000000000000000000000000..f74797b352c78f89a009d8240aeaa4232eef91a9 --- /dev/null +++ b/VtkVis/VtkRaster.h @@ -0,0 +1,145 @@ +/** + * \file VtkRaster.h + * 2012/02/01 KR Initial implementation + * + */ +#ifndef VTKRASTER_H +#define VTKRASTER_H + +#include <fstream> + +class vtkImageAlgorithm; +class vtkImageImport; +class vtkImageReader2; + +/** + * \brief Loading raster data such as images or ArcGIS-data into VTK image data structures. + * + * The VtkRaster class enables loading of raster data such as images or ArcGIS-data. Supported image formats are ..... + * Georeferenced data can be imported via the GeoTIFF- or asc-format. + */ +class VtkRaster +{ + /// Data structure for the asc-file header. + struct ascHeader + { + int ncols; + int nrows; + double x; + double y; + double cellsize; + std::string noData; + }; + +public: + /** + * \brief Loads an image- or raster-file into an vtkImageAlgorithm-Object. + * + * Public method for loading all data formats. Internally the method automatically differentiates between + * images and georeferenced files and then calls the appropriate method for reading the file. + * \param fileName Filename of the file that should be loaded. + * \param x0 X-coordinate of the upper left corner of the data set, the default value is 0. + * \param y0 Y-coordinate of the upper left corner of the data set, the default value is 0. + * \param delta The size of each pixel in the image which is needed for correctly displaying the data, the default value is 1. + * \return The ImageAlgorithm-object. + */ + static vtkImageAlgorithm* loadImage(const std::string &fileName, + double& x0, + double& y0, + double& delta); + + /** + * \brief Loads an ASC file into a double array. + * The array alternates between pixel values and their respective alpha-values, i.e. + * result = { pixel0-value; pixel0-alpha, pixel1-value; pixel1-alpha; ... } + * + * \param fileName Filename of the file that should be loaded. + * \param x0 The x-coordinate of the origin. + * \param y0 The y-coordinate of the origin. + * \param width The width of the image. + * \param height The height of the image + * \param delta The size of each pixel in the image which is needed for correctly displaying the data. + * \return A float-array of pixel values incl. opacity (noData values are transparent) + */ + static float* loadDataFromASC(const std::string &fileName, + double &x0, + double &y0, + size_t &width, + size_t &height, + double &delta); + + /** + * \brief Loads an ASC file into a double array. + * Works exactly like loadDataFromASC(). + */ + static float* loadDataFromSurfer(const std::string &fileName, + double &x0, + double &y0, + size_t &width, + size_t &height, + double &delta); + + /** + * \brief Returns a VtkImageAlgorithm from an array of pixel values and some image meta data. + */ + static vtkImageImport* loadImageFromArray(double* data_array, + double &x0, + double &y0, + size_t &width, + size_t &height, + double &delta, + double noData); + +private: + /** + * Loads ArcGIS asc-files to a vtkImageImport object. + * \param fileName Filename of the file that should be loaded. + * \param x0 The x-coordinate of the origin. + * \param y0 The y-coordinate of the origin. + * \param delta The size of each pixel in the image which is needed for correctly displaying the data. + * \return A vtkImageImport-object (derived from vtkImageAlgorithm). + */ + static vtkImageImport* loadImageFromASC(const std::string &fileName, + double& x0, double& y0, double& delta); + + /** + * Loads ArcGIS asc-files to a QPixmap object and automatically does a contrast stretching to adjust values to 8 bit greyscale images. + * \param fileName Filename of the file that should be loaded. + * \param raster The QPixmap into which the raster data will be written. + * \param origin The upper left corner of the data set + * \param delta The size of each pixel in the image which is needed for correctly displaying the data. + * \return A vtkImageImport-object (derived from vtkImageAlgorithm). + */ +#ifdef libgeotiff_FOUND + static vtkImageImport* loadImageFromTIFF(const std::string &fileName, + double& x0, double& y0, double& delta); +#endif + + /** + * Loads image files into a QPixmap object. Since images are not geo-referenced no origin point will be returned. + * \param fileName Filename of the file that should be loaded. + * \return vtkImageReader2-object containing the image data. + */ + static vtkImageReader2* loadImageFromFile(const std::string &fileName); + + /** + * Reads the header of an ArcGIS asc-file. + * \param header The ascHeader-object into which all the information will be written. + * \param in FileInputStream used for reading the data. + * \return True if the header could be read correctly, false otherwise. + */ + static bool readASCHeader(ascHeader &header, std::ifstream &in); + + /** + * Reads the header of a Surfer grd-file. + * \param header The ascHeader-object into which all the information will be written. + * \param in FileInputStream used for reading the data. + * \return True if the header could be read correctly, false otherwise. + */ + static bool readSurferHeader(ascHeader &header, std::ifstream &in); + + /// Converts an uint32-number into a quadruple representing RGBA-colours for a pixel. + static void uint32toRGBA(const unsigned int s, int* p); +}; + +#endif //VTKRASTER_H diff --git a/VtkVis/VtkSelectionFilter.h b/VtkVis/VtkSelectionFilter.h index 41df9e5bea3b170527a4c1636c2f184015e9f2fc..c58e6f6ee650a508ded1ffc3769b205a97943e39 100644 --- a/VtkVis/VtkSelectionFilter.h +++ b/VtkVis/VtkSelectionFilter.h @@ -9,8 +9,11 @@ // ** INCLUDES ** #include "VtkAlgorithmProperties.h" + #include <vtkUnstructuredGridAlgorithm.h> +#include <vector> + class VtkSelectionFilter : public vtkUnstructuredGridAlgorithm, public VtkAlgorithmProperties { public: diff --git a/VtkVis/VtkStationSource.cpp b/VtkVis/VtkStationSource.cpp index 3af0866f47c6c4a570fd52832c9b10f27853df3b..ccf6bea5a92fd2fee143514ec5e60230adaf83cd 100644 --- a/VtkVis/VtkStationSource.cpp +++ b/VtkVis/VtkStationSource.cpp @@ -11,6 +11,7 @@ #include "VtkStationSource.h" #include "vtkObjectFactory.h" +#include <vtkDoubleArray.h> #include <vtkCellArray.h> #include <vtkCellData.h> #include <vtkInformation.h> @@ -21,6 +22,7 @@ #include <vtkPolyData.h> #include <vtkSmartPointer.h> #include <vtkStreamingDemandDrivenPipeline.h> +#include <vtkProperty.h> vtkStandardNewMacro(VtkStationSource); vtkCxxRevisionMacro(VtkStationSource, "$Revision$"); @@ -28,6 +30,7 @@ vtkCxxRevisionMacro(VtkStationSource, "$Revision$"); VtkStationSource::VtkStationSource() : _stations(NULL) { + _removable = false; // From VtkAlgorithmProperties this->SetNumberOfInputPorts(0); const GEOLIB::Color* c = GEOLIB::getRandomColor(); @@ -76,6 +79,15 @@ int VtkStationSource::RequestData( vtkInformation* request, if (nStations == 0) return 0; + bool useStationValues(false); + double sValue=static_cast<GEOLIB::Station*>((*_stations)[0])->getStationValue(); + for (size_t i = 1; i < nStations; i++) + if (static_cast<GEOLIB::Station*>((*_stations)[i])->getStationValue() != sValue) + { + useStationValues = true; + break; + } + bool isBorehole = (static_cast<GEOLIB::Station*>((*_stations)[0])->type() == GEOLIB::Station::BOREHOLE) ? true : false; @@ -100,6 +112,10 @@ int VtkStationSource::RequestData( vtkInformation* request, station_ids->SetNumberOfComponents(1); station_ids->SetName("SiteIDs"); + vtkSmartPointer<vtkDoubleArray> station_values = vtkSmartPointer<vtkDoubleArray>::New(); + station_values->SetNumberOfComponents(1); + station_values->SetName("StationValue"); + vtkSmartPointer<vtkIntArray> strat_ids = vtkSmartPointer<vtkIntArray>::New(); strat_ids->SetNumberOfComponents(1); strat_ids->SetName("Stratigraphies"); @@ -114,6 +130,8 @@ int VtkStationSource::RequestData( vtkInformation* request, double coords[3] = { (*(*it))[0], (*(*it))[1], (*(*it))[2] }; vtkIdType sid = newStations->InsertNextPoint(coords); station_ids->InsertNextValue(site_count); + if (useStationValues) + station_values->InsertNextValue(static_cast<GEOLIB::Station*>(*it)->getStationValue()); if (!isBorehole) newVerts->InsertNextCell(1, &sid); @@ -137,6 +155,8 @@ int VtkStationSource::RequestData( vtkInformation* request, newLines->InsertCellPoint(lastMaxIndex + 1); //end of boreholelayer lastMaxIndex++; strat_ids->InsertNextValue(this->GetIndexByName(soilNames[i])); + if (useStationValues) + station_values->InsertNextValue(static_cast<GEOLIB::Station*>(*it)->getStationValue()); } lastMaxIndex++; } @@ -157,7 +177,9 @@ int VtkStationSource::RequestData( vtkInformation* request, output->GetCellData()->SetActiveAttribute("Stratigraphies", vtkDataSetAttributes::SCALARS); } - + if (useStationValues) + output->GetPointData()->AddArray(station_values); + return 1; } @@ -191,8 +213,9 @@ size_t VtkStationSource::GetIndexByName( std::string name ) if (it->second > max_key) max_key = it->second; } - vtkIdType new_index(max_key + 1); - std::cout << "Key \"" << name << "\" not found in color lookup table..." << std::endl; + + vtkIdType new_index = (_id_map.empty()) ? 0 : (max_key+1); + std::cout << "Key \"" << name << "\" (Index " << new_index << ") not found in color lookup table..." << std::endl; _id_map.insert(std::pair<std::string, vtkIdType>(name, new_index)); return new_index; } diff --git a/VtkVis/VtkSurfacesSource.cpp b/VtkVis/VtkSurfacesSource.cpp index 3e0a92165089ecf43b5b604a2f05475be4cdec60..fc7c47b42b09551aebcce43e407770ea839af8f7 100644 --- a/VtkVis/VtkSurfacesSource.cpp +++ b/VtkVis/VtkSurfacesSource.cpp @@ -20,6 +20,7 @@ #include <vtkPolygon.h> #include <vtkSmartPointer.h> #include <vtkStreamingDemandDrivenPipeline.h> +#include <vtkProperty.h> vtkStandardNewMacro(VtkSurfacesSource); vtkCxxRevisionMacro(VtkSurfacesSource, "$Revision$"); @@ -27,6 +28,7 @@ vtkCxxRevisionMacro(VtkSurfacesSource, "$Revision$"); VtkSurfacesSource::VtkSurfacesSource() : _surfaces(NULL) { + _removable = false; // From VtkAlgorithmProperties this->SetNumberOfInputPorts(0); //this->SetColorBySurface(true); diff --git a/VtkVis/VtkTextureOnSurfaceFilter.cpp b/VtkVis/VtkTextureOnSurfaceFilter.cpp index a7fe3d3086c09c0b64f1fd102b6828ec8f7fa855..e27219111483e6336778cfafb1d74d7518cc53a6 100644 --- a/VtkVis/VtkTextureOnSurfaceFilter.cpp +++ b/VtkVis/VtkTextureOnSurfaceFilter.cpp @@ -15,13 +15,15 @@ #include <vtkPointData.h> #include <vtkSmartPointer.h> #include <vtkStreamingDemandDrivenPipeline.h> +#include <vtkImageShiftScale.h> +#include <vtkImageAlgorithm.h> +#include <vtkProperty.h> +#include <vtkTexture.h> #include "MathTools.h" #include "VtkTextureOnSurfaceFilter.h" #include "VtkVisHelper.h" -#include <QImage> - vtkStandardNewMacro(VtkTextureOnSurfaceFilter); vtkCxxRevisionMacro(VtkTextureOnSurfaceFilter, "$Revision$"); @@ -67,18 +69,42 @@ int VtkTextureOnSurfaceFilter::RequestData( vtkInformation* request, //calculate texture coordinates vtkPoints* points = input->GetPoints(); vtkSmartPointer<vtkFloatArray> textureCoordinates = vtkSmartPointer<vtkFloatArray>::New(); - textureCoordinates->SetNumberOfComponents(3); + textureCoordinates->SetNumberOfComponents(2); textureCoordinates->SetName("TextureCoordinates"); size_t nPoints = points->GetNumberOfPoints(); +/* // adaptation for netcdf-curtain for TERENO Demo + double dist(0.0); + for (size_t i = 0; i < nPoints; i++) + { + double coords[3]; + if ((i==0) || (i==173)) + { + if (i==0) dist=0; + } + else + { + points->GetPoint(i-1, coords); + GEOLIB::Point* pnt = new GEOLIB::Point(coords); + points->GetPoint(i, coords); + GEOLIB::Point* pnt2 = new GEOLIB::Point(coords); + if (i<173) + dist += sqrt(MathLib::sqrDist(pnt, pnt2)); + else + dist -= sqrt(MathLib::sqrDist(pnt, pnt2)); + } + points->GetPoint(i, coords); + double x = MathLib::normalize(0, 8404, dist); + double z = MathLib::normalize(-79.5, 1.5, coords[2]); + float newcoords[2] = {x, z}; + textureCoordinates->InsertNextTuple(newcoords); + } +*/ for (size_t i = 0; i < nPoints; i++) { double coords[3]; points->GetPoint(i, coords); - float newcoords[3] = - {MathLib::normalize(min.first, max.first, coords[0]), MathLib::normalize(min.second, - max.second, - coords[1]), - 0 /*coords[2]*/ }; + float newcoords[2] = { MathLib::normalize(min.first, max.first, coords[0]), + MathLib::normalize(min.second,max.second, coords[1])}; textureCoordinates->InsertNextTuple(newcoords); } @@ -93,14 +119,29 @@ int VtkTextureOnSurfaceFilter::RequestData( vtkInformation* request, return 1; } -void VtkTextureOnSurfaceFilter::SetRaster(QImage &img, - std::pair<float, float> origin, +void VtkTextureOnSurfaceFilter::SetRaster(vtkImageAlgorithm* img, + double x0, double y0, double scalingFactor) { - _origin = origin; + double range[2]; + img->Update(); + img->GetOutput()->GetPointData()->GetScalars()->GetRange(range); + vtkSmartPointer<vtkImageShiftScale> scale = vtkSmartPointer<vtkImageShiftScale>::New(); + scale->SetInputConnection(img->GetOutputPort()); + scale->SetShift(-range[0]); + scale->SetScale(255.0/(range[1]-range[0])); + scale->SetOutputScalarTypeToUnsignedChar(); // Comment this out to get colored grayscale textures + scale->Update(); + + vtkTexture* texture = vtkTexture::New(); + texture->InterpolateOff(); + texture->RepeatOff(); + // texture->EdgeClampOn(); // does not work + texture->SetInput(scale->GetOutput()); + this->SetTexture(texture); + + _origin = std::pair<float, float>(static_cast<float>(x0), static_cast<float>(y0)); _scalingFactor = scalingFactor; - QImage raster = img.transformed(QTransform(1, 0, 0, -1, 0, 0), Qt::FastTransformation); - this->SetTexture(VtkVisHelper::QImageToVtkTexture(raster)); } void VtkTextureOnSurfaceFilter::SetUserProperty( QString name, QVariant value ) diff --git a/VtkVis/VtkTextureOnSurfaceFilter.h b/VtkVis/VtkTextureOnSurfaceFilter.h index ad47c1b55f66f9ed8607bbace3a6980b40952be3..2db29b931b974aaccd71ce53736d1d3b236e6eab 100644 --- a/VtkVis/VtkTextureOnSurfaceFilter.h +++ b/VtkVis/VtkTextureOnSurfaceFilter.h @@ -13,6 +13,7 @@ #include <vtkPolyDataAlgorithm.h> class QImage; +class vtkImageAlgorithm; /** * \brief Filter class for assigning a texture to a surface. @@ -38,7 +39,7 @@ public: void PrintSelf(ostream& os, vtkIndent indent); /// Sets the raster/image to be used as a texture map - void SetRaster(QImage &img, std::pair<float, float> origin, double scalingFactor); + void SetRaster(vtkImageAlgorithm* img, double x0, double y0, double scalingFactor); virtual void SetUserProperty(QString name, QVariant value); diff --git a/VtkVis/VtkVisImageItem.cpp b/VtkVis/VtkVisImageItem.cpp index 11e784c0741edca32b11f3ea789df49dc14cddd5..b523a0116e915655d611987e4daacbca8859ae98 100644 --- a/VtkVis/VtkVisImageItem.cpp +++ b/VtkVis/VtkVisImageItem.cpp @@ -6,13 +6,17 @@ // ** INCLUDES ** #include "VtkAlgorithmProperties.h" #include "VtkVisImageItem.h" +#include "VtkGeoImageSource.h" #include <vtkActor.h> #include <vtkDataSetMapper.h> #include <vtkImageAlgorithm.h> #include <vtkImageChangeInformation.h> +#include <vtkImageData.h> +#include <vtkPointData.h> #include <vtkRenderer.h> #include <vtkSmartPointer.h> +#include <vtkImageShiftScale.h> // export #include <vtkImageActor.h> @@ -39,8 +43,30 @@ VtkVisImageItem::~VtkVisImageItem() void VtkVisImageItem::Initialize(vtkRenderer* renderer) { + vtkImageAlgorithm* img = dynamic_cast<vtkImageAlgorithm*>(_algorithm); + img->Update(); + //VtkGeoImageSource* img = dynamic_cast<VtkGeoImageSource*>(_algorithm); + + double origin[3]; + double spacing[3]; + double range[2]; + img->GetOutput()->GetOrigin(origin); + img->GetOutput()->GetSpacing(spacing); + //img->getRange(range); + img->GetOutput()->GetPointData()->GetScalars()->GetRange(range); + vtkImageShiftScale* scale = vtkImageShiftScale::New(); + scale->SetOutputScalarTypeToUnsignedChar(); + scale->SetInputConnection(img->GetOutputPort()); + scale->SetShift(-range[0]); + scale->SetScale(255.0/(range[1]-range[0])); + _transformFilter = vtkImageChangeInformation::New(); - _transformFilter->SetInputConnection(_algorithm->GetOutputPort()); + _transformFilter->SetInputConnection(scale->GetOutputPort()); + //double origin[3]; + //img->getOrigin(origin); + //double spacing = img->getSpacing(); + //_transformFilter->SetOutputOrigin(origin2); + //_transformFilter->SetOutputSpacing(spacing2); _transformFilter->Update(); _renderer = renderer; diff --git a/VtkVis/VtkVisPipeline.cpp b/VtkVis/VtkVisPipeline.cpp index 6ed962d5d940f25f9368bf6c035052c8c9987346..c44f094baef57a00c5633543f93d85ceb3f952a8 100644 --- a/VtkVis/VtkVisPipeline.cpp +++ b/VtkVis/VtkVisPipeline.cpp @@ -240,6 +240,21 @@ void VtkVisPipeline::setGlobalSuperelevation(double factor) const emit vtkVisPipelineChanged(); } +void VtkVisPipeline::setGlobalBackfaceCulling(bool enable) const +{ + // iterate over all source items + for (int i = 0; i < _rootItem->childCount(); ++i) + { + VtkVisPipelineItem* item = static_cast<VtkVisPipelineItem*>(_rootItem->child(i)); + item->setBackfaceCulling(enable); + + // recursively set on all child items + item->setBackfaceCullingOnChildren(enable); + } + + emit vtkVisPipelineChanged(); +} + void VtkVisPipeline::addPipelineItem(GeoTreeModel* model, const std::string &name, GEOLIB::GEOTYPE type) @@ -283,10 +298,8 @@ QModelIndex VtkVisPipeline::addPipelineItem(VtkVisPipelineItem* item, const QMod _actorMap.insert(item->actor(), newIndex); // Do not interpolate images -#ifndef OGS_USE_OPENSG if (dynamic_cast<vtkImageAlgorithm*>(item->algorithm())) static_cast<vtkImageActor*>(item->actor())->InterpolateOff(); -#endif // OGS_USE_OPENSG reset(); emit vtkVisPipelineChanged(); @@ -299,10 +312,6 @@ QModelIndex VtkVisPipeline::addPipelineItem( vtkAlgorithm* source, { TreeItem* parentItem = getItem(parent); - // If the parent is not the root TreeItem - //if (parent.isValid()) - // VtkVisPipelineItem* visParentItem = static_cast<VtkVisPipelineItem*>(parentItem); - QList<QVariant> itemData; QString itemName; if (!parent.isValid()) // if source object diff --git a/VtkVis/VtkVisPipeline.h b/VtkVis/VtkVisPipeline.h index 8fbefb0d561894b0b00c10515ed6307c1d4c440f..1594232a9285e8922057f3afe7f4789c75497a3c 100644 --- a/VtkVis/VtkVisPipeline.h +++ b/VtkVis/VtkVisPipeline.h @@ -82,6 +82,9 @@ public: /// the factor on other items to 1. void setGlobalSuperelevation(double factor) const; + /// \brief Enables / disables backface culling on all actors. + void setGlobalBackfaceCulling(bool enable) const; + public slots: /// \brief Adds the given Model to the pipeline. void addPipelineItem(MshModel* model, const QModelIndex &idx); diff --git a/VtkVis/VtkVisPipelineItem.cpp b/VtkVis/VtkVisPipelineItem.cpp index cc2fe2cb975855ddcfe74f61f6d30c051d3d66e5..fd79579b341071ff191704bdf941d59b96c94de3 100644 --- a/VtkVis/VtkVisPipelineItem.cpp +++ b/VtkVis/VtkVisPipelineItem.cpp @@ -8,6 +8,7 @@ // ** INCLUDES ** #include "VtkAlgorithmProperties.h" #include "VtkVisPipelineItem.h" +#include "VtkCompositeFilter.h" #include "QVtkDataSetMapper.h" #include <vtkActor.h> @@ -18,15 +19,12 @@ #include <vtkRenderer.h> #include <vtkSmartPointer.h> #include <vtkTextureMapToPlane.h> - #include <vtkGenericDataObjectWriter.h> - -#include <QMessageBox> - -#include "VtkCompositeFilter.h" - #include <vtkCellData.h> #include <vtkPointData.h> +#include <vtkImageActor.h> + +#include <QMessageBox> #ifdef OGS_USE_OPENSG #include "vtkOsgConverter.h" @@ -37,7 +35,7 @@ VtkVisPipelineItem::VtkVisPipelineItem( vtkAlgorithm* algorithm, TreeItem* parentItem, const QList<QVariant> data /*= QList<QVariant>()*/) : TreeItem(data, parentItem), _actor(NULL), _algorithm(algorithm), - _renderer(NULL),_compositeFilter(NULL) + _renderer(NULL), _compositeFilter(NULL), _vtkProps(NULL) { VtkVisPipelineItem* visParentItem = dynamic_cast<VtkVisPipelineItem*>(parentItem); if (parentItem->parentItem()) @@ -47,7 +45,8 @@ VtkVisPipelineItem::VtkVisPipelineItem( VtkVisPipelineItem::VtkVisPipelineItem( VtkCompositeFilter* compositeFilter, TreeItem* parentItem, const QList<QVariant> data /*= QList<QVariant>()*/) - : TreeItem(data, parentItem), _actor(NULL), _renderer(NULL), _compositeFilter(compositeFilter) + : TreeItem(data, parentItem), _actor(NULL), _renderer(NULL), _compositeFilter(compositeFilter), + _vtkProps(NULL) { _algorithm = _compositeFilter->GetOutputAlgorithm(); } @@ -105,15 +104,21 @@ int VtkVisPipelineItem::writeToFile(const std::string &filename) const if (filename.substr(filename.size() - 4).find("os") != std::string::npos) { #ifdef OGS_USE_OPENSG - vtkOsgConverter osgConverter(static_cast<vtkActor*>(_actor)); - if(osgConverter.WriteAnActor()) - OSG::SceneFileHandler::the().write( - osgConverter.GetOsgNode(), filename.c_str()); -#else + if(!dynamic_cast<vtkImageActor*>(_actor)) + { + vtkOsgConverter osgConverter(static_cast<vtkActor*>(_actor)); + if(osgConverter.WriteAnActor()) + OSG::SceneFileHandler::the().write( + osgConverter.GetOsgNode(), filename.c_str()); + } + else + QMessageBox::warning(NULL, "Conversion to OpenSG not possible", + "It is not possible to convert an vtkImageData based object\nto OpenSG. If you want to convert raster data import it via \" File / Import / Raster Files as PolyData\"!"); +#else QMessageBox::warning( - NULL, - "Functionality not implemented", - "Sorry but this program was not compiled with OpenSG support."); + NULL, + "Functionality not implemented", + "Sorry but this program was not compiled with OpenSG support."); #endif return 0; } @@ -156,3 +161,40 @@ void VtkVisPipelineItem::setScaleOnChildren(double x, double y, double z) const child->setScale(x, y, z); } } + +void VtkVisPipelineItem::setBackfaceCulling(bool enable) const +{ + // Reimplemented in subclass + (void)enable; +} + +void VtkVisPipelineItem::setBackfaceCullingOnChildren(bool enable) const +{ + for (int i = 0; i < this->childCount(); ++i) + { + VtkVisPipelineItem* child = this->child(i); + child->setBackfaceCulling((int)enable); + child->setBackfaceCullingOnChildren((int)enable); + } +} + +QStringList VtkVisPipelineItem::getScalarArrayNames() const +{ + vtkDataSet* dataSet = vtkDataSet::SafeDownCast(this->algorithm()->GetOutputDataObject(0)); + QStringList dataSetAttributesList; + if (dataSet) + { + vtkPointData* pointData = dataSet->GetPointData(); + //std::cout << " #point data arrays: " << pointData->GetNumberOfArrays() << std::endl; + for (int i = 0; i < pointData->GetNumberOfArrays(); i++) + //std::cout << " Name: " << pointData->GetArrayName(i) << std::endl; + dataSetAttributesList.push_back(QString("P-") + pointData->GetArrayName(i)); + + vtkCellData* cellData = dataSet->GetCellData(); + //std::cout << " #cell data arrays: " << cellData->GetNumberOfArrays() << std::endl; + for (int i = 0; i < cellData->GetNumberOfArrays(); i++) + //std::cout << " Name: " << cellData->GetArrayName(i) << std::endl; + dataSetAttributesList.push_back(QString("C-") + cellData->GetArrayName(i)); + } + return dataSetAttributesList; +} \ No newline at end of file diff --git a/VtkVis/VtkVisPipelineItem.h b/VtkVis/VtkVisPipelineItem.h index 9c07af2e58b15a0cb94a1b14f4adbe60b2e9740e..dc35c1ff980226a123a07645d8da64cddec9a7ca 100644 --- a/VtkVis/VtkVisPipelineItem.h +++ b/VtkVis/VtkVisPipelineItem.h @@ -17,6 +17,7 @@ #include <QString> #include <QVariant> +class QStringList; class vtkAlgorithm; class vtkDataSetAttributes; class vtkPointSet; @@ -83,7 +84,8 @@ public: /// @brief Sets the visibility of the VTK object in the visualization. void setVisible(bool visible); - /// @brief Writes this algorithm's vtkDataSet (i.e. vtkPolyData or vtkUnstructuredGrid) to a vtk-file. + /// @brief Writes this algorithm's vtkDataSet (i.e. vtkPolyData or vtkUnstructuredGrid) + /// to a vtk-file. int writeToFile(const std::string &filename) const; /** @@ -92,6 +94,10 @@ public: */ virtual void setScale(double x, double y, double z) const; + /// @brief Sets the geometry and date scaling recursively on all children of + /// this item. + void setScaleOnChildren(double x, double y, double z) const; + /** * @brief Translates the item in visualisation-space. * This function is empty and needs to be implemented by derived classes. @@ -104,9 +110,18 @@ public: */ virtual vtkAlgorithm* transformFilter() const = 0; - /// @brief Sets the geometry and date scaling recursively on all children of - /// this item. - void setScaleOnChildren(double x, double y, double z) const; + /// @brief Enables / disables backface culling. + virtual void setBackfaceCulling(bool enable) const; + + /// @brief Enables / disables backface culling on all children. + void setBackfaceCullingOnChildren(bool enable) const; + + /// @brief Returns a list of array names prefixed with P- or C- + /// for point and cell data. + QStringList getScalarArrayNames() const; + + /// @brief Returns the VtkAlgorithmProperties. + VtkAlgorithmProperties* getVtkProperties() const { return _vtkProps; }; protected: vtkProp3D* _actor; @@ -114,6 +129,10 @@ protected: vtkRenderer* _renderer; VtkCompositeFilter* _compositeFilter; + /// @brief The active VtkAlgorithmProperties. + /// From algorithm, compositeFilter, or copied from parent + VtkAlgorithmProperties* _vtkProps; + /** * Selects the appropriate VTK-Writer object and writes the object to a file with the given name. * This function is empty and needs to be implemented by derived classes. diff --git a/VtkVis/VtkVisPipelineView.cpp b/VtkVis/VtkVisPipelineView.cpp index 32aae875e0935c94c1f97b6da42c214606b3fd22..edbf601c73b26f790e0ca591f1c70d96ef6a1a29 100644 --- a/VtkVis/VtkVisPipelineView.cpp +++ b/VtkVis/VtkVisPipelineView.cpp @@ -11,6 +11,7 @@ #include "CheckboxDelegate.h" #include "VtkVisPipeline.h" #include "VtkVisPipelineItem.h" +#include "VtkVisPointSetItem.h" #include <vtkDataSetMapper.h> #include <vtkProp3D.h> @@ -21,21 +22,23 @@ #include <QHeaderView> #include <QMenu> #include <QSettings> +#include <QMessageBox> //image to mesh conversion +#include "msh_mesh.h" +#include "GridAdapter.h" #include "VtkGeoImageSource.h" +#include <vtkImageData.h> #include "MeshFromRasterDialog.h" #include <vtkDataObject.h> -#include <vtkImageData.h> #include <vtkSmartPointer.h> - -#include "msh_mesh.h" #include <vtkGenericDataObjectReader.h> #include <vtkTransformFilter.h> #include <vtkUnstructuredGrid.h> #include <vtkUnstructuredGridAlgorithm.h> #include <vtkXMLUnstructuredGridReader.h> + VtkVisPipelineView::VtkVisPipelineView( QWidget* parent /*= 0*/ ) : QTreeView(parent) { @@ -62,13 +65,10 @@ void VtkVisPipelineView::contextMenuEvent( QContextMenuEvent* event ) if (index.isValid()) { // check object type - vtkAlgorithm* algorithm = - static_cast<VtkVisPipelineItem*>(static_cast<VtkVisPipeline*>(this->model()) - -> - getItem(this->selectionModel()-> - currentIndex()))->algorithm(); - int objectType = algorithm->GetOutputDataObject(0)->GetDataObjectType(); - VtkAlgorithmProperties* vtkProps = dynamic_cast<VtkAlgorithmProperties*>(algorithm); + VtkVisPipelineItem* item = static_cast<VtkVisPipelineItem*>(static_cast<VtkVisPipeline*>( + this->model())->getItem(this->selectionModel()->currentIndex())); + int objectType = item->algorithm()->GetOutputDataObject(0)->GetDataObjectType(); + VtkAlgorithmProperties* vtkProps = item->getVtkProperties(); bool isSourceItem = (this->selectionModel()->currentIndex().parent().isValid()) ? 0 : 1; @@ -79,7 +79,8 @@ void VtkVisPipelineView::contextMenuEvent( QContextMenuEvent* event ) QAction* addMeshingAction(NULL); if (objectType == VTK_IMAGE_DATA) { - isSourceItem = false; // this exception is needed as image object are only displayed in the vis-pipeline + // this exception is needed as image object are only displayed in the vis-pipeline + isSourceItem = false; addMeshingAction = menu.addAction("Convert Image to Mesh..."); connect(addMeshingAction, SIGNAL(triggered()), this, SLOT(showImageToMeshConversionDialog())); @@ -101,7 +102,7 @@ void VtkVisPipelineView::contextMenuEvent( QContextMenuEvent* event ) QAction* exportVtkAction = menu.addAction("Export as VTK"); QAction* exportOsgAction = menu.addAction("Export as OpenSG"); QAction* removeAction = NULL; - if (!isSourceItem || vtkProps == NULL) + if (!isSourceItem || vtkProps->IsRemovable()) { removeAction = menu.addAction("Remove"); connect(removeAction, SIGNAL(triggered()), this, @@ -175,20 +176,22 @@ void VtkVisPipelineView::constructMeshFromImage(QString msh_name, MshElemType::t getItem(this->selectionModel()->currentIndex()))->algorithm(); vtkSmartPointer<VtkGeoImageSource> imageSource = VtkGeoImageSource::SafeDownCast(algorithm); - vtkSmartPointer<vtkImageData> image = imageSource->GetOutput(); + double origin[3]; + imageSource->GetOutput()->GetOrigin(origin); + double spacing[3]; + imageSource->GetOutput()->GetSpacing(spacing); - MeshLib::CFEMesh* mesh = VtkMeshConverter::convertImgToMesh(image, imageSource->getOrigin(), - imageSource->getSpacing(), - element_type, intensity_type); - std::string new_mesh_name(msh_name.toStdString()); - emit meshAdded(mesh, new_mesh_name); + GridAdapter* mesh = VtkMeshConverter::convertImgToMesh(imageSource->GetOutput(), origin, spacing[0], element_type, intensity_type); + mesh->setName(msh_name.toStdString()); + emit meshAdded(mesh); } void VtkVisPipelineView::convertVTKToOGSMesh() { - vtkSmartPointer<vtkAlgorithm> algorithm = - static_cast<VtkVisPipelineItem*>(static_cast<VtkVisPipeline*>(this->model())->getItem( - this->selectionModel()->currentIndex()))->algorithm(); + VtkVisPipelineItem* item = static_cast<VtkVisPipelineItem*>(static_cast<VtkVisPipeline*>(this->model())->getItem( + this->selectionModel()->currentIndex())); + vtkSmartPointer<vtkAlgorithm> algorithm = item->algorithm(); + vtkUnstructuredGrid* grid(NULL); vtkUnstructuredGridAlgorithm* ugAlg = vtkUnstructuredGridAlgorithm::SafeDownCast(algorithm); @@ -207,9 +210,9 @@ void VtkVisPipelineView::convertVTKToOGSMesh() grid = vtkUnstructuredGrid::SafeDownCast(xmlReader->GetOutput()); } } - MeshLib::CFEMesh* mesh = VtkMeshConverter::convertUnstructuredGrid(grid); - std::string msh_name("NewMesh"); - emit meshAdded(mesh, msh_name); + GridAdapter* mesh = VtkMeshConverter::convertUnstructuredGrid(grid); + mesh->setName(item->data(0).toString().toStdString()); + emit meshAdded(mesh); } void VtkVisPipelineView::selectionChanged( const QItemSelection &selected, @@ -258,23 +261,28 @@ void VtkVisPipelineView::addColorTable() const QString array_name = item->GetActiveAttribute(); QSettings settings("UFZ", "OpenGeoSys-5"); - QString fileName = QFileDialog::getOpenFileName(this, "Select color table", - settings.value( - "lastOpenedTextureFileDirectory"). - toString(), - "Color table files (*.lut);;"); - QFileInfo fi(fileName); + QString filename = QFileDialog::getOpenFileName(this, "Select color table", + settings.value("lastOpenedLutFileDirectory"). toString(), + "Color table files (*.xml);;"); + QFileInfo fi(filename); - if (fi.suffix().toLower() == "lut") + if (fi.suffix().toLower() == "xml") { - VtkAlgorithmProperties* props = - dynamic_cast<VtkAlgorithmProperties*>(item->algorithm()); - if (props) + VtkVisPointSetItem* pointSetItem = dynamic_cast<VtkVisPointSetItem*>(item); + if (pointSetItem) { - const std::string file (fileName.toStdString()); - props->SetLookUpTable(array_name, file); - item->SetActiveAttribute(array_name); - emit requestViewUpdate(); + VtkAlgorithmProperties* props = pointSetItem->getVtkProperties(); + if (props) + { + props->SetLookUpTable(array_name, filename); + item->SetActiveAttribute(array_name); + emit requestViewUpdate(); + } } + else + QMessageBox::warning(NULL, "Color lookup table could not be applied.", + "Color lookup tables can only be applied to VtkVisPointSetItem."); + QDir dir = QDir(filename); + settings.setValue("lastOpenedLutFileDirectory", dir.absolutePath()); } } diff --git a/VtkVis/VtkVisPipelineView.h b/VtkVis/VtkVisPipelineView.h index e2d28ae33abe760bfb9f5d4e1ceb9f75bb959381..652f121398c394bf4b547d567f2f43fd9d281257 100644 --- a/VtkVis/VtkVisPipelineView.h +++ b/VtkVis/VtkVisPipelineView.h @@ -78,7 +78,7 @@ signals: void itemSelected(VtkVisPipelineItem*); void actorSelected(vtkProp3D*); void dataObjectSelected(vtkDataObject*); - void meshAdded(MeshLib::CFEMesh*, std::string&); + void meshAdded(GridAdapter*); }; #endif // VTKVISPIPELINEVIEW_H diff --git a/VtkVis/VtkVisPointSetItem.cpp b/VtkVis/VtkVisPointSetItem.cpp index 39f6ec6af2ea7eac4ae306398c5ccdd3b71269ab..70283bcb10e1a526450fb90a1f287379022a47f5 100644 --- a/VtkVis/VtkVisPointSetItem.cpp +++ b/VtkVis/VtkVisPointSetItem.cpp @@ -6,6 +6,8 @@ // ** INCLUDES ** #include "VtkAlgorithmProperties.h" #include "VtkVisPointSetItem.h" +#include "VtkCompositeFilter.h" +#include "VtkCompositeThresholdFilter.h" #include <limits> @@ -19,9 +21,13 @@ #include <vtkSmartPointer.h> #include <vtkTransform.h> #include <vtkTransformFilter.h> +#include <vtkProperty.h> +#include <vtkLookupTable.h> #include <QObject> #include <QRegExp> +#include <QSettings> +#include <QStringList> // export test #include <vtkPolyDataAlgorithm.h> @@ -37,7 +43,7 @@ VtkVisPointSetItem::VtkVisPointSetItem( vtkAlgorithm* algorithm, TreeItem* parentItem, const QList<QVariant> data /*= QList<QVariant>()*/) : VtkVisPipelineItem(algorithm, parentItem, data), _mapper(NULL), - _transformFilter(NULL), _activeAttribute("") + _transformFilter(NULL), _onPointData(true), _activeArrayName("") { VtkVisPipelineItem* visParentItem = dynamic_cast<VtkVisPipelineItem*>(parentItem); if (parentItem->parentItem()) @@ -60,7 +66,7 @@ VtkVisPointSetItem::VtkVisPointSetItem( VtkCompositeFilter* compositeFilter, TreeItem* parentItem, const QList<QVariant> data /*= QList<QVariant>()*/) : VtkVisPipelineItem(compositeFilter, parentItem, data), _mapper(NULL), - _transformFilter(NULL), _activeAttribute("") + _transformFilter(NULL), _onPointData(true), _activeArrayName("") { } @@ -69,10 +75,13 @@ VtkVisPointSetItem::~VtkVisPointSetItem() _transformFilter->Delete(); _mapper->Delete(); } +const QString VtkVisPointSetItem::GetActiveAttribute() const +{ + return _vtkProps->GetActiveAttribute(); +} void VtkVisPointSetItem::Initialize(vtkRenderer* renderer) { - _activeAttribute = ""; _transformFilter = vtkTransformFilter::New(); vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); transform->Identity(); @@ -90,48 +99,69 @@ void VtkVisPointSetItem::Initialize(vtkRenderer* renderer) static_cast<vtkActor*>(_actor)->SetMapper(_mapper); _renderer->AddActor(_actor); - // Set pre-set properties + // Determine the right pre-set properties + // Order is: _algorithm, _compositeFilter, create a new one with props copied from parent VtkAlgorithmProperties* vtkProps = dynamic_cast<VtkAlgorithmProperties*>(_algorithm); - if (vtkProps) - setVtkProperties(vtkProps); - - // Copy properties from parent - else + if (!vtkProps) { - VtkVisPipelineItem* parentItem = dynamic_cast<VtkVisPipelineItem*>(this->parentItem()); - while (parentItem) + vtkProps = dynamic_cast<VtkAlgorithmProperties*>(_compositeFilter); + + // Copy properties from parent or create a new VtkAlgorithmProperties + if (!vtkProps) { - VtkAlgorithmProperties* parentProps = - dynamic_cast<VtkAlgorithmProperties*>(parentItem->algorithm()); - if (parentProps) + VtkVisPipelineItem* parentItem = dynamic_cast<VtkVisPipelineItem*>(this->parentItem()); + while (parentItem) { - VtkAlgorithmProperties* newProps = new VtkAlgorithmProperties(); - newProps->SetScalarVisibility(parentProps->GetScalarVisibility()); - newProps->SetTexture(parentProps->GetTexture()); - setVtkProperties(newProps); - vtkProps = newProps; - parentItem = NULL; + VtkAlgorithmProperties* parentProps = NULL; + if(dynamic_cast<VtkVisPointSetItem*>(parentItem)) + parentProps = dynamic_cast<VtkVisPointSetItem*>(parentItem)->getVtkProperties(); + if (parentProps) + { + vtkProps = new VtkAlgorithmProperties(); // TODO memory leak? + vtkProps->SetScalarVisibility(parentProps->GetScalarVisibility()); + vtkProps->SetTexture(parentProps->GetTexture()); + vtkProps->SetActiveAttribute(parentProps->GetActiveAttribute()); + parentItem = NULL; + } + else + parentItem = dynamic_cast<VtkVisPipelineItem*>(parentItem->parentItem()); } - else - parentItem = dynamic_cast<VtkVisPipelineItem*>(parentItem->parentItem()); + + // Has no parents + if (!vtkProps) + vtkProps = new VtkAlgorithmProperties(); // TODO memory leak? } } - - // Set active scalar to the desired one from VtkAlgorithmProperties - // or to match those of the parent. - if (vtkProps) + _vtkProps = vtkProps; + + if (vtkProps->GetActiveAttribute().length() == 0) { - if (vtkProps->GetActiveAttribute().length() > 0) - this->SetActiveAttribute(vtkProps->GetActiveAttribute()); + // Get first scalar and set it to active + QStringList arrayNames = this->getScalarArrayNames(); + if (arrayNames.length() > 0) + vtkProps->SetActiveAttribute(arrayNames[0]); else - { - VtkVisPointSetItem* visParentItem = - dynamic_cast<VtkVisPointSetItem*>(this->parentItem()); - if (visParentItem) - this->SetActiveAttribute(visParentItem->GetActiveAttribute()); - if (vtkProps->GetTexture() != NULL) - this->SetActiveAttribute("Solid Color"); - } + vtkProps->SetActiveAttribute("Solid Color"); + } + this->setVtkProperties(vtkProps); + this->SetActiveAttribute(vtkProps->GetActiveAttribute()); + + + // Set global backface culling + QSettings settings("UFZ, OpenGeoSys-5"); + bool backfaceCulling = settings.value("globalCullBackfaces", 0).toBool(); + this->setBackfaceCulling(backfaceCulling); + + // Set the correct threshold range + if (dynamic_cast<VtkCompositeThresholdFilter*>(this->_compositeFilter)) + { + double range[2]; + this->GetRangeForActiveAttribute(range); + QList<QVariant> thresholdRangeList; + thresholdRangeList.push_back(range[0]); + thresholdRangeList.push_back(range[1]); + dynamic_cast<VtkCompositeFilter*>(this->_compositeFilter) + ->SetUserVectorProperty("Threshold Between", thresholdRangeList); } } @@ -145,8 +175,6 @@ void VtkVisPointSetItem::setVtkProperties(VtkAlgorithmProperties* vtkProps) QObject::connect(vtkProps, SIGNAL(ScalarVisibilityChanged(bool)), _mapper, SLOT(SetScalarVisibility(bool))); - this->setLookupTableForActiveScalar(); - vtkActor* actor = dynamic_cast<vtkActor*>(_actor); if (actor) { @@ -203,14 +231,13 @@ int VtkVisPointSetItem::callVTKWriter(vtkAlgorithm* algorithm, const std::string void VtkVisPointSetItem::SetActiveAttribute( const QString& name ) { // Get type by identifier - bool onPointData = true; if (name.contains(QRegExp("^P-"))) - onPointData = true; + _onPointData = true; else if (name.contains(QRegExp("^C-"))) - onPointData = false; + _onPointData = false; else if (name.contains("Solid Color")) { - _activeAttribute = "Solid Color"; + _vtkProps->SetActiveAttribute("Solid Color"); _mapper->ScalarVisibilityOff(); return; } @@ -218,25 +245,28 @@ void VtkVisPointSetItem::SetActiveAttribute( const QString& name ) return; // Remove type identifier - std::string strippedName = QString(name).remove(0, 2).toStdString(); - const char* charName = strippedName.c_str(); + _activeArrayName = QString(name).remove(0, 2).toStdString(); + const char* charName = _activeArrayName.c_str(); + double range[2]; vtkDataSet* dataSet = vtkDataSet::SafeDownCast(this->_algorithm->GetOutputDataObject(0)); if (dataSet) { - if (onPointData) + if (_onPointData) { vtkPointData* pointData = dataSet->GetPointData(); if(pointData) { - if(activeAttributeExists(pointData, strippedName)) + if(activeAttributeExists(pointData, _activeArrayName)) { _algorithm->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, charName); _mapper->SetScalarModeToUsePointData(); + pointData->GetArray(_activeArrayName.c_str())->GetRange(range); } else { - _activeAttribute = "Solid Color"; + _activeArrayName = ""; + _vtkProps->SetActiveAttribute("Solid Color"); _mapper->ScalarVisibilityOff(); return; } @@ -247,26 +277,45 @@ void VtkVisPointSetItem::SetActiveAttribute( const QString& name ) vtkCellData* cellData = dataSet->GetCellData(); if(cellData) { - if(activeAttributeExists(cellData, strippedName)) + if(activeAttributeExists(cellData, _activeArrayName)) { _algorithm->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, charName); _mapper->SetScalarModeToUseCellData(); + cellData->GetArray(_activeArrayName.c_str())->GetRange(range); } else { - _activeAttribute = "Solid Color"; + _activeArrayName = ""; + _vtkProps->SetActiveAttribute("Solid Color"); _mapper->ScalarVisibilityOff(); return; } } } - _activeAttribute = name; - _mapper->SetScalarRange(dataSet->GetScalarRange()); - this->setLookupTableForActiveScalar(); - _mapper->ScalarVisibilityOn(); + //std::cout << "Range for " << name.toStdString() << " :" << range[0] << " " << range[1] << std::endl; + _vtkProps->SetActiveAttribute(name); + + QVtkDataSetMapper* mapper = dynamic_cast<QVtkDataSetMapper*>(_mapper); + if (mapper) + { + // Create a default color table when there is no lookup table for this attribute + vtkLookupTable* lut = _vtkProps->GetLookupTable(name); + if (lut == NULL) + { + //std::cout << "Creating new lookup table for: " << name.toStdString() << std::endl; + lut = vtkLookupTable::New(); // is not a memory leak, gets deleted in VtkAlgorithmProperties + lut->SetTableRange(range); + _vtkProps->SetLookUpTable(name, lut); + } - //_mapper->Update(); // KR: TODO - this is incredibly slow ... WHY??? + _mapper->SetLookupTable(lut); + _mapper->UseLookupTableScalarRangeOn(); + //_mapper->SetScalarRange(range); // not necessary when UseLookupTableScalarRange is on + } + + _mapper->ScalarVisibilityOn(); + _mapper->Update(); } } @@ -288,41 +337,12 @@ bool VtkVisPointSetItem::activeAttributeExists(vtkDataSetAttributes* data, std:: return false; } -void VtkVisPointSetItem::setLookupTableForActiveScalar() -{ - VtkAlgorithmProperties* vtkProps = dynamic_cast<VtkAlgorithmProperties*>(_algorithm); - if (vtkProps) - { - QVtkDataSetMapper* mapper = dynamic_cast<QVtkDataSetMapper*>(_mapper); - if (mapper) - { - if (vtkProps->GetLookupTable(this->GetActiveAttribute()) == NULL) // default color table - { - vtkLookupTable* lut = vtkLookupTable::New(); - vtkProps->SetLookUpTable(GetActiveAttribute(), lut); - } - else // specific color table - _mapper->SetLookupTable(vtkProps->GetLookupTable(this->GetActiveAttribute())); - - //_mapper->SetScalarRange(this->_transformFilter->GetOutput()->GetScalarRange()); - _mapper->SetScalarRange(vtkDataSet::SafeDownCast(this->_algorithm->GetOutputDataObject(0))->GetScalarRange()); - //_mapper->Update(); //KR: not necessary?! - } - } -} - -void VtkVisPointSetItem::SetScalarRange(double min, double max) -{ - _mapper->SetScalarRange(min, max); - _mapper->Update(); -} - void VtkVisPointSetItem::setScale(double x, double y, double z) const { if (this->transformFilter()) { vtkTransform* transform = - static_cast<vtkTransform*>(this->_transformFilter->GetTransform()); + static_cast<vtkTransform*>(this->_transformFilter->GetTransform()); double* trans = transform->GetPosition(); transform->Identity(); transform->Scale(x, y, z); @@ -336,7 +356,7 @@ void VtkVisPointSetItem::setTranslation(double x, double y, double z) const if (this->transformFilter()) { vtkTransform* transform = - static_cast<vtkTransform*>(this->_transformFilter->GetTransform()); + static_cast<vtkTransform*>(this->_transformFilter->GetTransform()); double* scale = transform->GetScale(); transform->Identity(); transform->Scale(scale); @@ -349,3 +369,27 @@ vtkAlgorithm* VtkVisPointSetItem::transformFilter() const { return _transformFilter; } + +void VtkVisPointSetItem::setBackfaceCulling(bool enable) const +{ + static_cast<vtkActor*>(this->_actor)->GetProperty()->SetBackfaceCulling((int)enable); +} + +void VtkVisPointSetItem::GetRangeForActiveAttribute(double range[2]) const +{ + vtkDataSet* dataSet = vtkDataSet::SafeDownCast(this->_algorithm->GetOutputDataObject(0)); + if (dataSet && _activeArrayName.length() > 0) + { + if (_onPointData) + { + vtkPointData* pointData = dataSet->GetPointData(); + if(pointData) + pointData->GetArray(_activeArrayName.c_str())->GetRange(range); + } + else + { + vtkCellData* cellData = dataSet->GetCellData(); + cellData->GetArray(_activeArrayName.c_str())->GetRange(range); + } + } +} diff --git a/VtkVis/VtkVisPointSetItem.h b/VtkVis/VtkVisPointSetItem.h index 90298eca855637e891b3e007bbf015850503db73..ad106761807d0dd6a0fcc005cc6553f152c719c1 100644 --- a/VtkVis/VtkVisPointSetItem.h +++ b/VtkVis/VtkVisPointSetItem.h @@ -47,7 +47,10 @@ public: ~VtkVisPointSetItem(); /// @brief Gets the last selected attribute. - const QString GetActiveAttribute() const {return _activeAttribute; } + const QString GetActiveAttribute() const; + + /// @brief Get the scalar range for the active attribute + void GetRangeForActiveAttribute(double range[2]) const; /// @brief Initializes vtkMapper and vtkActor necessary for visualization of /// the item and sets the item's properties. @@ -58,26 +61,24 @@ public: /// @brief Sets the selected attribute array for the visualisation of the data set. void SetActiveAttribute(const QString& name); - /// @brief Sets the scalar range for the selected data array - void SetScalarRange(double min, double max); - /// @brief Scales the data in visualisation-space. void setScale(double x, double y, double z) const; /// @brief Translates the item in visualisation-space. void setTranslation(double x, double y, double z) const; + /// @brief Enables / disables backface culling. + void setBackfaceCulling(bool enable) const; + protected: QVtkDataSetMapper* _mapper; vtkTransformFilter* _transformFilter; - QString _activeAttribute; + bool _onPointData; + std::string _activeArrayName; /// Selects the appropriate VTK-Writer object and writes the object to a file with the given name. virtual int callVTKWriter(vtkAlgorithm* algorithm, const std::string &filename) const; - /// Sets a color lookup table for the current scalar array. - void setLookupTableForActiveScalar(); - void SetScalarVisibility(bool on); /// @brief Sets pre-set properties on vtkActor and on vtkMapper @@ -86,6 +87,7 @@ protected: private: /// Checks if the selected attribute actually exists for the data set bool activeAttributeExists(vtkDataSetAttributes* data, std::string& name); + }; #endif // VTKVISPOINTSETITEM_H diff --git a/VtkVis/VtkVisTabWidget.cpp b/VtkVis/VtkVisTabWidget.cpp index 880fca04054105049c58a0fec5ae647b8a53ecde..2901f6de52fb8e73360b0a387a804c18b937a005 100644 --- a/VtkVis/VtkVisTabWidget.cpp +++ b/VtkVis/VtkVisTabWidget.cpp @@ -198,7 +198,8 @@ void VtkVisTabWidget::on_scaleZ_textChanged(const QString &text) bool ok = true; double scale = text.toDouble(&ok); - if (ok) + // If z scale becomes zero, the object becomes invisible + if (ok && scale != 0.0) { _item->setScale(1.0, 1.0, scale); @@ -344,24 +345,8 @@ void VtkVisTabWidget::buildProportiesDialog(VtkVisPipelineItem* item) void VtkVisTabWidget::buildScalarArrayComboBox(VtkVisPipelineItem* item) { - vtkDataSet* dataSet = vtkDataSet::SafeDownCast(item->algorithm()->GetOutputDataObject(0)); - QStringList dataSetAttributesList; - if (dataSet) - { - vtkPointData* pointData = dataSet->GetPointData(); - //std::cout << " #point data arrays: " << pointData->GetNumberOfArrays() << std::endl; - for (int i = 0; i < pointData->GetNumberOfArrays(); i++) - //std::cout << " Name: " << pointData->GetArrayName(i) << std::endl; - dataSetAttributesList.push_back(QString("P-") + pointData->GetArrayName(i)); - - vtkCellData* cellData = dataSet->GetCellData(); - //std::cout << " #cell data arrays: " << cellData->GetNumberOfArrays() << std::endl; - for (int i = 0; i < cellData->GetNumberOfArrays(); i++) - //std::cout << " Name: " << cellData->GetArrayName(i) << std::endl; - dataSetAttributesList.push_back(QString("C-") + cellData->GetArrayName(i)); - - dataSetAttributesList.push_back("Solid Color"); // all scalars switched off - } + QStringList dataSetAttributesList = item->getScalarArrayNames(); + dataSetAttributesList.push_back("Solid Color"); // all scalars switched off this->activeScalarComboBox->blockSignals(true); this->activeScalarComboBox->clear(); this->activeScalarComboBox->insertItems(0, dataSetAttributesList);