voxcity 0.6.17__py3-none-any.whl → 0.6.19__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 voxcity might be problematic. Click here for more details.

@@ -111,6 +111,7 @@ def get_voxel_color_map(color_scheme='default'):
111
111
  - 'pastel': Softer, muted colors for aesthetic appeal
112
112
  - 'dark_mode': Darker colors for dark backgrounds
113
113
  - 'grayscale': Black and white gradient with color accents
114
+ - 'white_mode': Light minimal palette for white backgrounds
114
115
 
115
116
  Thematic Schemes:
116
117
  - 'autumn': Warm reds, oranges, and browns
@@ -329,6 +330,36 @@ def get_voxel_color_map(color_scheme='default'):
329
330
  14: [230, 230, 230], # 'No Data'
330
331
  }
331
332
 
333
+ elif color_scheme == 'white_mode':
334
+ return {
335
+ -99: [0, 0, 0], # void (transparent in rendering)
336
+ -30: [220, 80, 80], # subtle highlight for landmarks
337
+ -17: [250, 250, 250], # plaster (near white)
338
+ -16: [210, 225, 235], # glass (light blue-gray)
339
+ -15: [230, 225, 215], # stone (warm light gray)
340
+ -14: [225, 230, 235], # metal (cool light gray)
341
+ -13: [236, 236, 236], # concrete (very light gray)
342
+ -12: [245, 232, 210], # wood (light beige)
343
+ -11: [235, 210, 205], # brick (light rose)
344
+ -3: [225, 230, 240], # Building (soft blue-gray)
345
+ -2: [190, 210, 190], # Tree (soft green)
346
+ -1: [230, 215, 215], # Underground (soft pinkish)
347
+ 1: [248, 245, 235], # Bareland
348
+ 2: [225, 235, 215], # Rangeland
349
+ 3: [220, 235, 220], # Shrub
350
+ 4: [240, 235, 215], # Agriculture land
351
+ 5: [210, 230, 210], # Tree (ground)
352
+ 6: [245, 250, 235], # Moss and lichen
353
+ 7: [220, 235, 230], # Wet land
354
+ 8: [205, 215, 210], # Mangrove
355
+ 9: [200, 220, 245], # Water (pale blue)
356
+ 10: [252, 252, 252], # Snow and ice (almost white)
357
+ 11: [230, 230, 230], # Developed space
358
+ 12: [210, 210, 215], # Road (light neutral)
359
+ 13: [230, 235, 240], # Building (ground surface)
360
+ 14: [248, 245, 235], # No Data
361
+ }
362
+
332
363
  elif color_scheme == 'autumn':
