voxcity 0.6.11__tar.gz → 0.6.12__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 (37) hide show
  1. {voxcity-0.6.11 → voxcity-0.6.12}/PKG-INFO +1 -1
  2. {voxcity-0.6.11 → voxcity-0.6.12}/pyproject.toml +1 -1
  3. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/osm.py +75 -10
  4. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/draw.py +1085 -832
  5. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/utils/visualization.py +14 -6
  6. {voxcity-0.6.11 → voxcity-0.6.12}/AUTHORS.rst +0 -0
  7. {voxcity-0.6.11 → voxcity-0.6.12}/LICENSE +0 -0
  8. {voxcity-0.6.11 → voxcity-0.6.12}/README.md +0 -0
  9. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/__init__.py +0 -0
  10. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/__init__.py +0 -0
  11. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/citygml.py +0 -0
  12. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/eubucco.py +0 -0
  13. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/gee.py +0 -0
  14. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/mbfp.py +0 -0
  15. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/oemj.py +0 -0
  16. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/overture.py +0 -0
  17. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/utils.py +0 -0
  18. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/exporter/__init__.py +0 -0
  19. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/exporter/cityles.py +0 -0
  20. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/exporter/envimet.py +0 -0
  21. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/exporter/magicavoxel.py +0 -0
  22. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/exporter/obj.py +0 -0
  23. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/generator.py +0 -0
  24. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/__init__.py +0 -0
  25. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/grid.py +0 -0
  26. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/mesh.py +0 -0
  27. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/network.py +0 -0
  28. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/polygon.py +0 -0
  29. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/utils.py +0 -0
  30. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/simulator/__init__.py +0 -0
  31. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/simulator/solar.py +0 -0
  32. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/simulator/utils.py +0 -0
  33. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/simulator/view.py +0 -0
  34. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/utils/__init__.py +0 -0
  35. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/utils/lc.py +0 -0
  36. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/utils/material.py +0 -0
  37. {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/utils/weather.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: voxcity
3
- Version: 0.6.11
3
+ Version: 0.6.12
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
  Author: Kunihiko Fujiwara
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "voxcity"
3
- version = "0.6.11"
3
+ version = "0.6.12"
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"
@@ -398,7 +398,12 @@ def load_gdf_from_openstreetmap(rectangle_vertices):
398
398
  max_lat = max(v[1] for v in rectangle_vertices)
399
399
 
400
400
  # Enhanced Overpass API query with recursive member extraction
401
- overpass_url = "http://overpass-api.de/api/interpreter"
401
+ # Try multiple Overpass endpoints to improve resiliency against rate limits or outages
402
+ overpass_endpoints = [
403
+ "https://overpass-api.de/api/interpreter",
404
+ "https://overpass.kumi.systems/api/interpreter",
405
+ "https://overpass.openstreetmap.ru/api/interpreter",
406
+ ]
402
407
  overpass_query = f"""
403
408
  [out:json];
404
409
  (
@@ -412,9 +417,40 @@ def load_gdf_from_openstreetmap(rectangle_vertices):
412
417
  out geom;
413
418
  """
414
419
 
415
- # Send the request to the Overpass API
416
- response = requests.get(overpass_url, params={'data': overpass_query})
417
- data = response.json()
420
+ # Send the request to the Overpass API with fallbacks and robust JSON handling
421
+ headers = {"User-Agent": "voxcity/ci (https://github.com/voxcity)"}
422
+ data = None
423
+ last_error = None
424
+ for overpass_url in overpass_endpoints:
425
+ try:
426
+ response = requests.get(overpass_url, params={"data": overpass_query}, headers=headers, timeout=30)
427
+ # Ensure HTTP OK
428
+ if response.status_code != 200:
429
+ last_error = Exception(f"HTTP {response.status_code} from {overpass_url}")
430
+ continue
431
+ # Some servers return HTML/plain text on rate-limit; guard JSON parsing
432
+ content_type = response.headers.get("Content-Type", "")
433
+ if "json" not in content_type.lower():
434
+ # Attempt JSON anyway; if fails, try next endpoint
435
+ try:
436
+ data = response.json()
437
+ except Exception as e:
438
+ last_error = e
439
+ continue
440
+ else:
441
+ data = response.json()
442
+ # Validate structure
443
+ if not isinstance(data, dict) or "elements" not in data:
444
+ last_error = Exception(f"Malformed Overpass response from {overpass_url}")
445
+ data = None
446
+ continue
447
+ # Success
448
+ break
449
+ except Exception as e:
450
+ last_error = e
451
+ continue
452
+ if data is None:
453
+ raise RuntimeError(f"Failed to fetch OSM data from Overpass endpoints. Last error: {last_error}")
418
454
 
419
455
  # Build a mapping from (type, id) to element
420
456
  id_map = {}
@@ -932,14 +968,43 @@ def load_land_cover_gdf_from_osm(rectangle_vertices_ori):
932
968
  "out skel qt;"
933
969
  )
934
970
 
935
- # Overpass API endpoint
936
- overpass_url = "http://overpass-api.de/api/interpreter"
971
+ # Overpass API endpoints (fallbacks)
972
+ overpass_endpoints = [
973
+ "https://overpass-api.de/api/interpreter",
974
+ "https://overpass.kumi.systems/api/interpreter",
975
+ "https://overpass.openstreetmap.ru/api/interpreter",
976
+ ]
937
977
 
938
- # Fetch data from Overpass API
978
+ # Fetch data from Overpass API with fallbacks and robust JSON handling
939
979
  print("Fetching data from Overpass API...")
940
- response = requests.get(overpass_url, params={'data': query})
941
- response.raise_for_status()
942
- data = response.json()
980
+ headers = {"User-Agent": "voxcity/ci (https://github.com/voxcity)"}
981
+ data = None
982
+ last_error = None
983
+ for overpass_url in overpass_endpoints:
984
+ try:
985
+ response = requests.get(overpass_url, params={'data': query}, headers=headers, timeout=30)
986
+ if response.status_code != 200:
987
+ last_error = Exception(f"HTTP {response.status_code} from {overpass_url}")
988
+ continue
989
+ content_type = response.headers.get("Content-Type", "")
990
+ if "json" not in content_type.lower():
991
+ try:
992
+ data = response.json()
993
+ except Exception as e:
994
+ last_error = e
995
+ continue
996
+ else:
997
+ data = response.json()
998
+ if not isinstance(data, dict) or 'elements' not in data:
999
+ last_error = Exception(f"Malformed Overpass response from {overpass_url}")
1000
+ data = None
1001
+ continue
1002
+ break
1003
+ except Exception as e:
1004
+ last_error = e
1005
+ continue
1006
+ if data is None:
1007
+ raise RuntimeError(f"Failed to fetch OSM data from Overpass endpoints. Last error: {last_error}")
943
1008
 
944
1009
  # Convert OSM data to GeoJSON format using our custom converter instead of json2geojson
945
1010
  print("Converting data to GeoJSON format...")