# geo

package module
Version: v0.7.1-0...-94539ff Latest Latest

Go to latest
Published: Jan 25, 2018 License: MIT

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

♫ around the world ♪
``````

### 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
table: points
latCol: lat
lngCol: lng
``````
###### MySQL
``````development:
driver: mysql
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.

• 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!

## Documentation ¶

### Constants ¶

View Source
```const (
DEFAULT_PGSQL_OPEN_STR = "user=postgres dbname=points sslmode=disable"
DEFAULT_MYSQL_OPEN_STR = "points/root/"
DEFAULT_TEST_OPEN_STR  = "\"\""
)```
View Source
```const (
)```

### Variables ¶

View Source
`var GoogleAPIKey = ""`
View Source
`var MapquestAPIKey = ""`
View Source
`var OpenCageAPIKey = ""`

### Functions ¶

`func SetGoogleAPIKey(newAPIKey string)`

`func SetGoogleGeocodeURL(newGeocodeURL string)`

Note: In the next major revision (1.0.0), it is planned

```That Geocoders should adhere to the `geo.Geocoder`
interface and provide versioning of APIs accordingly.
```

Sets the base URL for the Google Geocoding API.

#### func SetMapquestAPIKey ¶

`func SetMapquestAPIKey(newAPIKey string)`

#### func SetMapquestGeocodeURL ¶

`func SetMapquestGeocodeURL(newGeocodeURL string)`

Note: In the next major revision (1.0.0), it is planned

```That Geocoders should adhere to the `geo.Geocoder`
interface and provide versioning of APIs accordingly.
```

Sets the base URL for the MapQuest Geocoding API.

#### func SetOpenCageAPIKey ¶

`func SetOpenCageAPIKey(newAPIKey string)`

#### func SetOpenCageGeocodeURL ¶

`func SetOpenCageGeocodeURL(newGeocodeURL string)`

Note: In the next major revision (1.0.0), it is planned

```That Geocoders should adhere to the `geo.Geocoder`
interface and provide versioning of APIs accordingly.
```

Sets the base URL for the OpenCage Geocoding API.

### Types ¶

#### type Geocoder ¶

```type Geocoder interface {
Geocode(query string) (*Point, error)
ReverseGeocode(p *Point) (string, error)
}```

This interface describes a Geocoder, which provides the ability to Geocode and Reverse Geocode geographic points of interest. Geocoding should accept a string that represents a street address, and returns a pointer to a Point that most closely identifies it. Reverse geocoding should accept a pointer to a Point, and return the street address that most closely represents it.

```type GoogleGeocoder struct {
HttpClient *http.Client
}```

This struct contains all the funcitonality of interacting with the Google Maps Geocoding Service

`func (g *GoogleGeocoder) Geocode(address string) (*Point, error)`

Geocodes the passed in query string and returns a pointer to a new Point struct. Returns an error if the underlying request cannot complete.

`func (g *GoogleGeocoder) Request(params string) ([]byte, error)`

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. Note: Since this is an arbitrary request, you are responsible for passing in your API key if you want one.

`func (g *GoogleGeocoder) ReverseGeocode(p *Point) (string, error)`

Reverse geocodes the pointer to a Point struct and returns the first address that matches or returns an error if the underlying request cannot complete.

#### type MapQuestGeocoder ¶

`type MapQuestGeocoder struct{}`

This struct contains all the funcitonality of interacting with the MapQuest Geocoding Service

#### func (*MapQuestGeocoder) Geocode ¶

`func (g *MapQuestGeocoder) Geocode(address string) (*Point, error)`

Returns the first point returned by MapQuest's geocoding service or an error if one occurs during the geocoding request.

#### func (*MapQuestGeocoder) Request ¶

`func (g *MapQuestGeocoder) Request(url string) ([]byte, error)`

Issues a request to the open mapquest api geocoding services using the passed in url query. Returns an array of bytes as the result of the api call or an error if one occurs during the process. Note: Since this is an arbitrary request, you are responsible for passing in your API key if you want one.

#### func (*MapQuestGeocoder) ReverseGeocode ¶

`func (g *MapQuestGeocoder) ReverseGeocode(p *Point) (string, error)`

Returns the first most available address that corresponds to the passed in point. It may also return an error if one occurs during execution.

#### type Mapper ¶

```type Mapper interface {
}```

This interface describes a Mapper, which should be a data storage mechanism that can execute interesting queries. Currently, mappers should be able to find points within a radius of an origin point.

#### type OpenCageGeocoder ¶

`type OpenCageGeocoder struct{}`

This struct contains all the funcitonality of interacting with the OpenCage Geocoding Service

#### func (*OpenCageGeocoder) Geocode ¶

`func (g *OpenCageGeocoder) Geocode(address string) (*Point, error)`

Returns the first point returned by OpenCage's geocoding service or an error if one occurs during the geocoding request.

#### func (*OpenCageGeocoder) Request ¶

`func (g *OpenCageGeocoder) Request(url string) ([]byte, error)`

Issues a request to the open OpenCage API geocoding services using the passed in url query. Returns an array of bytes as the result of the api call or an error if one occurs during the process. Note: Since this is an arbitrary request, you are responsible for passing in your API key if you want one.

#### func (*OpenCageGeocoder) ReverseGeocode ¶

`func (g *OpenCageGeocoder) ReverseGeocode(p *Point) (string, error)`

Returns the first most available address that corresponds to the passed in point. It may also return an error if one occurs during execution.

#### type Point ¶

```type Point struct {
// contains filtered or unexported fields
}```

Represents a Physical Point in geographic notation [lat, lng].

