mattijn / topojson

Encode spatial data as topology in Python! 🌍 https://mattijn.github.io/topojson
BSD 3-Clause "New" or "Revised" License
179 stars 27 forks source link

Non-topological simplification #84

Closed DanRunfola closed 4 years ago

DanRunfola commented 4 years ago

First and foremost, thank you for the effort you're putting into this package - much appreciated.

I was wondering what the rationale was for precluding the user from using a simplification algorithm that preserves topology - i.e., on this line:

https://github.com/mattijn/topojson/blob/fd271849921651f74e6a5c9f31481a310d334a52/topojson/ops.py#L569

Right now, it's hard-coded to use the DP algorithm (which does not preserve topology), rather than the shapely default (which does preserve topology).

I'm doing a quick pull of this later today to test what happens as well :)

DanRunfola commented 4 years ago

Ok - so, a very (very) brief test I just ran does work - i.e., simply changing preserve_topology=True in topojson/topojson/ops.py doesn't bring everything crashing down. I didn't run any additional tests beyond a quick Egypt case, using a very large toposimplify value (.01) which would have resulted in invalid polygons (with less than 3 points) if preserve_topolgy was set to False:

image

Toposimplify = .1:

image

Code: Full code for replication:

import json
import requests
import topojson
from geojson import Feature, Point, FeatureCollection, Polygon

r = requests.get("https://www.geoboundaries.org/gbRequest.html?ISO=EGY&ADM=ADM1&VER=3_0_0")

#Zipfile URL:
dlPath = r.json()[0]['downloadURL']

#You can swap .zip for .geojson for direct access to the geometry.
#Alternatively, you can skip this, download the *.zip, extract it locally,
#then load in the shape file.
dlPath = dlPath.replace("-all.zip", ".geojson")
geoBoundary = requests.get(dlPath).json()

with open('topoTester.topo', 'w') as outfile:
  topo = topojson.Topology(FeatureCollection(geoBoundary['features']), 
                  prequantize=False,
                  presimplify=False,
                  toposimplify=.1, 
                  simplify_with='shapely', 
                  simplify_algorithm='dp', 
                  winding_order='CW_CCW').to_json()
  json.dump(json.loads(topo), outfile)
mattijn commented 4 years ago

Thanks for the clear described issue. All good points here. This type of parameter setting for simplification should be included.

DanRunfola commented 4 years ago

Did a quick PR: https://github.com/mattijn/topojson/pull/85

mattijn commented 4 years ago

I have introduced this option in #86 using the new introduced parameter prevent_oversimplify. Set to True for the so-called, topology-preserving variant of linestring simplification.