voxcity 0.6.25__tar.gz → 0.6.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 (39) hide show
  1. {voxcity-0.6.25 → voxcity-0.6.27}/PKG-INFO +1 -1
  2. {voxcity-0.6.25 → voxcity-0.6.27}/pyproject.toml +1 -1
  3. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/downloader/__init__.py +2 -1
  4. voxcity-0.6.27/src/voxcity/downloader/gba.py +210 -0
  5. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/exporter/cityles.py +76 -95
  6. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/generator.py +17 -2
  7. {voxcity-0.6.25 → voxcity-0.6.27}/AUTHORS.rst +0 -0
  8. {voxcity-0.6.25 → voxcity-0.6.27}/LICENSE +0 -0
  9. {voxcity-0.6.25 → voxcity-0.6.27}/README.md +0 -0
  10. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/__init__.py +0 -0
  11. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/downloader/citygml.py +0 -0
  12. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/downloader/eubucco.py +0 -0
  13. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/downloader/gee.py +0 -0
  14. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/downloader/mbfp.py +0 -0
  15. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/downloader/oemj.py +0 -0
  16. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/downloader/osm.py +0 -0
  17. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/downloader/overture.py +0 -0
  18. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/downloader/utils.py +0 -0
  19. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/exporter/__init__.py +0 -0
  20. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/exporter/envimet.py +0 -0
  21. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/exporter/magicavoxel.py +0 -0
  22. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/exporter/netcdf.py +0 -0
  23. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/exporter/obj.py +0 -0
  24. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/geoprocessor/__init__.py +0 -0
  25. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/geoprocessor/draw.py +0 -0
  26. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/geoprocessor/grid.py +0 -0
  27. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/geoprocessor/mesh.py +0 -0
  28. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/geoprocessor/network.py +0 -0
  29. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/geoprocessor/polygon.py +0 -0
  30. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/geoprocessor/utils.py +0 -0
  31. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/simulator/__init__.py +0 -0
  32. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/simulator/solar.py +0 -0
  33. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/simulator/utils.py +0 -0
  34. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/simulator/view.py +0 -0
  35. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/utils/__init__.py +0 -0
  36. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/utils/lc.py +0 -0
  37. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/utils/material.py +0 -0
  38. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/utils/visualization.py +0 -0
  39. {voxcity-0.6.25 → voxcity-0.6.27}/src/voxcity/utils/weather.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voxcity
3
- Version: 0.6.25
3
+ Version: 0.6.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
  License: MIT
6
6
  License-File: AUTHORS.rst
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "voxcity"
3
- version = "0.6.25"
3
+ version = "0.6.27"
4
4
  description = "voxcity is an easy and one-stop tool to output 3d city models for microclimate simulation by integrating multiple geospatial open-data"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -4,4 +4,5 @@ from .gee import *
4
4
  from .osm import *
5
5
  from .oemj import *
6
6
  from .eubucco import *
