voxcity 0.5.26__tar.gz → 0.5.27__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.

Files changed (53) hide show
  1. {voxcity-0.5.26 → voxcity-0.5.27}/PKG-INFO +1 -1
  2. {voxcity-0.5.26 → voxcity-0.5.27}/pyproject.toml +1 -1
  3. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/exporter/__init__.py +2 -1
  4. voxcity-0.5.27/src/voxcity/exporter/cityles.py +368 -0
  5. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity.egg-info/PKG-INFO +1 -1
  6. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity.egg-info/SOURCES.txt +1 -0
  7. {voxcity-0.5.26 → voxcity-0.5.27}/AUTHORS.rst +0 -0
  8. {voxcity-0.5.26 → voxcity-0.5.27}/CONTRIBUTING.rst +0 -0
  9. {voxcity-0.5.26 → voxcity-0.5.27}/HISTORY.rst +0 -0
  10. {voxcity-0.5.26 → voxcity-0.5.27}/LICENSE +0 -0
  11. {voxcity-0.5.26 → voxcity-0.5.27}/MANIFEST.in +0 -0
  12. {voxcity-0.5.26 → voxcity-0.5.27}/README.md +0 -0
  13. {voxcity-0.5.26 → voxcity-0.5.27}/docs/Makefile +0 -0
  14. {voxcity-0.5.26 → voxcity-0.5.27}/docs/_static/logo.png +0 -0
  15. {voxcity-0.5.26 → voxcity-0.5.27}/docs/conf.py +0 -0
  16. {voxcity-0.5.26 → voxcity-0.5.27}/docs/logo.png +0 -0
  17. {voxcity-0.5.26 → voxcity-0.5.27}/docs/make.bat +0 -0
  18. {voxcity-0.5.26 → voxcity-0.5.27}/setup.cfg +0 -0
  19. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/__init__.py +0 -0
  20. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/downloader/__init__.py +0 -0
  21. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/downloader/citygml.py +0 -0
  22. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/downloader/eubucco.py +0 -0
  23. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/downloader/gee.py +0 -0
  24. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/downloader/mbfp.py +0 -0
  25. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/downloader/oemj.py +0 -0
  26. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/downloader/osm.py +0 -0
  27. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/downloader/overture.py +0 -0
  28. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/downloader/utils.py +0 -0
  29. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/exporter/envimet.py +0 -0
  30. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/exporter/magicavoxel.py +0 -0
  31. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/exporter/obj.py +0 -0
  32. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/generator.py +0 -0
  33. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/geoprocessor/__init__.py +0 -0
  34. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/geoprocessor/draw.py +0 -0
  35. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/geoprocessor/grid.py +0 -0
  36. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/geoprocessor/mesh.py +0 -0
  37. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/geoprocessor/network.py +0 -0
  38. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/geoprocessor/polygon.py +0 -0
  39. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/geoprocessor/utils.py +0 -0
  40. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/simulator/__init__.py +0 -0
  41. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/simulator/solar.py +0 -0
  42. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/simulator/utils.py +0 -0
  43. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/simulator/view.py +0 -0
  44. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/utils/__init__.py +0 -0
  45. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/utils/lc.py +0 -0
  46. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/utils/material.py +0 -0
  47. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/utils/visualization.py +0 -0
  48. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity/utils/weather.py +0 -0
  49. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity.egg-info/dependency_links.txt +0 -0
  50. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity.egg-info/requires.txt +0 -0
  51. {voxcity-0.5.26 → voxcity-0.5.27}/src/voxcity.egg-info/top_level.txt +0 -0
  52. {voxcity-0.5.26 → voxcity-0.5.27}/tests/__init__.py +0 -0
  53. {voxcity-0.5.26 → voxcity-0.5.27}/tests/voxelcity.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voxcity
3
- Version: 0.5.26
3
+ Version: 0.5.27
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>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "voxcity"
3
- version = "0.5.26"
3
+ version = "0.5.27"
4
4
  requires-python = ">=3.10,<3.13"
