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.

206 lines
6.5 KiB

#ifndef MODGMT_OBJECTS_H
#define MODGMT_OBJECTS_H
#include <cmath>
#include <map>
#include <string.h>
#include <type_traits>
#include <vector>
#include "common.h"
#include "modgmt_structs.h"
// Centimeters to GMT points scale factor
// 1 inch = 72 pt = 2.54 cm --> 1 cm = 72/2.54 pt
// GMT's own scaling factor is 0.06
inline static double cm2GMT(double cm)
{
static const double scale=(72.0/2.54)/0.06;
return cm*scale;
}
template<class GMTStruct>
class ObjectGMTClass: public ObjectBase
{
static_assert(std::is_base_of<gmt_struct,GMTStruct>::value,"Template parameter of ObjectGMTClass must be gmt_struct-derived type");
const static std::string type;
GMTStruct s;
public:
// Constructor
ObjectGMTClass(const GMTStruct& n):s(n) {}
// Pure virtual overrides
ObjectBase* Copy() const override {return new ObjectGMTClass(s);}
bool Print() const override
{
COUT(NORMAL)<<std::endl<<"Object type: "<<Type()<<std::endl;
COUT(NORMAL)<<"Value: "<<Value()<<std::endl;
return true;
}
std::string Type() const override {return type;}
// Own functions
ObjectBase* Get(const std::string& gname) const
{
std::string name=gname;
tolower(name);
if("value"==name) return new ObjectString(Value());
return OGet(name);
}
std::string Value() const {return s.Value();}
GMTStruct Data() const {return s;}
private:
// This is class-dependent Get function
ObjectBase* OGet(const std::string& name) const {return 0;}
};
// GMTCoord
typedef ObjectGMTClass<struct gmt_coord> ObjectGMTCoord;
template<> inline ObjectBase* ObjectGMTCoord::OGet(const std::string& name) const
{
if("n"==name || "number"==name) return new ObjectReal(s);
return 0;
}
// GMTRegion
typedef ObjectGMTClass<struct gmt_region> ObjectGMTRegion;
template<> inline ObjectBase* ObjectGMTRegion::OGet(const std::string& name) const
{
if("xb"==name) return new ObjectGMTCoord(s.xb);
if("xe"==name) return new ObjectGMTCoord(s.xe);
if("yb"==name) return new ObjectGMTCoord(s.yb);
if("ye"==name) return new ObjectGMTCoord(s.ye);
return 0;
}
// GMTProjection
typedef ObjectGMTClass<struct gmt_projection> ObjectGMTProjection;
template<> inline ObjectBase* ObjectGMTProjection::OGet(const std::string& name) const
{
if("xb"==name) return new ObjectGMTCoord(s.region.xb);
if("xe"==name) return new ObjectGMTCoord(s.region.xe);
if("yb"==name) return new ObjectGMTCoord(s.region.yb);
if("ye"==name) return new ObjectGMTCoord(s.region.ye);
if("width"==name) return new ObjectReal(s.rwidth);
if("height"==name) return new ObjectReal(s.rheight);
if("region"==name) return new ObjectGMTRegion(s.region);
return 0;
}
// GMTColor
typedef ObjectGMTClass<struct gmt_color> ObjectGMTColor;
template<> inline ObjectBase* ObjectGMTColor::OGet(const std::string& name) const
{
if("gray"==name || "grey"==name) return new ObjectReal(s.Gray());
if("r"==name || "red"==name) return new ObjectReal(s.R());
if("g"==name || "green"==name) return new ObjectReal(s.G());
if("b"==name || "blue"==name) return new ObjectReal(s.B());
if("h"==name || "hue"==name) return new ObjectReal(s.H());
if("s"==name || "saturation"==name) return new ObjectReal(s.S());
if("v"==name || "value"==name) return new ObjectReal(s.V());
if("c"==name || "cyan"==name) return new ObjectReal(s.C());
if("m"==name || "magenta"==name) return new ObjectReal(s.M());
if("y"==name || "yellow"==name) return new ObjectReal(s.Y());
if("k"==name || "black"==name) return new ObjectReal(s.K());
if("t"==name || "transparency"==name) return new ObjectReal(s.transparency);
return 0;
}
// GMTDash
typedef ObjectGMTClass<struct gmt_dash> ObjectGMTDash;
// GMTPen
typedef ObjectGMTClass<struct gmt_pen> ObjectGMTPen;
template<> inline ObjectBase* ObjectGMTPen::OGet(const std::string& name) const
{
if("w"==name || "width"==name) return new ObjectReal(s.width);
if("c"==name || "color"==name) return new ObjectGMTColor(s.color);
if("d"==name || "dash"==name) return new ObjectGMTDash(s.dash);
return 0;
}
// GMTFont
typedef ObjectGMTClass<struct gmt_font> ObjectGMTFont;
template<> inline ObjectBase* ObjectGMTFont::OGet(const std::string& name) const
{
if("s"==name || "size"==name) return new ObjectReal(s.size);
if("f"==name || "family"==name)return new ObjectString(s.family);
if("c"==name || "color"==name) return new ObjectGMTColor(s.color);
return 0;
}
// GMTLayer
class ObjectGMTLayer: public ObjectBase
{
double shiftx,shifty;
struct gmt_projection proj;
std::string creator;
std::shared_ptr<std::string> data;
ObjectGMTLayer() {}
// This is saveable object
virtual const int8_t* Blob(size_t* size) const override
{
if(Shifted())
{
std::string b="V "+ToString(cm2GMT(shiftx))+" "+ToString(cm2GMT(shifty))+" T\n";
std::string e="U\n";
int8_t* p=new int8_t[b.size()+data->size()+e.size()];
memcpy(p,b.data(),b.size());
memcpy(p+b.size(),data->data(),data->size());
memcpy(p+b.size()+data->size(),e.data(),e.size());
return p;
}
else
{
*size=data->size();
return reinterpret_cast<const int8_t*>(data->data());
}
}
virtual void DeallocBlob(const int8_t* ptr) const override
{
if(Shifted()) delete[] ptr;
};
public:
// Constructor
ObjectGMTLayer(const std::string& newdata, const struct gmt_projection& newproj, const std::string& newcreator, double newshiftx=0.0, double newshifty=0.0):shiftx(newshiftx),shifty(newshifty),proj(newproj),creator(newcreator)
{
std::string* pdata=new std::string(newdata.data(),newdata.length()); // To prevent COW
data.reset(pdata);
}
// Pure virtual overrides
ObjectBase* Copy() const override
{
auto ret=new ObjectGMTLayer;
ret->shiftx=shiftx; ret->shifty=shifty;
ret->proj=proj;
ret->creator=creator;
ret->data=data;
return ret;
}
bool Print() const override
{
COUT(NORMAL)<<std::endl<<"Object type: "<<Type()<<std::endl;
COUT(NORMAL)<<"Made by: "<<creator<<std::endl;
COUT(NORMAL)<<"Size: "<<proj.rwidth<<"x"<<proj.rheight<<std::endl;
if(Shifted()) COUT(NORMAL)<<"Shifted by: "<<shiftx<<"x"<<shifty<<std::endl;
return true;
}
std::string Type() const override {return "GMTLayer";}
// Own functions
ObjectBase* Get(const std::string& gname) const
{
std::string name=gname;
tolower(name);
if("proj"==name || "projection"==name) return new ObjectGMTProjection(proj);
if("w"==name || "width"==name) return new ObjectReal(proj.rwidth);
if("h"==name || "height"==name) return new ObjectReal(proj.rheight);
if("shiftx"==name) return new ObjectReal(shiftx);
if("shifty"==name) return new ObjectReal(shifty);
return 0;
}
bool Shifted() const {return shiftx!=0.0 || shifty!=0.0;}
};
#endif