[FOSS4G Asia 2023] GEOS runs on web browsers - WebAssembly power for geospatial analysis


November 30, 23


2023/11/29(Wed) FOSS4G Asia 2023 Online talk about GEOS-WASM.


Georepublic Japan Developer


埋め込む »CMSなどでJSが使えない場合



GEOS runs on web browsers WebAssembly power for geospatial analysis 2023/11/29(Wed) FOSS4G Asia 2023 Online Talk Ko Nagase @sanak


Self Introduction ● ● ● Georepublic Japan Developer GitHub: @sanak OSGeo: @Sanak ○ ○ ○ ● pgRouting contributor pgRoutingLayer (QGIS Plugin) contributor OSGeoLive Japanese translator, contributor Regular work: ○ ○ Main: Maintaining Redmine base system’s backend side (Ruby/Ruby on Rails/PostGIS) Sub: Maintaining the system’s frontend side (ReactNative/Next.js/TypeScript)


Agenda ● ● ● ● What is GEOS ? What is GEOS-WASM ? GEOS-WASM using library/app Background ○ ○ ● ● ● ● ● 2D geospatial analysis libraries WebAssembly How the project started Characteristics of GEOS-WASM Recent related topics Future possibilities of WebAssembly Acknowledgements


What is GEOS ? ● ● ● ● Website: https://libgeos.org/ C/C++ library for computational geometry Implements OGC Simple Features geometry model and spatial functions Core dependency of PostGIS, QGIS, GDAL, Shapely, etc.


What is GEOS-WASM ? (1/2) ● ● ● ● Website: https://chrispahm.github.io/geo s-wasm/ WebAssembly build of the GEOS library which can be used in the browser and Node.js. Exposes the low-level GEOS C-API to JavaScript without any abstractions. Intended to be used as a building block for higher-level libraries and specific use cases.

What is GEOS-WASM ? (2/2)

npm install geos-wasm


<script type="module">
import initGeosJs from

import initGeosJs from 'geos-wasm'
// initGeosJs returns a promise that resolves to a GEOS object
const geos = await initGeosJs()
// use the GEOS object to call GEOS functions
// Example: get the area of a polygon
// create a WKT reader
const reader = geos.GEOSWKTReader_create()
const wkt = 'POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))'
// read the WKT string into a GEOS geometry -> returns a pointer
const geomPtr = geos.GEOSWKTReader_read(reader, wkt)
// create a pointer where the area will be written to
const areaPtr = geos.Module._malloc(8)
// calculate the area of the geometry
geos.GEOSArea(geomPtr, areaPtr)
// read the area from the pointer into a JS number
const area = geos.Module.getValue(areaPtr, 'double')
console.log(area) // area = 1
// free the WKT reader, the geometry, and the pointer


GEOS-WASM using library/app (1/2) geotoolbox ● ● ● ● ● GitHub: neocarto/geotoolbox Developed by @neocarto. Demo site: https://observablehq.com/@neoca rtocnrs/hello-geotoolbox Various working examples GEOS-WASM has been used in some functions (Buffer, Clip, Densify and Union) since v2.0


GEOS-WASM using library/app (2/2) GEOS WASM Tester ● ● ● ● ● GitHub: sanak/geos-wasm-tester Developed by me Demo site: https://sanak.github.io/geos-wa sm-tester/ Inspired from JTS Test Builder which works on Desktop environment GEOS-WASM is used as git submodule


Background ● ● 2D geospatial analysis libraries WebAssembly


