From d458087d33f6b9eb47b1d306942c3ca260400e01 Mon Sep 17 00:00:00 2001 From: Michael Uleysky Date: Wed, 10 Feb 2016 16:04:00 +1000 Subject: [PATCH] Gmt module: Function GMT_DrawFrame for drawing map frame with ticks and annotations. --- modules/gmt/modgmt.cpp | 1 + modules/gmt/modgmt_func.cpp | 213 ++++++++++++++++++++++++++++++++++++ modules/gmt/modgmt_func.h | 3 + 3 files changed, 217 insertions(+) diff --git a/modules/gmt/modgmt.cpp b/modules/gmt/modgmt.cpp index 5896623..59c75a0 100644 --- a/modules/gmt/modgmt.cpp +++ b/modules/gmt/modgmt.cpp @@ -41,5 +41,6 @@ int gmt_module_init(void* p) RegisterFunction("Pen",GMT_Type); RegisterFunction("Font",GMT_Type); RegisterFunction("Shift",GMT_LayerShift); + RegisterFunction("DrawFrame",GMT_DrawFrame); return 0; } diff --git a/modules/gmt/modgmt_func.cpp b/modules/gmt/modgmt_func.cpp index 7873dc2..813d2d6 100644 --- a/modules/gmt/modgmt_func.cpp +++ b/modules/gmt/modgmt_func.cpp @@ -1,5 +1,16 @@ #include "modgmt_func.h" +static double AutoStep(double b, double e) +{ + double n=pow(10.0,ceil(log10(e-b)-1.0)); + double steps[]={0.5,1,2,5,10,0}; + double div=0.0; + uint i=0; + + do if((e-b)*steps[i]/n<10.0) div=n/steps[i]; while(0.0!=steps[++i]); + return div; +} + ObjectBase* GMT_Header(const ObjectList* input) { return new ObjectString(header); @@ -131,3 +142,205 @@ ObjectBase* GMT_LayerShift(const ObjectList* input) fail: return 0; } + + +// Draw frame with tics +/* +Input: pairs list. +proj or projection or unnamed GMTProjection parameter - projection. This is mandatory argument. +xtics - position of tics for x axis. Can be none, up, down or both. Default is down. +ytics - position of tics for y axis. Can be none, left, right or both. Default is left. +xint - tics interval for x axis. Numerical value or word auto. Default is auto. +yint - tics interval for y axis. Numerical value or word auto. Default is auto. +domain - coordinates domain. Can be pos (0:360), neg (-360:0) or center (-180:180) (only for geographic projections). Default is pos. +mark - using letters (W, E, S, N) instead of sign for coordinates (only for geographic projections). Can be yes or no. Default is no. +font - font using for annotations. Default is 12,Times-Roman,black. +offset - distance from end of tick-mark to start of annotation in cm. Default is 0.18. +framewidth - width of frame (only for geographic projections) in cm. Default is 0.1. +framepen - pen for drawing frame. Default is 0.35,black. +ticklen - lenght of tick-marks in cm. Default is 0.18. +tickpen - pen for drawing ticks. Default is 0.3,black. +trans or transparency - transparency level, double from 0 to 100. Default is 0 (opaque). +transpmodel - transparency model, string. Choose from Color, ColorBurn, ColorDodge, Darken, Difference, Exclusion, HardLight, Hue, Lighten, Luminosity, Multiply, Normal, Overlay, Saturation, SoftLight, and Screen. Default is Normal. +x, xr or xrel - shift layer on x cm in horisontal direction. Default is 0. +y, yr or yrel - shift layer on y cm in vertical direction. Default is 0. +*/ +ObjectBase* GMT_DrawFrame(const ObjectList* input) +{ + std::string opts="-P -O -K "; + bool suc=true; + struct gmt_layer layer; + // Defaults + std::string defxtics="down", defytics="left", defint="auto", defdomain="pos", deftranspmodel="Normal"; + bool defmark=false; + gmt_font deffont; deffont.Convert("12,Times-Roman,black"); + double defoffset=0.18, defframewidth=0.1, defticklen=0.18; + gmt_pen defframepen, deftickpen; defframepen.Convert("0.35,black"); deftickpen.Convert("0.3,black"); + + { // Get projection + BaseMT2Projection proj(input,"proj","projection"); + + layer.proj=proj(&suc); + if(!suc) goto fail; + opts+=layer.proj.Value()+" "; + } + + { // Get xint and yint + BaseMD2String xint(input,defint,"xint"), yint(input,defint,"yint"); + double dx,dy; + std::string str; + + str=xint(&suc); + if(suc && "auto"==str) dx=AutoStep(layer.proj.region.xb,layer.proj.region.xe); + else // No auto, get numeric value + { + Base2Double xint(input,"xint"); + suc=true; + dx=xint(&suc); + if(!suc) goto fail; // Parameter exists, but conversion failed + } + + str=yint(&suc); + if(suc && "auto"==str) dy=AutoStep(layer.proj.region.yb,layer.proj.region.ye); + else // No auto, get numeric value + { + Base2Double yint(input,"yint"); + suc=true; + dy=yint(&suc); + if(!suc) goto fail; // Parameter exists, but conversion failed + } + opts+="-Bx"+ToString(dx)+" -By"+ToString(dy)+" "; + } + + { // Get xtics and ytics + BaseMD2String x(input,defxtics,"xtics"), y(input,defytics,"ytics"); + std::string xtics,ytics; + std::string xaxis,yaxis; + + xtics=x(&suc); + if(!suc) goto fail; // Conversion failed + if("none"==xtics) xaxis="sn"; + if("down"==xtics) xaxis="Sn"; + if("up"==xtics) xaxis="sN"; + if("both"==xtics) xaxis="SN"; + + ytics=y(&suc); + if(!suc) goto fail; // Conversion failed + if("none"==ytics) yaxis="we"; + if("left"==ytics) yaxis="We"; + if("right"==ytics) yaxis="wE"; + if("both"==ytics) yaxis="WE"; + + if(xaxis.empty() || yaxis.empty()) goto fail; // Unknown value of xtics and/or ytics + + opts+="-B"+xaxis+yaxis+" "; + } + + { // Get domain and mark + BaseMD2String d(input,defdomain,"domain"); + BaseMD2Bool m(input,defmark,"mark"); + std::string format; + + std::string domain=d(&suc); + if(!suc) goto fail; // Conversion failed + if("pos"==domain) format="+ddd:mm:ss"; + if("neg"==domain) format="-ddd:mm:ss"; + if("center"==domain) format="ddd:mm:ss"; + if(format.empty()) goto fail; // Unknown domain + + if(m(&suc)) format+="F"; + if(!suc) goto fail; // Conversion failed + + opts+="--FORMAT_GEO_MAP="+format+" "; + } + + { // Get font + BaseMD2Font f(input,deffont,"font"); + gmt_font font; + font=f(&suc); + if(!suc) goto fail; // Conversion failed + opts+="--FONT_ANNOT_PRIMARY="+font.Value()+" "; + } + + { // Get offset + BaseMD2Double o(input,defoffset,"offset"); + double offset; + offset=o(&suc); + if(!suc) goto fail; // Conversion failed + opts+="--MAP_ANNOT_OFFSET_PRIMARY="+ToString(offset)+"c "; + } + + { // Get framewidth + SearchParameterWDef > f(input,defframewidth,"framewidth"); + double framewidth; + framewidth=f(&suc); + if(!suc) goto fail; // Conversion failed + opts+="--MAP_FRAME_WIDTH="+ToString(framewidth)+"c "; + } + + { // Get framepen + BaseMD2Pen p(input,defframepen,"framepen"); + gmt_pen framepen; + framepen=p(&suc); + if(!suc) goto fail; // Conversion failed + opts+="--MAP_FRAME_PEN="+framepen.Value()+" "; + } + + { // Get ticklen + BaseMD2Double t(input,defticklen,"ticklen","ticklength"); + double ticklen; + ticklen=t(&suc); + if(!suc) goto fail; // Conversion failed + opts+="--MAP_TICK_LENGTH_PRIMARY="+ToString(ticklen)+"c "; + } + + { // Get tickpen + BaseMD2Pen t(input,deftickpen,"tickpen"); + gmt_pen tickpen; + tickpen=t(&suc); + if(!suc) goto fail; // Conversion failed + opts+="--MAP_TICK_PEN_PRIMARY="+tickpen.Value()+" "; + } + + { // Get transparency + Base2Transp t(input,"trans","transp","transparency"); + double transp; + transp=t(&suc); + if(!suc) goto fail; // Conversion failed + if(transp!=0) opts+="-t"+ToString(transp)+" "; + } + + { // Get transpmodel + BaseMD2String tm(input,deftranspmodel,"transpmodel","transparencymodel"); + std::string transpmodel; + transpmodel=tm(&suc); + if(!suc) goto fail; // Conversion failed + opts+="--PS_TRANSPARENCY="+transpmodel+" "; + } + + { // Get x, y + BaseMD2Double x(input,0.0,"x","xr","xrel"), y(input,0.0,"y","yr","yrel"); + layer.shiftx=x(&suc); + layer.shifty=y(&suc); + if(!suc) goto fail; // Conversion failed + } + + { // Calling psbasemap + void* gmtapi; + std::string* draw=new std::string; + int ret; + + gmtapi=GMT_Create_Session("DrawFrame",2,GMTMODE,0); + if(0==gmtapi) goto fail; // Can't create GMT GMT_Create_Session + ret=callgmtmodule(gmtapi,"psbasemap",opts,draw); + GMT_Destroy_Session(gmtapi); + if(0!=ret) {delete draw; goto fail;} // Psbasemap error + layer.data.reset(draw); + } + + layer.creator="psbasemap "+opts; + return new ObjectGMTLayer(layer); + + fail: + return 0; +} diff --git a/modules/gmt/modgmt_func.h b/modules/gmt/modgmt_func.h index 61effd9..4899020 100644 --- a/modules/gmt/modgmt_func.h +++ b/modules/gmt/modgmt_func.h @@ -1441,4 +1441,7 @@ ObjectBase* GMT_Type(const ObjectList* input) // Shift position of layer ObjectBase* GMT_LayerShift(const ObjectList* input); +// Draw frame with tics +ObjectBase* GMT_DrawFrame(const ObjectList* input); + #endif