WSL/SLF GitLab Repository

Commit e2e3db32 authored by Mathias Bavay's avatar Mathias Bavay
Browse files

New methods "moveByXY" and "moveByBearing" have been added to Coords,...

New methods "moveByXY" and "moveByBearing" have been added to Coords, addressing issue 39. Code cleanup and extensive documenting have been performed on Graphics and PNGIO, that now supports creating world file (optionnally). A new option has also been added to ARCIO, "A3D_view", to generate file names compatible with the Alpine3D's grid viewer (false by default). A new function to remove the extension from a file name has been implemented in IOUtils.
parent 4b6b15e9
......@@ -115,7 +115,7 @@ MESSAGE(STATUS "RELEASE CXXFLAGS: ${CMAKE_CXX_FLAGS_RELEASE}")
SET(PLUGIN_ARCIO ON CACHE BOOL "Compilation ARCIO ON or OFF")
SET(PLUGIN_ARPSIO ON CACHE BOOL "Compilation ARPSIO ON or OFF")
SET(PLUGIN_PGMIO ON CACHE BOOL "Compilation PGMIO ON or OFF")
SET(PLUGIN_PNGIO ON CACHE BOOL "Compilation PNGIO ON or OFF")
SET(PLUGIN_PNGIO OFF CACHE BOOL "Compilation PNGIO ON or OFF")
SET(PLUGIN_BORMAIO OFF CACHE BOOL "Compilation BORMAIO ON or OFF")
SET(PLUGIN_GEOTOPIO ON CACHE BOOL "Compilation GEOTOPIO ON or OFF")
SET(PLUGIN_SNIO ON CACHE BOOL "Compilation SNIO ON or OFF")
......
......@@ -156,6 +156,29 @@ bool Coords::isNodata() const {
return false;
}
///< move the point by the specified distance (in m) along easting and northing
void Coords::moveByXY(const double& x_displacement, const double& y_displacement) {
setXY(easting+x_displacement, northing+y_displacement, altitude, true);
}
///< move the point by the specified bearing and distance (in m)
void Coords::moveByBearing(const double& bearing, const double& distance) {
double new_lat, new_lon;
switch(distance_algo) {
case GEO_COSINE:
cosineInverse(latitude, longitude, distance, bearing, new_lat, new_lon);
break;
case GEO_VINCENTY:
VincentyInverse(latitude, longitude, distance, bearing, new_lat, new_lon);
break;
default:
throw InvalidArgumentException("Unrecognized geodesic distance algorithm selected", AT);
}
setLatLon(new_lat, new_lon, altitude, true);
}
/**
* @brief Simple merge strategy.
* If some fields of the first argument are empty, they will be filled by the macthing field from the
......
......@@ -67,6 +67,8 @@ class Coords {
bool operator==(const Coords&) const; ///<Operator that tests for equality
bool operator!=(const Coords&) const; ///<Operator that tests for inequality
bool isNodata() const;
void moveByXY(const double& x_displacement, const double& y_displacement);
void moveByBearing(const double& bearing, const double& distance);
static Coords merge(const Coords& coord1, const Coords& coord2);
void merge(const Coords& coord2);
......
......@@ -184,53 +184,38 @@ void Color::RGBtoHSV(const double r, const double g, const double b,
h += 360;
}
//values between 0 and 1
//h between 0 and 360
void Color::HSVtoRGB(const double h, const double s, const double v, double &r, double &g, double &b)
{
if( s==0 ) {
// achromatic (grey)
if( s==0 ) { //achromatic (grey)
r = g = b = v;
return;
}
const double h_p = h/60; // sector 0 to 5
const int i = (int)floor(h_p); //HACK: replace by static_cast<int>
const double f = h_p - i; // factorial part of h
const double p = v * ( 1 - s );
const double q = v * ( 1 - s * f );
const double t = v * ( 1 - s * ( 1 - f ) );
const double h_p = h/60.; //sector 0 to 5
const int i = static_cast<int>(h_p);
const double f = h_p - i; //factorial part of h
const double p = v * ( 1. - s );
const double q = v * ( 1. - s * f );
const double t = v * ( 1. - s * ( 1. - f ) );
switch( i ) {
case 0:
r = v;
g = t;
b = p;
r = v; g = t; b = p;
break;
case 1:
r = q;
g = v;
b = p;
r = q; g = v; b = p;
break;
case 2:
r = p;
g = v;
b = t;
r = p; g = v; b = t;
break;
case 3:
r = p;
g = q;
b = v;
r = p; g = q; b = v;
break;
case 4:
r = t;
g = p;
b = v;
r = t; g = p; b = v;
break;
default: // case 5:
r = v;
g = p;
b = q;
default: // case 5:
r = v; g = p; b = q;
break;
}
}
......@@ -247,18 +232,28 @@ Gradient::Gradient(const Type& type, const double& i_min, const double& i_max, c
void Gradient::set(const Type& type, const double& i_min, const double& i_max, const bool& i_autoscale)
{
delta_val = i_max - i_min;
autoscale = i_autoscale;
if(type==terrain) model = new terrain_gradient(i_min, i_max, i_autoscale);
else if(type==slope) model = new slope_gradient(i_min, i_max, i_autoscale);
else if(type==azi) model = new azi_gradient(i_min, i_max, i_autoscale);
else if(type==heat) model = new heat_gradient(i_min, i_max, i_autoscale);
else if(type==water) model = new water_gradient(i_min, i_max, i_autoscale);
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);
else if(type==azi) model = new gr_azi(i_min, i_max, i_autoscale);
else if(type==heat) model = new gr_heat(i_min, i_max, i_autoscale);
else if(type==freeze) model = new gr_freeze(i_min, i_max, i_autoscale);
else if(type==blue) model = new gr_blue(i_min, i_max, i_autoscale);
else if(type==blue_pink) model = new gr_blue_pink(i_min, i_max, i_autoscale);
else if(type==pastel) model = new gr_pastel(i_min, i_max, i_autoscale);
}
//val between min_val and max_val
//return values between 0 and 255 per channel
//getColor: take value between min & max, as defined in the constructor (use min/max for rescaling gradient control points). Use autoscale bool only for specific adjustments (ie: remove sea level blue color in autoscale, etc) ie: autoscaling is done purely by the caller, who specifies the min/max for the gradient (and that should be enough)
void Gradient::getColor(const double& val, unsigned char& r, unsigned char& g, unsigned char& b, unsigned char& a) const
{
if(model==NULL) {
throw UnknownValueException("Please set the color gradient before using it!", AT);
}
if(val==IOUtils::nodata) {
r=0; g=0; b=0; a=0;
return;
......@@ -271,13 +266,11 @@ void Gradient::getColor(const double& val, unsigned char& r, unsigned char& g, u
r=0; g=0; b=0; a=255;
return;
}
if(delta_val==0) {
r=g=b=0; a=255;
if(autoscale && delta_val==0) { //constant data through the grid & autoscale are no friends...
r=g=b=125; a=255;
return;
}
//get the rgba components by providing val between 0 and 1
model->getColor(val, r, g, b, a);
}
......@@ -331,9 +324,20 @@ void Gradient_model::getColor(const double &val, unsigned char &r, unsigned char
a = 255; //no alpha for valid values
}
void heat_gradient::getColor(const double &i_val, unsigned char &r, unsigned char &g, unsigned char &b, unsigned char &a) const
/////////////////////////////////////////////////////////////////////////////////////////////////
// Various Gradients
/////////////////////////////////////////////////////////////////////////////////////////////////
void gr_heat::getColor(const double &i_val, unsigned char &r, unsigned char &g, unsigned char &b, unsigned char &a) const
{
const double val = (i_val-min_val)/delta_val; //autoscale HACK: do autoscale, new way!!
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;
......@@ -343,7 +347,42 @@ void heat_gradient::getColor(const double &i_val, unsigned char &r, unsigned cha
a = 255; //no alpha for valid values
}
water_gradient::water_gradient(const double& i_min, const double& i_max, const bool& i_autoscale) {
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);
//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
X.push_back(.4); v_h.push_back(213.); v_s.push_back(.4); v_v.push_back(.95); //violet
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);
//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, unsigned char &r, unsigned char &g, unsigned char &b, unsigned char &a) const
{
r = static_cast<unsigned char>(getInterpol(val, X, v_r)*255);
g = static_cast<unsigned char>(getInterpol(val, X, v_g)*255);
b = static_cast<unsigned char>(getInterpol(val, X, v_b)*255);
a = 255; //no alpha for valid values
}
gr_blue::gr_blue(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
//write gradient control points
......@@ -359,7 +398,22 @@ water_gradient::water_gradient(const double& i_min, const double& i_max, const b
for(size_t i=0; i<X.size(); i++) X[i] = X[i]*delta_val + min_val;
}
terrain_gradient::terrain_gradient(const double& i_min, const double& i_max, const bool& i_autoscale) {
gr_pastel::gr_pastel(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, 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;
}
gr_terrain::gr_terrain(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
//write gradient control points
......@@ -386,7 +440,7 @@ terrain_gradient::terrain_gradient(const double& i_min, const double& i_max, con
}
}
slope_gradient::slope_gradient(const double& i_min, const double& i_max, const bool& i_autoscale) {
gr_slope::gr_slope(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
//write gradient control points
......@@ -402,7 +456,7 @@ slope_gradient::slope_gradient(const double& i_min, const double& i_max, const b
for(size_t i=0; i<X.size(); i++) X[i] = X[i]*delta_val + min_val;
}
azi_gradient::azi_gradient(const double& i_min, const double& i_max, const bool& i_autoscale) {
gr_azi::gr_azi(const double& i_min, const double& i_max, const bool& i_autoscale) {
setMinMax(i_min, i_max, i_autoscale);
//write gradient control points
......@@ -412,8 +466,8 @@ azi_gradient::azi_gradient(const double& i_min, const double& i_max, const bool&
} else {
X.push_back(0.); v_h.push_back(240.); v_s.push_back(.78); v_v.push_back(1.); //blue
X.push_back(.25); v_h.push_back(310.); v_s.push_back(.78); v_v.push_back(1.); //magenta
X.push_back(.5); v_h.push_back(360.); v_s.push_back(.78); v_v.push_back(1.); //red, increasing hue
X.push_back(.5); v_h.push_back(0.); v_s.push_back(.78); v_v.push_back(1.); //red, back to hue=0
X.push_back(.5); v_h.push_back(360.); v_s.push_back(1.); v_v.push_back(1.); //red, increasing hue
X.push_back(.5); v_h.push_back(0.); v_s.push_back(1.); v_v.push_back(1.); //red, back to hue=0
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
}
......
......@@ -37,8 +37,27 @@ namespace mio {
*/
class legend {
public:
/**
* @brief Constructor.
* @param height available height of the plot (for centering the legend)
* @param minimum start value of the legend
* @param maximum end value of the legend
*/
legend(const unsigned int &height, const double &minimum, const double &maximum);
/**
* @brief Get the actual width of the legend
* This is constant but depends on various parameters of the legend: font size, number of characters, spacing etc.
* @return width of the legend
*/
static double getLegendWidth();
/**
* @brief Get the legend in an array
* The legend is coded as values between min and max (+background and text colors) in an array. This array can then be used
* alongside the data array to build the full plot
* @return legend array
*/
const Array2D<double> getLegend();
static const int bg_color; ///<marker for solid background
......@@ -72,13 +91,41 @@ class legend {
};
namespace Color {
/**
* @brief convert RGB to HSV.
* This converts Red-Green-Blue values to Hue-Saturation-Value.
* See https://secure.wikimedia.org/wikipedia/en/wiki/HSL_and_HSV
* or http://www.cs.rit.edu/~ncs/color/t_convert.html
* @param r red (between 0 and 1)
* @param g green (between 0 and 1)
* @param b blue (between 0 and 1)
* @param h hue (between 0 and 360)
* @param s saturation (between 0 and 1)
* @param v value (between 0 and 1)
* @ingroup graphics
*/
void RGBtoHSV(const double r, const double g, const double b, double &h, double &s, double &v);
/**
* @brief convert HSV to RGB.
* This converts Hue-Saturation-Value to Red-Green-Blue values.
* See https://secure.wikimedia.org/wikipedia/en/wiki/HSL_and_HSV
* or http://www.cs.rit.edu/~ncs/color/t_convert.html
* @param h hue (between 0 and 360)
* @param s saturation (between 0 and 1)
* @param v value (between 0 and 1)
* @param r red (between 0 and 1)
* @param g green (between 0 and 1)
* @param b blue (between 0 and 1)
* @ingroup graphics
*/
void HSVtoRGB(const double h, const double s, const double v, double &r, double &g, double &b);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Gradient class
/////////////////////////////////////////////////////////////////////////////////////////////////
//This class is the base class for the various gradients
class Gradient_model {
public:
Gradient_model() {setMinMax(0., 0., true);}; //do not use this constructor!
......@@ -86,7 +133,6 @@ class Gradient_model {
//setBgColor()
//setFgColor()
//val must be between 0 and 1 -> check + in doc? TODO
virtual void getColor(const double &val, unsigned char &r, unsigned char &g, unsigned char &b, unsigned char &a) const;
protected:
double getInterpol(const double& val, const std::vector<double>& X, const std::vector<double>& Y) const;
......@@ -98,59 +144,136 @@ class Gradient_model {
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
};
//getColor: take value between min & max, as defined in the constructor (use min/max for rescaling gradient control points). Use autoscale bool only for specific adjustments (ie: remove sea level blue color in autoscale, etc) ie: autoscaling is done purely by the caller, who specifies the min/max for the gradient (and that should be enough)
/**
* @class Gradient
* @brief This converts numeric values into rgba values.
* The object is initialized with the range that the gradient should cover and the gradient type. Then each numeric value
* that is given will be converted into rgba values from the selected gradient. Data out of range are converted to either
* the minimum or the maximum of the gradient. Alpha channel is ONLY used by special pixels.
*
* Some special pixels are recognized:
* - IOUtils::nodata returns a transparent pixel
* - legend::bg_color returns a white pixel
* - legend::text_color returns a black pixel
*
* The autoscale is handled both by the object and its caller: if "autoscale==true", the gradient might adjust its control points, for
* example removing sea and snow lines in the terrain gradient. The min and max values are used to scale the gradient: all values less than min
* will receive the start color while all values greater than max will receive the end color. Therefore true autoscale is acheived by:
* - setting min/max to the data min/max
* - passing i_autoscale=true so the gradient might receive some specific adjustments
*
* On the other hand, fixed scale is acheived by:
* - setting min/max to fixed values (so the gradient will be rescaled between these fixed boundaries)
* - passing i_autoscale=false so the gradient might be able to set so fix points (like sea and snow line)
*
* @ingroup graphics
* @author Mathias Bavay
* @date 2012-01-06
*/
class Gradient {
public:
/// This enum provides names for possible color gradients
typedef enum TYPE {
terrain, ///< suitable for DEM. if autoscale, then sea and snow line are turned off
slope, ///< suitable to represent slope
azi, ///< suitable to represent slope azimuth. In autoscale, it becomes a two color gradient
heat, ///< the traditional heat gradient (with all its associated shortcomings)
freeze, ///< two, two-color gradients with a sharp transition at 0
blue_pink, ///< blue to pink gradient
pastel, ///< same color scale as "slope" but linear
blue ///< white to slightly violet gradient. This is similar to the one used for the SLF avalanche bulletin
} Type;
/**
* @brief Default Constructor.
* This should be followed by a call to set() before calling getColor
*/
Gradient() {model=NULL; delta_val=0.;};
/**
* @brief Constructor.
* The object will associate to each numeric value RGB values. See class description for more...
* @param type set the color gradient to use, from the enum Gradient::Type
* @param min_val start value of the gradient
* @param max_val end value of the gradient
* @param i_autoscale do autoscale for setting the colors?
*/
Gradient(const Type& type, const double& min_val, const double &max_val, const bool& i_autoscale);
~Gradient() {delete model;};
/**
* @brief Setter
* See class description for more...
* @param type set the color gradient to use, from the enum Gradient::Type
* @param min_val start value of the gradient
* @param max_val end value of the gradient
* @param i_autoscale do autoscale for setting the colors?
*/
void set(const Type& type, const double& min_val, const double &max_val, const bool& i_autoscale);
//setBgColor()
//setFgColor()
/**
* @brief Get RGB values for a given numeric value
* See class description for more explanations on the implementation/behavior
* @param val numerical value to convert
* @param r red (between 0 and 255)
* @param g green (between 0 and 255)
* @param b blue (between 0 and 255)
* @param a alpha (between 0 and 255)
*/
void getColor(const double &val, unsigned char &r, unsigned char &g, unsigned char &b, unsigned char &a) const;
private:
double delta_val;
bool autoscale;
Gradient_model *model;
};
class heat_gradient : public Gradient_model {
class gr_heat : public Gradient_model {
public:
heat_gradient(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) {setMinMax(i_min, i_max, i_autoscale);};
void getColor(const double &i_val, unsigned char &r, unsigned char &g, unsigned char &b, unsigned char &a) const;
};
class water_gradient : public Gradient_model {
class gr_blue_pink : public Gradient_model {
public:
water_gradient(const double& i_min, const double& i_max, const bool& i_autoscale);
gr_blue_pink(const double& i_min, const double& i_max, const bool& i_autoscale);
};
class terrain_gradient : public Gradient_model {
class gr_freeze : public Gradient_model {
public:
terrain_gradient(const double& i_min, const double& i_max, const bool& i_autoscale);
gr_freeze(const double& i_min, const double& i_max, const bool& i_autoscale);
void getColor(const double &val, unsigned char &r, unsigned char &g, unsigned char &b, unsigned char &a) const;
private:
//This gradient is interpolated in RGB color space
std::vector<double> X, v_r,v_g,v_b; ///<control points: vector of X and associated r,g,b. They must be in X ascending order
};
class slope_gradient : public Gradient_model {
class gr_blue : public Gradient_model {
public:
slope_gradient(const double& i_min, const double& i_max, const bool& i_autoscale);
gr_blue(const double& i_min, const double& i_max, const bool& i_autoscale);
};
class azi_gradient : public Gradient_model {
class gr_terrain : public Gradient_model {
public:
azi_gradient(const double& i_min, const double& i_max, const bool& i_autoscale);
gr_terrain(const double& i_min, const double& i_max, const bool& i_autoscale);
};
class Gradient {
class gr_slope : public Gradient_model {
public:
/// This enum provides names for possible color gradients
typedef enum TYPE {
terrain,
slope,
azi,
heat,
water
} Type;
Gradient() {model=NULL; delta_val=0.;};
Gradient(const Type& type, const double& min_val, const double &max_val, const bool& i_autoscale);
~Gradient() {delete model;};
void set(const Type& type, const double& min_val, const double &max_val, const bool& i_autoscale);
//setBgColor()
//setFgColor()
gr_slope(const double& i_min, const double& i_max, const bool& i_autoscale);
};
//val must be between 0 and 1 -> check + in doc? TODO
void getColor(const double &val, unsigned char &r, unsigned char &g, unsigned char &b, unsigned char &a) const;
class gr_azi : public Gradient_model {
public:
gr_azi(const double& i_min, const double& i_max, const bool& i_autoscale);
};
private:
double delta_val;
Gradient_model *model;
class gr_pastel : public Gradient_model {
public:
gr_pastel(const double& i_min, const double& i_max, const bool& i_autoscale);
};
} //namespace
......
......@@ -169,6 +169,17 @@ std::string IOUtils::getExtension(const std::string& filename)
return filename.substr(startpos+1, endpos-startpos);
}
std::string IOUtils::removeExtension(const std::string& filename)
{
const std::string whitespaces(" \t\f\v\n\r");
const size_t start_basename = filename.find_last_of("/\\"); //we will skip the path
const size_t startpos = filename.find_last_of('.');
if( startpos==std::string::npos ) return filename;
if( start_basename!=std::string::npos && startpos<start_basename ) return filename;
return filename.substr(0, startpos);
}
void IOUtils::trim(std::string& str)
{
const std::string whitespaces(" \t\f\v\n\r");
......@@ -189,6 +200,12 @@ void IOUtils::toUpper(std::string& str){
}
}
void IOUtils::toLower(std::string& str){
for(size_t t=0; t<str.length(); t++) {
str[t] = (char)tolower(str[t]);
}
}
bool IOUtils::isNumeric(const std::string& str, const unsigned int& nBase)
{
std::string s = str;
......
......@@ -157,6 +157,15 @@ namespace IOUtils {
*/
std::string getExtension(const std::string& filename);
/**
* @brief remove the extension part of a given filename.
* The extension is defined as all the non-whitespace characters after the last '.'
* in the filename.
* @param filename filename to remove the extension from
* @return filename without extension (the '.' is also removed)
*/
std::string removeExtension(const std::string& filename);
/**
* @brief Removes trailing and leading whitespaces, tabs and newlines from a string.
* @param s The reference of the string to trim (in/out parameter)
......@@ -184,6 +193,7 @@ namespace IOUtils {
const std::string& keyprefix="", const bool& setToUpperCase=false);
void toUpper(std::string& str);
void toLower(std::string& str);
bool isNumeric(const std::string& input, const unsigned int& nBase=10);
size_t readLineToVec(const std::string& line_in, std::vector<std::string>& vecString);
size_t readLineToVec(const std::string& line_in, std::vector<std::string>& vecString, const char& delim);
......
......@@ -40,6 +40,10 @@ namespace mio {
Documentation for available data structures.
*/
/*! \defgroup graphics Graphical elements and operations
Documentation for available classes and methods for dealing with graphical elements, color conversions, etc
*/
/**