• Stars
    star
    152
  • Rank 236,653 (Top 5 %)
  • Language
    Python
  • License
    MIT License
  • Created almost 8 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Very fast Python line simplification using either the RDP or Visvalingam-Whyatt algorithm implemented in Rust

Build Status Coverage Status DownloadsDOI

Simplification

Simplify a LineString using the Ramer–Douglas–Peucker or Visvalingam-Whyatt algorithms

Line

Installation

pip install simplification
Please use a recent (>= 8.1.2) version of pip.

Supported Python Versions (Linux x86_64 + aarch64, macOS x86_64 + arm64, Windows amd64)

  • Python 3.7
  • Python 3.8
  • Python 3.9
  • Python 3.10
  • Python 3.11

Supported Platforms

  • Linux (manylinux-compatible) x86_64 and aarch64
  • macOS Darwin x86_64 and arm64
  • Windows 64-bit

Usage

from simplification.cutil import (
    simplify_coords,
    simplify_coords_idx,
    simplify_coords_vw,
    simplify_coords_vw_idx,
    simplify_coords_vwp,
)

# Using Ramer–Douglas–Peucker
coords = [
    [0.0, 0.0],
    [5.0, 4.0],
    [11.0, 5.5],
    [17.3, 3.2],
    [27.8, 0.1]
]

# For RDP, Try an epsilon of 1.0 to start with. Other sensible values include 0.01, 0.001
simplified = simplify_coords(coords, 1.0)

# simplified is [[0.0, 0.0], [5.0, 4.0], [11.0, 5.5], [27.8, 0.1]]

# Using Visvalingam-Whyatt
# You can also pass numpy arrays, in which case you'll get numpy arrays back
import numpy as np
coords_vw = np.array([
    [5.0, 2.0],
    [3.0, 8.0],
    [6.0, 20.0],
    [7.0, 25.0],
    [10.0, 10.0]
])
simplified_vw = simplify_coords_vw(coords_vw, 30.0)

# simplified_vw is [[5.0, 2.0], [7.0, 25.0], [10.0, 10.0]]

Passing empty and/or 1-element lists will return them unaltered.

But I only want the simplified Indices

simplification now has:

  • cutil.simplify_coords_idx
  • cutil.simplify_coords_vw_idx

The values returned by these functions are the retained indices. In order to use them as e.g. a masked array in Numpy, something like the following will work:

import numpy as np
from simplification.cutil import simplify_coords_idx

# assume an array of coordinates: orig
simplified = simplify_coords_idx(orig, 1.0)
# build new geometry using only retained coordinates
orig_simplified = orig[simplified]

But I need to ensure that the resulting geometries are valid

You can use the topology-preserving variant of VW for this: simplify_coords_vwp. It's slower, but has a far greater likelihood of producing a valid geometry.

But I Want to Simplify Polylines

No problem; Decode them to LineStrings first.

# pip install pypolyline before you do this
from pypolyline.cutil import decode_polyline
# an iterable of Google-encoded Polylines, so precision is 5. For OSRM &c., it's 6
decoded = (decode_polyline(line, 5) for line in polylines)
simplified = [simplify_coords(line, 1.0) for line in decoded]

How it Works

FFI and a Rust binary

Is It Fast

I should think so.

What does that mean

Using numpy arrays for input and output, the library can be reasonably expected to process around 2500 1000-point LineStrings per second on a Core i7 or equivalent, for a 98%+ reduction in size.
A larger LineString, containing 200k+ points can be reduced to around 3k points (98.5%+) in around 50ms using RDP.

This is based on a test harness available here.

Disclaimer

All benchmarks are subjective, and pathological input will greatly increase processing time. Error-checking is non-existent at this point.

License

MIT

Citing Simplification

If Simplification has been significant in your research, and you would like to acknowledge the project in your academic publication, we suggest citing it as follows (example in APA style, 7th edition):

Hügel, S. (2021). Simplification (Version X.Y.Z) [Computer software]. https://doi.org/10.5281/zenodo.5774852

In Bibtex format:

