Browse Source

Gmt module: Add function Pen.

ObjPtr
Michael Uleysky 9 years ago
parent
commit
8c2f0c6ef8
  1. 1
      modules/gmt/modgmt.cpp
  2. 239
      modules/gmt/modgmt_func.cpp
  3. 1
      modules/gmt/modgmt_func.h
  4. 94
      modules/gmt/modgmt_structs.h

1
modules/gmt/modgmt.cpp

@ -36,5 +36,6 @@ int gmt_module_init(void* p)
RegisterFunction("ColorRGB",GMT_ColorRGB);
RegisterFunction("ColorHSV",GMT_ColorHSV);
RegisterFunction("ColorCMYK",GMT_ColorCMYK);
RegisterFunction("Pen",GMT_Pen);
return 0;
}

239
modules/gmt/modgmt_func.cpp

@ -1122,6 +1122,225 @@ class ColorConv<ObjectList>
}
};
// Helper types
typedef GetDouble<PMin<0>,PDefaultVal<>> Base2Width;
typedef GetDouble<PMin<0>,PMultiInputNames> BaseM2Width;
// Converting String to GMTDash
template<class O> class DashConv
{
public:
struct gmt_dash operator()(const O* o, bool* issuc, const double& w) const
{
struct gmt_dash d;
if(!d.Convert(o->Value(),w)) *issuc=false;
return d;
}
};
// Special case is GMTDash
template<>
class DashConv<ObjectGMTDash>
{
public:
struct gmt_dash operator()(const ObjectGMTDash* o, bool* suc, const double& w) const {return o->Data();}
};
typedef Base2Something<DashConv,ObjectString,ObjectGMTDash> Base2Dash;
// Converting List to GMTPen
template<class O> class PenConv
{
public:
struct gmt_pen operator()(const O* o, bool* issuc) const
{
struct gmt_pen p;
if(!p.Convert(o->Value())) *issuc=false;
return p;
}
};
// Special case is GMTPen
template<>
class PenConv<ObjectGMTPen>
{
public:
struct gmt_pen operator()(const ObjectGMTPen* o, bool* suc) const {return o->Data();}
};
typedef Base2Something<PenConv,ObjectList,ObjectString,ObjectReal,ObjectInt,ObjectGMTPen> Base2Pen;
// Conversion from List
template<>
class PenConv<ObjectList>
{
public:
// Cases see in description of GMT_Pen function
struct gmt_pen operator()(const ObjectList* input, bool* issuc) const
{
struct gmt_pen p;
auto size=input->Size();
if(1==size) // Cases 1, 2 and 4
{
Base2Pen a(input,0);
bool suc=true;
p=a(&suc);
if(suc) return p;
goto fail;
}
// Case 3
{
bool upd=false;
bool casevalid=false;
// Update case, arguments list contains parameter with type GMTPen.
for(ObjectList::ListValues::size_type i=0;i<size;i++)
{
OBType<ObjectGMTPen> pen(input->At(i));
if(pen)
{
if(upd) goto fail; // Only one pen in list allowed
p=pen->Data();
upd=true;
}
}
// Update case, arguments list contains parameter p or pen.
{
Base2Pen pshort(input,"p");
Base2Pen plong(input,"pen");
if(pshort.Exist() && plong.Exist()) goto fail; // Only one parameter allowed
if(pshort.Exist())
{
if(upd) goto fail; // Already have pen to update
bool suc=true;
upd=true;
p=pshort(&suc);
if(!suc) goto fail; // Parse error
}
if(plong.Exist())
{
if(upd) goto fail; // Already have pen to update
upd=true;
bool suc=true;
p=plong(&suc);
if(!suc) goto fail; // Parse error
}
}
if(!upd)
{
// default pen is solid black 1mm width
p.width=1;
p.color.Convert(0);
p.dash.Clear();
}
{
BaseM2Width w(input,"w","width");
if(w.Exist())
{
bool suc=true;
p.width=w(&suc);
if(!suc) goto fail; // Parsing error
casevalid=true;
}
}
// Color
{
bool havec=false;
// Find parameter with type GMTColor.
for(ObjectList::ListValues::size_type i=0;i<size;i++)
{
OBType<ObjectGMTColor> c(input->At(i));
if(c)
{
if(havec) goto fail; // Only one color in list allowed
p.color=c->Data();
havec=true;
}
}
Base2Color sh(input,"c"), lo(input,"color");
if(sh.Exist() && lo.Exist()) goto fail; // Only one parameter allowed
if(sh.Exist())
{
if(havec) goto fail; // Already have color
havec=true;
bool suc=true;
p.color=sh(&suc);
if(!suc) goto fail; // Parsing error
}
if(lo.Exist())
{
if(havec) goto fail; // Already have color
havec=true;
bool suc=true;
p.color=lo(&suc);
if(!suc) goto fail; // Parsing error
}
if(havec) casevalid=true;
}
// Dash
{
bool haved=false;
// Find parameter with type GMTDash.
for(ObjectList::ListValues::size_type i=0;i<size;i++)
{
OBType<ObjectGMTDash> d(input->At(i));
if(d)
{
if(haved) goto fail; // Only one color in list allowed
p.dash=d->Data();
haved=true;
}
}
Base2Dash sh(input,"d"), lo(input,"dash");
if(sh.Exist() && lo.Exist()) goto fail; // Only one parameter allowed
if(sh.Exist())
{
if(haved) goto fail; // Already have color
haved=true;
bool suc=true;
p.dash=sh(&suc,p.width);
if(!suc) goto fail; // Parsing error
}
if(lo.Exist())
{
if(haved) goto fail; // Already have color
haved=true;
bool suc=true;
p.dash=lo(&suc,p.width);
if(!suc) goto fail; // Parsing error
}
if(haved) casevalid=true;
}
if(casevalid || upd) return p; // Pen created or updated
}
// Case 5 and 6
if(2==size || 3==size)
{
Base2Width w(input,0);
Base2Color c(input,1);
Base2Dash d(input,2);
bool suc=true;
if(w && c)
{
p.width=w(&suc);
p.color=c(&suc);
}
else goto fail; // Something wrong
if(d) p.dash=d(&suc,p.width);
if(!suc) goto fail; // Something wrong
return p;
}
fail:
*issuc=false;
return p; // Something go wrong
}
};
/*
Input is one argument, Int, Real, String or GMTCoord.
ObjectString can be number or in form "dd:mm[:ss]", where dd is degrees from -360 to 360, mm is minutes from 0 to 59
@ -1269,3 +1488,23 @@ ObjectBase* GMT_ColorCMYK(const ObjectList* input)
if(suc) return new ObjectGMTColor(c);
else return 0;
}
/*
Input:
1) One argument, Pen. Return copy of this argument.
2) One argument, list. Recursively calling GMT_Pen.
3) Pairs list. Names are width (w), color(c), dash(f). Default values is 1 for width, black for color and solid for dash.
If pair with name pen(p) exists in list, when recursively calling GMT_Line on the value of this parameter, when modify it with specified parameters.
If argument with type Pen exists in list, when copy it and modify with specified parameters.
Instead of color and dash unnamed parameters with Color and Dash types may be used.
4) One argument, interprets as width of black solid line.
5) Two arguments, interprets as width and color of solid line.
6) Three arguments, interprets as width, color and dash.
*/
ObjectBase* GMT_Pen(const ObjectList* input)
{
bool suc=true;
struct gmt_pen p=PenConv<ObjectList>()(input,&suc);
if(suc) return new ObjectGMTPen(p);
else return 0;
}

