Boolean polygon clipping/overlay operations (union, intersection, difference, xor) on Polygon and MultiPolygon geometry. A Go port of the mfogel/polygon-clipping JS library.
A := [][][][]float64{{{{0.0, 0.0}, {0.0, 6.0}, {6.0, 6.0}, {6.0, 0.0}, {0.0, 0.0}}}}
B := [][][][]float64{{{{5.0, 1.0}, {5.0, 5.0}, {7.0, 5.0}, {7.0, 1.0}, {5.0, 1.0}}}}
C := [][][][]float64{{{{3.0, -2.0}, {3.0, 2.0}, {9.0, 2.0}, {9.0, -2.0}, {3.0, -2.0}}}}
union, _ := polygol.Union(A, B, C)
intersection, _ := polygol.Intersection(A, B, C)
difference, _ := polygol.Difference(A, B, C)
xor, _ := polygol.XOR(A, B, C)
polygol
only has a single type Geom
which represents the coordinate structure of a MultiPolygon:
type Geom [][][][]float64
Each Boolean operation (union, intersection, difference and XOR) takes in one subject Geom
with any number of clipping Geom
's and then returns a single result Geom
:
func polygol.Union(geom polygol.Geom, moreGeoms ...polygol.Geom) (polygol.Geom, error)
Note that particularly large geometries may cause errors that will suggest increasing environment variables POLYGOL_MAX_QUEUE_SIZE and POLYGOL_MAX_SWEEPLINE_SEGMENTS.
The examples page includes some information on how polygol
can interface with Go geometry libraries like paulmach/go.geojson, paulmach/orb and twpayne/go-geom.
At the moment, polygol
aims to have 100% test coverage relative to polygon-clipping; all unit and end-to-end tests have been ported over to Go.
polygol
only has a single dependency: engelsjk/splay-tree. This is a Go port of the JS library w8r/splay-tree which is used in polygon-clipping. BST splay trees are used for the coordinate rounder, the sweep event priority queue and the sweep line itself.
The polygon-clipping library is a well-tested implementation of the Martínez-Rueda-Feito algorithm and is also currently used behind-the-scenes in both TurfJS and the OpenStreetMap iD editor. Naively porting this library from JS to Go is intended to provide a fairly robust polygon clipping capability in Go without the need for GEOS bindings.
Future improvements may include algorithm restructuring and built-in interfaces to common Go geometry libraries.
The Martínez-Rueda-Feito polygon clipping algorithm computes the Boolean operations in O((n+k)*log(n))
time, where n
is the total number of edges of all polygons and k
is the number of intersections between edges.
The algorithm implemented here and in polygon-clipping is based on the following paper:
A new algorithm for computing Boolean operations on polygons by Francisco Martínez, Antonio J. Rueda, Francisco R. Feito (2009)
Additional information can also be found in the follow-up paper:
A simple algorithm for Boolean operations on polygons by Francisco Martínez, Carlos Ogayar, Juan R. Jiménez and Antonio J. Rueda (2013)
Language | URL | Notes |
---|---|---|
C++ | fmartin/bool_op | original implementation |
JavaScript | w8r/martinez | an extension of the original algorithm |
JavaScript | mfogel/polygon-clipping | originally forked from w8r/martinez, notably used here and here |
JavaScript | mapbox/polyclip | by mourner! archived though |
JavaScript | velipso/polybooljs | "based somewhat" on the original |
Go | engelsjk/polygol | this one, a port of mfogel/polygon-clipping |
Go | toanqng/martinez-rueda | based on kudm761/martinez-rueda-php |
Go | akavel/polyclip-go | "known to have bugs" |
Rust | 21re/rust-geo-booleanop | closely follows w8r/martinez |
Python | lycantropos/martinez | port of the original |
Python | lycantropos/clipping | |
PHP | kudm761/martinez-rueda-php | based on the original |
C/ActionScript3 | akavel/martinez-src | copy of the original with an AS3 port |
Scala | JonMcPherson/martinez-polygon-clipper | ported from w8r/martinez |