Browse Source
Realization of Coord, Region and Projection functions. Move some code from modgmt to modgmt_internals. Some helper functions.ObjPtr
Michael Uleysky
9 years ago
6 changed files with 999 additions and 96 deletions
@ -1,87 +1,35 @@ |
|||||||
#include "modgmt.h" |
#include "modgmt.h" |
||||||
#include "modgmt_func.h" |
#include "modgmt_func.h" |
||||||
|
#include "modgmt_internals.h" |
||||||
std::string header,footer; |
|
||||||
|
|
||||||
#if defined MODGMT_WORKAROUND_EXIT |
|
||||||
// Exit handler.
|
|
||||||
static void gmtonexithandler(int ret, void* x) |
|
||||||
{ |
|
||||||
reinterpret_cast<struct gmtworkthreadpars*>(x)->ret=ret; |
|
||||||
close(reinterpret_cast<struct gmtworkthreadpars*>(x)->fd); |
|
||||||
pthread_exit(&(reinterpret_cast<struct gmtworkthreadpars*>(x)->ret)); |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
// This function call GMT_Call_Module in separate thread. It just a hack to workaround absence of callbacks.
|
|
||||||
static void* gmtworkthread(void* x) |
|
||||||
{ |
|
||||||
struct gmtworkthreadpars* p=reinterpret_cast<struct gmtworkthreadpars*>(x); |
|
||||||
#if defined MODGMT_WORKAROUND_EXIT |
|
||||||
on_exit(gmtonexithandler,x); |
|
||||||
#endif |
|
||||||
GMT_Append_Option(p->api,GMT_Make_Option(p->api,'>',const_cast<char*>(("/dev/fd/"+std::to_string(p->fd)).c_str())),p->opts); |
|
||||||
p->ret=GMT_Call_Module(p->api,p->module,GMT_MODULE_OPT,p->opts); |
|
||||||
#if defined MODGMT_WORKAROUND_EXIT |
|
||||||
exit(p->ret); |
|
||||||
#endif |
|
||||||
close(p->fd); |
|
||||||
return &p->ret; |
|
||||||
} |
|
||||||
|
|
||||||
// Wrapper for GMT_Call_Module, res is output.
|
|
||||||
int callgmtmodule(void *api, const char *module, struct GMT_OPTION *opts, std::string* res, gmt_filter filt, void* filtpar) |
|
||||||
{ |
|
||||||
int pipefd[2]; |
|
||||||
pthread_t wthr; |
|
||||||
struct gmtworkthreadpars p; |
|
||||||
int *pret; |
|
||||||
|
|
||||||
pipe(pipefd); |
|
||||||
p.api=api; |
|
||||||
p.module=module; |
|
||||||
p.opts=opts; |
|
||||||
p.fd=pipefd[1]; |
|
||||||
|
|
||||||
pthread_create(&wthr,0,&gmtworkthread,&p); |
|
||||||
res->erase(); |
|
||||||
|
|
||||||
(*filt)(pipefd[0],res,filtpar); |
|
||||||
|
|
||||||
res->shrink_to_fit(); |
|
||||||
pthread_join(wthr,reinterpret_cast<void**>(&pret)); |
|
||||||
|
|
||||||
return *pret; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// Initialisation function
|
// Initialisation function
|
||||||
int gmt_module_init(void* p) |
int gmt_module_init(void* p) |
||||||
{ |
{ |
||||||
// Fill header and footer
|
// Fill header and footer
|
||||||
struct GMT_OPTION* opts; |
|
||||||
void* gmtapi; |
void* gmtapi; |
||||||
int ret; |
int ret=0; |
||||||
const char* ch="--GMT_HISTORY=f -C -P -K"; |
|
||||||
const char* cf="--GMT_HISTORY=f -C -P -O"; |
|
||||||
char* h=strdup(ch); |
|
||||||
char* f=strdup(cf); |
|
||||||
|
|
||||||
gmtapi=GMT_Create_Session("gmt_makemap",2,3,0); |
gmtapi=GMT_Create_Session("gmt_makemap",2,GMTMODE,0); |
||||||
if(0==gmtapi) return 1; |
if(0==gmtapi) return 1; |
||||||
opts=GMT_Create_Options(gmtapi,0,h); |
if(0==ret) ret=callgmtmodule(gmtapi,"psclip","-C -P -K",&header,gmt_filter_headfoot); |
||||||
ret=callgmtmodule(gmtapi,"psclip",opts,&header,gmt_filter_headfoot); |
if(0==ret) ret=callgmtmodule(gmtapi,"psclip","-C -P -O",&footer,gmt_filter_headfoot); |
||||||
GMT_Destroy_Options(gmtapi,&opts); |
|
||||||
opts=GMT_Create_Options(gmtapi,0,f); |
|
||||||
if(0==ret) ret=callgmtmodule(gmtapi,"psclip",opts,&footer,gmt_filter_headfoot); |
|
||||||
GMT_Destroy_Options(gmtapi,&opts); |
|
||||||
GMT_Destroy_Session(gmtapi); |
GMT_Destroy_Session(gmtapi); |
||||||
free(h); free(f); |
|
||||||
if(0!=ret) return ret; |
if(0!=ret) return ret; |
||||||
|
|
||||||
gmt_projection::FillProjNames(); |
gmt_projection::FillProjNames(); |
||||||
|
|
||||||
RegisterFunction("GMT_Header",GMT_Header); |
RegisterFunction("GMT_Header",GMT_Header); |
||||||
RegisterFunction("GMT_Footer",GMT_Footer); |
RegisterFunction("GMT_Footer",GMT_Footer); |
||||||
|
RegisterFunction("GET",Get<ObjectGMTCoord>); |
||||||
|
RegisterFunction("GET",Get<ObjectGMTRegion>); |
||||||
|
RegisterFunction("GET",Get<ObjectGMTProjection>); |
||||||
|
RegisterFunction("GET",Get<ObjectGMTColor>); |
||||||
|
RegisterFunction("GET",Get<ObjectGMTDash>); |
||||||
|
RegisterFunction("GET",Get<ObjectGMTPen>); |
||||||
|
RegisterFunction("GET",Get<ObjectGMTLayer>); |
||||||
|
|
||||||
|
RegisterFunction("Coord",GMT_Coord); |
||||||
|
RegisterFunction("Region",GMT_Region); |
||||||
|
RegisterFunction("Projection",GMT_Projection); |
||||||
return 0; |
return 0; |
||||||
} |
} |
||||||
|
@ -1,35 +1,9 @@ |
|||||||
#ifndef MODGMT_H |
#ifndef MODGMT_H |
||||||
#define MODGMT_H |
#define MODGMT_H |
||||||
#include <pthread.h> |
|
||||||
#include <gmt.h> |
|
||||||
#include <string.h> |
|
||||||
#include "common.h" |
#include "common.h" |
||||||
#include "filters.h" |
|
||||||
|
|
||||||
// Workaround exit() in GMT_Call_Module. May need because return mode of gmt api is not very reliable
|
|
||||||
#if defined MODGMT_WORKAROUND_EXIT |
|
||||||
#define GMTMODE 0 |
|
||||||
#else |
|
||||||
#define GMTMODE 3 |
|
||||||
#endif |
|
||||||
|
|
||||||
// here we save header and footer of gmt-produced eps files
|
|
||||||
extern std::string header,footer; |
|
||||||
|
|
||||||
// Parameters for working thread
|
|
||||||
struct gmtworkthreadpars |
|
||||||
{ |
|
||||||
void* api; |
|
||||||
const char* module; |
|
||||||
struct GMT_OPTION* opts; |
|
||||||
int fd; |
|
||||||
int ret; |
|
||||||
}; |
|
||||||
|
|
||||||
extern "C" { |
extern "C" { |
||||||
EXPORT int gmt_module_init(void* p); |
EXPORT int gmt_module_init(void* p); |
||||||
} |
} |
||||||
|
|
||||||
int callgmtmodule(void *api, const char *module, struct GMT_OPTION *opts, std::string* res, gmt_filter filt=gmt_filter_default, void* filtpar=0); |
|
||||||
|
|
||||||
#endif |
#endif |
||||||
|
@ -1,7 +1,11 @@ |
|||||||
#ifndef MODGMT_FUNC_H |
#ifndef MODGMT_FUNC_H |
||||||
#define MODGMT_FUNC_H |
#define MODGMT_FUNC_H |
||||||
|
#include "modgmt_objects.h" |
||||||
|
|
||||||
ObjectBase* GMT_Header(const ObjectList* input); |
ObjectBase* GMT_Header(const ObjectList* input); |
||||||
ObjectBase* GMT_Footer(const ObjectList* input); |
ObjectBase* GMT_Footer(const ObjectList* input); |
||||||
|
ObjectBase* GMT_Coord(const ObjectList* input); |
||||||
|
ObjectBase* GMT_Region(const ObjectList* input); |
||||||
|
ObjectBase* GMT_Projection(const ObjectList* input); |
||||||
|
|
||||||
#endif |
#endif |
||||||
|
@ -0,0 +1,131 @@ |
|||||||
|
#include <pthread.h> |
||||||
|
#include "common.h" |
||||||
|
#include "modgmt_internals.h" |
||||||
|
|
||||||
|
std::string header,footer; |
||||||
|
|
||||||
|
// Workaround exit() in GMT_Call_Module. May need because return mode of gmt api is not very reliable
|
||||||
|
#if defined MODGMT_WORKAROUND_EXIT |
||||||
|
const int GMTMODE=GMT_SESSION_NORMAL; |
||||||
|
#else |
||||||
|
const int GMTMODE=GMT_SESSION_NOEXIT; |
||||||
|
#endif |
||||||
|
|
||||||
|
#if defined MODGMT_WORKAROUND_EXIT |
||||||
|
// Exit handler.
|
||||||
|
static void gmtonexithandler(int ret, void* x) |
||||||
|
{ |
||||||
|
reinterpret_cast<struct gmtworkthreadpars*>(x)->ret=ret; |
||||||
|
close(reinterpret_cast<struct gmtworkthreadpars*>(x)->fd); |
||||||
|
pthread_exit(&(reinterpret_cast<struct gmtworkthreadpars*>(x)->ret)); |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
// This function call GMT_Call_Module in separate thread. It just a hack to workaround absence of callbacks.
|
||||||
|
static void* gmtworkthread(void* x) |
||||||
|
{ |
||||||
|
struct gmtworkthreadpars* p=reinterpret_cast<struct gmtworkthreadpars*>(x); |
||||||
|
#if defined MODGMT_WORKAROUND_EXIT |
||||||
|
on_exit(gmtonexithandler,x); |
||||||
|
#endif |
||||||
|
GMT_Append_Option(p->api,GMT_Make_Option(p->api,'>',const_cast<char*>(("/dev/fd/"+std::to_string(p->fd)).c_str())),p->opts); |
||||||
|
p->ret=GMT_Call_Module(p->api,p->module,GMT_MODULE_OPT,p->opts); |
||||||
|
#if defined MODGMT_WORKAROUND_EXIT |
||||||
|
exit(p->ret); |
||||||
|
#endif |
||||||
|
close(p->fd); |
||||||
|
return &p->ret; |
||||||
|
} |
||||||
|
|
||||||
|
// Wrapper for GMT_Call_Module, res is output.
|
||||||
|
int callgmtmodule(void *api, const char *module, struct GMT_OPTION *opts, std::string* res, gmt_filter filt, void* filtpar) |
||||||
|
{ |
||||||
|
int pipefd[2]; |
||||||
|
pthread_t wthr; |
||||||
|
struct gmtworkthreadpars p; |
||||||
|
int *pret; |
||||||
|
|
||||||
|
pipe(pipefd); |
||||||
|
p.api=api; |
||||||
|
p.module=module; |
||||||
|
p.opts=opts; |
||||||
|
p.fd=pipefd[1]; |
||||||
|
|
||||||
|
pthread_create(&wthr,0,&gmtworkthread,&p); |
||||||
|
res->erase(); |
||||||
|
|
||||||
|
(*filt)(pipefd[0],res,filtpar); |
||||||
|
|
||||||
|
res->shrink_to_fit(); |
||||||
|
pthread_join(wthr,reinterpret_cast<void**>(&pret)); |
||||||
|
|
||||||
|
return *pret; |
||||||
|
} |
||||||
|
// Overloaded variant with opts as std::string
|
||||||
|
int callgmtmodule(void *api, const char *module, const std::string& opts, std::string* res, gmt_filter filt, void* filtpar) |
||||||
|
{ |
||||||
|
struct GMT_OPTION *gopts; |
||||||
|
int ret; |
||||||
|
gopts=str2options(api,opts); |
||||||
|
ret=callgmtmodule(api,module,gopts,res,filt,filtpar); |
||||||
|
GMT_Destroy_Options(api,&gopts); |
||||||
|
return ret; |
||||||
|
} |
||||||
|
// Overloaded variant with opts as char*
|
||||||
|
int callgmtmodule(void *api, const char *module, const char* opts, std::string* res, gmt_filter filt, void* filtpar) |
||||||
|
{ |
||||||
|
struct GMT_OPTION *gopts; |
||||||
|
int ret; |
||||||
|
gopts=str2options(api,opts); |
||||||
|
ret=callgmtmodule(api,module,gopts,res,filt,filtpar); |
||||||
|
GMT_Destroy_Options(api,&gopts); |
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
// Calculate real width and height of projection. If height!=0 recalculate width accordingly.
|
||||||
|
bool ProjectionRealSize(struct gmt_projection& p, double height) |
||||||
|
{ |
||||||
|
// Decart projection is special case
|
||||||
|
if(gmt_projection::XY==p.proj) |
||||||
|
{ |
||||||
|
p.rwidth=p.width; |
||||||
|
p.rheight=p.x.height; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
void* gmtapi; |
||||||
|
int ret=0; |
||||||
|
std::string wh; |
||||||
|
double w,h; |
||||||
|
double sw=p.width; |
||||||
|
size_t pos; |
||||||
|
|
||||||
|
gmtapi=GMT_Create_Session("ProjectionRealSize",2,GMTMODE,0); |
||||||
|
if(0==gmtapi) return false; |
||||||
|
p.width=1.0; |
||||||
|
ret=callgmtmodule(gmtapi,"mapproject",p.Value()+" -W",&wh); |
||||||
|
p.width=sw; |
||||||
|
GMT_Destroy_Session(gmtapi); |
||||||
|
if(0!=ret) return false; |
||||||
|
|
||||||
|
pos=wh.find('\n'); |
||||||
|
if(std::string::npos!=pos) wh.erase(pos); |
||||||
|
pos=wh.find_first_of(" \t",0,2); |
||||||
|
if(std::string::npos==pos) return false; |
||||||
|
if(!str2double(std::string(wh.c_str(),wh.c_str()+pos),&w)) return false; |
||||||
|
if(!str2double(wh.substr(pos+1),&h)) return false; |
||||||
|
if(height>0.0) |
||||||
|
{ |
||||||
|
p.width=height/h; |
||||||
|
p.rwidth=w*height/h; |
||||||
|
p.rheight=height; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
p.width=sw/w; |
||||||
|
p.rwidth=sw; |
||||||
|
p.rheight=h*sw/w; |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
#ifndef MODGMT_INTERNALS_H |
||||||
|
#define MODGMT_INTERNALS_H |
||||||
|
#include <gmt.h> |
||||||
|
#include <string.h> |
||||||
|
#include "filters.h" |
||||||
|
#include "modgmt_structs.h" |
||||||
|
|
||||||
|
// here we save header and footer of gmt-produced eps files
|
||||||
|
extern std::string header,footer; |
||||||
|
extern const int GMTMODE; |
||||||
|
|
||||||
|
// Parameters for working thread
|
||||||
|
struct gmtworkthreadpars |
||||||
|
{ |
||||||
|
void* api; |
||||||
|
const char* module; |
||||||
|
struct GMT_OPTION* opts; |
||||||
|
int fd; |
||||||
|
int ret; |
||||||
|
}; |
||||||
|
|
||||||
|
// Calling GMT module with filtering
|
||||||
|
int callgmtmodule(void *api, const char *module, struct GMT_OPTION *opts, std::string* res, gmt_filter filt=gmt_filter_default, void* filtpar=0); |
||||||
|
int callgmtmodule(void *api, const char *module, const std::string& opts, std::string* res, gmt_filter filt=gmt_filter_default, void* filtpar=0); |
||||||
|
int callgmtmodule(void *api, const char *module, const char* opts, std::string* res, gmt_filter filt=gmt_filter_default, void* filtpar=0); |
||||||
|
|
||||||
|
// Workaround non-const pointer in GMT_Create_Options
|
||||||
|
inline struct GMT_OPTION* str2options(void *api, const char* str, size_t size=0) |
||||||
|
{ |
||||||
|
static char default_gmt_options[]="--GMT_HISTORY=f --PS_LINE_CAP=round --PS_LINE_JOIN=round --GMT_COMPATIBILITY=5 --PS_PAGE_ORIENTATION=portrait --PS_IMAGE_COMPRESS=deflate,9 --PROJ_LENGTH_UNIT=cm"; |
||||||
|
char* t; |
||||||
|
if(0==size) t=strdup(str); |
||||||
|
else |
||||||
|
{ |
||||||
|
t=static_cast<char*>(malloc(size+1)); |
||||||
|
memcpy(t,str,size+1); |
||||||
|
} |
||||||
|
struct GMT_OPTION* opts=GMT_Create_Options(api,0,t); |
||||||
|
GMT_Append_Option(api,GMT_Create_Options(api,0,default_gmt_options),opts); |
||||||
|
free(t); |
||||||
|
return opts; |
||||||
|
} |
||||||
|
inline struct GMT_OPTION* str2options(void *api, const std::string& str) |
||||||
|
{ |
||||||
|
return str2options(api,str.data(),str.length()); |
||||||
|
} |
||||||
|
|
||||||
|
// Calculate real width and height of projection. If height!=0 recalculate width accordingly.
|
||||||
|
bool ProjectionRealSize(struct gmt_projection& p, double height=0.0); |
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue