voxcity 0.7.0__py3-none-any.whl → 1.0.2__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.
Files changed (42) hide show
  1. voxcity/__init__.py +14 -14
  2. voxcity/exporter/__init__.py +12 -12
  3. voxcity/exporter/cityles.py +633 -633
  4. voxcity/exporter/envimet.py +733 -728
  5. voxcity/exporter/magicavoxel.py +333 -333
  6. voxcity/exporter/netcdf.py +238 -238
  7. voxcity/exporter/obj.py +1480 -1480
  8. voxcity/generator/__init__.py +47 -44
  9. voxcity/generator/api.py +721 -675
  10. voxcity/generator/grids.py +381 -379
  11. voxcity/generator/io.py +94 -94
  12. voxcity/generator/pipeline.py +282 -282
  13. voxcity/generator/update.py +429 -0
  14. voxcity/generator/voxelizer.py +18 -6
  15. voxcity/geoprocessor/__init__.py +75 -75
  16. voxcity/geoprocessor/draw.py +1488 -1219
  17. voxcity/geoprocessor/merge_utils.py +91 -91
  18. voxcity/geoprocessor/mesh.py +806 -806
  19. voxcity/geoprocessor/network.py +708 -708
  20. voxcity/geoprocessor/raster/buildings.py +435 -428
  21. voxcity/geoprocessor/raster/export.py +93 -93
  22. voxcity/geoprocessor/raster/landcover.py +5 -2
  23. voxcity/geoprocessor/utils.py +824 -824
  24. voxcity/models.py +113 -113
  25. voxcity/simulator/solar/__init__.py +66 -43
  26. voxcity/simulator/solar/integration.py +336 -336
  27. voxcity/simulator/solar/sky.py +668 -0
  28. voxcity/simulator/solar/temporal.py +792 -434
  29. voxcity/utils/__init__.py +11 -0
  30. voxcity/utils/classes.py +194 -0
  31. voxcity/utils/lc.py +80 -39
  32. voxcity/utils/shape.py +230 -0
  33. voxcity/visualizer/__init__.py +24 -24
  34. voxcity/visualizer/builder.py +43 -43
  35. voxcity/visualizer/grids.py +141 -141
  36. voxcity/visualizer/maps.py +187 -187
  37. voxcity/visualizer/renderer.py +1145 -928
  38. {voxcity-0.7.0.dist-info → voxcity-1.0.2.dist-info}/METADATA +90 -49
  39. {voxcity-0.7.0.dist-info → voxcity-1.0.2.dist-info}/RECORD +42 -38
  40. {voxcity-0.7.0.dist-info → voxcity-1.0.2.dist-info}/WHEEL +0 -0
  41. {voxcity-0.7.0.dist-info → voxcity-1.0.2.dist-info}/licenses/AUTHORS.rst +0 -0
  42. {voxcity-0.7.0.dist-info → voxcity-1.0.2.dist-info}/licenses/LICENSE +0 -0
