"""visualize テスト共通フィクスチャ.
照度ベイクテスト・ビューアテストで使用する SceneConfig と STL ファイルを提供する.
Mitsuba をモックせず実オブジェクトを使う(testing.md モック方針).
"""
from __future__ import annotations
from pathlib import Path
import numpy as np
import pytest
import trimesh
from sm_tias_lightsim.scene.schema import SceneConfig
def _write_flat_plane_stl(path: Path, z_mm: float = 0.0) -> None:
"""z=z_mm の水平三角形 1 枚の STL を書き出す(mm 単位).
三角形の頂点:
v0 = (0, 0, z_mm)
v1 = (10, 0, z_mm)
v2 = (10, 10, z_mm)
法線は +Z 方向(仕様に合わせ正規化は trimesh に任せる).
"""
vertices = np.array(
[
[0.0, 0.0, z_mm],
[10.0, 0.0, z_mm],
[10.0, 10.0, z_mm],
],
dtype=np.float64,
)
faces = np.array([[0, 1, 2]], dtype=np.int64)
mesh = trimesh.Trimesh(vertices=vertices, faces=faces, process=False)
mesh.export(str(path))
def _write_blocker_stl(path: Path) -> None:
"""LED と評価板の間に配置する遮蔽板 STL を書き出す(mm 単位).
z=50mm に大きな平面を置く(光源 z=100mm, 評価板 z=0mm の中間).
頂点: (−100, −100, 50), (100, −100, 50), (100, 100, 50), (−100, 100, 50)
法線は +Z 方向.
"""
vertices = np.array(
[
[-100.0, -100.0, 50.0],
[100.0, -100.0, 50.0],
[100.0, 100.0, 50.0],
[-100.0, 100.0, 50.0],
],
dtype=np.float64,
)
# 2 三角形で四角形を構成
faces = np.array([[0, 1, 2], [0, 2, 3]], dtype=np.int64)
mesh = trimesh.Trimesh(vertices=vertices, faces=faces, process=False)
mesh.export(str(path))
def _write_downward_plane_stl(path: Path, z_mm: float = 0.0) -> None:
"""法線が -Z 方向の水平三角形 1 枚の STL を書き出す(mm 単位).
頂点の巻き順を逆にして -Z 法線を作る.
"""
vertices = np.array(
[
[0.0, 0.0, z_mm],
[10.0, 10.0, z_mm],
[10.0, 0.0, z_mm],
],
dtype=np.float64,
)
faces = np.array([[0, 1, 2]], dtype=np.int64)
mesh = trimesh.Trimesh(vertices=vertices, faces=faces, process=False)
mesh.export(str(path))
def _make_minimal_scene_config(
mesh_path: str,
mesh_id: str = "plane",
light_dict: dict | None = None,
) -> SceneConfig:
"""最小限の SceneConfig を辞書から作成する.
Args:
mesh_path: STL ファイルへのパス文字列(プロジェクトルート相対 or 絶対).
mesh_id: メッシュ ID.
light_dict: lights リストの要素辞書 1 個.None なら PointLight のデフォルトを使う.
"""
if light_dict is None:
light_dict = {
"id": "led",
"type": "point",
"position": [0.0, 0.0, 100.0],
"intensity": 1.0,
"profile": "lambertian",
}
data = {
"name": "test_bake",
"geometry": {
"meshes": [
{
"id": mesh_id,
"path": mesh_path,
"unit": "mm",
"material": "white",
}
]
},
"materials": {
"white": {"type": "diffuse", "reflectance": 0.9},
},
"lights": [light_dict],
"sensor": {
"type": "perspective",
"position": [0.0, 0.0, 200.0],
"target": [0.0, 0.0, 0.0],
"up": [0.0, 1.0, 0.0],
"fov_deg": 60.0,
"film": {"width": 64, "height": 64},
},
"render": {
"variant": "scalar_rgb",
"integrator": "path",
"max_depth": 2,
"spp": 1,
},
}
return SceneConfig.model_validate(data)
@pytest.fixture
def flat_plane_stl(tmp_path: Path) -> Path:
"""法線 +Z の水平三角形 1 枚の STL を tmp_path に書き出す(z=0mm)."""
path = tmp_path / "flat_plane.stl"
_write_flat_plane_stl(path, z_mm=0.0)
return path
@pytest.fixture
def blocker_stl(tmp_path: Path) -> Path:
"""LED (z=100mm) と評価板 (z=0mm) の間(z=50mm)に置く遮蔽板 STL."""
path = tmp_path / "blocker.stl"
_write_blocker_stl(path)
return path
@pytest.fixture
def downward_plane_stl(tmp_path: Path) -> Path:
"""法線 -Z の水平三角形 1 枚の STL を tmp_path に書き出す(z=0mm)."""
path = tmp_path / "downward_plane.stl"
_write_downward_plane_stl(path, z_mm=0.0)
return path
@pytest.fixture
def point_light_scene_config(flat_plane_stl: Path) -> tuple[SceneConfig, Path]:
"""PointLight + 法線 +Z 平面の SceneConfig と project_root を返す.
光源: position=(0, 0, 100mm), intensity=1.0
メッシュ: z=0mm 三角形(法線 +Z)
"""
config = _make_minimal_scene_config(
mesh_path=str(flat_plane_stl),
mesh_id="plane",
light_dict={
"id": "led",
"type": "point",
"position": [0.0, 0.0, 100.0],
"intensity": 1.0,
"profile": "lambertian",
},
)
return config, flat_plane_stl.parent
@pytest.fixture
def directional_light_scene_config(flat_plane_stl: Path) -> tuple[SceneConfig, Path]:
"""DirectionalLight + 法線 +Z 平面の SceneConfig と project_root を返す.
光源: direction=(0, 0, -1)(下向き), irradiance=1.0
メッシュ: z=0mm 三角形(法線 +Z)
"""
config = _make_minimal_scene_config(
mesh_path=str(flat_plane_stl),
mesh_id="plane",
light_dict={
"id": "dir_light",
"type": "directional",
"direction": [0.0, 0.0, -1.0],
"irradiance": 1.0,
},
)
return config, flat_plane_stl.parent