Package geom implements efficient geometry types for geospatial applications.

go-geom

PkgGoDev Go Report Card Coverage Status

Package geom implements efficient geometry types for geospatial applications.

Key features

  • OpenGeo Consortium-style geometries.
  • Support for 2D and 3D geometries, measures (time and/or distance), and unlimited extra dimensions.
  • Encoding and decoding of common geometry formats (GeoJSON, KML, WKB, and others) including sql.Scanner and driver.Value interface implementations for easy database integration.
  • 2D and 3D topology functions.
  • Efficient, cache-friendly internal representation.
  • Optional protection against malicious or malformed inputs.

Examples

Detailed features

Geometry types

Encoding and decoding

Geometry functions

  • XY 2D geometry functions
  • XYZ 3D geometry functions

Protection against malicious or malformed inputs

The WKB and EWKB formats encode geometry sizes, and memory is allocated for those geometries. If the input is malicious or malformed, the memory allocation can be very large, leading to a memory starvation denial-of-service attack against the server. For example, a client might send a MultiPoint with header indicating that it contains 2^32-1 points. This will result in the server reading that geometry to allocate 2 × sizeof(float64) × (2^32-1) = 64GB of memory to store those points. By default, malicious or malformed input protection is disabled, but can be enabled by setting positive values for wkbcommon.MaxGeometryElements.

Related libraries

License

BSD-2-Clause

