topologicpy 0.7.90__py3-none-any.whl → 0.7.92__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- topologicpy/Face.py +128 -6
- topologicpy/Graph.py +557 -152
- topologicpy/Plotly.py +43 -22
- topologicpy/Vector.py +58 -42
- topologicpy/version.py +1 -1
- {topologicpy-0.7.90.dist-info → topologicpy-0.7.92.dist-info}/METADATA +1 -1
- {topologicpy-0.7.90.dist-info → topologicpy-0.7.92.dist-info}/RECORD +10 -10
- {topologicpy-0.7.90.dist-info → topologicpy-0.7.92.dist-info}/LICENSE +0 -0
- {topologicpy-0.7.90.dist-info → topologicpy-0.7.92.dist-info}/WHEEL +0 -0
- {topologicpy-0.7.90.dist-info → topologicpy-0.7.92.dist-info}/top_level.txt +0 -0
topologicpy/Face.py
CHANGED
@@ -1690,6 +1690,8 @@ class Face():
|
|
1690
1690
|
"""
|
1691
1691
|
Returns the face representing the isovist projection from the input viewpoint.
|
1692
1692
|
This method assumes all input is in 2D. Z coordinates are ignored.
|
1693
|
+
This method and the metrics are largely derived from isovists.org. Even if not explicitly listed, please assume that all credit
|
1694
|
+
goes to the authors of that website and its associated software.
|
1693
1695
|
|
1694
1696
|
Parameters
|
1695
1697
|
----------
|
@@ -1731,6 +1733,12 @@ class Face():
|
|
1731
1733
|
- d_f : float, Fractal Dimension measures the complexity of the isovist's boundary.
|
1732
1734
|
- e_c : float , Edge Complexity measures how complex the edges of the isovist boundary are.
|
1733
1735
|
- theta : float, Mean Visual Field Angle measures the average angular extent of the visible area from the observation point.
|
1736
|
+
- occlusivity: float, the proportion of edges of an isovist that are not physically defined.
|
1737
|
+
- drift: float, the distance from the observation point to the centroid of its isovist.
|
1738
|
+
- closed_perimeter: float, the total length of non-occluded edges of the isovist.
|
1739
|
+
- average_radial: float, "the mean view length of all space visible from a location." (from isovists.org)
|
1740
|
+
- variance: float, "the mean of the square of deviation between all radial lengths and average radial length of an isovist (Benedikt, 1979)." (from isovists.org)
|
1741
|
+
- skewness: float, "the mean of the cube of deviation between all radial lengths and average radial length of an isovist (Benediky, 1979)." (from isovists.org)
|
1734
1742
|
triangles : bool , optional
|
1735
1743
|
If set to True, the subtended triangles of the isovist are created and stored as contents of the returned isovist face. The default is False.
|
1736
1744
|
mantissa : int , optional
|
@@ -1934,6 +1942,81 @@ class Face():
|
|
1934
1942
|
|
1935
1943
|
return float(distance), Vertex.ByCoordinates(list(closest_point))
|
1936
1944
|
|
1945
|
+
|
1946
|
+
|
1947
|
+
def compute_average_radial_variance_skewness(vertex, edges, mantissa=6):
|
1948
|
+
from math import atan2, pi, sqrt, pow
|
1949
|
+
|
1950
|
+
def subtended_angle(vertex, edge, mantissa=6):
|
1951
|
+
"""Compute the angle subtended by the edge at point V."""
|
1952
|
+
v = Vertex.Coordinates(vertex, mantissa=mantissa)
|
1953
|
+
start = Vertex.Coordinates(Edge.StartVertex(edge), mantissa=mantissa)
|
1954
|
+
end = Vertex.Coordinates(Edge.EndVertex(edge), mantissa=mantissa)
|
1955
|
+
# Calculate the angles of the start and end vertices relative to V
|
1956
|
+
angle_start = atan2(start[1] - v[1], start[0] - v[0])
|
1957
|
+
angle_end = atan2(end[1] - v[1], end[0] - v[0])
|
1958
|
+
# Ensure the angle is in the range [0, 2*pi]
|
1959
|
+
angle_start = angle_start if angle_start >= 0 else angle_start + 2 * pi
|
1960
|
+
angle_end = angle_end if angle_end >= 0 else angle_end + 2 * pi
|
1961
|
+
# Compute the difference and handle wrapping around 2*pi
|
1962
|
+
angle_diff = abs(angle_end - angle_start)
|
1963
|
+
return min(angle_diff, 2 * pi - angle_diff)
|
1964
|
+
|
1965
|
+
total_weighted_distance = 0
|
1966
|
+
total_angle_weight = 0
|
1967
|
+
total_weighted_squared_deviation = 0
|
1968
|
+
total_weighted_cubed_deviation = 0
|
1969
|
+
distances = []
|
1970
|
+
angles = []
|
1971
|
+
for edge in edges:
|
1972
|
+
# Calculate the distance between V and the edge
|
1973
|
+
distance = Vertex.Distance(vertex, edge, mantissa=mantissa)
|
1974
|
+
distances.append(distance)
|
1975
|
+
|
1976
|
+
# Calculate the subtended angle for the edge
|
1977
|
+
angle = subtended_angle(vertex, edge, mantissa=mantissa)
|
1978
|
+
angles.append(angle)
|
1979
|
+
|
1980
|
+
# Weight the distance by the subtended angle
|
1981
|
+
total_weighted_distance += distance * angle
|
1982
|
+
total_angle_weight += angle
|
1983
|
+
|
1984
|
+
# Compute the Average Radial value
|
1985
|
+
if total_angle_weight == 0:
|
1986
|
+
average_radial = 0 # Avoid division by zero
|
1987
|
+
else:
|
1988
|
+
average_radial = round(total_weighted_distance / total_angle_weight, mantissa)
|
1989
|
+
|
1990
|
+
# Compute Variance
|
1991
|
+
for i, edge in enumerate(edges):
|
1992
|
+
# Calculate the distance between V and the edge
|
1993
|
+
distance = distances[i]
|
1994
|
+
# Calculate the subtended angle for the edge
|
1995
|
+
angle = angles[i]
|
1996
|
+
|
1997
|
+
# Calculate the deviation squared from the average radial
|
1998
|
+
deviation_squared = (distance - average_radial) ** 2
|
1999
|
+
# Calculate the deviation cubed from the average radial
|
2000
|
+
deviation_cubed = (distance - average_radial) ** 3
|
2001
|
+
# Weight the squared deviation by the subtended angle
|
2002
|
+
total_weighted_squared_deviation += deviation_squared * angle
|
2003
|
+
total_weighted_cubed_deviation += deviation_cubed * angle
|
2004
|
+
|
2005
|
+
# Compute the Variance value
|
2006
|
+
if total_angle_weight == 0:
|
2007
|
+
variance = 0 # Avoid division by zero
|
2008
|
+
else:
|
2009
|
+
variance = round(sqrt(total_weighted_squared_deviation / total_angle_weight), mantissa)
|
2010
|
+
|
2011
|
+
# Compute the Skewness value
|
2012
|
+
if total_angle_weight == 0:
|
2013
|
+
skewness = 0 # Avoid division by zero
|
2014
|
+
else:
|
2015
|
+
skewness = round(pow(total_weighted_cubed_deviation / total_angle_weight, 1/3), mantissa)
|
2016
|
+
|
2017
|
+
return average_radial, variance, skewness
|
2018
|
+
|
2019
|
+
# Main Code
|
1937
2020
|
origin = Topology.Centroid(face)
|
1938
2021
|
normal = Face.Normal(face)
|
1939
2022
|
flat_face = Topology.Flatten(face, origin=origin, direction=normal)
|
@@ -2022,7 +2105,7 @@ class Face():
|
|
2022
2105
|
return None
|
2023
2106
|
simpler_face = Face.RemoveCollinearEdges(return_face)
|
2024
2107
|
if Topology.IsInstance(simpler_face, "face"):
|
2025
|
-
if transferDictionaries == True:
|
2108
|
+
if transferDictionaries == True or metrics == True:
|
2026
2109
|
j_edges = [Topology.Edges(t) for t in obstacles]
|
2027
2110
|
j_edges = Helper.Flatten(j_edges)
|
2028
2111
|
j_edges += Topology.Edges(face)
|
@@ -2030,19 +2113,24 @@ class Face():
|
|
2030
2113
|
used = [0 for _ in range(len(j_edges))]
|
2031
2114
|
for i, i_edge in enumerate(i_edges):
|
2032
2115
|
d_i = Topology.Dictionary(i_edge)
|
2116
|
+
d_i = Dictionary.SetValueAtKey(d_i, "occlusive", True)
|
2117
|
+
i_edge = Topology.SetDictionary(i_edge, d_i)
|
2033
2118
|
for j, j_edge in enumerate(j_edges):
|
2034
2119
|
if used[j] == 0:
|
2035
2120
|
if Edge.IsCollinear(i_edge, j_edge):
|
2121
|
+
d_i = Dictionary.SetValueAtKey(d_i, "occlusive", False)
|
2122
|
+
i_edge = Topology.SetDictionary(i_edge, d_i)
|
2036
2123
|
d_j = Topology.Dictionary(j_edge)
|
2037
2124
|
d_result = Dictionary.ByMergedDictionaries([d_i, d_j])
|
2038
|
-
|
2125
|
+
if transferDictionaries == True:
|
2126
|
+
i_edge = Topology.SetDictionary(i_edge, d_result)
|
2039
2127
|
used[j] == 1
|
2040
2128
|
|
2041
2129
|
return_face = Topology.Unflatten(simpler_face, origin=origin, direction=normal)
|
2042
|
-
|
2130
|
+
else:
|
2131
|
+
return_face = Topology.Unflatten(return_face, origin=origin, direction=normal)
|
2043
2132
|
if metrics == True:
|
2044
2133
|
vertices = Topology.Vertices(return_face)
|
2045
|
-
edges = Topology.Edges(return_face)
|
2046
2134
|
# 1 Viewpoint
|
2047
2135
|
viewpoint = Vertex.Coordinates(vertex, mantissa=mantissa)
|
2048
2136
|
# 2 Direction
|
@@ -2110,6 +2198,27 @@ class Face():
|
|
2110
2198
|
e_c = round(edge_complexity(coords), mantissa)
|
2111
2199
|
# 18 Mean Visual Field Angle
|
2112
2200
|
theta = round(mean_visual_field_angle(viewpoint, coords), mantissa)
|
2201
|
+
# 19 Occlusivity
|
2202
|
+
occ_length = 0
|
2203
|
+
edges = Topology.Edges(return_face)
|
2204
|
+
for edge in edges:
|
2205
|
+
d = Topology.Dictionary(edge)
|
2206
|
+
if Dictionary.ValueAtKey(d, "occlusive") == True:
|
2207
|
+
occ_length += Edge.Length(edge)
|
2208
|
+
if perimeter > 0:
|
2209
|
+
occlusivity = round(occ_length/perimeter, mantissa)
|
2210
|
+
else:
|
2211
|
+
occlusivity = round(0.0, 6)
|
2212
|
+
|
2213
|
+
# 20 Drift
|
2214
|
+
drift = Vertex.Distance(vertex, Topology.Centroid(return_face), mantissa=mantissa)
|
2215
|
+
|
2216
|
+
# 21 Closed Perimeter
|
2217
|
+
closed_perimeter = round(perimeter - occ_length, mantissa)
|
2218
|
+
|
2219
|
+
# 22/23/24 Average Radial, Variance, and Skewness
|
2220
|
+
average_radial, variance, skewness = compute_average_radial_variance_skewness(vertex, edges, mantissa=6)
|
2221
|
+
|
2113
2222
|
keys = ["viewpoint",
|
2114
2223
|
"direction",
|
2115
2224
|
"fov",
|
@@ -2127,7 +2236,14 @@ class Face():
|
|
2127
2236
|
"symmetry",
|
2128
2237
|
"d_f",
|
2129
2238
|
"e_c",
|
2130
|
-
"theta"
|
2239
|
+
"theta",
|
2240
|
+
"occlusivity",
|
2241
|
+
"drift",
|
2242
|
+
"closed_perimeter",
|
2243
|
+
"average_radial",
|
2244
|
+
"variance",
|
2245
|
+
"skewness"]
|
2246
|
+
|
2131
2247
|
values = [viewpoint,
|
2132
2248
|
direction,
|
2133
2249
|
fov,
|
@@ -2145,7 +2261,13 @@ class Face():
|
|
2145
2261
|
symmetry,
|
2146
2262
|
d_f,
|
2147
2263
|
e_c,
|
2148
|
-
theta
|
2264
|
+
theta,
|
2265
|
+
occlusivity,
|
2266
|
+
drift,
|
2267
|
+
closed_perimeter,
|
2268
|
+
average_radial,
|
2269
|
+
variance,
|
2270
|
+
skewness]
|
2149
2271
|
d = Dictionary.ByKeysValues(keys, values)
|
2150
2272
|
return_face = Topology.SetDictionary(return_face, d)
|
2151
2273
|
if triangles:
|