Skip to content

Commit

Permalink
Scour docs for consistency, grammar, etc. (#416)
Browse files Browse the repository at this point in the history
* review coins.py

* review dimension.py

* review weights.py

* review utils.py

* review distribution.py

* review diversity.py

* review elements.py

* review graph.py

* review shape.py

* review intensity.py

* revise & correct [1]
  • Loading branch information
jGaboardi committed Sep 19, 2022
1 parent 81cdec4 commit f2d998e
Show file tree
Hide file tree
Showing 10 changed files with 1,247 additions and 1,411 deletions.
154 changes: 62 additions & 92 deletions momepy/coins.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
class COINS:

"""
Calculates natural continuity and hierarchy of street networks in given
GeoDataFrame using COINS algorithm.
Calculates natural continuity and hierarchy of street networks in a given
GeoDataFrame using the COINS algorithm.
For details on the algorithms refer to the original paper :cite:`tripathy2020open`.
Expand All @@ -37,17 +37,16 @@ class COINS:
Parameters
----------
edge_gdf : GeoDataFrame
GeoDataFrame containing edge geometry of street network. edge_gdf should
ideally not contain MultiLineStrings.
A GeoDataFrame containing edge geometry of a street network.
``edge_gdf`` should ideally not contain MultiLineStrings.
angle_threshold : int, float (default 0)
the angle threshold for the COINS algorithm.
Segments will only be considered a part of the same street if the
deflection angle is above the threshold.
The angle threshold for the COINS algorithm. Segments will only be considered
a part of the same street if the deflection angle is above the threshold.
Examples
--------
Initialise COINS class. This step will already compute the topology.
Initialise a ``COINS`` class. This step will compute the topology.
>>> coins = momepy.COINS(streets)
Expand All @@ -74,36 +73,34 @@ def __init__(self, edge_gdf, angle_threshold=0):
# split edges into line segments
self._split_lines()

# # create unique_id for each individual line segment
# create unique_id for each individual line segment
self._unique_id()

# # compute edge connectivity table
# compute edge connectivity table
self._get_links()

# # find best link at every point for both lines
# find best link at every point for both lines
self._best_link()

# # cross check best links and enter angle threshold for connectivity
# cross check best links and enter angle threshold for connectivity
self._cross_check_links(angle_threshold)

def _premerge(self):
"""
Returns a GeoDataFrame containing the individual segments with all underlying
Return a GeoDataFrame containing the individual segments with all underlying
information. The result is useful for debugging purposes.
"""
return self._create_gdf_premerge()

def stroke_gdf(self):
"""
Returns a GeoDataFrame containing merged final stroke geometry.
"""
"""Return a GeoDataFrame containing merged final stroke geometry."""
if not self.already_merged:
self._merge_lines()
return self._create_gdf_strokes()

def stroke_attribute(self):
"""
Returns a pandas Series encoding stroke groups onto the original input geometry.
Return a pandas Series encoding stroke groups onto the original input geometry.
"""
if not self.already_merged:
self._merge_lines()
Expand All @@ -130,8 +127,8 @@ def _split_lines(self):
self.uv_index[idx],
]
)
# merge the coordinates as string, this will help in finding adjacent
# edges in the function below
# merge the coordinates as a string, this will help
# in finding adjacent edges in the function below
self.temp_array.append(
[n, f"{part[0][0]}_{part[0][1]}", f"{part[1][0]}_{part[1][1]}"]
)
Expand All @@ -141,7 +138,7 @@ def _split_lines(self):
self.split = out_line

def _unique_id(self):
# Loop through split lines, assign unique ID and
# Loop through split lines, assign unique ID, and
# store inside a list along with the connectivity dictionary
self.unique = dict(enumerate(self.split))

Expand Down Expand Up @@ -182,12 +179,10 @@ def _best_link(self):
p1_angle_set = []
p2_angle_set = []

"""
Instead of computing the angle between the two segments twice, the method
calculates it once and stores in the dictionary for both the keys. So that
it does not calculate the second time because the key is already present in
the dictionary.
"""
# Instead of computing the angle between the two segments twice,
# this method calculates it once and stores in a dictionary for
# both the keys. The key is already present in the dictionary so
# it does not calculate a second time.
for link1 in self.unique[edge][2]:
self.angle_pairs["%d_%d" % (edge, link1)] = _angle_between_two_lines(
self.unique[edge][0], self.unique[link1][0]
Expand All @@ -200,12 +195,10 @@ def _best_link(self):
)
p2_angle_set.append(self.angle_pairs["%d_%d" % (edge, link2)])

"""
Among the adjacent segments deflection angle values, check for the maximum
value at both the ends. The segment with the maximum angle is stored in the
attributes to be cross-checked later for before finalising the segments at
both the ends.
"""
# Among the adjacent segments deflection angle values, check
# for the maximum value at both the ends. The segment with
# the maximum angle is stored in the attributes to be cross-checked
# later before finalising the segments at both the ends.
if len(p1_angle_set) != 0:
val1, idx1 = max((val, idx) for (idx, val) in enumerate(p1_angle_set))
self.unique[edge][4] = self.unique[edge][2][idx1], val1
Expand Down Expand Up @@ -267,7 +260,6 @@ def _merge_lines(self):

# Export geodataframes, 3 options
def _create_gdf_premerge(self):
# create empty list to fill out
my_list = []

for parts in range(0, len(self.unique)):
Expand All @@ -285,7 +277,6 @@ def _create_gdf_premerge(self):
p1_final = self.unique[parts][6]
p2_final = self.unique[parts][7]

# append list
my_list.append(
[
_unique_id,
Expand Down Expand Up @@ -321,10 +312,8 @@ def _create_gdf_premerge(self):

def _create_gdf_strokes(self):

# create empty list to fill
my_list = []

# loop through merged geometry
for a in self.merged:

# get all segment points and make line strings
Expand All @@ -334,14 +323,12 @@ def _create_gdf_strokes(self):
for b in linelist:
list_lines_segments.append(LineString(b))

# merge seperate segments
geom_multi_line = ops.linemerge(MultiLineString(list_lines_segments))

# get other values for gdf
id_value = a
n_segments = len(self.merged[a])

# append list
my_list.append([id_value, n_segments, geom_multi_line])

edge_gdf = gpd.GeoDataFrame(
Expand All @@ -355,29 +342,25 @@ def _create_gdf_strokes(self):

def _add_gdf_stroke_attributes(self):

# Invert self.edge_idx to get a dictionary where the key is the original edge
# index and the value is the group
# Invert self.edge_idx to get a dictionary where the key is
# the original edge index and the value is the group
inv_edges = {
value: key for key in self.edge_idx for value in self.edge_idx[key]
}

# create empty list that will contain attributes of stroke
stroke_group = list()
stroke_group_attributes = list()

for edge in self.uv_index:
stroke_group.append(inv_edges[edge])

return pd.Series(stroke_group, index=self.edge_gdf.index)
stroke_group_attributes.append(inv_edges[edge])


"""
The imported shapefile lines comes as tuple, whereas
the export requires list, this finction converts tuple
inside lines to list
"""
return pd.Series(stroke_group_attributes, index=self.edge_gdf.index)


def _tuple_to_list(line):
"""
The imported shapefile lines comes as tuple, whereas the export requires list,
this function converts tuples inside lines to lists.
"""
for a in range(0, len(line)):
line[a] = list(line[a])
return line
Expand All @@ -389,13 +372,8 @@ def _list_to_tuple(line):
return tuple(line)


"""
The below function takes a line as an input and splits
it at every point.
"""


def _list_to_pairs(in_list):
"""Split a line at every point."""
out_list = []
index = 0
for index in range(0, len(in_list) - 1):
Expand All @@ -404,64 +382,56 @@ def _list_to_pairs(in_list):
return out_list


"""
The function below calculates the angle between two points in space.
"""


def _compute_angle(point1, point2):
"""Calculates the angle between two points in space."""
height = abs(point2[1] - point1[1])
base = abs(point2[0] - point1[0])
angle = round(math.degrees(math.atan(height / base)), 3)
return angle


"""
This function calculates the orientation of a line segment.
Point1 is the lower one on the y-axes and vice-cersa for
Point2.
"""


def _compute_orientation(line):
"""Calculates the orientation of a line segment. Point1 is
the lower one on the y-axes and vice versa for Point2.
"""
point1 = line[1]
point2 = line[0]
"""
If the latutide of a point is less and the longitude is more, or
If the latitude of a point is more and the longitude is less, then
the point is oriented leftward and wil have negative orientation.
"""

# If the latutide of a point is less and the longitude is more, or
# If the latitude of a point is more and the longitude is less, then
# the point is oriented leftward and wil have negative orientation.
if ((point2[0] > point1[0]) and (point2[1] < point1[1])) or (
(point2[0] < point1[0]) and (point2[1] > point1[1])
):
return -_compute_angle(point1, point2)

# if the latitudes are same, the line is horizontal
elif point2[1] == point1[1]:
return 0

# if the longitudes are same, the line is vertical
elif point2[0] == point1[0]:
return 90
return _compute_angle(point1, point2)


"""
This below function calculates the acute joining angle between
two given set of points.
"""
return _compute_angle(point1, point2)


def _points_set_angle(line1, line2):
"""Calculate the acute joining angle between two given set of points."""
l1orien = _compute_orientation(line1)
l2orien = _compute_orientation(line2)

if ((l1orien > 0) and (l2orien < 0)) or ((l1orien < 0) and (l2orien > 0)):
return abs(l1orien) + abs(l2orien)

elif ((l1orien > 0) and (l2orien > 0)) or ((l1orien < 0) and (l2orien < 0)):
theta1 = abs(l1orien) + 180 - abs(l2orien)
theta2 = abs(l2orien) + 180 - abs(l1orien)
if theta1 < theta2:
return theta1
else:
return theta2

elif (l1orien == 0) or (l2orien == 0):
if l1orien < 0:
return 180 - abs(l1orien)
Expand All @@ -471,29 +441,25 @@ def _points_set_angle(line1, line2):
return 180 - (
abs(_compute_orientation(line1)) + abs(_compute_orientation(line2))
)

elif l1orien == l2orien:
return 180


"""
The below function calculates the joining angle between
two line segments.
"""


def _angle_between_two_lines(line1, line2):
"""Calculate the joining angle between two line segments."""
l1p1, l1p2 = line1
l2p1, l2p2 = line2
l1orien = _compute_orientation(line1)
l2orien = _compute_orientation(line2)
"""
If both lines have same orientation, return 180 If one of the lines is zero,
exception for that If both the lines are on same side of the horizontal plane,
calculate 180-(sumOfOrientation) If both the lines are on same side of the vertical
plane, calculate pointSetAngle
"""

# If both lines have same orientation, return 180 If one of the
# lines is zero, exception for that If both the lines are on same side
# of the horizontal plane, calculate 180-(sumOfOrientation) If both the
# lines are on same side of the vertical plane, calculate pointSetAngle.
if l1orien == l2orien:
angle = 180

elif (l1orien == 0) or (l2orien == 0):
angle = _points_set_angle(line1, line2)

Expand All @@ -504,27 +470,31 @@ def _angle_between_two_lines(line1, line2):
angle = 180 - (abs(l1orien) + abs(l2orien))
else:
angle = _points_set_angle([l1p1, l1p2], [l2p1, l2p2])

elif l1p1 == l2p2:
if ((l1p1[1] > l2p1[1]) and (l1p1[1] > l1p2[1])) or (
(l1p1[1] < l2p1[1]) and (l1p1[1] < l1p2[1])
):
angle = 180 - (abs(l1orien) + abs(l2orien))
else:
angle = _points_set_angle([l1p1, l1p2], [l2p2, l2p1])

elif l1p2 == l2p1:
if ((l1p2[1] > l1p1[1]) and (l1p2[1] > l2p2[1])) or (
(l1p2[1] < l1p1[1]) and (l1p2[1] < l2p2[1])
):
angle = 180 - (abs(l1orien) + abs(l2orien))
else:
angle = _points_set_angle([l1p2, l1p1], [l2p1, l2p2])

elif l1p2 == l2p2:
if ((l1p2[1] > l1p1[1]) and (l1p2[1] > l2p1[1])) or (
(l1p2[1] < l1p1[1]) and (l1p2[1] < l2p1[1])
):
angle = 180 - (abs(l1orien) + abs(l2orien))
else:
angle = _points_set_angle([l1p2, l1p1], [l2p2, l2p1])

return angle


Expand Down
Loading

0 comments on commit f2d998e

Please sign in to comment.