333
364
  return {
334
365
  -99: [0, 0, 0], # void
voxcity/utils/weather.py CHANGED
@@ -233,10 +233,15 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
233
233
  If no stations within this distance, uses closest available.
234
234
  extract_zip (bool): Whether to extract the ZIP file (default True)
235
235
  load_data (bool): Whether to load the EPW data into a DataFrame (default True)
236
- region (str or List[str], optional): Specific region(s) to scan for stations.
237
- Options: "Africa", "Asia", "Japan", "India", "Argentina",
238
- "Canada", "USA", "Caribbean", "Southwest_Pacific",
239
- "Europe", "Antarctica", or "all".
236
+ region (str or List[str], optional): Specific region(s) or dataset(s) to scan for stations.
237
+ Regions: "Africa", "Asia", "South_America",
238
+ "North_and_Central_America", "Southwest_Pacific",
239
+ "Europe", "Antarctica".
240
+ Sub-datasets (can be used alone or auto-included by region):
241
+ "Japan", "India", "CSWD", "CityUHK", "PHIKO",
242
+ "Argentina", "INMET_TRY", "AMTUes", "BrazFuture",
243
+ plus legacy "Canada", "USA", "Caribbean" (Region 4).
244
+ Use "all" to scan every dataset.
240
245
  If None, will auto-detect region based on coordinates.
241
246
 
242
247
  Returns:
@@ -250,35 +255,83 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
250
255
  requests.exceptions.RequestException: If network requests fail
251
256
  """
252
257
 
253
- # Regional KML sources from Climate.OneBuilding.Org
254
- # Each region maintains its own KML file with weather station locations and metadata
258
+ # Regional KML sources from Climate.OneBuilding.Org (2024+ TMYx structure)
259
+ # Each WMO region maintains a primary KML in /sources with the naming pattern:
260
+ # Region{N}_{Name}_TMYx_EPW_Processing_locations.kml
261
+ # Keep sub-region keys for backward compatibility (mapping to the Region KML where applicable)
255
262
  KML_SOURCES = {
256
- "Africa": "https://climate.onebuilding.org/WMO_Region_1_Africa/Region1_Africa_EPW_Processing_locations.kml",
257
- "Asia": "https://climate.onebuilding.org/WMO_Region_2_Asia/Region2_Asia_EPW_Processing_locations.kml",
263
+ # WMO Region 1
264
+ "Africa": "https://climate.onebuilding.org/sources/Region1_Africa_TMYx_EPW_Processing_locations.kml",
265
+ # WMO Region 2
266
+ "Asia": "https://climate.onebuilding.org/sources/Region2_Asia_TMYx_EPW_Processing_locations.kml",
267
+ # Subsets/datasets within Asia that still publish dedicated KMLs
258
268
  "Japan": "https://climate.onebuilding.org/sources/JGMY_EPW_Processing_locations.kml",
259
269
  "India": "https://climate.onebuilding.org/sources/ITMY_EPW_Processing_locations.kml",
270
+ "CSWD": "https://climate.onebuilding.org/sources/CSWD_EPW_Processing_locations.kml",
271
+ "CityUHK": "https://climate.onebuilding.org/sources/CityUHK_EPW_Processing_locations.kml",
272
+ "PHIKO": "https://climate.onebuilding.org/sources/PHIKO_EPW_Processing_locations.kml",
273
+ # WMO Region 3
274
+ "South_America": "https://climate.onebuilding.org/sources/Region3_South_America_TMYx_EPW_Processing_locations.kml",
275
+ # Historical/legacy dataset for Argentina maintained separately
260
276
  "Argentina": "https://climate.onebuilding.org/sources/ArgTMY_EPW_Processing_locations.kml",
277
+ "INMET_TRY": "https://climate.onebuilding.org/sources/INMET_TRY_EPW_Processing_locations.kml",
278
+ "AMTUes": "https://climate.onebuilding.org/sources/AMTUes_EPW_Processing_locations.kml",
279
+ "BrazFuture": "https://climate.onebuilding.org/sources/BrazFuture_EPW_Processing_locations.kml",
280
+ # WMO Region 4 (use subregion KMLs; umbrella selection expands to these)
281
+ # Note: There is no single unified Region 4 KML in /sources as of 2024.
282
+ # Use these three subregion KMLs instead.
261
283
  "Canada": "https://climate.onebuilding.org/sources/Region4_Canada_TMYx_EPW_Processing_locations.kml",
262
284
  "USA": "https://climate.onebuilding.org/sources/Region4_USA_TMYx_EPW_Processing_locations.kml",
263
285
  "Caribbean": "https://climate.onebuilding.org/sources/Region4_NA_CA_Caribbean_TMYx_EPW_Processing_locations.kml",
286
+ # WMO Region 5
264
287
  "Southwest_Pacific": "https://climate.onebuilding.org/sources/Region5_Southwest_Pacific_TMYx_EPW_Processing_locations.kml",
288
+ # WMO Region 6
265
289
  "Europe": "https://climate.onebuilding.org/sources/Region6_Europe_TMYx_EPW_Processing_locations.kml",
266
- "Antarctica": "https://climate.onebuilding.org/sources/Region7_Antarctica_TMYx_EPW_Processing_locations.kml"
290
+ # WMO Region 7
291
+ "Antarctica": "https://climate.onebuilding.org/sources/Region7_Antarctica_TMYx_EPW_Processing_locations.kml",
292
+ }
293
+
294
+ # Group region selections to include relevant sub-datasets automatically
295
+ REGION_DATASET_GROUPS = {
296
+ "Africa": ["Africa"],
297
+ "Asia": ["Asia", "Japan", "India", "CSWD", "CityUHK", "PHIKO"],
298
+ "South_America": ["South_America", "Argentina", "INMET_TRY", "AMTUes", "BrazFuture"],
299
+ "North_and_Central_America": ["North_and_Central_America", "Canada", "USA", "Caribbean"],
300
+ "Southwest_Pacific": ["Southwest_Pacific"],
301
+ "Europe": ["Europe"],
302
+ "Antarctica": ["Antarctica"],
267
303
  }
268
304
 
269
305
  # Define approximate geographical boundaries for automatic region detection
270
306
  # These bounds help determine which regional KML files to scan based on coordinates
271
307
  REGION_BOUNDS = {
272
- "Africa": {"lon_min": -20, "lon_max": 55, "lat_min": -35, "lat_max": 40},
273
- "Asia": {"lon_min": 25, "lon_max": 150, "lat_min": 0, "lat_max": 55},
308
+ # WMO Region 1 - Africa (includes islands in Indian Ocean and Spanish territories off N. Africa)
309
+ "Africa": {"lon_min": -25, "lon_max": 80, "lat_min": -55, "lat_max": 45},
310
+ # WMO Region 2 - Asia (includes SE Asia, West Asia, Asian Russia, and BIOT)
311
+ "Asia": {"lon_min": 20, "lon_max": 180, "lat_min": -10, "lat_max": 80},
312
+ # Subsets
274
313
  "Japan": {"lon_min": 127, "lon_max": 146, "lat_min": 24, "lat_max": 46},
275
314
  "India": {"lon_min": 68, "lon_max": 97, "lat_min": 6, "lat_max": 36},
315
+ # WMO Region 3 - South America (includes Falklands, South Georgia/Sandwich, Galapagos)
316
+ "South_America": {"lon_min": -92, "lon_max": -20, "lat_min": -60, "lat_max": 15},
317
+ # Legacy/compatibility subset
276
318
  "Argentina": {"lon_min": -75, "lon_max": -53, "lat_min": -55, "lat_max": -22},
319
+ # WMO Region 4 - North and Central America (includes Greenland and Caribbean)
320
+ "North_and_Central_America": {"lon_min": -180, "lon_max": 20, "lat_min": -10, "lat_max": 85},
321
+ # Backward-compatible subsets mapped to Region 4 KML
277
322
  "Canada": {"lon_min": -141, "lon_max": -52, "lat_min": 42, "lat_max": 83},
278
323
  "USA": {"lon_min": -170, "lon_max": -65, "lat_min": 20, "lat_max": 72},
279
324
  "Caribbean": {"lon_min": -90, "lon_max": -59, "lat_min": 10, "lat_max": 27},
280
- "Southwest_Pacific": {"lon_min": 110, "lon_max": 180, "lat_min": -50, "lat_max": 0},
281
- "Europe": {"lon_min": -25, "lon_max": 40, "lat_min": 35, "lat_max": 72},
325
+ # WMO Region 5 - Southwest Pacific (covers SE Asia + Pacific islands + Hawaii via antimeridian)
326
+ "Southwest_Pacific": {
327
+ "boxes": [
328
+ {"lon_min": 90, "lon_max": 180, "lat_min": -50, "lat_max": 25},
329
+ {"lon_min": -180, "lon_max": -140, "lat_min": -50, "lat_max": 25},
330
+ ]
331
+ },
332
+ # WMO Region 6 - Europe (includes Middle East countries listed and Greenland)
333
+ "Europe": {"lon_min": -75, "lon_max": 60, "lat_min": 25, "lat_max": 85},
334
+ # WMO Region 7 - Antarctica
282
335
  "Antarctica": {"lon_min": -180, "lon_max": 180, "lat_min": -90, "lat_max": -60}
283
336
  }
284
337
 
@@ -306,34 +359,45 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
306
359
  elif lon > 180:
307
360
  lon_adjusted = lon - 360
308
361
 
309
- # Check if coordinates fall within any region bounds
362
+ # Helper to test point within a single box
363
+ def _in_box(bx: Dict[str, float], lon_v: float, lat_v: float) -> bool:
364
+ return (bx["lon_min"] <= lon_v <= bx["lon_max"] and
365
+ bx["lat_min"] <= lat_v <= bx["lat_max"])
366
+
367
+ # Check if coordinates fall within any region bounds (support multi-box)
310
368
  for region_name, bounds in REGION_BOUNDS.items():
311
- # Check if point is within region bounds
312
- if (bounds["lon_min"] <= lon_adjusted <= bounds["lon_max"] and
313
- bounds["lat_min"] <= lat <= bounds["lat_max"]):
314
- matching_regions.append(region_name)
369
+ if "boxes" in bounds:
370
+ for bx in bounds["boxes"]:
371
+ if _in_box(bx, lon_adjusted, lat):
372
+ matching_regions.append(region_name)
373
+ break
374
+ else:
375
+ if _in_box(bounds, lon_adjusted, lat):
376
+ matching_regions.append(region_name)
315
377
 
316
378
  # If no regions matched, find the closest regions by boundary distance
317
379
  if not matching_regions:
318
380
  # Calculate "distance" to each region's boundary (simplified metric)
319
381
  region_distances = []
320
382
  for region_name, bounds in REGION_BOUNDS.items():
321
- # Calculate distance to closest edge of region bounds
322
- lon_dist = 0
323
- if lon_adjusted < bounds["lon_min"]:
324
- lon_dist = bounds["lon_min"] - lon_adjusted
325
- elif lon_adjusted > bounds["lon_max"]:
326
- lon_dist = lon_adjusted - bounds["lon_max"]
327
-
328
- lat_dist = 0
329
- if lat < bounds["lat_min"]:
330
- lat_dist = bounds["lat_min"] - lat
331
- elif lat > bounds["lat_max"]:
332
- lat_dist = lat - bounds["lat_max"]
333
-
334
- # Simple Euclidean distance metric (not actual geographic distance)
335
- distance = (lon_dist**2 + lat_dist**2)**0.5
336
- region_distances.append((region_name, distance))
383
+ def _box_distance(bx: Dict[str, float]) -> float:
384
+ lon_dist = 0
385
+ if lon_adjusted < bx["lon_min"]:
386
+ lon_dist = bx["lon_min"] - lon_adjusted
387
+ elif lon_adjusted > bx["lon_max"]:
388
+ lon_dist = lon_adjusted - bx["lon_max"]
389
+ lat_dist = 0
390
+ if lat < bx["lat_min"]:
391
+ lat_dist = bx["lat_min"] - lat
392
+ elif lat > bx["lat_max"]:
393
+ lat_dist = lat - bx["lat_max"]
394
+ return (lon_dist**2 + lat_dist**2)**0.5
395
+
396
+ if "boxes" in bounds:
397
+ d = min(_box_distance(bx) for bx in bounds["boxes"])
398
+ else:
399
+ d = _box_distance(bounds)
400
+ region_distances.append((region_name, d))
337
401
 
338
402
  # Get 3 closest regions to ensure we find stations
339
403
  closest_regions = sorted(region_distances, key=lambda x: x[1])[:3]
@@ -511,6 +575,74 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
511
575
 
512
576
  return metadata
513
577
 
578
+ def try_download_station_zip(original_url: str, timeout_s: int = 30) -> Optional[bytes]:
579
+ """
580
+ Try downloading station archive; on 404s, attempt smart fallbacks.
581
+
582
+ Fallback strategies:
583
+ - Country rename: /TUR_Turkey/ -> /TUR_Turkiye/ (per Oct 2024 site update)
584
+ - TMYx period variants: .2009-2023.zip, .2007-2021.zip, .zip, .2004-2018.zip
585
+
586
+ Args:
587
+ original_url: URL extracted from KML
588
+ timeout_s: request timeout seconds
589
+ Returns:
590
+ Bytes of the downloaded zip on success, otherwise None
591
+ """
592
+ def candidate_urls(url: str) -> List[str]:
593
+ urls = []
594
+ urls.append(url)
595
+ # Country rename variants
596
+ if "/TUR_Turkey/" in url:
597
+ urls.append(url.replace("/TUR_Turkey/", "/TUR_Turkiye/"))
598
+ if "/TUR_Turkiye/" in url:
599
+ urls.append(url.replace("/TUR_Turkiye/", "/TUR_Turkey/"))
600
+ # TMYx period variants
601
+ m = re.search(r"(.*_TMYx)(?:\.(\d{4}-\d{4}))?\.zip$", url)
602
+ if m:
603
+ base = m.group(1)
604
+ suffix = m.group(2)
605
+ variants = [
606
+ f"{base}.2009-2023.zip",
607
+ f"{base}.2007-2021.zip",
608
+ f"{base}.zip",
609
+ f"{base}.2004-2018.zip",
610
+ ]
611
+ for v in variants:
612
+ if v not in urls:
613
+ urls.append(v)
614
+ # Also apply country rename to each variant
615
+ extra = []
616
+ for v in variants:
617
+ if "/TUR_Turkey/" in url:
618
+ extra.append(v.replace("/TUR_Turkey/", "/TUR_Turkiye/"))
619
+ if "/TUR_Turkiye/" in url:
620
+ extra.append(v.replace("/TUR_Turkiye/", "/TUR_Turkey/"))
621
+ for v in extra:
622
+ if v not in urls:
623
+ urls.append(v)
624
+ return urls
625
+
626
+ tried = set()
627
+ for u in candidate_urls(original_url):
628
+ if u in tried:
629
+ continue
630
+ tried.add(u)
631
+ try:
632
+ resp = requests.get(u, timeout=timeout_s)
633
+ resp.raise_for_status()
634
+ return resp.content
635
+ except requests.exceptions.HTTPError as he:
636
+ # Only continue on 404; raise on other HTTP errors
637
+ if getattr(he.response, "status_code", None) == 404:
638
+ continue
639
+ else:
640
+ raise
641
+ except requests.exceptions.RequestException:
642
+ # On network errors, try next candidate
643
+ continue
644
+ return None
645
+
514
646
  def get_stations_from_kml(kml_url: str) -> List[Dict]:
515
647
  """
516
648
  Get weather stations from a KML file.
@@ -584,6 +716,18 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
584
716
 
585
717
  # Determine which regions to scan based on user input or auto-detection
586
718
  regions_to_scan = {}
719
+ def _add_selection(selection_name: str, mapping: Dict[str, str], out: Dict[str, str]):
720
+ """Expand a region or dataset selection into concrete KML URLs."""
721
+ if selection_name in REGION_DATASET_GROUPS:
722
+ for key in REGION_DATASET_GROUPS[selection_name]:
723
+ if key in KML_SOURCES:
724
+ out[key] = KML_SOURCES[key]
725
+ elif selection_name in KML_SOURCES:
726
+ out[selection_name] = KML_SOURCES[selection_name]
727
+ else:
728
+ valid = sorted(list(REGION_DATASET_GROUPS.keys()) + list(KML_SOURCES.keys()))
729
+ raise ValueError(f"Invalid region/dataset: '{selection_name}'. Valid options include: {', '.join(valid)}")
730
+
587
731
  if region is None:
588
732
  # Auto-detect regions based on coordinates
589
733
  detected_regions = detect_regions(longitude, latitude)
@@ -591,34 +735,32 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
591
735
  if detected_regions:
592
736
  print(f"Auto-detected regions: {', '.join(detected_regions)}")
593
737
  for r in detected_regions:
594
- regions_to_scan[r] = KML_SOURCES[r]
738
+ _add_selection(r, KML_SOURCES, regions_to_scan)
595
739
  else:
596
740
  # Fallback to all regions if detection fails
597
741
  print("Could not determine region from coordinates. Scanning all regions.")
598
- regions_to_scan = KML_SOURCES
742
+ regions_to_scan = dict(KML_SOURCES)
599
743
  elif isinstance(region, str):
600
744
  # Handle string input for region selection
601
745
  if region.lower() == "all":
602
- regions_to_scan = KML_SOURCES
603
- elif region in KML_SOURCES:
604
- regions_to_scan[region] = KML_SOURCES[region]
746
+ regions_to_scan = dict(KML_SOURCES)
605
747
  else:
606
- valid_regions = ", ".join(KML_SOURCES.keys())
607
- raise ValueError(f"Invalid region: '{region}'. Valid regions are: {valid_regions}")
748
+ _add_selection(region, KML_SOURCES, regions_to_scan)
608
749
  else:
609
750
  # Handle list input for multiple regions
610
751
  for r in region:
611
- if r not in KML_SOURCES:
612
- valid_regions = ", ".join(KML_SOURCES.keys())
613
- raise ValueError(f"Invalid region: '{r}'. Valid regions are: {valid_regions}")
614
- regions_to_scan[r] = KML_SOURCES[r]
752
+ _add_selection(r, KML_SOURCES, regions_to_scan)
615
753
 
616
754
  # Get stations from selected KML sources
617
755
  print("Fetching weather station data from Climate.OneBuilding.Org...")
618
756
  all_stations = []
619
757
 
620
758
  # Process each selected region
759
+ scanned_urls = set()
621
760
  for region_name, url in regions_to_scan.items():
761
+ if url in scanned_urls:
762
+ continue
763
+ scanned_urls.add(url)
622
764
  print(f"Scanning {region_name}...")
623
765
  stations = get_stations_from_kml(url)
624
766
  all_stations.extend(stations)
@@ -627,7 +769,23 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
627
769
  print(f"\nTotal stations found: {len(all_stations)}")
628
770
 
629
771
  if not all_stations:
630
- raise ValueError("No weather stations found")
772
+ # Fallback: if no stations found, try scanning all available datasets
773
+ if not (isinstance(region, str) and region.lower() == "all"):
774
+ print("No stations found from detected/selected regions. Falling back to global scan...")
775
+ regions_to_scan = dict(KML_SOURCES)
776
+ all_stations = []
777
+ scanned_urls = set()
778
+ for region_name, url in regions_to_scan.items():
779
+ if url in scanned_urls:
780
+ continue
781
+ scanned_urls.add(url)
782
+ print(f"Scanning {region_name}...")
783
+ stations = get_stations_from_kml(url)
784
+ all_stations.extend(stations)
785
+ print(f"Found {len(stations)} stations in {region_name}")
786
+ print(f"\nTotal stations found after global scan: {len(all_stations)}")
787
+ if not all_stations:
788
+ raise ValueError("No weather stations found")
631
789
 
632
790
  # Calculate distances from target coordinates to all stations
633
791
  stations_with_distances = [
@@ -654,10 +812,11 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
654
812
  # Find the nearest weather station
655
813
  nearest_station, distance = min(stations_with_distances, key=lambda x: x[1])
656
814
 
657
- # Download the EPW file from the nearest station
815
+ # Download the EPW archive from the nearest station with fallbacks
658
816
  print(f"\nDownloading EPW file for {nearest_station['name']}...")
659
- epw_response = requests.get(nearest_station['url'])
660
- epw_response.raise_for_status()
817
+ archive_bytes = try_download_station_zip(nearest_station['url'], timeout_s=30)
818
+ if archive_bytes is None:
819
+ raise ValueError(f"Failed to download EPW archive from station URL and fallbacks: {nearest_station['url']}")
661
820
 
662
821
  # Create a temporary directory for zip extraction
663
822
  temp_dir = Path(output_dir) / "temp"
@@ -666,7 +825,7 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
666
825
  # Save the downloaded zip file temporarily
667
826
  zip_file = temp_dir / "weather_data.zip"
668
827
  with open(zip_file, 'wb') as f:
669
- f.write(epw_response.content)
828
+ f.write(archive_bytes)
670
829
 
671
830
  final_epw = None
672
831
  try:
@@ -1,8 +1,10 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: voxcity
3
- Version: 0.6.17
3
+ Version: 0.6.19
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
+ License-File: AUTHORS.rst
7
+ License-File: LICENSE
6
8
  Author: Kunihiko Fujiwara
7
9
  Author-email: fujiwara.kunihiko@takenaka.co.jp
8
10
  Maintainer: Kunihiko Fujiwara
@@ -27,6 +29,7 @@ Requires-Dist: ipyleaflet
27
29
  Requires-Dist: joblib
28
30
  Requires-Dist: lxml
29
31
  Requires-Dist: matplotlib
32
+ Requires-Dist: netCDF4
30
33
  Requires-Dist: numba
31
34
  Requires-Dist: numpy
32
35
  Requires-Dist: osmnx
@@ -51,6 +54,7 @@ Requires-Dist: timezonefinder
51
54
  Requires-Dist: tqdm
52
55
  Requires-Dist: trimesh
53
56
  Requires-Dist: typer
57
+ Requires-Dist: xarray
54
58
  Project-URL: bugs, https://github.com/kunifujiwara/voxcity/issues
55
59
  Project-URL: changelog, https://github.com/kunifujiwara/voxcity/blob/master/changelog.md
56
60
  Project-URL: homepage, https://github.com/kunifujiwara/voxcity
@@ -232,7 +236,7 @@ Generate voxel data grids and corresponding building geoJSON:
232
236
  from voxcity.generator import get_voxcity
233
237
 
234
238
  voxcity_grid, building_height_grid, building_min_height_grid, \
235
- building_id_grid, canopy_height_grid, land_cover_grid, dem_grid, \
239
+ building_id_grid, canopy_height_grid, canopy_bottom_height_grid, land_cover_grid, dem_grid, \
236
240
  building_gdf = get_voxcity(
237
241
  rectangle_vertices,
238
242
  building_source,
@@ -8,11 +8,12 @@ voxcity/downloader/oemj.py,sha256=iDacTpiqn7RAXuqyEtHP29m0Cycwta5sMy9-GdvX3Fg,12
8
8
  voxcity/downloader/osm.py,sha256=7Wo6lSodci7gALMKLQ_0ricmn0ZrfUK90vKYQ-ayU2A,46285
9
9
  voxcity/downloader/overture.py,sha256=hVxu-3Fmuu2E1tEzcDcNyU1cR-aE-6h6jkcxkuqN1-s,13343
10
10
  voxcity/downloader/utils.py,sha256=tz6wt4B9BhEOyvoF5OYXlr8rUd5cBEDedWL3j__oT70,3099
11
- voxcity/exporter/__init__.py,sha256=dvyWJ184Eik9tFc0VviGbzTQzZi7O0JNyrqi_n39pVI,94
11
+ voxcity/exporter/__init__.py,sha256=ikmRs3jGKvYTjpleiROfiCPYlwtqxwl1T6pk8pievQw,117
12
12
  voxcity/exporter/cityles.py,sha256=Kfl2PAn4WquqCdjOlyPrHysxPLaudh8QfsoC6WAXlvs,18325
13
13
  voxcity/exporter/envimet.py,sha256=Sh7s1JdQ6SgT_L2Xd_c4gtEGWK2hTS87bccaoIqik-s,31105
14
14
  voxcity/exporter/magicavoxel.py,sha256=SfGEgTZRlossKx3Xrv9d3iKSX-HmfQJEL9lZHgWMDX4,12782
15
- voxcity/exporter/obj.py,sha256=h1_aInpemcsu96fSTwjKMqX2VZAFYbZbElWd4M1ogyI,27973
15
+ voxcity/exporter/netcdf.py,sha256=48rJ3wDsFhi9ANbElhMjXLxWMJoJzBt1gFbN0ekPp-A,7404
16
+ voxcity/exporter/obj.py,sha256=7xmVSQ_y-X8QLjNdASDPsaltGvmyW9-yAacocByYKl4,58160
16
17
  voxcity/generator.py,sha256=4WSjO09f8z3zt0tpKY0fyAfOMym1JT4VH3Tt1lOg2Bk,66900
17
18
  voxcity/geoprocessor/__init__.py,sha256=WYxcAQrjGucIvGHF0JTC6rONZzL3kCms1S2vpzS6KaU,127
18
19
  voxcity/geoprocessor/draw.py,sha256=AZMWq23wxxDJygNloCbVzWAAr1JO7nC94umf9LSxJ5o,49248
@@ -28,10 +29,10 @@ voxcity/simulator/view.py,sha256=k3FoS6gsibR-eDrTHJivJSQfvN3Tg8R8eSTeMqd9ans,939
28
29
  voxcity/utils/__init__.py,sha256=Q-NYCqYnAAaF80KuNwpqIjbE7Ec3Gr4y_khMLIMhJrg,68
29
30
  voxcity/utils/lc.py,sha256=722Gz3lPbgAp0mmTZ-g-QKBbAnbxrcgaYwb1sa7q8Sk,16189
30
31
  voxcity/utils/material.py,sha256=H8K8Lq4wBL6dQtgj7esUW2U6wLCOTeOtelkTDJoRgMo,10007
31
- voxcity/utils/visualization.py,sha256=TQKMmATpAqSDTPMvMi1a-n2CvvzE2KcYVsss7iiShS4,116877
32
- voxcity/utils/weather.py,sha256=2Jtg-rIVJcsTtiKE-KuDnhIqS1-MSS16_zFRzj6zmu4,36435
33
- voxcity-0.6.17.dist-info/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
34
- voxcity-0.6.17.dist-info/LICENSE,sha256=s_jE1Df1nTPL4A_5GCGic5Zwex0CVaPKcAmSilxJPPE,1089
35
- voxcity-0.6.17.dist-info/METADATA,sha256=pAyV4xbQG-58dQrWCWOMqcVCn1pDkhq8DXDs7SteiG8,26092
36
- voxcity-0.6.17.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
37
- voxcity-0.6.17.dist-info/RECORD,,
32
+ voxcity/utils/visualization.py,sha256=_c5WnhA0fawkseUviKEIpUUsF-M-OOLOT9FrpgQIh1A,118556
33
+ voxcity/utils/weather.py,sha256=WcmohW0yx2-uNMO5ffgxCtKUt32q6PQsAT43P5DwJx4,44760
34
+ voxcity-0.6.19.dist-info/licenses/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
35
+ voxcity-0.6.19.dist-info/licenses/LICENSE,sha256=s_jE1Df1nTPL4A_5GCGic5Zwex0CVaPKcAmSilxJPPE,1089
36
+ voxcity-0.6.19.dist-info/METADATA,sha256=AUmkbdSOZM7RywhizzSM_xzphJ-QLbQEuHx9IjvGSKQ,26212
37
+ voxcity-0.6.19.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
38
+ voxcity-0.6.19.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.3
2
+ Generator: poetry-core 2.2.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any