7
- from .overture import *
7
+ from .overture import *
8
+ from .gba import *
@@ -0,0 +1,210 @@
1
+ """
2
+ Downloader for Global Building Atlas (GBA) LOD1 polygons.
3
+
4
+ This module downloads GeoParquet tiles from the Global Building Atlas (GBA)
5
+ hosted at data.source.coop, selects tiles intersecting a user-specified
6
+ rectangle, loads them into a GeoDataFrame, and filters features to the
7
+ rectangle extent.
8
+
9
+ Tile scheme:
10
+ - Global 5x5-degree tiles named like: e010_n50_e015_n45.parquet
11
+ - longitudes: e/w with 3-digit zero padding (e.g., e010, w060)
12
+ - latitudes: n/s with 2-digit zero padding (e.g., n50, s25)
13
+ - filename order: west_lon, north_lat, east_lon, south_lat
14
+
15
+ Usage:
16
+ gdf = load_gdf_from_gba(rectangle_vertices=[(lon1, lat1), (lon2, lat2), ...])
17
+
18
+ Notes:
19
+ - Output CRS is EPSG:4326.
20
+ - Requires pyarrow or fastparquet for parquet reading via GeoPandas.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import math
26
+ import os
27
+ import tempfile
28
+ from typing import Iterable, List, Optional, Sequence, Tuple
29
+
30
+ import geopandas as gpd
31
+ import pandas as pd
32
+ import requests
33
+ from shapely.geometry import Polygon
34
+
35
+
36
+ def _bbox_from_rectangle_vertices(vertices: Sequence[Tuple[float, float]]) -> Tuple[float, float, float, float]:
37
+ """
38
+ Convert rectangle vertices in (lon, lat) into bbox as (min_lon, min_lat, max_lon, max_lat).
39
+ """
40
+ if not vertices:
41
+ raise ValueError("rectangle_vertices must be a non-empty sequence of (lon, lat)")
42
+ lons = [v[0] for v in vertices]
43
+ lats = [v[1] for v in vertices]
44
+ return (min(lons), min(lats), max(lons), max(lats))
45
+
46
+
47
+ def _pad_lon(deg: int) -> str:
48
+ return f"{abs(deg):03d}"
49
+
50
+
51
+ def _pad_lat(deg: int) -> str:
52
+ return f"{abs(deg):02d}"
53
+
54
+
55
+ def _lon_tag(deg: int) -> str:
56
+ return ("e" if deg >= 0 else "w") + _pad_lon(deg)
57
+
58
+
59
+ def _lat_tag(deg: int) -> str:
60
+ return ("n" if deg >= 0 else "s") + _pad_lat(deg)
61
+
62
+
63
+ def _snap_down(value: float, step: int) -> int:
64
+ return int(math.floor(value / step) * step)
65
+
66
+
67
+ def _snap_up(value: float, step: int) -> int:
68
+ return int(math.ceil(value / step) * step)
69
+
70
+
71
+ def _generate_tile_bounds_for_bbox(
72
+ min_lon: float, min_lat: float, max_lon: float, max_lat: float, tile_size_deg: int = 5
73
+ ) -> Iterable[Tuple[int, int, int, int]]:
74
+ """
75
+ Generate 5-degree tile bounds (west, south, east, north) covering bbox.
76
+ All values are integer degrees aligned to tile_size_deg.
77
+ """
78
+ west = _snap_down(min_lon, tile_size_deg)
79
+ east = _snap_up(max_lon, tile_size_deg)
80
+ south = _snap_down(min_lat, tile_size_deg)
81
+ north = _snap_up(max_lat, tile_size_deg)
82
+
83
+ for lon in range(west, east, tile_size_deg):
84
+ for lat in range(south, north, tile_size_deg):
85
+ yield (lon, lat, lon + tile_size_deg, lat + tile_size_deg)
86
+
87
+
88
+ def _tile_filename(west: int, south: int, east: int, north: int) -> str:
89
+ """
90
+ Construct GBA tile filename for given integer-degree bounds.
91
+ Naming convention examples:
92
+ e010_n50_e015_n45.parquet
93
+ e140_s25_e145_s30.parquet
94
+ w060_s30_w055_s35.parquet
95
+ """
96
+ return f"{_lon_tag(west)}_{_lat_tag(north)}_{_lon_tag(east)}_{_lat_tag(south)}.parquet"
97
+
98
+
99
+ def _tile_url(base_url: str, west: int, south: int, east: int, north: int) -> str:
100
+ filename = _tile_filename(west, south, east, north)
101
+ return f"{base_url.rstrip('/')}/{filename}"
102
+
103
+
104
+ def _download_parquet(url: str, download_dir: str, timeout: int = 60) -> Optional[str]:
105
+ """
106
+ Download a parquet file to download_dir. Returns local filepath or None if not found.
107
+ """
108
+ try:
109
+ with requests.get(url, stream=True, timeout=timeout) as r:
110
+ if r.status_code != 200:
111
+ return None
112
+ filename = os.path.basename(url)
113
+ local_path = os.path.join(download_dir, filename)
114
+ with open(local_path, "wb") as f:
115
+ for chunk in r.iter_content(chunk_size=1024 * 1024):
116
+ if chunk:
117
+ f.write(chunk)
118
+ return local_path
119
+ except requests.RequestException:
120
+ return None
121
+
122
+
123
+ def _filter_to_rectangle(gdf: gpd.GeoDataFrame, rectangle: Polygon, clip: bool) -> gpd.GeoDataFrame:
124
+ gdf = gdf[gdf.geometry.notnull()].copy()
125
+ # Ensure CRS is WGS84
126
+ if gdf.crs is None:
127
+ gdf.set_crs(epsg=4326, inplace=True)
128
+ elif gdf.crs.to_epsg() != 4326:
129
+ gdf = gdf.to_crs(epsg=4326)
130
+
131
+ intersects = gdf.intersects(rectangle)
132
+ gdf = gdf[intersects].copy()
133
+ if clip and not gdf.empty:
134
+ # GeoPandas clip performs overlay to trim geometries to rectangle
135
+ gdf = gpd.clip(gdf, gpd.GeoSeries([rectangle], crs="EPSG:4326").to_frame("geometry"))
136
+ return gdf
137
+
138
+
139
+ def load_gdf_from_gba(
140
+ rectangle_vertices: Sequence[Tuple[float, float]],
141
+ base_url: str = "https://data.source.coop/tge-labs/globalbuildingatlas-lod1",
142
+ download_dir: Optional[str] = None,
143
+ clip_to_rectangle: bool = False,
144
+ ) -> Optional[gpd.GeoDataFrame]:
145
+ """
146
+ Download GBA tiles intersecting a rectangle and return combined GeoDataFrame.
147
+
148
+ Args:
149
+ rectangle_vertices: Sequence of (lon, lat) defining the area of interest.
150
+ base_url: Base URL hosting GBA parquet tiles.
151
+ download_dir: Optional directory to store downloaded tiles. If None, a
152
+ temporary directory is used and cleaned up by the OS later.
153
+ clip_to_rectangle: If True, geometries are clipped to rectangle extent.
154
+
155
+ Returns:
156
+ GeoDataFrame with EPSG:4326 geometry and an 'id' column, or None if no data.
157
+ """
158
+ min_lon, min_lat, max_lon, max_lat = _bbox_from_rectangle_vertices(rectangle_vertices)
159
+ rectangle = Polygon([
160
+ (min_lon, min_lat),
161
+ (max_lon, min_lat),
162
+ (max_lon, max_lat),
163
+ (min_lon, max_lat),
164
+ (min_lon, min_lat),
165
+ ])
166
+
167
+ tmp_dir_created = False
168
+ if download_dir is None:
169
+ download_dir = tempfile.mkdtemp(prefix="gba_tiles_")
170
+ tmp_dir_created = True
171
+ else:
172
+ os.makedirs(download_dir, exist_ok=True)
173
+
174
+ local_files: List[str] = []
175
+ for west, south, east, north in _generate_tile_bounds_for_bbox(min_lon, min_lat, max_lon, max_lat):
176
+ url = _tile_url(base_url, west, south, east, north)
177
+ local = _download_parquet(url, download_dir)
178
+ if local is not None:
179
+ local_files.append(local)
180
+
181
+ if not local_files:
182
+ return None
183
+
184
+ gdfs: List[gpd.GeoDataFrame] = []
185
+ for path in local_files:
186
+ try:
187
+ # GeoParquet read
188
+ gdf = gpd.read_parquet(path)
189
+ if gdf is not None and not gdf.empty:
190
+ gdfs.append(gdf)
191
+ except Exception:
192
+ # Skip unreadable tiles
193
+ continue
194
+
195
+ if not gdfs:
196
+ return None
197
+
198
+ combined = pd.concat(gdfs, ignore_index=True)
199
+ combined = gpd.GeoDataFrame(combined, geometry="geometry")
200
+ combined = _filter_to_rectangle(combined, rectangle, clip=clip_to_rectangle)
201
+
202
+ if combined.empty:
203
+ return None
204
+
205
+ # Ensure sequential ids
206
+ combined["id"] = combined.index.astype(int)
207
+ combined.set_crs(epsg=4326, inplace=True, allow_override=True)
208
+ return combined
209
+
210
+
@@ -36,126 +36,107 @@ VOXCITY_STANDARD_CLASSES = {
36
36
  }
37
37
 
38
38
  ## Source-specific class name to CityLES land use mappings
39
- # CityLES land use codes (updated to match provided definitions):
40
- # 1: High reflective ASPHALT, 2: High reflective ASPHALT without AH,
41
- # 3: CONCRETE (proxy of jari), 4: CONCRETE building,
42
- # 5: Slate roof (Ordinal wooden house), 6: PADDY,
43
- # 7: Dryland Cropland and Pasture, 8: Barren or Sparsely Vegetated,
44
- # 9: WATER, 10: Grassland, 11: CONCRETE (proxy of block),
45
- # 12: ASPHALT without AH, 13: ASPHALT,
46
- # 14-17: Deciduous Broadleaf Forest
47
-
48
- # OpenStreetMap / Standard (mapped to updated CityLES landuse codes)
39
+ # CityLES land use codes: 1=Water, 2=Rice Paddy, 3=Crops, 4=Grassland, 5=Deciduous Broadleaf Forest,
40
+ # 9=Bare Land, 10=Building, 16=Asphalt (road), etc.
41
+
42
+ # OpenStreetMap / Standard
49
43
  OSM_CLASS_TO_CITYLES = {
50
- 'Bareland': 8,
51
- 'Rangeland': 10,
52
- 'Shrub': 10,
53
- 'Moss and lichen': 10,
54
- 'Agriculture land': 7,
55
- 'Tree': 14,
56
- 'Wet land': 6,
57
- 'Mangroves': 14,
58
- 'Water': 9,
59
- 'Snow and ice': 8,
60
- 'Developed space': 4,
61
- 'Road': 13,
62
- 'Building': 4,
63
- 'No Data': 10
44
+ 'Bareland': 9,
45
+ 'Rangeland': 4,
46
+ 'Shrub': 4,
47
+ 'Moss and lichen': 4,
48
+ 'Agriculture land': 3,
49
+ 'Tree': 5,
50
+ 'Wet land': 2,
51
+ 'Mangroves': 5,
52
+ 'Water': 1,
53
+ 'Snow and ice': 9,
54
+ 'Developed space': 10,
55
+ 'Road': 16,
56
+ 'Building': 10,
57
+ 'No Data': 4
64
58
  }
65
59
 
66
60
  # Urbanwatch
67
61
  URBANWATCH_CLASS_TO_CITYLES = {
68
- 'Building': 4,
69
- 'Road': 13,
70
- 'Parking Lot': 13,
71
- 'Tree Canopy': 14,
72
- 'Grass/Shrub': 10,
73
- 'Agriculture': 7,
74
- 'Water': 9,
75
- 'Barren': 8,
76
- 'Unknown': 10,
77
- 'Sea': 9
62
+ 'Building': 10,
63
+ 'Road': 16,
64
+ 'Parking Lot': 16,
65
+ 'Tree Canopy': 5,
66
+ 'Grass/Shrub': 4,
67
+ 'Agriculture': 3,
68
+ 'Water': 1,
69
+ 'Barren': 9,
70
+ 'Unknown': 4,
71
+ 'Sea': 1
78
72
  }
79
73
 
80
74
  # OpenEarthMapJapan
81
75
  OEMJ_CLASS_TO_CITYLES = {
82
- 'Bareland': 8,
83
- 'Rangeland': 10,
84
- 'Developed space': 4,
85
- 'Road': 13,
86
- 'Tree': 14,
87
- 'Water': 9,
88
- 'Agriculture land': 7,
89
- 'Building': 4
76
+ 'Bareland': 9,
77
+ 'Rangeland': 4,
78
+ 'Developed space': 10,
79
+ 'Road': 16,
80
+ 'Tree': 5,
81
+ 'Water': 1,
82
+ 'Agriculture land': 3,
83
+ 'Building': 10
90
84
  }
91
85
 
92
86
  # ESA WorldCover
93
87
  ESA_CLASS_TO_CITYLES = {
94
- 'Trees': 14,
95
- 'Shrubland': 10,
96
- 'Grassland': 10,
97
- 'Cropland': 7,
98
- 'Built-up': 4,
99
- 'Barren / sparse vegetation': 8,
100
- 'Snow and ice': 8,
101
- 'Open water': 9,
102
- 'Herbaceous wetland': 6,
103
- 'Mangroves': 14,
104
- 'Moss and lichen': 10
88
+ 'Trees': 5,
89
+ 'Shrubland': 4,
90
+ 'Grassland': 4,
91
+ 'Cropland': 3,
92
+ 'Built-up': 10,
93
+ 'Barren / sparse vegetation': 9,
94
+ 'Snow and ice': 9,
95
+ 'Open water': 1,
96
+ 'Herbaceous wetland': 2,
97
+ 'Mangroves': 5,
98
+ 'Moss and lichen': 9
105
99
  }
106
100
 
107
101
  # ESRI 10m Annual Land Cover
108
102
  ESRI_CLASS_TO_CITYLES = {
109
- 'No Data': 10,
110
- 'Water': 9,
111
- 'Trees': 14,
112
- 'Grass': 10,
113
- 'Flooded Vegetation': 6,
114
- 'Crops': 7,
115
- 'Scrub/Shrub': 10,
116
- 'Built Area': 4,
117
- 'Bare Ground': 8,
118
- 'Snow/Ice': 8,
119
- 'Clouds': 10
103
+ 'No Data': 4,
104
+ 'Water': 1,
105
+ 'Trees': 5,
106
+ 'Grass': 4,
107
+ 'Flooded Vegetation': 2,
108
+ 'Crops': 3,
109
+ 'Scrub/Shrub': 4,
110
+ 'Built Area': 10,
111
+ 'Bare Ground': 9,
112
+ 'Snow/Ice': 9,
113
+ 'Clouds': 4
120
114
  }
121
115
 
122
116
  # Dynamic World V1
123
117
  DYNAMIC_WORLD_CLASS_TO_CITYLES = {
124
- 'Water': 9,
125
- 'Trees': 14,
126
- 'Grass': 10,
127
- 'Flooded Vegetation': 6,
128
- 'Crops': 7,
129
- 'Shrub and Scrub': 10,
130
- 'Built': 4,
131
- 'Bare': 8,
132
- 'Snow and Ice': 8
118
+ 'Water': 1,
119
+ 'Trees': 5,
120
+ 'Grass': 4,
121
+ 'Flooded Vegetation': 2,
122
+ 'Crops': 3,
123
+ 'Shrub and Scrub': 4,
124
+ 'Built': 10,
125
+ 'Bare': 9,
126
+ 'Snow and Ice': 9
133
127
  }
134
128
 
135
- # Building material mapping based on corrected definitions (101-117)
129
+ # Building material mapping based on corrected documentation
136
130
  BUILDING_MATERIAL_MAPPING = {
137
- 'building': 104, # CONCRETE building
138
- 'concrete': 104, # CONCRETE building
139
- 'residential': 105, # Slate roof (Ordinal wooden house)
140
- 'wooden': 105, # Slate roof (Ordinal wooden house)
141
- 'commercial': 104, # CONCRETE building
142
- 'industrial': 104, # CONCRETE building
143
- 'default': 104 # Default to CONCRETE building
131
+ 'building': 110, # Building (general)
132
+ 'concrete': 110, # Building (concrete)
133
+ 'residential': 111, # Old wooden house
134
+ 'wooden': 111, # Old wooden house
135
+ 'commercial': 110, # Building (commercial)
136
+ 'industrial': 110, # Building (industrial)
137
+ 'default': 110 # Default to general building
144
138
  }
145
139
 
146
- # Helper to convert landuse code (1-17) to building material code (101-117)
147
- def landuse_to_building_material_code(landuse_code: int) -> int:
148
- """Map landuse code to building-material code with required adjustments.
149
-
150
- The general rule is 100 + landuse_code, except for ASPHALT classes where
151
- landuse 12 (ASPHALT without AH) maps to 113 and landuse 13 (ASPHALT) maps to 112.
152
- """
153
- # if landuse_code == 12:
154
- # return 113
155
- # if landuse_code == 13:
156
- # return 112
157
- return 100 + int(landuse_code)
158
-
159
140
  # Tree type mapping for vmap.txt
160
141
  TREE_TYPE_MAPPING = {
161
142
  'deciduous': 101, # Leaf
@@ -248,7 +229,7 @@ def export_topog(building_height_grid, building_id_grid, output_path,
248
229
  # Decide material code per cell
249
230
  if cityles_landuse_grid is not None:
250
231
  cell_lu = int(cityles_landuse_grid[j, i])
251
- material_code_cell = landuse_to_building_material_code(cell_lu)
232
+ material_code_cell = cell_lu + 100
252
233
  else:
253
234
  if height > 0:
254
235
  material_code_cell = material_code
@@ -48,6 +48,7 @@ from .downloader.oemj import save_oemj_as_geotiff
48
48
  from .downloader.eubucco import load_gdf_from_eubucco
49
49
  from .downloader.overture import load_gdf_from_overture
50
50
  from .downloader.citygml import load_buid_dem_veg_from_citygml
51
+ from .downloader.gba import load_gdf_from_gba
51
52
 
52
53
  # Google Earth Engine related imports - for satellite and elevation data
53
54
  from .downloader.gee import (
@@ -206,8 +207,9 @@ def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, b
206
207
  - list: Filtered building features
207
208
  """
