feat(B07): CAD 수확 — pattern 채움 무늬를 다각형 안 선 · 원으로 펴서 도면에(88-4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016PSXsvyDxjNmufteN5bqmt
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
// B07 CAD 수확 — pattern 채움(노면공 무늬 셋 · 물넘이 빗금)을 다각형 안 선 · 원으로 펴기(88-4).
|
||||
// 실제 코드(`B07_DesignDetail_Cross_Overlay.patternMarks`)를 vite ssr 로 묶어 돌린다.
|
||||
// 실행: node resources/tester/test_cad_pattern_harvest.mjs
|
||||
import assert from "node:assert/strict";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { mkdtempSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
|
||||
const ROOT = resolve(import.meta.dirname, "../..");
|
||||
const out = mkdtempSync(join(tmpdir(), "cad-pattern-"));
|
||||
execFileSync(
|
||||
"node",
|
||||
[
|
||||
"./config/node_modules/vite/bin/vite.js",
|
||||
"build",
|
||||
"--configLoader",
|
||||
"runner",
|
||||
"--ssr",
|
||||
"../B07_DesignDetail/B07_DesignDetail_Cross_Overlay.ts",
|
||||
"--outDir",
|
||||
out,
|
||||
"--logLevel",
|
||||
"error",
|
||||
],
|
||||
{ cwd: ROOT, stdio: "pipe" },
|
||||
);
|
||||
const { patternMarks } = await import(
|
||||
pathToFileURL(join(out, "B07_DesignDetail_Cross_Overlay.js")).href
|
||||
);
|
||||
|
||||
// 도면 좌표(y 위로) 다각형 — SVG y 100~103(두께 3) · x 10~70. 닫힌 점열.
|
||||
const polygon = [
|
||||
[10, -100],
|
||||
[70, -100],
|
||||
[70, -103],
|
||||
[10, -103],
|
||||
[10, -100],
|
||||
];
|
||||
const inPoly = ([x, y]) => x >= 10 - 1e-6 && x <= 70 + 1e-6 && y <= -100 + 1e-6 && y >= -103 - 1e-6;
|
||||
const allPoints = (marks) => [
|
||||
...marks.polylines.flat(),
|
||||
...marks.circles.flatMap(({ center: [cx, cy], radius }) => [
|
||||
[cx - radius, cy],
|
||||
[cx + radius, cy],
|
||||
[cx, cy - radius],
|
||||
[cx, cy + radius],
|
||||
]),
|
||||
];
|
||||
|
||||
// ① 콘크리트 · 물넘이 빗금(M0,6 L6,0 · 칸 6) — 대각선이 칸을 넘어 이어져 한 줄씩 · 모두 다각형 안
|
||||
{
|
||||
const marks = patternMarks(polygon, {
|
||||
width: 6,
|
||||
height: 6,
|
||||
paths: [
|
||||
[
|
||||
[0, 6],
|
||||
[6, 0],
|
||||
],
|
||||
],
|
||||
rings: [],
|
||||
});
|
||||
assert.equal(marks.circles.length, 0);
|
||||
// x+y = 6k 인 대각선 중 띠(y 100~103)를 지나는 것: x+y ∈ (110, 173) → k = 19..28 = 10 줄
|
||||
assert.equal(marks.polylines.length, 10, `빗금 줄 수 ${marks.polylines.length}`);
|
||||
for (const run of marks.polylines) assert.equal(run.length, 2, "한 줄 = 두 점(이어 붙임)");
|
||||
assert.ok(allPoints(marks).every(inPoly), "빗금이 다각형 밖으로 나감");
|
||||
}
|
||||
|
||||
// ② 아스콘 점(원 r 0.7 · 칸 5) — 온전히 든 원은 원 그대로
|
||||
{
|
||||
const marks = patternMarks(polygon, {
|
||||
width: 5,
|
||||
height: 5,
|
||||
paths: [],
|
||||
rings: [{ cx: 1.5, cy: 1.5, rx: 0.7, ry: 0.7 }],
|
||||
});
|
||||
// 중심 y = 101.5 (칸 j=20) · x = 11.5, 16.5 … 66.5 = 12 개 — 모두 띠 안
|
||||
assert.equal(marks.circles.length, 12, `점 수 ${marks.circles.length}`);
|
||||
assert.equal(marks.polylines.length, 0);
|
||||
assert.ok(allPoints(marks).every(inPoly), "점이 다각형 밖으로 나감");
|
||||
}
|
||||
|
||||
// ③ 쇄석 돌(원 r 1.6 + 타원 · 칸 9) — 걸친 것은 잘린 폴리선 · 밖으로 안 나감
|
||||
{
|
||||
const marks = patternMarks(polygon, {
|
||||
width: 9,
|
||||
height: 9,
|
||||
paths: [],
|
||||
rings: [
|
||||
{ cx: 2.5, cy: 2.5, rx: 1.6, ry: 1.6 },
|
||||
{ cx: 6.8, cy: 6.5, rx: 1.8, ry: 1.2 },
|
||||
],
|
||||
});
|
||||
assert.ok(marks.polylines.length + marks.circles.length > 0, "돌 무늬 없음");
|
||||
assert.ok(allPoints(marks).every(inPoly), "돌이 다각형 밖으로 나감");
|
||||
}
|
||||
|
||||
// ④ 빈 칸 · 다각형 없음 = 무늬 없음
|
||||
{
|
||||
assert.deepEqual(patternMarks(polygon, { width: 0, height: 6, paths: [], rings: [] }), {
|
||||
polylines: [],
|
||||
circles: [],
|
||||
});
|
||||
assert.equal(patternMarks([], { width: 6, height: 6, paths: [], rings: [] }).polylines.length, 0);
|
||||
}
|
||||
|
||||
console.log("OK test_cad_pattern_harvest.mjs — 4건");
|
||||
Reference in New Issue
Block a user