ObjectNat 1.3.0__tar.gz → 1.3.2__tar.gz
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.
- {objectnat-1.3.0 → objectnat-1.3.2}/PKG-INFO +3 -3
- {objectnat-1.3.0 → objectnat-1.3.2}/README.rst +2 -2
- {objectnat-1.3.0 → objectnat-1.3.2}/pyproject.toml +1 -1
- objectnat-1.3.2/src/objectnat/_version.py +1 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/noise/noise_simulation.py +1 -1
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/visibility/visibility_analysis.py +79 -56
- objectnat-1.3.0/src/objectnat/_version.py +0 -1
- {objectnat-1.3.0 → objectnat-1.3.2}/LICENSE.txt +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/__init__.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/_api.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/_config.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/__init__.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/coverage_zones/__init__.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/coverage_zones/graph_coverage.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/coverage_zones/radius_voronoi_coverage.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/coverage_zones/stepped_coverage.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/isochrones/__init__.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/isochrones/isochrone_utils.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/isochrones/isochrones.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/noise/__init__.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/noise/noise_init_data.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/noise/noise_reduce.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/noise/noise_simulation_simplified.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/point_clustering/__init__.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/point_clustering/cluster_points_in_polygons.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/provision/__init__.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/provision/provision.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/provision/provision_exceptions.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/provision/provision_model.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/utils/__init__.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/utils/geom_utils.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/utils/graph_utils.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/utils/math_utils.py +0 -0
- {objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/visibility/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: ObjectNat
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: ObjectNat is an open-source library created for geospatial analysis created by IDU team
|
|
5
5
|
License: BSD-3-Clause
|
|
6
6
|
Author: DDonnyy
|
|
@@ -51,9 +51,9 @@ Object-oriented Network Analysis Tools
|
|
|
51
51
|
|
|
52
52
|
|badge-black| |badge-pypi| |badge-ci| |badge-codecov| |badge-license| |badge-docs|
|
|
53
53
|
|
|
54
|
-
`РИДМИ (Russian) <https://github.com/IDUclub/ObjectNat/blob/
|
|
54
|
+
`РИДМИ (Russian) <https://github.com/IDUclub/ObjectNat/blob/master/README_RU.rst>`__
|
|
55
55
|
|
|
56
|
-
.. image:: https://raw.githubusercontent.com/IDUclub/ObjectNat/
|
|
56
|
+
.. image:: https://raw.githubusercontent.com/IDUclub/ObjectNat/master/docs/_static/ONlogo.svg
|
|
57
57
|
:align: center
|
|
58
58
|
:width: 400
|
|
59
59
|
:alt: ObjectNat logo
|
|
@@ -30,9 +30,9 @@ Object-oriented Network Analysis Tools
|
|
|
30
30
|
|
|
31
31
|
|badge-black| |badge-pypi| |badge-ci| |badge-codecov| |badge-license| |badge-docs|
|
|
32
32
|
|
|
33
|
-
`РИДМИ (Russian) <https://github.com/IDUclub/ObjectNat/blob/
|
|
33
|
+
`РИДМИ (Russian) <https://github.com/IDUclub/ObjectNat/blob/master/README_RU.rst>`__
|
|
34
34
|
|
|
35
|
-
.. image:: https://raw.githubusercontent.com/IDUclub/ObjectNat/
|
|
35
|
+
.. image:: https://raw.githubusercontent.com/IDUclub/ObjectNat/master/docs/_static/ONlogo.svg
|
|
36
36
|
:align: center
|
|
37
37
|
:width: 400
|
|
38
38
|
:alt: ObjectNat logo
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "ObjectNat"
|
|
3
|
-
version = "1.3.
|
|
3
|
+
version = "1.3.2"
|
|
4
4
|
description = "ObjectNat is an open-source library created for geospatial analysis created by IDU team"
|
|
5
5
|
license = "BSD-3-Clause"
|
|
6
6
|
authors = ["DDonnyy <63115678+DDonnyy@users.noreply.github.com>"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "1.3.2"
|
|
@@ -145,9 +145,9 @@ def simulate_noise(
|
|
|
145
145
|
source_points = source_points.copy()
|
|
146
146
|
if len(obstacles) > 0:
|
|
147
147
|
obstacles = obstacles.copy()
|
|
148
|
-
obstacles.geometry = obstacles.geometry.simplify(tolerance=1)
|
|
149
148
|
local_crs = obstacles.estimate_utm_crs()
|
|
150
149
|
obstacles.to_crs(local_crs, inplace=True)
|
|
150
|
+
obstacles.geometry = obstacles.geometry.simplify(tolerance=1)
|
|
151
151
|
source_points.to_crs(local_crs, inplace=True)
|
|
152
152
|
else:
|
|
153
153
|
local_crs = source_points.estimate_utm_crs()
|
|
@@ -21,6 +21,44 @@ from objectnat.methods.utils.math_utils import min_max_normalization
|
|
|
21
21
|
logger = config.logger
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
def _ensure_crs(point_from, obstacles):
|
|
25
|
+
if isinstance(point_from, gpd.GeoDataFrame):
|
|
26
|
+
if point_from.empty:
|
|
27
|
+
raise ValueError("GeoDataFrame 'point_from' is empty.")
|
|
28
|
+
return_gdf = True
|
|
29
|
+
original_crs = point_from.crs
|
|
30
|
+
local_crs = point_from.estimate_utm_crs()
|
|
31
|
+
point_from = point_from.to_crs(local_crs)
|
|
32
|
+
if len(point_from) > 1:
|
|
33
|
+
logger.warning(
|
|
34
|
+
"This method processes only a single point. "
|
|
35
|
+
f"The GeoDataFrame contains {len(point_from)} points – "
|
|
36
|
+
"only the first geometry will be used for visibility calculation."
|
|
37
|
+
)
|
|
38
|
+
point_geom = point_from.iloc[0].geometry
|
|
39
|
+
if len(obstacles) > 0:
|
|
40
|
+
obstacles = obstacles.to_crs(local_crs)
|
|
41
|
+
|
|
42
|
+
else:
|
|
43
|
+
return_gdf = False
|
|
44
|
+
|
|
45
|
+
if len(obstacles) > 0:
|
|
46
|
+
original_crs = obstacles.crs
|
|
47
|
+
local_crs = obstacles.estimate_utm_crs()
|
|
48
|
+
obstacles = obstacles.to_crs(local_crs)
|
|
49
|
+
point_geom = gpd.GeoDataFrame(geometry=[point_from], crs=original_crs).to_crs(local_crs).iloc[0].geometry
|
|
50
|
+
else:
|
|
51
|
+
original_crs = 4326
|
|
52
|
+
logger.warning("No information about CRS was found, accepting everything in 4326")
|
|
53
|
+
point_gdf = gpd.GeoDataFrame(geometry=[point_from], crs=original_crs)
|
|
54
|
+
local_crs = point_gdf.estimate_utm_crs()
|
|
55
|
+
|
|
56
|
+
point_gdf = point_gdf.to_crs(local_crs)
|
|
57
|
+
point_geom = point_gdf.geometry.iloc[0]
|
|
58
|
+
|
|
59
|
+
return point_geom, obstacles, original_crs, local_crs, return_gdf
|
|
60
|
+
|
|
61
|
+
|
|
24
62
|
def get_visibility_accurate(
|
|
25
63
|
point_from: Point | gpd.GeoDataFrame, obstacles: gpd.GeoDataFrame, view_distance, return_max_view_dist=False
|
|
26
64
|
) -> Polygon | gpd.GeoDataFrame | tuple[Polygon | gpd.GeoDataFrame, float]:
|
|
@@ -56,31 +94,21 @@ def get_visibility_accurate(
|
|
|
56
94
|
raise e
|
|
57
95
|
return res
|
|
58
96
|
|
|
59
|
-
local_crs =
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if isinstance(point_from, gpd.GeoDataFrame):
|
|
63
|
-
original_crs = point_from.crs
|
|
64
|
-
return_gdf = True
|
|
65
|
-
if len(obstacles) > 0:
|
|
66
|
-
local_crs = obstacles.estimate_utm_crs()
|
|
67
|
-
else:
|
|
68
|
-
local_crs = point_from.estimate_utm_crs()
|
|
69
|
-
obstacles = obstacles.to_crs(local_crs)
|
|
70
|
-
point_from = point_from.to_crs(local_crs)
|
|
71
|
-
if len(point_from) > 1:
|
|
72
|
-
logger.warning(
|
|
73
|
-
f"This method processes only single point. The GeoDataFrame contains {len(point_from)} points - "
|
|
74
|
-
"only the first geometry will be used for isochrone calculation. "
|
|
75
|
-
)
|
|
76
|
-
point_from = point_from.iloc[0].geometry
|
|
77
|
-
else:
|
|
78
|
-
obstacles = obstacles.copy()
|
|
79
|
-
if obstacles.contains(point_from).any():
|
|
97
|
+
point_geom, obstacles, original_crs, local_crs, return_gdf = _ensure_crs(point_from, obstacles)
|
|
98
|
+
|
|
99
|
+
if len(obstacles) > 0 and obstacles.contains(point_geom).any():
|
|
80
100
|
return Polygon()
|
|
101
|
+
|
|
102
|
+
point_buffer = point_geom.buffer(view_distance, resolution=32)
|
|
103
|
+
|
|
104
|
+
if len(obstacles) == 0:
|
|
105
|
+
full_vision_gdf = gpd.GeoDataFrame(geometry=[point_buffer], crs=local_crs).to_crs(original_crs)
|
|
106
|
+
return full_vision_gdf if return_gdf else full_vision_gdf.iloc[0].geometry
|
|
107
|
+
|
|
81
108
|
obstacles.reset_index(inplace=True, drop=True)
|
|
82
|
-
|
|
109
|
+
|
|
83
110
|
allowed_geom_types = ["MultiPolygon", "Polygon", "LineString", "MultiLineString"]
|
|
111
|
+
|
|
84
112
|
obstacles = obstacles[obstacles.geom_type.isin(allowed_geom_types)]
|
|
85
113
|
s = obstacles.intersects(point_buffer)
|
|
86
114
|
obstacles_in_buffer = obstacles.loc[s[s].index].geometry
|
|
@@ -98,26 +126,26 @@ def get_visibility_accurate(
|
|
|
98
126
|
+ [Point(line.coords[-1]) for line in buildings_lines_in_buffer.geometry]
|
|
99
127
|
)
|
|
100
128
|
|
|
101
|
-
max_dist = max(view_distance, buildings_in_buffer_points.distance(
|
|
129
|
+
max_dist = max(view_distance, buildings_in_buffer_points.distance(point_geom).max())
|
|
102
130
|
polygons = []
|
|
103
131
|
buildings_lines_in_buffer = gpd.GeoDataFrame(geometry=buildings_lines_in_buffer, crs=obstacles.crs).reset_index()
|
|
104
132
|
logger.debug("Calculation vis polygon")
|
|
105
133
|
while not buildings_lines_in_buffer.empty:
|
|
106
134
|
gdf_sindex = buildings_lines_in_buffer.sindex
|
|
107
135
|
# TODO check if 2 walls are nearest and use the widest angle between points
|
|
108
|
-
nearest_wall_sind = gdf_sindex.nearest(
|
|
136
|
+
nearest_wall_sind = gdf_sindex.nearest(point_geom, return_all=False, max_distance=max_dist)
|
|
109
137
|
nearest_wall = buildings_lines_in_buffer.loc[nearest_wall_sind[1]].iloc[0]
|
|
110
138
|
wall_points = [Point(coords) for coords in nearest_wall.geometry.coords]
|
|
111
139
|
|
|
112
140
|
# Calculate angles and sort by angle
|
|
113
141
|
points_with_angle = sorted(
|
|
114
|
-
[(pt, math.atan2(pt.y -
|
|
142
|
+
[(pt, math.atan2(pt.y - point_geom.y, pt.x - point_geom.x)) for pt in wall_points], key=lambda x: x[1]
|
|
115
143
|
)
|
|
116
144
|
delta_angle = 2 * math.pi + points_with_angle[0][1] - points_with_angle[-1][1]
|
|
117
145
|
if round(delta_angle, 10) == round(math.pi, 10):
|
|
118
146
|
wall_b_centroid = obstacles_in_buffer.loc[nearest_wall["index"]].centroid
|
|
119
|
-
p1 = get_point_from_a_thorough_b(
|
|
120
|
-
p2 = get_point_from_a_thorough_b(
|
|
147
|
+
p1 = get_point_from_a_thorough_b(point_geom, points_with_angle[0][0], max_dist)
|
|
148
|
+
p2 = get_point_from_a_thorough_b(point_geom, points_with_angle[1][0], max_dist)
|
|
121
149
|
polygon = LineString([p1, p2])
|
|
122
150
|
polygon = polygon.buffer(
|
|
123
151
|
distance=max_dist * point_side_of_line(polygon, wall_b_centroid), single_sided=True
|
|
@@ -126,8 +154,8 @@ def get_visibility_accurate(
|
|
|
126
154
|
if delta_angle > math.pi:
|
|
127
155
|
delta_angle = 2 * math.pi - delta_angle
|
|
128
156
|
a = math.sqrt((max_dist**2) * (1 + (math.tan(delta_angle / 2) ** 2)))
|
|
129
|
-
p1 = get_point_from_a_thorough_b(
|
|
130
|
-
p2 = get_point_from_a_thorough_b(
|
|
157
|
+
p1 = get_point_from_a_thorough_b(point_geom, points_with_angle[0][0], a)
|
|
158
|
+
p2 = get_point_from_a_thorough_b(point_geom, points_with_angle[-1][0], a)
|
|
131
159
|
polygon = Polygon([points_with_angle[0][0], p1, p2, points_with_angle[1][0]])
|
|
132
160
|
|
|
133
161
|
polygons.append(polygon)
|
|
@@ -146,15 +174,16 @@ def get_visibility_accurate(
|
|
|
146
174
|
if isinstance(res, MultiPolygon):
|
|
147
175
|
res = list(res.geoms)
|
|
148
176
|
for polygon in res:
|
|
149
|
-
if polygon.intersects(
|
|
177
|
+
if polygon.intersects(point_geom):
|
|
150
178
|
res = polygon
|
|
151
179
|
break
|
|
152
180
|
|
|
181
|
+
result_gdf = gpd.GeoDataFrame(geometry=[res], crs=local_crs).to_crs(original_crs)
|
|
153
182
|
if return_gdf:
|
|
154
|
-
|
|
155
|
-
|
|
183
|
+
return result_gdf
|
|
184
|
+
res = result_gdf.to_crs(original_crs).iloc[0].geometry
|
|
156
185
|
if return_max_view_dist:
|
|
157
|
-
return res, find_furthest_point(
|
|
186
|
+
return res, find_furthest_point(point_geom, res)
|
|
158
187
|
return res
|
|
159
188
|
|
|
160
189
|
|
|
@@ -184,29 +213,24 @@ def get_visibility(
|
|
|
184
213
|
This function provides a quicker but less accurate result compared to `get_visibility_accurate()`.
|
|
185
214
|
If accuracy is important, consider using `get_visibility_accurate()` instead.
|
|
186
215
|
"""
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
)
|
|
202
|
-
point_from = point_from.iloc[0].geometry
|
|
203
|
-
else:
|
|
204
|
-
obstacles = obstacles.copy()
|
|
205
|
-
point_buffer = point_from.buffer(view_distance, resolution=resolution)
|
|
216
|
+
|
|
217
|
+
obstacles = obstacles.copy()
|
|
218
|
+
|
|
219
|
+
point_geom, obstacles, original_crs, local_crs, return_gdf = _ensure_crs(point_from, obstacles)
|
|
220
|
+
print(return_gdf)
|
|
221
|
+
if len(obstacles) > 0 and obstacles.contains(point_geom).any():
|
|
222
|
+
return Polygon()
|
|
223
|
+
|
|
224
|
+
point_buffer = point_geom.buffer(view_distance, resolution=resolution)
|
|
225
|
+
|
|
226
|
+
if len(obstacles) == 0:
|
|
227
|
+
full_vision_gdf = gpd.GeoDataFrame(geometry=[point_buffer], crs=local_crs).to_crs(original_crs)
|
|
228
|
+
return full_vision_gdf if return_gdf else full_vision_gdf.iloc[0].geometry
|
|
229
|
+
|
|
206
230
|
s = obstacles.intersects(point_buffer)
|
|
207
231
|
buildings_in_buffer = obstacles.loc[s[s].index].reset_index(drop=True)
|
|
208
232
|
buffer_exterior_ = list(point_buffer.exterior.coords)
|
|
209
|
-
line_geometry = [LineString([
|
|
233
|
+
line_geometry = [LineString([point_geom, ext]) for ext in buffer_exterior_]
|
|
210
234
|
buffer_lines_gdf = gpd.GeoDataFrame(geometry=line_geometry)
|
|
211
235
|
united_buildings = buildings_in_buffer.union_all()
|
|
212
236
|
if united_buildings:
|
|
@@ -223,9 +247,8 @@ def get_visibility(
|
|
|
223
247
|
if united_buildings:
|
|
224
248
|
circuit = circuit.difference(united_buildings)
|
|
225
249
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
return circuit
|
|
250
|
+
result_gdf = gpd.GeoDataFrame(geometry=[circuit], crs=local_crs).to_crs(original_crs)
|
|
251
|
+
return result_gdf if return_gdf else result_gdf.iloc[0].geometry
|
|
229
252
|
|
|
230
253
|
|
|
231
254
|
def get_visibilities_from_points(
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = "1.3.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/coverage_zones/radius_voronoi_coverage.py
RENAMED
|
File without changes
|
{objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/coverage_zones/stepped_coverage.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{objectnat-1.3.0 → objectnat-1.3.2}/src/objectnat/methods/noise/noise_simulation_simplified.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|