feat(B06): 306 횡단 맹암거 안 엇갈려 겹친 돌 무늬 · 그림 전용 · 고르기 차례 = 안쪽 판정면 맨 아래 · 테두리 판정 면 판정 맨 위
- 돌 무늬: 켜마다 반 칸 엇갈림 · 이웃 · 위아래와 겹침 · 기울기 ±22° 번갈아 교차 · 맹암거 색(카드 · [상세] 모달 같은 그림) - 맹암거 무리 pointer-events none — 성토 띠 · 포장 · 넓은 관 판정면이 맹암거 안에서도 골라짐 - 차례: 보라 선 > 맹암거 테두리 > 구조물 판정면(작은 것 위) > 그림 · 띠 > 맹암거 안쪽 - 시험 test_306_underdrain_pick Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TteK8mfYZetk5P3bEZkyVZ
This commit is contained in:
@@ -5,12 +5,19 @@
|
||||
* 판정면(구조물 · 띠 · 형상)을 다 꽂은 뒤 넓이 큰 것부터 아래로 다시 세움(작은 것 위) ·
|
||||
* 보라 선 판정(넓이 0 · 요구 185 사면 손잡이)은 맨 위 · 면적 띠(절 · 성토)는 맨 아래 그대로.
|
||||
* 끌고 뗀 누름(3 px 넘게 움직임)은 고름 아님.
|
||||
* 맹암거(306-2) = 안쪽 판정면은 맨 아래(겹친 띠 · 구조물이 위) · 테두리 판정(투명 굵은 선)이 면 판정 맨 위.
|
||||
* ========================================================================== */
|
||||
|
||||
import { thickenDown } from "./B06_Section_UI_Cross_Shape_Pick";
|
||||
|
||||
/** 면 판정 — 구조물(벽 · 관 · 박스 · 도수로 띠 등) · 물넘이포장 · 맹암거 형상. */
|
||||
const SURFACE_HIT_CLASSES = ["b06-chart__culvert-revet-hit", "b06-chart__shape-hit"];
|
||||
/** 선 판정 — 보라 설계선 조각(`_Cross_Design_Pick`). */
|
||||
const LINE_HIT_CLASS = "b06-chart__design-hit";
|
||||
/** 맹암거 몸(그림) · 테두리 판정 클래스(306-2). */
|
||||
const UNDERDRAIN_GROUP = "b06-chart__underdrain";
|
||||
const UNDERDRAIN_BODY = "b06-chart__underdrain-body";
|
||||
const EDGE_CLASS = "b06-chart__shape-hit--edge";
|
||||
/** 끌기로 볼 움직임(px) — 형상 고름(`SHAPE_DRAG_PX`)과 같은 값. */
|
||||
const DRAG_PX = 3;
|
||||
|
||||
@@ -33,13 +40,36 @@ export function pointsArea(points: string | null): number {
|
||||
/** 판정면을 넓이 차례로 다시 세우고 보라 선 판정을 맨 위로 · 끌기 누름을 막음. */
|
||||
export function stackPickTargets(layer: SVGElement): void {
|
||||
const kids = [...layer.children];
|
||||
// 맹암거 판정면 = 형상 고름이 몸 둘레(`thickenDown`)로 꽂은 것
|
||||
const bodies = new Set(
|
||||
kids
|
||||
.filter((el) => el.classList.contains(UNDERDRAIN_GROUP))
|
||||
.flatMap((group) => [...group.children])
|
||||
.filter((el) => el.classList.contains(UNDERDRAIN_BODY))
|
||||
.map((el) => thickenDown(el.getAttribute("points") ?? "")),
|
||||
);
|
||||
const inners = kids.filter(
|
||||
(el) =>
|
||||
el.classList.contains("b06-chart__shape-hit") && bodies.has(el.getAttribute("points") ?? ""),
|
||||
);
|
||||
const edges = inners.map((inner) => {
|
||||
layer.prepend(inner);
|
||||
const edge = inner.cloneNode() as SVGElement;
|
||||
edge.classList.add(EDGE_CLASS);
|
||||
edge.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
inner.dispatchEvent(new MouseEvent("click")); // 고름은 안쪽 판정면 창구 하나
|
||||
});
|
||||
return edge;
|
||||
});
|
||||
const surfaces = kids
|
||||
.filter((el) => SURFACE_HIT_CLASSES.some((name) => el.classList.contains(name)))
|
||||
.filter((el) => !inners.includes(el))
|
||||
.map((el) => ({ el, area: pointsArea(el.getAttribute("points")) }))
|
||||
.sort((a, b) => b.area - a.area)
|
||||
.map(({ el }) => el);
|
||||
const lines = kids.filter((el) => el.classList.contains(LINE_HIT_CLASS));
|
||||
layer.append(...surfaces, ...lines);
|
||||
layer.append(...surfaces, ...edges, ...lines);
|
||||
let down: { x: number; y: number } | null = null;
|
||||
layer.addEventListener(
|
||||
"pointerdown",
|
||||
|
||||
@@ -5,17 +5,39 @@
|
||||
* · 노면 = 설계 노면 — 서버 · TS 짝이 암거 경사로 지대 낮은 쪽 한 경사로 기울여 냄 · 측구 없음.
|
||||
* · 옵셋선 = 노면을 암거 높이만큼 아래로 같은 각도.
|
||||
* · 성토 쪽 = 옵셋선을 성토 사면과 만날 때까지 · 절토 쪽 = 절토 사면을 아래로 늘여 옵셋선과 만남.
|
||||
* · 노면 · 양쪽 선 · 옵셋선이 둘러싼 안 = 돌 무늬(흙막이 돌 그리기 `drawStones`).
|
||||
* · 노면 · 양쪽 선 · 옵셋선이 둘러싼 안 = 돌 무늬(306-1) — 켜마다 반 칸 엇갈리고 이웃과 겹친 돌 ·
|
||||
* 기울기를 번갈아 서로 교차 · 그림 전용(누름 안 받음 · CSS `.b06-chart__underdrain`).
|
||||
* 높이가 비면 그리지 않음(수치를 지어내지 않음).
|
||||
* ========================================================================== */
|
||||
|
||||
import type { CrossDesign } from "./B06_Section_Api_Fetch";
|
||||
import type { OffsetPoint } from "./B06_Section_UI_Cross_Culvert_Types";
|
||||
import { drawStones } from "./B06_Section_UI_Cross_Wall_Hatch";
|
||||
import { cell, courses, type BandFrame } from "./B06_Section_UI_Cross_Wall_Hatch";
|
||||
import type { UnderdrainSpec } from "@util/common_util_structure_underdrain";
|
||||
|
||||
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
let clipSeq = 0;
|
||||
/** 돌 한 칸(m · 보기용) · 이웃과 겹침 배수 · 번갈아 기울기(도). */
|
||||
const STONE_M = 0.25;
|
||||
const STONE_OVERLAP = 1.4;
|
||||
const STONE_TILT_DEG = 22;
|
||||
|
||||
/** 엇갈려 겹친 돌 무늬(306-1) — 켜(가로줄)마다 반 칸 밀고 · 돌은 칸보다 커서 이웃 · 위아래와 겹침 ·
|
||||
* 기울기를 번갈아 서로 교차. `frame` v = −0.5(노면) ~ 0.5(옵셋선). */
|
||||
export function drawCrossedStones(group: SVGElement, frame: BandFrame, heightM: number): void {
|
||||
const rows = courses(heightM, STONE_M);
|
||||
const count = courses(frame.spanM, STONE_M);
|
||||
const across = (heightM / rows) * STONE_OVERLAP;
|
||||
const along = (frame.spanM / count) * STONE_OVERLAP;
|
||||
for (let r = 0; r < rows; r += 1) {
|
||||
const shift = r % 2 ? 0 : 0.5;
|
||||
for (let i = 0; i + shift <= count; i += 1) {
|
||||
const tilt = (i + r) % 2 ? STONE_TILT_DEG : -STONE_TILT_DEG;
|
||||
const lean = { ...frame, leanDegrees: frame.leanDegrees + tilt };
|
||||
group.append(cell(lean, (i + shift) / count, (r + 0.5) / rows - 0.5, across, along, 0.45));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Edge = { offset_m: number; elevation_m: number };
|
||||
|
||||
@@ -120,7 +142,7 @@ export function appendUnderdrainOverlay(
|
||||
};
|
||||
const [ax, ay] = px(at(0, 0));
|
||||
const [bx, by] = px(at(1, 0));
|
||||
drawStones(
|
||||
drawCrossedStones(
|
||||
stones,
|
||||
{
|
||||
spanM: Math.hypot(hi - lo, grade * (hi - lo)),
|
||||
@@ -128,7 +150,6 @@ export function appendUnderdrainOverlay(
|
||||
point: (u, v) => px(at(u, v)),
|
||||
leanDegrees: (Math.atan2(bx - ax, -(by - ay)) * 180) / Math.PI,
|
||||
},
|
||||
false,
|
||||
height,
|
||||
);
|
||||
group.append(body, clip, stones);
|
||||
|
||||
@@ -267,7 +267,25 @@
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
/* 맹암거(288-1): 노면 아래 돌 무늬 형상 */
|
||||
/* 맹암거(288-1): 노면 아래 돌 무늬 형상 · 그림 전용 — 누름은 판정면(306-2) */
|
||||
.b06-chart__underdrain {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* 엇갈려 겹친 돌(306-1) — 맹암거 색 · 밝음 · 어두움 모두 읽힘 */
|
||||
.b06-chart__underdrain .b06-chart__culvert-stone {
|
||||
stroke: #3aa0a8;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
/* 맹암거 테두리 판정(306-2) — 면 판정 맨 위 · 안쪽 판정면은 맨 아래 */
|
||||
.b06-chart__shape-hit.b06-chart__shape-hit--edge {
|
||||
fill: none;
|
||||
stroke: transparent;
|
||||
stroke-width: 8;
|
||||
pointer-events: stroke;
|
||||
}
|
||||
|
||||
.b06-chart__underdrain-body {
|
||||
fill: color-mix(in srgb, #3aa0a8 16%, transparent);
|
||||
stroke: #3aa0a8;
|
||||
|
||||
Reference in New Issue
Block a user