From 4dafcc0274654a7baff37ac755c4d6d0ac5ece0d Mon Sep 17 00:00:00 2001 From: yscha Date: Tue, 2 Dec 2025 01:31:17 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B2=BD=EA=B3=84=EC=84=A0=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/skeleton-utils.js | 105 ++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/src/util/skeleton-utils.js b/src/util/skeleton-utils.js index 4e859840..9565d22b 100644 --- a/src/util/skeleton-utils.js +++ b/src/util/skeleton-utils.js @@ -772,6 +772,57 @@ if(roof.moveUpDown??0 > 0) { //roofline 외곽선 설정 + // Check if wallBaseLine is inside the polygon formed by sortedWallLines + const isWallBaseLineInside = (() => { + if (!wallBaseLine || sortedWallLines.length < 3) return false; + + // Get both endpoints of the wall base line + const p1 = { x: wallBaseLine.x1, y: wallBaseLine.y1 }; + const p2 = { x: wallBaseLine.x2, y: wallBaseLine.y2 }; + const midPoint = { + x: (p1.x + p2.x) / 2, + y: (p1.y + p2.y) / 2 + }; + + // Create polygon points from wall lines + const polygonPoints = sortedWallLines.map(line => ({x: line.x1, y: line.y1})); + console.log('Polygon points:', polygonPoints); + // Close the polygon if needed + if (polygonPoints.length > 0) { + const first = polygonPoints[0]; + const last = polygonPoints[polygonPoints.length - 1]; + if (first.x !== last.x || first.y !== last.y) { + polygonPoints.push({...first}); + } + } + + // Check both endpoints and midpoint to be more accurate + const p1Inside = isPointInsidePolygon(p1, polygonPoints); + const p2Inside = isPointInsidePolygon(p2, polygonPoints); + const midPointInside = isPointInsidePolygon(midPoint, polygonPoints); + + // If any of the points are inside, consider the line as inside + return p1Inside || p2Inside || midPointInside; + })(); + +// Debug information + console.log(`Wall base line at index ${index}:`, + JSON.parse(JSON.stringify({ + p1: {x: wallBaseLine.x1, y: wallBaseLine.y1}, + p2: {x: wallBaseLine.x2, y: wallBaseLine.y2}, + isWallBaseLineInside + })) + ); + + if (isWallBaseLineInside) { + console.log(`Wall base line at index ${index} is INSIDE the polygon`); + // Your logic for inside case + } else { + console.log(`Wall base line at index ${index} is OUTSIDE the polygon`); + // Your logic for outside case + } + + console.log('=== Line Coordinates ==='); console.table({ 'Point' : ['X', 'Y'], @@ -851,6 +902,7 @@ if(roof.moveUpDown??0 > 0) { if (fullyMoved) { //반시계방향향 console.log("moveFully:::::::::::::", wallBaseLine, newPStart, newPEnd) + if (getOrientation(roofLine) === 'vertical') { //왼쪽 부터 roofLine, wallBaseLine if (newPEnd.y <= wallBaseLine.y2 && wallBaseLine.y2 <= newPStart.y && newPStart.y <= wallBaseLine.y1) { //top right @@ -3956,4 +4008,55 @@ function updateAndAddLine(innerLines, targetPoint) { } return updatedLines; -} \ No newline at end of file +} + +/** + * A, B, C: 각각 QLine 1개 (x1,y1,x2,y2 존재) + * + * 의미: + * - 'in' : C와 B의 y가 같고, C의 x범위가 B 안에 완전히 포함 + * - 'center' : C의 y가 A와 B 사이(위/아래 원하는 대로 조정 가능)이고, + * C의 x범위가 B와 겹침 + * - 'out' : 그 외 + */ +function classifyLineABC(A, B, C) { + if (!A || !B || !C) return undefined; + + function toHSegment(line) { + let { x1, y1, x2, y2 } = line; + if (x1 > x2) { + const tx = x1; x1 = x2; x2 = tx; + } + return { x1, x2, y: y1 }; + } + + const a = toHSegment(A); + const b = toHSegment(B); + const c = toHSegment(C); + + // x 겹침 / 포함 + function isXOverlap(s1, s2) { + return !(s1.x2 < s2.x1 || s2.x2 < s1.x1); + } + function isXInside(inner, outer) { + return inner.x1 >= outer.x1 && inner.x2 <= outer.x2; + } + + // 1) C가 B와 같은 y 이고, x 범위가 B 안에 완전히 포함되면 -> in + const sameYasB = Math.abs(c.y - b.y) < 1e-6; + if (sameYasB && isXInside(c, b)) { + return 'in'; + } + + // 2) C가 A와 B 사이 y 이고, x 가 B 와 겹치면 -> center + const minY = Math.min(a.y, b.y); + const maxY = Math.max(a.y, b.y); + const betweenY = c.y > minY && c.y < maxY; + + if (betweenY && isXOverlap(c, b)) { + return 'center'; + } + + // 3) 나머지 -> out + return 'out'; +}