voxcity 0.6.13__tar.gz → 0.6.14__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.13 → voxcity-0.6.14}/PKG-INFO +1 -1
- {voxcity-0.6.13 → voxcity-0.6.14}/pyproject.toml +1 -1
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/geoprocessor/draw.py +80 -1
- {voxcity-0.6.13 → voxcity-0.6.14}/AUTHORS.rst +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/LICENSE +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/README.md +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/__init__.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/downloader/__init__.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/downloader/citygml.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/downloader/eubucco.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/downloader/gee.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/downloader/mbfp.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/downloader/oemj.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/downloader/osm.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/downloader/overture.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/downloader/utils.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/exporter/__init__.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/exporter/cityles.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/exporter/envimet.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/exporter/magicavoxel.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/exporter/obj.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/generator.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/geoprocessor/__init__.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/geoprocessor/grid.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/geoprocessor/mesh.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/geoprocessor/network.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/geoprocessor/polygon.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/geoprocessor/utils.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/simulator/__init__.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/simulator/solar.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/simulator/utils.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/simulator/view.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/utils/__init__.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/utils/lc.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/utils/material.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/src/voxcity/utils/visualization.py +0 -0
- {voxcity-0.6.13 → voxcity-0.6.14}/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.14"
|
|
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"
|
|
@@ -39,7 +39,7 @@ from ipyleaflet import (
|
|
|
39
39
|
from geopy import distance
|
|
40
40
|
import shapely.geometry as geom
|
|
41
41
|
import geopandas as gpd
|
|
42
|
-
from ipywidgets import VBox, HBox, Button, FloatText, Label, Output, HTML
|
|
42
|
+
from ipywidgets import VBox, HBox, Button, FloatText, Label, Output, HTML, Checkbox
|
|
43
43
|
import pandas as pd
|
|
44
44
|
from IPython.display import display, clear_output
|
|
45
45
|
|
|
@@ -934,6 +934,7 @@ def draw_additional_trees(tree_gdf=None, initial_center=None, zoom=17, rectangle
|
|
|
934
934
|
top_height_input = FloatText(value=10.0, description='Top height (m):', disabled=False, style={'description_width': 'initial'})
|
|
935
935
|
bottom_height_input = FloatText(value=4.0, description='Bottom height (m):', disabled=False, style={'description_width': 'initial'})
|
|
936
936
|
crown_diameter_input = FloatText(value=6.0, description='Crown diameter (m):', disabled=False, style={'description_width': 'initial'})
|
|
937
|
+
fixed_prop_checkbox = Checkbox(value=True, description='Fixed proportion', indent=False)
|
|
937
938
|
|
|
938
939
|
add_mode_button = Button(description='Add', button_style='success')
|
|
939
940
|
remove_mode_button = Button(description='Remove', button_style='')
|
|
@@ -947,6 +948,7 @@ def draw_additional_trees(tree_gdf=None, initial_center=None, zoom=17, rectangle
|
|
|
947
948
|
top_height_input,
|
|
948
949
|
bottom_height_input,
|
|
949
950
|
crown_diameter_input,
|
|
951
|
+
fixed_prop_checkbox,
|
|
950
952
|
hover_info,
|
|
951
953
|
status_output
|
|
952
954
|
])
|
|
@@ -956,6 +958,83 @@ def draw_additional_trees(tree_gdf=None, initial_center=None, zoom=17, rectangle
|
|
|
956
958
|
|
|
957
959
|
# State for mode
|
|
958
960
|
mode = 'add'
|
|
961
|
+
# Fixed proportion state
|
|
962
|
+
base_bottom_ratio = bottom_height_input.value / top_height_input.value if top_height_input.value else 0.4
|
|
963
|
+
base_crown_ratio = crown_diameter_input.value / top_height_input.value if top_height_input.value else 0.6
|
|
964
|
+
updating_params = False
|
|
965
|
+
|
|
966
|
+
def recompute_from_top(new_top: float):
|
|
967
|
+
nonlocal updating_params
|
|
968
|
+
if new_top <= 0:
|
|
969
|
+
return
|
|
970
|
+
new_bottom = max(0.0, base_bottom_ratio * new_top)
|
|
971
|
+
new_crown = max(0.0, base_crown_ratio * new_top)
|
|
972
|
+
updating_params = True
|
|
973
|
+
bottom_height_input.value = new_bottom
|
|
974
|
+
crown_diameter_input.value = new_crown
|
|
975
|
+
updating_params = False
|
|
976
|
+
|
|
977
|
+
def recompute_from_bottom(new_bottom: float):
|
|
978
|
+
nonlocal updating_params
|
|
979
|
+
if base_bottom_ratio <= 0:
|
|
980
|
+
return
|
|
981
|
+
new_top = max(0.0, new_bottom / base_bottom_ratio)
|
|
982
|
+
new_crown = max(0.0, base_crown_ratio * new_top)
|
|
983
|
+
updating_params = True
|
|
984
|
+
top_height_input.value = new_top
|
|
985
|
+
crown_diameter_input.value = new_crown
|
|
986
|
+
updating_params = False
|
|
987
|
+
|
|
988
|
+
def recompute_from_crown(new_crown: float):
|
|
989
|
+
nonlocal updating_params
|
|
990
|
+
if base_crown_ratio <= 0:
|
|
991
|
+
return
|
|
992
|
+
new_top = max(0.0, new_crown / base_crown_ratio)
|
|
993
|
+
new_bottom = max(0.0, base_bottom_ratio * new_top)
|
|
994
|
+
updating_params = True
|
|
995
|
+
top_height_input.value = new_top
|
|
996
|
+
bottom_height_input.value = new_bottom
|
|
997
|
+
updating_params = False
|
|
998
|
+
|
|
999
|
+
def on_toggle_fixed(change):
|
|
1000
|
+
nonlocal base_bottom_ratio, base_crown_ratio
|
|
1001
|
+
if change['name'] == 'value':
|
|
1002
|
+
if change['new']:
|
|
1003
|
+
# Capture current ratios as baseline
|
|
1004
|
+
top = float(top_height_input.value) or 1.0
|
|
1005
|
+
bot = float(bottom_height_input.value)
|
|
1006
|
+
crn = float(crown_diameter_input.value)
|
|
1007
|
+
base_bottom_ratio = max(0.0, bot / top)
|
|
1008
|
+
base_crown_ratio = max(0.0, crn / top)
|
|
1009
|
+
else:
|
|
1010
|
+
# Keep last ratios but do not auto-update
|
|
1011
|
+
pass
|
|
1012
|
+
|
|
1013
|
+
def on_top_change(change):
|
|
1014
|
+
if change['name'] == 'value' and fixed_prop_checkbox.value and not updating_params:
|
|
1015
|
+
try:
|
|
1016
|
+
recompute_from_top(float(change['new']))
|
|
1017
|
+
except Exception:
|
|
1018
|
+
pass
|
|
1019
|
+
|
|
1020
|
+
def on_bottom_change(change):
|
|
1021
|
+
if change['name'] == 'value' and fixed_prop_checkbox.value and not updating_params:
|
|
1022
|
+
try:
|
|
1023
|
+
recompute_from_bottom(float(change['new']))
|
|
1024
|
+
except Exception:
|
|
1025
|
+
pass
|
|
1026
|
+
|
|
1027
|
+
def on_crown_change(change):
|
|
1028
|
+
if change['name'] == 'value' and fixed_prop_checkbox.value and not updating_params:
|
|
1029
|
+
try:
|
|
1030
|
+
recompute_from_crown(float(change['new']))
|
|
1031
|
+
except Exception:
|
|
1032
|
+
pass
|
|
1033
|
+
|
|
1034
|
+
fixed_prop_checkbox.observe(on_toggle_fixed, names='value')
|
|
1035
|
+
top_height_input.observe(on_top_change, names='value')
|
|
1036
|
+
bottom_height_input.observe(on_bottom_change, names='value')
|
|
1037
|
+
crown_diameter_input.observe(on_crown_change, names='value')
|
|
959
1038
|
|
|
960
1039
|
def set_mode(new_mode):
|
|
961
1040
|
nonlocal mode
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|