concave-hull: A very fast 2D concave hull algorithm.
Install: pip install -U concave_hull
Simple usage¶
In [2]:
Copied!
import json
import numpy as np
with open('songjiang.json', encoding='utf8') as f:
feature = json.load(f)
coords = np.array(feature['geometry']['coordinates'][0])
print(f'loadded polygon, #coords: {len(coords)}')
from concave_hull import concave_hull
thresh = 100.0
hull = concave_hull(coords, length_threshold=thresh, is_wgs84=True)
print(f'thresh:{thresh}, #hull: {len(hull)}')
import json
import numpy as np
with open('songjiang.json', encoding='utf8') as f:
feature = json.load(f)
coords = np.array(feature['geometry']['coordinates'][0])
print(f'loadded polygon, #coords: {len(coords)}')
from concave_hull import concave_hull
thresh = 100.0
hull = concave_hull(coords, length_threshold=thresh, is_wgs84=True)
print(f'thresh:{thresh}, #hull: {len(hull)}')
loadded polygon, #coords: 318 thresh:100.0, #hull: 281
Make it interactive¶
In [3]:
Copied!
import ipywidgets as widgets
slider = widgets.IntSlider(100, min=10, max=10000, step=10)
output = widgets.Output()
def handle_slider_change(change):
with output:
thresh = change.new
hull = concave_hull(coords, length_threshold=thresh, is_wgs84=True)
print(f'(thresh:{thresh} -> #hull:{len(hull)})', end='; ')
slider.observe(handle_slider_change, names='value')
print(f'#coords: {len(coords)}')
display(slider, output)
import ipywidgets as widgets
slider = widgets.IntSlider(100, min=10, max=10000, step=10)
output = widgets.Output()
def handle_slider_change(change):
with output:
thresh = change.new
hull = concave_hull(coords, length_threshold=thresh, is_wgs84=True)
print(f'(thresh:{thresh} -> #hull:{len(hull)})', end='; ')
slider.observe(handle_slider_change, names='value')
print(f'#coords: {len(coords)}')
display(slider, output)
#coords: 318
IntSlider(value=100, max=10000, min=10, step=10)
Output()
In [4]:
Copied!
from ipyleaflet import Map, Polygon, basemaps, WidgetControl
def show_map(*, thresh, m=None):
if m is None:
center = [121.2350, 31.0184]
m = Map(
center=center[::-1],
zoom=10,
scroll_wheel_zoom=True,
max_zoom=30,
basemap=basemaps.Gaode.Normal,
)
polygon = Polygon(
locations=[[lla[1], lla[0]] for lla in coords],
color="green",
fill_color="green",
)
# m.add_layer(polygon)
hull = concave_hull(coords, length_threshold=thresh, is_wgs84=True)
hull_polygon = Polygon(
locations=[[lla[1], lla[0]] for lla in hull],
color="red",
fill_color="red",
)
# m.add_layer(hull_polygon)
m.layers = (m.layers[0], hull_polygon)
return m
# show_map(thresh=1000)
from ipyleaflet import Map, Polygon, basemaps, WidgetControl
def show_map(*, thresh, m=None):
if m is None:
center = [121.2350, 31.0184]
m = Map(
center=center[::-1],
zoom=10,
scroll_wheel_zoom=True,
max_zoom=30,
basemap=basemaps.Gaode.Normal,
)
polygon = Polygon(
locations=[[lla[1], lla[0]] for lla in coords],
color="green",
fill_color="green",
)
# m.add_layer(polygon)
hull = concave_hull(coords, length_threshold=thresh, is_wgs84=True)
hull_polygon = Polygon(
locations=[[lla[1], lla[0]] for lla in hull],
color="red",
fill_color="red",
)
# m.add_layer(hull_polygon)
m.layers = (m.layers[0], hull_polygon)
return m
# show_map(thresh=1000)
In [5]:
Copied!
import ipywidgets as widgets
slider = widgets.IntSlider(100, min=10, max=10000, step=10)
output = widgets.Output()
m = show_map(thresh=slider.value)
# display(m)
def handle_slider_change(change):
with output:
output.clear_output()
display(show_map(thresh=change.new, m=m))
slider.observe(handle_slider_change, names='value')
display(slider, output)
import ipywidgets as widgets
slider = widgets.IntSlider(100, min=10, max=10000, step=10)
output = widgets.Output()
m = show_map(thresh=slider.value)
# display(m)
def handle_slider_change(change):
with output:
output.clear_output()
display(show_map(thresh=change.new, m=m))
slider.observe(handle_slider_change, names='value')
display(slider, output)
IntSlider(value=100, max=10000, min=10, step=10)
Output()
In [ ]:
Copied!