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

voxcity/generator.py CHANGED
@@ -82,7 +82,7 @@ def get_land_cover_grid(rectangle_vertices, meshsize, source, output_dir, **kwar
82
82
  print(f"Data source: {source}")
83
83
 
84
84
  # Initialize Earth Engine for accessing satellite data
85
- if source is not "OpenStreetMap":
85
+ if source != "OpenStreetMap":
86
86
  initialize_earth_engine()
87
87
 
88
88
  # Create output directory if it doesn't exist
@@ -158,7 +158,7 @@ def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, *
158
158
  """
159
159
 
160
160
  # Initialize Earth Engine for accessing satellite data
161
- if source is not "OpenStreetMap":
161
+ if source not in ["OpenStreetMap", "Overture", "Local file"]:
162
162
  initialize_earth_engine()
163
163
 
164
164
  print("Creating Building Height grid\n ")
@@ -236,7 +236,9 @@ def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, *
236
236
  # Visualize grid if requested
237
237
  grid_vis = kwargs.get("gridvis", True)
238
238
  if grid_vis:
239
- visualize_numerical_grid(np.flipud(building_height_grid), meshsize, "building height (m)", cmap='viridis', label='Value')
239
+ building_height_grid_nan = building_height_grid.copy()
240
+ building_height_grid_nan[building_height_grid_nan == 0] = np.nan
241
+ visualize_numerical_grid(np.flipud(building_height_grid_nan), meshsize, "building height (m)", cmap='viridis', label='Value')
240
242
 
241
243
  return building_height_grid, building_min_height_grid, building_id_grid, filtered_buildings
242
244
 
@@ -282,7 +284,9 @@ def get_canopy_height_grid(rectangle_vertices, meshsize, source, output_dir, **k
282
284
  # Visualize grid if requested
283
285
  grid_vis = kwargs.get("gridvis", True)
284
286
  if grid_vis:
285
- visualize_numerical_grid(np.flipud(canopy_height_grid), meshsize, "Tree canopy height", cmap='Greens', label='Tree canopy height (m)')
287
+ canopy_height_grid_nan = canopy_height_grid.copy()
288
+ canopy_height_grid_nan[canopy_height_grid_nan == 0] = np.nan
289
+ visualize_numerical_grid(np.flipud(canopy_height_grid_nan), meshsize, "Tree canopy height", cmap='Greens', label='Tree canopy height (m)')
286
290
 
287
291
  return canopy_height_grid
288
292
 
@@ -156,7 +156,7 @@ def extract_building_heights_from_gdf(gdf_0: gpd.GeoDataFrame, gdf_1: gpd.GeoDat
156
156
 
157
157
  # Process each building in primary dataset that needs height data
158
158
  for idx_primary, row in gdf_primary.iterrows():
159
- if row['height'] == 0:
159
+ if row['height'] <= 0 or pd.isna(row['height']):
160
160
  count_0 += 1
161
161
  geom = row.geometry
162
162
 
@@ -619,7 +619,7 @@ def extract_building_heights_from_geotiff(geotiff_path, gdf):
619
619
  transformer = Transformer.from_crs(CRS.from_epsg(4326), src.crs, always_xy=True)
620
620
 
621
621
  # Filter buildings that need height processing
622
- mask_condition = (gdf.geometry.geom_type == 'Polygon') & (gdf.get('height', 0) <= 0)
622
+ mask_condition = (gdf.geometry.geom_type == 'Polygon') & ((gdf.get('height', 0) <= 0) | gdf.get('height').isna())
623
623
  buildings_to_process = gdf[mask_condition]
624
624
  count_0 = len(buildings_to_process)
625
625
 
@@ -815,14 +815,24 @@ def process_building_footprints_by_overlap(filtered_gdf, overlap_threshold=0.5):
815
815
  if 'id' not in gdf.columns:
816
816
  gdf['id'] = gdf.index
817
817
 
818
- # Calculate areas and sort by area (descending)
819
- gdf['area'] = gdf.geometry.area
820
- gdf = gdf.sort_values(by='area', ascending=False)
821
- gdf = gdf.reset_index(drop=True)
818
+ # Check if CRS is set before transforming
819
+ if gdf.crs is None:
820
+ # Work with original geometries if no CRS is set
821
+ gdf_projected = gdf.copy()
822
+ else:
823
+ # Store original CRS to convert back later
824
+ original_crs = gdf.crs
825
+ # Project to Web Mercator for accurate area calculation
826
+ gdf_projected = gdf.to_crs("EPSG:3857")
827
+
828
+ # Calculate areas on the geometries
829
+ gdf_projected['area'] = gdf_projected.geometry.area
830
+ gdf_projected = gdf_projected.sort_values(by='area', ascending=False)
831
+ gdf_projected = gdf_projected.reset_index(drop=True)
822
832
 
823
833
  # Create spatial index for efficient querying
824
834
  spatial_idx = index.Index()
825
- for i, geom in enumerate(gdf.geometry):
835
+ for i, geom in enumerate(gdf_projected.geometry):
826
836
  if geom.is_valid:
827
837
  spatial_idx.insert(i, geom.bounds)
828
838
  else:
@@ -835,10 +845,10 @@ def process_building_footprints_by_overlap(filtered_gdf, overlap_threshold=0.5):
835
845
  id_mapping = {}
836
846
 
837
847
  # Process each building (skip the largest one)
838
- for i in range(1, len(gdf)):
839
- current_poly = gdf.iloc[i].geometry
840
- current_area = gdf.iloc[i].area
841
- current_id = gdf.iloc[i]['id']
848
+ for i in range(1, len(gdf_projected)):
849
+ current_poly = gdf_projected.iloc[i].geometry
850
+ current_area = gdf_projected.iloc[i].area
851
+ current_id = gdf_projected.iloc[i]['id']
842
852
 
843
853
  # Skip if already mapped
844
854
  if current_id in id_mapping:
@@ -854,8 +864,8 @@ def process_building_footprints_by_overlap(filtered_gdf, overlap_threshold=0.5):
854
864
  potential_overlaps = [j for j in spatial_idx.intersection(current_poly.bounds) if j < i]
855
865
 
856
866
  for j in potential_overlaps:
857
- larger_poly = gdf.iloc[j].geometry
858
- larger_id = gdf.iloc[j]['id']
867
+ larger_poly = gdf_projected.iloc[j].geometry
868
+ larger_id = gdf_projected.iloc[j]['id']
859
869
 
860
870
  # Skip if already processed
861
871
  if larger_id in id_mapping:
@@ -876,7 +886,7 @@ def process_building_footprints_by_overlap(filtered_gdf, overlap_threshold=0.5):
876
886
  # Replace ID if overlap exceeds threshold
877
887
  if overlap_ratio > overlap_threshold:
878
888
  id_mapping[current_id] = larger_id
879
- gdf.at[i, 'id'] = larger_id
889
+ gdf_projected.at[i, 'id'] = larger_id
880
890
  break # Stop at first significant overlap
881
891
  except (GEOSException, ValueError) as e:
882
892
  # Handle geometry errors gracefully
@@ -1450,7 +1450,7 @@ def create_multi_view_scene(meshes, output_directory="output", projection_type="
1450
1450
 
1451
1451
  # Add orthographic views
1452
1452
  ortho_views = {
1453
- 'xy_top': [center + np.array([0, 0, distance]), center, (0, 1, 0)],
1453
+ 'xy_top': [center + np.array([0, 0, distance]), center, (-1, 0, 0)],
1454
1454
  'yz_right': [center + np.array([distance, 0, 0]), center, (0, 0, 1)],
1455
1455
  'xz_front': [center + np.array([0, distance, 0]), center, (0, 0, 1)],
1456
1456
  'yz_left': [center + np.array([-distance, 0, 0]), center, (0, 0, 1)],
@@ -1787,7 +1787,7 @@ def visualize_voxcity_with_sim_meshes(voxel_array, meshsize, custom_meshes=None,
1787
1787
  # Set vmin/vmax if not provided
1788
1788
  local_vmin = vmin if vmin is not None else np.nanmin(values[~np.isnan(values)])
1789
1789
  local_vmax = vmax if vmax is not None else np.nanmax(values[~np.isnan(values)])
1790
-
1790
+
1791
1791
  # Create colors
1792
1792
  cmap = cm.get_cmap(cmap_name)
1793
1793
  norm = mcolors.Normalize(vmin=local_vmin, vmax=local_vmax)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: voxcity
3
- Version: 0.4.3
3
+ Version: 0.4.4
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>
@@ -1,5 +1,5 @@
1
1
  voxcity/__init__.py,sha256=el9v3gfybHOF_GUYPeSOqN0-vCrTW0eU1mcvi0sEfeU,252
2
- voxcity/generator.py,sha256=rsS5Z77Esgomho9Bd3HRQeYlncvyEG1CEHUXAB_SHxw,35048
2
+ voxcity/generator.py,sha256=0RKWcWKfwFs2xcepyEDLMQdHqGhAGlpPwhNe6UJTRuI,35348
3
3
  voxcity/downloader/__init__.py,sha256=OgGcGxOXF4tjcEL6DhOnt13DYPTvOigUelp5xIpTqM0,171
4
4
  voxcity/downloader/eubucco.py,sha256=XCkkdEPNuWdrnuxzL80Ext37WsgiCiZGueb-aQV5rvI,14476
5
5
  voxcity/downloader/gee.py,sha256=hEN5OvQAltORYnrlPbmYcDequ6lKLmwyTbNaCZ81Vj8,16089
@@ -18,7 +18,7 @@ voxcity/geoprocessor/draw.py,sha256=8Em2NvazFpYfFJUqG9LofNXaxdghKLL_rNuztmPwn8Q,
18
18
  voxcity/geoprocessor/grid.py,sha256=t-KAdYOk1iUeBuOMcoAb5e4hzJjMIfVItTdFP6FJs1A,44340
19
19
  voxcity/geoprocessor/mesh.py,sha256=z6e-BigN_K1CGpS9mopkf121pbCnBFJMu32XYfqpLI4,10506
20
20
  voxcity/geoprocessor/network.py,sha256=opb_kpUCAxDd1qtrWPStqR5reYZtVe96XxazNSen7Lk,18851
21
- voxcity/geoprocessor/polygon.py,sha256=wXU3K-lghAlAOe_C-m1YD4_75DvCWzdszuWieenP5mA,37208
21
+ voxcity/geoprocessor/polygon.py,sha256=8Vb2AbkpKYhq1kk2hQMc-gitmUo9pFIe910v4p1vP2g,37772
22
22
  voxcity/geoprocessor/utils.py,sha256=1BRHp-DDeOA8HG8jplY7Eo75G3oXkVGL6DGONL4BA8A,19815
23
23
  voxcity/simulator/__init_.py,sha256=APdkcdaovj0v_RPOaA4SBvFUKT2RM7Hxuuz3Sux4gCo,65
24
24
  voxcity/simulator/solar.py,sha256=amJ5GJtzdG9NE7oxrLj4EMRxGvDY9s2BQdDJ2paFfn0,56709
@@ -27,11 +27,11 @@ voxcity/simulator/view.py,sha256=-CM-pPbfthg_meyMdcZs9Ar3CHaZhw2fRf_dM6ioN_Q,748
27
27
  voxcity/utils/__init_.py,sha256=nLYrj2huBbDBNMqfchCwexGP8Tlt9O_XluVDG7MoFkw,98
28
28
  voxcity/utils/lc.py,sha256=RwPd-VY3POV3gTrBhM7TubgGb9MCd3nVah_G8iUEF7k,11562
29
29
  voxcity/utils/material.py,sha256=Vt3IID5Ft54HNJcEC4zi31BCPqi_687X3CSp7rXaRVY,5907
30
- voxcity/utils/visualization.py,sha256=8r7ffnvBCAmvEYnJQ4KKh18aaah3G9ARoV9EDXUyo8I,85255
30
+ voxcity/utils/visualization.py,sha256=UJ2wyFFbuI6glZJ8adyiVtNlZFUgleC278S-r2OO33g,85240
31
31
  voxcity/utils/weather.py,sha256=CFPtoqRTajwMRswswDChwQ3BW1cGsnA3orgWHgz7Ehg,26304
32
- voxcity-0.4.3.dist-info/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
33
- voxcity-0.4.3.dist-info/LICENSE,sha256=-hGliOFiwUrUSoZiB5WF90xXGqinKyqiDI2t6hrnam8,1087
34
- voxcity-0.4.3.dist-info/METADATA,sha256=kCm6TzscCstqLacexWTUM6I1u9qm_wT-AeYdlCe8P9o,25527
35
- voxcity-0.4.3.dist-info/WHEEL,sha256=EaM1zKIUYa7rQnxGiOCGhzJABRwy4WO57rWMR3_tj4I,91
36
- voxcity-0.4.3.dist-info/top_level.txt,sha256=00b2U-LKfDllt6RL1R33MXie5MvxzUFye0NGD96t_8I,8
37
- voxcity-0.4.3.dist-info/RECORD,,
32
+ voxcity-0.4.4.dist-info/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
33
+ voxcity-0.4.4.dist-info/LICENSE,sha256=-hGliOFiwUrUSoZiB5WF90xXGqinKyqiDI2t6hrnam8,1087
34
+ voxcity-0.4.4.dist-info/METADATA,sha256=73PRyC5f-BPeFk8FpmZvaUvUVYGVDqAHMK-_Rj_oQs0,25527
35
+ voxcity-0.4.4.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
36
+ voxcity-0.4.4.dist-info/top_level.txt,sha256=00b2U-LKfDllt6RL1R33MXie5MvxzUFye0NGD96t_8I,8
37
+ voxcity-0.4.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.9.1)
2
+ Generator: setuptools (76.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5