fix(B05 평면 곡선 창): 곡선 없는 교각점(삼각)도 하단에 「내각 N° · 곡선 없음」 표기 (403-1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Se7ytqbohmBQnfYpwYFnYf
This commit is contained in:
@@ -54,6 +54,16 @@ export function centerDirectionOf(
|
||||
return length <= 1e-9 ? null : [sx / length, sy / length];
|
||||
}
|
||||
|
||||
/** 패널 하단 글 — **내각만** 남긴다(2026-09-12 사용자 지시 ㉗) · 고정 여부는 단추 색, 하한은
|
||||
* 칸이 막음. 155° 이상은 L 하한을 안 거는 까닭이 보이게. 곡선 없는 교각점(삼각)도 내각(403-1). */
|
||||
export function curveInfoText(curveOn: boolean, inner: number | null, optional: boolean): string {
|
||||
const angle = inner ? `내각 ${Math.round(inner)}°` : "";
|
||||
if (!curveOn) return [angle, "곡선 없음 — 직선이 그대로 꺾입니다"].filter(Boolean).join(" · ");
|
||||
return angle && optional
|
||||
? `${angle} · ${CURVE_OPTIONAL_INNER_ANGLE_DEG}° 이상 — 곡선 생략 가능`
|
||||
: angle;
|
||||
}
|
||||
|
||||
/** 꺾임점과 패널 사이 여백(px) — 손잡이(접선점 네모)를 가리지 않을 만큼 띄운다. */
|
||||
const GAP_PX = 40;
|
||||
/** 자동 자리를 고를 방위 수 — 16방위(22.5°마다). */
|
||||
@@ -342,19 +352,7 @@ export function createCurveLabel(
|
||||
state.radiusShown === null ? "" : String(Math.round(state.radiusShown * 10) / 10);
|
||||
arc.value =
|
||||
state.arcLengthShown === null ? "" : String(Math.round(state.arcLengthShown * 10) / 10);
|
||||
const inner = state.innerAngleDeg;
|
||||
// 하단에는 **내각만** 남긴다(2026-09-12 사용자 지시 ㉗) — 고정 여부는 단추 색으로,
|
||||
// 하한은 칸이 이미 막으므로 글로 또 적을 까닭이 없다.
|
||||
// 내각 155° 이상은 법이 곡선을 안 둬도 된다고 한 자리다 — L 하한을 안 거는 까닭이
|
||||
// 여기서 보여야 한다(2026-09-12 사용자 확정).
|
||||
info.textContent = state.curveOn
|
||||
? inner
|
||||
? `내각 ${Math.round(inner)}°` +
|
||||
(state.curveOptional
|
||||
? ` · ${CURVE_OPTIONAL_INNER_ANGLE_DEG}° 이상 — 곡선 생략 가능`
|
||||
: "")
|
||||
: ""
|
||||
: "곡선 없음 — 직선이 그대로 꺾입니다";
|
||||
info.textContent = curveInfoText(state.curveOn, state.innerAngleDeg, state.curveOptional);
|
||||
place(state);
|
||||
// 글자가 바뀌면 상자 높이가 한 박자 늦게 자란다 — 다음 그림 직전에 한 번 더 맞춘다.
|
||||
requestAnimationFrame(() => {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/* 403 곡선 창 하단 글 헬퍼 — `_Label.curveInfoText` 를 트랜스파일해 경우별 글을 JSON 으로 낸다. */
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
||||
const B05 = path.join(__dirname, "..", "..", "B05_Profile");
|
||||
|
||||
const STUBS = {
|
||||
"@ui/ui_template_elements": { createButton: () => null },
|
||||
"./B05_Profile_UI_Panel_Fields": { numberField: () => null, toggleButton: () => null },
|
||||
};
|
||||
function loadTs(full) {
|
||||
const js = ts.transpileModule(fs.readFileSync(full, "utf8"), {
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
||||
}).outputText;
|
||||
const box = { exports: {} };
|
||||
const localRequire = (request) => {
|
||||
if (STUBS[request]) return STUBS[request];
|
||||
if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`));
|
||||
return require(request);
|
||||
};
|
||||
new Function("exports", "module", "require", js)(box.exports, box, localRequire);
|
||||
return box.exports;
|
||||
}
|
||||
|
||||
const { curveInfoText } = loadTs(path.join(B05, "B05_Profile_UI_RouteEdit_Label.ts"));
|
||||
process.stdout.write(
|
||||
JSON.stringify({
|
||||
curve: curveInfoText(true, 132.4, false),
|
||||
curveOptional: curveInfoText(true, 160.2, true),
|
||||
triangle: curveInfoText(false, 132.6, false),
|
||||
triangleOptional: curveInfoText(false, 168.4, true),
|
||||
triangleUnknown: curveInfoText(false, null, false),
|
||||
}),
|
||||
);
|
||||
@@ -0,0 +1,47 @@
|
||||
"""403 곡선 없는 교각점(삼각) 각도 글(요구 250-5) — 곡선 창 하단에 곡선 있는 자리와 같은 「내각 N°」.
|
||||
|
||||
Node 헬퍼(`helper_403_triangle_angle.cjs`)가 `_Label.curveInfoText` 를 트랜스파일해 돌림.
|
||||
./venv/Scripts/python.exe -m pytest resources/tester/test_403_triangle_angle.py -q
|
||||
"""
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def texts():
|
||||
proc = subprocess.run(
|
||||
["node", str(HERE / "helper_403_triangle_angle.cjs")],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
timeout=60,
|
||||
)
|
||||
assert proc.returncode == 0, proc.stderr
|
||||
return json.loads(proc.stdout)
|
||||
|
||||
|
||||
def test_곡선_있는_자리_그대로(texts):
|
||||
assert texts["curve"] == "내각 132°"
|
||||
assert texts["curveOptional"] == "내각 160° · 155° 이상 — 곡선 생략 가능"
|
||||
|
||||
|
||||
def test_삼각_자리도_내각(texts):
|
||||
assert texts["triangle"] == "내각 133° · 곡선 없음 — 직선이 그대로 꺾입니다"
|
||||
assert texts["triangleOptional"].startswith("내각 168° · ")
|
||||
|
||||
|
||||
def test_내각_모르면_곡선_없음만(texts):
|
||||
assert texts["triangleUnknown"] == "곡선 없음 — 직선이 그대로 꺾입니다"
|
||||
|
||||
|
||||
def test_화면이_같은_함수를_씀():
|
||||
label = (HERE.parents[1] / "B05_Profile" / "B05_Profile_UI_RouteEdit_Label.ts").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
assert "info.textContent = curveInfoText(state.curveOn, state.innerAngleDeg" in label
|
||||
Reference in New Issue
Block a user