#!/usr/bin/env python
# encoding: utf-8
#title :concave_hull1.py
#description :script accompagnant l'article "Sur la création des enveloppes concaves (concave hull) et les divers moyens d'y parvenir".
#auteur :M.Laloux
#date :20140930
#==============================================================================
from shapely.geometry import shape,mapping MultiLineString
from shapely.ops import polygonize, unary_union
from scipy.spatial import Delaunay
import numpy as np
import fiona
couche = fiona.open("points_test.shp")
points = [pt['geometry']['coordinates'] for pt in couche]
points= np.array(points)
# Delaunay
tri = Delaunay(np.array(points))
# calcul des alpha_shapes
def add_edge(edges, edge_points,i, j):
"""Ajoute une ligne entre le i ème point et le j ème points si elle n'est pas dans la liste"""
if (i, j) in edges or (j, i) in edges:
# déjà dans la liste
return
edges.add( (i, j) )
edge_points.append(points[ [i, j] ])
def calc_alpha2(alpha):
edges = set()
edge_points = []
# loop over triangles:
for ia, ib, ic in tri.vertices:
# extraction des points de Delaunay
pa = points[ia]
pb = points[ib]
pc = points[ic]
# Longueurs des cotés du triangle
a = np.sqrt((pa[0]-pb[0])**2 + (pa[1]-pb[1])**2)
b = np.sqrt((pb[0]-pc[0])**2 + (pb[1]-pc[1])**2)
c = np.sqrt((pc[0]-pa[0])**2 + (pc[1]-pa[1])**2)
# Semiperimètre du triangle
s = (a + b + c)/2.0
# Surface du triangle par la formule de Heron
area = np.sqrt(s*(s-a)*(s-b)*(s-c))
# rayon de filtrage
circum_r = a*b*c/(4.0*area)
if circum_r < alpha:
add_edge(edges,edge_points, ia, ib)
add_edge(edges,edge_points,ib, ic)
add_edge(edges,edge_points,ic, ia)
return edge_points
for alpha in np.arange(30,40):
m = MultiLineString(calc_alpha2(alpha))
triangles = list(polygonize(m))
a = unary_union(triangles)
# sélection de la première géométrie de type Polygon rencontrée
if a.geom_type == "Polygon":
print alpha
schema = {'geometry': 'Polygon','properties': {'test': 'str'}}
with fiona.open('myshp.shp', 'w', 'ESRI Shapefile', schema, crs) as layer:
elem = {}
elem['geometry'] = mapping(a)
elem['properties'] = {'test': '145'}
layer.write(elem)
break
else:
continue