voxcity/models.py CHANGED
@@ -1,113 +1,113 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass, field
4
- from typing import Tuple, Optional, Dict, Any
5
-
6
- import numpy as np
7
-
8
-
9
- @dataclass
10
- class GridMetadata:
11
- crs: str
12
- bounds: Tuple[float, float, float, float]
13
- meshsize: float
14
-
15
-
16
- @dataclass
17
- class BuildingGrid:
18
- heights: np.ndarray
19
- min_heights: np.ndarray # object-dtype array of lists per cell
20
- ids: np.ndarray
21
- meta: GridMetadata
22
-
23
-
24
- @dataclass
25
- class LandCoverGrid:
26
- classes: np.ndarray
27
- meta: GridMetadata
28
-
29
-
30
- @dataclass
31
- class DemGrid:
32
- elevation: np.ndarray
33
- meta: GridMetadata
34
-
35
-
36
- @dataclass
37
- class VoxelGrid:
38
- classes: np.ndarray
39
- meta: GridMetadata
40
-
41
-
42
- @dataclass
43
- class CanopyGrid:
44
- top: np.ndarray
45
- meta: GridMetadata
46
- bottom: Optional[np.ndarray] = None
47
-
48
-
49
- @dataclass
50
- class VoxCity:
51
- voxels: VoxelGrid
52
- buildings: BuildingGrid
53
- land_cover: LandCoverGrid
54
- dem: DemGrid
55
- tree_canopy: CanopyGrid
56
- extras: Dict[str, Any] = field(default_factory=dict)
57
-
58
-
59
- @dataclass
60
- class PipelineConfig:
61
- rectangle_vertices: Any
62
- meshsize: float
63
- building_source: Optional[str] = None
64
- land_cover_source: Optional[str] = None
65
- canopy_height_source: Optional[str] = None
66
- dem_source: Optional[str] = None
67
- output_dir: str = "output"
68
- trunk_height_ratio: Optional[float] = None
69
- static_tree_height: Optional[float] = None
70
- remove_perimeter_object: Optional[float] = None
71
- mapvis: bool = False
72
- gridvis: bool = True
73
- # Structured options for strategies and I/O/visualization
74
- land_cover_options: Dict[str, Any] = field(default_factory=dict)
75
- building_options: Dict[str, Any] = field(default_factory=dict)
76
- canopy_options: Dict[str, Any] = field(default_factory=dict)
77
- dem_options: Dict[str, Any] = field(default_factory=dict)
78
- io_options: Dict[str, Any] = field(default_factory=dict)
79
- visualize_options: Dict[str, Any] = field(default_factory=dict)
80
-
81
-
82
- # -----------------------------
83
- # Mesh data structures
84
- # -----------------------------
85
-
86
- @dataclass
87
- class MeshModel:
88
- vertices: np.ndarray # (N, 3) float
89
- faces: np.ndarray # (M, 3|4) int
90
- colors: Optional[np.ndarray] = None # (M, 4) uint8 or None
91
- name: Optional[str] = None
92
-
93
-
94
- @dataclass
95
- class MeshCollection:
96
- """Container for named meshes with simple add/access helpers."""
97
- meshes: Dict[str, MeshModel] = field(default_factory=dict)
98
-
99
- def add(self, name: str, mesh: MeshModel) -> None:
100
- self.meshes[name] = mesh
101
-
102
- def get(self, name: str) -> Optional[MeshModel]:
103
- return self.meshes.get(name)
104
-
105
- def __iter__(self):
106
- return iter(self.meshes.items())
107
-
108
- # Compatibility: some renderers expect `collection.items.items()`
109
- @property
110
- def items(self) -> Dict[str, MeshModel]:
111
- return self.meshes
112
-
113
-
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import Tuple, Optional, Dict, Any
5
+
6
+ import numpy as np
7
+
8
+
9
+ @dataclass
10
+ class GridMetadata:
11
+ crs: str
12
+ bounds: Tuple[float, float, float, float]
13
+ meshsize: float
14
+
15
+
16
+ @dataclass
17
+ class BuildingGrid:
18
+ heights: np.ndarray
19
+ min_heights: np.ndarray # object-dtype array of lists per cell
20
+ ids: np.ndarray
21
+ meta: GridMetadata
22
+
23
+
24
+ @dataclass
25
+ class LandCoverGrid:
26
+ classes: np.ndarray
27
+ meta: GridMetadata
28
+
29
+
30
+ @dataclass
31
+ class DemGrid:
32
+ elevation: np.ndarray
33
+ meta: GridMetadata
34
+
35
+
36
+ @dataclass
37
+ class VoxelGrid:
38
+ classes: np.ndarray
39
+ meta: GridMetadata
40
+
41
+
42
+ @dataclass
43
+ class CanopyGrid:
44
+ top: np.ndarray
45
+ meta: GridMetadata
46
+ bottom: Optional[np.ndarray] = None
47
+
48
+
49
+ @dataclass
50
+ class VoxCity:
51
+ voxels: VoxelGrid
52
+ buildings: BuildingGrid
53
+ land_cover: LandCoverGrid
54
+ dem: DemGrid
55
+ tree_canopy: CanopyGrid
56
+ extras: Dict[str, Any] = field(default_factory=dict)
57
+
58
+
59
+ @dataclass
60
+ class PipelineConfig:
61
+ rectangle_vertices: Any
62
+ meshsize: float
63
+ building_source: Optional[str] = None
64
+ land_cover_source: Optional[str] = None
65
+ canopy_height_source: Optional[str] = None
66
+ dem_source: Optional[str] = None
67
+ output_dir: str = "output"
68
+ trunk_height_ratio: Optional[float] = None
69
+ static_tree_height: Optional[float] = None
70
+ remove_perimeter_object: Optional[float] = None
71
+ mapvis: bool = False
72
+ gridvis: bool = True
73
+ # Structured options for strategies and I/O/visualization
74
+ land_cover_options: Dict[str, Any] = field(default_factory=dict)
75
+ building_options: Dict[str, Any] = field(default_factory=dict)
76
+ canopy_options: Dict[str, Any] = field(default_factory=dict)
77
+ dem_options: Dict[str, Any] = field(default_factory=dict)
78
+ io_options: Dict[str, Any] = field(default_factory=dict)
79
+ visualize_options: Dict[str, Any] = field(default_factory=dict)
80
+
81
+
82
+ # -----------------------------
83
+ # Mesh data structures
84
+ # -----------------------------
85
+
86
+ @dataclass
87
+ class MeshModel:
88
+ vertices: np.ndarray # (N, 3) float
89
+ faces: np.ndarray # (M, 3|4) int
90
+ colors: Optional[np.ndarray] = None # (M, 4) uint8 or None
91
+ name: Optional[str] = None
92
+
93
+
94
+ @dataclass
95
+ class MeshCollection:
96
+ """Container for named meshes with simple add/access helpers."""
97
+ meshes: Dict[str, MeshModel] = field(default_factory=dict)
98
+
99
+ def add(self, name: str, mesh: MeshModel) -> None:
100
+ self.meshes[name] = mesh
101
+
102
+ def get(self, name: str) -> Optional[MeshModel]:
103
+ return self.meshes.get(name)
104
+
105
+ def __iter__(self):
106
+ return iter(self.meshes.items())
107
+
108
+ # Compatibility: some renderers expect `collection.items.items()`
109
+ @property
110
+ def items(self) -> Dict[str, MeshModel]:
111
+ return self.meshes
112
+
113
+
@@ -1,43 +1,66 @@
1
- """
2
- Solar Irradiance Simulation Package
3
-
4
- Public API exports for the refactored solar simulator. The implementation
5
- is decomposed into focused stages:
6
- 1) kernels.py - Low-level kernels for visibility/irradiance
7
- 2) radiation.py - Physics: convert geometry to irradiance
8
- 3) temporal.py - Time-series integration and solar position
9
- 4) integration.py- High-level workflows and I/O
10
- """
11
-
12
- # Stage 1: Kernels / Solar position
13
- from .kernels import ( # noqa: F401
14
- compute_direct_solar_irradiance_map_binary,
15
- )
16
- from .temporal import ( # noqa: F401
17
- get_solar_positions_astral,
18
- )
19
-
20
- # Stage 2: Radiation
21
- from .radiation import ( # noqa: F401
22
- get_direct_solar_irradiance_map,
23
- get_diffuse_solar_irradiance_map,
24
- get_global_solar_irradiance_map,
25
- compute_solar_irradiance_for_all_faces,
26
- get_building_solar_irradiance,
27
- )
28
-
29
- # Stage 3: Temporal
30
- from .temporal import ( # noqa: F401
31
- get_cumulative_global_solar_irradiance,
32
- get_cumulative_building_solar_irradiance,
33
- _configure_num_threads,
34
- _auto_time_batch_size,
35
- )
36
-
37
- # Stage 4: Integration
38
- from .integration import ( # noqa: F401
39
- get_global_solar_irradiance_using_epw,
40
- get_building_global_solar_irradiance_using_epw,
41
- save_irradiance_mesh,
42
- load_irradiance_mesh,
43
- )
1
+ """
2
+ Solar Irradiance Simulation Package
3
+
4
+ Public API exports for the refactored solar simulator. The implementation
5
+ is decomposed into focused stages:
6
+ 1) kernels.py - Low-level kernels for visibility/irradiance
7
+ 2) radiation.py - Physics: convert geometry to irradiance
8
+ 3) temporal.py - Time-series integration and solar position
9
+ 4) integration.py- High-level workflows and I/O
10
+ 5) sky.py - Sky hemisphere discretization methods
11
+ """
12
+
13
+ # Stage 1: Kernels / Solar position
14
+ from .kernels import ( # noqa: F401
15
+ compute_direct_solar_irradiance_map_binary,
16
+ )
17
+ from .temporal import ( # noqa: F401
18
+ get_solar_positions_astral,
19
+ )
20
+
21
+ # Sky discretization methods
22
+ from .sky import ( # noqa: F401
23
+ # Tregenza (145 patches)
24
+ generate_tregenza_patches,
25
+ get_tregenza_patch_index,
26
+ get_tregenza_patch_index_fast,
27
+ TREGENZA_BANDS,
28
+ TREGENZA_BAND_BOUNDARIES,
29
+ # Reinhart (subdivided Tregenza)
30
+ generate_reinhart_patches,
31
+ # Uniform grid
32
+ generate_uniform_grid_patches,
33
+ # Fibonacci spiral
34
+ generate_fibonacci_patches,
35
+ # Sun position binning
36
+ bin_sun_positions_to_patches,
37
+ bin_sun_positions_to_tregenza_fast,
38
+ # Utilities
39
+ get_patch_info,
40
+ visualize_sky_patches,
41
+ )
42
+
43
+ # Stage 2: Radiation
44
+ from .radiation import ( # noqa: F401
45
+ get_direct_solar_irradiance_map,
46
+ get_diffuse_solar_irradiance_map,
47
+ get_global_solar_irradiance_map,
48
+ compute_solar_irradiance_for_all_faces,
49
+ get_building_solar_irradiance,
50
+ )
51
+
52
+ # Stage 3: Temporal
53
+ from .temporal import ( # noqa: F401
54
+ get_cumulative_global_solar_irradiance,
55
+ get_cumulative_building_solar_irradiance,
56
+ _configure_num_threads,
57
+ _auto_time_batch_size,
58
+ )
59
+
60
+ # Stage 4: Integration
61
+ from .integration import ( # noqa: F401
62
+ get_global_solar_irradiance_using_epw,
63
+ get_building_global_solar_irradiance_using_epw,
64
+ save_irradiance_mesh,
65
+ load_irradiance_mesh,
66
+ )