208
209
 
209
- # Initialize Earth Engine for satellite-based building data sources
210
- if source not in ["OpenStreetMap", "Overture", "Local file", "GeoDataFrame"]:
210
+ # Initialize Earth Engine only for building sources that require it
211
+ ee_required_sources = {"Open Building 2.5D Temporal"}
212
+ if source in ee_required_sources:
211
213
  initialize_earth_engine()
212
214
 
213
215
  print("Creating Building Height grid\n ")
@@ -243,6 +245,11 @@ def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, b
243
245
  elif source == "Overture":
244
246
  # Open building dataset from Overture Maps Foundation
245
247
  gdf = load_gdf_from_overture(rectangle_vertices, floor_height=floor_height)
248
+ elif source in ("GBA", "Global Building Atlas"):
249
+ # Global Building Atlas LOD1 polygons (GeoParquet tiles)
250
+ clip_gba = kwargs.get("gba_clip", False)
251
+ gba_download_dir = kwargs.get("gba_download_dir")
252
+ gdf = load_gdf_from_gba(rectangle_vertices, download_dir=gba_download_dir, clip_to_rectangle=clip_gba)
246
253
  elif source == "Local file":
247
254
  # Handle user-provided local building data files
248
255
  _, extension = os.path.splitext(kwargs["building_path"])
