Skip to content
swift-navPublic
forked from sams96/rgeo

About

Go package for basic, fast, local reverse geocoding

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

rgeo

Codecov Release go.dev reference

Rgeo is a fast, simple solution for local reverse geocoding, Rather than relying on external software or online APIs, rgeo packages all of the data it needs in your binary. This means it will only ever work down to the level of cities , but if that's all you need then this is the library for you.

Rgeo uses data from naturalearthdata.com, if your coordinates are going to be near specific borders I would advise checking the data beforehand (links to which are in the files). If you want to use your own dataset, check out datagen.

Current status

Rgeo is not being activly developed. I will try to keep dependencies up to date but no new features will be added. You can read more here if you are interested. If you are looking for an alternative, I recommend:

  • smilyorg/tinygpkg - Very nice package inspired by Rgeo. It uses a different approach to vastly reduce startup time at the cost of slightly slower queries.
  • authenticvision/rgeo - The most active fork of Rgeo, and most of the contributions I’ve had have come from these guys. Otherwise it should be fine to keep using Rgeo with its existing features.

Key Features

  • Fast - So I haven't actually benchmarked other reverse geocoding tools but on my laptop rgeo can run at under 800ns/op.
  • Local - Rgeo doesn't require pinging some API, most of which either cost money to use or have severe rate limits.
  • Lightweight - The rgeo repo is 32MB, which is large for a Go package but compared to the 800GB needed for a full planet install of Nominatim it's miniscule.

Installation

Download with

go get github.com/sams96/rgeo

and add

import "github.com/sams96/rgeo"

to the top of your Go file to include it in your project.

Usage

r, err := New(Provinces10, Cities10)
if err != nil {
	// Handle error
}

loc, err := r.ReverseGeocode([]float64{141.35, 43.07})
if err != nil {
	// Handle error
}

fmt.Println(loc)
// Output: <Location> Sapporo, Hokkaidō, Japan (JPN), Asia

First initialise rgeo using rgeo.New,

func New(datasets ...func() []byte) (*Rgeo, error)

which takes any non-zero number of datasets as arguments. The included datasets are:

  • Countries110 - Just country information, smallest and lowest detail of the included datasets.
  • Countries10 - The same as above but with more detail.
  • CountriesEEZ10 - An alternative to Countries10 built from the MarineRegions EEZ land union. Its polygons extend to the edge of each country's exclusive economic zone (roughly 200 nautical miles offshore) rather than stopping at the coastline, so points at sea resolve to a country instead of returning ErrLocationNotFound.
  • Provinces10 - Includes province information as well as country, so can still be used alone.
  • Cities10 - Just city information, if you want provinces and/or countries as well use one of the above datasets with it. Once initialised you can use ReverseGeocode on the value returned by New, with your coordinates to get the location information. See the Go Docs for more information on usage.

Then use ReverseGeocode to get the location information of the given coordinate.

func (r *Rgeo) ReverseGeocode(loc geom.Coord) (Location, error)

The input is a geom.Coord, which is just a []float64 with the longitude in the zeroth position and the latitude in the first position (i.e. []float64{lon, lat}). ReverseGeocode returns a Location, which looks like this:

type Location struct {
	// Commonly used country name
	Country string `json:"country,omitempty"`

	// Formal name of country
	CountryLong string `json:"country_long,omitempty"`

	// ISO 3166-1 alpha-1 and alpha-2 codes
	CountryCode2 string `json:"country_code_2,omitempty"`
	CountryCode3 string `json:"country_code_3,omitempty"`

	Continent string `json:"continent,omitempty"`
	Region    string `json:"region,omitempty"`
	SubRegion string `json:"subregion,omitempty"`

	Province string `json:"province,omitempty"`

	// ISO 3166-2 code
	ProvinceCode string `json:"province_code,omitempty"`

	City string `json:"city,omitempty"`
}

So, to put it all together:

r, err := rgeo.New(Countries110)
if err != nil {
	// Handle error
}

loc, err := r.ReverseGeocode([]float64{0, 52})
if err != nil {
	// Handle error
}

fmt.Printf("%s\n", loc.Country)
fmt.Printf("%s\n", loc.CountryLong)
fmt.Printf("%s\n", loc.CountryCode2)
fmt.Printf("%s\n", loc.CountryCode3)
fmt.Printf("%s\n", loc.Continent)
fmt.Printf("%s\n", loc.Region)
fmt.Printf("%s\n", loc.SubRegion)

// Output: United Kingdom
// United Kingdom of Great Britain and Northern Ireland
// GB
// GBR
// Europe
// Europe
// Northern Europe

Data sources

Countries110, Countries10, Provinces10 and Cities10 are built from Natural Earth, which is in the public domain.

CountriesEEZ10 uses the MarineRegions EEZ land union for its geometry, with country attributes and names from Natural Earth. The MarineRegions data is licensed CC-BY 4.0 and requires attribution:

Flanders Marine Institute (2024). Union of the ESRI Country shapefile and the Exclusive Economic Zones (version 4). Available online at https://www.marineregions.org/. https://doi.org/10.14284/698.

Per-dataset provenance is recorded alongside each file in data/. CountriesEEZ10 is rebuilt by scripts/eez/simplify.sh; the other datasets by datagen.

Contributing

I'm not accepting new features for the time being, see above.

About

Go package for basic, fast, local reverse geocoding

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages