voxcity 0.3.14__tar.gz → 0.3.15__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 (52) hide show
  1. {voxcity-0.3.14 → voxcity-0.3.15}/PKG-INFO +3 -3
  2. {voxcity-0.3.14 → voxcity-0.3.15}/README.md +2 -2
  3. {voxcity-0.3.14 → voxcity-0.3.15}/pyproject.toml +1 -1
  4. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/geoprocessor/grid.py +89 -9
  5. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/utils/visualization.py +135 -0
  6. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity.egg-info/PKG-INFO +3 -3
  7. {voxcity-0.3.14 → voxcity-0.3.15}/AUTHORS.rst +0 -0
  8. {voxcity-0.3.14 → voxcity-0.3.15}/CONTRIBUTING.rst +0 -0
  9. {voxcity-0.3.14 → voxcity-0.3.15}/HISTORY.rst +0 -0
  10. {voxcity-0.3.14 → voxcity-0.3.15}/LICENSE +0 -0
  11. {voxcity-0.3.14 → voxcity-0.3.15}/MANIFEST.in +0 -0
  12. {voxcity-0.3.14 → voxcity-0.3.15}/docs/Makefile +0 -0
  13. {voxcity-0.3.14 → voxcity-0.3.15}/docs/archive/README.rst +0 -0
  14. {voxcity-0.3.14 → voxcity-0.3.15}/docs/authors.rst +0 -0
  15. {voxcity-0.3.14 → voxcity-0.3.15}/docs/conf.py +0 -0
  16. {voxcity-0.3.14 → voxcity-0.3.15}/docs/index.rst +0 -0
  17. {voxcity-0.3.14 → voxcity-0.3.15}/docs/make.bat +0 -0
  18. {voxcity-0.3.14 → voxcity-0.3.15}/setup.cfg +0 -0
  19. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/__init__.py +0 -0
  20. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/downloader/__init__.py +0 -0
  21. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/downloader/eubucco.py +0 -0
  22. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/downloader/gee.py +0 -0
  23. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/downloader/mbfp.py +0 -0
  24. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/downloader/oemj.py +0 -0
  25. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/downloader/omt.py +0 -0
  26. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/downloader/osm.py +0 -0
  27. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/downloader/overture.py +0 -0
  28. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/downloader/utils.py +0 -0
  29. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/exporter/__init_.py +0 -0
  30. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/exporter/envimet.py +0 -0
  31. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/exporter/magicavoxel.py +0 -0
  32. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/exporter/obj.py +0 -0
  33. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/generator.py +0 -0
  34. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/geoprocessor/__init_.py +0 -0
  35. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/geoprocessor/draw.py +0 -0
  36. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/geoprocessor/network.py +0 -0
  37. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/geoprocessor/polygon.py +0 -0
  38. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/geoprocessor/utils.py +0 -0
  39. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/simulator/__init_.py +0 -0
  40. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/simulator/solar.py +0 -0
  41. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/simulator/utils.py +0 -0
  42. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/simulator/view.py +0 -0
  43. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/utils/__init_.py +0 -0
  44. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/utils/lc.py +0 -0
  45. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/utils/material.py +0 -0
  46. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity/utils/weather.py +0 -0
  47. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity.egg-info/SOURCES.txt +0 -0
  48. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity.egg-info/dependency_links.txt +0 -0
  49. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity.egg-info/requires.txt +0 -0
  50. {voxcity-0.3.14 → voxcity-0.3.15}/src/voxcity.egg-info/top_level.txt +0 -0
  51. {voxcity-0.3.14 → voxcity-0.3.15}/tests/__init__.py +0 -0
  52. {voxcity-0.3.14 → voxcity-0.3.15}/tests/voxelcity.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: voxcity
3
- Version: 0.3.14
3
+ Version: 0.3.15
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>
@@ -225,7 +225,7 @@ from voxcity import get_voxcity
225
225
 
226
226
  voxcity_grid, building_height_grid, building_min_height_grid, \
