feat(381-3 B05 평면): 교각점 크게 · 라벨 위 · 맴돔 강조 · 노드와 횡단 눈금 집기 한 길
- 노드 반지름 4 → 6(고름 +2) · 노드 · 손잡이를 라벨 뒤 맨 위로
- 집기 문턱 노드 9 → 12 · pickAtScreen: 노드 가운데 6px 안 = 노드 · 밖 = 노드와 눈금 중 가까운 쪽
- stationAtScreen → {chainage, distance} · 맴돔은 집기와 같은 셈 · 노드 = 고리 · 눈금 = 파랑(새 _Hover)
- 누를 때 · 끄는 동안 · 재는 중 · 캔버스 밖 = 맴돔 끔 · [측점] 끔이면 눈금 안 봄
- 시험 test_b05_routeedit_pick 겹침 경우 · test_381_3_routeedit_node_pick
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QyNXY2TUKXCFMwAca2APG
This commit is contained in:
@@ -128,7 +128,7 @@ const stationLine = [
|
||||
[100, 0],
|
||||
];
|
||||
const stationAt = (px, py, labels) =>
|
||||
input.stationAtScreen(stationLine, toScreen, 20, px, py, 11, labels);
|
||||
input.stationAtScreen(stationLine, toScreen, 20, px, py, 11, labels)?.chainage ?? null;
|
||||
const rot = (dx, dy, rad) => [
|
||||
dx * Math.cos(rad) - dy * Math.sin(rad),
|
||||
dx * Math.sin(rad) + dy * Math.cos(rad),
|
||||
@@ -156,6 +156,42 @@ const label = {
|
||||
emptyElsewhere: stationAt(5, 5, boxes),
|
||||
};
|
||||
|
||||
// ⑥ 381-3 노드 · 횡단 눈금 겹침 — 노드 [41,0] = 화면 (82,400) · 눈금 40 = 화면 (80,400).
|
||||
const overlapNodes = [
|
||||
[0, 0],
|
||||
[41, 0],
|
||||
[100, 100],
|
||||
];
|
||||
const overlapAt = (px, py, stationOn = true) =>
|
||||
input.pickAtScreen(
|
||||
overlapNodes,
|
||||
toScreen,
|
||||
px,
|
||||
py,
|
||||
12,
|
||||
6,
|
||||
stationOn ? () => input.stationAtScreen(stationLine, toScreen, 20, px, py, 11, []) : null,
|
||||
);
|
||||
const overlap = {
|
||||
center: overlapAt(82, 400),
|
||||
coreNearTick: overlapAt(79, 400), // 노드 3px · 눈금 1px — 가운데 6px 안이라 노드
|
||||
tickCloser: overlapAt(74, 400), // 노드 8px · 눈금 6px — 눈금
|
||||
nodeCloser: overlapAt(90, 400), // 노드 8px · 눈금 10px — 노드
|
||||
edgeTick: overlapAt(70, 400), // 노드 12px(문턱 끝) · 눈금 10px — 눈금
|
||||
stationsOff: overlapAt(74, 400, false), // [측점] 끔 — 노드
|
||||
far: overlapAt(82, 430),
|
||||
tickOnly: overlapAt(160, 400), // 눈금 80 위 · 노드 멀리
|
||||
distance: input.stationAtScreen(stationLine, toScreen, 20, 74, 400, 11, []),
|
||||
};
|
||||
|
||||
process.stdout.write(
|
||||
JSON.stringify({ arcMatchesDrawn, pick, pick2, node: c.node_first, labelsMatchRects, label }),
|
||||
JSON.stringify({
|
||||
arcMatchesDrawn,
|
||||
pick,
|
||||
pick2,
|
||||
node: c.node_first,
|
||||
labelsMatchRects,
|
||||
label,
|
||||
overlap,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
"""381-3 B05 평면 교각점(요구 241-14) — 크기 · 그리는 차례 · 맴돔 강조 · 집기 한 길.
|
||||
|
||||
겹침 셈(`pickAtScreen`)은 test_b05_routeedit_pick 이 돌려 봄 — 여기는 배선만.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
B05 = Path(__file__).resolve().parents[2] / "B05_Profile"
|
||||
|
||||
|
||||
def _read(name: str) -> str:
|
||||
return (B05 / name).read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_노드_크기_문턱():
|
||||
assert "const NODE_R = 6;" in _read("B05_Profile_UI_RouteEdit_Render.ts")
|
||||
pointer = _read("B05_Profile_UI_RouteEdit_Pointer.ts")
|
||||
assert "const NODE_HIT_PX = 12;" in pointer and "const NODE_CORE_PX = 6;" in pointer
|
||||
|
||||
|
||||
def test_노드는_라벨_뒤_맨_위_회전_안():
|
||||
render = _read("B05_Profile_UI_RouteEdit_Render.ts")
|
||||
scene = render[render.index("export function drawRouteEditScene(") :]
|
||||
scene = scene[: scene.index("context.restore(); // 회전 끝")]
|
||||
labels = scene.index("drawContourLabels(context, scene, band, style);")
|
||||
for later in ("scene.planned.forEach(", "scene.curveInfo.forEach(", "drawPickHover("):
|
||||
assert labels < scene.index(later), later
|
||||
for earlier in ("drawStationMarks(", "scene.overStations?.(", "drawMeasureMarks("):
|
||||
assert scene.index(earlier) < labels, earlier
|
||||
|
||||
|
||||
def test_집기_맴돔_한_함수():
|
||||
pointer = _read("B05_Profile_UI_RouteEdit_Pointer.ts")
|
||||
assert "pickAtScreen(" in pointer
|
||||
down = pointer[pointer.index('addEventListener("pointerdown"') :]
|
||||
down = down[: down.index('addEventListener("pointermove"')]
|
||||
assert "hover(null);" in down and "const pick = pickAt(px, py);" in down
|
||||
assert "nodeAt(px, py)" not in down and "stationAtScreen(" not in down
|
||||
move = pointer[pointer.index('addEventListener("pointermove"') :]
|
||||
move = move[: move.index("const endDrag")]
|
||||
# 끄는 동안은 앞에서 돌아감 — 맴돔은 끌기 갈래 뒤
|
||||
assert move.index("if (dragNode >= 0)") < move.index("pickAt(px, py)")
|
||||
assert "hover(over);" in move
|
||||
assert 'addEventListener("pointerleave"' in pointer
|
||||
|
||||
|
||||
def test_맴돔_그림():
|
||||
hover = _read("B05_Profile_UI_RouteEdit_Hover.ts")
|
||||
assert "pickHover(context.canvas)" in hover
|
||||
assert '"node" in hover' in hover and "stationFrameAt(line, hover.chainage)" in hover
|
||||
@@ -69,3 +69,16 @@ def test_라벨이_없거나_빈_곳은_안_고름(results):
|
||||
label = results["label"]
|
||||
assert label["emptyNoLabels"] is None
|
||||
assert label["emptyElsewhere"] is None
|
||||
|
||||
|
||||
def test_381_3_노드_눈금_겹침은_가까운_쪽(results):
|
||||
o = results["overlap"]
|
||||
assert o["center"] == {"node": 1}
|
||||
assert o["coreNearTick"] == {"node": 1} # 가운데 6px 안 = 노드
|
||||
assert o["tickCloser"] == {"chainage": 40}
|
||||
assert o["nodeCloser"] == {"node": 1}
|
||||
assert o["edgeTick"] == {"chainage": 40}
|
||||
assert o["stationsOff"] == {"node": 1} # [측점] 끔 = 눈금 안 봄
|
||||
assert o["far"] is None
|
||||
assert o["tickOnly"] == {"chainage": 80}
|
||||
assert o["distance"] == {"chainage": 40, "distance": 6}
|
||||
|
||||
Reference in New Issue
Block a user