voxcity 0.5.23__tar.gz → 0.5.25__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.5.23 → voxcity-0.5.25}/PKG-INFO +2 -1
- {voxcity-0.5.23 → voxcity-0.5.25}/pyproject.toml +3 -2
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/geoprocessor/mesh.py +46 -2
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/utils/visualization.py +18 -17
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity.egg-info/PKG-INFO +2 -1
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity.egg-info/requires.txt +1 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/AUTHORS.rst +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/CONTRIBUTING.rst +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/HISTORY.rst +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/LICENSE +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/MANIFEST.in +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/README.md +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/docs/Makefile +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/docs/_static/logo.png +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/docs/conf.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/docs/logo.png +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/docs/make.bat +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/setup.cfg +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/__init__.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/downloader/__init__.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/downloader/citygml.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/downloader/eubucco.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/downloader/gee.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/downloader/mbfp.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/downloader/oemj.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/downloader/osm.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/downloader/overture.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/downloader/utils.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/exporter/__init__.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/exporter/envimet.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/exporter/magicavoxel.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/exporter/obj.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/generator.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/geoprocessor/__init__.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/geoprocessor/draw.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/geoprocessor/grid.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/geoprocessor/network.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/geoprocessor/polygon.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/geoprocessor/utils.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/simulator/__init__.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/simulator/solar.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/simulator/utils.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/simulator/view.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/utils/__init__.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/utils/lc.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/utils/material.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity/utils/weather.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity.egg-info/SOURCES.txt +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity.egg-info/dependency_links.txt +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/src/voxcity.egg-info/top_level.txt +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/tests/__init__.py +0 -0
- {voxcity-0.5.23 → voxcity-0.5.25}/tests/voxelcity.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: voxcity
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.25
|
|
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>
|
|
@@ -52,6 +52,7 @@ Requires-Dist: trimesh
|
|
|
52
52
|
Requires-Dist: pyvista
|
|
53
53
|
Requires-Dist: IPython
|
|
54
54
|
Requires-Dist: lxml
|
|
55
|
+
Requires-Dist: scikit-learn
|
|
55
56
|
Provides-Extra: dev
|
|
56
57
|
Requires-Dist: coverage; extra == "dev"
|
|
57
58
|
Requires-Dist: mypy; extra == "dev"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "voxcity"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.25"
|
|
4
4
|
requires-python = ">=3.10,<3.13"
|
|
5
5
|
classifiers = [
|
|
6
6
|
"Programming Language :: Python :: 3.10",
|
|
@@ -53,7 +53,8 @@ dependencies = [
|
|
|
53
53
|
"trimesh",
|
|
54
54
|
"pyvista",
|
|
55
55
|
"IPython",
|
|
56
|
-
"lxml"
|
|
56
|
+
"lxml",
|
|
57
|
+
"scikit-learn"
|
|
57
58
|
]
|
|
58
59
|
|
|
59
60
|
[project.optional-dependencies]
|
|
@@ -590,7 +590,7 @@ def split_vertices_manual(mesh):
|
|
|
590
590
|
out_mesh = trimesh.util.concatenate(new_meshes)
|
|
591
591
|
return out_mesh
|
|
592
592
|
|
|
593
|
-
def save_obj_from_colored_mesh(meshes, output_path, base_filename):
|
|
593
|
+
def save_obj_from_colored_mesh(meshes, output_path, base_filename, max_materials=None):
|
|
594
594
|
"""
|
|
595
595
|
Save a collection of colored meshes as OBJ and MTL files with material support.
|
|
596
596
|
|
|
@@ -620,6 +620,12 @@ def save_obj_from_colored_mesh(meshes, output_path, base_filename):
|
|
|
620
620
|
- {base_filename}.obj : The main geometry file
|
|
621
621
|
- {base_filename}.mtl : The material definitions file
|
|
622
622
|
|
|
623
|
+
max_materials : int, optional
|
|
624
|
+
Maximum number of materials/colors to create. If specified and the number
|
|
625
|
+
of unique colors exceeds this limit, colors will be quantized using
|
|
626
|
+
k-means clustering to reduce them to the specified number.
|
|
627
|
+
If None (default), all unique colors are preserved as separate materials.
|
|
628
|
+
|
|
623
629
|
Returns
|
|
624
630
|
-------
|
|
625
631
|
tuple
|
|
@@ -644,6 +650,11 @@ def save_obj_from_colored_mesh(meshes, output_path, base_filename):
|
|
|
644
650
|
... meshes, 'output/models', 'city'
|
|
645
651
|
... )
|
|
646
652
|
|
|
653
|
+
Limiting materials to 5:
|
|
654
|
+
>>> obj_path, mtl_path = save_obj_from_colored_mesh(
|
|
655
|
+
... meshes, 'output/models', 'city', max_materials=5
|
|
656
|
+
... )
|
|
657
|
+
|
|
647
658
|
Notes
|
|
648
659
|
-----
|
|
649
660
|
- Creates unique materials for each distinct face color
|
|
@@ -653,6 +664,9 @@ def save_obj_from_colored_mesh(meshes, output_path, base_filename):
|
|
|
653
664
|
- Vertices are written in OBJ's 1-based indexing format
|
|
654
665
|
- Faces are grouped by material for efficient rendering
|
|
655
666
|
- The MTL file is automatically referenced in the OBJ file
|
|
667
|
+
- If max_materials is specified, k-means clustering is used for color quantization
|
|
668
|
+
- Color quantization preserves the overall color distribution while reducing material count
|
|
669
|
+
- Requires scikit-learn package when max_materials is specified (install with: pip install scikit-learn)
|
|
656
670
|
|
|
657
671
|
File Format Details
|
|
658
672
|
-----------------
|
|
@@ -674,8 +688,38 @@ def save_obj_from_colored_mesh(meshes, output_path, base_filename):
|
|
|
674
688
|
combined_mesh = trimesh.util.concatenate(list(meshes.values()))
|
|
675
689
|
combined_mesh = split_vertices_manual(combined_mesh)
|
|
676
690
|
|
|
677
|
-
#
|
|
691
|
+
# Get face colors
|
|
678
692
|
face_colors = combined_mesh.visual.face_colors
|
|
693
|
+
|
|
694
|
+
# Apply color quantization if max_materials is specified
|
|
695
|
+
if max_materials is not None:
|
|
696
|
+
try:
|
|
697
|
+
from sklearn.cluster import KMeans
|
|
698
|
+
except ImportError:
|
|
699
|
+
raise ImportError("scikit-learn is required for color quantization. "
|
|
700
|
+
"Install it with: pip install scikit-learn")
|
|
701
|
+
|
|
702
|
+
# Prepare colors for clustering (use only RGB, not alpha)
|
|
703
|
+
colors_rgb = face_colors[:, :3].astype(float)
|
|
704
|
+
|
|
705
|
+
# Perform k-means clustering
|
|
706
|
+
kmeans = KMeans(n_clusters=max_materials, random_state=42, n_init=10)
|
|
707
|
+
color_labels = kmeans.fit_predict(colors_rgb)
|
|
708
|
+
|
|
709
|
+
# Get the cluster centers as the new colors
|
|
710
|
+
quantized_colors_rgb = kmeans.cluster_centers_.astype(np.uint8)
|
|
711
|
+
|
|
712
|
+
# Create new face colors with quantized RGB and original alpha
|
|
713
|
+
quantized_face_colors = np.zeros_like(face_colors)
|
|
714
|
+
# Assign each face to its nearest cluster center
|
|
715
|
+
quantized_face_colors[:, :3] = quantized_colors_rgb[color_labels]
|
|
716
|
+
quantized_face_colors[:, 3] = face_colors[:, 3] # Preserve original alpha
|
|
717
|
+
|
|
718
|
+
# Update the mesh with quantized colors
|
|
719
|
+
combined_mesh.visual.face_colors = quantized_face_colors
|
|
720
|
+
face_colors = quantized_face_colors
|
|
721
|
+
|
|
722
|
+
# Create unique materials for each unique face color
|
|
679
723
|
unique_colors = np.unique(face_colors, axis=0)
|
|
680
724
|
|
|
681
725
|
# Write MTL file
|
|
@@ -2490,20 +2490,27 @@ def visualize_voxcity_with_sim_meshes(voxel_array, meshsize, custom_meshes=None,
|
|
|
2490
2490
|
# plt.tight_layout()
|
|
2491
2491
|
# plt.show()
|
|
2492
2492
|
|
|
2493
|
-
# Export if filename provided
|
|
2494
|
-
if base_filename is not None:
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2493
|
+
# # Export if filename provided
|
|
2494
|
+
# if base_filename is not None:
|
|
2495
|
+
# print(f"Exporting files to '{base_filename}.*' ...")
|
|
2496
|
+
# # Create output directory if it doesn't exist
|
|
2497
|
+
# os.makedirs(output_directory, exist_ok=True)
|
|
2498
|
+
# export_meshes(meshes, output_directory, base_filename)
|
|
2500
2499
|
|
|
2501
|
-
# Create and save multiple views
|
|
2502
|
-
print("Creating multiple views...")
|
|
2503
2500
|
# Create output directory if it doesn't exist
|
|
2504
2501
|
os.makedirs(output_directory, exist_ok=True)
|
|
2505
2502
|
|
|
2503
|
+
# After creating the meshes and before visualization
|
|
2504
|
+
if save_obj:
|
|
2505
|
+
output_directory = kwargs.get('output_directory', 'output')
|
|
2506
|
+
output_file_name = kwargs.get('output_file_name', 'voxcity_mesh')
|
|
2507
|
+
max_materials = kwargs.get('max_materials', 20)
|
|
2508
|
+
obj_path, mtl_path = save_obj_from_colored_mesh(meshes, output_directory, output_file_name, max_materials=max_materials)
|
|
2509
|
+
print(f"Saved mesh files to:\n {obj_path}\n {mtl_path}")
|
|
2510
|
+
|
|
2506
2511
|
if show_views:
|
|
2512
|
+
# Create and save multiple views
|
|
2513
|
+
print("Creating multiple views...")
|
|
2507
2514
|
image_files = create_multi_view_scene(meshes, output_directory=output_directory,
|
|
2508
2515
|
projection_type=projection_type,
|
|
2509
2516
|
distance_factor=distance_factor)
|
|
@@ -2516,14 +2523,8 @@ def visualize_voxcity_with_sim_meshes(voxel_array, meshsize, custom_meshes=None,
|
|
|
2516
2523
|
plt.title(view_name.replace('_', ' ').title(), pad=20)
|
|
2517
2524
|
plt.axis('off')
|
|
2518
2525
|
plt.show()
|
|
2519
|
-
plt.close()
|
|
2520
|
-
|
|
2521
|
-
# After creating the meshes and before visualization
|
|
2522
|
-
if save_obj:
|
|
2523
|
-
output_directory = kwargs.get('output_directory', 'output')
|
|
2524
|
-
output_file_name = kwargs.get('output_file_name', 'voxcity_mesh')
|
|
2525
|
-
obj_path, mtl_path = save_obj_from_colored_mesh(meshes, output_directory, output_file_name)
|
|
2526
|
-
print(f"Saved mesh files to:\n {obj_path}\n {mtl_path}")
|
|
2526
|
+
plt.close()
|
|
2527
|
+
|
|
2527
2528
|
|
|
2528
2529
|
def visualize_building_sim_results(voxel_array, meshsize, building_sim_mesh, **kwargs):
|
|
2529
2530
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: voxcity
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.25
|
|
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>
|
|
@@ -52,6 +52,7 @@ Requires-Dist: trimesh
|
|
|
52
52
|
Requires-Dist: pyvista
|
|
53
53
|
Requires-Dist: IPython
|
|
54
54
|
Requires-Dist: lxml
|
|
55
|
+
Requires-Dist: scikit-learn
|
|
55
56
|
Provides-Extra: dev
|
|
56
57
|
Requires-Dist: coverage; extra == "dev"
|
|
57
58
|
Requires-Dist: mypy; extra == "dev"
|
|
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
|
|
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
|