voxcity 0.5.27__py3-none-any.whl → 0.5.28__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
@@ -6,12 +6,19 @@ It handles land cover, building heights, canopy heights, and digital elevation m
6
6
 
7
7
  The main functions are:
8
8
  - get_land_cover_grid: Creates a grid of land cover classifications
9
- - get_building_height_grid: Creates a grid of building heights
9
+ - get_building_height_grid: Creates a grid of building heights (supports GeoDataFrame input)
10
10
  - get_canopy_height_grid: Creates a grid of tree canopy heights
11
11
  - get_dem_grid: Creates a digital elevation model grid
12
12
  - create_3d_voxel: Combines the grids into a 3D voxel representation
13
13
  - create_3d_voxel_individuals: Creates separate voxel grids for each component
14
- - get_voxcity: Main function to generate a complete voxel city model
14
+ - get_voxcity: Main function to generate a complete voxel city model (supports GeoDataFrame input)
15
+
16
+ Key Features:
17
+ - Support for multiple data sources (OpenStreetMap, ESA WorldCover, Google Earth Engine, etc.)
18
+ - Direct GeoDataFrame input for building data (useful for custom datasets)
19
+ - 3D voxel generation with configurable resolution
20
+ - Visualization capabilities for both 2D grids and 3D models
21
+ - Data export in various formats (GeoTIFF, GeoJSON, pickle)
15
22
  """
16
23
 
17
24
  # Standard library imports
@@ -87,6 +94,7 @@ def get_land_cover_grid(rectangle_vertices, meshsize, source, output_dir, **kwar
87
94
  - esri_landcover_year: Year for ESRI land cover data
88
95
  - dynamic_world_date: Date for Dynamic World data
89
96
  - gridvis: Whether to visualize the grid
97
+ - default_land_cover_class: Default class for grid cells with no intersecting polygons (default: 'Developed space')
90
98
 
91
99
  Returns:
92
100
  numpy.ndarray: Grid of land cover classifications as integer values
@@ -142,7 +150,8 @@ def get_land_cover_grid(rectangle_vertices, meshsize, source, output_dir, **kwar
142
150
  # Different processing for vector vs raster data sources
143
151
  if source == 'OpenStreetMap':
144
152
  # Process vector data directly from GeoDataFrame
145
- land_cover_grid_str = create_land_cover_grid_from_gdf_polygon(land_cover_gdf, meshsize, source, rectangle_vertices)
153
+ default_class = kwargs.get('default_land_cover_class', 'Developed space')
154
+ land_cover_grid_str = create_land_cover_grid_from_gdf_polygon(land_cover_gdf, meshsize, source, rectangle_vertices, default_class=default_class)
146
155
  else:
147
156
  # Process raster data from GeoTIFF file
148
157
  land_cover_grid_str = create_land_cover_grid_from_geotiff_polygon(geotiff_path, meshsize, land_cover_classes, rectangle_vertices)
@@ -164,14 +173,15 @@ def get_land_cover_grid(rectangle_vertices, meshsize, source, output_dir, **kwar
164
173
  return land_cover_grid_int
165
174
 
166
175
  # def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir="output", visualization=True, maptiler_API_key=None, file_path=None):
167
- def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, **kwargs):
176
+ def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, building_gdf=None, **kwargs):
168
177
  """Creates a grid of building heights.
169
178
 
170
179
  Args:
171
180
  rectangle_vertices: List of coordinates defining the area of interest
172
181
  meshsize: Size of each grid cell in meters
173
- source: Data source for buildings (e.g. 'OpenStreetMap', 'Microsoft Building Footprints')
182
+ source: Data source for buildings (e.g. 'OpenStreetMap', 'Microsoft Building Footprints', 'GeoDataFrame')
174
183
  output_dir: Directory to save output files
184
+ building_gdf: Optional GeoDataFrame with building footprint, height and other information
175
185
  **kwargs: Additional arguments including:
176
186
  - maptiler_API_key: API key for MapTiler
177
187
  - building_path: Path to local building data file
@@ -187,7 +197,7 @@ def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, *
187
197
  """
188
198
 
189
199
  # Initialize Earth Engine for satellite-based building data sources
190
- if source not in ["OpenStreetMap", "Overture", "Local file"]:
200
+ if source not in ["OpenStreetMap", "Overture", "Local file", "GeoDataFrame"]:
191
201
  initialize_earth_engine()
192
202
 
193
203
  print("Creating Building Height grid\n ")
@@ -195,32 +205,40 @@ def get_building_height_grid(rectangle_vertices, meshsize, source, output_dir, *
195
205
 
196
206
  os.makedirs(output_dir, exist_ok=True)
197
207
 
198
- # Fetch building data from primary source
199
- # Each source has different data formats and processing requirements
200
- if source == 'Microsoft Building Footprints':
201
- # Machine learning-derived building footprints from satellite imagery
202
- gdf = get_mbfp_gdf(output_dir, rectangle_vertices)
203
- elif source == 'OpenStreetMap':
204
- # Crowd-sourced building data with varying completeness
205
- gdf = load_gdf_from_openstreetmap(rectangle_vertices)
206
- elif source == "Open Building 2.5D Temporal":
207
- # Special case: this source provides both footprints and heights
208
- # Skip GeoDataFrame processing and create grids directly
209
- building_height_grid, building_min_height_grid, building_id_grid, filtered_buildings = create_building_height_grid_from_open_building_temporal_polygon(meshsize, rectangle_vertices, output_dir)
210
- elif source == 'EUBUCCO v0.1':
211
- # European building database with height information
212
- gdf = load_gdf_from_eubucco(rectangle_vertices, output_dir)
213
- # elif source == "OpenMapTiles":
214
- # # Vector tiles service for building data
215
- # gdf = load_gdf_from_openmaptiles(rectangle_vertices, kwargs["maptiler_API_key"])
216
- elif source == "Overture":
217
- # Open building dataset from Overture Maps Foundation
218
- gdf = load_gdf_from_overture(rectangle_vertices)
219
- elif source == "Local file":
220
- # Handle user-provided local building data files
221
- _, extension = os.path.splitext(kwargs["building_path"])
222
- if extension == ".gpkg":
223
- gdf = get_gdf_from_gpkg(kwargs["building_path"], rectangle_vertices)
208
+ # If building_gdf is provided, use it directly
209
+ if building_gdf is not None:
210
+ gdf = building_gdf
211
+ print("Using provided GeoDataFrame for building data")
212
+ else:
213
+ # Fetch building data from primary source
214
+ # Each source has different data formats and processing requirements
215
+ if source == 'Microsoft Building Footprints':
216
+ # Machine learning-derived building footprints from satellite imagery
217
+ gdf = get_mbfp_gdf(output_dir, rectangle_vertices)
218
+ elif source == 'OpenStreetMap':
219
+ # Crowd-sourced building data with varying completeness
220
+ gdf = load_gdf_from_openstreetmap(rectangle_vertices)
221
+ elif source == "Open Building 2.5D Temporal":
222
+ # Special case: this source provides both footprints and heights
223
+ # Skip GeoDataFrame processing and create grids directly
224
+ building_height_grid, building_min_height_grid, building_id_grid, filtered_buildings = create_building_height_grid_from_open_building_temporal_polygon(meshsize, rectangle_vertices, output_dir)
225
+ elif source == 'EUBUCCO v0.1':
226
+ # European building database with height information
227
+ gdf = load_gdf_from_eubucco(rectangle_vertices, output_dir)
228
+ # elif source == "OpenMapTiles":
229
+ # # Vector tiles service for building data
230
+ # gdf = load_gdf_from_openmaptiles(rectangle_vertices, kwargs["maptiler_API_key"])
231
+ elif source == "Overture":
232
+ # Open building dataset from Overture Maps Foundation
233
+ gdf = load_gdf_from_overture(rectangle_vertices)
234
+ elif source == "Local file":
235
+ # Handle user-provided local building data files
236
+ _, extension = os.path.splitext(kwargs["building_path"])
237
+ if extension == ".gpkg":
238
+ gdf = get_gdf_from_gpkg(kwargs["building_path"], rectangle_vertices)
239
+ elif source == "GeoDataFrame":
240
+ # This case is handled by the building_gdf parameter above
241
+ raise ValueError("When source is 'GeoDataFrame', building_gdf parameter must be provided")
224
242
 
225
243
  # Handle complementary data sources to fill gaps or provide additional information
226
244
  # This allows combining multiple sources for better coverage or accuracy
@@ -590,16 +608,17 @@ def create_3d_voxel_individuals(building_height_grid_ori, land_cover_grid_ori, d
590
608
 
591
609
  return land_cover_voxel_grid, building_voxel_grid, tree_voxel_grid, dem_voxel_grid, layered_voxel_grid
592
610
 
593
- def get_voxcity(rectangle_vertices, building_source, land_cover_source, canopy_height_source, dem_source, meshsize, **kwargs):
611
+ def get_voxcity(rectangle_vertices, building_source, land_cover_source, canopy_height_source, dem_source, meshsize, building_gdf=None, **kwargs):
594
612
  """Main function to generate a complete voxel city model.