Background - 2D geospatial analysis libraries ● JTS Topology Suite(Java, LGPL=>EPL, 2000~) ○ ○ ● GEOS(C++, LGPL, 2002~) ○ Bindings: Shapely(Python), sf(R), RGeo(Ruby), GeoRust/GEOS(Rust), GeoSwift(Swift), LibGEOS.jl(Julia), node-geos(JavaScript), .etc App/DB: QGIS, PostGIS, SpatiaLite, .etc ○ DB: MySQL(>=5.7) ○ ● ● ● ● Bindings: GEOS(C++), NetTopologySuite(C#), JSTS(JavaScript), dart_jts(Dart) App/Library: OpenJUMP, GeoTools Boost.Geometry(C++, BSL, 2009~) D3.js(JavaScript, BSD, 2011~) Turf.js(JavaScript, MIT, 2013~) GeoRust/Geo(Rust, MIT/Apache, 2015~)


Background - WebAssembly (1/3) Summary: MDN, webassembly.org ● ● ● ● ● Low-level assembly-like language Runs on modern web browsers Near-native performance Compiled from C/C++, Rust, etc. Designed to complement and run alongside JavaScript History: Wiki ● ● ● 2015 Jun: First announced 2017 Nov: Supported on all major browsers 2019 Dec: WebAssembly Core Specification (v1) becomes W3C standard


Background - WebAssembly (2/3) ● FOSS4G 2019: ○ ● FOSS4G 2021: ○ ○ ● WebAssembly - a new technology and its potential for geospatial application by Pirmin Kalberer (YouTube) OSGeo in the browser: Advances in client-side WebAssembly-based Geospatial Analysis and frontend visualization using jsgeoda and Vis.gl by Dylan Halpern (YouTube) Handling GeoTIFFs in client-side code with GDAL and Loam by Derek Dohler (YouTube) FOSS4G 2022: ○ ○ Write once, run anywhere: safe and reusable analytic modules for WebAssembly, Javascript, or more! by Stuart Lynn WebAssembly4G: Where we are, and where we're heading by Michael Schmuki


Background - WebAssembly (3/3) ● Emscripten (C/C++) ○ ○ ○ ○ ● ddohler/gdal-js (GDAL) azavea/loam (GDAL) bugra9/gdal3.js (GDAL, Demo) jvail/spl.js (SpatiaLite, Demo) Rust ○ dabreegster/route_snapper (Demo) ■ Draw routes in MapLibre snapped to a street network using client-side routing ○ :


How the project started (1/6) The project idea itself started from @tmcw’s braindump: https://github.com/tmcw/geos-wasm ● ● ● ● Turf is most comfortable for web development. But for robustness, it needs other stable implementations like JSTS which is port from JTS. Getting the same features/bugs as GEOS is preferable. Raise GEOS/WASM proposal.


How the project started (2/6) @chrispahm found the repository, then created the POC version with GEOS using Emscripten: geos-wasm Is it worth the effort? · Issue #2 · tmcw/geos-wasm ● ● ● Full working “buffer” demo and very detailed documents. Compiling process is based on bugra9/gdal3.js. Serialization performance issue was mentioned.


How the project started (3/6) @kylebarron wrote his blog: Thoughts on GEOS in WebAssembly ● ● ● ● Similarity with Apache Parquet bindings. Details of WebAssembly performance concept. Details of the serialization performance issue. GeoRust possibility for future ○ ○ geoarrow/geoarrow-rs Prototyping GeoRust + GeoArrow in WebAssembly / Kyle Barron | Observable


How the project started (4/6) I found @kylebarron’s blog, and feel excited about the project. ● ● ● Experience of GEOS COM Wrapper for Windows+IE (ActiveX). Demo (require DLL registration) Tried node-geos contribution, but gave up it because Node (v8) C++ API is difficult for me and it only supports Node, and not web browsers. Started contributions to the project from PR #2 and #3.


How the project started (5/6) ● ● ● ● Preferred data transfer between JS and WASM context → shouldn't it be WKB? · Issue #4 · chrispahm/geos-wasm Passing Geometries between JavaScript and GEOS-WASM was slow when using text-based format (WKT (Well-Known-Text) and stringified GeoJSON). Using WKB (Well-Known-Binary) format with @syncpoint/wkx package increases performance. (Later, helper methods were added via PR #19.)


How the project started (6/6) ● ● ● ● API preferences? · Issue #5 · chrispahm/geos-wasm Originally, it was designed with mixing high-level function (like “buffer”) which is compatible with Turf.js. Personally, I wanted to have Shapely like API, but releasing allocated memory seems to be difficult in JavaScript Garbage Collection… From the discussion, now it provides only low-level GEOS C-API functions.


Characteristics of GEOS-WASM ● Unique to compile C/C++ code by Emscripten in bindings of GEOS ○ ○ ○ ○ ○ Unlike other GEOS bindings (Shapely, etc.) which are dynamic links to GEOS C/C++ library. JTS bindings (JSTS, dart_jts, NTS, etc.) port Java code to each language, so GEOS-WASM is a bit similar to those. GEOS patch version up requires full compilation to WebAssembly. License is LGPL 2.1, same as GEOS. Due to full compilation, the npm package size is bigger than Turf.js and similar to JSTS ■ geos-wasm: 2.98 MB ■ jsts: 3.42 MB ■ @turf/turf: 658 kB


Recent related topics ● WebAssembly ○ ○ ● The State of WebAssembly 2023 WebAssembly Garbage Collection (WasmGC) enabled by default in Chrome ■ Related Flutter news: Support for WebAssembly (Wasm) | Flutter WebAssembly in FOSS4G ○ ○ qgis/qgis-js (Demo) ■ QGIS runs on web browsers with Emscripten build SotM EU 2023 workshop: Ungap the Map: designing moonshot cycling networks by Dustin Carlino ● Client side routing with custom cost function (link)


Future possibilities of WebAssembly ● Shade routing with open 3D building data and client side routing ? ○ ○ ● From Rust existing resources (dabreegster/route_snapper) ? Or pgRouting core C/C++ part can be exported as WebAssembly by Emscripten ? More interoperability across languages ○ “Component Model” which is mentioned in FOSS4G 2022 WebAssembly4G: Where we are, and where we're heading slide’s p.20 and p.37 by Michael Schmuki


Acknowledgements ● ● ● GEOS-WASM authors and contributors GEOS community And other all projects and persons in this slide


Thank you! ● ● GitHub: @sanak Email: nagase@georepublic.co.jp