Go bindings for PROJ (formerly PROJ.4) - a library for performing conversions between cartographic projections, maintained by the OSGeo organization. See https://proj.org for more information.
This project, as Go module, follows semantic versioning. This means that backward-incompatible changes will not be made without a major version upgrade.
This project is also versioned to match the target PROJ version. This means that v8.*.*
of go-proj
(the current latest version) targets version 8.*.*
of PROJ. If your project needs to use a different version of PROJ, first check the releases page to see if a previous release of go-proj
targets that version. Alternatively, you may find that a particular version of go-proj
works with a non-targeted version of PROJ; for example v8.*.*
of go-proj
may still work with later versions of PROJ.
go-proj
uses Cgo to wrap the PROJ library with a Go interface. As such, in order to use this package, you must first install PROJ. The PROJ website contains details several methods for installing the library, but you may find that these sources are not up-to-date enough to provide the version that this package targets (see PROJ_VERSION
in Dockerfile) - in this case you can either compile from source (ensuring that you're using the correct tag), or use the official Docker images.
You can verify the installation by running the command below and checking that the version number matches the aforementioned PROJ_VERSION
:
proj --version
Then go-proj
can be added to your Go module as usual:
go get -u github.com/everystreet/go-proj/v8
go-proj
consists of two packages - cproj
contains raw Go bindings to the PROJ library, and proj
consists of a more idiomatic Go wrapper that doesn't require manual memory deallocation. The latter package, proj
should be used where possible by adding the following import
line:
import "github.com/everystreet/go-proj/v8/proj"
Below is an example of transforming a coordinate to the "Web Mercator" projection:
coord := proj.XYZ{
X: 2,
Y: 49,
Z: 10,
}
err := proj.CRSToCRS(
proj.CRS("+proj=latlong"),
proj.CRS("EPSG:3857"),
proj.TransformForward(&coord))
fmt.Printf("%.2f %.2f", coord.X, coord.Y) // 222638.98 6274861.39
CRSToCRS
is a wrapper around several PROJ functions, including proj_create_crs_to_crs_from_pj
. The source and target CRS values are passed to this function in the same way as the cs2cs
program, so the snippet above produces the same result as running the command below:
$ echo 2 49 | cs2cs +proj=latlong +to EPSG:3857
# 222638.98 6274861.39 0.00
For demonstration purposes, this repository also contains a simplified cs2cs
program that can be run like so:
$ echo 2 49 | go run cmd/proj/main.go +proj=latlong +to EPSG:3857
# 222638.98 6274861.39 0.00
The Go code above is equavalent to the following C snippet (based on the "Quick start" guide):
PJ_CONTEXT *C;
PJ *P;
PJ *P_for_GIS;
PJ_COORD a, b;
C = proj_context_create();
P = proj_create_crs_to_crs(C, "+proj=latlong", "EPSG:3857", NULL);
P_for_GIS = proj_normalize_for_visualization(C, P);
proj_destroy(P);
P = P_for_GIS;
a = proj_coord(2, 49, 10, 0);
b = proj_trans(P, PJ_FWD, a);
proj_destroy(P);
proj_context_destroy(C);
These bindings are generated by "c-for-go". By running the commands below, the bindings that make up the cproj
package can be regenerated:
podman build --target proj -t go-proj-builder .
podman run -v "$PWD":/go/src/go-proj:z -w /go/src/go-proj --rm go-proj-builder bash -c "rm -rf cproj \
&& go run -mod=vendor github.com/xlab/c-for-go -ccincl proj/proj.yaml \
&& chmod 0444 cproj/*"