595
613
 
596
614
  Args:
597
615
  rectangle_vertices: List of coordinates defining the area of interest
598
- building_source: Source for building height data (e.g. 'OSM', 'EUBUCCO')
616
+ building_source: Source for building height data (e.g. 'OSM', 'EUBUCCO', 'GeoDataFrame')
599
617
  land_cover_source: Source for land cover data (e.g. 'ESA', 'ESRI')
600
618
  canopy_height_source: Source for tree canopy height data
601
619
  dem_source: Source for digital elevation model data ('Flat' or other source)
602
620
  meshsize: Size of each grid cell in meters
621
+ building_gdf: Optional GeoDataFrame with building footprint, height and other information
603
622
  **kwargs: Additional keyword arguments including:
604
623
  - output_dir: Directory to save output files (default: 'output')
605
624
  - min_canopy_height: Minimum height threshold for tree canopy
@@ -607,6 +626,7 @@ def get_voxcity(rectangle_vertices, building_source, land_cover_source, canopy_h
607
626
  - mapvis: Whether to visualize grids on map
608
627
  - voxelvis: Whether to visualize 3D voxel model
609
628
  - voxelvis_img_save_path: Path to save 3D visualization
629
+ - default_land_cover_class: Default class for land cover grid cells with no intersecting polygons (default: 'Developed space')
610
630
 
611
631
  Returns:
612
632
  tuple containing:
@@ -633,7 +653,7 @@ def get_voxcity(rectangle_vertices, building_source, land_cover_source, canopy_h
633
653
  land_cover_grid = get_land_cover_grid(rectangle_vertices, meshsize, land_cover_source, output_dir, **kwargs)
634
654
 
635
655
  # Building footprints and height information
636
- building_height_grid, building_min_height_grid, building_id_grid, building_gdf = get_building_height_grid(rectangle_vertices, meshsize, building_source, output_dir, **kwargs)
656
+ building_height_grid, building_min_height_grid, building_id_grid, building_gdf = get_building_height_grid(rectangle_vertices, meshsize, building_source, output_dir, building_gdf=building_gdf, **kwargs)
637
657
 
638
658
  # Save building data to file for later analysis or visualization
639
659
  if not building_gdf.empty:
@@ -25,10 +25,19 @@ Dependencies:
25
25
 
26
26
  import math
27
27
  from pyproj import Proj, transform
28
- from ipyleaflet import Map, DrawControl, Rectangle, Polygon as LeafletPolygon
29
- import ipyleaflet
28
+ from ipyleaflet import (
29
+ Map,
30
+ DrawControl,
31
+ Rectangle,
32
+ Polygon as LeafletPolygon,
33
+ WidgetControl
34
+ )
30
35
  from geopy import distance
31
36
  import shapely.geometry as geom
37
+ import geopandas as gpd
38
+ from ipywidgets import VBox, HBox, Button, FloatText, Label, Output, HTML
39
+ import pandas as pd
40
+ from IPython.display import display, clear_output
32
41
 
33
42
  from .utils import get_coordinates_from_cityname
34
43
 
@@ -484,4 +493,268 @@ def display_buildings_and_draw_polygon(building_gdf=None, rectangle_vertices=Non
484
493
  draw_control.on_draw(handle_draw)
485
494
  m.add_control(draw_control)
486
495
 
487
- return m, drawn_polygon_vertices
496
+ return m, drawn_polygon_vertices
497
+
498
+ def draw_additional_buildings(building_gdf=None, initial_center=None, zoom=17):
499
+ """
500
+ Creates an interactive map for drawing building footprints with height input.
501
+
502
+ This function provides an interface for users to:
503
+ 1. Draw building footprints on an interactive map
504
+ 2. Set building height values through a UI widget
505
+ 3. Add new buildings to the existing building_gdf
506
+
507
+ The workflow is:
508
+ - User draws a polygon on the map
509
+ - Height input widget appears
510
+ - User enters height and clicks "Add Building"
511
+ - Building is added to GeoDataFrame and displayed on map
512
+
513
+ Args:
514
+ building_gdf (GeoDataFrame, optional): Existing building footprints to display.
515
+ If None, creates a new empty GeoDataFrame.
516
+ Must have 'geometry' column and optionally 'height' column.
517
+ initial_center (tuple, optional): Initial map center as (lon, lat).
518
+ If None, centers on existing buildings or defaults to (-100, 40).
519
+ zoom (int): Initial zoom level (default=17).
520
+
521
+ Returns:
522
+ tuple: (map_object, updated_building_gdf)
523
+ - map_object: ipyleaflet Map instance with drawing controls
524
+ - updated_building_gdf: GeoDataFrame that automatically updates when buildings are added
525
+
526
+ Example:
527
+ >>> # Start with empty buildings
528
+ >>> m, buildings = draw_additional_buildings()
529
+ >>> # Draw buildings on the map...
530
+ >>> print(buildings) # Will contain all drawn buildings
531
+ """
532
+
533
+ # Initialize or copy the building GeoDataFrame
534
+ if building_gdf is None:
535
+ # Create empty GeoDataFrame with required columns
536
+ updated_gdf = gpd.GeoDataFrame(
537
+ columns=['geometry', 'height', 'building_id'],
538
+ crs='EPSG:4326'
539
+ )
540
+ else:
541
+ # Make a copy to avoid modifying the original
542
+ updated_gdf = building_gdf.copy()
543
+ if 'height' not in updated_gdf.columns:
544
+ updated_gdf['height'] = 10.0 # Default height
545
+ if 'building_id' not in updated_gdf.columns:
546
+ updated_gdf['building_id'] = range(len(updated_gdf))
547
+
548
+ # Determine map center
549
+ if initial_center is not None:
550
+ center_lon, center_lat = initial_center
551
+ elif updated_gdf is not None and len(updated_gdf) > 0:
552
+ bounds = updated_gdf.total_bounds
553
+ min_lon, min_lat, max_lon, max_lat = bounds
554
+ center_lon = (min_lon + max_lon) / 2
555
+ center_lat = (min_lat + max_lat) / 2
556
+ else:
557
+ center_lon, center_lat = -100.0, 40.0
558
+
559
+ # Create the map
560
+ m = Map(center=(center_lat, center_lon), zoom=zoom, scroll_wheel_zoom=True)
561
+
562
+ # Display existing buildings
563
+ building_layers = {}
564
+ for idx, row in updated_gdf.iterrows():
565
+ if isinstance(row.geometry, geom.Polygon):
566
+ coords = list(row.geometry.exterior.coords)
567
+ lat_lon_coords = [(c[1], c[0]) for c in coords[:-1]]
568
+
569
+ height = row.get('height', 10.0)
570
+ bldg_layer = LeafletPolygon(
571
+ locations=lat_lon_coords,
572
+ color="blue",
573
+ fill_color="blue",
574
+ fill_opacity=0.3,
575
+ weight=2,
576
+ popup=HTML(f"<b>Building ID:</b> {row.get('building_id', idx)}<br>"
577
+ f"<b>Height:</b> {height}m")
578
+ )
579
+ m.add_layer(bldg_layer)
580
+ building_layers[idx] = bldg_layer
581
+
582
+ # Create UI widgets
583
+ height_input = FloatText(
584
+ value=10.0,
585
+ description='Height (m):',
586
+ disabled=False,
587
+ style={'description_width': 'initial'}
588
+ )
589
+
590
+ add_button = Button(
591
+ description='Add Building',
592
+ button_style='success',
593
+ disabled=True
594
+ )
595
+
596
+ clear_button = Button(
597
+ description='Clear Drawing',
598
+ button_style='warning',
599
+ disabled=True
600
+ )
601
+
602
+ status_output = Output()
603
+
604
+ # Create control panel
605
+ control_panel = VBox([
606
+ HTML("<h3>Draw Building Tool</h3>"),
607
+ HTML("<p>1. Draw a polygon on the map<br>2. Set height<br>3. Click 'Add Building'</p>"),
608
+ height_input,
609
+ HBox([add_button, clear_button]),
610
+ status_output
611
+ ])
612
+
613
+ # Add control panel to map
614
+ widget_control = WidgetControl(widget=control_panel, position='topright')
615
+ m.add_control(widget_control)
616
+
617
+ # Store the current drawn polygon
618
+ current_polygon = {'vertices': [], 'layer': None}
619
+
620
+ # Drawing control
621
+ draw_control = DrawControl(
622
+ polygon={
623
+ "shapeOptions": {
624
+ "color": "red",
625
+ "fillColor": "red",
626
+ "fillOpacity": 0.3,
627
+ "weight": 3
628
+ }
629
+ },
630
+ rectangle={},
631
+ circle={},
632
+ circlemarker={},
633
+ polyline={},
634
+ marker={}
635
+ )
636
+
637
+ def handle_draw(self, action, geo_json):
638
+ """Handle polygon drawing events"""
639
+ with status_output:
640
+ clear_output()
641
+
642
+ if action == 'created' and geo_json['geometry']['type'] == 'Polygon':
643
+ # Store vertices
644
+ coordinates = geo_json['geometry']['coordinates'][0]
645
+ current_polygon['vertices'] = [(coord[0], coord[1]) for coord in coordinates[:-1]]
646
+
647
+ # Enable buttons
648
+ add_button.disabled = False
649
+ clear_button.disabled = False
650
+
651
+ with status_output:
652
+ print(f"Polygon drawn with {len(current_polygon['vertices'])} vertices")
653
+ print("Set height and click 'Add Building'")
654
+
655
+ def add_building_click(b):
656
+ """Handle add building button click"""
657
+ # Use nonlocal to modify the outer scope variable
658
+ nonlocal updated_gdf
659
+
660
+ with status_output:
661
+ clear_output()
662
+
663
+ if current_polygon['vertices']:
664
+ # Create polygon geometry
665
+ polygon = geom.Polygon(current_polygon['vertices'])
666
+
667
+ # Get next building ID
668
+ if len(updated_gdf) > 0:
669
+ next_id = int(updated_gdf['building_id'].max() + 1)
670
+ else:
671
+ next_id = 1
672
+
673
+ # Create new row data
674
+ new_row_data = {
675
+ 'geometry': polygon,
676
+ 'height': float(height_input.value),
677
+ 'building_id': next_id
678
+ }
679
+
680
+ # Add any additional columns
681
+ for col in updated_gdf.columns:
682
+ if col not in new_row_data:
683
+ new_row_data[col] = None
684
+
685
+ # Append the new building in-place
686
+ new_index = len(updated_gdf)
687
+ updated_gdf.loc[new_index] = new_row_data
688
+
689
+ # Add to map
690
+ coords = list(polygon.exterior.coords)
691
+ lat_lon_coords = [(c[1], c[0]) for c in coords[:-1]]
692
+
693
+ new_layer = LeafletPolygon(
694
+ locations=lat_lon_coords,
695
+ color="blue",
696
+ fill_color="blue",
697
+ fill_opacity=0.3,
698
+ weight=2,
699
+ popup=HTML(f"<b>Building ID:</b> {next_id}<br>"
700
+ f"<b>Height:</b> {height_input.value}m")
701
+ )
702
+ m.add_layer(new_layer)
703
+
704
+ # Clear drawing
705
+ draw_control.clear()
706
+ current_polygon['vertices'] = []
707
+ add_button.disabled = True
708
+ clear_button.disabled = True
709
+
710
+ print(f"Building {next_id} added successfully!")
711
+ print(f"Height: {height_input.value}m")
712
+ print(f"Total buildings: {len(updated_gdf)}")
713
+
714
+ def clear_drawing_click(b):
715
+ """Handle clear drawing button click"""
716
+ with status_output:
717
+ clear_output()
718
+ draw_control.clear()
719
+ current_polygon['vertices'] = []
720
+ add_button.disabled = True
721
+ clear_button.disabled = True
722
+ print("Drawing cleared")
723
+
724
+ # Connect event handlers
725
+ draw_control.on_draw(handle_draw)
726
+ add_button.on_click(add_building_click)
727
+ clear_button.on_click(clear_drawing_click)
728
+
729
+ # Add draw control to map
730
+ m.add_control(draw_control)
731
+
732
+ # Display initial status
733
+ with status_output:
734
+ print(f"Total buildings loaded: {len(updated_gdf)}")
735
+ print("Draw a polygon to add a new building")
736
+
737
+ return m, updated_gdf
738
+
739
+
740
+ # Simple convenience function
741
+ def create_building_editor(building_gdf=None, initial_center=None, zoom=17):
742
+ """
743
+ Creates and displays an interactive building editor.
744
+
745
+ Args:
746
+ building_gdf: Existing buildings GeoDataFrame (optional)
747
+ initial_center: Map center as (lon, lat) tuple (optional)
748
+ zoom: Initial zoom level (default=17)
749
+
750
+ Returns:
751
+ GeoDataFrame: The building GeoDataFrame that automatically updates
752
+
753
+ Example:
754
+ >>> buildings = create_building_editor()
755
+ >>> # Draw buildings on the displayed map
756
+ >>> print(buildings) # Automatically contains all drawn buildings
757
+ """
758
+ m, gdf = draw_additional_buildings(building_gdf, initial_center, zoom)
759
+ display(m)
760
+ return gdf
@@ -412,7 +412,7 @@ def create_land_cover_grid_from_geotiff_polygon(tiff_path, mesh_size, land_cover
412
412
  # Flip grid vertically to match geographic orientation
413
413
  return np.flipud(grid)
414
414
 
415
- def create_land_cover_grid_from_gdf_polygon(gdf, meshsize, source, rectangle_vertices):
415
+ def create_land_cover_grid_from_gdf_polygon(gdf, meshsize, source, rectangle_vertices, default_class='Developed space'):
416
416
  """Create a grid of land cover classes from GeoDataFrame polygon data.
417
417
 
418
418
  Args:
@@ -420,6 +420,8 @@ def create_land_cover_grid_from_gdf_polygon(gdf, meshsize, source, rectangle_ver
420
420
  meshsize (float): Size of each grid cell in meters
421
421
  source (str): Source of the land cover data to determine class priorities
422
422
  rectangle_vertices (list): List of 4 (lon,lat) coordinate pairs defining the rectangle bounds
423
+ default_class (str, optional): Default land cover class for cells with no intersecting polygons.
424
+ Defaults to 'Developed space'.
423
425
 
424
426
  Returns:
425
427
  numpy.ndarray: 2D grid of land cover classes as strings
@@ -466,7 +468,7 @@ def create_land_cover_grid_from_gdf_polygon(gdf, meshsize, source, rectangle_ver
466
468
  print(f"Adjusted mesh size: {adjusted_meshsize}")
467
469
 
468
470
  # Initialize grid with default land cover class
469
- grid = np.full(grid_size, 'Developed space', dtype=object)
471
+ grid = np.full(grid_size, default_class, dtype=object)
470
472
 
471
473
  # Calculate bounding box for spatial indexing
472
474
  extent = [min(coord[1] for coord in rectangle_vertices), max(coord[1] for coord in rectangle_vertices),
@@ -485,7 +487,7 @@ def create_land_cover_grid_from_gdf_polygon(gdf, meshsize, source, rectangle_ver
485
487
  # Iterate through each grid cell
486
488
  for i in range(grid_size[0]):
487
489
  for j in range(grid_size[1]):
488
- land_cover_class = 'Developed space'
490
+ land_cover_class = default_class
489
491
  cell = create_cell_polygon(origin, i, j, adjusted_meshsize, u_vec, v_vec)
490
492
 
491
493
  # Check intersections with polygons that could overlap this cell
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voxcity
3
- Version: 0.5.27
3
+ Version: 0.5.28
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,12 +1,12 @@
1
1
  voxcity/__init__.py,sha256=el9v3gfybHOF_GUYPeSOqN0-vCrTW0eU1mcvi0sEfeU,252
2
- voxcity/generator.py,sha256=h1C2AaLQ1fqdU47UIUZTK1ox8d_c2I1Dql5mdscr7X8,52552
2
+ voxcity/generator.py,sha256=mEggM4FxE7LChTPCspAQmJlAoUz1PVcbaUfY11cMfzQ,54176
3
3
  voxcity/downloader/__init__.py,sha256=o_T_EU7hZLGyXxX9wVWn1x-OAa3ThGYdnpgB1_2v3AE,151
4
4
  voxcity/downloader/citygml.py,sha256=jVeHCLlJTf7k55OQGX0lZGQAngz_DD2V5TldSqRFlvc,36024
5
5
  voxcity/downloader/eubucco.py,sha256=ln1YNaaOgJfxNfCtVbYaMm775-bUvpAA_LDv60_i22w,17875
6
6
  voxcity/downloader/gee.py,sha256=O6HhQnUUumg_tTm4pP_cuyu5YjupDA1uKFxZWxD-i2E,23205
7
7
  voxcity/downloader/mbfp.py,sha256=UXDVjsO0fnb0fSal9yqrSFEIBThnRmnutnp08kZTmCA,6595
8
8
  voxcity/downloader/oemj.py,sha256=iDacTpiqn7RAXuqyEtHP29m0Cycwta5sMy9-GdvX3Fg,12293
9
- voxcity/downloader/osm.py,sha256=kXiUedT7dwPOQ_4nxXptfeqNb5RKTIsQLG5km7Q8kKk,41645
9
+ voxcity/downloader/osm.py,sha256=9nOVcVE50N76F5uquJbNIFr8Xajff4ac2Uj2oSGcFrc,42591
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=dvyWJ184Eik9tFc0VviGbzTQzZi7O0JNyrqi_n39pVI,94
@@ -15,8 +15,8 @@ voxcity/exporter/envimet.py,sha256=Sh7s1JdQ6SgT_L2Xd_c4gtEGWK2hTS87bccaoIqik-s,3
15
15
  voxcity/exporter/magicavoxel.py,sha256=SfGEgTZRlossKx3Xrv9d3iKSX-HmfQJEL9lZHgWMDX4,12782
16
16
  voxcity/exporter/obj.py,sha256=h1_aInpemcsu96fSTwjKMqX2VZAFYbZbElWd4M1ogyI,27973
17
17
  voxcity/geoprocessor/__init__.py,sha256=JzPVhhttxBWvaZ0IGX2w7OWL5bCo_TIvpHefWeNXruA,133
18
- voxcity/geoprocessor/draw.py,sha256=lcBtf4VAWXjk46cInPdSBeiLCTESdxzLOayr_0YOnus,22184
19
- voxcity/geoprocessor/grid.py,sha256=Uy8Oz4iL7vnPMqp_qtp4dQrs00yd2L9CSIPmF5KnbtI,63961
18
+ voxcity/geoprocessor/draw.py,sha256=qTYzXEF8GKWh3hquirspzlzwXTIzl39y9VuEJ0WjOis,32031
19
+ voxcity/geoprocessor/grid.py,sha256=lhELyznlk4Jt7vnd0uOpMCLPCjrYQjX7qtQq-xHkYE4,64161
20
20
  voxcity/geoprocessor/mesh.py,sha256=ElqAE2MA8KZs7yD7B1P88XYmryC6F9nkkP6cXv7FzIk,30777
21
21
  voxcity/geoprocessor/network.py,sha256=YynqR0nq_NUra_cQ3Z_56KxfRia1b6-hIzGCj3QT-wE,25137
22
22
  voxcity/geoprocessor/polygon.py,sha256=-LonxtW5du3UP61oygqtDJl6GGsCYnUuN9KYwl1UFdc,53707
@@ -30,9 +30,9 @@ voxcity/utils/lc.py,sha256=h2yOWLUIrrummkyMyhRK5VbyrsPtslS0MJov_y0WGIQ,18925
30
30
  voxcity/utils/material.py,sha256=H8K8Lq4wBL6dQtgj7esUW2U6wLCOTeOtelkTDJoRgMo,10007
31
31
  voxcity/utils/visualization.py,sha256=T-jKrCA4UMm93p-1O678RWM7e99iE0_Lj4wD07efcwI,112918
32
32
  voxcity/utils/weather.py,sha256=2Jtg-rIVJcsTtiKE-KuDnhIqS1-MSS16_zFRzj6zmu4,36435
33
- voxcity-0.5.27.dist-info/licenses/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
34
- voxcity-0.5.27.dist-info/licenses/LICENSE,sha256=s_jE1Df1nTPL4A_5GCGic5Zwex0CVaPKcAmSilxJPPE,1089
35
- voxcity-0.5.27.dist-info/METADATA,sha256=Jq5J4RKe0lXE4WjBJER70F2f9A0HgfxH7GWypmwEBXo,26724
36
- voxcity-0.5.27.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
- voxcity-0.5.27.dist-info/top_level.txt,sha256=00b2U-LKfDllt6RL1R33MXie5MvxzUFye0NGD96t_8I,8
38
- voxcity-0.5.27.dist-info/RECORD,,
33
+ voxcity-0.5.28.dist-info/licenses/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
34
+ voxcity-0.5.28.dist-info/licenses/LICENSE,sha256=s_jE1Df1nTPL4A_5GCGic5Zwex0CVaPKcAmSilxJPPE,1089
35
+ voxcity-0.5.28.dist-info/METADATA,sha256=1-Vf32nGdVvGxmOMXMcfTIi4IM92x4uGq5T7qzlDbxY,26724
36
+ voxcity-0.5.28.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
+ voxcity-0.5.28.dist-info/top_level.txt,sha256=00b2U-LKfDllt6RL1R33MXie5MvxzUFye0NGD96t_8I,8
38
+ voxcity-0.5.28.dist-info/RECORD,,