5
5
  classifiers = [
6
6
  "Programming Language :: Python :: 3.10",
@@ -1,3 +1,4 @@
1
1
  from .envimet import *
2
2
  from .magicavoxel import *
3
- from .obj import *
3
+ from .obj import *
4
+ from .cityles import *
@@ -0,0 +1,368 @@
1
+ """
2
+ CityLES Exporter Module for VoxCity
3
+
4
+ This module provides functionality to export VoxCity grid data to the CityLES input file format.
5
+ CityLES is a large-eddy simulation (LES) model for urban environments, requiring specific input files
6
+ describing land use, building geometry, vegetation, and terrain.
7
+
8
+ Key Features:
9
+ - Converts VoxCity grids to CityLES-compatible input files (topog.txt, landuse.txt, dem.txt, vmap.txt, lonlat.txt)
10
+ - Handles land cover, building heights, canopy heights, and digital elevation models
11
+ - Supports flexible mapping from land cover and building types to CityLES codes
12
+ - Generates all required text files and metadata for CityLES runs
13
+
14
+ Main Functions:
15
+ - export_cityles: Main function to export all required CityLES input files
16
+ - export_topog: Exports building geometry (topog.txt)
17
+ - export_landuse: Exports land use grid (landuse.txt)
18
+ - export_dem: Exports digital elevation model (dem.txt)
19
+ - export_vmap: Exports vegetation map (vmap.txt)
20
+ - export_lonlat: Exports longitude/latitude grid (lonlat.txt)
21
+
22
+ Dependencies:
23
+ - numpy: For array operations
24
+ - pathlib: For file and directory management
25
+ - os: For file system operations
26
+ """
27
+
28
+ import os
29
+ import numpy as np
30
+ from pathlib import Path
31
+
32
+
33
+ # Land cover to CityLES land use mapping
34
+ # Based on common land cover classifications to CityLES codes
35
+ LANDCOVER_TO_CITYLES_LANDUSE = {
36
+ # Built-up areas
37
+ 'building': 4, # Concrete building
38
+ 'road': 2, # High reflective asphalt without AH
39
+ 'parking': 2, # High reflective asphalt without AH
40
+ 'pavement': 11, # Concrete (proxy of block)
41
+
42
+ # Vegetation
43
+ 'grass': 10, # Grassland
44
+ 'forest': 16, # Deciduous broadleaf forest
45
+ 'tree': 16, # Deciduous broadleaf forest
46
+ 'agriculture': 7, # Dryland cropland and pasture
47
+ 'cropland': 7, # Dryland cropland and pasture
48
+ 'paddy': 6, # Paddy
49
+
50
+ # Water and bare land
51
+ 'water': 9, # Water
52
+ 'bare_soil': 8, # Barren or sparsely vegetated
53
+ 'sand': 8, # Barren or sparsely vegetated
54
+
55
+ # Default
56
+ 'default': 10 # Grassland as default
57
+ }
58
+
59
+ # Building material mapping
60
+ # Maps building types to CityLES building attribute codes
61
+ BUILDING_MATERIAL_MAPPING = {
62
+ 'concrete': 104, # Concrete building
63
+ 'residential': 105, # Slate roof (ordinal wooden house)
64
+ 'commercial': 104, # Concrete building
65
+ 'industrial': 104, # Concrete building
66
+ 'default': 104 # Default to concrete building
67
+ }
68
+
69
+ # Tree type mapping
70
+ TREE_TYPE_MAPPING = {
71
+ 'deciduous': 101, # Leaf
72
+ 'evergreen': 101, # Leaf (simplified)
73
+ 'default': 101 # Default to leaf
74
+ }
75
+
76
+
77
+ def create_cityles_directories(output_directory):
78
+ """Create necessary directories for CityLES output"""
79
+ output_path = Path(output_directory)
80
+ output_path.mkdir(parents=True, exist_ok=True)
81
+ return output_path
82
+
83
+
84
+ def get_land_use_code(land_cover_value, land_cover_source=None):
85
+ """
86
+ Convert land cover value to CityLES land use code
87
+
88
+ Parameters:
89
+ -----------
90
+ land_cover_value : int or str
91
+ Land cover value from VoxCity
92
+ land_cover_source : str, optional
93
+ Source of land cover data (e.g., 'esri', 'esa', 'osm')
94
+
95
+ Returns:
96
+ --------
97
+ int : CityLES land use code (1-17)
98
+ """
99
+ # If using numeric codes, you might need source-specific mappings
100
+ # This is a simplified example
101
+ if isinstance(land_cover_value, str):
102
+ return LANDCOVER_TO_CITYLES_LANDUSE.get(land_cover_value.lower(),
103
+ LANDCOVER_TO_CITYLES_LANDUSE['default'])
104
+
105
+ # Example mapping for ESRI land cover (adjust based on actual data source)
106
+ if land_cover_source == 'esri':
107
+ esri_mapping = {
108
+ 1: 9, # Water -> Water
109
+ 2: 16, # Trees -> Deciduous broadleaf forest
110
+ 4: 8, # Flooded vegetation -> Barren
111
+ 5: 10, # Crops -> Grassland (simplified)
112
+ 7: 4, # Built Area -> Concrete building
113
+ 8: 8, # Bare ground -> Barren
114
+ 9: 3, # Snow/Ice -> Concrete (proxy of jari)
115
+ 10: 9, # Clouds -> Water (simplified)
116
+ 11: 10 # Rangeland -> Grassland
117
+ }
118
+ return esri_mapping.get(land_cover_value, LANDCOVER_TO_CITYLES_LANDUSE['default'])
119
+
120
+ # Default mapping
121
+ return LANDCOVER_TO_CITYLES_LANDUSE['default']
122
+
123
+
124
+ def export_topog(building_height_grid, building_id_grid, output_path,
125
+ building_material='default'):
126
+ """
127
+ Export topog.txt file for CityLES
128
+
129
+ Parameters:
130
+ -----------
131
+ building_height_grid : numpy.ndarray
132
+ 2D array of building heights
133
+ building_id_grid : numpy.ndarray
134
+ 2D array of building IDs
135
+ output_path : Path
136
+ Output directory path
137
+ building_material : str
138
+ Building material type for mapping
139
+ """
140
+ filename = output_path / 'topog.txt'
141
+
142
+ # Get building positions (where height > 0)
143
+ building_positions = np.argwhere(building_height_grid > 0)
144
+ n_buildings = len(building_positions)
145
+
146
+ material_code = BUILDING_MATERIAL_MAPPING.get(building_material,
147
+ BUILDING_MATERIAL_MAPPING['default'])
148
+
149
+ with open(filename, 'w') as f:
150
+ # Write number of buildings
151
+ f.write(f"{n_buildings}\n")
152
+
153
+ # Write building data
154
+ for idx, (j, i) in enumerate(building_positions):
155
+ # CityLES uses 1-based indexing
156
+ i_1based = i + 1
157
+ j_1based = j + 1
158
+ height = building_height_grid[j, i]
159
+
160
+ # Format: i j height material_code depth1 depth2 changed_material
161
+ f.write(f"{i_1based} {j_1based} {height:.1f} {material_code} 0.0 0.0 102\n")
162
+
163
+
164
+ def export_landuse(land_cover_grid, output_path, land_cover_source=None):
165
+ """
166
+ Export landuse.txt file for CityLES
167
+
168
+ Parameters:
169
+ -----------
170
+ land_cover_grid : numpy.ndarray
171
+ 2D array of land cover values
172
+ output_path : Path
173
+ Output directory path
174
+ land_cover_source : str, optional
175
+ Source of land cover data
176
+ """
177
+ filename = output_path / 'landuse.txt'
178
+
179
+ # Flatten the grid and convert to CityLES codes
180
+ flat_grid = land_cover_grid.flatten()
181
+
182
+ with open(filename, 'w') as f:
183
+ for value in flat_grid:
184
+ cityles_code = get_land_use_code(value, land_cover_source)
185
+ f.write(f"{cityles_code}\n")
186
+
187
+
188
+ def export_dem(dem_grid, output_path):
189
+ """
190
+ Export dem.txt file for CityLES
191
+
192
+ Parameters:
193
+ -----------
194
+ dem_grid : numpy.ndarray
195
+ 2D array of elevation values
196
+ output_path : Path
197
+ Output directory path
198
+ """
199
+ filename = output_path / 'dem.txt'
200
+
201
+ ny, nx = dem_grid.shape
202
+
203
+ with open(filename, 'w') as f:
204
+ for j in range(ny):
205
+ for i in range(nx):
206
+ # CityLES uses 1-based indexing
207
+ i_1based = i + 1
208
+ j_1based = j + 1
209
+ elevation = dem_grid[j, i]
210
+
211
+ f.write(f"{i_1based} {j_1based} {elevation:.1f}\n")
212
+
213
+
214
+ def export_vmap(canopy_height_grid, output_path, tree_base_ratio=0.3, tree_type='default'):
215
+ """
216
+ Export vmap.txt file for CityLES
217
+
218
+ Parameters:
219
+ -----------
220
+ canopy_height_grid : numpy.ndarray
221
+ 2D array of canopy heights
222
+ output_path : Path
223
+ Output directory path
224
+ tree_base_ratio : float
225
+ Ratio of tree base height to total canopy height
226
+ tree_type : str
227
+ Tree type for mapping
228
+ """
229
+ filename = output_path / 'vmap.txt'
230
+
231
+ # Get tree positions (where canopy height > 0)
232
+ tree_positions = np.argwhere(canopy_height_grid > 0)
233
+ n_trees = len(tree_positions)
234
+
235
+ tree_code = TREE_TYPE_MAPPING.get(tree_type, TREE_TYPE_MAPPING['default'])
236
+
237
+ with open(filename, 'w') as f:
238
+ # Write number of trees
239
+ f.write(f"{n_trees}\n")
240
+
241
+ # Write tree data
242
+ for idx, (j, i) in enumerate(tree_positions):
243
+ # CityLES uses 1-based indexing
244
+ i_1based = i + 1
245
+ j_1based = j + 1
246
+ total_height = canopy_height_grid[j, i]
247
+ lower_height = total_height * tree_base_ratio
248
+ upper_height = total_height
249
+
250
+ # Format: i j lower_height upper_height tree_type
251
+ f.write(f"{i_1based} {j_1based} {lower_height:.1f} {upper_height:.1f} {tree_code}\n")
252
+
253
+
254
+ def export_lonlat(rectangle_vertices, grid_shape, output_path):
255
+ """
256
+ Export lonlat.txt file for CityLES
257
+
258
+ Parameters:
259
+ -----------
260
+ rectangle_vertices : list of tuples
261
+ List of (lon, lat) vertices defining the area
262
+ grid_shape : tuple
263
+ Shape of the grid (ny, nx)
264
+ output_path : Path
265
+ Output directory path
266
+ """
267
+ filename = output_path / 'lonlat.txt'
268
+
269
+ ny, nx = grid_shape
270
+
271
+ # Extract bounds from vertices
272
+ lons = [v[0] for v in rectangle_vertices]
273
+ lats = [v[1] for v in rectangle_vertices]
274
+ min_lon, max_lon = min(lons), max(lons)
275
+ min_lat, max_lat = min(lats), max(lats)
276
+
277
+ # Create coordinate grids
278
+ lon_vals = np.linspace(min_lon, max_lon, nx)
279
+ lat_vals = np.linspace(min_lat, max_lat, ny)
280
+
281
+ with open(filename, 'w') as f:
282
+ for j in range(ny):
283
+ for i in range(nx):
284
+ # CityLES uses 1-based indexing
285
+ i_1based = i + 1
286
+ j_1based = j + 1
287
+ lon = lon_vals[i]
288
+ lat = lat_vals[j]
289
+
290
+ f.write(f"{i_1based} {j_1based} {lon:.7f} {lat:.8f}\n")
291
+
292
+
293
+ def export_cityles(building_height_grid, building_id_grid, canopy_height_grid,
294
+ land_cover_grid, dem_grid, meshsize, land_cover_source,
295
+ rectangle_vertices, output_directory="output/cityles",
296
+ building_material='default', tree_type='default',
297
+ tree_base_ratio=0.3, **kwargs):
298
+ """
299
+ Export VoxCity data to CityLES format
300
+
301
+ Parameters:
302
+ -----------
303
+ building_height_grid : numpy.ndarray
304
+ 2D array of building heights
305
+ building_id_grid : numpy.ndarray
306
+ 2D array of building IDs
307
+ canopy_height_grid : numpy.ndarray
308
+ 2D array of canopy heights
309
+ land_cover_grid : numpy.ndarray
310
+ 2D array of land cover values
311
+ dem_grid : numpy.ndarray
312
+ 2D array of elevation values
313
+ meshsize : float
314
+ Grid cell size in meters
315
+ land_cover_source : str
316
+ Source of land cover data (e.g., 'esri', 'esa', 'osm')
317
+ rectangle_vertices : list of tuples
318
+ List of (lon, lat) vertices defining the area
319
+ output_directory : str
320
+ Output directory path
321
+ building_material : str
322
+ Building material type for mapping
323
+ tree_type : str
324
+ Tree type for mapping
325
+ tree_base_ratio : float
326
+ Ratio of tree base height to total canopy height
327
+ **kwargs : dict
328
+ Additional parameters (for compatibility)
329
+
330
+ Returns:
331
+ --------
332
+ str : Path to output directory
333
+ """
334
+ # Create output directory
335
+ output_path = create_cityles_directories(output_directory)
336
+
337
+ print(f"Exporting CityLES files to: {output_path}")
338
+
339
+ # Export individual files
340
+ print("Exporting topog.txt...")
341
+ export_topog(building_height_grid, building_id_grid, output_path, building_material)
342
+
343
+ print("Exporting landuse.txt...")
344
+ export_landuse(land_cover_grid, output_path, land_cover_source)
345
+
346
+ print("Exporting dem.txt...")
347
+ export_dem(dem_grid, output_path)
348
+
349
+ print("Exporting vmap.txt...")
350
+ export_vmap(canopy_height_grid, output_path, tree_base_ratio, tree_type)
351
+
352
+ print("Exporting lonlat.txt...")
353
+ export_lonlat(rectangle_vertices, building_height_grid.shape, output_path)
354
+
355
+ # Create metadata file for reference
356
+ metadata_file = output_path / 'cityles_metadata.txt'
357
+ with open(metadata_file, 'w') as f:
358
+ f.write("CityLES Export Metadata\n")
359
+ f.write("====================\n")
360
+ f.write(f"Grid shape: {building_height_grid.shape}\n")
361
+ f.write(f"Mesh size: {meshsize} m\n")
362
+ f.write(f"Land cover source: {land_cover_source}\n")
363
+ f.write(f"Building material: {building_material}\n")
364
+ f.write(f"Tree type: {tree_type}\n")
365
+ f.write(f"Bounds: {rectangle_vertices}\n")
366
+
367
+ print(f"CityLES export completed successfully!")
368
+ return str(output_path)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voxcity
3
- Version: 0.5.26
3
+ Version: 0.5.27
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>
@@ -27,6 +27,7 @@ src/voxcity/downloader/osm.py
27
27
  src/voxcity/downloader/overture.py
28
28
  src/voxcity/downloader/utils.py
29
29
  src/voxcity/exporter/__init__.py
30
+ src/voxcity/exporter/cityles.py
30
31
  src/voxcity/exporter/envimet.py
31
32
  src/voxcity/exporter/magicavoxel.py
32
33
  src/voxcity/exporter/obj.py
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