Giter VIP home page Giter VIP logo

golang-geo's Introduction

              ___                                                              
             /\_ \                                                             
   __     ___\//\ \      __      ___      __               __      __    ___   
 /'_ `\  / __`\\ \ \   /'__`\  /' _ `\  /'_ `\  _______  /'_ `\  /'__`\ / __`\ 
/\ \L\ \/\ \L\ \\_\ \_/\ \L\.\_/\ \/\ \/\ \L\ \/\______\/\ \L\ \/\  __//\ \L\ \
\ \____ \ \____//\____\ \__/.\_\ \_\ \_\ \____ \/______/\ \____ \ \____\ \____/
 \/___L\ \/___/ \/____/\/__/\/_/\/_/\/_/\/___L\ \        \/___L\ \/____/\/___/ 
   /\____/                                /\____/          /\____/             
   \_/__/                                 \_/__/           \_/__/              

♫ around the world ♪

Build Status Coverage Status GoDoc Join the chat at https://gitter.im/kellydunn/golang-geo

what

This library provides convenience functions for translating, geocoding, and calculating distances between geographical points. It is inspired by ruby's geokit and geokit-rails gems, and aims to make working with geographical data a little bit easier in golang.

documentation

You can read the documentation here.

usage

Import from github to get started!

package main

import("github.com/kellydunn/golang-geo"
       "fmt")

func main() {
     // Make a few points
     p := geo.NewPoint(42.25, 120.2)
     p2 := geo.NewPoint(30.25, 112.2)
     
     // find the great circle distance between them
     dist := p.GreatCircleDistance(p2)
     fmt.Printf("great circle distance: %d\n", dist)
}

Currently, golang-geo provides the following functionality:

  • Transposing a point for a given distance and bearing.
  • Calculating the Great Circle Distance between two points.
  • Geocoding an address using Google Maps, Mapquest (OpenStreetMap data), OpenCage (OpenStreetMap, twofishes and other data sources) API.
  • Reverse Geocoding a Point using the same services.
  • Querying for points within a radius using your own SQL data tables.

Keep in mind that you do not need to use SQL in order to perform simple Point operations and the only function that relies on SQL is PointsWithinRadius.

using SQL

As of 0.1.0, golang-geo will shift its scope of responsiblity with SQL management. The library will still support the functions exposed in its public API in the past, however, it will not concern itself so much with creating and maintaining *sql.DB connections as it has done in previous versions. It is suggested that if you are using geo.HandleWithSql that you should instead consider creating a geo.SQLMapper yourself by calling the newly introduced geo.NewSQLMapper method, which accepts a *sql.DB connection and a filepath to the configuration file used to inform golang-geo of your particular SQL setup.

That being said, geo.HandleWithSQL is configured to connect to a SQL database by reading a config/geo.yml file in the root level of your project. If it does not exist, it will use a Default SQL configuration that will use the postgres driver as described by lib/pq. The Default SQL configuration will attempt to connect as a user named "postgres" and with the password "postgres" to a database named "points".

examples of SQL database configurations

Here are some examples of valid config files that golang-geo knows how to process:

PostgreSQL
development:
  driver: postgres
  openStr: user=username password=password dbname=points sslmode=disable
  table: points
  latCol: lat
  lngCol: lng
MySQL
development:
  driver: mysql
  openStr: points/username/password
  table: points
  latCol: lat
  lngCol: lng  

notes

  • golang-geo currently only uses metric measurements to do calculations
  • The $GO_ENV environment variable is used to determine which configuration group in config.yml is to be used. For example, if you wanted to use the PostgreSQL configuration listed above, you could specify GO_ENV=development which would read config.yml and use the configuration under the root-level key development.

installing older versions of golang-geo

With the advent of gopkg.in, you can now install older versions of golang-geo! Consult CHANGELOG.md for the version you wish to build against.

roadmap

  • More Tests!
  • Redis / NOSQL Mapper
  • Bing Maps?
  • Add an abstraction layer for PostgreSQL earthdistance / PostGIS

testing

By default, golang-geo will attempt to run its test suite against a PostgreSQL database. However, you may run the tests with mocked SQL queries by specifying that you want to do so on the command line:

DB=mock GO_ENV=test go test

The $DB environment variable is used to specify which database you'd like to run the tests against. You may specify postgres, mysql, or mock. The Travis CI builds for this project currently runs against all of these when running the test suite.

contributing

  • Fork the project
  • Create a topic branch (preferably the in the gitflow style of feature/, hotfix/, etc)
  • Make your changes and write complimentary tests to ensure coverage.
  • Submit Pull Request once the full test suite is passing.
  • Pull Requests will then be reviewed by the maintainer and the community and hopefully merged!

Thanks!

golang-geo's People

Contributors

bitdeli-chef avatar codelingobot avatar codingsince1985 avatar djk121 avatar gitter-badger avatar grindhold avatar johannesboyne avatar kbudde avatar kellydunn avatar martinthoma avatar mish15 avatar mkvoya avatar mlerner avatar mrnugget avatar s-mang avatar whinette avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

golang-geo's Issues

Travis Build Broken

There are problems with the travis build as in #46. Again there is a problem with goose:

$ go get -d bitbucket.org/liamstask/goose/lib/goose
package bitbucket.org/liamstask/goose/lib/goose: https://api.bitbucket.org/1.0/repositories/liamstask/goose: 410 Gone
The command "go get -d bitbucket.org/liamstask/goose/lib/goose" failed and exited with 1 during .
Your build has been stopped.

Somehow the link is gone on Bitbucket.
Until this is resolved all Travis builds will fail.

Different results in Great Circle Distance vs Mongodb spherical query result

When doing a query in mongodb about the distance between those 2 points the result is a rounded 1079km.
However the result of the great circle distance function of this package is 1118.298549 , km I assume.

With manual testing I found the factor 0.965 to achieve nearly mongodb results.
How can it be that those 2 methods result in different results?

package main

import (
	"fmt"

	geo "github.com/kellydunn/golang-geo"
)

func main() {
	p1 := geo.NewPoint(9.1829321, 48.7758459)
	p2 := geo.NewPoint(5.03131, 39.542448)

	dist := p1.GreatCircleDistance(p2)
	fmt.Printf("great circle distance: %f\n", dist)
	fmt.Printf("mongo ~ distance: %f\n", dist*0.965)
}

my mongodb query is, using the official driver

			geoStage := bson.D{{
				"$geoNear", bson.D{
					{"near", profile.Location}, // see below
					{"distanceField", "distance"},
					{"minDistance", 1},
					{"maxDistance", radius},
					{"spherical", true},
				},
			},
			}

// -- below

// Location is a GeoJSON type.
type Location struct {
	Type        string    `json:"type" bson:"type"`
	Coordinates []float64 `json:"coordinates" bson:"coordinates"`
}

go get

Got a strange error

$ go get github.com/kellydunn/golang-geo
# github.com/kellydunn/golang-geo
/usr/local/go/src/pkg/github.com/kellydunn/golang-geo/sql_conf.go:27: function ends without a return statement

Error trying to install the package through go get

user@FRODO /d/goworkspace/bin
$ go get github.com/kellydunn/golang-geo
# cd D:\goworkspace\src\github.com\kylelemons\go-gypsy; git pull --ff-only
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> master

package github.com/kylelemons/go-gypsy/yaml: exit status 1

image

Tests For Geocoder

Hi Kelly,

I notice that the test coverage for the *Geocoder is a bit low. Will you be interested in a PR where I refactor the Geocode() and ReverseGeocode() methods to mock out the API calls.

For example, in GoogleGeocoder, I update the struct to have a field function:

type GoogleGeocoder struct {
    sendRequest func(params string) ([]byte, error)
}

Then I changed the Geocode() method to call g.sendRequest() like this:

func (g *GoogleGeocoder) Geocode(address string) (*Point, error) {
    if g.sendRequest == nil {   // this can go into the struct constructor
        g.sendRequest = g.Request
    }

    data, err := g.sendRequest(queryStr)
    if err != nil {
        return nil, err
    }

This will makes it easier to test these methods. For example, I can mock the sendRequest field in the test like this:

func TestGeocode(t *testing.T) {
  address := "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA"
  g := GoogleGeocoder{
    sendRequest: func(params string) ([]byte, error) {
      return []byte(`{
        "results":[
          {"formatted_address":"1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
            "geometry":{"location":{
              "lat":37.4224764,
              "lng":-122.0842499}
            }
          }
        ],
        "status":"OK"
      }`), nil
    },
  }
  actual, err := g.Geocode(address)
  if err != nil {
    t.Error("Unexpected error: ", err)
  }

  expected := &Point{lat: 37.4224764, lng: -122.0842499}
  if !assertPointsEqual(actual, expected, 4) {
    t.Errorf("Expected point to be %+v, but got %+v", expected, actual)
  }
}

Obviously, this can be done for all the different types of Geocoders. With this change, existing tests continue to pass, with test coverage for the Geocoders increased from around 30% to 78%.

WDYT?

Cannot instantiate a Point without requesting from a Geocoder service.

As mentioned in the golang-nuts google group, users cannot currently specify latitude or longitude values while instantiating new Points.

I propose that something akin to NewPoint(lat float64, lng float64) (*Point) should be implemented such that users may be able to create new Points while still keeping the internals private.

We could also implement some kind of getter for the internal fields of Points, like (p * Point) GetLat() (float64) and (p* Point) GetLng() (float64) such that users may be able to view the internals of these newly instantiated Points.

@FernandoEscher do you have any thoughts or outstanding pull requests you may want to make in regards to this issue?

Units

The units of the return values should be documented.

finding all stored locations within a 20 KM of a GPS point

could you advise me if this library can so his.

I dont need to use the SQL functionality for now. i just need to do it all in memory in the middle tier.

i have every users gps location.
I have a event, for which i have the GPS location.

So i need to write a job that searches for any users location, within 20 km of the Event location.

The advantage of this is that i can do all this without having to use google maps APi and all that

Refactor internal geocoder implementations to use data transfer objects

Much like the style of the google geocoder, each geocoder implementation should use a data transfer object style struct to marshal and unmarshal responses from various APIs; this could open up new posibilities for the geocoders and make it less hacky to parse responses from various apis.

  • google gecode response
  • google reverse geocode response
  • mapquest geocode response
  • mapquest reverse geocode response
  • opencage geocode response
  • opencage reverse geocode response

API Key support

Hello,

Not sure if its an issue or if its my shoddy attempt at using the API, but I don't see support for adding an API key to the end of the urls here. Is that something you are interested in supporting? I could add if so.

Expose http.Client

I am trying to use this library with Google App Engine which does not allow one to use the standard library to make HTTP requests. I ran into a similar issue with a Twitter API, but was able to replace the http.Client since it was exposed in the API.

I believe a change like this could allow for a similar capability:

// This struct contains all the funcitonality
// of interacting with the Google Maps Geocoding Service
type GoogleGeocoder struct{
    HttpClient    *http.Client
}

...

// Issues a request to the google geocoding service and forwards the passed in params string
// as a URL-encoded entity.  Returns an array of byes as a result, or an error if one occurs during the process.
func (g *GoogleGeocoder) Request(params string) ([]byte, error) {
    if g.HttpClient == nil {
        g.HttpClient = &http.Client{}
    }
    client := g.HttpClient
    ...

Thoughts?

Contains for polygons with holes

The p.Contains(pt) logic for polygons with holes may return bad results.

Context: I have not been able to find documentation for creating a polygon with holes. I assume that you simply continue to add call p.Add(pt) for the points of the holes inside the polygon.

If my assumption is correct, then false line segments are created between the boundary and contained holes (or between successive holes). If a raycast intersects with an odd number of these false segments, the wrong result is returned.

If my assumption is incorrect, better documentation on how to create polygons with holes would be appreciated.

Travis builds are failing because getting the migration cmd from bitbucket is failing

As confirmed by the owner of goose, a go migration tool, the project is no longer be actively supported and may change hands of ownership soon. (Comment here)

This might be a contributing factor as to why go get bitbucket.org/liamstask/goose/cmd/goose is no longer working as intended.

Until this is resolved, travis builds are failing:

Using worker: worker-linux-da6418d7-2.bb.travis-ci.org:travis-linux-1
system_info
Build system information
Build language: go
Build image provisioning date and time
Wed Feb  4 18:22:50 UTC 2015
Operating System Details
Distributor ID: Ubuntu
Description:    Ubuntu 12.04 LTS
Release:    12.04
Codename:   precise
Linux Version
2.6.32-042stab090.5
Cookbooks Version
23bb455 https://github.com/travis-ci/travis-cookbooks/tree/23bb455
GCC version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
LLVM version
clang version 3.4 (tags/RELEASE_34/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
Pre-installed Ruby versions
ruby-1.9.3-p551
Pre-installed Node.js versions
v0.10.36
Pre-installed Go versions
1.4.1
Redis version
redis-server 2.8.19
riak version
2.0.2
MongoDB version
MongoDB 2.4.12
CouchDB version
couchdb 1.6.1
Neo4j version
1.9.4
Cassandra version
2.0.9
RabbitMQ Version
3.4.3
ElasticSearch version
1.4.0
Installed Sphinx versions
2.0.10
2.1.9
2.2.6
Default Sphinx version
2.2.6
Installed Firefox version
firefox 31.0esr
PhantomJS version
1.9.8
ant -version
Apache Ant(TM) version 1.8.2 compiled on December 3 2011
mvn -version
Apache Maven 3.2.5 (12a6b3acb947671f09b81f49094c53f426d8cea1; 2014-12-14T17:29:23+00:00)
Maven home: /usr/local/maven
Java version: 1.7.0_76, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-7-oracle/jre
Default locale: en, platform encoding: UTF-8
OS name: "linux", version: "2.6.32-042stab090.5", arch: "amd64", family: "unix"
git.checkout
0.47s$ git clone --depth=50 --branch=v1.0.0-work-in-progress https://github.com/kellydunn/golang-geo.git kellydunn/golang-geo
Cloning into 'kellydunn/golang-geo'...
remote: Counting objects: 622, done.
remote: Compressing objects: 100% (305/305), done.
remote: Total 622 (delta 309), reused 595 (delta 288), pack-reused 0
Receiving objects: 100% (622/622), 179.90 KiB | 0 bytes/s, done.
Resolving deltas: 100% (309/309), done.
Checking connectivity... done.
$ cd kellydunn/golang-geo
$ git checkout -qf 9b75a0c43d4f209ac8a7c62331e4868acdc045a5
Installing gimme from https://raw.githubusercontent.com/meatballhat/gimme/v0.2.3/gimme
Setting environment variables from .travis.yml
$ export DB=postgres
$ export GO_ENV=test
4.28s$ eval "$(gimme 1.2.1)"
go version go1.2.1 linux/amd64
$ export GOPATH=$HOME/gopath
$ export PATH=$HOME/gopath/bin:$PATH
$ mkdir -p $HOME/gopath/src/github.com/kellydunn/golang-geo
$ rsync -az ${TRAVIS_BUILD_DIR}/ $HOME/gopath/src/github.com/kellydunn/golang-geo/
$ export TRAVIS_BUILD_DIR=$HOME/gopath/src/github.com/kellydunn/golang-geo
$ cd $HOME/gopath/src/github.com/kellydunn/golang-geo
$ gimme version
v0.2.3
$ go version
go version go1.2.1 linux/amd64
go.env
$ go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/travis/gopath"
GORACE=""
GOROOT="/home/travis/.gimme/versions/go1.2.1.linux.amd64"
GOTOOLDIR="/home/travis/.gimme/versions/go1.2.1.linux.amd64/pkg/tool/linux_amd64"
TERM="dumb"
CC="gcc"
GOGCCFLAGS="-g -O2 -fPIC -m64 -pthread"
CXX="g++"
CGO_ENABLED="1"
before_install
0.01s$ export PATH=/home/travis/gopath/bin:$PATH
4.29s$ go get bitbucket.org/liamstask/goose/cmd/goose
# github.com/mattn/go-sqlite3
Go type not supported in export: [0]byte
Go type not supported in export: [0]byte
Go type not supported in export: [0]byte
Go type not supported in export: [0]byte
Go type not supported in export: [0]byte
Go type not supported in export: [0]byte
Go type not supported in export: [0]byte
Go type not supported in export: [0]byte
Go type not supported in export: [0]byte
Go type not supported in export: [0]byte
The command "go get bitbucket.org/liamstask/goose/cmd/goose" failed and exited with 2 during .
Your build has been stopped.

Acceptance criteria:

  • Investigate issue
  • change goose dependecy path
    • fork the repo
    • find new canonical owner
  • ensure travis runs correctly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.