Skip to content

Commit

Permalink
ENH: SharedWalls length
Browse files Browse the repository at this point in the history
  • Loading branch information
martinfleis committed Dec 21, 2020
1 parent 3f768f5 commit 3131ce8
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 24 deletions.
1 change: 1 addition & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ spatial distribution
NeighboringStreetOrientationDeviation
Neighbors
Orientation
SharedWalls
SharedWallsRatio
StreetAlignment

Expand Down
3 changes: 3 additions & 0 deletions docs/bibtex.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"generated/momepy.Rectangularity": [
"dibble2017"
],
"generated/momepy.SharedWalls": [
"hamaina2012a"
],
"generated/momepy.SharedWallsRatio": [
"hamaina2012a"
],
Expand Down
80 changes: 58 additions & 22 deletions momepy/distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
# definitions of spatial distribution characters

import math
import warnings

import networkx as nx
import numpy as np
Expand All @@ -16,6 +15,7 @@

__all__ = [
"Orientation",
"SharedWalls",
"SharedWallsRatio",
"StreetAlignment",
"CellAlignment",
Expand Down Expand Up @@ -106,7 +106,55 @@ def _dist(a, b):
self.series = pd.Series(results_list, index=gdf.index)


class SharedWallsRatio:
class SharedWalls:
"""
Calculate the length of shared walls of adjacent elements (typically buildings)
.. math::
\\textit{length of shared walls}
Note that data needs to be topologically correct. Overlapping polygons will lead to
incorrect results.
Adapted from :cite:`hamaina2012a`.
Parameters
----------
gdf : GeoDataFrame
GeoDataFrame containing gdf to analyse
Attributes
----------
series : Series
Series containing resulting values
gdf : GeoDataFrame
original GeoDataFrame
Examples
--------
>>> buildings_df['swr'] = momepy.SharedWalls(buildings_df).series
See also
--------
SharedWallsRatio
"""

def __init__(self, gdf):
self.gdf = gdf

inp, res = gdf.sindex.query_bulk(gdf.geometry, predicate="intersects")
left = gdf.geometry.take(inp).reset_index(drop=True)
right = gdf.geometry.take(res).reset_index(drop=True)
intersections = left.intersection(right).length
results = intersections.groupby(inp).sum().reset_index(
drop=True
) - gdf.geometry.length.reset_index(drop=True)
results.index = gdf.index

self.series = results


class SharedWallsRatio(SharedWalls):
"""
Calculate shared walls ratio of adjacent elements (typically buildings)
Expand All @@ -122,8 +170,7 @@ class SharedWallsRatio:
----------
gdf : GeoDataFrame
GeoDataFrame containing gdf to analyse
unique_id : (deprecated)
perimeters : str, list, np.array, pd.Series (default None)
perimeters : str, list, np.array, pd.Series (default None, optional)
the name of the dataframe column, ``np.array``, or ``pd.Series`` where is stored perimeter value
Attributes
Expand All @@ -140,15 +187,14 @@ class SharedWallsRatio:
>>> buildings_df['swr'] = momepy.SharedWallsRatio(buildings_df).series
>>> buildings_df['swr'][10]
0.3424804411228673
"""
def __init__(self, gdf, unique_id=None, perimeters=None):
if unique_id is not None:
warnings.warn(
"unique_id is deprecated and will be removed in v0.4.", FutureWarning,
)
See also
--------
SharedWalls
"""

self.gdf = gdf
def __init__(self, gdf, perimeters=None):
super(SharedWallsRatio, self).__init__(gdf)

if perimeters is None:
self.perimeters = gdf.geometry.length
Expand All @@ -157,17 +203,7 @@ def __init__(self, gdf, unique_id=None, perimeters=None):
else:
self.perimeters = perimeters

inp, res = gdf.sindex.query_bulk(gdf.geometry, predicate="intersects")
left = gdf.geometry.take(inp).reset_index(drop=True)
right = gdf.geometry.take(res).reset_index(drop=True)
intersections = left.intersection(right).length
results = (
intersections.groupby(inp).sum().reset_index(drop=True)
- self.perimeters.reset_index(drop=True)
) / self.perimeters.reset_index(drop=True)
results.index = gdf.index

self.series = results
self.series = self.series / self.perimeters


class StreetAlignment:
Expand Down
11 changes: 9 additions & 2 deletions tests/test_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ def test_Orientation(self):
check = 40.7607
assert self.df_streets["orient"][0] == pytest.approx(check)

@pytest.mark.skipif(not GPD_08, reason="requires geopandas > 0.7")
def test_SharedWalls(self):
self.df_buildings["swr"] = mm.SharedWalls(self.df_buildings).series
nonconsecutive = self.df_buildings.drop(2)
result = mm.SharedWalls(nonconsecutive).series
check = 39.395484381507075
assert self.df_buildings["swr"][10] == check
assert result[10] == check

@pytest.mark.skipif(not GPD_08, reason="requires geopandas > 0.7")
def test_SharedWallsRatio(self):
self.df_buildings["swr"] = mm.SharedWallsRatio(self.df_buildings).series
Expand All @@ -44,8 +53,6 @@ def test_SharedWallsRatio(self):
assert self.df_buildings["swr"][10] == check
assert self.df_buildings["swr_array"][10] == check
assert result[10] == check
with pytest.warns(FutureWarning):
mm.SharedWallsRatio(self.df_buildings, "uID")

def test_StreetAlignment(self):
self.df_buildings["orient"] = orient = mm.Orientation(self.df_buildings).series
Expand Down

0 comments on commit 3131ce8

Please sign in to comment.