#### func NewPoint ¶

`func NewPoint(lat float64, lng float64) *Point`

Returns a new Point populated by the passed in latitude (lat) and longitude (lng) values.

#### func (*Point) AlongTrackDistance ¶

`func (p *Point) AlongTrackDistance(start *Point, end *Point) float64`

returns distance along the track in kilometers

#### func (*Point) BearingTo ¶

`func (p *Point) BearingTo(p2 *Point) float64`

Calculates the initial bearing (sometimes referred to as forward azimuth) Original Implementation from: http://www.movable-type.co.uk/scripts/latlong.html

#### func (*Point) CrossTrackError ¶

`func (p *Point) CrossTrackError(start *Point, end *Point) float64`

returns cross track error in kilometers

#### func (*Point) GreatCircleDistance ¶

`func (p *Point) GreatCircleDistance(p2 *Point) float64`

Calculates the Haversine distance between two points in kilometers. Original Implementation from: http://www.movable-type.co.uk/scripts/latlong.html

#### func (*Point) Lat ¶

`func (p *Point) Lat() float64`

Returns Point p's latitude.

#### func (*Point) Lng ¶

`func (p *Point) Lng() float64`

Returns Point p's longitude.

#### func (*Point) MarshalBinary ¶

`func (p *Point) MarshalBinary() ([]byte, error)`

Renders the current point to a byte slice. Implements the encoding.BinaryMarshaler Interface.

#### func (*Point) MarshalJSON ¶

`func (p *Point) MarshalJSON() ([]byte, error)`

Renders the current Point to valid JSON. Implements the json.Marshaller Interface.

#### func (*Point) MidpointTo ¶

`func (p *Point) MidpointTo(p2 *Point) *Point`

Calculates the midpoint between 'this' point and the supplied point. Original implementation from http://www.movable-type.co.uk/scripts/latlong.html

#### func (*Point) PointAtDistanceAndBearing ¶

`func (p *Point) PointAtDistanceAndBearing(dist float64, bearing float64) *Point`

Returns a Point populated with the lat and lng coordinates by transposing the origin point the passed in distance (in kilometers) by the passed in compass bearing (in degrees). Original Implementation from: http://www.movable-type.co.uk/scripts/latlong.html

#### func (*Point) UnmarshalBinary ¶

`func (p *Point) UnmarshalBinary(data []byte) error`

#### func (*Point) UnmarshalJSON ¶

`func (p *Point) UnmarshalJSON(data []byte) error`

Decodes the current Point from a JSON body. Throws an error if the body of the point cannot be interpreted by the JSON body

#### type Polygon ¶

```type Polygon struct {
// contains filtered or unexported fields
}```

A Polygon is carved out of a 2D plane by a set of (possibly disjoint) contours. It can thus contain holes, and can be self-intersecting.

#### func NewPolygon ¶

`func NewPolygon(points []*Point) *Polygon`

Creates and returns a new pointer to a Polygon composed of the passed in points. Points are considered to be in order such that the last point forms an edge with the first point.

`func (p *Polygon) Add(point *Point)`

Appends the passed in contour to the current Polygon.

#### func (*Polygon) Contains ¶

`func (p *Polygon) Contains(point *Point) bool`

Returns whether or not the current Polygon contains the passed in Point.

#### func (*Polygon) IsClosed ¶

`func (p *Polygon) IsClosed() bool`

Returns whether or not the polygon is closed. TODO: This can obviously be improved, but for now,

```this should be sufficient for detecting if points
are contained using the raycast algorithm.
```

#### func (*Polygon) Points ¶

`func (p *Polygon) Points() []*Point`

Returns the points of the current Polygon.

#### type SQLConf ¶

```type SQLConf struct {
// contains filtered or unexported fields
}```

Provides a set of configuration variables that describe how to interact with a SQL database.

#### func GetSQLConf ¶

`func GetSQLConf() (*SQLConf, error)`

Attempts to read config/geo.yml, and creates a SQLConf as described therein. Returns the DefaultSQLConf if no config/geo.yml is found, or an error if one arises during the process of parsing the configuration file.

#### func GetSQLConfFromFile ¶

`func GetSQLConfFromFile(filename string) (*SQLConf, error)`

Attempts to read from the passed in filename and creates a SQLconf as described therin. Retruns the DefaultSQLConf if the file cannot be found, or an error if one arises during the process of parsing the configuration file.

#### type SQLMapper ¶

```type SQLMapper struct {
// contains filtered or unexported fields
}```

A Mapper that uses Standard SQL Syntax to perform mapping functions and queries

#### func HandleWithSQL ¶

`func HandleWithSQL() (*SQLMapper, error)`

Retrieves the SQL configuration specified in config.yml that resides at the root level of the project. Returns a pointer to a SQLMapper if successful, or an error if there is an issue opening a database connection.

#### func NewSQLMapper ¶

`func NewSQLMapper(filename string, conn *sql.DB) (*SQLMapper, error)`

Creates and returns a pointer to a new geo.SQLMapper.

`func (s *SQLMapper) PointsWithinRadius(p *Point, radius float64) (*sql.Rows, error)`

Uses SQL to retrieve all points within the radius (in meters) passed in from the origin point passed in. Original implemenation from : http://www.movable-type.co.uk/scripts/latlong-db.html Returns a pointer to a sql.Rows as a result, or an error if one occurs during the query.

#### func (*SQLMapper) SqlDbConn ¶

`func (s *SQLMapper) SqlDbConn() *sql.DB`

Returns a pointer to the SQLMapper's SQL Database Connection.