227
227
  building_id_grid, canopy_height_grid, land_cover_grid, dem_grid, \
228
- building_geojson = get_voxcity(
228
+ building_gdf = get_voxcity(
229
229
  rectangle_vertices,
230
230
  building_source,
231
231
  land_cover_source,
@@ -410,7 +410,7 @@ landmark_kwargs = {
410
410
  "output_directory": "output", # Directory to save output files
411
411
  "output_file_name": "landmark_visibility" # Base filename for outputs
412
412
  }
413
- landmark_vis_map = get_landmark_visibility_map(voxcity_grid, building_id_grid, building_geojson, meshsize, **landmark_kwargs)
413
+ landmark_vis_map = get_landmark_visibility_map(voxcity_grid, building_id_grid, building_gdf, meshsize, **landmark_kwargs)
414
414
  ```
415
415
  <p align="center">
416
416
  <img src="https://raw.githubusercontent.com/kunifujiwara/VoxCity/main/images/landmark.png" alt="Landmark Visibility Map Rendered in Rhino" width="500">
@@ -167,7 +167,7 @@ from voxcity import get_voxcity
167
167
 
168
168
  voxcity_grid, building_height_grid, building_min_height_grid, \
169
169
  building_id_grid, canopy_height_grid, land_cover_grid, dem_grid, \
170
- building_geojson = get_voxcity(
170
+ building_gdf = get_voxcity(
171
171
  rectangle_vertices,
172
172
  building_source,
173
173
  land_cover_source,
@@ -352,7 +352,7 @@ landmark_kwargs = {
352
352
  "output_directory": "output", # Directory to save output files
353
353
  "output_file_name": "landmark_visibility" # Base filename for outputs
354
354
  }
355
- landmark_vis_map = get_landmark_visibility_map(voxcity_grid, building_id_grid, building_geojson, meshsize, **landmark_kwargs)
355
+ landmark_vis_map = get_landmark_visibility_map(voxcity_grid, building_id_grid, building_gdf, meshsize, **landmark_kwargs)
356
356
  ```
357
357
  <p align="center">
358
358
  <img src="https://raw.githubusercontent.com/kunifujiwara/VoxCity/main/images/landmark.png" alt="Landmark Visibility Map Rendered in Rhino" width="500">
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "voxcity"
3
- version = "0.3.14"
3
+ version = "0.3.15"
4
4
  requires-python = ">=3.10,<3.13"
5
5
  classifiers = [
6
6
  "Programming Language :: Python :: 3.10",
@@ -883,10 +883,19 @@ def grid_to_geodataframe(grid_ori, rectangle_vertices, meshsize):
883
883
 
884
884
  rows, cols = grid.shape
885
885
 
886
- # Calculate cell sizes in degrees (approximate)
887
- # 111,111 meters = 1 degree at equator
888
- cell_size_lon = meshsize / (111111 * np.cos(np.mean([min_lat, max_lat]) * np.pi / 180))
889
- cell_size_lat = meshsize / 111111
886
+ # Set up transformers for accurate coordinate calculations
887
+ wgs84 = CRS.from_epsg(4326)
888
+ web_mercator = CRS.from_epsg(3857)
889
+ transformer_to_mercator = Transformer.from_crs(wgs84, web_mercator, always_xy=True)
890
+ transformer_to_wgs84 = Transformer.from_crs(web_mercator, wgs84, always_xy=True)
891
+
892
+ # Convert bounds to Web Mercator for accurate distance calculations
893
+ min_x, min_y = transformer_to_mercator.transform(min_lon, min_lat)
894
+ max_x, max_y = transformer_to_mercator.transform(max_lon, max_lat)
895
+
896
+ # Calculate cell sizes in Web Mercator coordinates
897
+ cell_size_x = (max_x - min_x) / cols
898
+ cell_size_y = (max_y - min_y) / rows
890
899
 
891
900
  # Create lists to store data
892
901
  polygons = []
@@ -895,12 +904,16 @@ def grid_to_geodataframe(grid_ori, rectangle_vertices, meshsize):
895
904
  # Create grid cells
896
905
  for i in range(rows):
897
906
  for j in range(cols):
898
- # Calculate cell bounds
899
- cell_min_lon = min_lon + j * cell_size_lon
900
- cell_max_lon = min_lon + (j + 1) * cell_size_lon
907
+ # Calculate cell bounds in Web Mercator
908
+ cell_min_x = min_x + j * cell_size_x
909
+ cell_max_x = min_x + (j + 1) * cell_size_x
901
910
  # Flip vertical axis since grid is stored with origin at top-left
902
- cell_min_lat = max_lat - (i + 1) * cell_size_lat
903
- cell_max_lat = max_lat - i * cell_size_lat
911
+ cell_min_y = max_y - (i + 1) * cell_size_y
912
+ cell_max_y = max_y - i * cell_size_y
913
+
914
+ # Convert cell corners back to WGS84
915
+ cell_min_lon, cell_min_lat = transformer_to_wgs84.transform(cell_min_x, cell_min_y)
916
+ cell_max_lon, cell_max_lat = transformer_to_wgs84.transform(cell_max_x, cell_max_y)
904
917
 
905
918
  # Create polygon for cell
906
919
  cell_poly = box(cell_min_lon, cell_min_lat, cell_max_lon, cell_max_lat)
@@ -914,4 +927,71 @@ def grid_to_geodataframe(grid_ori, rectangle_vertices, meshsize):
914
927
  'value': values
915
928
  }, crs=CRS.from_epsg(4326))
916
929
 
930
+ return gdf
931
+
932
+ def grid_to_point_geodataframe(grid_ori, rectangle_vertices, meshsize):
933
+ """Converts a 2D grid to a GeoDataFrame with point geometries at cell centers and values.
934
+
935
+ Args:
936
+ grid: 2D numpy array containing grid values
937
+ rectangle_vertices: List of [lon, lat] coordinates defining area corners
938
+ meshsize: Size of each grid cell in meters
939
+
940
+ Returns:
941
+ GeoDataFrame with columns:
942
+ - geometry: Point geometry at center of each grid cell
943
+ - value: Value from the grid
944
+ """
945
+ grid = np.flipud(grid_ori.copy())
946
+
947
+ # Extract bounds from rectangle vertices
948
+ min_lon = min(v[0] for v in rectangle_vertices)
949
+ max_lon = max(v[0] for v in rectangle_vertices)
950
+ min_lat = min(v[1] for v in rectangle_vertices)
951
+ max_lat = max(v[1] for v in rectangle_vertices)
952
+
953
+ rows, cols = grid.shape
954
+
955
+ # Set up transformers for accurate coordinate calculations
956
+ wgs84 = CRS.from_epsg(4326)
957
+ web_mercator = CRS.from_epsg(3857)
958
+ transformer_to_mercator = Transformer.from_crs(wgs84, web_mercator, always_xy=True)
959
+ transformer_to_wgs84 = Transformer.from_crs(web_mercator, wgs84, always_xy=True)
960
+
961
+ # Convert bounds to Web Mercator for accurate distance calculations
962
+ min_x, min_y = transformer_to_mercator.transform(min_lon, min_lat)
963
+ max_x, max_y = transformer_to_mercator.transform(max_lon, max_lat)
964
+
965
+ # Calculate cell sizes in Web Mercator coordinates
966
+ cell_size_x = (max_x - min_x) / cols
967
+ cell_size_y = (max_y - min_y) / rows
968
+
969
+ # Create lists to store data
970
+ points = []
971
+ values = []
972
+
973
+ # Create grid points at cell centers
974
+ for i in range(rows):
975
+ for j in range(cols):
976
+ # Calculate cell center in Web Mercator
977
+ cell_center_x = min_x + (j + 0.5) * cell_size_x
978
+ # Flip vertical axis since grid is stored with origin at top-left
979
+ cell_center_y = max_y - (i + 0.5) * cell_size_y
980
+
981
+ # Convert cell center back to WGS84
982
+ center_lon, center_lat = transformer_to_wgs84.transform(cell_center_x, cell_center_y)
983
+
984
+ # Create point for cell center
985
+ from shapely.geometry import Point
986
+ cell_point = Point(center_lon, center_lat)
987
+
988
+ points.append(cell_point)
989
+ values.append(grid[i, j])
990
+
991
+ # Create GeoDataFrame
992
+ gdf = gpd.GeoDataFrame({
993
+ 'geometry': points,
994
+ 'value': values
995
+ }, crs=CRS.from_epsg(4326))
996
+
917
997
  return gdf
@@ -775,5 +775,140 @@ def visualize_numerical_grid_on_basemap(grid, rectangle_vertices, meshsize, valu
775
775
  # Set title and remove axes
776
776
  ax.set_axis_off()
777
777
 
778
+ plt.tight_layout()
779
+ plt.show()
780
+
781
+ def visualize_numerical_grid_gdf_on_basemap(gdf, value_name="value", cmap='viridis', vmin=None, vmax=None,
782
+ alpha=0.6, figsize=(12, 8), basemap='CartoDB light',
783
+ show_edge=False, edge_color='black', edge_width=0.5):
784
+ """Visualizes a GeoDataFrame with numerical values on a basemap.
785
+
786
+ Args:
787
+ gdf: GeoDataFrame containing grid cells with 'geometry' and 'value' columns
788
+ value_name: Name of the value column and legend label (default: "value")
789
+ cmap: Colormap to use (default: 'viridis')
790
+ vmin: Minimum value for colormap scaling (default: None)
791
+ vmax: Maximum value for colormap scaling (default: None)
792
+ alpha: Transparency of the grid overlay (default: 0.6)
793
+ figsize: Figure size in inches (default: (12, 8))
794
+ basemap: Basemap style (default: 'CartoDB light')
795
+ show_edge: Whether to show cell edges (default: False)
796
+ edge_color: Color of cell edges (default: 'black')
797
+ edge_width: Width of cell edges (default: 0.5)
798
+ """
799
+ # Convert to Web Mercator if not already in that CRS
800
+ if gdf.crs != 'EPSG:3857':
801
+ gdf_web = gdf.to_crs(epsg=3857)
802
+ else:
803
+ gdf_web = gdf
804
+
805
+ # Create figure and axis
806
+ fig, ax = plt.subplots(figsize=figsize)
807
+
808
+ # Plot the GeoDataFrame
809
+ gdf_web.plot(column='value',
810
+ ax=ax,
811
+ alpha=alpha,
812
+ cmap=cmap,
813
+ vmin=vmin,
814
+ vmax=vmax,
815
+ legend=True,
816
+ legend_kwds={'label': value_name},
817
+ edgecolor=edge_color if show_edge else 'none',
818
+ linewidth=edge_width if show_edge else 0)
819
+
820
+ # Add basemap
821
+ basemaps = {
822
+ 'CartoDB dark': ctx.providers.CartoDB.DarkMatter,
823
+ 'CartoDB light': ctx.providers.CartoDB.Positron,
824
+ 'CartoDB voyager': ctx.providers.CartoDB.Voyager,
825
+ 'CartoDB light no labels': ctx.providers.CartoDB.PositronNoLabels,
826
+ 'CartoDB dark no labels': ctx.providers.CartoDB.DarkMatterNoLabels,
827
+ }
828
+ ctx.add_basemap(ax, source=basemaps[basemap])
829
+
830
+ # Set title and remove axes
831
+ ax.set_axis_off()
832
+
833
+ plt.tight_layout()
834
+ plt.show()
835
+
836
+ def visualize_point_grid_on_basemap(point_gdf, value_name='value', **kwargs):
837
+ """Visualizes a point GeoDataFrame on a basemap with colors based on values.
838
+
839
+ Args:
840
+ point_gdf: GeoDataFrame with point geometries and values
841
+ value_name: Name of the column containing values to visualize (default: 'value')
842
+ **kwargs: Optional visualization parameters including:
843
+ - figsize: Tuple for figure size (default: (12, 8))
844
+ - colormap: Matplotlib colormap name (default: 'viridis')
845
+ - markersize: Size of points (default: 20)
846
+ - alpha: Transparency of points (default: 0.7)
847
+ - vmin: Minimum value for colormap scaling (default: None)
848
+ - vmax: Maximum value for colormap scaling (default: None)
849
+ - title: Plot title (default: None)
850
+ - basemap_style: Contextily basemap style (default: CartoDB.Positron)
851
+ - zoom: Basemap zoom level (default: 15)
852
+
853
+ Returns:
854
+ matplotlib figure and axis objects
855
+ """
856
+ import matplotlib.pyplot as plt
857
+ import contextily as ctx
858
+
859
+ # Set default parameters
860
+ defaults = {
861
+ 'figsize': (12, 8),
862
+ 'colormap': 'viridis',
863
+ 'markersize': 20,
864
+ 'alpha': 0.7,
865
+ 'vmin': None,
866
+ 'vmax': None,
867
+ 'title': None,
868
+ 'basemap_style': ctx.providers.CartoDB.Positron,
869
+ 'zoom': 15
870
+ }
871
+
872
+ # Update defaults with provided kwargs
873
+ settings = {**defaults, **kwargs}
874
+
875
+ # Create figure and axis
876
+ fig, ax = plt.subplots(figsize=settings['figsize'])
877
+
878
+ # Convert to Web Mercator for basemap compatibility
879
+ point_gdf_web = point_gdf.to_crs(epsg=3857)
880
+
881
+ # Plot points
882
+ scatter = point_gdf_web.plot(
883
+ column=value_name,
884
+ ax=ax,
885
+ cmap=settings['colormap'],
886
+ markersize=settings['markersize'],
887
+ alpha=settings['alpha'],
888
+ vmin=settings['vmin'],
889
+ vmax=settings['vmax'],
890
+ legend=True,
891
+ legend_kwds={
892
+ 'label': value_name,
893
+ 'orientation': 'vertical',
894
+ 'shrink': 0.8
895
+ }
896
+ )
897
+
898
+ # Add basemap
899
+ ctx.add_basemap(
900
+ ax,
901
+ source=settings['basemap_style'],
902
+ zoom=settings['zoom']
903
+ )
904
+
905
+ # Set title if provided
906
+ if settings['title']:
907
+ plt.title(settings['title'])
908
+
909
+ # Remove axes
910
+ ax.set_axis_off()
911
+
912
+ # Adjust layout to prevent colorbar cutoff
778
913
  plt.tight_layout()
779
914
  plt.show()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: voxcity
3
- Version: 0.3.14
3
+ Version: 0.3.15
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>
@@ -225,7 +225,7 @@ from voxcity import get_voxcity
225
225
 
226
226
  voxcity_grid, building_height_grid, building_min_height_grid, \
227
227
  building_id_grid, canopy_height_grid, land_cover_grid, dem_grid, \
228
- building_geojson = get_voxcity(
228
+ building_gdf = get_voxcity(
229
229
  rectangle_vertices,
230
230
  building_source,
231
231
  land_cover_source,
@@ -410,7 +410,7 @@ landmark_kwargs = {
410
410
  "output_directory": "output", # Directory to save output files
411
411
  "output_file_name": "landmark_visibility" # Base filename for outputs
412
412
  }
413
- landmark_vis_map = get_landmark_visibility_map(voxcity_grid, building_id_grid, building_geojson, meshsize, **landmark_kwargs)
413
+ landmark_vis_map = get_landmark_visibility_map(voxcity_grid, building_id_grid, building_gdf, meshsize, **landmark_kwargs)
414
414
  ```
415
415
  <p align="center">
416
416
  <img src="https://raw.githubusercontent.com/kunifujiwara/VoxCity/main/images/landmark.png" alt="Landmark Visibility Map Rendered in Rhino" width="500">
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes