Skip to content

Instantly share code, notes, and snippets.

@webstory
Created January 4, 2018 21:48
Show Gist options
  • Save webstory/10f13c5249559821b74473f0204a8355 to your computer and use it in GitHub Desktop.
Save webstory/10f13c5249559821b74473f0204a8355 to your computer and use it in GitHub Desktop.
Transform WGS84 to GOOGLE
package main
/*
#cgo LDFLAGS: -lproj
#include <string.h>
#include <proj_api.h>
*/
import "C"
import (
"fmt"
"os"
"strconv"
"strings"
"unsafe"
)
type Projection string
// Proj4 defs
const (
EPSG_900913 Projection = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"
EPSG_4326 Projection = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
)
// radians <-> degrees
const (
radians float64 = 0.017453292519943295
degrees float64 = 57.29577951308232
)
// Holds a LatLng pair
type LatLng struct {
Lat, Lng float64
}
func (ll *LatLng) ToDegrees() *LatLng {
return &LatLng{
Lat: ll.Lat * degrees,
Lng: ll.Lng * degrees,
}
}
func (ll *LatLng) ToRadians() *LatLng {
return &LatLng{
Lat: ll.Lat * radians,
Lng: ll.Lng * radians,
}
}
type Proj4Error struct {
retval int
}
func (e *Proj4Error) Error() string {
return fmt.Sprintf("Proj4 Error: %d", e.retval)
}
// Converts the given LatLng coordinate pair from the source projection to destination projection
func Convert(ll *LatLng, Source, Destination Projection) (*LatLng, error) {
fromProj := C.CString(string(Source))
toProj := C.CString(string(Destination))
defer func() {
C.free(unsafe.Pointer(fromProj))
C.free(unsafe.Pointer(toProj))
}()
fpj := C.pj_init_plus(fromProj)
tpj := C.pj_init_plus(toProj)
lat := C.double(ll.Lat)
lng := C.double(ll.Lng)
retval := int(C.pj_transform(fpj, tpj, 1, 1, &lng, &lat, nil))
C.pj_free(fpj)
C.pj_free(tpj)
if retval != 0 {
return nil, &Proj4Error{retval}
}
return &LatLng{
Lat: float64(lat),
Lng: float64(lng),
}, nil
}
func main() {
if len(os.Args) != 4 {
fmt.Println("usage: transform [from|to] <x> <y>\n\n\tUsed to convert between WGS84 and GOOGLE using Proj4 in Go.")
os.Exit(0)
}
cmd := strings.ToLower(os.Args[1])
x, err := strconv.ParseFloat(os.Args[2], 64)
if err != nil {
fmt.Printf("Failed to parse X: %s", err)
os.Exit(-1)
}
y, err := strconv.ParseFloat(os.Args[3], 64)
if err != nil {
fmt.Printf("Failed to parse Y: %s", err)
os.Exit(-1)
}
latlng := &LatLng{y, x}
var ll *LatLng
if cmd == "from" {
ll, err = Convert(latlng, EPSG_900913, EPSG_4326)
} else {
ll, err = Convert(latlng.ToRadians(), EPSG_4326, EPSG_900913)
}
if err != nil {
fmt.Println(err)
if pe, ok := err.(*Proj4Error); ok {
os.Exit(pe.retval)
}
}
//ll = ll.ToDegrees()
if cmd == "from" {
ll = ll.ToDegrees()
}
fmt.Printf("%.15f %.15f\n", ll.Lng, ll.Lat)
}
@webstory
Copy link
Author

webstory commented Jan 4, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment