WSL/SLF GitLab Repository

Commit 03109eee authored by Mathias Bavay's avatar Mathias Bavay
Browse files

A new key has been added that was missing: GRID2DPATH that can be in intput...

A new key has been added that was missing: GRID2DPATH that can be in intput and output. This key is now properly handled by the appropriate plugins. A new color reduction strategy has been implemented in the gradients and the PNG plugin: instead of reducing the colors coming out of the gradient, the values coming in are discretized. This leads to much more effective size reduction for the same output quality, with 5% speed increase compared to the original code not doing this reduction (test: reading and writing back a grid). The file size is now 1/3 of the full color file.
parent 244c1931
......@@ -228,14 +228,15 @@ const unsigned char Gradient::channel_max_color = 255;
Gradient::Gradient(const Type& type, const double& i_min, const double& i_max, const bool& i_autoscale)
{
set(type, i_min, i_max, i_autoscale);
nr_unique_levels = 0;
}
void Gradient::set(const Type& type, const double& i_min, const double& i_max, const bool& i_autoscale)
{
delta_val = i_max - i_min;
min = i_min;
max = i_max;
delta = i_max - i_min;
autoscale = i_autoscale;
color_discretization = 0.; //color discretization turned off
nr_unique_colors = 0;
if(type==terrain) model = new gr_terrain(i_min, i_max, i_autoscale);
else if(type==slope) model = new gr_slope(i_min, i_max, i_autoscale);
......@@ -248,9 +249,8 @@ void Gradient::set(const Type& type, const double& i_min, const double& i_max, c
else if(type==bg_isomorphic) model = new gr_bg_isomorphic(i_min, i_max, i_autoscale);
}
void Gradient::setNrOfColors(const unsigned int& i_nr_unique_colors) {
nr_unique_colors = static_cast<unsigned char>( pow(i_nr_unique_colors, 1./3.) );
color_discretization = (double)channel_max_color/(double)nr_unique_colors;
void Gradient::setNrOfLevels(const unsigned int& i_nr_unique_levels) {
nr_unique_levels = i_nr_unique_levels;
}
//val between min_val and max_val
......@@ -275,31 +275,27 @@ void Gradient::getColor(const double& val, unsigned char& r, unsigned char& g, u
r=0; g=0; b=0; a=false;
return;
}
if(autoscale && delta_val==0) { //constant data throughout the grid & autoscale are no friends...
if(autoscale && delta==0) { //constant data throughout the grid & autoscale are no friends...
r=g=b=channel_max_color/2; a=false;
return;
}
a=false;
double r_d,g_d,b_d;
model->getColor(val, r_d, g_d, b_d);
if(nr_unique_colors==0.) {
r = static_cast<unsigned char>(r_d*channel_max_color);
g = static_cast<unsigned char>(g_d*channel_max_color);
b = static_cast<unsigned char>(b_d*channel_max_color);
double val_norm;
if(nr_unique_levels==0) {
if(autoscale && val<min) val_norm=0.;
else if(autoscale && val>max) val_norm=1.;
else val_norm = (val-min)/delta;
} else {
r = static_cast<unsigned char>( static_cast<unsigned char>(r_d*nr_unique_colors)*color_discretization );
g = static_cast<unsigned char>( static_cast<unsigned char>(g_d*nr_unique_colors)*color_discretization );
b = static_cast<unsigned char>( static_cast<unsigned char>(b_d*nr_unique_colors)*color_discretization );
if(autoscale && val<min) val_norm=0.;
else if(autoscale && val>max) val_norm=1.;
else val_norm = (static_cast<unsigned int>( (val-min)/delta*(double)nr_unique_levels )) / (double)nr_unique_levels;
}
}
void Gradient_model::setMinMax(const double& i_min, const double& i_max, const bool& i_autoscale)
{
min_val = i_min;
max_val = i_max;
delta_val = (max_val-min_val);
autoscale = i_autoscale;
model->getColor(val_norm, r_d, g_d, b_d);
r = static_cast<unsigned char>(r_d*channel_max_color);
g = static_cast<unsigned char>(g_d*channel_max_color);
b = static_cast<unsigned char>(b_d*channel_max_color);
}
//we assume that the vectors are sorted by X
......@@ -353,25 +349,14 @@ void Gradient_model::getColor(const double &val, double &r, double &g, double &b
void gr_heat::getColor(const double &i_val, double &r, double &g, double &b) const
{
double val;
if(autoscale)
val = (i_val-min_val)/delta_val;
else { //since the user provided bounds do not reflect the data's bounds
if(i_val<min_val) val=0.;
else if(i_val>max_val) val=1.;
else val = (i_val-min_val)/delta_val;
}
const double h = 240. * (1.-val);
const double v = val*0.75+0.25;
const double s = 1.-val*0.3;
const double h = 240. * (1.-i_val);
const double v = i_val*0.75+0.25;
const double s = 1.-i_val*0.3;
Color::HSVtoRGB(h, s, v, r, g, b);
}
gr_blue_pink::gr_blue_pink(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
gr_blue_pink::gr_blue_pink(const double& /*i_min*/, const double& /*i_max*/, const bool& /*i_autoscale*/) {
//write gradient control points
X.push_back(0.); v_h.push_back(0.); v_s.push_back(0.); v_v.push_back(.95); //almost white
X.push_back(0.2); v_h.push_back(172.); v_s.push_back(.4); v_v.push_back(.95); //light blue
......@@ -379,33 +364,24 @@ gr_blue_pink::gr_blue_pink(const double& i_min, const double& i_max, const bool&
X.push_back(.6); v_h.push_back(255.); v_s.push_back(.4); v_v.push_back(.95); //violet/blue
X.push_back(.8); v_h.push_back(278.); v_s.push_back(.4); v_v.push_back(.95); //violet
X.push_back(1.); v_h.push_back(359.); v_s.push_back(.3); v_v.push_back(.95); //red
for(size_t i=0; i<X.size(); i++) X[i] = X[i]*delta_val + min_val;
}
gr_freeze::gr_freeze(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
gr_freeze::gr_freeze(const double& /*i_min*/, const double& /*i_max*/, const bool& /*i_autoscale*/) {
//write gradient control points
X.push_back(0.); v_r.push_back(0.); v_g.push_back(0.); v_b.push_back(1.); //blue
X.push_back(.5); v_r.push_back(1.); v_g.push_back(1.); v_b.push_back(0.); //yellow
X.push_back(.5); v_r.push_back(0.); v_g.push_back(1.); v_b.push_back(0.); //green
X.push_back(1.); v_r.push_back(1.); v_g.push_back(0.); v_b.push_back(0.); //red
for(size_t i=0; i<X.size(); i++) X[i] = X[i]*delta_val + min_val;
}
void gr_freeze::getColor(const double &val, double &r, double &g, double &b) const
{
void gr_freeze::getColor(const double &val, double &r, double &g, double &b) const {
//interpolation on RGB values
r = getInterpol(val, X, v_r);
g = getInterpol(val, X, v_g);
b = getInterpol(val, X, v_b);
}
gr_blue::gr_blue(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
gr_blue::gr_blue(const double& /*i_min*/, const double& /*i_max*/, const bool& /*i_autoscale*/) {
//write gradient control points
X.push_back(0.); v_h.push_back(0.); v_s.push_back(0.); v_v.push_back(.99); //5
X.push_back(.16667); v_h.push_back(180.); v_s.push_back(.2); v_v.push_back(.99); //10
......@@ -415,66 +391,50 @@ gr_blue::gr_blue(const double& i_min, const double& i_max, const bool& i_autosca
X.push_back(.83335); v_h.push_back(231.); v_s.push_back(.66); v_v.push_back(.88); //120
X.push_back(1.); v_h.push_back(244.); v_s.push_back(.78); v_v.push_back(.85); //200
X.push_back(1.); v_h.push_back(270.); v_s.push_back(1.); v_v.push_back(.8); //200
for(size_t i=0; i<X.size(); i++) X[i] = X[i]*delta_val + min_val;
}
gr_bg_isomorphic::gr_bg_isomorphic(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
gr_bg_isomorphic::gr_bg_isomorphic(const double& /*i_min*/, const double& /*i_max*/, const bool& /*i_autoscale*/) {
//write gradient control points
X.push_back(0.); v_h.push_back(47.); v_s.push_back(.92); v_v.push_back(0.); //black
X.push_back(.5); v_h.push_back(178.); v_s.push_back(.58); v_v.push_back(.67); //light blue
X.push_back(1.); v_h.push_back(84.); v_s.push_back(.67); v_v.push_back(1.); //light green
for(size_t i=0; i<X.size(); i++) X[i] = X[i]*delta_val + min_val;
}
gr_pastel::gr_pastel(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
gr_pastel::gr_pastel(const double& /*i_min*/, const double& /*i_max*/, const bool& /*i_autoscale*/) {
//write gradient control points
X.push_back(0.); v_h.push_back(0.); v_s.push_back(1.); v_v.push_back(0.); //black
X.push_back(1.); v_h.push_back(185.); v_s.push_back(.26); v_v.push_back(.56); //light blue
X.push_back(2.); v_h.push_back(122.); v_s.push_back(.44); v_v.push_back(.91); //light green
X.push_back(4.); v_h.push_back(60.); v_s.push_back(.44); v_v.push_back(.91); //light yellow
X.push_back(5.); v_h.push_back(22.); v_s.push_back(.44); v_v.push_back(.91); //orange
X.push_back(6.); v_h.push_back(0.); v_s.push_back(.44); v_v.push_back(.91); //red
X.push_back(7.); v_h.push_back(0.); v_s.push_back(.4); v_v.push_back(.7); //dark red
for(size_t i=0; i<X.size(); i++) X[i] = X[i]/7.*delta_val + min_val;
X.push_back(1./7.); v_h.push_back(185.); v_s.push_back(.26); v_v.push_back(.56); //light blue
X.push_back(2./7.); v_h.push_back(122.); v_s.push_back(.44); v_v.push_back(.91); //light green
X.push_back(4./7.); v_h.push_back(60.); v_s.push_back(.44); v_v.push_back(.91); //light yellow
X.push_back(5./7.); v_h.push_back(22.); v_s.push_back(.44); v_v.push_back(.91); //orange
X.push_back(6./7.); v_h.push_back(0.); v_s.push_back(.44); v_v.push_back(.91); //red
X.push_back(7./7.); v_h.push_back(0.); v_s.push_back(.4); v_v.push_back(.7); //dark red
}
gr_terrain::gr_terrain(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
gr_terrain::gr_terrain(const double& /*i_min*/, const double& i_max, const bool& i_autoscale) {
//write gradient control points
if(autoscale) {
if(i_autoscale) {
X.push_back(0.); v_h.push_back(144.); v_s.push_back(.50); v_v.push_back(.39); //sea level, dark green
X.push_back(.25); v_h.push_back(46.); v_s.push_back(.54); v_v.push_back(.86); //yellow
X.push_back(.5); v_h.push_back(4.); v_s.push_back(.71); v_v.push_back(.53); //dark red
X.push_back(.75); v_h.push_back(22.); v_s.push_back(.88); v_v.push_back(.41); //maroon
X.push_back(1.); v_h.push_back(22.); v_s.push_back(.2); v_v.push_back(.5); //light maroon
for(size_t i=0; i<X.size(); i++) X[i] = X[i]*delta_val + min_val;
} else {
X.push_back(-1.); v_h.push_back(198.); v_s.push_back(.50); v_v.push_back(.74); //sea, light blue
const double snow_line = i_max - 500.;
X.push_back(0.); v_h.push_back(198.); v_s.push_back(.50); v_v.push_back(.74); //sea, light blue
X.push_back(0.); v_h.push_back(144.); v_s.push_back(.50); v_v.push_back(.39); //sea level, dark green
X.push_back(1200.); v_h.push_back(46.); v_s.push_back(.54); v_v.push_back(.86); //yellow
X.push_back(2200.); v_h.push_back(4.); v_s.push_back(.71); v_v.push_back(.53); //dark red
X.push_back(2700.); v_h.push_back(22.); v_s.push_back(.88); v_v.push_back(.41); //maroon
X.push_back(2950.); v_h.push_back(22.); v_s.push_back(.36); v_v.push_back(.79); //light maroon
X.push_back(3000.); v_h.push_back(0.); v_s.push_back(0.); v_v.push_back(.7); //light gray == permanent snow line
for(size_t i=0; i<X.size(); i++) X[i] = X[i]/3000.*delta_val + min_val; //snow line is the reference
X.push_back(max_val+600.); v_h.push_back(0.); v_s.push_back(0.); v_v.push_back(.95); //almost white == fully glaciated line
X.push_back(.4); v_h.push_back(46.); v_s.push_back(.54); v_v.push_back(.86); //yellow, 1200m
X.push_back(.73333); v_h.push_back(4.); v_s.push_back(.71); v_v.push_back(.53); //dark red, 2200m
X.push_back(.9); v_h.push_back(22.); v_s.push_back(.88); v_v.push_back(.41); //maroon, 2700m
X.push_back(.98333); v_h.push_back(22.); v_s.push_back(.36); v_v.push_back(.79); //light maroon, 2950m
X.push_back(1.); v_h.push_back(0.); v_s.push_back(0.); v_v.push_back(.7); //light gray == permanent snow line, 3000m
for(size_t i=0; i<X.size(); i++) X[i] = X[i]*snow_line/i_max; //snow line is the reference
X.push_back(1.); v_h.push_back(0.); v_s.push_back(0.); v_v.push_back(.95); //almost white == fully glaciated line
}
}
gr_slope::gr_slope(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
gr_slope::gr_slope(const double& /*i_min*/, const double& /*i_max*/, const bool& /*i_autoscale*/) {
//write gradient control points
//usually, between 0 and 50
X.push_back(0.); v_h.push_back(185.); v_s.push_back(.26); v_v.push_back(.56); //light blue
......@@ -484,15 +444,11 @@ gr_slope::gr_slope(const double& i_min, const double& i_max, const bool& i_autos
X.push_back(.8); v_h.push_back(0.); v_s.push_back(.44); v_v.push_back(.91); //red
X.push_back(.9); v_h.push_back(0.); v_s.push_back(.58); v_v.push_back(.35); //dark red
X.push_back(1.); v_h.push_back(0.); v_s.push_back(1.); v_v.push_back(0.); //black
for(size_t i=0; i<X.size(); i++) X[i] = X[i]*delta_val + min_val;
}
gr_azi::gr_azi(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
gr_azi::gr_azi(const double& /*i_min*/, const double& /*i_max*/, const bool& i_autoscale) {
//write gradient control points
if(autoscale) {
if(i_autoscale) {
X.push_back(0.); v_h.push_back(113.); v_s.push_back(.66); v_v.push_back(.91); //light green
X.push_back(1.); v_h.push_back(360.); v_s.push_back(.66); v_v.push_back(.91); //light red
} else {
......@@ -503,8 +459,6 @@ gr_azi::gr_azi(const double& i_min, const double& i_max, const bool& i_autoscale
X.push_back(.75); v_h.push_back(28.); v_s.push_back(.78); v_v.push_back(1.); //orange
X.push_back(1.); v_h.push_back(240.); v_s.push_back(.78); v_v.push_back(1.); //back to blue
}
for(size_t i=0; i<X.size(); i++) X[i] = X[i]*delta_val + min_val;
}
} //namespace
......@@ -127,21 +127,20 @@ namespace Color {
/////////////////////////////////////////////////////////////////////////////////////////////////
//This class is the base class for the various gradients.
//DO NOT USE pure white in a gradient, since this might be interpreted as a transparent pixel!
//Gradients scale between 0 and 1, but might receive some out of range values for special effects (below sea level, above snow line, etc)
class Gradient_model {
public:
Gradient_model() {setMinMax(0., 0., true);}; //do not use this constructor!
Gradient_model(const double& i_min, const double& i_max, const bool& i_autoscale) {setMinMax(i_min, i_max, i_autoscale);};
Gradient_model() {}; //do not use this constructor!
Gradient_model(const double& i_min, const double& i_max, const bool& i_autoscale) { (void)i_min; (void)i_max; (void)i_autoscale;};
//setBgColor()
//setFgColor()
//val MUST be between 0 and 1
virtual void getColor(const double &val, double &r, double &g, double &b) const;
protected:
double getInterpol(const double& val, const std::vector<double>& X, const std::vector<double>& Y) const;
void setMinMax(const double& i_min, const double& i_max, const bool& i_autoscale);
void HSV2RGB(const double& h, const double& s, const double& v, unsigned char &r, unsigned char &g, unsigned char &b) const;
double max_val, min_val, delta_val;
bool autoscale;
std::vector<double> X, v_h,v_s,v_v; ///<control points: vector of X and associated hues, saturations and values. They must be in X ascending order
};
......@@ -194,7 +193,7 @@ class Gradient {
* @brief Default Constructor.
* This should be followed by a call to set() before calling getColor
*/
Gradient() {model=NULL; delta_val=0.;};
Gradient() {model=NULL; min=max=delta=0.; nr_unique_levels=0;};
/**
* @brief Constructor.
......@@ -221,14 +220,15 @@ class Gradient {
//setFgColor()
/**
* @brief Set a reduced number of colors for the gradient
* The given argument is an upper bound for the number of unique colors in the generated
* gradient. This is a specially easy and useful way of reducing a file size with
* @brief Set a reduced number of levels for the gradient
* The given argument is an upper bound for the number of unique levels in the generated
* gradient (leading to a reduced number of colors). This is a specially easy and useful way of reducing a file size with
* no run time overhead (and even a small benefit) and little visible impact if
* the number of colors remains large enough (say, at least a few thousands)
* @param i_nr_unique_colors maximum number of unique colors
* the number of levels/colors remains large enough (say, at least 30)
* @param i_nr_unique_levels maximum number of unique levels
*/
void setNrOfColors(const unsigned int& i_nr_unique_colors);
void setNrOfLevels(const unsigned int& i_nr_unique_levels);
/**
* @brief Get RGB values for a given numeric value
* See class description for more explanations on the implementation/behavior
......@@ -242,16 +242,15 @@ class Gradient {
static const unsigned char channel_max_color; ///< nr of colors per channel of the generated gradients
private:
double delta_val;
double min, max, delta;
bool autoscale;
double color_discretization;
unsigned char nr_unique_colors;
unsigned char nr_unique_levels;
Gradient_model *model;
};
class gr_heat : public Gradient_model {
public:
gr_heat(const double& i_min, const double& i_max, const bool& i_autoscale) {setMinMax(i_min, i_max, i_autoscale);};
gr_heat(const double& i_min, const double& i_max, const bool& i_autoscale) {(void)i_min; (void)i_max; (void)i_autoscale;};
void getColor(const double &i_val, double &r, double &g, double &b) const;
};
......
......@@ -96,7 +96,7 @@ class IOInterface : public PluginObject {
/**
* @brief A generic function for parsing 2D grids into a Grid2DObject. The string parameter shall be used for addressing the
* specific 2D grid to be parsed into the Grid2DObject.
* specific 2D grid to be parsed into the Grid2DObject, relative to GRID2DPATH for most plugins.
* @param grid_out A Grid2DObject instance
* @param parameter A std::string representing some information for the function on what grid to retrieve
*/
......@@ -104,7 +104,7 @@ class IOInterface : public PluginObject {
/**
* @brief Read the given meteo parameter into a Grid2DObject.
* Each plugin has its own logic for finding the requested meteo parameter grid.
* Each plugin has its own logic for finding the requested meteo parameter grid relative to GRID2DPATH for most plugins
* @param grid_out A Grid2DObject instance
* @param parameter The meteo parameter grid type to return (ie: air temperature, wind component, etc)
* @param date date of the data to read
......@@ -229,6 +229,7 @@ class IOInterface : public PluginObject {
/**
* @brief Write a Grid2DObject
* The filename is specified relative to GRID2DPATH for most plugins
* @param grid_in (Grid2DObject) The grid to write
* @param options (string) Identifier usefull for the output plugin (it could become part of a file name, a db table, etc)
*/
......@@ -236,6 +237,7 @@ class IOInterface : public PluginObject {
/**
* @brief Write a Grid2DObject comtaining a known meteorological parameter
* A filename is build relative to GRID2DPATH for most plugins.
* @param grid_in (Grid2DObject) The grid to write
* @param parameter The meteo parameter grid type of the provided grid object (ie: air temperature, wind component, etc)
* @param date date of the data to write
......
......@@ -87,6 +87,7 @@ namespace mio {
* - COORDPARAM: extra input coordinates parameters (see Coords) specified in the [Input] section
* - COORDSYS: output coordinate system (see Coords) specified in the [Output] section
* - COORDPARAM: extra output coordinates parameters (see Coords) specified in the [Output] section
* - GRID2DPATH: meteo grids directory where to read/write the grids; [Input] and [Output] sections
* - A3D_view: use Alpine3D's grid viewer naming scheme (default=false)? [Input] and [Output] sections.
* - DEMFILE: for reading the data as a DEMObject
* - LANDUSE: for interpreting the data as landuse codes
......@@ -100,6 +101,7 @@ ARCIO::ARCIO(void (*delObj)(void*), const Config& i_cfg) : IOInterface(delObj),
cfg.getValue("A3D_view", "Input", a3d_view_in, Config::nothrow);
a3d_view_out = false;
cfg.getValue("A3D_view", "Output", a3d_view_out, Config::nothrow);
getGridPaths();
}
ARCIO::ARCIO(const std::string& configfile) : IOInterface(NULL), cfg(configfile)
......@@ -109,6 +111,7 @@ ARCIO::ARCIO(const std::string& configfile) : IOInterface(NULL), cfg(configfile)
cfg.getValue("A3D_view", "Input", a3d_view_in, Config::nothrow);
a3d_view_out = false;
cfg.getValue("A3D_view", "Output", a3d_view_out, Config::nothrow);
getGridPaths();
}
ARCIO::ARCIO(const Config& cfgreader) : IOInterface(NULL), cfg(cfgreader)
......@@ -118,6 +121,19 @@ ARCIO::ARCIO(const Config& cfgreader) : IOInterface(NULL), cfg(cfgreader)
cfg.getValue("A3D_view", "Input", a3d_view_in, Config::nothrow);
a3d_view_out = false;
cfg.getValue("A3D_view", "Output", a3d_view_out, Config::nothrow);
getGridPaths();
}
void ARCIO::getGridPaths() {
grid2dpath_in="", grid2dpath_out="";
string tmp="";
cfg.getValue("GRID2D", "Input", tmp, Config::nothrow);
if (tmp == "ARC") //keep it synchronized with IOHandler.cc for plugin mapping!!
cfg.getValue("GRID2DPATH", "Input", grid2dpath_in);
tmp="";
cfg.getValue("GRID2D", "Output", tmp, Config::nothrow);
if (tmp == "ARC") //keep it synchronized with IOHandler.cc for plugin mapping!!
cfg.getValue("GRID2DPATH", "Output", grid2dpath_out);
}
ARCIO::~ARCIO() throw()
......@@ -135,7 +151,7 @@ void ARCIO::cleanup() throw()
}
}
void ARCIO::read2DGrid(Grid2DObject& grid_out, const std::string& filename)
void ARCIO::read2DGrid_internal(Grid2DObject& grid_out, const std::string& full_name)
{
int i_ncols, i_nrows;
unsigned int ncols, nrows;
......@@ -145,17 +161,17 @@ void ARCIO::read2DGrid(Grid2DObject& grid_out, const std::string& filename)
std::string line="";
std::map<std::string, std::string> header; // A map to save key value pairs of the file header
if (!IOUtils::validFileName(filename)) {
throw InvalidFileNameException(filename, AT);
if (!IOUtils::validFileName(full_name)) {
throw InvalidFileNameException(full_name, AT);
}
if (!IOUtils::fileExists(filename)) {
throw FileNotFoundException(filename, AT);
if (!IOUtils::fileExists(full_name)) {
throw FileNotFoundException(full_name, AT);
}
fin.clear();
fin.open (filename.c_str(), ifstream::in);
fin.open (full_name.c_str(), ifstream::in);
if (fin.fail()) {
throw FileAccessException(filename, AT);
throw FileAccessException(full_name, AT);
}
char eoln = IOUtils::getEoln(fin); //get the end of line character for the file
......@@ -178,10 +194,10 @@ void ARCIO::read2DGrid(Grid2DObject& grid_out, const std::string& filename)
cellsize = IOUtils::standardizeNodata(cellsize, plugin_nodata);
if ((i_ncols==0) || (i_nrows==0)) {
throw IOException("Number of rows or columns in 2D Grid given is zero, in file: " + filename, AT);
throw IOException("Number of rows or columns in 2D Grid given is zero, in file: " + full_name, AT);
}
if((i_ncols<0) || (i_nrows<0)) {
throw IOException("Number of rows or columns in 2D Grid read as \"nodata\", in file: " + filename, AT);
throw IOException("Number of rows or columns in 2D Grid read as \"nodata\", in file: " + full_name, AT);
}
ncols = (unsigned int)i_ncols;
nrows = (unsigned int)i_nrows;
......@@ -198,12 +214,12 @@ void ARCIO::read2DGrid(Grid2DObject& grid_out, const std::string& filename)
getline(fin, line, eoln); //read complete line
if (IOUtils::readLineToVec(line, tmpvec) != ncols) {
throw InvalidFormatException("Premature End " + filename, AT);
throw InvalidFormatException("Premature End " + full_name, AT);
}
for (unsigned int ll=0; ll < ncols; ll++){
if (!IOUtils::convertString(tmp_val, tmpvec[ll], std::dec)) {
throw ConversionFailedException("For Grid2D value in line: " + line + " in file " + filename, AT);
throw ConversionFailedException("For Grid2D value in line: " + line + " in file " + full_name, AT);
}
grid_out.grid2D(ll, kk) = IOUtils::standardizeNodata(tmp_val, plugin_nodata);
}
......@@ -211,34 +227,38 @@ void ARCIO::read2DGrid(Grid2DObject& grid_out, const std::string& filename)
} catch(const std::exception& e) {
cleanup();
std::stringstream msg;
msg << "[E] Error while reading file " << filename << ": " << e.what();
msg << "[E] Error while reading file " << full_name << ": " << e.what();
throw InvalidFormatException(msg.str(), AT);
}
cleanup();
}
void ARCIO::read2DGrid(Grid2DObject& grid_out, const std::string& filename) {
read2DGrid_internal(grid_out, grid2dpath_in+"/"+filename);
}
void ARCIO::read2DGrid(Grid2DObject& grid_out, const MeteoGrids::Parameters& parameter, const Date& date)
{
if(a3d_view_in) {
string ext = MeteoGrids::getParameterName(parameter);
IOUtils::toLower(ext);
read2DGrid(grid_out, date.toString(Date::NUM)+"."+ext );
read2DGrid_internal(grid_out, grid2dpath_in + "/" + date.toString(Date::NUM)+"."+ext );
} else
read2DGrid(grid_out, date.toString(Date::NUM) + "_" + MeteoGrids::getParameterName(parameter) + ".asc");
read2DGrid_internal(grid_out, grid2dpath_in + "/" + date.toString(Date::NUM) + "_" + MeteoGrids::getParameterName(parameter) + ".asc");
}
void ARCIO::readDEM(DEMObject& dem_out)
{
string filename="";
cfg.getValue("DEMFILE", "Input", filename);
read2DGrid(dem_out, filename);
read2DGrid_internal(dem_out, filename);
}
void ARCIO::readLanduse(Grid2DObject& landuse_out)
{
string filename="";
cfg.getValue("LANDUSEFILE", "Input", filename);
read2DGrid(landuse_out, filename);
read2DGrid_internal(landuse_out, filename);
}
void ARCIO::readAssimilationData(const Date& date_in, Grid2DObject& da_out)
......@@ -253,7 +273,7 @@ void ARCIO::readAssimilationData(const Date& date_in, Grid2DObject& da_out)
ss.fill('0');
ss << filepath << "/" << setw(4) << yyyy << setw(2) << MM << setw(2) << dd << setw(2) << hh << setw(2) << mm << ".sca";
read2DGrid(da_out, ss.str());
read2DGrid_internal(da_out, ss.str());
}
void ARCIO::readStationData(const Date&, std::vector<StationData>&)
......@@ -283,9 +303,10 @@ void ARCIO::readSpecialPoints(std::vector<Coords>&)
void ARCIO::write2DGrid(const Grid2DObject& grid_in, const std::string& name)
{
fout.open(name.c_str());
std::string full_name = grid2dpath_out+"/"+name;
fout.open(full_name.c_str());
if (fout.fail()) {
throw FileAccessException(name, AT);
throw FileAccessException(full_name, AT);
}
try {
......@@ -309,7 +330,7 @@ void ARCIO::write2DGrid(const Grid2DObject& grid_in, const std::string& name)
fout << "\n";
}
} catch(...) {
cout << "[E] error when writing ARC grid \"" << name << "\" " << AT << ": "<< endl;
cout << "[E] error when writing ARC grid \"" << full_name << "\" " << AT << ": "<< endl;
cleanup();
throw;
}
......@@ -319,6 +340,7 @@ void ARCIO::write2DGrid(const Grid2DObject& grid_in, const std::string& name)
void ARCIO::write2DGrid(const Grid2DObject& grid_in, const MeteoGrids::Parameters& parameter, const Date& date)
{
//the path will be added by write2DGrid
if(a3d_view_out) {
string ext = MeteoGrids::getParameterName(parameter);
IOUtils::toLower(ext);
......
......@@ -67,13 +67,16 @@ class ARCIO : public IOInterface {
virtual void write2DGrid(const Grid2DObject& grid_in, const MeteoGrids::Parameters& parameter, const Date& date);
private:
void getGridPaths();
void cleanup() throw();
void read2DGrid_internal(Grid2DObject& grid_out, const std::string& full_name);
Config cfg;
bool a3d_view_in, a3d_view_out; ///< make filename compatible with the Alpine3D's viewer?
std::ifstream fin; //Input file streams
std::ofstream fout;//Output file streams
std::string coordin, coordinparam, coordout, coordoutparam; //projection parameters
std::string grid2dpath_in, grid2dpath_out;
};
} //end namespace mio
......
......@@ -35,6 +35,7 @@ namespace mio {
* This plugin uses the following keywords:
* - COORDSYS: coordinate system (see Coords); [Input] and [Output] section
* - COORDPARAM: extra coordinates parameters (see Coords); [Input] and [Output] section
* - GRID2DPATH: meteo grids directory where to read/write the grids; [Input] and [Output] sections
* - PGM_XCOORD: lower left x coordinate; [Input] section
* - PGM_YCOORD: lower left y coordinate; [Input] section
* - PGM_CELLSIZE: cellsize in meters; [Input] section
......@@ -47,20 +48,34 @@ const double PGMIO::plugin_nodata = -999.; //plugin specific nodata value. It ca
PGMIO::PGMIO(void (*delObj)(void*), const Config& i_cfg) : IOInterface(delObj), cfg(i_cfg)