You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

404 lines
9.2 KiB

#ifndef MODGMT_STRUCT_H
#define MODGMT_STRUCT_H
#include <cinttypes>
#include <cmath>
#include <map>
#include "common.h"
// Coordinate
struct gmt_coord
{
bool isdeg;
union
{
double r;
struct
{
bool sign;
uint16_t d;
uint8_t m;
double s;
};
};
std::string Value() const
{
if(!isdeg) return std::to_string(r);
else return (sign?"":"-")+std::to_string(d)+":"+std::to_string(m)+(s==0?"":":"+std::to_string(s));
}
operator double() const
{
if(isdeg) return (d+(m+s/60.0)/60.0)*(sign?1:-1);
else return r;
}
bool Convert(const std::string& str)
{
WordList wl;
WordList::const_iterator cw;
wl=Split(str,":",true);
if(1==wl.size()) // No dd:mm
{
isdeg=false;
return str2double(str,&r);
}
if(0==wl.size() || wl.size()>3) return false;
isdeg=true;
int64_t res;
// degrees
cw=wl.begin();
if(!str2int(*cw,&res)) return false;
if(res>360 || res<-360) res%=360;
sign=(std::string::npos==cw->find('-'));
d=static_cast<uint16_t>(sign?res:-res);
// minutes
cw++;
if(!str2int(*cw,&res)) return false;
if(res<0 || res>=60) return false;
m=static_cast<uint8_t>(res);
s=0;
// seconds
cw++;
if(wl.end()==cw) return true; // No seconds
if(!str2double(*cw,&s) ) return false;
if(s<0.0 || s>=60.0) return false;
return true;
}
bool Convert(double num)
{
isdeg=false;
r=num;
return true;
}
};
// Region
struct gmt_region
{
enum Type {NORMAL,BBOX,GLOBAL360,GLOBAL180};
Type type;
struct gmt_coord xb,xe,yb,ye;
std::string Value() const
{
switch(type)
{
case(NORMAL): return std::string("-R")+xb.Value()+"/"+xe.Value()+"/"+yb.Value()+"/"+ye.Value();
case(BBOX): return std::string("-R")+xb.Value()+"/"+yb.Value()+"/"+xe.Value()+"/"+ye.Value()+"r";
case(GLOBAL360): return "-Rg";
case(GLOBAL180): return "-Rd";
}
return "";
}
// Only "global", "global180" and "global360"
// TODO: add parsing of "-R" strings
bool Convert(const std::string& istr)
{
std::string str=istr;
tolower(str);
if("global180"==str)
{
type=GLOBAL180;
xb.Convert(-180.0); xe.Convert(180.0);
yb.Convert(-90.0); ye.Convert(90.0);
return true;
}
if("global360"==str || "global"==str)
{
type=GLOBAL360;
xb.Convert(0.0); xe.Convert(360.0);
yb.Convert(-90.0); ye.Convert(90.0);
return true;
}
return false;
}
// Make by coordinates
bool Convert(struct gmt_coord ixb, struct gmt_coord ixe, struct gmt_coord iyb, struct gmt_coord iye, bool isbbox=false)
{
type=isbbox?BBOX:NORMAL;
xb=ixb; yb=iyb; xe=ixe; ye=iye;
return true;
}
};
// Projection
struct gmt_projection
{
// OBLIQMERCATOR types
enum class OType {NOTDEF,A,B,C};
// No UTM (-Ju)
enum projection {NOTDEF,XY,CYL_EQU,MERCATOR,TRANSMERCATOR,OBLIQMERCATOR,CASSINI,CYL_EQA,MILLER,CYL_STERE};
// Real size in cm of drawing area
double rwidth,rheight;
struct gmt_region region;
projection proj;
double width; // parameter of projection
static const double default_width;
union // other projection parameters
{
// XY
struct {double height;} x;
// Cylindrical projections
// CYL_EQU (Cylindrical Equidistant -Jq)
struct {struct gmt_coord stpar,cmer;} q;
// MERCATOR (-Jm)
struct {struct gmt_coord stpar,cmer;} m;
// TRANSMERCATOR (-Jt)
struct {struct gmt_coord cmer,orlat; double scale;} t;
// OBLIQMERCATOR (-Jo)
struct
{
OType type;
struct gmt_coord clon,clat;
union
{
struct gmt_coord azimuth; // A
struct {struct gmt_coord eqlon,eqlat;}; // B
struct {struct gmt_coord polelon,polelat;}; // C
};
} o;
// CASSINI (-Jc)
struct {struct gmt_coord clon,clat;} c;
// CYL_EQA (Cylindrical equal-area -Jy)
struct {struct gmt_coord stpar,cmer;} y;
// MILLER (-Jj)
struct {struct gmt_coord cmer;} j;
// CYL_STERE (Cylindrical stereographic -Jcyl_stere)
struct {struct gmt_coord stpar,cmer;} cyl_stere;
};
std::string Value() const
{
std::string ret;
switch(proj)
{
case(XY): {ret="-JX"+std::to_string(width)+"c/"+std::to_string(x.height)+"c"; break;}
case(CYL_EQU): {ret="-JQ"+q.cmer.Value()+"/"+q.stpar.Value()+"/"+std::to_string(width)+"c"; break;}
case(MERCATOR): {ret="-JM"+m.cmer.Value()+"/"+m.stpar.Value()+"/"+std::to_string(width)+"c"; break;}
case(TRANSMERCATOR): {ret="-JT"+t.cmer.Value()+"/"+t.orlat.Value()+"/"+std::to_string(width)+"c --PROJ_SCALE_FACTOR="+std::to_string(t.scale); break;}
case(OBLIQMERCATOR):
{
switch(o.type)
{
case(OType::A): {ret="-JOa"+o.clon.Value()+"/"+o.clat.Value()+"/"+o.azimuth.Value()+"/"+std::to_string(width)+"c"; break;}
case(OType::B): {ret="-JOb"+o.clon.Value()+"/"+o.clat.Value()+"/"+o.eqlon.Value()+"/"+o.eqlat.Value()+"/"+std::to_string(width)+"c"; break;}
case(OType::C): {ret="-JOb"+o.clon.Value()+"/"+o.clat.Value()+"/"+o.polelon.Value()+"/"+o.polelat.Value()+"/"+std::to_string(width)+"c"; break;}
default: return "";
}
}
case(CASSINI): {ret="-JC"+c.clon.Value()+"/"+c.clat.Value()+"/"+std::to_string(width)+"c"; break;}
case(CYL_EQA): {ret="-JY"+y.stpar.Value()+"/"+y.cmer.Value()+"/"+std::to_string(width)+"c"; break;}
case(MILLER): {ret="-JJ"+j.cmer.Value()+"/"+std::to_string(width)+"c"; break;}
case(CYL_STERE): {ret="-JCyl_stere"+cyl_stere.stpar.Value()+"/"+cyl_stere.cmer.Value()+"/"+std::to_string(width)+"c"; break;}
default: return "";
}
ret+=" "+region.Value();
return ret;
}
bool SetType(const std::string& s)
{
proj=NOTDEF;
std::string str=s;
tolower(str);
if(projnames.end()==projnames.find(s)) return false;
proj=projnames[s];
return true;
}
static void FillProjNames();
private:
static std::map<std::string,projection> projnames;
};
// Color
struct gmt_color
{
enum ColorModel {RGB,GRAY,HSV,CMYK};
ColorModel model;
union
{
double gray; // 0-255
struct {double r,g,b;}; // 0-255
struct {double hue,saturation,value;}; // 0-360, 0-1, 0-1
struct {double cyan,magenta,yellow,black;}; // 0-100
};
double transparency;
std::string Value() const
{
std::string trans=(transparency!=0)?("@"+std::to_string(transparency)):"";
switch(model)
{
case(RGB): return std::to_string(r)+"/"+std::to_string(g)+"/"+std::to_string(b)+trans;
case(GRAY): return std::to_string(gray)+trans;
case(HSV): return std::to_string(hue)+"-"+std::to_string(saturation)+"-"+std::to_string(value)+trans;
case(CMYK): return std::to_string(cyan)+"/"+std::to_string(magenta)+"/"+std::to_string(yellow)+"/"+std::to_string(black)+trans;
}
return "";
}
double Gray() const
{
switch(model)
{
case(RGB): return RGB2Gray().gray;
case(GRAY): return gray;
case(HSV): return HSV2Gray().gray;
case(CMYK): return CMYK2Gray().gray;
}
return 0;
}
double R() const
{
switch(model)
{
case(RGB): return r;
case(GRAY): return Gray2RGB().r;
case(HSV): return HSV2RGB().r;
case(CMYK): return CMYK2RGB().r;
}
return 0;
}
double G() const
{
switch(model)
{
case(RGB): return g;
case(GRAY): return Gray2RGB().g;
case(HSV): return HSV2RGB().g;
case(CMYK): return CMYK2RGB().g;
}
return 0;
}
double B() const
{
switch(model)
{
case(RGB): return b;
case(GRAY): return Gray2RGB().b;
case(HSV): return HSV2RGB().b;
case(CMYK): return CMYK2RGB().b;
}
return 0;
}
double H() const
{
switch(model)
{
case(RGB): return RGB2HSV().hue;
case(GRAY): return Gray2HSV().hue;
case(HSV): return hue;
case(CMYK): return CMYK2HSV().hue;
}
return 0;// Own functions
}
double S() const
{
switch(model)
{
case(RGB): return RGB2HSV().saturation;
case(GRAY): return Gray2HSV().saturation;
case(HSV): return saturation;
case(CMYK): return CMYK2HSV().saturation;
}
return 0;
}
double V() const
{
switch(model)
{
case(RGB): return RGB2HSV().value;
case(GRAY): return Gray2HSV().value;
case(HSV): return value;
case(CMYK): return CMYK2HSV().value;
}
return 0;
}
double C() const
{
switch(model)
{
case(RGB): return RGB2CMYK().cyan;
case(GRAY): return Gray2CMYK().cyan;
case(HSV): return HSV2CMYK().cyan;
case(CMYK): return cyan;
}
return 0;
}
double M() const
{
switch(model)
{
case(RGB): return RGB2CMYK().magenta;
case(GRAY): return Gray2CMYK().magenta;
case(HSV): return HSV2CMYK().magenta;
case(CMYK): return magenta;
}
return 0;
}
double Y() const
{
switch(model)
{
case(RGB): return RGB2CMYK().yellow;
case(GRAY): return Gray2CMYK().yellow;
case(HSV): return HSV2CMYK().yellow;
case(CMYK): return yellow;
}
return 0;
}
double K() const
{
switch(model)
{
case(RGB): return RGB2CMYK().black;
case(GRAY): return Gray2CMYK().black;
case(HSV): return HSV2CMYK().black;
case(CMYK): return black;
}
return 0;
}
// Transformation functions
private:
#include "colortransform.h"
};
// Dash
struct gmt_dash
{
std::vector<double> dash;
double shift;
std::string Value() const
{
std::string ret;
if(dash.empty()) return ret;
for(auto i:dash) ret+=std::to_string(i)+"_";
ret.back()=':';
ret+=std::to_string(shift)+"c";
return ret;
}
operator bool() const {return !dash.empty();}
};
// Pen
struct gmt_pen
{
double width;
struct gmt_color color;
struct gmt_dash dash;
std::string Value() const {return std::to_string(width)+","+color.Value()+(dash?(","+dash.Value()):"");}
};
#endif