GEOS for WebAssembly
v3.15.0WebAssemblyGEOS 3.15.0 for browsers, Node.js and edge runtimes, precompiled for wasm32, single-threaded and multi-threaded as @crossbind/port-geos-wasm.
npm install @crossbind/port-geos-wasm@betaInstall
crossbind itself arrives with your bundler plugin, or with a new project from npm create crossbind@beta; Bundlers has Vite, Webpack, Rspack and Rollup.
Usage
Each example runs here, in this tab, and prints what the site build checked.
Each example also has a JavaScript only tab: the same task with no C++ file, calling GEOS's own headers from @crossbind/port-geos directly. All 5 work that way.
Intersect, unite and subtract two polygons
Overlay is the most used part of GEOS: GEOSIntersection_r, GEOSUnion_r and GEOSDifference_r on shapes read from WKT, with GEOSArea_r to measure the result.
3.15.0-CAPI-1.21.0 POLYGON ((5 5, 5 10, 10 10, 10 5, 5 5)) 25 175 75
The same reentrant calls the C++ makes, on geos_c.h as GEOS ships it. What the wrapper did is now yours: the context, a WKT reader and writer (the shorter GEOSGeomToWKT_r pads every number to 5.0000000000000000), the double * of GEOSArea_r as an 8-byte allocBuffer read with readNumberAt, the char * WKT read with readCString and returned to GEOSFree_r, and every geometry destroyed by hand. GEOS hands its error text only to a callback and a JavaScript function cannot cross into the worker, so a failed call gives only its failure value (null for bad WKT) and no message.
3.15.0-CAPI-1.21.0 POLYGON ((5 5, 5 10, 10 10, 10 5, 5 5)) 25 175 75
Test points against a prepared polygon
Point in polygon is the most common spatial question. GEOSPrepare_r indexes the polygon once; GEOSPreparedContainsXY_r and GEOSPreparedIntersectsXY_r then answer per point and differ only on the boundary, and GEOSPreparedRelate_r gives the full DE-9IM matrix.
2 2: contains true, intersects true 5 5: contains false, intersects false 10 5: contains false, intersects true 12 5: contains false, intersects false 212101212
The prepared geometry and the XY predicates work as they are. Each predicate returns a C char, which arrives as the number 1, 0 or 2 (GEOS failed), so JavaScript turns it into a boolean itself. The DE-9IM matrix is a char * to read with readCString and return to GEOSFree_r, and the prepared geometry is destroyed before the polygon it indexes.
2 2: contains true, intersects true 5 5: contains false, intersects false 10 5: contains false, intersects true 12 5: contains false, intersects false 212101212
Measure area, length and distance
GEOSArea_r, GEOSLength_r and GEOSDistance_r in the units of the coordinates, GEOSNearestPoints_r for where two shapes come closest, and GEOSGetCentroid_r. GEOS works in the plane, so project longitude and latitude before measuring.
1200 140 60 15 LINESTRING (40 30, 52 39) POINT (20 15)
Area, length and distance come back through a double *: one 8-byte allocBuffer serves every call and readNumberAt(out, 0, 'float64') reads it after each. GEOSNearestPoints_r returns a coordinate sequence handle and GEOSGeom_createLineString_r takes ownership of it, so only the line is destroyed.
1200 140 60 15 LINESTRING (40 30, 52 39) POINT (20 15)
Buffer points, lines and polygons
GEOSBuffer_r turns a point into a circle of straight segments, GEOSBufferWithStyle_r sets the caps and joins of a line's corridor, a negative distance shrinks a polygon, and GEOSOffsetCurve_r draws a parallel line.
312.1445 1000 1078.0361 POLYGON ((2 2, 2 18, 18 18, 18 2, 2 2)) 256 LINESTRING (0 5, 100 5)
GEOS declares the cap and join styles as int parameters and names them in the GEOSBufCapStyles and GEOSBufJoinStyles enums, so pass the member's .value: the member itself crosses as 0 without an error, and the flat-capped corridor then comes back as POLYGON EMPTY.
312.1445 1000 1078.0361 POLYGON ((2 2, 2 18, 18 18, 18 2, 2 2)) 256 LINESTRING (0 5, 100 5)
Find why a polygon is invalid and repair it
GEOSisValid_r and GEOSisValidReason_r say whether a shape breaks the OGC rules, what is wrong and where. GEOSMakeValidWithParams_r repairs it two ways, which agree on a bowtie and differ on a hole that leaks out of its shell.
false Self-intersection[5 5] MULTIPOLYGON (((5 5, 10 10, 10 0, 5 5)), ((0 0, 0 10, 5 5, 0 0))) true 50 Self-intersection[5 10] linework 150 structure 75
GEOSMakeValidParams_setMethod_r takes an enum GEOSMakeValidMethods, so pass the member itself: a plain number crosses as 0, GEOS_MAKE_VALID_LINEWORK, and the call still returns 1. GEOSisValid_r returns a C char (1, 0, or 2 when GEOS failed), and the reason is a char * to read with readCString and return to GEOSFree_r.
false Self-intersection[5 5] MULTIPOLYGON (((5 5, 10 10, 10 0, 5 5)), ((0 0, 0 10, 5 5, 0 0))) true 50 Self-intersection[5 10] linework 150 structure 75
What is different on WebAssembly
- In a browser the module runs in a Worker by default (
useWorker), so every call returns a promise:awaitcalls and constructors alike. - The module has its own filesystem:
m.FSwrites files,m.getFileBytesreads them back andm.autoMountFilesmountsFileobjects from an<input type=file>./memfslives in memory;/opfspersists across reloads and needs the Worker. See Filesystem. - In Node.js,
m.FSis the real disk, so use real paths there. - Multi-threaded builds (
runtime: 'mt') need COOP and COEP headers in production. See Threading.
Other platforms
- GEOS overview: the apps, every platform's setup and the packages.
- GEOS for Android: React Native apps on Android.
- GEOS for iOS: React Native apps on iOS.
- GEOS for WASI: command-line programs under wasmtime.
Facts on this page come from the port manifests in the repository and from what npm served on beta when the site was built. See the Libraries guide for the full consumer flow.