Merge pull request '지붕면 할당 로직 수정' (#214) from dev into dev-deploy

Reviewed-on: #214
This commit is contained in:
ysCha 2025-07-17 17:02:21 +09:00
commit 12fd22d051

View File

@ -303,13 +303,119 @@ export function removeDuplicatePolygons(polygons, hasAuxiliaryLine = false) {
}
})
if (!hasAuxiliaryLine) {
uniquePolygons = uniquePolygons.filter((polygon) => {
return isValidPoints(polygon)
uniquePolygons = uniquePolygons.filter((polygon) => {
return !checkPolygonSelfIntersection(polygon)
})
// uniquePolygons = uniquePolygons.filter((polygon) => {
// return isValidPoints(polygon)
// })
console.log('uniquePolygons2', uniquePolygons)
return uniquePolygons
}
/**
* 선분이 교차하는지 확인하는 함수
* @param {Object} p1 번째 선분의 시작점 {x, y}
* @param {Object} q1 번째 선분의 끝점 {x, y}
* @param {Object} p2 번째 선분의 시작점 {x, y}
* @param {Object} q2 번째 선분의 끝점 {x, y}
* @returns {boolean} 교차하면 true, 아니면 false
*/
function doSegmentsIntersect(p1, q1, p2, q2) {
// CCW (Counter-Clockwise) 방향 확인 함수
function orientation(p, q, r) {
const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)
if (val === 0) return 0 // 일직선
return val > 0 ? 1 : 2 // 시계방향 또는 반시계방향
}
// 점 q가 선분 pr 위에 있는지 확인
function onSegment(p, q, r) {
return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y)
}
// 같은 끝점을 공유하는 경우는 교차로 보지 않음
if ((p1.x === p2.x && p1.y === p2.y) || (p1.x === q2.x && p1.y === q2.y) || (q1.x === p2.x && q1.y === p2.y) || (q1.x === q2.x && q1.y === q2.y)) {
return false
}
const o1 = orientation(p1, q1, p2)
const o2 = orientation(p1, q1, q2)
const o3 = orientation(p2, q2, p1)
const o4 = orientation(p2, q2, q1)
// 일반적인 교차 경우
if (o1 !== o2 && o3 !== o4) return true
// 특별한 경우들 (한 점이 다른 선분 위에 있는 경우)
if (o1 === 0 && onSegment(p1, p2, q1)) return true
if (o2 === 0 && onSegment(p1, q2, q1)) return true
if (o3 === 0 && onSegment(p2, p1, q2)) return true
if (o4 === 0 && onSegment(p2, q1, q2)) return true
return false
}
/**
* 다각형의 자기 교차를 검사하는 메인 함수
* @param {Array} coordinates 다각형의 좌표 배열 [{x, y}, ...]
* @returns {Object} 검사 결과 {hasSelfIntersection: boolean, intersections: Array}
*/
function checkPolygonSelfIntersection(coordinates) {
if (coordinates.length < 3) {
return {
hasSelfIntersection: false,
intersections: [],
error: '다각형은 최소 3개의 점이 필요합니다.',
}
}
const intersections = []
const edges = []
// 모든 변(edge) 생성
for (let i = 0; i < coordinates.length; i++) {
const start = coordinates[i]
const end = coordinates[(i + 1) % coordinates.length]
edges.push({
start: start,
end: end,
index: i,
})
}
return uniquePolygons
// 모든 변 쌍에 대해 교차 검사
for (let i = 0; i < edges.length; i++) {
for (let j = i + 1; j < edges.length; j++) {
// 인접한 변들은 제외 (끝점을 공유하므로)
if (Math.abs(i - j) === 1 || (i === 0 && j === edges.length - 1)) {
continue
}
const edge1 = edges[i]
const edge2 = edges[j]
if (doSegmentsIntersect(edge1.start, edge1.end, edge2.start, edge2.end)) {
intersections.push({
edge1Index: i,
edge2Index: j,
edge1: {
from: edge1.start,
to: edge1.end,
},
edge2: {
from: edge2.start,
to: edge2.end,
},
})
}
}
}
return intersections.length > 0
}
// 같은 직선상에 있는지 확인 같은 직선이라면 polygon을 생성할 수 없으므로 false