geokit/simplify
Douglas-Peucker line simplification.
Reduces the number of points in a LineString while preserving
its general shape: any point further than tolerance from the
straight line between its neighbours is kept; closer ones are
discarded.
tolerance is a distance in degrees on the lat/lng plane — no
projection is applied. For polylines spanning more than a few
degrees, project to Web Mercator first
(see geokit/mercator) and convert your
tolerance to pixels. For short segments (city-scale and below)
the planar approximation is well within rendering tolerance.
Reference: Douglas, D.; Peucker, T. (1973), “Algorithms for the reduction of the number of points required to represent a digitized line or its caricature”.
Types
Errors returned by line_string.
pub type SimplifyError {
NegativeTolerance(tolerance: Float)
}
Constructors
-
NegativeTolerance(tolerance: Float)tolerancewas negative.
Values
pub fn compute(
geometry geometry: geometry.Geometry,
tolerance tolerance: Float,
) -> Result(geometry.Geometry, SimplifyError)
Simplify any Geometry, matching the
bbox.compute /
centroid.compute call shape.
Pointis returned unchanged.LineStringis simplified vialine_string.Polygonsimplifies each ring; closure is preserved by always keeping the first and last vertex of each ring.MultiPolygonrecurses into each polygon.
import geokit/geometry
import geokit/simplify
let result =
geometry.LineString([a, b, c])
|> simplify.compute(tolerance: 0.001)
pub fn line_string(
points points: List(latlng.LatLng),
tolerance tolerance: Float,
) -> Result(List(latlng.LatLng), SimplifyError)
Simplify a sequence of points using Douglas-Peucker.
tolerance is in degrees. Larger values keep fewer points.
A tolerance of 0.0 is the canonical Douglas-Peucker
behaviour: it drops every intermediate point that lies
exactly on the straight line between its surviving neighbours,
because the comparison perpendicular_distance >. tolerance is
strict. Use a tiny positive value (for example 1.0e-12) if you
want to preserve every point.
import geokit/simplify
import geokit/latlng
let assert Ok(a) = latlng.new(lat: 0.0, lng: 0.0)
let assert Ok(b) = latlng.new(lat: 0.0, lng: 0.5)
let assert Ok(c) = latlng.new(lat: 0.0, lng: 1.0)
let assert Ok(simplified) =
simplify.line_string(points: [a, b, c], tolerance: 0.001)
// simplified == [a, c] (b is on the straight line between a and c)