Created
January 4, 2018 21:48
-
-
Save webstory/10f13c5249559821b74473f0204a8355 to your computer and use it in GitHub Desktop.
Transform WGS84 to GOOGLE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Original gist: https://gist.github.com/schoenobates/f6ca293eadfe2b7b4157