voxcity 0.6.22__py3-none-any.whl → 0.6.23__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.

@@ -2386,6 +2386,188 @@ def _rgb_tuple_to_plotly_color(rgb_tuple):
2386
2386
  return "rgb(128,128,128)"
2387
2387
 
2388
2388
 
2389
+ def visualize_building_sim_results_plotly(
2390
+ voxel_array,
2391
+ meshsize,
2392
+ building_sim_mesh,
2393
+ **kwargs
2394
+ ):
2395
+ """
2396
+ Interactive Plotly visualization of voxels with an overlaid building simulation mesh.
2397
+
2398
+ This function reuses visualize_voxcity_plotly to render voxel cubes and adds a
2399
+ Plotly Mesh3d trace for a provided building simulation mesh (e.g., SVF, temperature).
2400
+
2401
+ Parameters (kwargs)
2402
+ -------------------
2403
+ classes : list[int] or None
2404
+ Classes to render for voxel cubes. Default: all non-zero classes present.
2405
+ voxel_color_map : str or dict
2406
+ Scheme name understood by get_voxel_color_map or explicit mapping {class_id: [R,G,B]}.
2407
+ downsample : int or None
2408
+ Stride for voxel cubes. 1 means no downsampling.
2409
+ cubes_opacity : float
2410
+ Opacity for voxel cubes (default 0.95 for buildings, 0.6 for others via function's per-class logic; here default 0.9).
2411
+ title : str
2412
+ Figure title.
2413
+ width, height : int
2414
+ Figure size.
2415
+ value_name : str
2416
+ Metadata field name on building_sim_mesh storing per-face values (default 'svf_values').
2417
+ colormap : str
2418
+ Matplotlib colormap name for the simulation values (default 'viridis').
2419
+ vmin, vmax : float or None
2420
+ Value range for color mapping. If None, computed from finite values.
2421
+ nan_color : str
2422
+ Color name for NaN values (default 'gray').
2423
+ building_opacity : float
2424
+ Opacity for the simulation mesh (default 1.0).
2425
+ shaded : bool
2426
+ If True, apply lighting-based shading to the simulation mesh. Default False (unlit colors).
2427
+ render_voxel_buildings : bool
2428
+ If True, also render voxel buildings (-3) from voxcity_grid. Default False (hide voxel buildings
2429
+ so only simulation mesh buildings are visible).
2430
+ show : bool, return_fig : bool
2431
+ Standard display controls.
2432
+ """
2433
+ classes = kwargs.get('classes')
2434
+ voxel_color_map = kwargs.get('voxel_color_map', 'default')
2435
+ downsample = kwargs.get('downsample')
2436
+ title = kwargs.get('title', None)
2437
+ width = kwargs.get('width', 1000)
2438
+ height = kwargs.get('height', 800)
2439
+ cubes_opacity = kwargs.get('cubes_opacity', 0.9)
2440
+ show = kwargs.get('show', True)
2441
+ return_fig = kwargs.get('return_fig', False)
2442
+ render_voxel_buildings = kwargs.get('render_voxel_buildings', False)
2443
+
2444
+ # Determine classes for voxel cubes and exclude buildings (-3) by default
2445
+ if classes is None:
2446
+ classes_all = np.unique(voxel_array[voxel_array != 0]).tolist()
2447
+ else:
2448
+ classes_all = list(classes)
2449
+ classes_cubes = classes_all if render_voxel_buildings else [c for c in classes_all if int(c) != -3]
2450
+
2451
+ # Render voxel cubes background (or blank scene if nothing to render)
2452
+ if len(classes_cubes) > 0:
2453
+ fig = visualize_voxcity_plotly(
2454
+ voxel_array,
2455
+ meshsize,
2456
+ classes=classes_cubes,
2457
+ voxel_color_map=voxel_color_map,
2458
+ opacity=cubes_opacity,
2459
+ downsample=downsample,
2460
+ title=title or "Building Simulation (Plotly)",
2461
+ width=width,
2462
+ height=height,
2463
+ show=False,
2464
+ return_fig=True,
2465
+ )
2466
+ else:
2467
+ fig = go.Figure()
2468
+ fig.update_layout(
2469
+ title=title or "Building Simulation (Plotly)",
2470
+ width=width,
2471
+ height=height,
2472
+ scene=dict(
2473
+ xaxis_title="X (m)",
2474
+ yaxis_title="Y (m)",
2475
+ zaxis_title="Z (m)",
2476
+ aspectmode="data",
2477
+ camera=dict(eye=dict(x=1.6, y=1.6, z=1.0)),
2478
+ )
2479
+ )
2480
+
2481
+ # Nothing to overlay
2482
+ if building_sim_mesh is None or getattr(building_sim_mesh, 'vertices', None) is None:
2483
+ if show:
2484
+ fig.show()
2485
+ if return_fig:
2486
+ return fig
2487
+ return None
2488
+
2489
+ # Extract geometry
2490
+ V = np.asarray(building_sim_mesh.vertices)
2491
+ F = np.asarray(building_sim_mesh.faces)
2492
+ values = None
2493
+ value_name = kwargs.get('value_name', 'svf_values')
2494
+ if hasattr(building_sim_mesh, 'metadata') and isinstance(building_sim_mesh.metadata, dict):
2495
+ values = building_sim_mesh.metadata.get(value_name)
2496
+ if values is not None:
2497
+ values = np.asarray(values)
2498
+
2499
+ # Compute per-face scalar to avoid color interpolation across edges
2500
+ face_vals = None
2501
+ if values is not None and values.size == len(F):
2502
+ # Already per-face
2503
+ face_vals = values.astype(float)
2504
+ elif values is not None and values.size == len(V):
2505
+ # Average the three vertex values per face
2506
+ vals_v = values.astype(float)
2507
+ face_vals = np.nanmean(vals_v[F], axis=1)
2508
+
2509
+ # Map to colors
2510
+ cmap_name = kwargs.get('colormap', 'viridis')
2511
+ vmin = kwargs.get('vmin')
2512
+ vmax = kwargs.get('vmax')
2513
+ nan_color = kwargs.get('nan_color', 'gray')
2514
+ building_opacity = kwargs.get('building_opacity', 1.0)
2515
+
2516
+ facecolor = None
2517
+ if face_vals is not None:
2518
+ # Compute range
2519
+ finite = np.isfinite(face_vals)
2520
+ if vmin is None:
2521
+ vmin = float(np.nanmin(face_vals[finite])) if np.any(finite) else 0.0
2522
+ if vmax is None:
2523
+ vmax = float(np.nanmax(face_vals[finite])) if np.any(finite) else 1.0
2524
+ norm = mcolors.Normalize(vmin=vmin, vmax=vmax)
2525
+ cmap = cm.get_cmap(cmap_name)
2526
+ # Colors per face (constant on each triangle)
2527
+ colors_rgba = np.zeros((len(F), 4), dtype=float)
2528
+ colors_rgba[finite] = cmap(norm(face_vals[finite]))
2529
+ nan_rgba = np.array(mcolors.to_rgba(nan_color))
2530
+ colors_rgba[~finite] = nan_rgba
2531
+ facecolor = [
2532
+ f"rgb({int(255*c[0])},{int(255*c[1])},{int(255*c[2])})" for c in colors_rgba
2533
+ ]
2534
+
2535
+ # Lighting (disable shading by default for true color rendering)
2536
+ shaded = kwargs.get('shaded', False)
2537
+ if shaded:
2538
+ lighting = dict(ambient=0.35, diffuse=1.0, specular=0.4, roughness=0.5, fresnel=0.1)
2539
+ flat = False
2540
+ else:
2541
+ # Unlit: make colors independent of lighting
2542
+ lighting = dict(ambient=1.0, diffuse=0.0, specular=0.0, roughness=0.0, fresnel=0.0)
2543
+ flat = False
2544
+ cx = float((V[:,0].min() + V[:,0].max()) * 0.5)
2545
+ cy = float((V[:,1].min() + V[:,1].max()) * 0.5)
2546
+ cz = float((V[:,2].min() + V[:,2].max()) * 0.5)
2547
+ lx = cx + (V[:,0].max() - V[:,0].min() + meshsize) * 0.9
2548
+ ly = cy + (V[:,1].max() - V[:,1].min() + meshsize) * 0.6
2549
+ lz = cz + (V[:,2].max() - V[:,2].min() + meshsize) * 1.4
2550
+
2551
+ fig.add_trace(
2552
+ go.Mesh3d(
2553
+ x=V[:,0], y=V[:,1], z=V[:,2],
2554
+ i=F[:,0], j=F[:,1], k=F[:,2],
2555
+ facecolor=facecolor if facecolor is not None else None,
2556
+ color=None if facecolor is not None else 'rgb(200,200,200)',
2557
+ opacity=float(building_opacity),
2558
+ flatshading=flat,
2559
+ lighting=lighting,
2560
+ lightposition=dict(x=lx, y=ly, z=lz),
2561
+ name=value_name if facecolor is not None else 'building_mesh'
2562
+ )
2563
+ )
2564
+
2565
+ if show:
2566
+ fig.show()
2567
+ if return_fig:
2568
+ return fig
2569
+ return None
2570
+
2389
2571
  def visualize_voxcity_plotly(
2390
2572
  voxel_array,
2391
2573
  meshsize,
@@ -2405,6 +2587,8 @@ def visualize_voxcity_plotly(
2405
2587
  using Plotly Mesh3d. One Mesh3d trace per class.
2406
2588
 
2407
2589
  Parameters are similar to visualize_voxcity_plotly, but rendering is via exact cubes.
2590
+ voxel_color_map may be either a scheme name (str) understood by get_voxel_color_map,
2591
+ or a dict mapping class_id -> [R, G, B] (0-255).
2408
2592
  """
2409
2593
  if voxel_array is None or getattr(voxel_array, 'ndim', 0) != 3:
2410
2594
  raise ValueError("voxel_array must be a 3D numpy array (nx, ny, nz)")
@@ -2441,7 +2625,11 @@ def visualize_voxcity_plotly(
2441
2625
  if not classes:
2442
2626
  raise ValueError("No classes to visualize (voxel grid may be empty)")
2443
2627
 
2444
- vox_dict = get_voxel_color_map(voxel_color_map)
2628
+ # Resolve color map: accept scheme name or explicit dict
2629
+ if isinstance(voxel_color_map, dict):
2630
+ vox_dict = voxel_color_map
2631
+ else:
2632
+ vox_dict = get_voxel_color_map(voxel_color_map)
2445
2633
 
2446
2634
  def exposed_face_masks(occ):
2447
2635
  # occ shape (nx, ny, nz)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voxcity
3
- Version: 0.6.22
3
+ Version: 0.6.23
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
  License: MIT
6
6
  License-File: AUTHORS.rst
@@ -29,10 +29,10 @@ voxcity/simulator/view.py,sha256=k3FoS6gsibR-eDrTHJivJSQfvN3Tg8R8eSTeMqd9ans,939
29
29
  voxcity/utils/__init__.py,sha256=Q-NYCqYnAAaF80KuNwpqIjbE7Ec3Gr4y_khMLIMhJrg,68
30
30
  voxcity/utils/lc.py,sha256=722Gz3lPbgAp0mmTZ-g-QKBbAnbxrcgaYwb1sa7q8Sk,16189
31
31
  voxcity/utils/material.py,sha256=H8K8Lq4wBL6dQtgj7esUW2U6wLCOTeOtelkTDJoRgMo,10007
32
- voxcity/utils/visualization.py,sha256=kccIndyz3idTTSVMwGgniQ7zFuKLRRnOP4pgyn1xs20,109849
32
+ voxcity/utils/visualization.py,sha256=LGzDITOO-57abMA7Vx4wJLsdUP7el3GZZUbTEpx3TA0,117192
33
33
  voxcity/utils/weather.py,sha256=cb6ZooL42Hc4214OtFiJ78cCgWYM6VE-DU8S3e-urRg,48449
34
- voxcity-0.6.22.dist-info/licenses/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
35
- voxcity-0.6.22.dist-info/licenses/LICENSE,sha256=s_jE1Df1nTPL4A_5GCGic5Zwex0CVaPKcAmSilxJPPE,1089
36
- voxcity-0.6.22.dist-info/METADATA,sha256=DB0CXRCCFsr_THg8zt7BcGF-2GtXlBMzHFdKAES6jC0,26227
37
- voxcity-0.6.22.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
38
- voxcity-0.6.22.dist-info/RECORD,,
34
+ voxcity-0.6.23.dist-info/licenses/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
35
+ voxcity-0.6.23.dist-info/licenses/LICENSE,sha256=s_jE1Df1nTPL4A_5GCGic5Zwex0CVaPKcAmSilxJPPE,1089
36
+ voxcity-0.6.23.dist-info/METADATA,sha256=BNpPaAKeQYDz-pj4KA0keNf2MtDT0lyrJn9xkelLj80,26227
37
+ voxcity-0.6.23.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
38
+ voxcity-0.6.23.dist-info/RECORD,,