voxcity 0.5.21__py3-none-any.whl → 0.5.23__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.

@@ -386,12 +386,17 @@ def create_xml_content(building_height_grid, building_id_grid, land_cover_veg_gr
386
386
  r = (100 + verticalStretch) / 100 # Growth ratio
387
387
  S_target = (int(np.max(building_on_dem_grid)/meshsize + 0.5) * meshsize) * (domain_building_max_height_ratio - 1)
388
388
  min_n = find_min_n(a, r, S_target, max_n=1000000)
389
- grids_Z_tent = int(np.max(building_on_dem_grid)/meshsize + 0.5) + min_n
390
- if grids_Z_tent < min_grids_Z:
391
- grids_Z = min_grids_Z
392
- startStretch += (min_grids_Z - grids_Z)
389
+ if min_n is None:
390
+ # Fallback to non-telescoping grid if calculation fails
391
+ print("Warning: Telescoping grid calculation failed, using uniform grid")
392
+ grids_Z = max(int(np.max(building_on_dem_grid)/meshsize + 0.5) * domain_building_max_height_ratio, min_grids_Z)
393
393
  else:
394
- grids_Z = grids_Z_tent
394
+ grids_Z_tent = int(np.max(building_on_dem_grid)/meshsize + 0.5) + min_n
395
+ if grids_Z_tent < min_grids_Z:
396
+ grids_Z = min_grids_Z
397
+ startStretch += (min_grids_Z - grids_Z)
398
+ else:
399
+ grids_Z = grids_Z_tent
395
400
  else:
396
401
  # Calculate vertical grid cells without telescoping
397
402
  grids_Z = max(int(np.max(building_on_dem_grid)/meshsize + 0.5) * domain_building_max_height_ratio, min_grids_Z)
@@ -524,7 +524,7 @@ def get_city_country_name_from_rectangle(coordinates):
524
524
  center_coord = (center_lat, center_lon)
525
525
 
526
526
  # Initialize geocoder with rate limiting to avoid hitting API limits
527
- geolocator = Nominatim(user_agent="VoxCity/1.0 (voxcity@example.com)")
527
+ geolocator = Nominatim(user_agent="your_app_name (your_email@example.com)")
528
528
  reverse = RateLimiter(geolocator.reverse, min_delay_seconds=2, error_wait_seconds=5, max_retries=3)
529
529
 
530
530
  try:
@@ -537,11 +537,10 @@ def get_city_country_name_from_rectangle(coordinates):
537
537
  country = address.get('country', '')
538
538
  return f"{city}/ {country}"
539
539
  else:
540
- print("Location not found, using fallback value")
540
+ print("Location not found")
541
541
  return "Unknown Location/ Unknown Country"
542
542
  except Exception as e:
543
543
  print(f"Error retrieving location for {center_coord}: {e}")
544
- print("Using fallback value")
545
544
  return "Unknown Location/ Unknown Country"
546
545
 
547
546
  def get_timezone_info(rectangle_coords):
@@ -573,39 +572,27 @@ def get_timezone_info(rectangle_coords):
573
572
  center_lon = sum(longitudes) / len(longitudes)
574
573
  center_lat = sum(latitudes) / len(latitudes)
575
574
 
576
- try:
577
- # Find timezone at center coordinates
578
- tf = TimezoneFinder()
579
- timezone_str = tf.timezone_at(lng=center_lon, lat=center_lat)
580
-
581
- if timezone_str:
582
- # Get current time in local timezone to calculate offset
583
- timezone = pytz.timezone(timezone_str)
584
- now = datetime.now(timezone)
585
- offset_seconds = now.utcoffset().total_seconds()
586
- offset_hours = offset_seconds / 3600
587
-
588
- # Format timezone offset and calculate central meridian
589
- utc_offset = f"UTC{offset_hours:+.2f}"
590
- timezone_longitude = offset_hours * 15 # Each hour offset = 15 degrees longitude
591
- timezone_longitude_str = f"{timezone_longitude:.5f}"
592
-
593
- return utc_offset, timezone_longitude_str
594
- else:
595
- # Fallback: estimate timezone from longitude
596
- print("Timezone not found, estimating from longitude")
597
- estimated_offset = center_lon / 15 # Rough estimation: 15 degrees per hour
598
- utc_offset = f"UTC{estimated_offset:+.2f}"
599
- timezone_longitude_str = f"{center_lon:.5f}"
600
- return utc_offset, timezone_longitude_str
601
- except Exception as e:
602
- print(f"Error retrieving timezone for {center_lon}, {center_lat}: {e}")
603
- print("Using fallback timezone values")
604
- # Fallback values
605
- estimated_offset = center_lon / 15
606
- utc_offset = f"UTC{estimated_offset:+.2f}"
607
- timezone_longitude_str = f"{center_lon:.5f}"
575
+ # Find timezone at center coordinates
576
+ tf = TimezoneFinder()
577
+ timezone_str = tf.timezone_at(lng=center_lon, lat=center_lat)
578
+
579
+ if timezone_str:
580
+ # Get current time in local timezone to calculate offset
581
+ timezone = pytz.timezone(timezone_str)
582
+ now = datetime.now(timezone)
583
+ offset_seconds = now.utcoffset().total_seconds()
584
+ offset_hours = offset_seconds / 3600
585
+
586
+ # Format timezone offset and calculate central meridian
587
+ utc_offset = f"UTC{offset_hours:+.2f}"
588
+ timezone_longitude = offset_hours * 15 # Each hour offset = 15 degrees longitude
589
+ timezone_longitude_str = f"{timezone_longitude:.5f}"
590
+
608
591
  return utc_offset, timezone_longitude_str
592
+ else:
593
+ # Return fallback values if timezone cannot be determined
594
+ print("Warning: Timezone not found for the given location, using UTC+00:00")
595
+ return "UTC+00:00", "0.00000"
609
596
 
610
597
  def validate_polygon_coordinates(geometry):
611
598
  """
@@ -1341,11 +1341,12 @@ def get_building_solar_irradiance(
1341
1341
  # # Optional OBJ export
1342
1342
  # obj_export = kwargs.get("obj_export", False)
1343
1343
  # if obj_export:
1344
- # _export_solar_irradiance_mesh(
1345
- # irradiance_mesh,
1346
- # face_global,
1347
- # **kwargs
1348
- # )
1344
+ # # Get export parameters
1345
+ # output_dir = kwargs.get("output_directory", "output")
1346
+ # output_file_name = kwargs.get("output_file_name", "solar_irradiance")
1347
+
1348
+ # # Export the mesh directly
1349
+ # irradiance_mesh.export(f"{output_dir}/{output_file_name}.obj")
1349
1350
 
1350
1351
  return irradiance_mesh
1351
1352
 
@@ -1426,6 +1427,8 @@ def get_cumulative_building_solar_irradiance(
1426
1427
  face_cum_global = np.zeros(n_faces, dtype=np.float64)
1427
1428
 
1428
1429
  boundary_mask = None
1430
+ instant_kwargs = kwargs.copy()
1431
+ instant_kwargs['obj_export'] = False
1429
1432
 
1430
1433
  # Iterate over each timestep
1431
1434
  for idx, (time_utc, row) in enumerate(df_period_utc.iterrows()):
@@ -1450,7 +1453,7 @@ def get_cumulative_building_solar_irradiance(
1450
1453
  DNI,
1451
1454
  DHI,
1452
1455
  show_plot=False, # or any other flags
1453
- **kwargs
1456
+ **instant_kwargs
1454
1457
  )
1455
1458
 
1456
1459
  # Extract arrays
@@ -1488,14 +1491,15 @@ def get_cumulative_building_solar_irradiance(
1488
1491
 
1489
1492
  cumulative_mesh.name = "Cumulative Solar Irradiance (Wh/m²)"
1490
1493
 
1491
- # Optional export
1494
+ # # Optional OBJ export
1492
1495
  # obj_export = kwargs.get("obj_export", False)
1493
1496
  # if obj_export:
1494
- # _export_solar_irradiance_mesh(
1495
- # cumulative_mesh,
1496
- # face_cum_global,
1497
- # **kwargs
1498
- # )
1497
+ # # Get export parameters
1498
+ # output_dir = kwargs.get("output_directory", "output")
1499
+ # output_file_name = kwargs.get("output_file_name", "solar_irradiance")
1500
+
1501
+ # # Export the mesh directly
1502
+ # irradiance_mesh.export(f"{output_dir}/{output_file_name}.obj")
1499
1503
 
1500
1504
  return cumulative_mesh
1501
1505
 
@@ -2069,11 +2069,18 @@ def visualize_voxcity_multi_view(voxel_array, meshsize, **kwargs):
2069
2069
  plt.tight_layout()
2070
2070
  plt.show()
2071
2071
 
2072
- # Export mesh files if requested
2073
- if base_filename is not None:
2074
- print(f"Exporting files to '{base_filename}.*' ...")
2075
- os.makedirs(output_directory, exist_ok=True)
2076
- export_meshes(meshes, output_directory, base_filename)
2072
+ # # Export mesh files if requested
2073
+ # if base_filename is not None:
2074
+ # print(f"Exporting files to '{base_filename}.*' ...")
2075
+ # os.makedirs(output_directory, exist_ok=True)
2076
+ # export_meshes(meshes, output_directory, base_filename)
2077
+
2078
+ # Export OBJ mesh files if requested
2079
+ if save_obj:
2080
+ output_directory = kwargs.get('output_directory', 'output')
2081
+ output_file_name = kwargs.get('output_file_name', 'voxcity_mesh')
2082
+ obj_path, mtl_path = save_obj_from_colored_mesh(meshes, output_directory, output_file_name)
2083
+ print(f"Saved mesh files to:\n {obj_path}\n {mtl_path}")
2077
2084
 
2078
2085
  # Generate and display multiple camera views
2079
2086
  if show_views:
@@ -2091,13 +2098,6 @@ def visualize_voxcity_multi_view(voxel_array, meshsize, **kwargs):
2091
2098
  plt.show()
2092
2099
  plt.close()
2093
2100
 
2094
- # Export OBJ mesh files if requested
2095
- if save_obj:
2096
- output_directory = kwargs.get('output_directory', 'output')
2097
- output_file_name = kwargs.get('output_file_name', 'voxcity_mesh')
2098
- obj_path, mtl_path = save_obj_from_colored_mesh(meshes, output_directory, output_file_name)
2099
- print(f"Saved mesh files to:\n {obj_path}\n {mtl_path}")
2100
-
2101
2101
  def visualize_voxcity_multi_view_with_multiple_sim_grids(voxel_array, meshsize, sim_configs, **kwargs):
2102
2102
  """
2103
2103
  Create multiple views of the voxel city data with multiple simulation grids.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voxcity
3
- Version: 0.5.21
3
+ Version: 0.5.23
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>
@@ -64,10 +64,11 @@ Dynamic: license-file
64
64
  [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1Lofd3RawKMr6QuUsamGaF48u2MN0hfrP?usp=sharing)
65
65
  [![License](https://img.shields.io/pypi/l/voxcity.svg)](https://pypi.org/project/voxcity/)
66
66
  [![Downloads](https://pepy.tech/badge/voxcity)](https://pepy.tech/project/voxcity)
67
+ [![Documentation Status](https://readthedocs.org/projects/voxcity/badge/?version=latest)](https://voxcity.readthedocs.io/en/latest/?badge=latest)
67
68
  <!-- [![License: CC BY-SA 4.0](https://licensebuttons.net/l/by-sa/4.0/80x15.png)](https://creativecommons.org/licenses/by-sa/4.0/) -->
68
69
 
69
70
  <p align="center">
70
- Tutorial preview: <a href="https://colab.research.google.com/drive/1Lofd3RawKMr6QuUsamGaF48u2MN0hfrP?usp=sharing">[Google Colab]</a>
71
+ Tutorial preview: <a href="https://colab.research.google.com/drive/1Lofd3RawKMr6QuUsamGaF48u2MN0hfrP?usp=sharing">[Google Colab]</a> | Documentation: <a href="https://voxcity.readthedocs.io/en/latest">[Read the Docs]</a>
71
72
  </p>
72
73
 
73
74
  <p align="center">
@@ -76,7 +77,7 @@ Dynamic: license-file
76
77
 
77
78
  # VoxCity
78
79
 
79
- **voxcity** is a Python package that provides a seamless solution for grid-based 3D city model generation and urban simulation for cities worldwide. VoxCity's generator module automatically downloads building heights, tree canopy heights, land cover, and terrain elevation within a specified target area, and voxelizes buildings, trees, land cover, and terrain to generate an integrated voxel city model. The simulator module enables users to conduct environmental simulations, including solar radiation and view index analyses. Users can export the generated models using several file formats compatible with external software, such as ENVI-met (INX), Blender, and Rhino (OBJ). Try it out using the [Google Colab Demo](https://colab.research.google.com/drive/1Lofd3RawKMr6QuUsamGaF48u2MN0hfrP?usp=sharing) or your local environment.
80
+ **voxcity** is a Python package that provides a seamless solution for grid-based 3D city model generation and urban simulation for cities worldwide. VoxCity's generator module automatically downloads building heights, tree canopy heights, land cover, and terrain elevation within a specified target area, and voxelizes buildings, trees, land cover, and terrain to generate an integrated voxel city model. The simulator module enables users to conduct environmental simulations, including solar radiation and view index analyses. Users can export the generated models using several file formats compatible with external software, such as ENVI-met (INX), Blender, and Rhino (OBJ). Try it out using the [Google Colab Demo](https://colab.research.google.com/drive/1Lofd3RawKMr6QuUsamGaF48u2MN0hfrP?usp=sharing) or your local environment. For detailed documentation, API reference, and tutorials, visit our [Read the Docs](https://voxcity.readthedocs.io/en/latest) page.
80
81
 
81
82
  <!-- <p align="center">
82
83
  <picture>
@@ -10,7 +10,7 @@ voxcity/downloader/osm.py,sha256=kXiUedT7dwPOQ_4nxXptfeqNb5RKTIsQLG5km7Q8kKk,416
10
10
  voxcity/downloader/overture.py,sha256=4YG2DMwUSSyZKUw_o8cGhMmAkPJon82aPqOFBvrre-Y,11987
11
11
  voxcity/downloader/utils.py,sha256=tz6wt4B9BhEOyvoF5OYXlr8rUd5cBEDedWL3j__oT70,3099
12
12
  voxcity/exporter/__init__.py,sha256=2htEXMrq6knO8JMROtfz-0HFGddsAJkXqNUB2_MhqvM,70
13
- voxcity/exporter/envimet.py,sha256=Esi7SmidEyaRvSLOUgS-o9lcjJlhbp_D-ZdXa-BMrGU,30746
13
+ voxcity/exporter/envimet.py,sha256=un8Ay55XttGWFkFzkxLymHoRuA-UJkowQ4bMCjod_Jk,31093
14
14
  voxcity/exporter/magicavoxel.py,sha256=SfGEgTZRlossKx3Xrv9d3iKSX-HmfQJEL9lZHgWMDX4,12782
15
15
  voxcity/exporter/obj.py,sha256=h1_aInpemcsu96fSTwjKMqX2VZAFYbZbElWd4M1ogyI,27973
16
16
  voxcity/geoprocessor/__init__.py,sha256=JzPVhhttxBWvaZ0IGX2w7OWL5bCo_TIvpHefWeNXruA,133
@@ -19,19 +19,19 @@ voxcity/geoprocessor/grid.py,sha256=Uy8Oz4iL7vnPMqp_qtp4dQrs00yd2L9CSIPmF5KnbtI,
19
19
  voxcity/geoprocessor/mesh.py,sha256=MK2rkBfVyLQ_nkhgLMa6R3_SxYFE2-MHaSiRP6bJ7no,28584
20
20
  voxcity/geoprocessor/network.py,sha256=YynqR0nq_NUra_cQ3Z_56KxfRia1b6-hIzGCj3QT-wE,25137
21
21
  voxcity/geoprocessor/polygon.py,sha256=-LonxtW5du3UP61oygqtDJl6GGsCYnUuN9KYwl1UFdc,53707
22
- voxcity/geoprocessor/utils.py,sha256=yt9mGm3_AefXTlQ5LWqhm5WQTSHr0XbD7GbkvpSMCGs,31077
22
+ voxcity/geoprocessor/utils.py,sha256=DVg3EMRytLQLEQeXLvNgjt1Ynoa689EsD-To-14xgSQ,30369
23
23
  voxcity/simulator/__init__.py,sha256=APdkcdaovj0v_RPOaA4SBvFUKT2RM7Hxuuz3Sux4gCo,65
24
- voxcity/simulator/solar.py,sha256=HUvSm7IHOpU8JyF6rib54LXBijoWaWM87dKYGeC_BxA,82298
24
+ voxcity/simulator/solar.py,sha256=t7zOSxBObQMuWvQSiHN9AViJstzfkXqAg3BpIppn0KA,82694
25
25
  voxcity/simulator/utils.py,sha256=sEYBB2-hLJxTiXQps1_-Fi7t1HN3-1OPOvBCWtgIisA,130
26
26
  voxcity/simulator/view.py,sha256=F2c-XFdRN811_RJvsznRjbUu5Uv7C6iniezsUMD-Olw,59419
27
27
  voxcity/utils/__init__.py,sha256=Q-NYCqYnAAaF80KuNwpqIjbE7Ec3Gr4y_khMLIMhJrg,68
28
28
  voxcity/utils/lc.py,sha256=h2yOWLUIrrummkyMyhRK5VbyrsPtslS0MJov_y0WGIQ,18925
29
29
  voxcity/utils/material.py,sha256=H8K8Lq4wBL6dQtgj7esUW2U6wLCOTeOtelkTDJoRgMo,10007
30
- voxcity/utils/visualization.py,sha256=-Hc9XJbAppI0CB_Sfrlv0kLnJGRBdY2u8g0jdCPYT7w,112803
30
+ voxcity/utils/visualization.py,sha256=QWeWaIXFqOnUZT6TF2Boctz8v9xQoz-GZS3f0E7LmqA,112813
31
31
  voxcity/utils/weather.py,sha256=2Jtg-rIVJcsTtiKE-KuDnhIqS1-MSS16_zFRzj6zmu4,36435
32
- voxcity-0.5.21.dist-info/licenses/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
33
- voxcity-0.5.21.dist-info/licenses/LICENSE,sha256=s_jE1Df1nTPL4A_5GCGic5Zwex0CVaPKcAmSilxJPPE,1089
34
- voxcity-0.5.21.dist-info/METADATA,sha256=nhmsreM885ktO6XCBJQoSw60lbvcWK-ywcWbHYovJxg,26328
35
- voxcity-0.5.21.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
- voxcity-0.5.21.dist-info/top_level.txt,sha256=00b2U-LKfDllt6RL1R33MXie5MvxzUFye0NGD96t_8I,8
37
- voxcity-0.5.21.dist-info/RECORD,,
32
+ voxcity-0.5.23.dist-info/licenses/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
33
+ voxcity-0.5.23.dist-info/licenses/LICENSE,sha256=s_jE1Df1nTPL4A_5GCGic5Zwex0CVaPKcAmSilxJPPE,1089
34
+ voxcity-0.5.23.dist-info/METADATA,sha256=qYB15e8LlRWQ9aOsUxH9UUIHHXnwhpx1dkTA6AmC5pQ,26695
35
+ voxcity-0.5.23.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
+ voxcity-0.5.23.dist-info/top_level.txt,sha256=00b2U-LKfDllt6RL1R33MXie5MvxzUFye0NGD96t_8I,8
37
+ voxcity-0.5.23.dist-info/RECORD,,