feat(E04): 3D 보기 = 활동체 걷어낸 지표 + 잘린 활동면(테두리 틈 없음) · 노선 관 · 측점 이름 솎기 · 토글 꼴 · 시험 더함 (533-3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,8 @@ writeFileSync(process.argv[3], JSON.stringify({
|
||||
terrain: mesh(M.terrainMesh(c.grid, c.z)),
|
||||
sphere: mesh(M.slipMesh(c.grid, c.z, c.sphere)),
|
||||
ellipsoid: mesh(M.slipMesh(c.grid, c.z, c.ellipsoid)),
|
||||
cut: Array.from(M.cutCells(c.grid, c.z, c.sphere).keys()),
|
||||
holed: mesh(M.terrainWithout(c.grid, c.z, M.cutCells(c.grid, c.z, c.sphere))),
|
||||
hCenter: M.slipHeight(c.sphere, 110, 207),
|
||||
hEdge: M.slipHeight(c.sphere, 116.5, 207),
|
||||
hEll: [M.slipHeight(c.ellipsoid, 121, 207), M.slipHeight(c.ellipsoid, 110, 212)],
|
||||
@@ -146,17 +148,43 @@ def test_terrain_mesh(ts):
|
||||
assert 4 * nx + 3 not in ts["terrain"]["cells"]
|
||||
|
||||
|
||||
def _py_rim(cut: set[int]) -> set[int]:
|
||||
nx, ny = GRID["nx"], GRID["ny"]
|
||||
rim = set()
|
||||
for index in cut:
|
||||
ix, iy = index % nx, index // nx
|
||||
for dy in (-1, 0, 1):
|
||||
for dx in (-1, 0, 1):
|
||||
jx, jy = ix + dx, iy + dy
|
||||
nxt = jy * nx + jx
|
||||
if 0 <= jx < nx and 0 <= jy < ny and nxt not in cut and Z[nxt] is not None:
|
||||
rim.add(nxt)
|
||||
return rim
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", ["sphere", "ellipsoid"])
|
||||
def test_slip_mesh_vertices(ts, name):
|
||||
"""활동면 꼭짓점 = 잘린 셀(활동면 높이 · 지표 아래) + 테두리 셀(지표 높이)."""
|
||||
best = SPHERE if name == "sphere" else ELLIPSOID
|
||||
want = _py_cut(best)
|
||||
cut = dict(_py_cut(best))
|
||||
rim = _py_rim(set(cut))
|
||||
want = sorted(set(cut) | rim)
|
||||
got = ts[name]
|
||||
assert got["n"] == len(want) > 20
|
||||
assert got["cells"] == [i for i, _ in want]
|
||||
assert got["zs"] == pytest.approx([z for _, z in want], abs=1e-3) # Float32
|
||||
assert len(cut) > 20 and rim
|
||||
assert got["n"] == len(want)
|
||||
assert got["cells"] == want
|
||||
assert got["zs"] == pytest.approx([cut.get(i, Z[i]) for i in want], abs=1e-3) # Float32
|
||||
assert got["tri"] > 0
|
||||
# 활동면 꼭짓점은 모두 지표 아래
|
||||
assert all(z < Z[i] for i, z in want)
|
||||
assert all(z < Z[i] for i, z in cut.items())
|
||||
|
||||
|
||||
def test_terrain_hole_matches_cut(ts):
|
||||
"""활동체를 걷어낸 지표 = 지표 꼭짓점 − 잘린 셀 · 구멍 테두리는 활동면 메쉬와 같은 꼭짓점."""
|
||||
cut = [i for i, _ in _py_cut(SPHERE)]
|
||||
assert ts["cut"] == cut
|
||||
assert ts["holed"]["n"] == ts["terrain"]["n"] - len(cut)
|
||||
assert not set(ts["holed"]["cells"]) & set(cut)
|
||||
assert _py_rim(set(cut)) <= set(ts["holed"]["cells"])
|
||||
|
||||
|
||||
def test_slip_height_and_terrain_height(ts):
|
||||
|
||||
Reference in New Issue
Block a user