In [1]:
import numpy as np
import pysal as ps
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
import matplotlib as mpl
import shapely
import time
import sys
from scipy.spatial import Voronoi, voronoi_plot_2d
%matplotlib inline

mpl.rcParams['figure.figsize'] = 25,25  #set the default map size
mpl.rcParams['patch.linewidth'] = 0.5  #set default polygon line width

np.random.seed(352)

# Local path on user's machine
path = '/Users/jgaboardi/Algorithms_etc./Data/'


/Users/jgaboardi/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/matplotlib/font_manager.py:273: UserWarning: Matplotlib is building the font cache using fc-list. This may take a moment.
  warnings.warn('Matplotlib is building the font cache using fc-list. This may take a moment.')

In [2]:
# Waverly  Hills
streets = gpd.read_file(path+'Waverly_Trim/Waverly.shp')
streets.to_crs(epsg=2779, inplace=True) # NAD83(HARN) / Florida North
streets.to_file(path+'waverly/waverly.shp')
shp_waverly = ps.open(path+'waverly/waverly.shp')
b_box = shp_waverly.bbox

In [3]:
intial_buffer = streets.buffer(50)  #Buffer in meters
intial_buffer[:5]


Out[3]:
0    POLYGON ((623124.0407875385 164212.5102460865,...
1    POLYGON ((622546.5762248621 163255.235891574, ...
2    POLYGON ((623559.7869314271 165528.3883790929,...
3    POLYGON ((623200.6855916528 164368.5069398382,...
4    POLYGON ((623558.3641320666 165459.8080567809,...
dtype: object

In [4]:
union_buffer = intial_buffer.unary_union  #Buffer Union
union_buffer = gpd.GeoSeries(union_buffer)
union_buffer.crs = streets.crs
final_buffer = gpd.GeoDataFrame(union_buffer, crs=streets.crs)
final_buffer.columns = ['geometry']

In [5]:
t1_allpoints = time.time()
np.random.seed(352)
x = np.random.uniform(b_box[0], b_box[2], 100)
np.random.seed(850)
y = np.random.uniform(b_box[1], b_box[3], 100)  
coords = zip(x,y)
coords = [shapely.geometry.Point(i) for i in coords]
simulated_hh = gpd.GeoDataFrame(coords)
simulated_hh.crs = streets.crs
simulated_hh.columns = ['geometry']
t2_allpoints = time.time()-t1_allpoints
print t2_allpoints, 'seconds to simulate households in Waverly'


0.00380682945251 seconds to simulate households in Waverly

In [6]:
intersection = [final_buffer['geometry'].intersection(hh) for hh in simulated_hh['geometry']]
intersection = gpd.GeoDataFrame(intersection, crs=streets.crs)
intersection.columns = ['geometry']
intersection[:5]


Out[6]:
geometry
0 ()
1 ()
2 POINT (621913.3153830337 164903.3379650218)
3 POINT (621612.0857702466 164217.1288344094)
4 ()

In [7]:
# Remove shapely.geometry.collection.GeometryCollection
t1_allpoints = time.time()
hh_in = []
for hh in intersection['geometry']:
    if type(hh) == shapely.geometry.point.Point:
        hh_in.append(hh)

In [8]:
households_gdf = gpd.GeoDataFrame(hh_in, crs=streets.crs)
households_gdf.columns = ['geometry']
households_gdf[:5]


Out[8]:
geometry
0 POINT (621913.3153830337 164903.3379650218)
1 POINT (621612.0857702466 164217.1288344094)
2 POINT (621854.4787915241 163374.7302612905)
3 POINT (622860.0605300277 163653.4038665046)
4 POINT (621477.7574525437 164085.8951444005)

In [9]:
household_coords = []
for i,j in households_gdf['geometry'].iteritems():
    household_coords.append([j.x, j.y])

In [10]:
def in_box(households, bounding_box):
    return np.logical_and(np.logical_and(bounding_box[0] >= households[:, 0],
                                         households[:, 0] >= bounding_box[1]),
                          np.logical_and(bounding_box[2] >= households[:, 1],
                                         households[:, 1] >= bounding_box[3]))

In [11]:
def voronoi(households, bounding_box):
    # Select households inside the bounding box
    i = True
    print i
    # Mirror points
    points_center = households[:]
    print points_center
    points_left = np.copy(points_center)
    points_left[:, 0] = bounding_box[0] - (points_left[:, 0] - bounding_box[0])
    points_right = np.copy(points_center)
    points_right[:, 0] = bounding_box[1] + (bounding_box[1] - points_right[:, 0])
    points_down = np.copy(points_center)
    points_down[:, 1] = bounding_box[2] - (points_down[:, 1] - bounding_box[2])
    points_up = np.copy(points_center)
    points_up[:, 1] = bounding_box[3] + (bounding_box[3] - points_up[:, 1])
    points = np.append(points_center,
                       np.append(np.append(points_left,
                                           points_right,
                                           axis=0),
                                 np.append(points_down,
                                           points_up,
                                           axis=0),
                                 axis=0),
                       axis=0)
    
    # Compute Voronoi
    vor = Voronoi(points)
    # Filter regions
    regions = []
    for region in vor.regions:
        flag = True
        for index in region:
            if index == -1:
                flag = False
                break
            else:
                x = vor.vertices[index, 0]
                y = vor.vertices[index, 1]
                if not(bounding_box[0] - eps <= x and x <= bounding_box[1] + eps and
                       bounding_box[2] - eps <= y and y <= bounding_box[3] + eps):
                    flag = False
                    break
        if region != [] and flag:
            regions.append(region)
    vor.filtered_points = points_center
    vor.filtered_regions = regions
    return vor

In [12]:
def centroid_region(vertices):
    # Polygon's signed area
    A = 0
    # Centroid's x
    C_x = 0
    # Centroid's y
    C_y = 0
    for i in range(0, len(vertices) - 1):
        s = (vertices[i, 0] * vertices[i + 1, 1] - vertices[i + 1, 0] * vertices[i, 1])
        A = A + s
        C_x = C_x + (vertices[i, 0] + vertices[i + 1, 0]) * s
        C_y = C_y + (vertices[i, 1] + vertices[i + 1, 1]) * s
    A = 0.5 * A
    C_x = (1.0 / (6.0 * A)) * C_x
    C_y = (1.0 / (6.0 * A)) * C_y
    return np.array([[C_x, C_y]])

In [13]:
#b_box_flip = [162927.08355677937, 621380.1358320742, 166307.62055677705, 623680.8311320741]

In [14]:
eps = sys.float_info.epsilon

households = np.array(household_coords)

bounding_box = b_box # [x_min, x_max, y_min, y_max]

vor = voronoi(households, bounding_box)


True
[[ 621913.31538303  164903.33796502]
 [ 621612.08577025  164217.12883441]
 [ 621854.47879152  163374.73026129]
 [ 622860.06053003  163653.4038665 ]
 [ 621477.75745254  164085.8951444 ]
 [ 622313.02918287  163326.96885212]
 [ 623095.00014426  165332.03277227]
 [ 622617.43158479  163383.37943412]
 [ 621424.52587588  164082.90113953]
 [ 622190.57691827  164269.4846543 ]
 [ 622344.62643726  163727.75853608]
 [ 622496.33129734  164195.07859592]
 [ 622112.84504121  164847.96024011]
 [ 622864.26588002  163860.85489368]
 [ 623432.63319852  165909.1287265 ]
 [ 623034.95409415  165488.06634485]
 [ 621951.55472905  164266.26249991]
 [ 623224.75575692  165205.15741402]
 [ 622799.75403544  164189.19844283]
 [ 623143.2759538   164991.358878  ]
 [ 621834.64364827  164230.17264774]
 [ 623058.41761852  165199.26462735]
 [ 622362.44769929  165435.06686262]
 [ 623583.54190129  165198.63627999]
 [ 623528.52346316  165338.87242054]
 [ 622331.36233504  165213.56124487]
 [ 621752.98852402  164708.67854278]
 [ 622948.72922876  164415.72427487]
 [ 622843.42104375  164856.90319253]
 [ 623328.66033326  164860.63948472]
 [ 622521.21728308  163967.39737577]
 [ 623634.51075671  165996.81791243]
 [ 623041.26339931  164886.93896287]
 [ 622516.08644089  164070.68524682]
 [ 622518.74369431  164096.66457944]
 [ 622101.93693081  164299.9787336 ]
 [ 621976.73317737  165208.64419627]
 [ 621845.59467642  164472.74188271]
 [ 622502.68274706  165161.35048265]
 [ 622615.39838501  163718.87098755]
 [ 623098.07329855  164124.01257753]
 [ 622479.54525202  163725.95690497]
 [ 623127.89506616  164370.3464826 ]
 [ 621589.06804034  163494.31867425]
 [ 622089.97381947  163516.86191917]
 [ 621843.4478542   163424.43405719]
 [ 622802.79860151  164787.16942842]
 [ 621994.26188359  163906.4067645 ]
 [ 621488.18185637  164071.47898892]]

In [15]:
fig = plt.figure()
ax = fig.gca()

# Plot initial points
ax.plot(vor.filtered_points[:, 0], vor.filtered_points[:, 1], 'b.')

# Plot ridges points
for region in vor.filtered_regions:
    vertices = vor.vertices[region, :]
    ax.plot(vertices[:, 0], vertices[:, 1], 'go')

# Plot ridges
for region in vor.filtered_regions:
    vertices = vor.vertices[region + [region[0]], :]
    ax.plot(vertices[:, 0], vertices[:, 1], 'k-')

# Compute and plot centroids
centroids = []
for region in vor.filtered_regions:
    vertices = vor.vertices[region + [region[0]], :]
    centroid = centroid_region(vertices)
    centroids.append(list(centroid[0, :]))
    ax.plot(centroid[:, 0], centroid[:, 1], 'r.')

#ax.set_xlim([-0.1, 10.1])
#ax.set_ylim([-0.1, 10.1])
#plt.savefig("bounded_voronoi.png")

voronoi_plot_2d(vor)
#plt.savefig("voronoi.png")


Out[15]:

In [16]:
# Instantiate and Plot the Voronoi    
t1_voronoi = time.time()
vor = Voronoi(household_coords)
voronoi_plot_2d(vor)
plt.show()
t2_voronoi = time.time()-t1_voronoi
print t2_voronoi, 'seconds to instantiate the Voronoi Tessellation and plot the diagram'
print vor.npoints, 'points'
print len(vor.regions), 'regions'


0.40952706337 seconds to instantiate the Voronoi Tessellation and plot the diagram
49 points
50 regions

In [ ]:
#polylines = [shapely.geometry.LineString(vor.vertices[line])
#         for line in vor.ridge_vertices
#         if -1 not in line]
polylines = [shapely.geometry.LineString(vor.vertices[line])
         for line in vor.ridge_vertices]

In [ ]:
voronoi_all_df = gpd.GeoSeries([p for p in shapely.ops.polygonize(polylines)])
voronoi_all_df = gpd.GeoDataFrame(voronoi_all_df,  crs=streets.crs)
voronoi_all_df.columns = ['geometry']

In [ ]:
voronoi_all_centroids = gpd.GeoDataFrame(voronoi_all_df.centroid, crs=streets.crs)
voronoi_all_centroids.columns = ['geometry']

In [ ]:
bounding_box = gpd.read_file(path+'bounding_box/bounding_box.shp')

In [ ]:
poly_in_bbox = [bounding_box['geometry'].intersection(hh) for hh in voronoi_all_df['geometry']]
voronoi_in_df = gpd.GeoDataFrame(poly_in_bbox,  crs=streets.crs)
voronoi_in_df.columns = ['geometry']

In [ ]:
voronoi_in_centroids = gpd.GeoDataFrame(voronoi_in_df.centroid, crs=streets.crs)
voronoi_in_centroids.columns = ['geometry']

In [ ]:
households_gdf.to_file(path+'households/households.shp')
voronoi_all_centroids.to_file(path+'voronoi/centroids_all.shp')
voronoi_all_df.to_file(path+'voronoi/voronoi_all.shp')
voronoi_in_centroids.to_file(path+'voronoi/centroids_in.shp')
voronoi_in_df.to_file(path+'voronoi/voronoi_in.shp')

In [ ]:


In [ ]: