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
+}