지붕면 할당 로직 수정 #214
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user