@software{Hugel_Simplification_2021,
author = {Hügel, Stephan},
doi = {10.5281/zenodo.5774852},
license = {MIT},
month = {12},
title = {{Simplification}},
url = {https://github.com/urschrei/simplification},
version = {X.Y.Z},
year = {2021}
}

More Repositories

1

pyzotero

Pyzotero: a Python client for the Zotero API
Python
749
star
2

Geopython

Notebooks and libraries for spatial/geo Python explorations
Jupyter Notebook
334
star
3

CityEngine-Twitter

Visualise Twitter activity using a procedurally-generated 3D city model
Python
71
star
4

polylabel-rs

A Rust implementation of the Polylabel algorithm, with FFI.
Rust
48
star
5

convertbng

Fast, accurate WGS84 ⬅️➡️ OSGB36 (OSTN15) conversion, using Python and Rust
Python
37
star
6

pypolyline

Fast Google Polyline encoding and decoding using a Rust binary
Python
36
star
7

lonlat_bng

A multithreaded Rust library with FFI for converting WGS84 longitude and latitude coordinates into BNG (OSGB36) Eastings and Northings and vice versa (using OSTN15)
Rust
25
star
8

rdp

A library providing FFI access to fast Ramer–Douglas–Peucker and Visvalingam-Whyatt line simplification algorithms
Rust
20
star
9

router_comparison

Comparative explorations of the Bicycle journey characteristics calculated by the OSRM, Valhalla, and Google Maps routing engines
Python
16
star
10

geojson_example

Minimal examples of GeoJSON parsing using Rust
Rust
14
star
11

lovecraft

A basic NLTK demo, using the collected works of H. P. Lovecraft as a corpus
Jupyter Notebook
13
star
12

polylabel_cmd

A command-line utility for generating optimum polygon label coordinates from GeoJSON
Rust
12
star
13

hexagrams

Procedural generation of I Ching hexagrams and trigrams using PIL and NumPy
Python
10
star
14

linalg

Least-squares estimation (regression analysis) using Python (statsmodels and Pandas)
Jupyter Notebook
7
star
15

rust_anybar

A command-line Anybar client written in Rust
Rust
7
star
16

geojson_d3

Make RFC 7946 GeoJSON (Multi)Polygons d3-geo-compatible, or vice versa
Rust
6
star
17

hexcover

Hexcover: tile an area with regular flat-topped hexagons
Python
6
star
18

cocktails

🍹Branch and bound solution using Rust to calculate an optimal cocktail ingredient list of arbitrary length 🍸
Rust
6
star
19

WIREs

Scientometric Analysis for a literature review article --->
Jupyter Notebook
5
star
20

Circles

Draw geodesic circles exhibiting projection distortion using Basemap
Python
5
star
21

Plowman

A Python script which tweets epic poetry from plain text files
Python
5
star
22

ckmeans

Optimal univariate k-means clustering using dynamic programming
Rust
4
star
23

project-euler

Project Euler solutions
Python
4
star
24

Twitrends

Output top ten trending twitter topics to Growl, based on WOEID
Python
4
star
25

tweetstodb

Example script to log tweets from a set of Twitter users to a Postgres DB
Python
4
star
26

minimal_cross_manylinux

Example of a minimal CI setup using Cross to build a manylinux2010-compatible Rust binary
Rust
4
star
27

hovertube

TfL's rail lines, hovering, ghost-like in the sky above the city 👻
Jupyter Notebook
3
star
28

cleantwitter

Safari 5, Firefox 3, and Google Chrome 5 extensions which remove annoying ‘social’ features such as ‘Who to follow’ and ‘Trending’ topics from twitter.com
JavaScript
3
star
29

CDP

British Museum CDPP
Python
3
star
30

HH-Expunge

A Safari extension that allows users to be selectively ignored
JavaScript
3
star
31

edit_my_tilde

Send pull requests with content for my tilde.club page:
JavaScript
3
star
32

ostn15_phf

A Rust crate providing Ordnance Survey OSTN15 adjustments for ETRS89 coordinates
Rust
3
star
33

greggs

Greggs and Pret Heat Map
JavaScript
2
star
34

rustfest

My Rustfest 2016 slides
2
star
35

tweetmute

Twitter keyword mute regexes
2
star
36

mefignore

A Safari extension for ignoring MetaFilter users
JavaScript
1
star
37

rust_fizzbuzz

Implementing FizzBuzz using Rust 1.0
Rust
1
star
38

irishsecondaryschools

Irish Secondary Schools spatial- and metadata, 2022
1
star
39

urschrei

1
star
40

robust-wasm

WASM port of the robust crate
Rust
1
star
41

polyline-ffi

FFI Bindings for the rust-polyline crate
Rust
1
star
42

patterns

An example showing efficient matching of arbitrary ASCII string patterns in Rust
Rust
1
star