Skip to content
Types and utilities for working with 2d geometry in Golang
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
clip smartclip: implicitly close rings that have endpoints in the bound Feb 24, 2018
encoding encoding/wkb: only limit multi allocations not read length Mar 9, 2019
geo again more readme stuff Feb 6, 2018
geojson geojson: add bbox support Aug 29, 2018
internal encoding/wkb: improve scanner and test coverage Feb 10, 2018
maptile tilecover: improve mergeup functions Mar 27, 2018
planar add some more planar area tests and comments Nov 21, 2018
project
quadtree add more tests and fix examples Feb 21, 2018
resample add most tests Feb 21, 2018
simplify add most tests Feb 21, 2018
.travis.yml fix travis, 1.10 yaml.... Sep 11, 2018
LICENSE.md add license Oct 30, 2017
README.md Fix small typo in README Nov 21, 2018
bound.go add most tests Feb 21, 2018
bound_test.go
clone.go add Equal function and some tests Nov 11, 2017
clone_test.go add Equal function and some tests Nov 11, 2017
define.go Add orb.Round function Sep 9, 2018
equal.go fix equal for types with the same geojson type Feb 9, 2018
equal_test.go add most tests Feb 21, 2018
geometry.go
geometry_test.go add most tests Feb 21, 2018
json_test.go remove New* initializers Nov 11, 2017
line_string.go remove New* initializers Nov 11, 2017
line_string_test.go remove geo types and move the orb Nov 6, 2017
multi_line_string.go fix dimensions issue and bound geojson Nov 27, 2017
multi_line_string_test.go add most tests Feb 21, 2018
multi_point.go fix dimensions issue and bound geojson Nov 27, 2017
multi_point_test.go try to handle invalid/empty bounds Nov 11, 2017
multi_polygon.go clone nil geometries as nil Nov 22, 2017
multi_polygon_test.go add most tests Feb 21, 2018
point.go add quadtree implementation Jan 26, 2018
point_test.go try to handle invalid/empty bounds Nov 11, 2017
polygon.go clone nil geometries as nil Nov 22, 2017
ring.go clone nil geometries as nil Nov 22, 2017
ring_test.go add most tests Feb 21, 2018
round.go Add orb.Round function Sep 9, 2018
round_test.go Add orb.Round function Sep 9, 2018

README.md

orb Build Status Coverage Status Go Report Card Godoc Reference

Package orb defines a set of types for working with 2d geo and planar/projected geometric data in Golang. There are a set of sub-packages that use these types to do interesting things. They each provider their own README with extra info.

Interesting features

  • Simple types - allow for natural operations using the make, append, len, [s:e] builtins.
  • GeoJSON - support as part of the geojson sub-package.
  • Mapbox Vector Tile - encoding and decoding as part of the encoding/mvt sub-package.
  • Direct to type from DB query results - by scanning WKB data directly into types.
  • Rich set of sub-packages - including clipping, simplifing, quadtree and more.

Type definitions

type Point [2]float64
type MultiPoint []Point

type LineString []Point
type MultiLineString []LineString

type Ring LineString
type Polygon []Ring
type MultiPolygon []Polygon

type Collection []Geometry

type Bound struct { Min, Max Point }

Defining the types as slices allows them to be accessed in an idiomatic way using Go's built-in functions such at make, append, len and with slice notation like [s:e]. For example:

ls := make(orb.LineString, 0, 100)
ls = append(ls, orb.Point{1, 1})
point := ls[0]

Shared Geometry interface

All of the base types implement the orb.Geometry interface defined as:

type Geometry interface {
	GeoJSONType() string
	Dimensions() int // e.g. 0d, 1d, 2d
	Bound() Bound
}

This interface is accepted by functions in the sub-packages which then act on the base types correctly. For example:

l := clip.Geometry(bound, geom)

will use the appropriate clipping algorithm depending on if the input is 1d or 2d, e.g. a orb.LineString or a orb.Polygon.

Only a few methods are defined directly on these type, for example Clone, Equal, GeoJSONType. Other operation that depend on geo vs. planar contexts are defined in the respective sub-package. For example:

  • Computing the geo distance between two point:

      p1 := orb.Point{-72.796408, -45.407131}
      p2 := orb.Point{-72.688541, -45.384987}
    
      geo.Distance(p1, p2)
    
  • Compute the planar area and centroid of a polygon:

      poly := orb.Polygon{...}
      centroid, area := planar.CentroidArea(poly)
    

GeoJSON

The geojson sub-package implements Marshalling and Unmarshalling of GeoJSON data. Features are defined as:

type Feature struct {
	ID         interface{}  `json:"id,omitempty"`
	Type       string       `json:"type"`
	Geometry   orb.Geometry `json:"geometry"`
	Properties Properties   `json:"properties"`
}

Defining the geometry as an orb.Geometry interface along with sub-package functions accepting geometries allows them to work together to create easy to follow code. For example, clipping all the geometries in a collection:

fc, err := geojson.UnmarshalFeatureCollection(data)
for _, f := range fc {
	f.Geometry = clip.Geometry(bound, f.Geometry)
}

Mapbox Vector Tiles

The encoding/mvt sub-package implements Marshalling and Unmarshalling MVT data. This package uses sets of geojson.FeatureCollection to define the layers, keyed by the layer name. For example:

collections := map[string]*geojson.FeatureCollection{}

// Convert to a layers object and project to tile coordinates.
layers := mvt.NewLayers(collections)
layers.ProjectToTile(maptile.New(x, y, z))

// In order to be used as source for MapboxGL geometries need to be clipped
// to max allowed extent. (uncomment next line)
// layers.Clip(mvt.MapboxGLDefaultExtentBound)

// Simplify the geometry now that it's in tile coordinate space.
layers.Simplify(simplify.DouglasPeucker(1.0))

// Depending on use-case remove empty geometry, those too small to be
// represented in this tile space.
// In this case lines shorter than 1, and areas smaller than 2.
layers.RemoveEmpty(1.0, 2.0)

// encoding using the Mapbox Vector Tile protobuf encoding.
data, err := layers.Marshal() // this data is NOT gzipped.

// Sometimes MVT data is stored and transfered gzip compressed. In that case:
data, err := layers.MarshalGzipped()

Decoding WKB from a database query

Geometries are usually returned from databases in WKB format. The encoding/wkb sub-package offers helpers to "scan" the data into the base types directly. For example:

row := db.QueryRow("SELECT ST_AsBinary(point_column) FROM postgis_table")

var p orb.Point
err := row.Scan(wkb.Scanner(&p))

db.Exec("INSERT INTO table (point_column) VALUES (ST_GeomFromWKB(?))", wkb.Value(p))

List of sub-package utilities

  • clip - clipping geometry to a bounding box
  • encoding/mvt - encoded and decoding from Mapbox Vector Tiles
  • encoding/wkb - well-known binary as well as helpers to decode from the database queries
  • encoding/wkt - well-known text encoding
  • geojson - working with geojson and the types in this package
  • maptile - working with mercator map tiles
  • project - project geometries between geo and planar contexts
  • quadtree - quadtree implementation using the types in this package
  • resample - resample points in a line string geometry
  • simplify - linear geometry simplifications like Douglas-Peucker
You can’t perform that action at this time.