voxcity 0.3.15__tar.gz → 0.3.17__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.
Potentially problematic release.
This version of voxcity might be problematic. Click here for more details.
- {voxcity-0.3.15 → voxcity-0.3.17}/PKG-INFO +1 -1
- {voxcity-0.3.15 → voxcity-0.3.17}/pyproject.toml +1 -1
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/downloader/gee.py +32 -1
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/generator.py +13 -4
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/geoprocessor/draw.py +35 -25
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/geoprocessor/grid.py +8 -1
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity.egg-info/PKG-INFO +1 -1
- {voxcity-0.3.15 → voxcity-0.3.17}/AUTHORS.rst +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/CONTRIBUTING.rst +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/HISTORY.rst +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/LICENSE +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/MANIFEST.in +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/README.md +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/docs/Makefile +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/docs/archive/README.rst +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/docs/authors.rst +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/docs/conf.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/docs/index.rst +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/docs/make.bat +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/setup.cfg +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/__init__.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/downloader/__init__.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/downloader/eubucco.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/downloader/mbfp.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/downloader/oemj.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/downloader/omt.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/downloader/osm.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/downloader/overture.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/downloader/utils.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/exporter/__init_.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/exporter/envimet.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/exporter/magicavoxel.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/exporter/obj.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/geoprocessor/__init_.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/geoprocessor/network.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/geoprocessor/polygon.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/geoprocessor/utils.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/simulator/__init_.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/simulator/solar.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/simulator/utils.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/simulator/view.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/utils/__init_.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/utils/lc.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/utils/material.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/utils/visualization.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity/utils/weather.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity.egg-info/SOURCES.txt +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity.egg-info/dependency_links.txt +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity.egg-info/requires.txt +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/src/voxcity.egg-info/top_level.txt +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/tests/__init__.py +0 -0
- {voxcity-0.3.15 → voxcity-0.3.17}/tests/voxelcity.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: voxcity
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.17
|
|
4
4
|
Summary: voxcity is an easy and one-stop tool to output 3d city models for microclimate simulation by integrating multiple geospatial open-data
|
|
5
5
|
Author-email: Kunihiko Fujiwara <kunihiko@nus.edu.sg>
|
|
6
6
|
Maintainer-email: Kunihiko Fujiwara <kunihiko@nus.edu.sg>
|
|
@@ -393,4 +393,35 @@ def save_geotiff_open_buildings_temporal(aoi, geotiff_path):
|
|
|
393
393
|
scale=4,
|
|
394
394
|
region=aoi,
|
|
395
395
|
file_per_band=False
|
|
396
|
-
)
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
def save_geotiff_england_dsm_minus_dtm(roi, geotiff_path, meshsize):
|
|
399
|
+
"""Get the height difference between DSM and DTM from England 1m terrain data.
|
|
400
|
+
|
|
401
|
+
Args:
|
|
402
|
+
roi: Earth Engine geometry defining area of interest
|
|
403
|
+
geotiff_path: Output path for GeoTIFF file
|
|
404
|
+
meshsize: Size of each grid cell in meters
|
|
405
|
+
|
|
406
|
+
Returns:
|
|
407
|
+
ee.Image: Image representing DSM minus DTM (building/vegetation heights)
|
|
408
|
+
"""
|
|
409
|
+
# Initialize Earth Engine
|
|
410
|
+
ee.Initialize()
|
|
411
|
+
|
|
412
|
+
# Add buffer around ROI to ensure smooth interpolation at edges
|
|
413
|
+
buffer_distance = 100
|
|
414
|
+
roi_buffered = roi.buffer(buffer_distance)
|
|
415
|
+
|
|
416
|
+
collection_name = 'UK/EA/ENGLAND_1M_TERRAIN/2022'
|
|
417
|
+
dtm = ee.Image(collection_name).select('dtm')
|
|
418
|
+
dsm = ee.Image(collection_name).select('dsm_first')
|
|
419
|
+
|
|
420
|
+
# Subtract DTM from DSM to get height difference
|
|
421
|
+
height_diff = dsm.subtract(dtm)
|
|
422
|
+
|
|
423
|
+
# Clip to buffered ROI
|
|
424
|
+
image = height_diff.clip(roi_buffered)
|
|
425
|
+
|
|
426
|
+
# Export as GeoTIFF using meshsize as scale
|
|
427
|
+
save_geotiff(image, geotiff_path, scale=meshsize, region=roi_buffered, crs='EPSG:4326')
|
|
@@ -34,7 +34,8 @@ from .downloader.gee import (
|
|
|
34
34
|
save_geotiff_esa_land_cover,
|
|
35
35
|
save_geotiff_esri_landcover,
|
|
36
36
|
save_geotiff_dynamic_world_v1,
|
|
37
|
-
save_geotiff_open_buildings_temporal
|
|
37
|
+
save_geotiff_open_buildings_temporal,
|
|
38
|
+
save_geotiff_england_dsm_minus_dtm
|
|
38
39
|
)
|
|
39
40
|
from .geoprocessor.grid import (
|
|
40
41
|
group_and_label_cells,
|
|
@@ -185,11 +186,12 @@ def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, *
|
|
|
185
186
|
|
|
186
187
|
# Check for complementary building data source
|
|
187
188
|
building_complementary_source = kwargs.get("building_complementary_source")
|
|
189
|
+
building_complement_height = kwargs.get("building_complement_height")
|
|
188
190
|
|
|
189
191
|
if (building_complementary_source is None) or (building_complementary_source=='None'):
|
|
190
192
|
# Use only primary source
|
|
191
193
|
if source != "Open Building 2.5D Temporal":
|
|
192
|
-
building_height_grid, building_min_height_grid, building_id_grid, filtered_buildings = create_building_height_grid_from_gdf_polygon(gdf, meshsize, rectangle_vertices)
|
|
194
|
+
building_height_grid, building_min_height_grid, building_id_grid, filtered_buildings = create_building_height_grid_from_gdf_polygon(gdf, meshsize, rectangle_vertices, complement_height=building_complement_height)
|
|
193
195
|
else:
|
|
194
196
|
# Handle complementary source
|
|
195
197
|
if building_complementary_source == "Open Building 2.5D Temporal":
|
|
@@ -198,7 +200,14 @@ def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, *
|
|
|
198
200
|
os.makedirs(output_dir, exist_ok=True)
|
|
199
201
|
geotiff_path_comp = os.path.join(output_dir, "building_height.tif")
|
|
200
202
|
save_geotiff_open_buildings_temporal(roi, geotiff_path_comp)
|
|
201
|
-
building_height_grid, building_min_height_grid, building_id_grid, filtered_buildings = create_building_height_grid_from_gdf_polygon(gdf, meshsize, rectangle_vertices, geotiff_path_comp=geotiff_path_comp)
|
|
203
|
+
building_height_grid, building_min_height_grid, building_id_grid, filtered_buildings = create_building_height_grid_from_gdf_polygon(gdf, meshsize, rectangle_vertices, geotiff_path_comp=geotiff_path_comp, complement_height=building_complement_height)
|
|
204
|
+
elif building_complementary_source == "England 1m DSM - DTM":
|
|
205
|
+
# Special case: use temporal height data as complement
|
|
206
|
+
roi = get_roi(rectangle_vertices)
|
|
207
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
208
|
+
geotiff_path_comp = os.path.join(output_dir, "building_height.tif")
|
|
209
|
+
save_geotiff_england_dsm_minus_dtm(roi, geotiff_path_comp, meshsize)
|
|
210
|
+
building_height_grid, building_min_height_grid, building_id_grid, filtered_buildings = create_building_height_grid_from_gdf_polygon(gdf, meshsize, rectangle_vertices, geotiff_path_comp=geotiff_path_comp, complement_height=building_complement_height)
|
|
202
211
|
else:
|
|
203
212
|
# Get complementary data from other sources
|
|
204
213
|
if building_complementary_source == 'Microsoft Building Footprints':
|
|
@@ -220,7 +229,7 @@ def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, *
|
|
|
220
229
|
|
|
221
230
|
# Option to complement footprints only or both footprints and heights
|
|
222
231
|
complement_building_footprints = kwargs.get("complement_building_footprints")
|
|
223
|
-
building_height_grid, building_min_height_grid, building_id_grid, filtered_buildings = create_building_height_grid_from_gdf_polygon(gdf, meshsize, rectangle_vertices, gdf_comp=gdf_comp, complement_building_footprints=complement_building_footprints)
|
|
232
|
+
building_height_grid, building_min_height_grid, building_id_grid, filtered_buildings = create_building_height_grid_from_gdf_polygon(gdf, meshsize, rectangle_vertices, gdf_comp=gdf_comp, complement_building_footprints=complement_building_footprints, complement_height=building_complement_height)
|
|
224
233
|
|
|
225
234
|
# Visualize grid if requested
|
|
226
235
|
grid_vis = kwargs.get("gridvis", True)
|
|
@@ -223,15 +223,16 @@ def center_location_map_cityname(cityname, east_west_length, north_south_length,
|
|
|
223
223
|
|
|
224
224
|
return m, rectangle_vertices
|
|
225
225
|
|
|
226
|
-
def display_buildings_and_draw_polygon(building_gdf, zoom=17):
|
|
226
|
+
def display_buildings_and_draw_polygon(building_gdf=None, rectangle_vertices=None, zoom=17):
|
|
227
227
|
"""
|
|
228
228
|
Displays building footprints (in Lon-Lat order) on an ipyleaflet map,
|
|
229
229
|
and allows the user to draw a polygon whose vertices are returned
|
|
230
230
|
in a Python list (also in Lon-Lat).
|
|
231
231
|
|
|
232
232
|
Args:
|
|
233
|
-
building_gdf (GeoDataFrame): A GeoDataFrame containing building footprints,
|
|
234
|
-
|
|
233
|
+
building_gdf (GeoDataFrame, optional): A GeoDataFrame containing building footprints,
|
|
234
|
+
with geometry in [lon, lat] order.
|
|
235
|
+
rectangle_vertices (list, optional): List of [lon, lat] coordinates defining rectangle corners.
|
|
235
236
|
zoom (int): Initial zoom level for the map. Default=17.
|
|
236
237
|
|
|
237
238
|
Returns:
|
|
@@ -243,39 +244,48 @@ def display_buildings_and_draw_polygon(building_gdf, zoom=17):
|
|
|
243
244
|
# ---------------------------------------------------------
|
|
244
245
|
# 1. Determine a suitable map center via bounding box logic
|
|
245
246
|
# ---------------------------------------------------------
|
|
246
|
-
if
|
|
247
|
-
#
|
|
248
|
-
|
|
249
|
-
|
|
247
|
+
if rectangle_vertices is not None:
|
|
248
|
+
# Get bounds from rectangle vertices
|
|
249
|
+
lons = [v[0] for v in rectangle_vertices]
|
|
250
|
+
lats = [v[1] for v in rectangle_vertices]
|
|
251
|
+
min_lon, max_lon = min(lons), max(lons)
|
|
252
|
+
min_lat, max_lat = min(lats), max(lats)
|
|
253
|
+
center_lon = (min_lon + max_lon) / 2
|
|
254
|
+
center_lat = (min_lat + max_lat) / 2
|
|
255
|
+
elif building_gdf is not None and len(building_gdf) > 0:
|
|
250
256
|
# Get bounds from GeoDataFrame
|
|
251
257
|
bounds = building_gdf.total_bounds # Returns [minx, miny, maxx, maxy]
|
|
252
258
|
min_lon, min_lat, max_lon, max_lat = bounds
|
|
253
259
|
center_lon = (min_lon + max_lon) / 2
|
|
254
260
|
center_lat = (min_lat + max_lat) / 2
|
|
261
|
+
else:
|
|
262
|
+
# Fallback: If no inputs or invalid data, pick a default
|
|
263
|
+
center_lon, center_lat = -100.0, 40.0
|
|
255
264
|
|
|
256
265
|
# Create the ipyleaflet map (needs lat,lon)
|
|
257
266
|
m = Map(center=(center_lat, center_lon), zoom=zoom, scroll_wheel_zoom=True)
|
|
258
267
|
|
|
259
268
|
# -----------------------------------------
|
|
260
|
-
# 2. Add
|
|
269
|
+
# 2. Add building footprints to the map if provided
|
|
261
270
|
# -----------------------------------------
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
271
|
+
if building_gdf is not None:
|
|
272
|
+
for idx, row in building_gdf.iterrows():
|
|
273
|
+
# Only handle simple Polygons
|
|
274
|
+
if isinstance(row.geometry, geom.Polygon):
|
|
275
|
+
# Get coordinates from geometry
|
|
276
|
+
coords = list(row.geometry.exterior.coords)
|
|
277
|
+
# Convert to (lat,lon) for ipyleaflet, skip last repeated coordinate
|
|
278
|
+
lat_lon_coords = [(c[1], c[0]) for c in coords[:-1]]
|
|
279
|
+
|
|
280
|
+
# Create the polygon layer
|
|
281
|
+
bldg_layer = LeafletPolygon(
|
|
282
|
+
locations=lat_lon_coords,
|
|
283
|
+
color="blue",
|
|
284
|
+
fill_color="blue",
|
|
285
|
+
fill_opacity=0.2,
|
|
286
|
+
weight=2
|
|
287
|
+
)
|
|
288
|
+
m.add_layer(bldg_layer)
|
|
279
289
|
|
|
280
290
|
# -----------------------------------------------------------------
|
|
281
291
|
# 3. Enable drawing of polygons, capturing the vertices in Lon-Lat
|
|
@@ -480,7 +480,8 @@ def create_building_height_grid_from_gdf_polygon(
|
|
|
480
480
|
rectangle_vertices,
|
|
481
481
|
gdf_comp=None,
|
|
482
482
|
geotiff_path_comp=None,
|
|
483
|
-
complement_building_footprints=None
|
|
483
|
+
complement_building_footprints=None,
|
|
484
|
+
complement_height=None
|
|
484
485
|
):
|
|
485
486
|
"""
|
|
486
487
|
Create a building height grid from GeoDataFrame data within a polygon boundary.
|
|
@@ -492,6 +493,7 @@ def create_building_height_grid_from_gdf_polygon(
|
|
|
492
493
|
gdf_comp (geopandas.GeoDataFrame, optional): Complementary GeoDataFrame
|
|
493
494
|
geotiff_path_comp (str, optional): Path to complementary GeoTIFF file
|
|
494
495
|
complement_building_footprints (bool, optional): Whether to complement footprints
|
|
496
|
+
complement_height (float, optional): Height value to use for buildings with height=0
|
|
495
497
|
|
|
496
498
|
Returns:
|
|
497
499
|
tuple: (building_height_grid, building_min_height_grid, building_id_grid, filtered_buildings)
|
|
@@ -558,6 +560,11 @@ def create_building_height_grid_from_gdf_polygon(
|
|
|
558
560
|
for idx_b, row in filtered_gdf.iterrows():
|
|
559
561
|
polygon = row.geometry
|
|
560
562
|
height = row.get('height', None)
|
|
563
|
+
|
|
564
|
+
# Replace height=0 with complement_height if specified
|
|
565
|
+
if complement_height is not None and (height == 0 or height is None):
|
|
566
|
+
height = complement_height
|
|
567
|
+
|
|
561
568
|
min_height = row.get('min_height', 0)
|
|
562
569
|
is_inner = row.get('is_inner', False)
|
|
563
570
|
feature_id = row.get('id', idx_b)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: voxcity
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.17
|
|
4
4
|
Summary: voxcity is an easy and one-stop tool to output 3d city models for microclimate simulation by integrating multiple geospatial open-data
|
|
5
5
|
Author-email: Kunihiko Fujiwara <kunihiko@nus.edu.sg>
|
|
6
6
|
Maintainer-email: Kunihiko Fujiwara <kunihiko@nus.edu.sg>
|
|
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
|
|
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
|
|
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
|
|
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
|