@@ -290,6 +297,10 @@ def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, b
290
297
  # gdf_comp = load_gdf_from_openmaptiles(rectangle_vertices, kwargs["maptiler_API_key"])
291
298
  elif building_complementary_source == "Overture":
292
299
  gdf_comp = load_gdf_from_overture(rectangle_vertices, floor_height=floor_height)
300
+ elif building_complementary_source in ("GBA", "Global Building Atlas"):
301
+ clip_gba = kwargs.get("gba_clip", False)
302
+ gba_download_dir = kwargs.get("gba_download_dir")
303
+ gdf_comp = load_gdf_from_gba(rectangle_vertices, download_dir=gba_download_dir, clip_to_rectangle=clip_gba)
293
304
  elif building_complementary_source == "Local file":
294
305
  _, extension = os.path.splitext(kwargs["building_complementary_path"])
295
306
  if extension == ".gpkg":
@@ -979,6 +990,10 @@ def get_voxcity_CityGML(rectangle_vertices, land_cover_source, canopy_height_sou
979
990
  gdf_comp = load_gdf_from_eubucco(rectangle_vertices, kwargs.get("output_dir", "output"))
980
991
  elif building_complementary_source == 'Overture':
981
992
  gdf_comp = load_gdf_from_overture(rectangle_vertices, floor_height=floor_height)
993
+ elif building_complementary_source in ("GBA", "Global Building Atlas"):
994
+ clip_gba = kwargs.get("gba_clip", False)
995
+ gba_download_dir = kwargs.get("gba_download_dir")
996
+ gdf_comp = load_gdf_from_gba(rectangle_vertices, download_dir=gba_download_dir, clip_to_rectangle=clip_gba)
982
997
  elif building_complementary_source == 'Local file':
983
998
  comp_path = kwargs.get("building_complementary_path")
984
999
  if comp_path is not None:
File without changes
File without changes
File without changes