From 7d624b3d9afe23d24e7c9975071440cc83de88a0 Mon Sep 17 00:00:00 2001 From: Peter Kleiweg Date: Fri, 30 Aug 2019 14:35:40 +0200 Subject: [PATCH] first commit --- README.md | 5 +++ v5/proj.c | 20 +++++++++ v5/proj_go.h | 5 +++ v5/v5.go | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 README.md create mode 100644 v5/proj.c create mode 100644 v5/proj_go.h create mode 100644 v5/v5.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..c904102 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +The [Go](http://golang.org/) package _proj_ provides an interface to the Cartographic Projections Library [PROJ](https://proj.org/). + +Keywords: cartography, cartographic projection + +*Work in progress* diff --git a/v5/proj.c b/v5/proj.c new file mode 100644 index 0000000..ef6f137 --- /dev/null +++ b/v5/proj.c @@ -0,0 +1,20 @@ +#include "proj_go.h" + +int pjnull(PJ *pj) { + return pj == 0 ? 1 : 0; +} + +void trans(PJ *pj, PJ_DIRECTION direction, double u1, double v1, double w1, double t1, double *u2, double *v2, double *w2, double *t2) { + PJ_COORD + co1, + co2; + co1.uvwt.u = u1; + co1.uvwt.v = v1; + co1.uvwt.w = w1; + co1.uvwt.t = t1; + co2 = proj_trans(pj, direction, co1); + *u2 = co2.uvwt.u; + *v2 = co2.uvwt.v; + *w2 = co2.uvwt.w; + *t2 = co2.uvwt.t; +} diff --git a/v5/proj_go.h b/v5/proj_go.h new file mode 100644 index 0000000..3f89a3d --- /dev/null +++ b/v5/proj_go.h @@ -0,0 +1,5 @@ +#include +#include + +int pjnull(PJ *pj); +void trans(PJ *pj, PJ_DIRECTION direction, double u1, double v1, double w1, double t1, double *u2, double *v2, double *w2, double *t2); diff --git a/v5/v5.go b/v5/v5.go new file mode 100644 index 0000000..e48d87a --- /dev/null +++ b/v5/v5.go @@ -0,0 +1,119 @@ +package proj + +/* +#cgo darwin pkg-config: proj +#cgo !darwin LDFLAGS: -lproj +#include "proj_go.h" +*/ +import "C" + +import ( + "errors" + "runtime" + "unsafe" +) + +type Context struct { + pj_context *C.PJ_CONTEXT + opened bool +} + +type Proj struct { + pj *C.PJ + context *Context + opened bool +} + +type Coord struct { + U, V, W, T float64 +} + +var ( + errContextClosed = errors.New("Context is closed") + errProjectionClosed = errors.New("Projection is closed") +) + +func NewContext() *Context { + ctx := Context{ + pj_context: C.proj_context_create(), + opened: true, + } + runtime.SetFinalizer(&ctx, (*Context).Close) + return &ctx +} + +func (ctx *Context) Close() { + if ctx.opened { + C.proj_context_destroy(ctx.pj_context) + ctx.pj_context = nil + ctx.opened = false + // TODO: destroy projections + } +} + +func (ctx *Context) Create(definition string) (*Proj, error) { + if !ctx.opened { + return nil, errContextClosed + } + + cs := C.CString(definition) + defer C.free(unsafe.Pointer(cs)) + pj := C.proj_create(ctx.pj_context, cs) + if C.pjnull(pj) != 0 { + errno := C.proj_context_errno(ctx.pj_context) + err := C.GoString(C.proj_errno_string(errno)) + return nil, errors.New(err) + } + + p := Proj{ + opened: true, + context: ctx, + pj: pj, + } + + // TODO: projection toevoegen aan context + + runtime.SetFinalizer(&p, (*Proj).Close) + return &p, nil +} + +func (p *Proj) Close() { + if p.opened { + C.proj_destroy(p.pj) + p.context = nil + p.opened = false + // todo: projection verwijderen uit context + } +} + +func (p *Proj) Fwd(coord Coord) (Coord, error) { + return p.trans(coord, false) +} + +func (p *Proj) Inv(coord Coord) (Coord, error) { + return p.trans(coord, true) +} + +func (p *Proj) trans(coord Coord, inverse bool) (Coord, error) { + if !p.opened { + return Coord{}, errProjectionClosed + } + + var direction C.PJ_DIRECTION + if inverse { + direction = C.PJ_INV + } else { + direction = C.PJ_FWD + } + + var u, v, w, t C.double + C.trans(p.pj, direction, C.double(coord.U), C.double(coord.V), C.double(coord.W), C.double(coord.T), &u, &v, &w, &t) + + coord2 := Coord{ + U: float64(u), + V: float64(v), + W: float64(w), + T: float64(t), + } + return coord2, nil +}