Spaces:
Running
Running
File size: 3,120 Bytes
eecbf34 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | from __future__ import annotations
from pathlib import Path
import matplotlib
import numpy as np
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
matplotlib.use("Agg")
import matplotlib.pyplot as plt
def _axis_limits_from_points(points: np.ndarray) -> tuple[tuple[float, float], tuple[float, float], tuple[float, float]]:
x_min, x_max = float(np.min(points[:, 0])), float(np.max(points[:, 0]))
y_min, y_max = float(np.min(points[:, 1])), float(np.max(points[:, 1]))
z_min, z_max = float(np.min(points[:, 2])), float(np.max(points[:, 2]))
max_range = max(x_max - x_min, y_max - y_min, z_max - z_min) / 2.0
max_range = max(max_range, 1e-6) * 1.08
x_mid = (x_max + x_min) / 2.0
y_mid = (y_max + y_min) / 2.0
z_mid = (z_max + z_min) / 2.0
return (
(x_mid - max_range, x_mid + max_range),
(y_mid - max_range, y_mid + max_range),
(z_mid - max_range, z_mid + max_range),
)
def _to_vertices(face_v_item: object) -> np.ndarray | None:
verts = np.asarray(face_v_item, dtype=float)
if verts.ndim == 2 and verts.shape[1] == 3 and len(verts) >= 3:
return verts
flat = verts.reshape(-1)
if flat.size >= 9 and flat.size % 3 == 0:
shaped = flat.reshape(-1, 3)
if len(shaped) >= 3:
return shaped
return None
def visualize_geometry(
geometry_npz: str | Path,
output_png: str | Path,
*,
elev: float = 45.0,
azim: float = 15.0,
dpi: int = 300,
) -> Path:
"""Render geometry polygons from PACK geometry npz (expects key: face_v)."""
geometry_npz = Path(geometry_npz)
output_png = Path(output_png)
with np.load(geometry_npz, allow_pickle=True) as data:
if "face_v" not in data:
keys = ", ".join(sorted(data.files))
raise KeyError(f"Missing key 'face_v' in {geometry_npz}; keys=[{keys}]")
face_v = data["face_v"]
polygons: list[np.ndarray] = []
for item in face_v:
verts = _to_vertices(item)
if verts is not None:
polygons.append(verts)
if not polygons:
raise ValueError(f"No valid polygons in {geometry_npz}")
fig = plt.figure(figsize=(4, 4))
ax = fig.add_subplot(111, projection="3d")
ax.view_init(elev=elev, azim=azim)
fig.subplots_adjust(left=0, right=1, top=1, bottom=0)
for verts in polygons:
collection = Poly3DCollection(
[verts],
facecolors="#FFFFFF",
edgecolors="#4D4D4D",
linewidths=0.42,
alpha=0.35,
)
ax.add_collection3d(collection)
all_points = np.vstack(polygons)
x_lim, y_lim, z_lim = _axis_limits_from_points(all_points)
ax.set_xlim(*x_lim)
ax.set_ylim(*y_lim)
ax.set_zlim(*z_lim)
ax.set_box_aspect([1, 1, 1])
ax.set_axis_off()
output_png.parent.mkdir(parents=True, exist_ok=True)
fig.savefig(output_png, dpi=dpi, bbox_inches="tight", pad_inches=0.04, transparent=True)
plt.close(fig)
return output_png
|