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_func.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; |
||||
} |
||||
|
||||
#include "modgmt_internals.h" |
||||
|
||||
// Initialisation function
|
||||
int gmt_module_init(void* p) |
||||
{ |
||||
// Fill header and footer
|
||||
struct GMT_OPTION* opts; |
||||
void* gmtapi; |
||||
int ret; |
||||
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); |
||||
int ret=0; |
||||
|
||||
gmtapi=GMT_Create_Session("gmt_makemap",2,3,0); |
||||
gmtapi=GMT_Create_Session("gmt_makemap",2,GMTMODE,0); |
||||
if(0==gmtapi) return 1; |
||||
opts=GMT_Create_Options(gmtapi,0,h); |
||||
ret=callgmtmodule(gmtapi,"psclip",opts,&header,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); |
||||
if(0==ret) ret=callgmtmodule(gmtapi,"psclip","-C -P -K",&header,gmt_filter_headfoot); |
||||
if(0==ret) ret=callgmtmodule(gmtapi,"psclip","-C -P -O",&footer,gmt_filter_headfoot); |
||||
GMT_Destroy_Session(gmtapi); |
||||
free(h); free(f); |
||||
if(0!=ret) return ret; |
||||
|
||||
gmt_projection::FillProjNames(); |
||||
|
||||
RegisterFunction("GMT_Header",GMT_Header); |
||||
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; |
||||
} |
||||
|
@ -1,35 +1,9 @@
|
||||
#ifndef MODGMT_H |
||||
#define MODGMT_H |
||||
#include <pthread.h> |
||||
#include <gmt.h> |
||||
#include <string.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" { |
||||
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 |
||||
|
@ -1,7 +1,11 @@
|
||||
#ifndef MODGMT_FUNC_H |
||||
#define MODGMT_FUNC_H |
||||
#include "modgmt_objects.h" |
||||
|
||||
ObjectBase* GMT_Header(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 |
||||
|
@ -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