Comments
  • Error when trying to Scan an EWKB polygon

    Error when trying to Scan an EWKB polygon

    I am getting sql: Scan error on column index 0: unsupported Scan, storing driver.Value type []uint8 into type *geom.Polygon when trying to retrieve a geometry from my PostGIS database.

    I'm doing a very simple Scan now like so:

    rows, err := db.Query("SELECT geom FROM testgeoms")
    for rows.Next() {
    	var g gogeom.Polygon
    	err := rows.Scan(&g)
    }
    

    Any pointers on what went wrong here?

  • modify POINT to use [NaN] as the coordinates for empty

    modify POINT to use [NaN] as the coordinates for empty

    To follow Requirement 152 of http://www.geopackage.org/spec/:

    If the geometry is a Point, it SHALL be encoded with each coordinate value set to an IEEE-754 quiet NaN value. GeoPackages SHALL use big endian 0x7ff8000000000000 or little endian 0x000000000000f87f as the binary encoding of the NaN values. (This is because Well-Known Binary as defined in OGC 06-103r4 [9] does not provide a standardized encoding for an empty point set, i.e., 'Point Empty' in Well-Known Text.)
    

    and allow MULTIPOINT (EMPTY, POINT(1.0 1.0)) to be represented, we need to convert POINT to use NaN to encode empty.

    Ran into reflect.DeepEqual not respecting NaN == NaN, so had to split some tests out of their shell.

  • GeoJSON: Added DecodeGeoJSON to directly decode GeoJSON bytes to geo types

    GeoJSON: Added DecodeGeoJSON to directly decode GeoJSON bytes to geo types

    This implementation returns an interface{} directly to avoid the shaded geo.T type. Due to the architecture of the geo types in this library, a geo.T cannot be easily be type asserted directly into the other types. Returning an interface{} here instead of a geo.T sidesteps that limitation and allows the consuming program to type check and assert properly to the underlying geo type.

  • wkb: github.com/lib/pq requires binary_parameters=yes

    wkb: github.com/lib/pq requires binary_parameters=yes

    I'm using the wkb package to query PostGIS via github.com/lib/pq. In the default configuration, the queries failed with pq: invalid byte sequence for encoding "UTF8": 0x00. I found that it was necessary to add binary_parameters=yes to the connection string. (Documented here https://godoc.org/github.com/lib/pq#hdr-Data_Types.)

    Just wanted to open this issue in case someone else runs into the same problem. Maybe worth a note in the documentation?

    Thanks!

  • When appropriate changed []float64 to Coord in order to provide some semantics

    When appropriate changed []float64 to Coord in order to provide some semantics

    I found that I would sometimes it was not clear the meaning of float64 since it is used everywhere with different meanings. Sometimes a coordinate and should have a specific number of ordinates in this case and other times as the float coord representation of an object.

    The PR adds the Coord type (just []float64) primarily in order to add semantic meaning but it also has the benefit of providing compile time checking.

    I am thinking that a similar PR for a FlatCoord or Coords type could be useful.

  • Question: dealing with postgis geometry type

    Question: dealing with postgis geometry type

    My geo data are stored in a column of type GEOMETRY in postgis, because it can be a point, a line or a polygon.

    Thus I wonder which encoding/wkb type should I use to decode its value when I fetch the data. Indeed for instance it can't be a wkb.Point because it will work only for a geometry of kind point, and I will have an error for other kinds.

    Any help would be appreciated :)

  • encoding: support GEOMETRYCOLLECTION EMPTY wkb/ewkb writes

    encoding: support GEOMETRYCOLLECTION EMPTY wkb/ewkb writes

    This follows the WKT encoding protocol allowing GEOMETRYCOLLECTION EMPTY to be written as WKB and EWKB.

    cc https://github.com/cockroachdb/cockroach/issues/48533

  • wkb: unknown byte order: 1000111 (GeoPackage SQL Geometry Binary Format)

    wkb: unknown byte order: 1000111 (GeoPackage SQL Geometry Binary Format)

    I want to insert and query Geometry(point) from GeoPackage.gpkg. When query, got this:

    sql: Scan error on column index 0, name "geom": wkb: unknown byte order: 1000111
    

    I don't know much about Geometry Binary Format. http://www.geopackage.org/spec121/index.html#gpb_format

    It's there any way to solve the problem?

    Code:

    	db, e := sql.Open("sqlite3", "/home/x/公共的/Hubei.gpkg")
    	if e != nil {
    		log.Fatalln(e)
    	}
    
    	//查询
    	rows, err := db.Query("select geom, name from points limit 1")
    	if err != nil {
    		log.Fatal(err)
    	}
    	defer rows.Close()
    	for rows.Next() {
    		var ewkbPoint ewkb.Point
    		var name string
    		err = rows.Scan(&ewkbPoint, &name)
    		if err != nil {
    			log.Fatal(err)
    		}
    		fmt.Println("查到数据:", ewkbPoint.X(), ewkbPoint.Y(), name)
    	}
    	err = rows.Err()
    	if err != nil {
    		log.Fatal(err)
    	}
    

    GeoPackage DB(sqlite): https://file-1251456514.cos.ap-shanghai.myqcloud.com/geopackage/Hubei.gpkg

  • WKB is missing collections support

    WKB is missing collections support

    This WKB

    0107000000030000000101000000550B36BFABD753C07CE58B07A5D24540010200000005000000C4190D2ABBD753C028AA6D799BD24540B51F84DBB5D753C07954A1269FD24540F9DB9E20B1D753C0E3D011AFA1D24540FB8E86F8ACD753C0ED444948A4D24540550B36BFABD753C07CE58B07A5D24540010200000002000000550B36BFABD753C07CE58B07A5D24540F6D786E5AAD753C0C619C39CA0D24540
    

    is

    GEOMETRYCOLLECTION(POINT(-79.3698576 43.6456613),LINESTRING(-79.3707986 43.6453697,-79.3704747 43.6454819,-79.370186 43.6455592,-79.3699323 43.6456385,-79.3698576 43.6456613),LINESTRING(-79.3698576 43.6456613,-79.3698057 43.6455265))
    

    But fails with

    wkb: unsupported type: 7
    
  • Restore convex hull functionality

    Restore convex hull functionality

    Convex hull functionality was removed in #62 in response to #61.

    From https://github.com/twpayne/go-geom/issues/61#issuecomment-287302446:

    If you could contribute a replacement (the easiest way to do this is likely to find some BSD-compatible code and translate it to Go), that would be awesome! The only function that needs replacing is xy/internal/robustdeterminate/robust_determinate.go. You can then revert commit 2a0c7d6 to restore the functionality.

  • Fix floating point precision failures caused by FMA on ppc64le

    Fix floating point precision failures caused by FMA on ppc64le

    Following tests fail on ppc64le due to FMA: xy - TestAreaGetCentroid - TestCentroid - TestSignedArea - TestLineGetCentroidLines - TestLineGetCentroidPolygons - ExampleLinearRingsCentroid

    xy/lineintersector - TestRobustLineIntersectionLines

    xyz - TestVectorDot - TestVectorLength - TestDistanceLineToLine - TestDistancePointToLine

    See https://go.dev/ref/spec#Floating_point_operators for more details.

  • geojsonFeature does not support number ids

    geojsonFeature does not support number ids

    According to RFC 7946 a feature can have a numeric identifier:

    If a Feature has a commonly used identifier, that identifier SHOULD be included as a member of the Feature object with the name "id", and the value of this member is either a JSON string or number.

    When I try to load a file that uses numeric identifiers this currently results in an error, because geojsonFeature only accepts a string:

    https://github.com/twpayne/go-geom/blob/25827fa27637655126807e5b5466b28bbeff7fc9/encoding/geojson/geojson.go#L58-L64

  • Question about the Valuer implementation of EWKB

    Question about the Valuer implementation of EWKB

    Hi,

    lately I've been trying to get this library to work with sqlboiler, to basically teach it how to talk to PostGIS. Everything went pretty well, but when attempting to INSERT or UPDATE, this error https://github.com/golang/go/blob/master/src/database/sql/convert.go#L194 kept popping up.

    Everything looked good, I didn't understand why the Value isn't called. I found out this switch statement https://github.com/golang/go/blob/2ebe77a2fda1ee9ff6fd9a3e08933ad1ebaea039/src/database/sql/driver/types.go#L241 doesn't detect ewkb.GeometryCollection that I was using as a Valuer.

    The fix I ended up doing is this: https://github.com/JanBaryla/go-geom/commit/daae2eef34b19e20253170ee1b0a5c0786cd04ac. Not quite sure what the consequences could be, though, so I'm opening an Issue instead of a PR.

  • Determine WKT parsing strictness

    Determine WKT parsing strictness

    This is opened from the comments from @otan and @andyyang890 in #197.

    @otan wrote:

    i think in go-geom, we want to relax things we check in CockroachDB (subject to @twpayne guidance!) as go-geom takes a more "OGC spec" view of the world, namely: a) geometrycollections can have mixed dimensions. b) linestrings/polygons do not have to have 2/4 points respectively, and polygon rings don't have to be closed. c) i think empty can be mixed willy nilly in MultiPoint.

    we can choose to optionally allow these checks (but have them off by default). this should be done with options -- see how we did the EncodeOption for Marshal above. probably DecodeOptionRunPostGISCompatibilityChecks which enables all the checks we did above.

    @andyyang890 replied:

    a) geometrycollections can have mixed dimensions.

    If the PostGIS compatibility option is not specified:

    1. Should a GEOMETRYCOLLECTION{M, Z, ZM} be allowed to have geometries with different dimensions or does that only apply to GEOMETRYCOLLECTION?
    2. Should the layout for a GEOMETRYCOLLECTION always be geom.NoLayout?
    3. If the answer to 1 is no, should the layout of a *GeometryCollection be set if it is a GEOMETRYCOLLECTION{M, Z, ZM} or should it remain as geom.NoLayout?
  • Polygon intersection and containment

    Polygon intersection and containment

    I'm looking for a way to use this library to check, using Cartesian coordinates:

    • If two polygons intersect
    • if a polygon fully contains another polygon

    I'm not seeing any exported functions for doing this. Is there any support for it, or should I look somewhere else?

    From what I can tell, checking if a point is contained in a polygon can be accomplished this way:

    func PolygonContainsPoint(polygon *geom.Polygon, p *geom.Point) bool {
    	exterior := polygon.LinearRing(0)
    	if !xy.IsPointInRing(geom.XY, p.Coords(), exterior.FlatCoords()) {
    		return false
    	}
    
    	// Next rings are holes
    	num := polygon.NumLinearRings()
    	for i := 1; i < num; i++ {
    		interior := polygon.LinearRing(i)
    		if xy.IsPointInRing(geom.XY, p.Coords(), interior.FlatCoords()) {
    			return false
    		}
    	}
    
    	return true
    }
    

    Or? I'm not too familiar with rings or if this is how they're intended to be used. Either way, such a function would be a useful addition to this library, I think.

  • Use mapstructure to decode geometry

    Use mapstructure to decode geometry

    Hi,

    I'm using your library to convert some mongodb documents into postgis rows. The way I do it is simple, with mongodb I decode the bson into a struct with map[string]interface{}, Then I use your library to convert the geojson part into ewkb.

    But to do so I have to first use json.Marshal, because the Unmarshal method from geojson needs a json (in bytes) to Unmarshal it. So it's Bson -> map[string]interface{} -> json -> Geometry

    Would it be possible to use mapstructure to encode/decode (using maybe separate functions to not break the API), to prevent this kind of pattern? It should be pretty simple from my very short experience with mapstructure in the past.