1
modules/gmt/modgmt_func.h

@ -12,5 +12,6 @@ ObjectBase* GMT_ColorGray(const ObjectList* input);
ObjectBase* GMT_ColorRGB(const ObjectList* input);
ObjectBase* GMT_ColorHSV(const ObjectList* input);
ObjectBase* GMT_ColorCMYK(const ObjectList* input);
ObjectBase* GMT_Pen(const ObjectList* input);
#endif

94
modules/gmt/modgmt_structs.h

@ -601,6 +601,8 @@ struct gmt_color
#include "modgmt_colortransform.h"
};
// Helper types for pens
typedef GetDouble<PMin<0>,PFromValue> Value2Width;
// Dash
struct gmt_dash
@ -611,12 +613,54 @@ struct gmt_dash
{
std::string ret;
if(dash.empty()) return ret;
for(auto i:dash) ret+=std::to_string(i)+"_";
for(auto i:dash) ret+=std::to_string(i/10.0)+"_";
ret.back()=':';
ret+=std::to_string(shift)+"c";
return ret;
}
operator bool() const {return !dash.empty();}
void Clear() {dash.clear(); shift=0.0;}
bool Convert(const std::string& in, const double& w)
{
Clear();
shift=0;
if(0==in.size()) return true; // No dash
if(std::string::npos==in.find_first_not_of(".-")) // dot-dash form
{
double width=(0==w)?1:w;
for(const auto& i:in)
{
if('.'==i) dash.push_back(width); // Dot
else dash.push_back(8*width); // Dash
dash.push_back(4*width); // Gap
}
return true;
}
std::string dstr=in;
// Determine shift
{
WordList wl=Split(in,":");
if(wl.size()>1) return false;
if(1==wl.size())
{
Value2Width s(wl.back());
bool suc=true;
shift=s(&suc);
if(!suc) return false; // Parse error
dstr=wl.front();
}
}
WordList wl=Split(dstr,"_");
for(const auto& i:wl)
{
Value2Width d(i);
bool suc=true;
dash.push_back(d(&suc));
if(!suc) return false; // Parse error
}
return true;
}
};
@ -626,6 +670,52 @@ 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()):"");}
std::string Value() const {return std::to_string(width/10.0)+"c,"+color.Value()+(dash?(","+dash.Value()):"");}
// Interpret one numeric argument as width value
bool Convert(double in)
{
Value2Width w(in);
bool suc=true;
color.Convert(0); // Black
dash.Clear();
width=w(&suc);
return suc;
}
// Convert from string
bool Convert(const std::string& istr)
{
std::string str=istr;
WordList::const_iterator ci;
tolower(str);
WordList wl=Split(str,",",true);
// Defaults
width=1;
color.Convert(0); // Black
dash.Clear();
if(wl.size()>3) return false; // String is [width][,color][,dash]
ci=wl.begin();
if(wl.end()!=ci && 0!=ci->size())
{
Value2Width w(*ci);
bool suc=true;
width=w(&suc);
if(!suc) return false; // Parse error
}
if(wl.end()!=ci) ci++;
if(wl.end()!=ci && 0!=ci->size())
{
if(!color.Convert(*ci)) return false; // Parse error
}
if(wl.end()!=ci) ci++;
if(wl.end()!=ci && 0!=ci->size())
{
if(!dash.Convert(*ci,width)) return false; // Parse error
}
return true;
}
};
#endif

Loading…
Cancel
Save