From 6a706a23a645af9db8cff5c8471c49fac1694fd7 Mon Sep 17 00:00:00 2001 From: Peter Stace Date: Fri, 30 Jan 2026 17:04:47 +1100 Subject: [PATCH 1/2] Revamp README (WIP) --- .ci/assets/envelope.svg | 30 -------- README.md | 150 ++++++++-------------------------------- 2 files changed, 28 insertions(+), 152 deletions(-) delete mode 100644 .ci/assets/envelope.svg diff --git a/.ci/assets/envelope.svg b/.ci/assets/envelope.svg deleted file mode 100644 index a3f14279..00000000 --- a/.ci/assets/envelope.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/README.md b/README.md index 18caa459..730fb903 100644 --- a/README.md +++ b/README.md @@ -18,132 +18,32 @@ specification that [GEOS](https://trac.osgeo.org/geos), implement, so the Simple Features API will be familiar to developers who have used those libraries before. -#### Table of Contents - -- [Geometry Types](#geometry-types) -- [Marshalling and Unmarshalling](#marshalling-and-unmarshalling) -- [Geometry Algorithms](#geometry-algorithms) +**Table of Contents:** +- [Supported Features](#supported-features) - [GEOS Wrapper](#geos-wrapper) - [PROJ Wrapper](#proj-wrapper) - [Examples](#examples) -### Geometry Types - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TypeExampleDescription
PointPoint is a single location in space.
MultiPointMultiPoint is collection of points in space.
LineStringLineString is curve defined by linear interpolation between a set of -control points.
MultiLineStringMultiLineString is a collection of LineStrings.
PolygonPolygon is a planar surface geometry that bounds some area. It may have holes.
MultiPolygonMultiPolygon is collection of Polygons (with some constraints on how the Polygons interact with each other).
GeometryCollectionGeometryCollection is an unconstrained collection of geometries.
GeometryGeometry holds any type of geometry (Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, or GeometryCollection). It's the type that the Simple Features library uses when it needs to represent geometries in a generic way.
EnvelopeEnvelope is an axis aligned bounding box typically used to describe the spatial extent of other geometric entities.
- -### Marshalling and Unmarshalling - -Simple features supports the following external geometry representation formats: - -| Format | Example | Description | -| --- | --- | --- | -| WKT | `POLYGON((0 0,0 1,1 1,1 0,0 0))` | [Well Known Text](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry) is a human readable format for storing geometries. It's often the lowest common denominator geometry format, and is useful for integration with other GIS applications. | -| WKB | `` | [Well Known Binary](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry#Well-known_binary) is a machine readable format that is efficient for computers to use (both from a processing and storage space perspective). WKB is a good choice for transferring geometries to and from PostGIS and other databases that support geometric types. | -| GeoJSON | `{"type":"Polygon","coordinates":[[[0,0],[0,1],[1,1],[1,0],[0,0]]]}` | [GeoJSON](https://en.wikipedia.org/wiki/GeoJSON) represents geometries in a similar way to WKB, but is based on the JSON format. This makes it ideal to use with web APIs or other situations where JSON would normally be used. | -| TWKB | `` | [Tiny Well Known Binary](https://github.com/TWKB/Specification) is a multi-purpose compressed binary format for serialising vector geometries into a stream of bytes. It emphasises minimising the size of the serialised representation. It's a good choice when space is at a premium (e.g. for storage within a web token). | - -### Geometry Algorithms - -The following algorithms are supported: - -| Miscellaneous Algorithms | Description | -| --- | --- | -| [Area](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Geometry.Area) | Finds the area of the geometry (for Polygons and MultiPolygons). | -| [Centroid](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Geometry.Centroid) | Finds the centroid of the geometry. | -| [ConvexHull](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Geometry.ConvexHull) | Finds the convex hull of the geometry. | -| [Distance](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Distance) | Finds the shortest distance between two geometries. | -| [Envelope](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Geometry.Envelope) | Finds the smallest axis-aligned bounding-box that surrounds the geometry. | -| [ExactEquals](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#ExactEquals) | Determines if two geometries are structurally equal. | -| [Length](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Geometry.Length) | Finds the length of the geometry (for LineStrings and MultiLineStrings). | -| [PointOnSurface](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Geometry.PointOnSurface) | Finds a point that lies inside the geometry. | -| [Relate](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Relate) | Calculates the DE-9IM intersection describing the relationship between two geometries. | -| [Simplify](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Simplify) | Simplifies a geometry using the Ramer–Douglas–Peucker algorithm. | - -| Set Operations | Description | -| --- | --- | -| [Union](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Union) | Joins the parts from two geometries together. | -| [Intersection](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Intersection) | Finds the parts of two geometries that are in common. | -| [Difference](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Difference) | Finds the parts of a geometry that are not also part of another geometry. | -| [SymmetricDifference](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#SymmetricDifference) | Finds the parts of two geometries that are not in common. | - - -| Named Spatial Predicates | Description | -| --- | --- | -| [Equals](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Equals) | Determines if two geometries are topologically equal. | -| [Intersects](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Intersects) | Determines if two geometries intersect with each other. | -| [Disjoint](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Disjoint) | Determines if two geometries have no common points. | -| [Contains](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Contains) | Determines if one geometry contains another. | -| [CoveredBy](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#CoveredBy) | Determines if one geometry is covered by another. | -| [Covers](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Covers) | Determines if one geometry covers another. | -| [Overlaps](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Overlaps) | Determines if one geometry overlaps another. | -| [Touches](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Touches) | Determines if one geometry touches another. | -| [Within](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Within) | Determines if one geometry is within another. | -| [Crosses](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom#Crosses) | Determines if one geometry crosses another. | +### Package Structure + +TODO + +### Native Go Supported Features + +- **All 7 OGC Geometry Types:** `Point`, `MultiPoint`, `LineString`, `MultiLineString`, `Polygon`, `MultiPolygon`, `GeometryCollection`. +- **Overlay operations:** union, intersection, difference, symmetric difference, unary union. +- **Relate operations:** DE-9IM matrix, equals, intersects, disjoint, contains, covered by, covers, overlaps, touches, within, crosses. +- **Envelope operations:** intersects, contains, covers, distance, expand to include, center, width, height, area, bounding diagonal. +- **Measurements:** area, length, distance. +- **Analysis:** centroid, convex hull, envelope, point on surface, boundary, minimum area bounding rectangle, minimum width bounding rectangle. +- **Transformations:** simplify, densify, snap to grid, reverse, force clockwise, force counter-clockwise, affine transformation. +- **Comparison:** exact equals. +- **Linear Interpolation:** interpolate point, interpolate evenly spaced points. +- **Properties:** is simple, is empty, dimension, is clockwise, is counter-clockwise, validate. +- **Serialisation:** WKT, WKB, GeoJSON, TWKB. +- **Map projections:** equirectangular, web mercator, orthographic, sinusoidal, + UTM, Lambert cylindrical equal area, Lambert conformal conic, Albers equal + area conic, equidistant conic, azimuthal equidistant. ### GEOS Wrapper @@ -163,8 +63,14 @@ package](https://pkg.go.dev/github.com/peterstace/simplefeatures/proj?tab=doc), meaning that library users who don't need this additional functionality don't need to expose themselves to CGO. +### JTS Port + +TODO + ### Examples +TODO: Do we need this section? + The following examples show some common operations (errors are omitted for brevity). From bfed72e6fff1fc55af589326af3a321e29a1dfda Mon Sep 17 00:00:00 2001 From: Peter Stace Date: Sat, 31 Jan 2026 15:53:56 +1100 Subject: [PATCH 2/2] Finish updating README --- .github/pull_request_template.md | 2 + README.md | 194 ++++++++++++------------------- 2 files changed, 78 insertions(+), 118 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index fe75148b..ac35e67a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -13,6 +13,8 @@ Have you: - Updated release notes? (if appropriate?) +- Updated the README.md (if new functionality is added?) + ## Related Issue - Please link to the related issue(s). diff --git a/README.md b/README.md index 730fb903..f0744e94 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Simple Features -[![Documentation](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom?tab=doc) [![Build Status](https://github.com/peterstace/simplefeatures/workflows/build/badge.svg)](https://github.com/peterstace/simplefeatures/actions) [![Go Report Card](https://goreportcard.com/badge/github.com/peterstace/simplefeatures)](https://goreportcard.com/report/github.com/peterstace/simplefeatures) @@ -19,155 +18,114 @@ implement, so the Simple Features API will be familiar to developers who have used those libraries before. **Table of Contents:** -- [Supported Features](#supported-features) -- [GEOS Wrapper](#geos-wrapper) -- [PROJ Wrapper](#proj-wrapper) -- [Examples](#examples) +- [Native Go Packages](#native-go-packages) + - [Geom](#geom) + - [Carto](#carto) + - [R-Tree](#r-tree) +- [C-Wrapper Packages](#c-wrapper-packages) + - [GEOS](#geos) + - [PROJ](#proj) -### Package Structure +## Native Go Packages -TODO +The Simple Features library contains several packages that are implemented +purely in Go, and do not require CGO to use. These are `geom`, `carto`, and +`rtree`. -### Native Go Supported Features +### Geom -- **All 7 OGC Geometry Types:** `Point`, `MultiPoint`, `LineString`, `MultiLineString`, `Polygon`, `MultiPolygon`, `GeometryCollection`. +[Package +`geom`](https://pkg.go.dev/github.com/peterstace/simplefeatures/geom?tab=doc) +provides types (`Point`, `MultiPoint`, `LineString`, `MultiLineString`, +`Polygon`, `MultiPolygon`, `GeometryCollection`) representing each geometry, as +well as algorithms that operate with/on them. + +The following operations are supported: + +- **Serialisation:** WKT, WKB, GeoJSON, TWKB. - **Overlay operations:** union, intersection, difference, symmetric difference, unary union. - **Relate operations:** DE-9IM matrix, equals, intersects, disjoint, contains, covered by, covers, overlaps, touches, within, crosses. -- **Envelope operations:** intersects, contains, covers, distance, expand to include, center, width, height, area, bounding diagonal. - **Measurements:** area, length, distance. - **Analysis:** centroid, convex hull, envelope, point on surface, boundary, minimum area bounding rectangle, minimum width bounding rectangle. - **Transformations:** simplify, densify, snap to grid, reverse, force clockwise, force counter-clockwise, affine transformation. - **Comparison:** exact equals. - **Linear Interpolation:** interpolate point, interpolate evenly spaced points. - **Properties:** is simple, is empty, dimension, is clockwise, is counter-clockwise, validate. -- **Serialisation:** WKT, WKB, GeoJSON, TWKB. -- **Map projections:** equirectangular, web mercator, orthographic, sinusoidal, - UTM, Lambert cylindrical equal area, Lambert conformal conic, Albers equal - area conic, equidistant conic, azimuthal equidistant. - -### GEOS Wrapper - -A [GEOS](https://www.osgeo.org/projects/geos/) CGO wrapper is also provided, -giving access to functionality not yet implemented natively in Go. The [wrapper -is implemented in a separate -package](https://pkg.go.dev/github.com/peterstace/simplefeatures/geos?tab=doc), -meaning that library users who don't need this additional functionality don't -need to expose themselves to CGO. - -### PROJ Wrapper +- **Envelope operations:** intersects, contains, covers, distance, expand to include, center, width, height, area, bounding diagonal. -A [PROJ](https://proj.org/) CGO wrapper is also provided, giving access to a -vast array of transformations between various coordinate reference systems. -The [wrapper is implemented in a separate -package](https://pkg.go.dev/github.com/peterstace/simplefeatures/proj?tab=doc), -meaning that library users who don't need this additional functionality don't -need to expose themselves to CGO. +The overlay and relate operations are powered by a Go port of +[JTS](https://locationtech.github.io/jts/). This means that it's using robust +and battle tested algorithms that are common to JTS and its derivates (such as +GEOS). -### JTS Port +### Carto -TODO +[Package +`carto`](https://pkg.go.dev/github.com/peterstace/simplefeatures/carto?tab=doc) +provides cartographic map projections and related functionality. It can be used +as a lite replacement for PROJ for simple cartographic projections. -### Examples +The following projections are supported: -TODO: Do we need this section? +- **Conic:** Lambert conformal conic, Albers equal area conic, equidistant + conic. +- **Cylindrical:** equirectangular, web mercator, Lambert cylindrical equal + area. +- **Azimuthal:** orthographic, azimuthal equidistant. +- **Pseudocylindrical:** sinusoidal. +- **UTM:** All 60 UTM projections. -The following examples show some common operations (errors are omitted for -brevity). +### R-Tree -#### WKT +[Package +`rtree`](https://pkg.go.dev/github.com/peterstace/simplefeatures/rtree?tab=doc) +provides an in-memory R-Tree data structure, which can be used for fast and +efficient spatial searches. -Encoding and decoding WKT: +## C-Wrapper Packages -```go -// Unmarshal from WKT -input := "POLYGON((0 0,0 1,1 1,1 0,0 0))" -g, _ := geom.UnmarshalWKT(input) +The Simple Features library also contains several packages that depend on C +libraries (via CGO). They are segregated into separate Go packages so users who +don't need that functionality aren't required to install the relevant C +dependencies. -// Marshal to WKT -output := g.AsText() -fmt.Println(output) // Prints: POLYGON((0 0,0 1,1 1,1 0,0 0)) -``` +### GEOS -#### WKB +[Package +`geos`](https://pkg.go.dev/github.com/peterstace/simplefeatures/geos?tab=doc) +is a thin CGO wrapper around the [GEOS](https://www.osgeo.org/projects/geos/) +library. It provides access to GEOS functionality that has not yet been +implemented in the `geom` package natively in Go. -Encoding and decoding WKB directly: +To install the GEOS C library: -```go -// Marshal as WKB -coords := geom.Coordinates{XY: geom.XY{1.5, 2.5}} -pt := geom.NewPoint(coords) -wkb := pt.AsBinary() -fmt.Println(wkb) // Prints: [1 1 0 0 0 0 0 0 0 0 0 248 63 0 0 0 0 0 0 4 64] +```sh +# Debian/Ubuntu +apt-get install libgeos-dev -// Unmarshal from WKB -fromWKB, _ := geom.UnmarshalWKB(wkb) -fmt.Println(fromWKB.AsText()) // POINT(1.5 2.5) -``` +# Alpine +apk add geos-dev -Encoding and decoding WKB for integration with PostGIS: - -```go -db, _ := sql.Open("postgres", "postgres://...") - -db.Exec(` - CREATE TABLE my_table ( - my_geom geometry(geometry, 4326), - population double precision - )`, -) - -// Insert our geometry and population data into PostGIS via WKB. -coords := geom.Coordinates{XY: geom.XY{-74.0, 40.7}} -nyc := geom.NewPoint(coords) -db.Exec(` - INSERT INTO my_table - (my_geom, population) - VALUES (ST_GeomFromWKB($1, 4326), $2)`, - nyc, 8.4e6, -) - -// Get the geometry and population data back out of PostGIS via WKB. -var location geom.Geometry -var population float64 -db.QueryRow(` - SELECT ST_AsBinary(my_geom), population - FROM my_table LIMIT 1`, -).Scan(&location, &population) -fmt.Println(location.AsText(), population) // Prints: POINT(-74 40.7) 8.4e+06 +# macOS +brew install geos ``` -#### GeoJSON +### PROJ -Encoding and decoding GeoJSON directly: - -```go -// Unmarshal geometry from GeoJSON. -raw := `{"type":"Point","coordinates":[-74.0,40.7]}` -var g geom.Geometry -json.NewDecoder(strings.NewReader(raw)).Decode(&g) -fmt.Println(g.AsText()) // Prints: POINT(-74 40.7) - -// Marshal back to GeoJSON. -enc := json.NewEncoder(os.Stdout) -enc.Encode(g) // Prints: {"type":"Point","coordinates":[-74,40.7]} -``` +[Package +`proj`](https://pkg.go.dev/github.com/peterstace/simplefeatures/proj?tab=doc) +is a thin CGO wrapper around the [PROJ](https://proj.org/) library. It provides +an exhaustive set of cartographic projections and coordinate transformations. -Geometries can also be part of larger structs: +To install the PROJ C library: -```go -type CityPopulation struct { - Location geom.Geometry `json:"loc"` - Population int `json:"pop"` -} +```sh +# Debian/Ubuntu +apt-get install libproj-dev -// Unmarshal geometry from GeoJSON. -raw := `{"loc":{"type":"Point","coordinates":[-74.0,40.7]},"pop":8400000}` -var v CityPopulation -json.NewDecoder(strings.NewReader(raw)).Decode(&v) -fmt.Println(v.Location.AsText()) // Prints: POINT(-74 40.7) -fmt.Println(v.Population) // Prints: 8400000 +# Alpine +apk add proj-dev -// Marshal back to GeoJSON. -enc := json.NewEncoder(os.Stdout) -enc.Encode(v) // Prints: {"loc":{"type":"Point","coordinates":[-74,40.7]},"pop":8400000} +# macOS +brew install proj ```