Forked from
ogs / ogs
12953 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
NetCdfConfigureDialog.cpp 15.25 KiB
/**
* \copyright
* Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.net)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#include "NetCdfConfigureDialog.h"
#include "MathLib/Point3d.h"
#include "GeoLib/Raster.h"
#include "MeshLib/MeshGenerators/RasterToMesh.h"
#include "MeshLib/MeshEnums.h"
#include "VtkVis/VtkGeoImageSource.h"
#include "VtkVis/VtkRaster.h"
#include <QMessageBox>
#include <QSettings>
#include <vtkImageImport.h>
using namespace netCDF;
// Constructor
NetCdfConfigureDialog::NetCdfConfigureDialog(std::string const& fileName, QDialog* parent)
: QDialog(parent), _currentFile(fileName.c_str(), NcFile::read),
_currentInitialDateTime(QDateTime()), _currentMesh(nullptr), _currentRaster(nullptr), _currentPath(fileName)
{
setupUi(this);
int const idx = setVariableSelect(); // set up variables of the file in the combobox
comboBoxVariable->setCurrentIndex(idx); //pre-select the variable with the biggest number of dimensions...valueWithMaxDim()
_currentVar = _currentFile.getVar(comboBoxVariable->itemText(idx).toStdString());
setDimensionSelect();
lineEditName->setText(setName());
this->radioMesh->setChecked(true);
}
NetCdfConfigureDialog::~NetCdfConfigureDialog() = default;
// Instructions if the OK-Button has been pressed.
void NetCdfConfigureDialog::accept()
{
QMessageBox valueErrorBox;
if (_currentVar.getDimCount() < 2){
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();
this->done(QDialog::Accepted);
}
}
// Instructions if the Cancel-Button has been pressed.
void NetCdfConfigureDialog::reject()
{
this->done(QDialog::Rejected);
}
void NetCdfConfigureDialog::on_comboBoxVariable_currentIndexChanged(int id)
{
std::string const var_name = comboBoxVariable->itemText(_id_map[id]).toStdString();
_currentVar = _currentFile.getVar(var_name);
setDimensionSelect();
}
//set up x-axis/lat
void NetCdfConfigureDialog::on_comboBoxDim1_currentIndexChanged(int id)
{
if (id == -1) id = 0;
double firstValue=0, lastValue=0;
unsigned 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.getDimCount() > 1)
{
if (id == -1) id = 0;
double firstValue=0, lastValue=0;
unsigned 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.getDimCount() > 2)
{
if (id == -1) id = 0;
double firstValue=0, lastValue=0;
unsigned 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.getDimCount() > 3)
{
if (id == -1) id = 0;
double firstValue=0, lastValue=0;
unsigned size = 0;
getDimEdges(id,size,firstValue,lastValue);
// WARNING: Implicit conversion to int in spinBoxDim4->set*()
spinBoxDim4->setValue(static_cast<int>(firstValue));
spinBoxDim4->setMinimum(static_cast<int>(firstValue));
spinBoxDim4->setMaximum(static_cast<int>(lastValue));
}
}
int NetCdfConfigureDialog::setVariableSelect()
{
int max_dim = 0;
int max_dim_idx = 0;
auto const& names =_currentFile.getVars();
//auto const n_vars = _currentFile.getVarCount();
//for (int i = 0; i < n_vars; i++)
for (auto it = names.cbegin(); it != names.cend(); ++it)
{
//NcVar const& focusedVar = _currentFile.getVar(i);
int const var_dim_count = it->second.getDimCount();
if (var_dim_count > 1)
{
//_id_map.push_back(i);
comboBoxVariable->addItem(QString::fromStdString(it->first));
if (var_dim_count > max_dim)
{
max_dim = var_dim_count;
max_dim_idx = comboBoxVariable->count() - 1;
}
}
}
return max_dim_idx;
}
void NetCdfConfigureDialog::setDimensionSelect()
{
int const dim = _currentVar.getDimCount();
std::array<QComboBox*,4> dim_box = {{ comboBoxDim1, comboBoxDim2, comboBoxDim3, comboBoxDim4 }};
for (int i = 0; i < 4; ++i)
{
dim_box[i]->clear();
dim_box[i]->setEnabled(i < dim);
}
for (int i=0; i < dim; ++i) //write dimension-names into selection-boxes
{
for (int j = 0; j < dim; ++j)
dim_box[j]->addItem(QString::fromStdString(_currentVar.getDim(i).getName()));
}
comboBoxDim1->setCurrentIndex(dim-2);
on_comboBoxDim1_currentIndexChanged(dim-2);
comboBoxDim2->setCurrentIndex(dim-1);
on_comboBoxDim2_currentIndexChanged(dim-1);
dateTimeEditDim3->setEnabled(dim > 2); // time is only enabled if dim > 2
spinBoxDim4->setEnabled(dim > 3); // add. info is only enabled if dim > 3
if (dim > 2)
{
comboBoxDim3->setCurrentIndex(0);
on_comboBoxDim3_currentIndexChanged(0);
}
else
dateTimeEditDim3->setDateTime(_currentInitialDateTime);
if (dim == 4)
{
comboBoxDim4->setCurrentIndex(1);
on_comboBoxDim4_currentIndexChanged(1);
}
else
spinBoxDim4->setValue(0);
}
void NetCdfConfigureDialog::getDimEdges(int dimId, unsigned &size, double &firstValue, double &lastValue)
{
size = 0;
firstValue = 0;
lastValue = 0;
if (_currentFile.getVar(_currentVar.getDim(dimId).getName()).isNull())
return;
NcVar const& tmpVarOfDim = _currentFile.getVar(_currentVar.getDim(dimId).getName());
if ((tmpVarOfDim.getDimCount()) == 1)
{
/*
int sizeOfDim = tmpVarOfDim.getDim(0).getSize();
size = sizeOfDim;
double *arrayOfDimStart = new double[1]; //[1] = {0};
long edgeOfArray = 1; //[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];
*/
size = tmpVarOfDim.getDim(0).getSize();
std::vector<std::size_t> start_val{{0}};
std::vector<std::size_t> length{{1}};
tmpVarOfDim.getVar(start_val, length, &firstValue);
start_val[0] = size-1;
tmpVarOfDim.getVar(start_val, length, &lastValue);
}
}
void NetCdfConfigureDialog::getDaysTime(double minSince, QTime &time, int &days)
{
auto 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)
{
long tmpInitialToSelectedDate = static_cast<long>(selectedDate.daysTo(initialDateTime.date()));
long selectedDays = - tmpInitialToSelectedDate * 24 * 60;
long selectedMinutes = (selectedTime.hour() * 60) + selectedTime.minute() + selectedDays;
return selectedMinutes;
}
int NetCdfConfigureDialog::getTimeStep()
{
NcVar const& timeVar =
_currentFile.getVar(comboBoxDim2->currentText().toStdString());
double const 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 static_cast<int>(currentTime);
*/
/** TODO **/
return 0;
}
int NetCdfConfigureDialog::getDim4() const
{
/** TODO **/
/*
NcVar const& dim3Var =
_currentFile.getVar(comboBoxDim4->currentText().toStdString());
int timeArray[1] = {spinBoxDim4->value()};
int 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;
*/
return 0;
}
double NetCdfConfigureDialog::getResolution()
{
if (comboBoxDim1->currentIndex() > -1)
{
NcVar const& latVar =
_currentFile.getVar(comboBoxDim1->currentText().toStdString());
double firstValue = 0, lastValue = 0;
unsigned size = 0;
getDimEdges(latVar.getId(), size, firstValue, lastValue);
if (size < 2)
{
return 1;
}
double interval = fabs(lastValue - firstValue);
double resolution = (double)interval / (size - 1);
return resolution;
}
return 0;
}
void NetCdfConfigureDialog::createDataObject()
{
auto* length = new std::size_t[_currentVar.getDimCount()];
double originLon = 0, originLat = 0;
double lastLon = 0, lastLat = 0;
unsigned sizeLon = 0, sizeLat = 0;
getDimEdges(comboBoxDim1->currentIndex(), sizeLat, originLat, lastLat);
getDimEdges(comboBoxDim2->currentIndex(), sizeLon, originLon, lastLon);
for(int i=0; i < _currentVar.getDimCount(); i++) length[i]=1;
// set array edges: lat x lon
length[comboBoxDim1->currentIndex()]=sizeLat;
length[comboBoxDim2->currentIndex()]=sizeLon;
// set up array
auto* data_array = new double[sizeLat * sizeLon];
for(std::size_t i=0; i < (sizeLat*sizeLon); i++) data_array[i]=0;
//Time-Dimension:
/*
if (_currentVar.getDimCount() > 2)
{
auto* newOrigin = new long[_currentVar.getDimCount()];
for (int i=0; i < _currentVar.getDimCount(); i++) newOrigin[i]=0;
newOrigin[comboBoxDim3->currentIndex()] = getTimeStep(); //set origin to selected time
_currentVar.set_cur(newOrigin);
//Dimension 4:
if (_currentVar.getDimCount() > 3) newOrigin[comboBoxDim4->currentIndex()] = getDim4(); //if there are is a 4th dimension
delete [] newOrigin;
}
*/
std::vector<std::size_t> data_origin {{0, 0}};
std::vector<std::size_t> data_length {{sizeLat, sizeLon}};
_currentVar.getVar(data_origin, data_length, data_array); // create Array of Values
for (std::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;
MathLib::Point3d origin(std::array<double,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);
GeoLib::RasterHeader const header = {sizeLon, sizeLat, 1,
origin, resolution, -9999};
if (this->radioMesh->isChecked())
{
MeshLib::MeshElemType meshElemType = MeshLib::MeshElemType::QUAD;
MeshLib::UseIntensityAs useIntensity = MeshLib::UseIntensityAs::DATAVECTOR;
if (comboBoxMeshElemType->currentIndex() == 1)
{
meshElemType = MeshLib::MeshElemType::TRIANGLE;
}else{
meshElemType = MeshLib::MeshElemType::QUAD;
}
if ((comboBoxUseIntensity->currentIndex()) == 1)
{
useIntensity = MeshLib::UseIntensityAs::ELEVATION;
}else{
useIntensity = MeshLib::UseIntensityAs::DATAVECTOR;
}
_currentMesh = MeshLib::RasterToMesh::convert(
data_array, header, meshElemType, useIntensity, _currentVar.getName());
}
else
{
vtkImageImport* image = VtkRaster::loadImageFromArray(data_array, header);
_currentRaster = VtkGeoImageSource::New();
_currentRaster->setImage(image, QString::fromStdString(this->getName()), origin[0], origin[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("."));
return QString::fromStdString(name);
}
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, std::size_t width, std::size_t height)
{
auto* cp_array = new double[width * height];
for (std::size_t i=0; i<height; i++)
{
for (std::size_t j=0; j<width; j++)
{
std::size_t old_index((width*height)-(width*(i+1)));
std::size_t new_index(width*i);
cp_array[new_index+j] = data[old_index+j];
}
}
std::size_t length(height*width);
for (std::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(false);
this->comboBoxMeshElemType->setEnabled(true);
this->comboBoxUseIntensity->setEnabled(false);
}
else // output set to "raster"
{
this->label_2->setEnabled(false);
this->label_3->setEnabled(true);
this->comboBoxMeshElemType->setEnabled(false);
this->comboBoxUseIntensity->setEnabled(true);
}
}