voxcity 0.3.25__py3-none-any.whl → 0.4.1__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/exporter/obj.py +2 -2
- voxcity/generator.py +17 -4
- voxcity/geoprocessor/grid.py +5 -1
- voxcity/geoprocessor/mesh.py +21 -1
- voxcity/geoprocessor/polygon.py +95 -1
- voxcity/simulator/solar.py +656 -7
- voxcity/simulator/view.py +635 -2
- voxcity/utils/visualization.py +767 -168
- {voxcity-0.3.25.dist-info → voxcity-0.4.1.dist-info}/METADATA +13 -13
- {voxcity-0.3.25.dist-info → voxcity-0.4.1.dist-info}/RECORD +14 -14
- {voxcity-0.3.25.dist-info → voxcity-0.4.1.dist-info}/WHEEL +1 -1
- {voxcity-0.3.25.dist-info → voxcity-0.4.1.dist-info}/AUTHORS.rst +0 -0
- {voxcity-0.3.25.dist-info → voxcity-0.4.1.dist-info}/LICENSE +0 -0
- {voxcity-0.3.25.dist-info → voxcity-0.4.1.dist-info}/top_level.txt +0 -0
voxcity/utils/visualization.py
CHANGED
|
@@ -45,37 +45,516 @@ from ..geoprocessor.mesh import (
|
|
|
45
45
|
)
|
|
46
46
|
from .material import get_material_dict
|
|
47
47
|
|
|
48
|
-
def
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
48
|
+
# def get_voxel_color_map():
|
|
49
|
+
# return {
|
|
50
|
+
# -99: [0, 0, 0], # void,
|
|
51
|
+
# -30: [255, 0, 102], # (Pink) 'Landmark',
|
|
52
|
+
# -17: [238, 242, 234], # (light gray) 'plaster',
|
|
53
|
+
# -16: [56, 78, 84], # (Dark blue) 'glass',
|
|
54
|
+
# -15: [147, 140, 114], # (Light brown) 'stone',
|
|
55
|
+
# -14: [139, 149, 159], # (Gray) 'metal',
|
|
56
|
+
# -13: [186, 187, 181], # (Gray) 'concrete',
|
|
57
|
+
# -12: [248, 166, 2], # (Orange) 'wood',
|
|
58
|
+
# -11: [81, 59, 56], # (Dark red) 'brick',
|
|
59
|
+
# -3: [180, 187, 216], # Building
|
|
60
|
+
# -2: [78, 99, 63], # Tree
|
|
61
|
+
# -1: [188, 143, 143], # Underground
|
|
62
|
+
# 1: [239, 228, 176], # 'Bareland (ground surface)',
|
|
63
|
+
# 2: [123, 130, 59], # 'Rangeland (ground surface)',
|
|
64
|
+
# 3: [97, 140, 86], # 'Shrub (ground surface)',
|
|
65
|
+
# 4: [112, 120, 56], # 'Agriculture land (ground surface)',
|
|
66
|
+
# 5: [116, 150, 66], # 'Tree (ground surface)',
|
|
67
|
+
# 6: [187, 204, 40], # 'Moss and lichen (ground surface)',
|
|
68
|
+
# 7: [77, 118, 99], # 'Wet land (ground surface)',
|
|
69
|
+
# 8: [22, 61, 51], # 'Mangrove (ground surface)',
|
|
70
|
+
# 9: [44, 66, 133], # 'Water (ground surface)',
|
|
71
|
+
# 10: [205, 215, 224], # 'Snow and ice (ground surface)',
|
|
72
|
+
# 11: [108, 119, 129], # 'Developed space (ground surface)',
|
|
73
|
+
# 12: [59, 62, 87], # 'Road (ground surface)',
|
|
74
|
+
# 13: [150, 166, 190], # 'Building (ground surface)'
|
|
75
|
+
# 14: [239, 228, 176], # 'No Data (ground surface)'
|
|
76
|
+
# }
|
|
77
|
+
def get_voxel_color_map(color_scheme='default'):
|
|
78
|
+
"""
|
|
79
|
+
Returns a color map for voxel visualization based on the specified color scheme.
|
|
80
|
+
|
|
81
|
+
Parameters:
|
|
82
|
+
-----------
|
|
83
|
+
color_scheme : str, optional
|
|
84
|
+
The name of the color scheme to use. Options are:
|
|
85
|
+
- 'default': The original color scheme
|
|
86
|
+
- 'high_contrast': High contrast colors for better visibility
|
|
87
|
+
- 'monochrome': Shades of blue
|
|
88
|
+
- 'pastel': Softer, more muted colors
|
|
89
|
+
- 'dark_mode': Darker colors overall
|
|
90
|
+
- 'grayscale': Black and white gradient
|
|
91
|
+
- 'autumn': Warm reds, oranges, and browns
|
|
92
|
+
- 'cool': Cool blues, purples, and cyans
|
|
93
|
+
- 'earth_tones': Natural earth colors
|
|
94
|
+
- 'vibrant': Very bright, saturated colors
|
|
95
|
+
|
|
96
|
+
# NEW:
|
|
97
|
+
- 'cyberpunk': Neon-like purples, pinks, and blues
|
|
98
|
+
- 'tropical': Vibrant greens, oranges, pinks (island vibes)
|
|
99
|
+
- 'vintage': Muted, sepia-like tones
|
|
100
|
+
- 'neon_dreams': Super-bright, nightclub neon palette
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
--------
|
|
104
|
+
dict
|
|
105
|
+
A dictionary mapping voxel IDs to RGB color values
|
|
106
|
+
"""
|
|
107
|
+
# ----------------------
|
|
108
|
+
# DO NOT MODIFY DEFAULT
|
|
109
|
+
# ----------------------
|
|
110
|
+
if color_scheme == 'default':
|
|
111
|
+
return {
|
|
112
|
+
-99: [0, 0, 0], # void,
|
|
113
|
+
-30: [255, 0, 102], # (Pink) 'Landmark',
|
|
114
|
+
-17: [238, 242, 234], # (light gray) 'plaster',
|
|
115
|
+
-16: [56, 78, 84], # (Dark blue) 'glass',
|
|
116
|
+
-15: [147, 140, 114], # (Light brown) 'stone',
|
|
117
|
+
-14: [139, 149, 159], # (Gray) 'metal',
|
|
118
|
+
-13: [186, 187, 181], # (Gray) 'concrete',
|
|
119
|
+
-12: [248, 166, 2], # (Orange) 'wood',
|
|
120
|
+
-11: [81, 59, 56], # (Dark red) 'brick',
|
|
121
|
+
-3: [180, 187, 216], # Building
|
|
122
|
+
-2: [78, 99, 63], # Tree
|
|
123
|
+
-1: [188, 143, 143], # Underground
|
|
124
|
+
1: [239, 228, 176], # 'Bareland (ground surface)',
|
|
125
|
+
2: [123, 130, 59], # 'Rangeland (ground surface)',
|
|
126
|
+
3: [97, 140, 86], # 'Shrub (ground surface)',
|
|
127
|
+
4: [112, 120, 56], # 'Agriculture land (ground surface)',
|
|
128
|
+
5: [116, 150, 66], # 'Tree (ground surface)',
|
|
129
|
+
6: [187, 204, 40], # 'Moss and lichen (ground surface)',
|
|
130
|
+
7: [77, 118, 99], # 'Wet land (ground surface)',
|
|
131
|
+
8: [22, 61, 51], # 'Mangrove (ground surface)',
|
|
132
|
+
9: [44, 66, 133], # 'Water (ground surface)',
|
|
133
|
+
10: [205, 215, 224], # 'Snow and ice (ground surface)',
|
|
134
|
+
11: [108, 119, 129], # 'Developed space (ground surface)',
|
|
135
|
+
12: [59, 62, 87], # 'Road (ground surface)',
|
|
136
|
+
13: [150, 166, 190], # 'Building (ground surface)'
|
|
137
|
+
14: [239, 228, 176], # 'No Data (ground surface)'
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
elif color_scheme == 'high_contrast':
|
|
141
|
+
return {
|
|
142
|
+
-99: [0, 0, 0], # void
|
|
143
|
+
-30: [255, 0, 255], # (Bright Magenta) 'Landmark'
|
|
144
|
+
-17: [255, 255, 255], # (Pure White) 'plaster'
|
|
145
|
+
-16: [0, 0, 255], # (Bright Blue) 'glass'
|
|
146
|
+
-15: [153, 76, 0], # (Dark Brown) 'stone'
|
|
147
|
+
-14: [192, 192, 192], # (Silver) 'metal'
|
|
148
|
+
-13: [128, 128, 128], # (Gray) 'concrete'
|
|
149
|
+
-12: [255, 128, 0], # (Bright Orange) 'wood'
|
|
150
|
+
-11: [153, 0, 0], # (Dark Red) 'brick'
|
|
151
|
+
-3: [0, 255, 255], # (Cyan) Building
|
|
152
|
+
-2: [0, 153, 0], # (Green) Tree
|
|
153
|
+
-1: [204, 0, 102], # (Dark Pink) Underground
|
|
154
|
+
1: [255, 255, 153], # (Light Yellow) 'Bareland'
|
|
155
|
+
2: [102, 153, 0], # (Olive Green) 'Rangeland'
|
|
156
|
+
3: [0, 204, 0], # (Bright Green) 'Shrub'
|
|
157
|
+
4: [153, 204, 0], # (Yellowish Green) 'Agriculture land'
|
|
158
|
+
5: [0, 102, 0], # (Dark Green) 'Tree'
|
|
159
|
+
6: [204, 255, 51], # (Lime Green) 'Moss and lichen'
|
|
160
|
+
7: [0, 153, 153], # (Teal) 'Wet land'
|
|
161
|
+
8: [0, 51, 0], # (Very Dark Green) 'Mangrove'
|
|
162
|
+
9: [0, 102, 204], # (Bright Blue) 'Water'
|
|
163
|
+
10: [255, 255, 255], # (White) 'Snow and ice'
|
|
164
|
+
11: [76, 76, 76], # (Dark Gray) 'Developed space'
|
|
165
|
+
12: [0, 0, 0], # (Black) 'Road'
|
|
166
|
+
13: [102, 102, 255], # (Light Purple) 'Building'
|
|
167
|
+
14: [255, 204, 153], # (Light Orange) 'No Data'
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
elif color_scheme == 'monochrome':
|
|
171
|
+
return {
|
|
172
|
+
-99: [0, 0, 0], # void
|
|
173
|
+
-30: [28, 28, 99], # 'Landmark'
|
|
174
|
+
-17: [242, 242, 242], # 'plaster'
|
|
175
|
+
-16: [51, 51, 153], # 'glass'
|
|
176
|
+
-15: [102, 102, 204], # 'stone'
|
|
177
|
+
-14: [153, 153, 204], # 'metal'
|
|
178
|
+
-13: [204, 204, 230], # 'concrete'
|
|
179
|
+
-12: [76, 76, 178], # 'wood'
|
|
180
|
+
-11: [25, 25, 127], # 'brick'
|
|
181
|
+
-3: [179, 179, 230], # Building
|
|
182
|
+
-2: [51, 51, 153], # Tree
|
|
183
|
+
-1: [102, 102, 178], # Underground
|
|
184
|
+
1: [230, 230, 255], # 'Bareland'
|
|
185
|
+
2: [128, 128, 204], # 'Rangeland'
|
|
186
|
+
3: [102, 102, 204], # 'Shrub'
|
|
187
|
+
4: [153, 153, 230], # 'Agriculture land'
|
|
188
|
+
5: [76, 76, 178], # 'Tree'
|
|
189
|
+
6: [204, 204, 255], # 'Moss and lichen'
|
|
190
|
+
7: [76, 76, 178], # 'Wet land'
|
|
191
|
+
8: [25, 25, 127], # 'Mangrove'
|
|
192
|
+
9: [51, 51, 204], # 'Water'
|
|
193
|
+
10: [242, 242, 255], # 'Snow and ice'
|
|
194
|
+
11: [128, 128, 178], # 'Developed space'
|
|
195
|
+
12: [51, 51, 127], # 'Road'
|
|
196
|
+
13: [153, 153, 204], # 'Building'
|
|
197
|
+
14: [230, 230, 255], # 'No Data'
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
elif color_scheme == 'pastel':
|
|
201
|
+
return {
|
|
202
|
+
-99: [0, 0, 0], # void
|
|
203
|
+
-30: [255, 179, 217], # (Pastel Pink) 'Landmark'
|
|
204
|
+
-17: [245, 245, 245], # (Off White) 'plaster'
|
|
205
|
+
-16: [173, 196, 230], # (Pastel Blue) 'glass'
|
|
206
|
+
-15: [222, 213, 196], # (Pastel Brown) 'stone'
|
|
207
|
+
-14: [211, 219, 226], # (Pastel Gray) 'metal'
|
|
208
|
+
-13: [226, 226, 226], # (Light Gray) 'concrete'
|
|
209
|
+
-12: [255, 223, 179], # (Pastel Orange) 'wood'
|
|
210
|
+
-11: [204, 168, 166], # (Pastel Red) 'brick'
|
|
211
|
+
-3: [214, 217, 235], # (Pastel Purple) Building
|
|
212
|
+
-2: [190, 207, 180], # (Pastel Green) Tree
|
|
213
|
+
-1: [235, 204, 204], # (Pastel Pink) Underground
|
|
214
|
+
1: [250, 244, 227], # (Cream) 'Bareland'
|
|
215
|
+
2: [213, 217, 182], # (Pastel Olive) 'Rangeland'
|
|
216
|
+
3: [200, 226, 195], # (Pastel Green) 'Shrub'
|
|
217
|
+
4: [209, 214, 188], # (Pastel Yellow-Green) 'Agriculture land'
|
|
218
|
+
5: [195, 220, 168], # (Light Pastel Green) 'Tree'
|
|
219
|
+
6: [237, 241, 196], # (Pastel Yellow) 'Moss and lichen'
|
|
220
|
+
7: [180, 210, 205], # (Pastel Teal) 'Wet land'
|
|
221
|
+
8: [176, 196, 190], # (Darker Pastel Teal) 'Mangrove'
|
|
222
|
+
9: [188, 206, 235], # (Pastel Blue) 'Water'
|
|
223
|
+
10: [242, 245, 250], # (Light Blue-White) 'Snow and ice'
|
|
224
|
+
11: [209, 213, 219], # (Pastel Gray) 'Developed space'
|
|
225
|
+
12: [189, 190, 204], # (Pastel Blue-Gray) 'Road'
|
|
226
|
+
13: [215, 221, 232], # (Very Light Pastel Blue) 'Building'
|
|
227
|
+
14: [250, 244, 227], # (Cream) 'No Data'
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
elif color_scheme == 'dark_mode':
|
|
231
|
+
return {
|
|
232
|
+
-99: [0, 0, 0], # void
|
|
233
|
+
-30: [153, 51, 102], # (Dark Pink) 'Landmark'
|
|
234
|
+
-17: [76, 76, 76], # (Dark Gray) 'plaster'
|
|
235
|
+
-16: [33, 46, 51], # (Very Dark Blue) 'glass'
|
|
236
|
+
-15: [89, 84, 66], # (Very Dark Brown) 'stone'
|
|
237
|
+
-14: [83, 89, 94], # (Dark Gray) 'metal'
|
|
238
|
+
-13: [61, 61, 61], # (Dark Gray) 'concrete'
|
|
239
|
+
-12: [153, 102, 0], # (Dark Orange) 'wood'
|
|
240
|
+
-11: [51, 35, 33], # (Very Dark Red) 'brick'
|
|
241
|
+
-3: [78, 82, 99], # (Dark Purple) Building
|
|
242
|
+
-2: [46, 58, 37], # (Dark Green) Tree
|
|
243
|
+
-1: [99, 68, 68], # (Dark Pink) Underground
|
|
244
|
+
1: [102, 97, 75], # (Dark Yellow) 'Bareland'
|
|
245
|
+
2: [61, 66, 31], # (Dark Olive) 'Rangeland'
|
|
246
|
+
3: [46, 77, 46], # (Dark Green) 'Shrub'
|
|
247
|
+
4: [56, 61, 28], # (Dark Yellow-Green) 'Agriculture land'
|
|
248
|
+
5: [54, 77, 31], # (Dark Green) 'Tree'
|
|
249
|
+
6: [89, 97, 20], # (Dark Yellow) 'Moss and lichen'
|
|
250
|
+
7: [38, 59, 49], # (Dark Teal) 'Wet land'
|
|
251
|
+
8: [16, 31, 26], # (Very Dark Green) 'Mangrove'
|
|
252
|
+
9: [22, 33, 66], # (Dark Blue) 'Water'
|
|
253
|
+
10: [82, 87, 92], # (Dark Blue-Gray) 'Snow and ice'
|
|
254
|
+
11: [46, 51, 56], # (Dark Gray) 'Developed space'
|
|
255
|
+
12: [25, 31, 43], # (Very Dark Blue) 'Road'
|
|
256
|
+
13: [56, 64, 82], # (Dark Blue-Gray) 'Building'
|
|
257
|
+
14: [102, 97, 75], # (Dark Yellow) 'No Data'
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
elif color_scheme == 'grayscale':
|
|
261
|
+
return {
|
|
262
|
+
-99: [0, 0, 0], # void (black)
|
|
263
|
+
-30: [200, 200, 200], # 'Landmark'
|
|
264
|
+
-17: [240, 240, 240], # 'plaster'
|
|
265
|
+
-16: [60, 60, 60], # 'glass'
|
|
266
|
+
-15: [130, 130, 130], # 'stone'
|
|
267
|
+
-14: [150, 150, 150], # 'metal'
|
|
268
|
+
-13: [180, 180, 180], # 'concrete'
|
|
269
|
+
-12: [170, 170, 170], # 'wood'
|
|
270
|
+
-11: [70, 70, 70], # 'brick'
|
|
271
|
+
-3: [190, 190, 190], # Building
|
|
272
|
+
-2: [90, 90, 90], # Tree
|
|
273
|
+
-1: [160, 160, 160], # Underground
|
|
274
|
+
1: [230, 230, 230], # 'Bareland'
|
|
275
|
+
2: [120, 120, 120], # 'Rangeland'
|
|
276
|
+
3: [110, 110, 110], # 'Shrub'
|
|
277
|
+
4: [115, 115, 115], # 'Agriculture land'
|
|
278
|
+
5: [100, 100, 100], # 'Tree'
|
|
279
|
+
6: [210, 210, 210], # 'Moss and lichen'
|
|
280
|
+
7: [95, 95, 95], # 'Wet land'
|
|
281
|
+
8: [40, 40, 40], # 'Mangrove'
|
|
282
|
+
9: [50, 50, 50], # 'Water'
|
|
283
|
+
10: [220, 220, 220], # 'Snow and ice'
|
|
284
|
+
11: [140, 140, 140], # 'Developed space'
|
|
285
|
+
12: [30, 30, 30], # 'Road'
|
|
286
|
+
13: [170, 170, 170], # 'Building'
|
|
287
|
+
14: [230, 230, 230], # 'No Data'
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
elif color_scheme == 'autumn':
|
|
291
|
+
return {
|
|
292
|
+
-99: [0, 0, 0], # void
|
|
293
|
+
-30: [227, 66, 52], # (Red) 'Landmark'
|
|
294
|
+
-17: [250, 240, 230], # (Antique White) 'plaster'
|
|
295
|
+
-16: [94, 33, 41], # (Dark Red) 'glass'
|
|
296
|
+
-15: [160, 120, 90], # (Medium Brown) 'stone'
|
|
297
|
+
-14: [176, 141, 87], # (Bronze) 'metal'
|
|
298
|
+
-13: [205, 186, 150], # (Tan) 'concrete'
|
|
299
|
+
-12: [204, 85, 0], # (Dark Orange) 'wood'
|
|
300
|
+
-11: [128, 55, 36], # (Rust) 'brick'
|
|
301
|
+
-3: [222, 184, 135], # (Tan) Building
|
|
302
|
+
-2: [107, 68, 35], # (Brown) Tree
|
|
303
|
+
-1: [165, 105, 79], # (Copper) Underground
|
|
304
|
+
1: [255, 235, 205], # (Blanched Almond) 'Bareland'
|
|
305
|
+
2: [133, 99, 99], # (Brown) 'Rangeland'
|
|
306
|
+
3: [139, 69, 19], # (Saddle Brown) 'Shrub'
|
|
307
|
+
4: [160, 82, 45], # (Sienna) 'Agriculture land'
|
|
308
|
+
5: [101, 67, 33], # (Dark Brown) 'Tree'
|
|
309
|
+
6: [255, 228, 196], # (Bisque) 'Moss and lichen'
|
|
310
|
+
7: [138, 51, 36], # (Rust) 'Wet land'
|
|
311
|
+
8: [85, 45, 23], # (Deep Brown) 'Mangrove'
|
|
312
|
+
9: [175, 118, 70], # (Light Brown) 'Water'
|
|
313
|
+
10: [255, 250, 240], # (Floral White) 'Snow and ice'
|
|
314
|
+
11: [188, 143, 143], # (Rosy Brown) 'Developed space'
|
|
315
|
+
12: [69, 41, 33], # (Very Dark Brown) 'Road'
|
|
316
|
+
13: [210, 180, 140], # (Tan) 'Building'
|
|
317
|
+
14: [255, 235, 205], # (Blanched Almond) 'No Data'
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
elif color_scheme == 'cool':
|
|
321
|
+
return {
|
|
322
|
+
-99: [0, 0, 0], # void
|
|
323
|
+
-30: [180, 82, 205], # (Purple) 'Landmark'
|
|
324
|
+
-17: [240, 248, 255], # (Alice Blue) 'plaster'
|
|
325
|
+
-16: [70, 130, 180], # (Steel Blue) 'glass'
|
|
326
|
+
-15: [100, 149, 237], # (Cornflower Blue) 'stone'
|
|
327
|
+
-14: [176, 196, 222], # (Light Steel Blue) 'metal'
|
|
328
|
+
-13: [240, 255, 255], # (Azure) 'concrete'
|
|
329
|
+
-12: [65, 105, 225], # (Royal Blue) 'wood'
|
|
330
|
+
-11: [95, 158, 160], # (Cadet Blue) 'brick'
|
|
331
|
+
-3: [135, 206, 235], # (Sky Blue) Building
|
|
332
|
+
-2: [0, 128, 128], # (Teal) Tree
|
|
333
|
+
-1: [127, 255, 212], # (Aquamarine) Underground
|
|
334
|
+
1: [220, 240, 250], # (Light Blue) 'Bareland'
|
|
335
|
+
2: [72, 209, 204], # (Medium Turquoise) 'Rangeland'
|
|
336
|
+
3: [0, 191, 255], # (Deep Sky Blue) 'Shrub'
|
|
337
|
+
4: [100, 149, 237], # (Cornflower Blue) 'Agriculture land'
|
|
338
|
+
5: [0, 128, 128], # (Teal) 'Tree'
|
|
339
|
+
6: [175, 238, 238], # (Pale Turquoise) 'Moss and lichen'
|
|
340
|
+
7: [32, 178, 170], # (Light Sea Green) 'Wet land'
|
|
341
|
+
8: [25, 25, 112], # (Midnight Blue) 'Mangrove'
|
|
342
|
+
9: [30, 144, 255], # (Dodger Blue) 'Water'
|
|
343
|
+
10: [240, 255, 255], # (Azure) 'Snow and ice'
|
|
344
|
+
11: [119, 136, 153], # (Light Slate Gray) 'Developed space'
|
|
345
|
+
12: [25, 25, 112], # (Midnight Blue) 'Road'
|
|
346
|
+
13: [173, 216, 230], # (Light Blue) 'Building'
|
|
347
|
+
14: [220, 240, 250], # (Light Blue) 'No Data'
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
elif color_scheme == 'earth_tones':
|
|
351
|
+
return {
|
|
352
|
+
-99: [0, 0, 0], # void
|
|
353
|
+
-30: [210, 105, 30], # (Chocolate) 'Landmark'
|
|
354
|
+
-17: [245, 245, 220], # (Beige) 'plaster'
|
|
355
|
+
-16: [139, 137, 137], # (Gray) 'glass'
|
|
356
|
+
-15: [160, 120, 90], # (Medium Brown) 'stone'
|
|
357
|
+
-14: [169, 169, 169], # (Dark Gray) 'metal'
|
|
358
|
+
-13: [190, 190, 180], # (Light Gray-Tan) 'concrete'
|
|
359
|
+
-12: [160, 82, 45], # (Sienna) 'wood'
|
|
360
|
+
-11: [139, 69, 19], # (Saddle Brown) 'brick'
|
|
361
|
+
-3: [210, 180, 140], # (Tan) Building
|
|
362
|
+
-2: [85, 107, 47], # (Dark Olive Green) Tree
|
|
363
|
+
-1: [133, 94, 66], # (Beaver) Underground
|
|
364
|
+
1: [222, 184, 135], # (Burlywood) 'Bareland'
|
|
365
|
+
2: [107, 142, 35], # (Olive Drab) 'Rangeland'
|
|
366
|
+
3: [85, 107, 47], # (Dark Olive Green) 'Shrub'
|
|
367
|
+
4: [128, 128, 0], # (Olive) 'Agriculture land'
|
|
368
|
+
5: [34, 139, 34], # (Forest Green) 'Tree'
|
|
369
|
+
6: [189, 183, 107], # (Dark Khaki) 'Moss and lichen'
|
|
370
|
+
7: [143, 188, 143], # (Dark Sea Green) 'Wet land'
|
|
371
|
+
8: [46, 139, 87], # (Sea Green) 'Mangrove'
|
|
372
|
+
9: [95, 158, 160], # (Cadet Blue) 'Water'
|
|
373
|
+
10: [238, 232, 205], # (Light Tan) 'Snow and ice'
|
|
374
|
+
11: [169, 169, 169], # (Dark Gray) 'Developed space'
|
|
375
|
+
12: [90, 90, 90], # (Dark Gray) 'Road'
|
|
376
|
+
13: [188, 170, 152], # (Tan) 'Building'
|
|
377
|
+
14: [222, 184, 135], # (Burlywood) 'No Data'
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
elif color_scheme == 'vibrant':
|
|
381
|
+
return {
|
|
382
|
+
-99: [0, 0, 0], # void
|
|
383
|
+
-30: [255, 0, 255], # (Magenta) 'Landmark'
|
|
384
|
+
-17: [255, 255, 255], # (White) 'plaster'
|
|
385
|
+
-16: [0, 191, 255], # (Deep Sky Blue) 'glass'
|
|
386
|
+
-15: [255, 215, 0], # (Gold) 'stone'
|
|
387
|
+
-14: [0, 250, 154], # (Medium Spring Green) 'metal'
|
|
388
|
+
-13: [211, 211, 211], # (Light Gray) 'concrete'
|
|
389
|
+
-12: [255, 69, 0], # (Orange Red) 'wood'
|
|
390
|
+
-11: [178, 34, 34], # (Firebrick) 'brick'
|
|
391
|
+
-3: [123, 104, 238], # (Medium Slate Blue) Building
|
|
392
|
+
-2: [50, 205, 50], # (Lime Green) Tree
|
|
393
|
+
-1: [255, 20, 147], # (Deep Pink) Underground
|
|
394
|
+
1: [255, 255, 0], # (Yellow) 'Bareland'
|
|
395
|
+
2: [0, 255, 0], # (Lime) 'Rangeland'
|
|
396
|
+
3: [0, 128, 0], # (Green) 'Shrub'
|
|
397
|
+
4: [154, 205, 50], # (Yellow Green) 'Agriculture land'
|
|
398
|
+
5: [34, 139, 34], # (Forest Green) 'Tree'
|
|
399
|
+
6: [127, 255, 0], # (Chartreuse) 'Moss and lichen'
|
|
400
|
+
7: [64, 224, 208], # (Turquoise) 'Wet land'
|
|
401
|
+
8: [0, 100, 0], # (Dark Green) 'Mangrove'
|
|
402
|
+
9: [0, 0, 255], # (Blue) 'Water'
|
|
403
|
+
10: [240, 248, 255], # (Alice Blue) 'Snow and ice'
|
|
404
|
+
11: [128, 128, 128], # (Gray) 'Developed space'
|
|
405
|
+
12: [47, 79, 79], # (Dark Slate Gray) 'Road'
|
|
406
|
+
13: [135, 206, 250], # (Light Sky Blue) 'Building'
|
|
407
|
+
14: [255, 255, 224], # (Light Yellow) 'No Data'
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
# ------------------------------------------------
|
|
411
|
+
# NEWLY ADDED STYLISH COLOR SCHEMES BELOW:
|
|
412
|
+
# ------------------------------------------------
|
|
413
|
+
elif color_scheme == 'cyberpunk':
|
|
414
|
+
"""
|
|
415
|
+
Vibrant neon purples, pinks, and blues with deep blacks.
|
|
416
|
+
Think futuristic city vibes and bright neon signs.
|
|
417
|
+
"""
|
|
418
|
+
return {
|
|
419
|
+
-99: [0, 0, 0], # void (keep it pitch black)
|
|
420
|
+
-30: [255, 0, 255], # (Neon Magenta) 'Landmark'
|
|
421
|
+
-17: [255, 255, 255], # (Bright White) 'plaster'
|
|
422
|
+
-16: [0, 255, 255], # (Neon Cyan) 'glass'
|
|
423
|
+
-15: [128, 0, 128], # (Purple) 'stone'
|
|
424
|
+
-14: [50, 50, 50], # (Dark Gray) 'metal'
|
|
425
|
+
-13: [102, 0, 102], # (Dark Magenta) 'concrete'
|
|
426
|
+
-12: [255, 20, 147], # (Deep Pink) 'wood'
|
|
427
|
+
-11: [153, 0, 76], # (Deep Purple-Red) 'brick'
|
|
428
|
+
-3: [124, 0, 255], # (Strong Neon Purple) Building
|
|
429
|
+
-2: [0, 255, 153], # (Neon Greenish Cyan) Tree
|
|
430
|
+
-1: [255, 0, 102], # (Hot Pink) Underground
|
|
431
|
+
1: [255, 255, 153], # (Pale Yellow) 'Bareland'
|
|
432
|
+
2: [0, 204, 204], # (Teal) 'Rangeland'
|
|
433
|
+
3: [153, 51, 255], # (Light Purple) 'Shrub'
|
|
434
|
+
4: [0, 153, 255], # (Bright Neon Blue) 'Agriculture land'
|
|
435
|
+
5: [0, 255, 153], # (Neon Greenish Cyan) 'Tree'
|
|
436
|
+
6: [204, 0, 255], # (Vivid Violet) 'Moss and lichen'
|
|
437
|
+
7: [0, 255, 255], # (Neon Cyan) 'Wet land'
|
|
438
|
+
8: [0, 102, 102], # (Dark Teal) 'Mangrove'
|
|
439
|
+
9: [51, 0, 102], # (Deep Indigo) 'Water'
|
|
440
|
+
10: [255, 255, 255], # (White) 'Snow and ice'
|
|
441
|
+
11: [102, 102, 102], # (Gray) 'Developed space'
|
|
442
|
+
12: [0, 0, 0], # (Black) 'Road'
|
|
443
|
+
13: [204, 51, 255], # (Bright Magenta) 'Building'
|
|
444
|
+
14: [255, 255, 153], # (Pale Yellow) 'No Data'
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
elif color_scheme == 'tropical':
|
|
448
|
+
"""
|
|
449
|
+
Bold, bright 'tropical vacation' color palette.
|
|
450
|
+
Lots of greens, oranges, pinks, reminiscent of island florals.
|
|
451
|
+
"""
|
|
452
|
+
return {
|
|
453
|
+
-99: [0, 0, 0], # void
|
|
454
|
+
-30: [255, 99, 164], # (Bright Tropical Pink) 'Landmark'
|
|
455
|
+
-17: [255, 248, 220], # (Cornsilk) 'plaster'
|
|
456
|
+
-16: [0, 150, 136], # (Teal) 'glass'
|
|
457
|
+
-15: [255, 140, 0], # (Dark Orange) 'stone'
|
|
458
|
+
-14: [255, 215, 180], # (Light Peach) 'metal'
|
|
459
|
+
-13: [210, 210, 210], # (Light Gray) 'concrete'
|
|
460
|
+
-12: [255, 165, 0], # (Orange) 'wood'
|
|
461
|
+
-11: [205, 92, 92], # (Indian Red) 'brick'
|
|
462
|
+
-3: [255, 193, 37], # (Tropical Yellow) Building
|
|
463
|
+
-2: [34, 139, 34], # (Forest Green) Tree
|
|
464
|
+
-1: [255, 160, 122], # (Light Salmon) Underground
|
|
465
|
+
1: [240, 230, 140], # (Khaki) 'Bareland'
|
|
466
|
+
2: [60, 179, 113], # (Medium Sea Green) 'Rangeland'
|
|
467
|
+
3: [46, 139, 87], # (Sea Green) 'Shrub'
|
|
468
|
+
4: [255, 127, 80], # (Coral) 'Agriculture land'
|
|
469
|
+
5: [50, 205, 50], # (Lime Green) 'Tree'
|
|
470
|
+
6: [255, 239, 213], # (Papaya Whip) 'Moss and lichen'
|
|
471
|
+
7: [255, 99, 71], # (Tomato) 'Wet land'
|
|
472
|
+
8: [47, 79, 79], # (Dark Slate Gray) 'Mangrove'
|
|
473
|
+
9: [0, 128, 128], # (Teal) 'Water'
|
|
474
|
+
10: [224, 255, 255], # (Light Cyan) 'Snow and ice'
|
|
475
|
+
11: [218, 112, 214], # (Orchid) 'Developed space'
|
|
476
|
+
12: [85, 107, 47], # (Dark Olive Green) 'Road'
|
|
477
|
+
13: [253, 245, 230], # (Old Lace) 'Building'
|
|
478
|
+
14: [240, 230, 140], # (Khaki) 'No Data'
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
elif color_scheme == 'vintage':
|
|
482
|
+
"""
|
|
483
|
+
A muted, old-photo or sepia-inspired palette
|
|
484
|
+
for a nostalgic or antique look.
|
|
485
|
+
"""
|
|
486
|
+
return {
|
|
487
|
+
-99: [0, 0, 0], # void
|
|
488
|
+
-30: [133, 94, 66], # (Beaver/Brownish) 'Landmark'
|
|
489
|
+
-17: [250, 240, 230], # (Antique White) 'plaster'
|
|
490
|
+
-16: [169, 157, 143], # (Muted Brown-Gray) 'glass'
|
|
491
|
+
-15: [181, 166, 127], # (Khaki Tan) 'stone'
|
|
492
|
+
-14: [120, 106, 93], # (Faded Gray-Brown) 'metal'
|
|
493
|
+
-13: [190, 172, 145], # (Light Brown) 'concrete'
|
|
494
|
+
-12: [146, 109, 83], # (Leather Brown) 'wood'
|
|
495
|
+
-11: [125, 80, 70], # (Dusty Brick) 'brick'
|
|
496
|
+
-3: [201, 174, 146], # (Tanned Beige) Building
|
|
497
|
+
-2: [112, 98, 76], # (Faded Olive-Brown) Tree
|
|
498
|
+
-1: [172, 140, 114], # (Light Saddle Brown) Underground
|
|
499
|
+
1: [222, 202, 166], # (Light Tan) 'Bareland'
|
|
500
|
+
2: [131, 114, 83], # (Brownish) 'Rangeland'
|
|
501
|
+
3: [105, 96, 74], # (Dark Olive Brown) 'Shrub'
|
|
502
|
+
4: [162, 141, 118], # (Beige Brown) 'Agriculture land'
|
|
503
|
+
5: [95, 85, 65], # (Muted Dark Brown) 'Tree'
|
|
504
|
+
6: [212, 200, 180], # (Off-White Tan) 'Moss and lichen'
|
|
505
|
+
7: [140, 108, 94], # (Dusky Mauve-Brown) 'Wet land'
|
|
506
|
+
8: [85, 73, 60], # (Dark Taupe) 'Mangrove'
|
|
507
|
+
9: [166, 152, 121], # (Pale Brown) 'Water'
|
|
508
|
+
10: [250, 245, 235], # (Light Antique White) 'Snow and ice'
|
|
509
|
+
11: [120, 106, 93], # (Faded Gray-Brown) 'Developed space'
|
|
510
|
+
12: [77, 66, 55], # (Dark Taupe) 'Road'
|
|
511
|
+
13: [203, 188, 162], # (Light Warm Gray) 'Building'
|
|
512
|
+
14: [222, 202, 166], # (Light Tan) 'No Data'
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
elif color_scheme == 'neon_dreams':
|
|
516
|
+
"""
|
|
517
|
+
A super-bright, high-energy neon palette.
|
|
518
|
+
Perfect if you want a 'nightclub in 2080' vibe.
|
|
519
|
+
"""
|
|
520
|
+
return {
|
|
521
|
+
-99: [0, 0, 0], # void
|
|
522
|
+
-30: [255, 0, 255], # (Magenta) 'Landmark'
|
|
523
|
+
-17: [255, 255, 255], # (White) 'plaster'
|
|
524
|
+
-16: [0, 255, 255], # (Cyan) 'glass'
|
|
525
|
+
-15: [255, 255, 0], # (Yellow) 'stone'
|
|
526
|
+
-14: [0, 255, 0], # (Lime) 'metal'
|
|
527
|
+
-13: [128, 128, 128], # (Gray) 'concrete'
|
|
528
|
+
-12: [255, 165, 0], # (Neon Orange) 'wood'
|
|
529
|
+
-11: [255, 20, 147], # (Deep Pink) 'brick'
|
|
530
|
+
-3: [75, 0, 130], # (Indigo) Building
|
|
531
|
+
-2: [102, 255, 0], # (Bright Lime Green) Tree
|
|
532
|
+
-1: [255, 51, 153], # (Neon Pink) Underground
|
|
533
|
+
1: [255, 153, 0], # (Bright Orange) 'Bareland'
|
|
534
|
+
2: [153, 204, 0], # (Vivid Yellow-Green) 'Rangeland'
|
|
535
|
+
3: [102, 205, 170], # (Aquamarine-ish) 'Shrub'
|
|
536
|
+
4: [0, 250, 154], # (Medium Spring Green) 'Agriculture land'
|
|
537
|
+
5: [173, 255, 47], # (Green-Yellow) 'Tree'
|
|
538
|
+
6: [127, 255, 0], # (Chartreuse) 'Moss and lichen'
|
|
539
|
+
7: [64, 224, 208], # (Turquoise) 'Wet land'
|
|
540
|
+
8: [0, 128, 128], # (Teal) 'Mangrove'
|
|
541
|
+
9: [0, 0, 255], # (Blue) 'Water'
|
|
542
|
+
10: [224, 255, 255], # (Light Cyan) 'Snow and ice'
|
|
543
|
+
11: [192, 192, 192], # (Silver) 'Developed space'
|
|
544
|
+
12: [25, 25, 25], # (Near Black) 'Road'
|
|
545
|
+
13: [75, 0, 130], # (Indigo) 'Building'
|
|
546
|
+
14: [255, 153, 0], # (Bright Orange) 'No Data'
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
else:
|
|
550
|
+
# If an unknown color scheme is specified, return the default
|
|
551
|
+
print(f"Unknown color scheme '{color_scheme}'. Using default instead.")
|
|
552
|
+
return get_voxel_color_map('default')
|
|
553
|
+
|
|
554
|
+
def visualize_3d_voxel(voxel_grid, voxel_color_map = 'default', voxel_size=2.0, save_path=None):
|
|
555
|
+
|
|
556
|
+
color_map = get_voxel_color_map(voxel_color_map)
|
|
77
557
|
|
|
78
|
-
def visualize_3d_voxel(voxel_grid, color_map = get_default_voxel_color_map(), voxel_size=2.0, save_path=None):
|
|
79
558
|
print("\tVisualizing 3D voxel data")
|
|
80
559
|
# Create a figure and a 3D axis
|
|
81
560
|
fig = plt.figure(figsize=(12, 10))
|
|
@@ -133,7 +612,10 @@ def visualize_3d_voxel(voxel_grid, color_map = get_default_voxel_color_map(), vo
|
|
|
133
612
|
plt.show()
|
|
134
613
|
|
|
135
614
|
|
|
136
|
-
def visualize_3d_voxel_plotly(voxel_grid,
|
|
615
|
+
def visualize_3d_voxel_plotly(voxel_grid, voxel_color_map = 'default', voxel_size=2.0):
|
|
616
|
+
|
|
617
|
+
color_map = get_voxel_color_map(voxel_color_map)
|
|
618
|
+
|
|
137
619
|
print("Preparing visualization...")
|
|
138
620
|
|
|
139
621
|
print("Processing voxels...")
|
|
@@ -1030,21 +1512,10 @@ def visualize_voxcity_multi_view(voxel_array, meshsize, **kwargs):
|
|
|
1030
1512
|
pv.global_theme.background = 'white'
|
|
1031
1513
|
pv.global_theme.window_size = [1024, 768]
|
|
1032
1514
|
pv.global_theme.jupyter_backend = 'static'
|
|
1033
|
-
|
|
1034
|
-
# view_kwargs = {
|
|
1035
|
-
# "view_point_height": 1.5, # To set height of view point in meters. Default: 1.5 m.
|
|
1036
|
-
# "dem_grid": dem_grid,
|
|
1037
|
-
# "colormap": 'viridis', # Choose a colormap. Default: 'viridis'.
|
|
1038
|
-
# "obj_export": True, # Set "True" if you want to export the result in an OBJ file.
|
|
1039
|
-
# "output_directory": f'output/{key}/obj', # To set directory path for output files. Default: False.
|
|
1040
|
-
# "output_file_name": 'gvi', # To set file name excluding extension. Default: 'view_index'.
|
|
1041
|
-
# "num_colors": 10, # Number of discrete colors
|
|
1042
|
-
# "alpha": 1.0, # Set transparency (0.0 to 1.0)
|
|
1043
|
-
# "vmin": 0.0, # Minimum value for colormap normalization
|
|
1044
|
-
# "vmax": 1.0 # Maximum value for colormap normalization
|
|
1045
|
-
# }
|
|
1515
|
+
|
|
1046
1516
|
# Parse kwargs
|
|
1047
|
-
|
|
1517
|
+
voxel_color_map = kwargs.get("voxel_color_map", 'default')
|
|
1518
|
+
vox_dict = get_voxel_color_map(voxel_color_map)
|
|
1048
1519
|
output_directory = kwargs.get("output_directory", 'output')
|
|
1049
1520
|
base_filename = kwargs.get("output_file_name", None)
|
|
1050
1521
|
sim_grid = kwargs.get("sim_grid", None)
|
|
@@ -1143,7 +1614,8 @@ def visualize_voxcity_multi_view_with_multiple_sim_grids(voxel_array, meshsize,
|
|
|
1143
1614
|
pv.global_theme.jupyter_backend = 'static'
|
|
1144
1615
|
|
|
1145
1616
|
# Parse general kwargs
|
|
1146
|
-
|
|
1617
|
+
voxel_color_map = kwargs.get("voxel_color_map", 'default')
|
|
1618
|
+
vox_dict = get_voxel_color_map(voxel_color_map)
|
|
1147
1619
|
output_directory = kwargs.get("output_directory", 'output')
|
|
1148
1620
|
base_filename = kwargs.get("output_file_name", None)
|
|
1149
1621
|
dem_grid_ori = kwargs.get("dem_grid", None)
|
|
@@ -1219,125 +1691,252 @@ def visualize_voxcity_multi_view_with_multiple_sim_grids(voxel_array, meshsize,
|
|
|
1219
1691
|
|
|
1220
1692
|
return meshes
|
|
1221
1693
|
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
#
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
#
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
#
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
#
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
#
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
#
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
#
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
#
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
#
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
#
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
#
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1694
|
+
def visualize_voxcity_with_sim_meshes(voxel_array, meshsize, custom_meshes=None, **kwargs):
|
|
1695
|
+
"""
|
|
1696
|
+
Create multiple views of the voxel city data with custom simulation meshes replacing specific voxel classes.
|
|
1697
|
+
|
|
1698
|
+
Parameters
|
|
1699
|
+
----------
|
|
1700
|
+
voxel_array : np.ndarray
|
|
1701
|
+
3D array of voxel values.
|
|
1702
|
+
meshsize : float
|
|
1703
|
+
Size of each voxel in meters.
|
|
1704
|
+
custom_meshes : dict, optional
|
|
1705
|
+
Dictionary mapping voxel class IDs to custom meshes (e.g., {-3: building_svf_mesh}).
|
|
1706
|
+
These meshes will replace the original voxel meshes for visualization.
|
|
1707
|
+
**kwargs:
|
|
1708
|
+
vox_dict : dict
|
|
1709
|
+
Dictionary mapping voxel class IDs to colors.
|
|
1710
|
+
output_directory : str
|
|
1711
|
+
Directory to save output files.
|
|
1712
|
+
output_file_name : str
|
|
1713
|
+
Base filename for exported meshes.
|
|
1714
|
+
sim_grid : np.ndarray
|
|
1715
|
+
2D array with simulation values to visualize as a surface.
|
|
1716
|
+
dem_grid : np.ndarray
|
|
1717
|
+
2D array with elevation values.
|
|
1718
|
+
view_point_height : float
|
|
1719
|
+
Height offset for simulation grid visualization.
|
|
1720
|
+
colormap : str
|
|
1721
|
+
Matplotlib colormap name for simulation results.
|
|
1722
|
+
vmin, vmax : float
|
|
1723
|
+
Min/max values for color mapping.
|
|
1724
|
+
projection_type : str
|
|
1725
|
+
'perspective' or 'orthogonal'
|
|
1726
|
+
distance_factor : float
|
|
1727
|
+
Adjusts camera distance.
|
|
1728
|
+
colorbar_title : str
|
|
1729
|
+
Title for the colorbar (for simulation results).
|
|
1730
|
+
value_name : str
|
|
1731
|
+
Name of the field in metadata containing values to visualize.
|
|
1732
|
+
nan_color : str or tuple
|
|
1733
|
+
Color to use for NaN values (default: 'gray')
|
|
1734
|
+
|
|
1735
|
+
Returns
|
|
1736
|
+
-------
|
|
1737
|
+
list
|
|
1738
|
+
List of (view_name, image_file_path) tuples for the generated views.
|
|
1739
|
+
"""
|
|
1740
|
+
os.system('Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &')
|
|
1741
|
+
os.environ['DISPLAY'] = ':99'
|
|
1742
|
+
|
|
1743
|
+
# Configure PyVista settings
|
|
1744
|
+
pv.set_plot_theme('document')
|
|
1745
|
+
pv.global_theme.background = 'white'
|
|
1746
|
+
pv.global_theme.window_size = [1024, 768]
|
|
1747
|
+
pv.global_theme.jupyter_backend = 'static'
|
|
1748
|
+
|
|
1749
|
+
# Parse kwargs
|
|
1750
|
+
voxel_color_map = kwargs.get("voxel_color_map", 'default')
|
|
1751
|
+
vox_dict = get_voxel_color_map(voxel_color_map)
|
|
1752
|
+
output_directory = kwargs.get("output_directory", 'output')
|
|
1753
|
+
base_filename = kwargs.get("output_file_name", None)
|
|
1754
|
+
sim_grid = kwargs.get("sim_grid", None)
|
|
1755
|
+
dem_grid_ori = kwargs.get("dem_grid", None)
|
|
1756
|
+
if dem_grid_ori is not None:
|
|
1757
|
+
dem_grid = dem_grid_ori - np.min(dem_grid_ori)
|
|
1758
|
+
z_offset = kwargs.get("view_point_height", 1.5)
|
|
1759
|
+
cmap_name = kwargs.get("colormap", "viridis")
|
|
1760
|
+
vmin = kwargs.get("vmin", None)
|
|
1761
|
+
vmax = kwargs.get("vmax", None)
|
|
1762
|
+
projection_type = kwargs.get("projection_type", "perspective")
|
|
1763
|
+
distance_factor = kwargs.get("distance_factor", 1.0)
|
|
1764
|
+
colorbar_title = kwargs.get("colorbar_title", "")
|
|
1765
|
+
value_name = kwargs.get("value_name", None)
|
|
1766
|
+
nan_color = kwargs.get("nan_color", "gray")
|
|
1767
|
+
|
|
1768
|
+
if value_name is None:
|
|
1769
|
+
print("Set value_name")
|
|
1770
|
+
|
|
1771
|
+
# Create meshes from voxel data
|
|
1772
|
+
print("Creating voxel meshes...")
|
|
1773
|
+
meshes = create_city_meshes(voxel_array, vox_dict, meshsize=meshsize)
|
|
1774
|
+
|
|
1775
|
+
# Replace specific voxel class meshes with custom simulation meshes
|
|
1776
|
+
if custom_meshes is not None:
|
|
1777
|
+
for class_id, custom_mesh in custom_meshes.items():
|
|
1778
|
+
# Apply coloring to custom meshes if they have metadata values
|
|
1779
|
+
if hasattr(custom_mesh, 'metadata') and value_name in custom_mesh.metadata:
|
|
1780
|
+
# Create a colored copy of the mesh for visualization
|
|
1781
|
+
import matplotlib.cm as cm
|
|
1782
|
+
import matplotlib.colors as mcolors
|
|
1783
|
+
|
|
1784
|
+
# Get values from metadata
|
|
1785
|
+
values = custom_mesh.metadata[value_name]
|
|
1786
|
+
|
|
1787
|
+
# Set vmin/vmax if not provided
|
|
1788
|
+
local_vmin = vmin if vmin is not None else np.nanmin(values[~np.isnan(values)])
|
|
1789
|
+
local_vmax = vmax if vmax is not None else np.nanmax(values[~np.isnan(values)])
|
|
1790
|
+
|
|
1791
|
+
# Create colors
|
|
1792
|
+
cmap = cm.get_cmap(cmap_name)
|
|
1793
|
+
norm = mcolors.Normalize(vmin=local_vmin, vmax=local_vmax)
|
|
1794
|
+
|
|
1795
|
+
# Handle NaN values with custom color
|
|
1796
|
+
face_colors = np.zeros((len(values), 4))
|
|
1797
|
+
|
|
1798
|
+
# Convert string color to RGBA if needed
|
|
1799
|
+
if isinstance(nan_color, str):
|
|
1800
|
+
import matplotlib.colors as mcolors
|
|
1801
|
+
nan_rgba = np.array(mcolors.to_rgba(nan_color))
|
|
1802
|
+
else:
|
|
1803
|
+
# Assume it's already a tuple/list of RGBA values
|
|
1804
|
+
nan_rgba = np.array(nan_color)
|
|
1805
|
+
|
|
1806
|
+
# Apply colors: NaN values get nan_color, others get colormap colors
|
|
1807
|
+
nan_mask = np.isnan(values)
|
|
1808
|
+
face_colors[~nan_mask] = cmap(norm(values[~nan_mask]))
|
|
1809
|
+
face_colors[nan_mask] = nan_rgba
|
|
1810
|
+
|
|
1811
|
+
# Create a copy with colors
|
|
1812
|
+
vis_mesh = custom_mesh.copy()
|
|
1813
|
+
vis_mesh.visual.face_colors = face_colors
|
|
1814
|
+
|
|
1815
|
+
if class_id in meshes:
|
|
1816
|
+
print(f"Replacing voxel class {class_id} with colored custom simulation mesh")
|
|
1817
|
+
meshes[class_id] = vis_mesh
|
|
1818
|
+
else:
|
|
1819
|
+
print(f"Adding colored custom simulation mesh for class {class_id}")
|
|
1820
|
+
meshes[class_id] = vis_mesh
|
|
1821
|
+
else:
|
|
1822
|
+
# No metadata values, use the mesh as is
|
|
1823
|
+
if class_id in meshes:
|
|
1824
|
+
print(f"Replacing voxel class {class_id} with custom simulation mesh")
|
|
1825
|
+
meshes[class_id] = custom_mesh
|
|
1826
|
+
else:
|
|
1827
|
+
print(f"Adding custom simulation mesh for class {class_id}")
|
|
1828
|
+
meshes[class_id] = custom_mesh
|
|
1829
|
+
|
|
1830
|
+
# Create sim_grid surface mesh if provided
|
|
1831
|
+
if sim_grid is not None and dem_grid is not None:
|
|
1832
|
+
print("Creating sim_grid surface mesh...")
|
|
1833
|
+
|
|
1834
|
+
# If vmin/vmax not provided, use actual min/max of the valid sim data
|
|
1835
|
+
if vmin is None:
|
|
1836
|
+
vmin = np.nanmin(sim_grid)
|
|
1837
|
+
if vmax is None:
|
|
1838
|
+
vmax = np.nanmax(sim_grid)
|
|
1839
|
+
|
|
1840
|
+
sim_mesh = create_sim_surface_mesh(
|
|
1841
|
+
sim_grid, dem_grid,
|
|
1842
|
+
meshsize=meshsize,
|
|
1843
|
+
z_offset=z_offset,
|
|
1844
|
+
cmap_name=cmap_name,
|
|
1845
|
+
vmin=vmin,
|
|
1846
|
+
vmax=vmax,
|
|
1847
|
+
nan_color=nan_color # Pass nan_color to the mesh creation
|
|
1848
|
+
)
|
|
1849
|
+
if sim_mesh is not None:
|
|
1850
|
+
meshes["sim_surface"] = sim_mesh
|
|
1851
|
+
|
|
1852
|
+
# Prepare the colormap and create colorbar
|
|
1853
|
+
norm = mcolors.Normalize(vmin=vmin, vmax=vmax)
|
|
1854
|
+
scalar_map = cm.ScalarMappable(norm=norm, cmap=cmap_name)
|
|
1855
|
+
|
|
1856
|
+
# Create a figure and axis for the colorbar but don't display
|
|
1857
|
+
fig, ax = plt.subplots(figsize=(6, 1))
|
|
1858
|
+
cbar = plt.colorbar(scalar_map, cax=ax, orientation='horizontal')
|
|
1859
|
+
if colorbar_title:
|
|
1860
|
+
cbar.set_label(colorbar_title)
|
|
1861
|
+
plt.tight_layout()
|
|
1862
|
+
plt.show()
|
|
1863
|
+
|
|
1864
|
+
# Export if filename provided
|
|
1865
|
+
if base_filename is not None:
|
|
1866
|
+
print(f"Exporting files to '{base_filename}.*' ...")
|
|
1867
|
+
# Create output directory if it doesn't exist
|
|
1868
|
+
os.makedirs(output_directory, exist_ok=True)
|
|
1869
|
+
export_meshes(meshes, output_directory, base_filename)
|
|
1870
|
+
|
|
1871
|
+
# Create and save multiple views
|
|
1872
|
+
print("Creating multiple views...")
|
|
1873
|
+
# Create output directory if it doesn't exist
|
|
1874
|
+
os.makedirs(output_directory, exist_ok=True)
|
|
1875
|
+
image_files = create_multi_view_scene(meshes, output_directory=output_directory,
|
|
1876
|
+
projection_type=projection_type,
|
|
1877
|
+
distance_factor=distance_factor)
|
|
1878
|
+
|
|
1879
|
+
# Display each view separately
|
|
1880
|
+
for view_name, img_file in image_files:
|
|
1881
|
+
plt.figure(figsize=(12, 8))
|
|
1882
|
+
img = plt.imread(img_file)
|
|
1883
|
+
plt.imshow(img)
|
|
1884
|
+
plt.title(view_name.replace('_', ' ').title(), pad=20)
|
|
1885
|
+
plt.axis('off')
|
|
1886
|
+
plt.show()
|
|
1887
|
+
plt.close()
|
|
1888
|
+
|
|
1889
|
+
return image_files
|
|
1890
|
+
|
|
1891
|
+
def visualize_building_sim_results(voxel_array, meshsize, building_sim_mesh, **kwargs):
|
|
1892
|
+
"""
|
|
1893
|
+
Visualize building simulation results by replacing building meshes in the original model.
|
|
1894
|
+
|
|
1895
|
+
This is a specialized wrapper around visualize_voxcity_with_sim_meshes that specifically
|
|
1896
|
+
targets building simulation meshes (assuming building class ID is -3).
|
|
1897
|
+
|
|
1898
|
+
Parameters
|
|
1899
|
+
----------
|
|
1900
|
+
voxel_array : np.ndarray
|
|
1901
|
+
3D array of voxel values.
|
|
1902
|
+
meshsize : float
|
|
1903
|
+
Size of each voxel in meters.
|
|
1904
|
+
building_sim_mesh : trimesh.Trimesh
|
|
1905
|
+
Simulation result mesh for buildings with values stored in metadata.
|
|
1906
|
+
**kwargs:
|
|
1907
|
+
Same parameters as visualize_voxcity_with_sim_meshes.
|
|
1908
|
+
Additional parameters:
|
|
1909
|
+
value_name : str
|
|
1910
|
+
Name of the field in metadata containing values to visualize (default: 'svf_values')
|
|
1911
|
+
nan_color : str or tuple
|
|
1912
|
+
Color for NaN values (default: 'gray')
|
|
1913
|
+
|
|
1914
|
+
Returns
|
|
1915
|
+
-------
|
|
1916
|
+
list
|
|
1917
|
+
List of (view_name, image_file_path) tuples for the generated views.
|
|
1918
|
+
"""
|
|
1919
|
+
# Building class ID is typically -3 in voxcity
|
|
1920
|
+
building_class_id = kwargs.get("building_class_id", -3)
|
|
1921
|
+
|
|
1922
|
+
# Create custom meshes dictionary with the building simulation mesh
|
|
1923
|
+
custom_meshes = {building_class_id: building_sim_mesh}
|
|
1924
|
+
|
|
1925
|
+
# Add colorbar title if not provided
|
|
1926
|
+
if "colorbar_title" not in kwargs:
|
|
1927
|
+
# Try to guess a title based on the mesh name/type
|
|
1928
|
+
if hasattr(building_sim_mesh, 'name') and building_sim_mesh.name:
|
|
1929
|
+
kwargs["colorbar_title"] = building_sim_mesh.name
|
|
1930
|
+
else:
|
|
1931
|
+
# Use value_field name as fallback
|
|
1932
|
+
value_name = kwargs.get("value_name", "svf_values")
|
|
1933
|
+
pretty_name = value_name.replace('_', ' ').title()
|
|
1934
|
+
kwargs["colorbar_title"] = pretty_name
|
|
1935
|
+
|
|
1936
|
+
# Call the more general visualization function
|
|
1937
|
+
return visualize_voxcity_with_sim_meshes(
|
|
1938
|
+
voxel_array,
|
|
1939
|
+
meshsize,
|
|
1940
|
+
custom_meshes=custom_meshes,
|
|
1941
|
+
**kwargs
|
|
1942
|
+
)
|