JSTS: JavaScript Topology Suite
JSTS (JavaScript Topology Suite) is a comprehensive JavaScript library providing spatial predicates and functions for processing geometric data. It strictly adheres to the Simple Features Specification for SQL by the Open Geospatial Consortium (OGC). As a direct port of the well-established Java Topology Suite (JTS), JSTS offers a robust set of tools for geometric operations like buffering, intersection, union, and validity checks. The library is currently stable at version 2.12.1, with an active development cycle evidenced by consistent minor and patch releases. Key differentiators include its fidelity to the JTS API, support for common I/O formats such as WKT and GeoJSON, and integration capabilities with web mapping libraries like OpenLayers. For Node.js environments (version 18+), JSTS is distributed exclusively as ES Modules, moving away from CommonJS.
Common errors
-
TypeError: require is not a function
cause Attempting to use CommonJS `require()` syntax in an ES module context or with JSTS versions that are ESM-only.fixUse ES `import` statements with specific deep paths, e.g., `import GeoJSONReader from 'jsts/org/locationtech/jts/io/GeoJSONReader.js'`. -
TopologyException: Points of linear element are not distinct.
cause Geometric operations failing due to invalid input geometries or floating-point precision issues.fixValidate input geometries (`geometry.isValid()`). If valid, consider reducing precision using `new GeometryPrecisionReducer(precisionModel).reduce(geometry)`. -
TypeError: Cannot read properties of undefined (reading 'buffer')
cause Trying to call a shortcut method (like `buffer`, `intersects`) directly on a `Geometry` object in the ES module build of JSTS, where these methods are not directly attached.fixUse the dedicated operation classes, e.g., `import BufferOp from 'jsts/org/locationtech/jts/operation/buffer/BufferOp.js'; const buffered = new BufferOp(geometry, distance).getResultGeometry();`. -
ReferenceError: jsts is not defined
cause In a browser environment, the `jsts` global object is not available, typically because the UMD build script was not correctly included or executed.fixEnsure the JSTS UMD build (e.g., `jsts.min.js`) is correctly included via a `<script>` tag in your HTML before attempting to access `jsts`.
Warnings
- breaking JSTS is delivered as ES Modules only for Node.js (since version 1.4.0, solidified for Node.js 14+). CommonJS `require()` statements will no longer work and will result in errors.
- gotcha Direct shortcut methods like `.buffer()`, `.intersects()`, or `.union()` are not available on `Geometry` objects in the ES Modules build for Node.js. These methods are monkey-patched only into the bundled ES5 browser version.
- gotcha Due to JavaScript's lack of function overloading, some JTS methods like `GeometryFactory.createMultiPoint` may only accept specific argument types (e.g., `Point[]`) unlike their Java counterparts.
- gotcha Calculations may throw a `TopologyException` (as a JavaScript `Error`) if precision issues arise or input geometries are invalid according to the OGC Simple Features specification.
- breaking JSTS requires Node.js version 18 or higher for execution as specified in its `engines` field. Older Node.js versions may encounter compatibility issues or fail to run.
Install
-
npm install jsts -
yarn add jsts -
pnpm add jsts
Imports
- GeoJSONReader
const GeoJSONReader = require('jsts').io.GeoJSONReader;import GeoJSONReader from 'jsts/org/locationtech/jts/io/GeoJSONReader.js';
- GeometryFactory
const GeometryFactory = require('jsts/org/locationtech/jts/geom/GeometryFactory');import GeometryFactory from 'jsts/org/locationtech/jts/geom/GeometryFactory.js';
- WKTReader
import WKTReader from 'jsts/org/locationtech/jts/io/WKTReader.js';
- Point
import Point from 'jsts/org/locationtech/jts/geom/Point.js';
Quickstart
import GeoJSONReader from 'jsts/org/locationtech/jts/io/GeoJSONReader.js';
import GeoJSONWriter from 'jsts/org/locationtech/jts/io/GeoJSONWriter.js';
import GeometryFactory from 'jsts/org/locationtech/jts/geom/GeometryFactory.js';
import Point from 'jsts/org/locationtech/jts/geom/Point.js';
import BufferOp from 'jsts/org/locationtech/jts/operation/buffer/BufferOp.js';
// 1. Read a GeoJSON string into a JSTS Geometry object
const geoJsonInput = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [10, 20]
},
properties: {
name: 'Example Point'
}
};
const reader = new GeoJSONReader();
const geometry = reader.read(geoJsonInput);
console.log('Original Geometry (JSTS):', geometry.toString());
// Expected: POINT (10 20)
// 2. Perform a spatial operation, e.g., buffer
const distance = 5;
const bufferOp = new BufferOp(geometry, distance);
const bufferedGeometry = bufferOp.getResultGeometry();
console.log('Buffered Geometry (JSTS):', bufferedGeometry.toString());
// Expected: POLYGON ((...))
// 3. Create a new geometry using GeometryFactory
const factory = new GeometryFactory();
// JSTS Coordinate is expected by createPoint
const newPoint = factory.createPoint(new Point.Coordinate(15, 25));
console.log('Newly Created Point (JSTS):', newPoint.toString());
// Expected: POINT (15 25)
// 4. Write a JSTS Geometry object back to GeoJSON
const writer = new GeoJSONWriter();
const bufferedGeoJson = writer.write(bufferedGeometry);
console.log('Buffered Geometry (GeoJSON):', JSON.stringify(bufferedGeoJson, null, 2));
/*
Expected output example for bufferedGeoJson (simplified):
{
"type": "Polygon",
"coordinates": [
[
[5.000..., 20.000...],
...
]
]
}
*/