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.
- {voxcity-0.6.11 → voxcity-0.6.12}/PKG-INFO +1 -1
- {voxcity-0.6.11 → voxcity-0.6.12}/pyproject.toml +1 -1
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/osm.py +75 -10
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/draw.py +1085 -832
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/utils/visualization.py +14 -6
- {voxcity-0.6.11 → voxcity-0.6.12}/AUTHORS.rst +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/LICENSE +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/README.md +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/__init__.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/__init__.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/citygml.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/eubucco.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/gee.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/mbfp.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/oemj.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/overture.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/downloader/utils.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/exporter/__init__.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/exporter/cityles.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/exporter/envimet.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/exporter/magicavoxel.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/exporter/obj.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/generator.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/__init__.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/grid.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/mesh.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/network.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/polygon.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/geoprocessor/utils.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/simulator/__init__.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/simulator/solar.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/simulator/utils.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/simulator/view.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/utils/__init__.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/utils/lc.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/utils/material.py +0 -0
- {voxcity-0.6.11 → voxcity-0.6.12}/src/voxcity/utils/weather.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "voxcity"
|
|
3
|
-
version = "0.6.
|
|
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
|
-
|
|
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
|
-
|
|
417
|
-
data =
|
|
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
|
|
936
|
-
|
|
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
|
-
|
|
941
|
-
|
|
942
|
-
|
|
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...")
|