ObjectNat 1.2.1__py3-none-any.whl → 1.2.2__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.
Potentially problematic release.
This version of ObjectNat might be problematic. Click here for more details.
- objectnat/_api.py +14 -14
- objectnat/_config.py +47 -47
- objectnat/_version.py +1 -1
- objectnat/methods/coverage_zones/__init__.py +3 -3
- objectnat/methods/isochrones/__init__.py +1 -1
- objectnat/methods/isochrones/isochrone_utils.py +167 -167
- objectnat/methods/noise/__init__.py +3 -3
- objectnat/methods/noise/noise_init_data.py +10 -10
- objectnat/methods/noise/noise_reduce.py +155 -155
- objectnat/methods/point_clustering/__init__.py +1 -1
- objectnat/methods/provision/__init__.py +1 -1
- objectnat/methods/provision/provision.py +4 -0
- objectnat/methods/provision/provision_exceptions.py +59 -59
- objectnat/methods/provision/provision_model.py +348 -337
- objectnat/methods/utils/__init__.py +1 -1
- objectnat/methods/utils/geom_utils.py +173 -173
- objectnat/methods/utils/math_utils.py +32 -32
- objectnat/methods/visibility/__init__.py +6 -6
- {objectnat-1.2.1.dist-info → objectnat-1.2.2.dist-info}/METADATA +9 -8
- objectnat-1.2.2.dist-info/RECORD +33 -0
- {objectnat-1.2.1.dist-info → objectnat-1.2.2.dist-info}/WHEEL +1 -1
- objectnat-1.2.1.dist-info/RECORD +0 -33
- {objectnat-1.2.1.dist-info → objectnat-1.2.2.dist-info/licenses}/LICENSE.txt +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
from .graph_utils import gdf_to_graph, graph_to_gdf
|
|
1
|
+
from .graph_utils import gdf_to_graph, graph_to_gdf
|
|
@@ -1,173 +1,173 @@
|
|
|
1
|
-
import math
|
|
2
|
-
|
|
3
|
-
import geopandas as gpd
|
|
4
|
-
from shapely import LineString, MultiPolygon, Point, Polygon
|
|
5
|
-
from shapely.ops import polygonize, unary_union
|
|
6
|
-
|
|
7
|
-
from objectnat import config
|
|
8
|
-
|
|
9
|
-
logger = config.logger
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def polygons_to_multilinestring(geom: Polygon | MultiPolygon):
|
|
13
|
-
# pylint: disable-next=redefined-outer-name,reimported,import-outside-toplevel
|
|
14
|
-
from shapely import LineString, MultiLineString, MultiPolygon
|
|
15
|
-
|
|
16
|
-
def convert_polygon(polygon: Polygon):
|
|
17
|
-
lines = []
|
|
18
|
-
exterior = LineString(polygon.exterior)
|
|
19
|
-
lines.append(exterior)
|
|
20
|
-
interior = [LineString(p) for p in polygon.interiors]
|
|
21
|
-
lines = lines + interior
|
|
22
|
-
return lines
|
|
23
|
-
|
|
24
|
-
def convert_multipolygon(polygon: MultiPolygon):
|
|
25
|
-
return MultiLineString(sum([convert_polygon(p) for p in polygon.geoms], []))
|
|
26
|
-
|
|
27
|
-
if geom.geom_type == "Polygon":
|
|
28
|
-
return MultiLineString(convert_polygon(geom))
|
|
29
|
-
return convert_multipolygon(geom)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def explode_linestring(geometry: LineString) -> list[LineString]:
|
|
33
|
-
"""A function to return all segments of a linestring as a list of linestrings"""
|
|
34
|
-
coords_ext = geometry.coords # Create a list of all line node coordinates
|
|
35
|
-
result = [LineString(part) for part in zip(coords_ext, coords_ext[1:])]
|
|
36
|
-
return result
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def point_side_of_line(line: LineString, point: Point) -> int:
|
|
40
|
-
"""A positive indicates the left-hand side a negative indicates the right-hand side"""
|
|
41
|
-
x1, y1 = line.coords[0]
|
|
42
|
-
x2, y2 = line.coords[-1]
|
|
43
|
-
x, y = point.coords[0]
|
|
44
|
-
cross_product = (x2 - x1) * (y - y1) - (y2 - y1) * (x - x1)
|
|
45
|
-
if cross_product > 0:
|
|
46
|
-
return 1
|
|
47
|
-
return -1
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def get_point_from_a_thorough_b(a: Point, b: Point, dist):
|
|
51
|
-
"""
|
|
52
|
-
Func to get Point from point a thorough point b on dist
|
|
53
|
-
"""
|
|
54
|
-
direction = math.atan2(b.y - a.y, b.x - a.x)
|
|
55
|
-
c_x = a.x + dist * math.cos(direction)
|
|
56
|
-
c_y = a.y + dist * math.sin(direction)
|
|
57
|
-
return Point(c_x, c_y)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def gdf_to_circle_zones_from_point(
|
|
61
|
-
gdf: gpd.GeoDataFrame, point_from: Point, zone_radius, resolution=4, explode_multigeom=True
|
|
62
|
-
) -> gpd.GeoDataFrame:
|
|
63
|
-
"""n_segments = 4*resolution,e.g. if resolution = 4 that means there will be 16 segments"""
|
|
64
|
-
crs = gdf.crs
|
|
65
|
-
buffer = point_from.buffer(zone_radius, resolution=resolution)
|
|
66
|
-
gdf_unary = gdf.clip(buffer, keep_geom_type=True).union_all()
|
|
67
|
-
gdf_geometry = (
|
|
68
|
-
gpd.GeoDataFrame(geometry=[gdf_unary], crs=crs)
|
|
69
|
-
.explode(index_parts=True)
|
|
70
|
-
.geometry.apply(polygons_to_multilinestring)
|
|
71
|
-
.union_all()
|
|
72
|
-
)
|
|
73
|
-
zones_lines = [LineString([Point(coords1), Point(point_from)]) for coords1 in buffer.exterior.coords[:-1]]
|
|
74
|
-
if explode_multigeom:
|
|
75
|
-
return (
|
|
76
|
-
gpd.GeoDataFrame(geometry=list(polygonize(unary_union([gdf_geometry] + zones_lines))), crs=crs)
|
|
77
|
-
.clip(gdf_unary, keep_geom_type=True)
|
|
78
|
-
.explode(index_parts=False)
|
|
79
|
-
)
|
|
80
|
-
return gpd.GeoDataFrame(geometry=list(polygonize(unary_union([gdf_geometry] + zones_lines))), crs=crs).clip(
|
|
81
|
-
gdf_unary, keep_geom_type=True
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def remove_inner_geom(polygon: Polygon | MultiPolygon):
|
|
86
|
-
"""function to get rid of inner polygons"""
|
|
87
|
-
if isinstance(polygon, Polygon):
|
|
88
|
-
return Polygon(polygon.exterior.coords)
|
|
89
|
-
if isinstance(polygon, MultiPolygon):
|
|
90
|
-
polys = []
|
|
91
|
-
for poly in polygon.geoms:
|
|
92
|
-
polys.append(Polygon(poly.exterior.coords))
|
|
93
|
-
return MultiPolygon(polys)
|
|
94
|
-
else:
|
|
95
|
-
return Polygon()
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def combine_geometry(gdf: gpd.GeoDataFrame) -> gpd.GeoDataFrame:
|
|
99
|
-
"""
|
|
100
|
-
Combine geometry of intersecting layers into a single GeoDataFrame.
|
|
101
|
-
Parameters
|
|
102
|
-
----------
|
|
103
|
-
gdf: gpd.GeoDataFrame
|
|
104
|
-
A GeoPandas GeoDataFrame
|
|
105
|
-
|
|
106
|
-
Returns
|
|
107
|
-
-------
|
|
108
|
-
gpd.GeoDataFrame
|
|
109
|
-
The combined GeoDataFrame with aggregated in lists columns.
|
|
110
|
-
|
|
111
|
-
Examples
|
|
112
|
-
--------
|
|
113
|
-
>>> gdf = gpd.read_file('path_to_your_file.geojson')
|
|
114
|
-
>>> result = combine_geometry(gdf)
|
|
115
|
-
"""
|
|
116
|
-
|
|
117
|
-
crs = gdf.crs
|
|
118
|
-
|
|
119
|
-
enclosures = gpd.GeoDataFrame(
|
|
120
|
-
geometry=list(polygonize(gdf["geometry"].apply(polygons_to_multilinestring).union_all())), crs=crs
|
|
121
|
-
)
|
|
122
|
-
enclosures_points = enclosures.copy()
|
|
123
|
-
enclosures_points.geometry = enclosures.representative_point()
|
|
124
|
-
joined = gpd.sjoin(enclosures_points, gdf, how="inner", predicate="within").reset_index()
|
|
125
|
-
cols = joined.columns.tolist()
|
|
126
|
-
cols.remove("geometry")
|
|
127
|
-
joined = joined.groupby("index").agg({column: list for column in cols})
|
|
128
|
-
joined["geometry"] = enclosures
|
|
129
|
-
joined = gpd.GeoDataFrame(joined, geometry="geometry", crs=crs)
|
|
130
|
-
return joined
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
def distribute_points_on_linestrings(lines: gpd.GeoDataFrame, radius, lloyd_relax_n=2) -> gpd.GeoDataFrame:
|
|
134
|
-
lines = lines.copy()
|
|
135
|
-
lines = lines.explode(ignore_index=True)
|
|
136
|
-
lines = lines[lines.geom_type == "LineString"]
|
|
137
|
-
original_crs = lines.crs
|
|
138
|
-
lines = lines.to_crs(crs=lines.estimate_utm_crs())
|
|
139
|
-
lines = lines.reset_index(drop=True)
|
|
140
|
-
lines = lines[["geometry"]]
|
|
141
|
-
radius = radius * 1.1
|
|
142
|
-
segmentized = lines.geometry.apply(lambda x: x.simplify(radius).segmentize(radius))
|
|
143
|
-
points = [Point(pt) for line in segmentized for pt in line.coords]
|
|
144
|
-
|
|
145
|
-
points = gpd.GeoDataFrame(geometry=points, crs=lines.crs)
|
|
146
|
-
lines["lines"] = lines.geometry
|
|
147
|
-
geom_concave = lines.buffer(5, resolution=1).union_all()
|
|
148
|
-
|
|
149
|
-
for i in range(lloyd_relax_n):
|
|
150
|
-
points.geometry = points.voronoi_polygons().clip(geom_concave).centroid
|
|
151
|
-
points = points.sjoin_nearest(lines, how="left")
|
|
152
|
-
points = points[~points.index.duplicated(keep="first")]
|
|
153
|
-
points["geometry"] = points["lines"].interpolate(points["lines"].project(points.geometry))
|
|
154
|
-
points.drop(columns=["lines", "index_right"], inplace=True)
|
|
155
|
-
|
|
156
|
-
return points.dropna().to_crs(original_crs)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
def distribute_points_on_polygons(
|
|
160
|
-
polygons: gpd.GeoDataFrame, radius, only_exterior=True, lloyd_relax_n=2
|
|
161
|
-
) -> gpd.GeoDataFrame:
|
|
162
|
-
polygons = polygons.copy()
|
|
163
|
-
polygons = polygons.explode(ignore_index=True)
|
|
164
|
-
polygons = polygons[polygons.geom_type == "Polygon"]
|
|
165
|
-
|
|
166
|
-
if only_exterior:
|
|
167
|
-
polygons.geometry = polygons.geometry.apply(lambda x: LineString(x.exterior))
|
|
168
|
-
else:
|
|
169
|
-
polygons = gpd.GeoDataFrame(
|
|
170
|
-
geometry=list(polygons.geometry.apply(polygons_to_multilinestring)), crs=polygons.crs
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
return distribute_points_on_linestrings(polygons, radius, lloyd_relax_n=lloyd_relax_n)
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
import geopandas as gpd
|
|
4
|
+
from shapely import LineString, MultiPolygon, Point, Polygon
|
|
5
|
+
from shapely.ops import polygonize, unary_union
|
|
6
|
+
|
|
7
|
+
from objectnat import config
|
|
8
|
+
|
|
9
|
+
logger = config.logger
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def polygons_to_multilinestring(geom: Polygon | MultiPolygon):
|
|
13
|
+
# pylint: disable-next=redefined-outer-name,reimported,import-outside-toplevel
|
|
14
|
+
from shapely import LineString, MultiLineString, MultiPolygon
|
|
15
|
+
|
|
16
|
+
def convert_polygon(polygon: Polygon):
|
|
17
|
+
lines = []
|
|
18
|
+
exterior = LineString(polygon.exterior)
|
|
19
|
+
lines.append(exterior)
|
|
20
|
+
interior = [LineString(p) for p in polygon.interiors]
|
|
21
|
+
lines = lines + interior
|
|
22
|
+
return lines
|
|
23
|
+
|
|
24
|
+
def convert_multipolygon(polygon: MultiPolygon):
|
|
25
|
+
return MultiLineString(sum([convert_polygon(p) for p in polygon.geoms], []))
|
|
26
|
+
|
|
27
|
+
if geom.geom_type == "Polygon":
|
|
28
|
+
return MultiLineString(convert_polygon(geom))
|
|
29
|
+
return convert_multipolygon(geom)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def explode_linestring(geometry: LineString) -> list[LineString]:
|
|
33
|
+
"""A function to return all segments of a linestring as a list of linestrings"""
|
|
34
|
+
coords_ext = geometry.coords # Create a list of all line node coordinates
|
|
35
|
+
result = [LineString(part) for part in zip(coords_ext, coords_ext[1:])]
|
|
36
|
+
return result
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def point_side_of_line(line: LineString, point: Point) -> int:
|
|
40
|
+
"""A positive indicates the left-hand side a negative indicates the right-hand side"""
|
|
41
|
+
x1, y1 = line.coords[0]
|
|
42
|
+
x2, y2 = line.coords[-1]
|
|
43
|
+
x, y = point.coords[0]
|
|
44
|
+
cross_product = (x2 - x1) * (y - y1) - (y2 - y1) * (x - x1)
|
|
45
|
+
if cross_product > 0:
|
|
46
|
+
return 1
|
|
47
|
+
return -1
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_point_from_a_thorough_b(a: Point, b: Point, dist):
|
|
51
|
+
"""
|
|
52
|
+
Func to get Point from point a thorough point b on dist
|
|
53
|
+
"""
|
|
54
|
+
direction = math.atan2(b.y - a.y, b.x - a.x)
|
|
55
|
+
c_x = a.x + dist * math.cos(direction)
|
|
56
|
+
c_y = a.y + dist * math.sin(direction)
|
|
57
|
+
return Point(c_x, c_y)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def gdf_to_circle_zones_from_point(
|
|
61
|
+
gdf: gpd.GeoDataFrame, point_from: Point, zone_radius, resolution=4, explode_multigeom=True
|
|
62
|
+
) -> gpd.GeoDataFrame:
|
|
63
|
+
"""n_segments = 4*resolution,e.g. if resolution = 4 that means there will be 16 segments"""
|
|
64
|
+
crs = gdf.crs
|
|
65
|
+
buffer = point_from.buffer(zone_radius, resolution=resolution)
|
|
66
|
+
gdf_unary = gdf.clip(buffer, keep_geom_type=True).union_all()
|
|
67
|
+
gdf_geometry = (
|
|
68
|
+
gpd.GeoDataFrame(geometry=[gdf_unary], crs=crs)
|
|
69
|
+
.explode(index_parts=True)
|
|
70
|
+
.geometry.apply(polygons_to_multilinestring)
|
|
71
|
+
.union_all()
|
|
72
|
+
)
|
|
73
|
+
zones_lines = [LineString([Point(coords1), Point(point_from)]) for coords1 in buffer.exterior.coords[:-1]]
|
|
74
|
+
if explode_multigeom:
|
|
75
|
+
return (
|
|
76
|
+
gpd.GeoDataFrame(geometry=list(polygonize(unary_union([gdf_geometry] + zones_lines))), crs=crs)
|
|
77
|
+
.clip(gdf_unary, keep_geom_type=True)
|
|
78
|
+
.explode(index_parts=False)
|
|
79
|
+
)
|
|
80
|
+
return gpd.GeoDataFrame(geometry=list(polygonize(unary_union([gdf_geometry] + zones_lines))), crs=crs).clip(
|
|
81
|
+
gdf_unary, keep_geom_type=True
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def remove_inner_geom(polygon: Polygon | MultiPolygon):
|
|
86
|
+
"""function to get rid of inner polygons"""
|
|
87
|
+
if isinstance(polygon, Polygon):
|
|
88
|
+
return Polygon(polygon.exterior.coords)
|
|
89
|
+
if isinstance(polygon, MultiPolygon):
|
|
90
|
+
polys = []
|
|
91
|
+
for poly in polygon.geoms:
|
|
92
|
+
polys.append(Polygon(poly.exterior.coords))
|
|
93
|
+
return MultiPolygon(polys)
|
|
94
|
+
else:
|
|
95
|
+
return Polygon()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def combine_geometry(gdf: gpd.GeoDataFrame) -> gpd.GeoDataFrame:
|
|
99
|
+
"""
|
|
100
|
+
Combine geometry of intersecting layers into a single GeoDataFrame.
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
gdf: gpd.GeoDataFrame
|
|
104
|
+
A GeoPandas GeoDataFrame
|
|
105
|
+
|
|
106
|
+
Returns
|
|
107
|
+
-------
|
|
108
|
+
gpd.GeoDataFrame
|
|
109
|
+
The combined GeoDataFrame with aggregated in lists columns.
|
|
110
|
+
|
|
111
|
+
Examples
|
|
112
|
+
--------
|
|
113
|
+
>>> gdf = gpd.read_file('path_to_your_file.geojson')
|
|
114
|
+
>>> result = combine_geometry(gdf)
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
crs = gdf.crs
|
|
118
|
+
|
|
119
|
+
enclosures = gpd.GeoDataFrame(
|
|
120
|
+
geometry=list(polygonize(gdf["geometry"].apply(polygons_to_multilinestring).union_all())), crs=crs
|
|
121
|
+
)
|
|
122
|
+
enclosures_points = enclosures.copy()
|
|
123
|
+
enclosures_points.geometry = enclosures.representative_point()
|
|
124
|
+
joined = gpd.sjoin(enclosures_points, gdf, how="inner", predicate="within").reset_index()
|
|
125
|
+
cols = joined.columns.tolist()
|
|
126
|
+
cols.remove("geometry")
|
|
127
|
+
joined = joined.groupby("index").agg({column: list for column in cols})
|
|
128
|
+
joined["geometry"] = enclosures
|
|
129
|
+
joined = gpd.GeoDataFrame(joined, geometry="geometry", crs=crs)
|
|
130
|
+
return joined
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def distribute_points_on_linestrings(lines: gpd.GeoDataFrame, radius, lloyd_relax_n=2) -> gpd.GeoDataFrame:
|
|
134
|
+
lines = lines.copy()
|
|
135
|
+
lines = lines.explode(ignore_index=True)
|
|
136
|
+
lines = lines[lines.geom_type == "LineString"]
|
|
137
|
+
original_crs = lines.crs
|
|
138
|
+
lines = lines.to_crs(crs=lines.estimate_utm_crs())
|
|
139
|
+
lines = lines.reset_index(drop=True)
|
|
140
|
+
lines = lines[["geometry"]]
|
|
141
|
+
radius = radius * 1.1
|
|
142
|
+
segmentized = lines.geometry.apply(lambda x: x.simplify(radius).segmentize(radius))
|
|
143
|
+
points = [Point(pt) for line in segmentized for pt in line.coords]
|
|
144
|
+
|
|
145
|
+
points = gpd.GeoDataFrame(geometry=points, crs=lines.crs)
|
|
146
|
+
lines["lines"] = lines.geometry
|
|
147
|
+
geom_concave = lines.buffer(5, resolution=1).union_all()
|
|
148
|
+
|
|
149
|
+
for i in range(lloyd_relax_n):
|
|
150
|
+
points.geometry = points.voronoi_polygons().clip(geom_concave).centroid
|
|
151
|
+
points = points.sjoin_nearest(lines, how="left")
|
|
152
|
+
points = points[~points.index.duplicated(keep="first")]
|
|
153
|
+
points["geometry"] = points["lines"].interpolate(points["lines"].project(points.geometry))
|
|
154
|
+
points.drop(columns=["lines", "index_right"], inplace=True)
|
|
155
|
+
|
|
156
|
+
return points.dropna().to_crs(original_crs)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def distribute_points_on_polygons(
|
|
160
|
+
polygons: gpd.GeoDataFrame, radius, only_exterior=True, lloyd_relax_n=2
|
|
161
|
+
) -> gpd.GeoDataFrame:
|
|
162
|
+
polygons = polygons.copy()
|
|
163
|
+
polygons = polygons.explode(ignore_index=True)
|
|
164
|
+
polygons = polygons[polygons.geom_type == "Polygon"]
|
|
165
|
+
|
|
166
|
+
if only_exterior:
|
|
167
|
+
polygons.geometry = polygons.geometry.apply(lambda x: LineString(x.exterior))
|
|
168
|
+
else:
|
|
169
|
+
polygons = gpd.GeoDataFrame(
|
|
170
|
+
geometry=list(polygons.geometry.apply(polygons_to_multilinestring)), crs=polygons.crs
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
return distribute_points_on_linestrings(polygons, radius, lloyd_relax_n=lloyd_relax_n)
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def min_max_normalization(data, new_min=0, new_max=1):
|
|
5
|
-
"""
|
|
6
|
-
Min-max normalization for a given array of data.
|
|
7
|
-
|
|
8
|
-
Parameters
|
|
9
|
-
----------
|
|
10
|
-
data: numpy.ndarray
|
|
11
|
-
Input data to be normalized.
|
|
12
|
-
new_min: float, optional
|
|
13
|
-
New minimum value for normalization. Defaults to 0.
|
|
14
|
-
new_max: float, optional
|
|
15
|
-
New maximum value for normalization. Defaults to 1.
|
|
16
|
-
|
|
17
|
-
Returns
|
|
18
|
-
-------
|
|
19
|
-
numpy.ndarray
|
|
20
|
-
Normalized data.
|
|
21
|
-
|
|
22
|
-
Examples
|
|
23
|
-
--------
|
|
24
|
-
>>> import numpy as np
|
|
25
|
-
>>> data = np.array([1, 2, 3, 4, 5])
|
|
26
|
-
>>> normalized_data = min_max_normalization(data, new_min=0, new_max=1)
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
min_value = np.min(data)
|
|
30
|
-
max_value = np.max(data)
|
|
31
|
-
normalized_data = (data - min_value) / (max_value - min_value) * (new_max - new_min) + new_min
|
|
32
|
-
return normalized_data
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def min_max_normalization(data, new_min=0, new_max=1):
|
|
5
|
+
"""
|
|
6
|
+
Min-max normalization for a given array of data.
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
data: numpy.ndarray
|
|
11
|
+
Input data to be normalized.
|
|
12
|
+
new_min: float, optional
|
|
13
|
+
New minimum value for normalization. Defaults to 0.
|
|
14
|
+
new_max: float, optional
|
|
15
|
+
New maximum value for normalization. Defaults to 1.
|
|
16
|
+
|
|
17
|
+
Returns
|
|
18
|
+
-------
|
|
19
|
+
numpy.ndarray
|
|
20
|
+
Normalized data.
|
|
21
|
+
|
|
22
|
+
Examples
|
|
23
|
+
--------
|
|
24
|
+
>>> import numpy as np
|
|
25
|
+
>>> data = np.array([1, 2, 3, 4, 5])
|
|
26
|
+
>>> normalized_data = min_max_normalization(data, new_min=0, new_max=1)
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
min_value = np.min(data)
|
|
30
|
+
max_value = np.max(data)
|
|
31
|
+
normalized_data = (data - min_value) / (max_value - min_value) * (new_max - new_min) + new_min
|
|
32
|
+
return normalized_data
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
from .visibility_analysis import (
|
|
2
|
-
calculate_visibility_catchment_area,
|
|
3
|
-
get_visibilities_from_points,
|
|
4
|
-
get_visibility,
|
|
5
|
-
get_visibility_accurate,
|
|
6
|
-
)
|
|
1
|
+
from .visibility_analysis import (
|
|
2
|
+
calculate_visibility_catchment_area,
|
|
3
|
+
get_visibilities_from_points,
|
|
4
|
+
get_visibility,
|
|
5
|
+
get_visibility_accurate,
|
|
6
|
+
)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: ObjectNat
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.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
|
+
License-File: LICENSE.txt
|
|
6
7
|
Author: DDonnyy
|
|
7
8
|
Author-email: 63115678+DDonnyy@users.noreply.github.com
|
|
8
9
|
Requires-Python: >=3.10,<3.13
|
|
@@ -44,28 +45,28 @@ Each feature is accompanied by a Jupyter notebook example and full documentation
|
|
|
44
45
|
|
|
45
46
|
1. **[Isochrones and Transport Accessibility](./examples/isochrone_generator.ipynb)**
|
|
46
47
|
Analyze areas reachable within a given time along a transport network.
|
|
47
|
-
📄 [See documentation](https://
|
|
48
|
+
📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/isochrones.html)
|
|
48
49
|
|
|
49
50
|
2. **[Coverage Zones](./examples/coverage_zones.ipynb)**
|
|
50
51
|
Build zones of reachability for each point using routing or simple radius.
|
|
51
|
-
📄 [See documentation](https://
|
|
52
|
+
📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/coverage.html)
|
|
52
53
|
|
|
53
54
|
3. **[Service Provision Analysis](./examples/calculate_provision.ipynb)**
|
|
54
55
|
Evaluate service availability and model demand-supply balance.
|
|
55
|
-
📄 [See documentation](https://
|
|
56
|
+
📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/provision.html)
|
|
56
57
|
|
|
57
58
|
4. **[Visibility Analysis](./examples/visibility_analysis.ipynb)**
|
|
58
59
|
Estimate visibility to nearby buildings from selected points.
|
|
59
|
-
📄 [See documentation](https://
|
|
60
|
+
📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/visibility.html)
|
|
60
61
|
|
|
61
62
|
5. **[Noise Simulation](./examples/noise_simulation.ipynb)**
|
|
62
63
|
Simulate noise propagation considering obstacles and environment.
|
|
63
|
-
📄 [See documentation](https://
|
|
64
|
+
📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/noise.html)
|
|
64
65
|
🔗 [Detailed theory in the Wiki](https://github.com/DDonnyy/ObjectNat/wiki/Noise-simulation)
|
|
65
66
|
|
|
66
67
|
6. **[Point Clusterization](./examples/point_clusterization.ipynb)**
|
|
67
68
|
Group nearby points into clusters and analyze service composition.
|
|
68
|
-
📄 [See documentation](https://
|
|
69
|
+
📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/clustering.html)
|
|
69
70
|
|
|
70
71
|
---
|
|
71
72
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
objectnat/__init__.py,sha256=VZ0TaIuB73EOl5Tin4Cs6-TCEOgBImCNYozwHD3bI_g,248
|
|
2
|
+
objectnat/_api.py,sha256=0R1nypAQUcbQ9YSLw_MUgUWoNl8c1zMZteV8wGzdkvc,711
|
|
3
|
+
objectnat/_config.py,sha256=fGPsMZqA8FVBBOINxRiTFkOOZsNLyablM5G0tdKeQB4,1306
|
|
4
|
+
objectnat/_version.py,sha256=rTrUbw2CeioGu2bqQWB_ZsbWrK8mfBzgGdEKgPrvi_M,19
|
|
5
|
+
objectnat/methods/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
objectnat/methods/coverage_zones/__init__.py,sha256=3uTDC1xf3zgQRqSQR4URp__HjZ8eVUtjK8r3mGq-zuQ,161
|
|
7
|
+
objectnat/methods/coverage_zones/graph_coverage.py,sha256=e4seTrhOTqEZ8DhE9xiH_fe-TwPNZXH3ujEq87CuEA0,4190
|
|
8
|
+
objectnat/methods/coverage_zones/radius_voronoi_coverage.py,sha256=A-O6WhgpJTizIHGiJ9JuP882iHbNejh0EW10H493kDM,1631
|
|
9
|
+
objectnat/methods/coverage_zones/stepped_coverage.py,sha256=e-zNE0JP4Q1Crb-JEbIZc0dYFzZXle2LjTxJPGS-7XE,5659
|
|
10
|
+
objectnat/methods/isochrones/__init__.py,sha256=bDfUZPbS3_PuTEB2QcRTYjvyJtUvjbDhAw6QJvD_ih4,90
|
|
11
|
+
objectnat/methods/isochrones/isochrone_utils.py,sha256=dJwvoGXUypwU2_oF-rdxNZm90gOi-RUp_0WM1C2HaPU,6870
|
|
12
|
+
objectnat/methods/isochrones/isochrones.py,sha256=VgpwubX7VEFStXyXM0B58cpFoCn3AboVekIU8GtXWls,11573
|
|
13
|
+
objectnat/methods/noise/__init__.py,sha256=-zWdeD3sUr4HO8yEHiQuQm_FXviqZONffkthJ5v9VtA,186
|
|
14
|
+
objectnat/methods/noise/noise_init_data.py,sha256=Vp-R_yH7CgYqZEtbGAdr1iiIbgauReniLQ_a2TcszhY,503
|
|
15
|
+
objectnat/methods/noise/noise_reduce.py,sha256=B85ifAN_mHiBKJso-cZiSkj7588w2sA-ugGvEal4CBw,6885
|
|
16
|
+
objectnat/methods/noise/noise_simulation.py,sha256=-2pTzV-nShJfhgPg4AejKlMSvlTlnQDBCngLPZhFX8w,22389
|
|
17
|
+
objectnat/methods/noise/noise_simulation_simplified.py,sha256=igj4hI3rPDdKYgabq0aH0Evhy2jg-uTstLSqFjx2VSw,11094
|
|
18
|
+
objectnat/methods/point_clustering/__init__.py,sha256=pX2qDUCvs9LJI36mr65vbdRml6AE8hIYYxIJLdQZQxs,61
|
|
19
|
+
objectnat/methods/point_clustering/cluster_points_in_polygons.py,sha256=reY5ekJrAJUdWwVMvvZBp5T34H4K2V4mt3rQuyoUYPQ,5193
|
|
20
|
+
objectnat/methods/provision/__init__.py,sha256=0Uy66n2xH0Y45JyhIYHEVfC2rig6bMYp6PV2KkNhbK8,80
|
|
21
|
+
objectnat/methods/provision/provision.py,sha256=xf3y5ZfGD1rGSCqvUd2JFSEzcPe7Af_bIyA38pBTtrU,5157
|
|
22
|
+
objectnat/methods/provision/provision_exceptions.py,sha256=lznEmlmZDzGIOtapZVqZDMutIi5eGbFuVCYeVa7VZWk,1687
|
|
23
|
+
objectnat/methods/provision/provision_model.py,sha256=edzXSnGwTjc5kw4k6ZbO886uHp6xIyqSNdJ9YuZTdmE,14998
|
|
24
|
+
objectnat/methods/utils/__init__.py,sha256=sGXy4KUOe5I0UYztnB4rIl2HNd-oqnqRYrBsiU-dpNY,52
|
|
25
|
+
objectnat/methods/utils/geom_utils.py,sha256=PdUjQDZ8drJ1ZFCFabDJnD6oFvgHeAQrsbeivuDOdcI,6385
|
|
26
|
+
objectnat/methods/utils/graph_utils.py,sha256=aOtFZbuPAiGhkglMJBi9xcsb8XBbVFW7535DrhjWx1w,12667
|
|
27
|
+
objectnat/methods/utils/math_utils.py,sha256=Vc8U15LtFOwgIt1YSOSKWYOIiW_1XLuMGOa6ejBpEUk,839
|
|
28
|
+
objectnat/methods/visibility/__init__.py,sha256=Mx1kaoV-yfQUxlMkgNF4AhjSweFEJMEx3NBis5OM3mA,161
|
|
29
|
+
objectnat/methods/visibility/visibility_analysis.py,sha256=nXcDQ9zewpM4FFSXuYophUNsh6wiHSIHjM88vV6Iv_U,20843
|
|
30
|
+
objectnat-1.2.2.dist-info/licenses/LICENSE.txt,sha256=gI3AMqmBc4AdVW3_l1YV4pBBhle1fvAqiK62uA543uI,1526
|
|
31
|
+
objectnat-1.2.2.dist-info/METADATA,sha256=og2Gul8hS_YIua9eXocfsKwFZ3-juQGp6hrAXFXvy-c,4536
|
|
32
|
+
objectnat-1.2.2.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
|
|
33
|
+
objectnat-1.2.2.dist-info/RECORD,,
|
objectnat-1.2.1.dist-info/RECORD
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
objectnat/__init__.py,sha256=VZ0TaIuB73EOl5Tin4Cs6-TCEOgBImCNYozwHD3bI_g,248
|
|
2
|
-
objectnat/_api.py,sha256=tor-BVRvbVeqGUrFlNc3pVJ_N3gpyDgMpxQfHgV5Y1U,725
|
|
3
|
-
objectnat/_config.py,sha256=bt9wohg8Hjwxril5PzotO5fjaIcown9vHq6kvXa3tzo,1353
|
|
4
|
-
objectnat/_version.py,sha256=1ZlkgkmphZGnGYOHAq5WqbnpVdTi39MMaQJd1wOEceI,19
|
|
5
|
-
objectnat/methods/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
objectnat/methods/coverage_zones/__init__.py,sha256=iebp-RbU60GRjIosd0Yvypz8-XNCme7f1Aah2nqynig,164
|
|
7
|
-
objectnat/methods/coverage_zones/graph_coverage.py,sha256=e4seTrhOTqEZ8DhE9xiH_fe-TwPNZXH3ujEq87CuEA0,4190
|
|
8
|
-
objectnat/methods/coverage_zones/radius_voronoi_coverage.py,sha256=A-O6WhgpJTizIHGiJ9JuP882iHbNejh0EW10H493kDM,1631
|
|
9
|
-
objectnat/methods/coverage_zones/stepped_coverage.py,sha256=e-zNE0JP4Q1Crb-JEbIZc0dYFzZXle2LjTxJPGS-7XE,5659
|
|
10
|
-
objectnat/methods/isochrones/__init__.py,sha256=inpyVZ4Mfz53k8HxW1zz3XFAqOE1xOQfpnfsS2f-a58,91
|
|
11
|
-
objectnat/methods/isochrones/isochrone_utils.py,sha256=84OLlj0tbnJAg7H_k0Il3wRHzdFhlMNU4G3w8z1_x6c,7037
|
|
12
|
-
objectnat/methods/isochrones/isochrones.py,sha256=VgpwubX7VEFStXyXM0B58cpFoCn3AboVekIU8GtXWls,11573
|
|
13
|
-
objectnat/methods/noise/__init__.py,sha256=fXlEuZ1z9Pw7cP4YRcbLaQnEgJIRkFdr2dTe2ypMhgg,189
|
|
14
|
-
objectnat/methods/noise/noise_init_data.py,sha256=jMFOqi5T7FYqcKjYg8AOIr_VNYbRZQks9wGULYNaMlw,513
|
|
15
|
-
objectnat/methods/noise/noise_reduce.py,sha256=KuVYLF5-hQGDqki6KU4BtgEufQ8tkOZvBWjFFjgw4m4,7040
|
|
16
|
-
objectnat/methods/noise/noise_simulation.py,sha256=-2pTzV-nShJfhgPg4AejKlMSvlTlnQDBCngLPZhFX8w,22389
|
|
17
|
-
objectnat/methods/noise/noise_simulation_simplified.py,sha256=igj4hI3rPDdKYgabq0aH0Evhy2jg-uTstLSqFjx2VSw,11094
|
|
18
|
-
objectnat/methods/point_clustering/__init__.py,sha256=SLRcjLZ_NyQvKBu5SHZTt7snCWpa0n7HlJqxlACJMyM,62
|
|
19
|
-
objectnat/methods/point_clustering/cluster_points_in_polygons.py,sha256=reY5ekJrAJUdWwVMvvZBp5T34H4K2V4mt3rQuyoUYPQ,5193
|
|
20
|
-
objectnat/methods/provision/__init__.py,sha256=a8h_Md3rBnmXK0o-MuaYiTIMRFMFu0bRZJ7ZP0P2hDQ,81
|
|
21
|
-
objectnat/methods/provision/provision.py,sha256=4NpZiUBllflt1woIOXAf1zh7MAB5Q6DegN67fXpJHu0,4947
|
|
22
|
-
objectnat/methods/provision/provision_exceptions.py,sha256=ofZOEv0jIZRNBgfrwqphkIHUWaGDo2WOa-hf7EuCM1g,1746
|
|
23
|
-
objectnat/methods/provision/provision_model.py,sha256=texAsht4DeBHveJpp6FEvsA4nE13kbf6iYXZD-xK7mw,14866
|
|
24
|
-
objectnat/methods/utils/__init__.py,sha256=1jhuPYwWwlNALtiO6n5IF-5z85nLKX4aC-ZaI85LEMM,53
|
|
25
|
-
objectnat/methods/utils/geom_utils.py,sha256=lCuMayV1iu8WJVVtwbswxfvl4B4dwxAqRcFfF1jd98M,6558
|
|
26
|
-
objectnat/methods/utils/graph_utils.py,sha256=aOtFZbuPAiGhkglMJBi9xcsb8XBbVFW7535DrhjWx1w,12667
|
|
27
|
-
objectnat/methods/utils/math_utils.py,sha256=Gcoi7MOmoWlu0ao5465GLtnP2eW4ZXKsGU9NyvUDR6E,871
|
|
28
|
-
objectnat/methods/visibility/__init__.py,sha256=vgrN4OTnap4fYfqm5GgNi787TZ85GbS9LbGfTIyTg-I,167
|
|
29
|
-
objectnat/methods/visibility/visibility_analysis.py,sha256=nXcDQ9zewpM4FFSXuYophUNsh6wiHSIHjM88vV6Iv_U,20843
|
|
30
|
-
objectnat-1.2.1.dist-info/LICENSE.txt,sha256=gI3AMqmBc4AdVW3_l1YV4pBBhle1fvAqiK62uA543uI,1526
|
|
31
|
-
objectnat-1.2.1.dist-info/METADATA,sha256=8s9EHELAA7LodH5DMtuKTF1JN3NyyBbWINlzqzKDCtw,4510
|
|
32
|
-
objectnat-1.2.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
33
|
-
objectnat-1.2.1.dist-info/RECORD,,
|
|
File without changes
|