voxcity 0.5.30__py3-none-any.whl → 0.6.0__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 +58 -49
- voxcity/geoprocessor/grid.py +305 -139
- voxcity/geoprocessor/mesh.py +790 -758
- voxcity/geoprocessor/polygon.py +1343 -1343
- voxcity/simulator/solar.py +2252 -1820
- voxcity/simulator/view.py +2239 -1336
- voxcity/utils/lc.py +21 -100
- voxcity/utils/visualization.py +91 -45
- {voxcity-0.5.30.dist-info → voxcity-0.6.0.dist-info}/METADATA +1 -1
- {voxcity-0.5.30.dist-info → voxcity-0.6.0.dist-info}/RECORD +14 -14
- {voxcity-0.5.30.dist-info → voxcity-0.6.0.dist-info}/WHEEL +0 -0
- {voxcity-0.5.30.dist-info → voxcity-0.6.0.dist-info}/licenses/AUTHORS.rst +0 -0
- {voxcity-0.5.30.dist-info → voxcity-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {voxcity-0.5.30.dist-info → voxcity-0.6.0.dist-info}/top_level.txt +0 -0
voxcity/utils/lc.py
CHANGED
|
@@ -183,114 +183,35 @@ def get_land_cover_classes(source):
|
|
|
183
183
|
|
|
184
184
|
def convert_land_cover(input_array, land_cover_source='Urbanwatch'):
|
|
185
185
|
"""
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
This function maps land cover classes from various data sources to a standardized
|
|
189
|
-
classification system. Each source has different class definitions and indices,
|
|
190
|
-
so this conversion enables consistent processing across different data sources.
|
|
191
|
-
|
|
192
|
-
Args:
|
|
193
|
-
input_array (numpy.ndarray): Input array with source-specific land cover indices
|
|
194
|
-
land_cover_source (str): Name of the source land cover classification system
|
|
195
|
-
Default is 'Urbanwatch'
|
|
196
|
-
|
|
197
|
-
Returns:
|
|
198
|
-
numpy.ndarray: Array with standardized land cover indices
|
|
199
|
-
|
|
200
|
-
Standardized Classification System:
|
|
201
|
-
0: Bareland
|
|
202
|
-
1: Rangeland
|
|
203
|
-
2: Shrub
|
|
204
|
-
3: Agriculture land
|
|
205
|
-
4: Tree
|
|
206
|
-
5: Moss and lichen
|
|
207
|
-
6: Wet land
|
|
208
|
-
7: Mangrove
|
|
209
|
-
8: Water
|
|
210
|
-
9: Snow and ice
|
|
211
|
-
10: Developed space
|
|
212
|
-
11: Road
|
|
213
|
-
12: Building
|
|
214
|
-
13: No Data
|
|
186
|
+
Optimized version using direct numpy array indexing instead of np.vectorize.
|
|
187
|
+
This is 10-100x faster than the original.
|
|
215
188
|
"""
|
|
216
|
-
|
|
189
|
+
# Define mappings
|
|
217
190
|
if land_cover_source == 'Urbanwatch':
|
|
218
|
-
|
|
219
|
-
convert_dict = {
|
|
220
|
-
0: 12, # Building
|
|
221
|
-
1: 11, # Road
|
|
222
|
-
2: 10, # Parking Lot -> Developed space
|
|
223
|
-
3: 4, # Tree Canopy -> Tree
|
|
224
|
-
4: 1, # Grass/Shrub -> Rangeland
|
|
225
|
-
5: 3, # Agriculture -> Agriculture land
|
|
226
|
-
6: 8, # Water
|
|
227
|
-
7: 0, # Barren -> Bareland
|
|
228
|
-
8: 13, # Unknown -> No Data
|
|
229
|
-
9: 8 # Sea -> Water
|
|
230
|
-
}
|
|
191
|
+
mapping = {0: 12, 1: 11, 2: 10, 3: 4, 4: 1, 5: 3, 6: 8, 7: 0, 8: 13, 9: 8}
|
|
231
192
|
elif land_cover_source == 'ESA WorldCover':
|
|
232
|
-
|
|
233
|
-
convert_dict = {
|
|
234
|
-
0: 4, # Trees -> Tree
|
|
235
|
-
1: 2, # Shrubland -> Shrub
|
|
236
|
-
2: 1, # Grassland -> Rangeland
|
|
237
|
-
3: 3, # Cropland -> Agriculture land
|
|
238
|
-
4: 10, # Built-up -> Developed space
|
|
239
|
-
5: 0, # Barren / sparse vegetation -> Bareland
|
|
240
|
-
6: 9, # Snow and ice
|
|
241
|
-
7: 8, # Open water -> Water
|
|
242
|
-
8: 6, # Herbaceous wetland -> Wet land
|
|
243
|
-
9: 7, # Mangroves
|
|
244
|
-
10: 5 # Moss and lichen
|
|
245
|
-
}
|
|
193
|
+
mapping = {0: 4, 1: 2, 2: 1, 3: 3, 4: 10, 5: 0, 6: 9, 7: 8, 8: 6, 9: 7, 10: 5}
|
|
246
194
|
elif land_cover_source == "ESRI 10m Annual Land Cover":
|
|
247
|
-
|
|
248
|
-
convert_dict = {
|
|
249
|
-
0: 13, # No Data
|
|
250
|
-
1: 8, # Water
|
|
251
|
-
2: 4, # Trees -> Tree
|
|
252
|
-
3: 1, # Grass -> Rangeland
|
|
253
|
-
4: 6, # Flooded Vegetation -> Wet land
|
|
254
|
-
5: 3, # Crops -> Agriculture land
|
|
255
|
-
6: 2, # Scrub/Shrub -> Shrub
|
|
256
|
-
7: 10, # Built Area -> Developed space
|
|
257
|
-
8: 0, # Bare Ground -> Bareland
|
|
258
|
-
9: 9, # Snow/Ice
|
|
259
|
-
10: 13 # Clouds -> No Data
|
|
260
|
-
}
|
|
195
|
+
mapping = {0: 13, 1: 8, 2: 4, 3: 1, 4: 6, 5: 3, 6: 2, 7: 10, 8: 0, 9: 9, 10: 13}
|
|
261
196
|
elif land_cover_source == "Dynamic World V1":
|
|
262
|
-
|
|
263
|
-
convert_dict = {
|
|
264
|
-
0: 8, # Water
|
|
265
|
-
1: 4, # Trees -> Tree
|
|
266
|
-
2: 1, # Grass -> Rangeland
|
|
267
|
-
3: 6, # Flooded Vegetation -> Wet land
|
|
268
|
-
4: 3, # Crops -> Agriculture land
|
|
269
|
-
5: 2, # Shrub and Scrub -> Shrub
|
|
270
|
-
6: 10, # Built -> Developed space
|
|
271
|
-
7: 0, # Bare -> Bareland
|
|
272
|
-
8: 9 # Snow and Ice
|
|
273
|
-
}
|
|
197
|
+
mapping = {0: 8, 1: 4, 2: 1, 3: 6, 4: 3, 5: 2, 6: 10, 7: 0, 8: 9}
|
|
274
198
|
elif land_cover_source == "OpenEarthMapJapan":
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
6: 3, # Agriculture land
|
|
284
|
-
7: 12, # Building
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
# Create a vectorized function for the conversion
|
|
288
|
-
vectorized_convert = np.vectorize(lambda x: convert_dict.get(x, x))
|
|
199
|
+
mapping = {0: 0, 1: 1, 2: 10, 3: 11, 4: 4, 5: 8, 6: 3, 7: 12}
|
|
200
|
+
else:
|
|
201
|
+
# If unknown source, return as-is
|
|
202
|
+
return input_array.copy()
|
|
203
|
+
|
|
204
|
+
# Create a full mapping array for all possible values (0-255 for uint8)
|
|
205
|
+
max_val = max(max(mapping.keys()), input_array.max()) + 1
|
|
206
|
+
lookup = np.arange(max_val, dtype=input_array.dtype)
|
|
289
207
|
|
|
290
|
-
# Apply the
|
|
291
|
-
|
|
208
|
+
# Apply the mapping
|
|
209
|
+
for old_val, new_val in mapping.items():
|
|
210
|
+
if old_val < max_val:
|
|
211
|
+
lookup[old_val] = new_val
|
|
292
212
|
|
|
293
|
-
|
|
213
|
+
# Use fancy indexing for fast conversion
|
|
214
|
+
return lookup[input_array]
|
|
294
215
|
|
|
295
216
|
def get_class_priority(source):
|
|
296
217
|
"""
|
voxcity/utils/visualization.py
CHANGED
|
@@ -45,6 +45,7 @@ import trimesh
|
|
|
45
45
|
import pyvista as pv
|
|
46
46
|
from IPython.display import display
|
|
47
47
|
import os
|
|
48
|
+
import sys
|
|
48
49
|
|
|
49
50
|
# Import utility functions for land cover classification
|
|
50
51
|
from .lc import get_land_cover_classes
|
|
@@ -301,7 +302,7 @@ def get_voxel_color_map(color_scheme='default'):
|
|
|
301
302
|
elif color_scheme == 'grayscale':
|
|
302
303
|
return {
|
|
303
304
|
-99: [0, 0, 0], # void (black)
|
|
304
|
-
-30: [
|
|
305
|
+
-30: [253, 231, 37], # (Pink) 'Landmark',
|
|
305
306
|
-17: [240, 240, 240], # 'plaster'
|
|
306
307
|
-16: [60, 60, 60], # 'glass'
|
|
307
308
|
-15: [130, 130, 130], # 'stone'
|
|
@@ -1839,13 +1840,34 @@ def create_multi_view_scene(meshes, output_directory="output", projection_type="
|
|
|
1839
1840
|
>>> views = create_multi_view_scene(meshes, "renders/", "orthographic", 1.5)
|
|
1840
1841
|
>>> print(f"Generated {len(views)} views")
|
|
1841
1842
|
"""
|
|
1842
|
-
#
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1843
|
+
# Precompute PyVista meshes once to avoid repeated conversion per view
|
|
1844
|
+
pv_meshes = {}
|
|
1845
|
+
for class_id, mesh in meshes.items():
|
|
1846
|
+
if mesh is None or len(mesh.vertices) == 0 or len(mesh.faces) == 0:
|
|
1847
|
+
continue
|
|
1848
|
+
# PyVista expects a faces array where each face is prefixed by its vertex count (3 for triangles)
|
|
1849
|
+
faces = np.hstack([[3, *face] for face in mesh.faces])
|
|
1850
|
+
pv_mesh = pv.PolyData(mesh.vertices, faces)
|
|
1851
|
+
# Attach per-cell colors if provided
|
|
1852
|
+
colors = getattr(mesh.visual, 'face_colors', None)
|
|
1853
|
+
if colors is not None:
|
|
1854
|
+
colors = np.asarray(colors)
|
|
1855
|
+
if colors.size and colors.max() > 1:
|
|
1856
|
+
colors = colors / 255.0
|
|
1857
|
+
pv_mesh.cell_data['colors'] = colors
|
|
1858
|
+
pv_meshes[class_id] = pv_mesh
|
|
1859
|
+
|
|
1860
|
+
# Compute overall bounding box across all meshes without stacking
|
|
1861
|
+
min_xyz = np.array([np.inf, np.inf, np.inf], dtype=float)
|
|
1862
|
+
max_xyz = np.array([-np.inf, -np.inf, -np.inf], dtype=float)
|
|
1863
|
+
for mesh in meshes.values():
|
|
1864
|
+
if mesh is None or len(mesh.vertices) == 0:
|
|
1865
|
+
continue
|
|
1866
|
+
v = mesh.vertices
|
|
1867
|
+
# update mins and maxs
|
|
1868
|
+
min_xyz = np.minimum(min_xyz, v.min(axis=0))
|
|
1869
|
+
max_xyz = np.maximum(max_xyz, v.max(axis=0))
|
|
1870
|
+
bbox = np.vstack([min_xyz, max_xyz])
|
|
1849
1871
|
|
|
1850
1872
|
# Compute the center and diagonal of the bounding box
|
|
1851
1873
|
center = (bbox[1] + bbox[0]) / 2
|
|
@@ -1897,21 +1919,14 @@ def create_multi_view_scene(meshes, output_directory="output", projection_type="
|
|
|
1897
1919
|
elif projection_type.lower() != "perspective":
|
|
1898
1920
|
print(f"Warning: Unknown projection_type '{projection_type}'. Using perspective projection.")
|
|
1899
1921
|
|
|
1900
|
-
# Add each mesh to the scene
|
|
1901
|
-
for class_id,
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
if colors.max() > 1:
|
|
1909
|
-
colors = colors / 255.0
|
|
1910
|
-
pv_mesh.cell_data['colors'] = colors
|
|
1911
|
-
|
|
1912
|
-
plotter.add_mesh(pv_mesh,
|
|
1913
|
-
rgb=True,
|
|
1914
|
-
scalars='colors' if hasattr(mesh.visual, 'face_colors') else None)
|
|
1922
|
+
# Add each precomputed mesh to the scene
|
|
1923
|
+
for class_id, pv_mesh in pv_meshes.items():
|
|
1924
|
+
has_colors = 'colors' in pv_mesh.cell_data
|
|
1925
|
+
plotter.add_mesh(
|
|
1926
|
+
pv_mesh,
|
|
1927
|
+
rgb=True,
|
|
1928
|
+
scalars='colors' if has_colors else None
|
|
1929
|
+
)
|
|
1915
1930
|
|
|
1916
1931
|
# Set camera position for this view
|
|
1917
1932
|
plotter.camera_position = camera_pos
|
|
@@ -2350,8 +2365,11 @@ def visualize_voxcity_with_sim_meshes(voxel_array, meshsize, custom_meshes=None,
|
|
|
2350
2365
|
- visualize_voxcity_multi_view(): Basic voxel visualization without custom meshes
|
|
2351
2366
|
- create_multi_view_scene(): Lower-level rendering function
|
|
2352
2367
|
"""
|
|
2353
|
-
|
|
2354
|
-
|
|
2368
|
+
# Setup offscreen rendering only when needed and supported
|
|
2369
|
+
if sys.platform.startswith('linux'):
|
|
2370
|
+
if 'DISPLAY' not in os.environ:
|
|
2371
|
+
os.system('Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &')
|
|
2372
|
+
os.environ['DISPLAY'] = ':99'
|
|
2355
2373
|
|
|
2356
2374
|
# Configure PyVista settings
|
|
2357
2375
|
pv.set_plot_theme('document')
|
|
@@ -2381,13 +2399,25 @@ def visualize_voxcity_with_sim_meshes(voxel_array, meshsize, custom_meshes=None,
|
|
|
2381
2399
|
nan_color = kwargs.get("nan_color", "gray")
|
|
2382
2400
|
show_views = kwargs.get("show_views", True)
|
|
2383
2401
|
save_obj = kwargs.get("save_obj", False)
|
|
2402
|
+
include_classes = kwargs.get("include_classes", None)
|
|
2403
|
+
exclude_classes = kwargs.get("exclude_classes", None)
|
|
2404
|
+
copy_custom_mesh = kwargs.get("copy_custom_mesh", False)
|
|
2384
2405
|
|
|
2385
2406
|
if value_name is None:
|
|
2386
2407
|
print("Set value_name")
|
|
2387
2408
|
|
|
2388
2409
|
# Create meshes from voxel data
|
|
2389
2410
|
print("Creating voxel meshes...")
|
|
2390
|
-
meshes
|
|
2411
|
+
# Skip generating voxel meshes for classes that will be replaced by custom meshes
|
|
2412
|
+
if exclude_classes is None and custom_meshes is not None:
|
|
2413
|
+
exclude_classes = list(custom_meshes.keys())
|
|
2414
|
+
meshes = create_city_meshes(
|
|
2415
|
+
voxel_array,
|
|
2416
|
+
vox_dict,
|
|
2417
|
+
meshsize=meshsize,
|
|
2418
|
+
include_classes=include_classes,
|
|
2419
|
+
exclude_classes=exclude_classes,
|
|
2420
|
+
)
|
|
2391
2421
|
|
|
2392
2422
|
# Replace specific voxel class meshes with custom simulation meshes
|
|
2393
2423
|
if custom_meshes is not None:
|
|
@@ -2399,18 +2429,23 @@ def visualize_voxcity_with_sim_meshes(voxel_array, meshsize, custom_meshes=None,
|
|
|
2399
2429
|
import matplotlib.colors as mcolors
|
|
2400
2430
|
|
|
2401
2431
|
# Get values from metadata
|
|
2402
|
-
values = custom_mesh.metadata[value_name]
|
|
2432
|
+
values = np.asarray(custom_mesh.metadata[value_name])
|
|
2403
2433
|
|
|
2404
2434
|
# Set vmin/vmax if not provided
|
|
2405
|
-
|
|
2406
|
-
|
|
2435
|
+
finite_mask = np.isfinite(values)
|
|
2436
|
+
if not np.any(finite_mask):
|
|
2437
|
+
local_vmin = 0.0 if vmin is None else vmin
|
|
2438
|
+
local_vmax = 1.0 if vmax is None else vmax
|
|
2439
|
+
else:
|
|
2440
|
+
local_vmin = vmin if vmin is not None else float(np.nanmin(values[finite_mask]))
|
|
2441
|
+
local_vmax = vmax if vmax is not None else float(np.nanmax(values[finite_mask]))
|
|
2407
2442
|
|
|
2408
2443
|
# Create colors
|
|
2409
2444
|
cmap = cm.get_cmap(cmap_name)
|
|
2410
2445
|
norm = mcolors.Normalize(vmin=local_vmin, vmax=local_vmax)
|
|
2411
2446
|
|
|
2412
2447
|
# Handle NaN values with custom color
|
|
2413
|
-
face_colors = np.zeros((len(values), 4))
|
|
2448
|
+
face_colors = np.zeros((len(values), 4), dtype=float)
|
|
2414
2449
|
|
|
2415
2450
|
# Convert string color to RGBA if needed
|
|
2416
2451
|
if isinstance(nan_color, str):
|
|
@@ -2421,25 +2456,25 @@ def visualize_voxcity_with_sim_meshes(voxel_array, meshsize, custom_meshes=None,
|
|
|
2421
2456
|
nan_rgba = np.array(nan_color)
|
|
2422
2457
|
|
|
2423
2458
|
# Apply colors: NaN values get nan_color, others get colormap colors
|
|
2424
|
-
nan_mask =
|
|
2459
|
+
nan_mask = ~finite_mask
|
|
2425
2460
|
face_colors[~nan_mask] = cmap(norm(values[~nan_mask]))
|
|
2426
2461
|
face_colors[nan_mask] = nan_rgba
|
|
2427
2462
|
|
|
2428
2463
|
# Create a copy with colors
|
|
2429
|
-
vis_mesh = custom_mesh.copy()
|
|
2464
|
+
vis_mesh = custom_mesh.copy() if copy_custom_mesh else custom_mesh
|
|
2430
2465
|
vis_mesh.visual.face_colors = face_colors
|
|
2431
2466
|
|
|
2432
|
-
# Prepare the colormap and create colorbar
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2467
|
+
# Prepare the colormap and create colorbar if views will be shown
|
|
2468
|
+
if show_views:
|
|
2469
|
+
norm = mcolors.Normalize(vmin=local_vmin, vmax=local_vmax)
|
|
2470
|
+
scalar_map = cm.ScalarMappable(norm=norm, cmap=cmap_name)
|
|
2471
|
+
fig, ax = plt.subplots(figsize=(6, 1))
|
|
2472
|
+
cbar = plt.colorbar(scalar_map, cax=ax, orientation='horizontal')
|
|
2473
|
+
if colorbar_title:
|
|
2474
|
+
cbar.set_label(colorbar_title)
|
|
2475
|
+
plt.tight_layout()
|
|
2476
|
+
plt.show()
|
|
2477
|
+
plt.close(fig)
|
|
2443
2478
|
|
|
2444
2479
|
if class_id in meshes:
|
|
2445
2480
|
print(f"Replacing voxel class {class_id} with colored custom simulation mesh")
|
|
@@ -2504,8 +2539,12 @@ def visualize_voxcity_with_sim_meshes(voxel_array, meshsize, custom_meshes=None,
|
|
|
2504
2539
|
if save_obj:
|
|
2505
2540
|
output_directory = kwargs.get('output_directory', 'output')
|
|
2506
2541
|
output_file_name = kwargs.get('output_file_name', 'voxcity_mesh')
|
|
2507
|
-
|
|
2508
|
-
|
|
2542
|
+
# Default: do NOT quantize to preserve exact face colors like in images
|
|
2543
|
+
max_materials = kwargs.get('max_materials', None)
|
|
2544
|
+
if max_materials is None:
|
|
2545
|
+
obj_path, mtl_path = save_obj_from_colored_mesh(meshes, output_directory, output_file_name)
|
|
2546
|
+
else:
|
|
2547
|
+
obj_path, mtl_path = save_obj_from_colored_mesh(meshes, output_directory, output_file_name, max_materials=max_materials)
|
|
2509
2548
|
print(f"Saved mesh files to:\n {obj_path}\n {mtl_path}")
|
|
2510
2549
|
|
|
2511
2550
|
if show_views:
|
|
@@ -2559,6 +2598,13 @@ def visualize_building_sim_results(voxel_array, meshsize, building_sim_mesh, **k
|
|
|
2559
2598
|
|
|
2560
2599
|
# Create custom meshes dictionary with the building simulation mesh
|
|
2561
2600
|
custom_meshes = {building_class_id: building_sim_mesh}
|
|
2601
|
+
|
|
2602
|
+
# Performance: skip voxel mesh generation for building class by default
|
|
2603
|
+
if "include_classes" not in kwargs and "exclude_classes" not in kwargs:
|
|
2604
|
+
kwargs["exclude_classes"] = [building_class_id]
|
|
2605
|
+
|
|
2606
|
+
# Memory-safety: do not duplicate the provided mesh unless requested
|
|
2607
|
+
kwargs.setdefault("copy_custom_mesh", False)
|
|
2562
2608
|
|
|
2563
2609
|
# Add colorbar title if not provided
|
|
2564
2610
|
if "colorbar_title" not in kwargs:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: voxcity
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
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=
|
|
2
|
+
voxcity/generator.py,sha256=mnwlmfFr-23_ZytPSeU-5SpHklO30w5b8NbNOQLemik,54983
|
|
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
|
|
@@ -16,23 +16,23 @@ voxcity/exporter/magicavoxel.py,sha256=SfGEgTZRlossKx3Xrv9d3iKSX-HmfQJEL9lZHgWMD
|
|
|
16
16
|
voxcity/exporter/obj.py,sha256=h1_aInpemcsu96fSTwjKMqX2VZAFYbZbElWd4M1ogyI,27973
|
|
17
17
|
voxcity/geoprocessor/__init__.py,sha256=JzPVhhttxBWvaZ0IGX2w7OWL5bCo_TIvpHefWeNXruA,133
|
|
18
18
|
voxcity/geoprocessor/draw.py,sha256=avXQwbGQWG3ZPPI8mwy0YN0K_aG4NMBdXI0vDg7yad0,35837
|
|
19
|
-
voxcity/geoprocessor/grid.py,sha256=
|
|
20
|
-
voxcity/geoprocessor/mesh.py,sha256
|
|
19
|
+
voxcity/geoprocessor/grid.py,sha256=uIfEE-2rfT274QKN9qnyXu3E2nCwaUHiuxHra2iclZM,71186
|
|
20
|
+
voxcity/geoprocessor/mesh.py,sha256=-r_3EGL3PZr-QngMOXrwKllYA4o0moDj0-bZvU0mlOo,31237
|
|
21
21
|
voxcity/geoprocessor/network.py,sha256=YynqR0nq_NUra_cQ3Z_56KxfRia1b6-hIzGCj3QT-wE,25137
|
|
22
|
-
voxcity/geoprocessor/polygon.py,sha256
|
|
22
|
+
voxcity/geoprocessor/polygon.py,sha256=DfzXf6R-qoWXEZv1z1aHCVfr-DCuCFw6lieQT5cNHPA,61188
|
|
23
23
|
voxcity/geoprocessor/utils.py,sha256=DVg3EMRytLQLEQeXLvNgjt1Ynoa689EsD-To-14xgSQ,30369
|
|
24
24
|
voxcity/simulator/__init__.py,sha256=APdkcdaovj0v_RPOaA4SBvFUKT2RM7Hxuuz3Sux4gCo,65
|
|
25
|
-
voxcity/simulator/solar.py,sha256=
|
|
25
|
+
voxcity/simulator/solar.py,sha256=h_jVPjJ8wKl8z8Tx0EcVJBzNRKSr8WXBL9bVCgJpyZE,101788
|
|
26
26
|
voxcity/simulator/utils.py,sha256=sEYBB2-hLJxTiXQps1_-Fi7t1HN3-1OPOvBCWtgIisA,130
|
|
27
|
-
voxcity/simulator/view.py,sha256=
|
|
27
|
+
voxcity/simulator/view.py,sha256=W6QtoSnLSQPEPtTy5B6BB5l0UGQ5Vs-Bt1ISNZKdGTI,92020
|
|
28
28
|
voxcity/utils/__init__.py,sha256=Q-NYCqYnAAaF80KuNwpqIjbE7Ec3Gr4y_khMLIMhJrg,68
|
|
29
|
-
voxcity/utils/lc.py,sha256=
|
|
29
|
+
voxcity/utils/lc.py,sha256=722Gz3lPbgAp0mmTZ-g-QKBbAnbxrcgaYwb1sa7q8Sk,16189
|
|
30
30
|
voxcity/utils/material.py,sha256=H8K8Lq4wBL6dQtgj7esUW2U6wLCOTeOtelkTDJoRgMo,10007
|
|
31
|
-
voxcity/utils/visualization.py,sha256=
|
|
31
|
+
voxcity/utils/visualization.py,sha256=Hk31pVOZ3q8K0QaudAMSqKUquF1Hd1Hug8626D4JJ74,115143
|
|
32
32
|
voxcity/utils/weather.py,sha256=2Jtg-rIVJcsTtiKE-KuDnhIqS1-MSS16_zFRzj6zmu4,36435
|
|
33
|
-
voxcity-0.
|
|
34
|
-
voxcity-0.
|
|
35
|
-
voxcity-0.
|
|
36
|
-
voxcity-0.
|
|
37
|
-
voxcity-0.
|
|
38
|
-
voxcity-0.
|
|
33
|
+
voxcity-0.6.0.dist-info/licenses/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
|
|
34
|
+
voxcity-0.6.0.dist-info/licenses/LICENSE,sha256=s_jE1Df1nTPL4A_5GCGic5Zwex0CVaPKcAmSilxJPPE,1089
|
|
35
|
+
voxcity-0.6.0.dist-info/METADATA,sha256=C-1oyOYd7anMYVqYfTIH_zJWNDqpRL5v5bvcYgsYPkI,26723
|
|
36
|
+
voxcity-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
37
|
+
voxcity-0.6.0.dist-info/top_level.txt,sha256=00b2U-LKfDllt6RL1R33MXie5MvxzUFye0NGD96t_8I,8
|
|
38
|
+
voxcity-0.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|