fix(562-3): D03 갈래 시작 = 가장 가까운 꺾임점 · 제약 기울기 칸 = 오르내림 같은 크기

- 갈래 · 마크 누름: 붙는 반경 안 꺾임점 중 첫 것이 아니라 가장 가까운 것(짧은 구간이 붙어 있으면 앞 점이 잡히던 흠)
- 562-1 짝이 |기울기|로 셈 → 칸 이름 「기울기(± 같음)」 · 자리 없음 안내 ±값

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 20:41:00 +09:00
co-authored by Claude Opus 5.5
parent 1bb7a2c957
commit 604808ede7
+13 -5
View File
@@ -4,7 +4,8 @@
*
* 본선 = D02 시점에서 · D02 종점 둘레(SNAP_PX)에 오면 종점에 붙고 그 점에서 끝.
* 미리보기 = 마지막 점 → 마우스 길이(m) · 원지반 기울기(%, + 오르막) — 제약 칸 넷:
* 자유 · 길이 고정 · 기울기 고정(마우스 방향 첫 자리) · 둘 다(양각기 원 위 후보 중 마우스에 가까운 것).
* 자유 · 길이 고정 · 기울기 고정(마우스 방향 첫 자리) · 둘 다(양각기 원 위 후보 중 마우스에 가까운 것) ·
* 제약 기울기 = 오르내림 같은 크기(562-1 짝이 |기울기|로 셈) · 미리보기 값은 + 오르막 / − 내리막.
* 갈래 = 기존 선 꺾임점(선 위면 꺾임점 끼움)을 눌러 시작 · 구역 마크 = 선 위 누름(오른쪽 = 지움).
* 키 = Enter 끝 · Esc 이번 긋기 취소 · Backspace 마지막 점 빼기(설정 창 단축키 표 D03 줄).
* 셈 = 562-1 짝(`logic/D03_PlanAnalysis_Draw`) · 꼴 다루기 = `logic/D03_PlanAnalysis_Plan` ·
@@ -165,7 +166,7 @@ export function createPlanDraw(params: PlanDrawParams): PlanDraw {
});
lengthField.input.dataset.role = "draw-length";
const slopeField = createInputField({
label: "기울기(+ 오르막)",
label: "기울기(± 같음)",
type: "number",
value: String(slopePct),
unit: "%",
@@ -240,10 +241,10 @@ export function createPlanDraw(params: PlanDrawParams): PlanDraw {
point = fixedLengthPoint(from, cursor, lengthM);
} else if (kind === "slope") {
point = fixedSlopePoint(from, cursor, slopePct, z);
if (!point) note = `이 방향엔 ${signed(slopePct)} % 자리 없음`;
if (!point) note = `이 방향엔 ±${fmt(Math.abs(slopePct))} % 자리 없음`;
} else if (kind === "both") {
point = compassPoint(from, cursor, lengthM, slopePct, z);
if (!point) note = `반지름 ${fmt(lengthM)} m 원 위에 ${signed(slopePct)} % 자리 없음`;
if (!point) note = `반지름 ${fmt(lengthM)} m 원 위에 ±${fmt(Math.abs(slopePct))} % 자리 없음`;
}
const at = point ?? cursor;
const length = segmentLength(from, at);
@@ -268,7 +269,14 @@ export function createPlanDraw(params: PlanDrawParams): PlanDraw {
let bestPx = LINE_HIT_PX;
params.network().lines.forEach((line, index) => {
if (line.vertices.length < 2) return;
const vertex = line.vertices.findIndex((v) => near(map.toScreen(v), [px, py], SNAP_PX));
// 붙는 반경 안 꺾임점 중 가장 가까운 것
let vertex = -1;
let vertexPx = SNAP_PX;
line.vertices.forEach((v, i) => {
const [vx, vy] = map.toScreen(v);
const d = Math.hypot(vx - px, vy - py);
if (d <= vertexPx) [vertex, vertexPx] = [i, d];
});
const atM =
vertex >= 0
? lineLength(line.vertices.slice(0, vertex + 1))