- 391-1 측점 맴돔 · 고름 = 한 함수(drawStationNormal) · 좌우 20 m 고정 하늘색 · 짧은 12 px 선 · 절성토 색 지움 · 구조물 마름모 그대로 - 391-2 고른 곡선 = 굵은 호 + 교각점→BC · EC 접선 + BC · MC · EC 세 점(새 파일 RouteEdit_Curve_Pick · MC = curveMidVertex) · 곡선 없는 교각점 = 같은 크기 삼각형 - 391-3 잠금 = 황금(#ca8a04 · 어두움 #facc15) · 굵기 4 + 흰 테 - 시험 test_391_routeedit_plan_draw 새로 · test_381_3 맴돔 배선 고쳐 씀 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013QyNXY2TUKXCFMwAca2APG
75 lines
2.9 KiB
TypeScript
75 lines
2.9 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_RouteEdit_Curve_Pick.ts
|
|
* 노선 편집 평면 **고른 곡선 밝힘 · 곡선 없는 교각점 삼각형**(요구 242-12 · 13 · PLAN 391-2).
|
|
*
|
|
* 고른 곡선(교각점 고름 · 호 누름 = 같은 `picked`) = 호 굵게 + 교각점→BC · EC 접선 + BC · MC · EC
|
|
* 세 점(하늘색). `_Render` 가 노드 · 손잡이 뒤 맨 위에서 부름 — 집기(`_Input`)는 그대로.
|
|
* ========================================================================== */
|
|
|
|
import type { RouteEditScene } from "./B05_Profile_UI_RouteEdit_Render";
|
|
import { curveArcVertices, curveMidVertex } from "./logic/B05_Profile_UI_RouteEdit_Curve";
|
|
import type { Vertex } from "./logic/B05_Profile_UI_RouteEdit_Curve";
|
|
|
|
/** 고름 색 — 측점 법선(`_Hover`)과 같은 하늘색. */
|
|
const PICK_COLOR = "#0ea5e9";
|
|
/** 삼각형 외접 반지름 = 노드 반지름 × 이 값 — 원과 넓이가 비슷해 보이게. */
|
|
const TRIANGLE_SCALE = 1.4;
|
|
|
|
/** 곡선 없는 교각점 삼각형(391-2) — 꼭짓점 위 · 원 대신 같은 자리 · 크기. 경로만 그림. */
|
|
export function traceNodeTriangle(
|
|
context: CanvasRenderingContext2D,
|
|
x: number,
|
|
y: number,
|
|
radius: number,
|
|
): void {
|
|
const r = radius * TRIANGLE_SCALE;
|
|
context.moveTo(x, y - r);
|
|
context.lineTo(x + r * Math.cos(Math.PI / 6), y + r / 2);
|
|
context.lineTo(x - r * Math.cos(Math.PI / 6), y + r / 2);
|
|
context.closePath();
|
|
}
|
|
|
|
/** 고른 곡선 밝힘(391-2) — 곡선을 지운 교각점 · 고름 없음이면 안 그림. */
|
|
export function drawPickedCurve(
|
|
context: CanvasRenderingContext2D,
|
|
scene: RouteEditScene,
|
|
style: CSSStyleDeclaration,
|
|
): void {
|
|
const curve = scene.curveInfo.find((item) => item.node_first === scene.picked);
|
|
if (!curve || scene.curveOn[curve.node_first] === false) return;
|
|
const halo = style.getPropertyValue("--map-halo") || "rgba(255,255,255,0.9)";
|
|
const path = (points: ReadonlyArray<Vertex>): void => {
|
|
context.beginPath();
|
|
points.forEach((vertex, index) => {
|
|
const [x, y] = scene.toScreen(vertex);
|
|
if (index === 0) context.moveTo(x, y);
|
|
else context.lineTo(x, y);
|
|
});
|
|
};
|
|
context.save();
|
|
context.strokeStyle = PICK_COLOR;
|
|
context.lineWidth = 2;
|
|
context.setLineDash([6, 4]);
|
|
path([curve.start, curve.apex, curve.end]);
|
|
context.stroke();
|
|
context.setLineDash([]);
|
|
path(curveArcVertices(curve));
|
|
context.strokeStyle = halo;
|
|
context.lineWidth = 8;
|
|
context.stroke();
|
|
context.strokeStyle = PICK_COLOR;
|
|
context.lineWidth = 5;
|
|
context.stroke();
|
|
context.fillStyle = PICK_COLOR;
|
|
context.strokeStyle = halo;
|
|
context.lineWidth = 2;
|
|
[curve.start, curveMidVertex(curve), curve.end].forEach((point) => {
|
|
const [x, y] = scene.toScreen(point);
|
|
context.beginPath();
|
|
context.arc(x, y, 5, 0, Math.PI * 2);
|
|
context.fill();
|
|
context.stroke();
|
|
});
|
|
context.restore();
|
|
}
|