Efficient 2D geometry library for Go.

geometry An efficient 2D geometry library for Go. Features Point, Rect, Line, and Polygon geometry types Operations such as Intersects, Contains, and

Dec 22, 2022
Go (golang) wrapper for GDAL, the Geospatial Data Abstraction Library

------------- About ------------- The gdal.go package provides a go wrapper for GDAL, the Geospatial Data Abstraction Library. More information about

Dec 24, 2022
Real-time Geospatial and Geofencing
Real-time Geospatial and Geofencing

Tile38 is an open source (MIT licensed), in-memory geolocation data store, spatial index, and realtime geofence. It supports a variety of object types

Dec 30, 2022
Geometry/geography library in Go, DEPRECATED, use ->

go.geo (deprecated) Go.geo is a geometry/geography library in Go. The primary use case is GIS geometry manipulation on the server side vs. in the brow

Jan 2, 2023
S2 geometry library in Go

Overview S2 is a library for spherical geometry that aims to have the same robustness, flexibility, and performance as the best planar geometry librar

Dec 31, 2022
Package polyline implements a Google Maps Encoding Polyline encoder and decoder.

go-polyline Package polyline implements a Google Maps Encoding Polyline encoder and decoder. Encoding example func ExampleEncodeCoords() { coords :=

Dec 1, 2022
Geocache is an in-memory cache that is suitable for geolocation based applications.
Geocache is an in-memory cache that is suitable for geolocation based applications.

geocache geocache is an in-memory cache that is suitable for geolocation based applications. It uses geolocation as a key for storing items. You can s

Oct 27, 2022
Go package to quick and easy create json data in geojson format.

#GEOJSON Go package to easy and quick create datastructure which can be serialized to geojson format INSTALLATION $ go get github.com/kpawlik/geojson

Jun 6, 2022
Package kml provides convenince methods for creating and writing KML documents.

go-kml Package kml provides convenience methods for creating and writing KML documents. Key Features Simple API for building arbitrarily complex KML d

Jul 29, 2022
A pure Go package for coordinate transformations.

WGS84 A pure Go package for coordinate transformations. go get github.com/wroge/wgs84 Usage east, north, h := wgs84.LonLat().To(wgs84.ETRS89UTM(32)).R

Nov 25, 2022
yet another point in polygon package

piper Yet another point in polygon package. Piper makes use of ray casting and does account for holes in polygons. Installation go get -u github.com/i

Oct 17, 2022
Plugs module to see different types of plug types needed in different countries, and a comparison tool between two countries plug socket types.

plugs Importing the module: go get github.com/matthewboyd/plugs "github.com/matthewboyd/plugs" How to use the module: There are two functions wi

Dec 28, 2021
Types and utilities for working with 2d geometry in Golang

orb 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

Dec 28, 2022
Types and utilities for working with 2d geometry in Golang

orb 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

Dec 28, 2022
Efficient 2D geometry library for Go.

geometry An efficient 2D geometry library for Go. Features Point, Rect, Line, and Polygon geometry types Operations such as Intersects, Contains, and

Dec 22, 2022
Package varflag implements command-line flag parsing into vars.Variables for easy type handling with additional flag types.

varflag Package flag implements command-line flag parsing into vars.Variables for easy type handling with additional flag types. varflag Flags String

Aug 2, 2022
Package mafsa implements Minimal Acyclic Finite State Automata in Go, essentially a high-speed, memory-efficient, Unicode-friendly set of strings.

MA-FSA for Go Package mafsa implements Minimal Acyclic Finite State Automata (MA-FSA) with Minimal Perfect Hashing (MPH). Basically, it's a set of str

Oct 27, 2022
BuntDB is an embeddable, in-memory key/value database for Go with custom indexing and geospatial support
BuntDB is an embeddable, in-memory key/value database for Go with custom indexing and geospatial support

BuntDB is a low-level, in-memory, key/value store in pure Go. It persists to disk, is ACID compliant, and uses locking for multiple readers and a sing

Dec 30, 2022
Go (golang) wrapper for GDAL, the Geospatial Data Abstraction Library

------------- About ------------- The gdal.go package provides a go wrapper for GDAL, the Geospatial Data Abstraction Library. More information about

Dec 24, 2022
Real-time Geospatial and Geofencing
Real-time Geospatial and Geofencing

Tile38 is an open source (MIT licensed), in-memory geolocation data store, spatial index, and realtime geofence. It supports a variety of object types

Jan 4, 2023