wallbaseLine merge
This commit is contained in:
parent
f0e71df5d4
commit
008a1230cc
@ -212,12 +212,14 @@ const movingLineFromSkeleton = (roofId, canvas) => {
|
|||||||
point.y = Big(point.y).plus(moveUpDownLength).toNumber();
|
point.y = Big(point.y).plus(moveUpDownLength).toNumber();
|
||||||
}
|
}
|
||||||
}else if(moveDirection === 'out'){
|
}else if(moveDirection === 'out'){
|
||||||
if(isSamePoint(roof.basePoints[index], originalStartPoint)) {
|
if(isSamePoint(roof.basePoints[index], originalStartPoint) || isSamePoint(roof.basePoints[index], originalEndPoint)) {
|
||||||
point.y = Big(point.y).minus(moveUpDownLength).toNumber();
|
|
||||||
}
|
|
||||||
if (isSamePoint(roof.basePoints[index], originalEndPoint)) {
|
|
||||||
point.y = Big(point.y).minus(moveUpDownLength).toNumber();
|
point.y = Big(point.y).minus(moveUpDownLength).toNumber();
|
||||||
|
// console.log('roof.basePoints[index]', roof.basePoints[index])
|
||||||
|
// console.log('point.x::::', point)
|
||||||
|
// console.log('originalStartPoint', originalStartPoint)
|
||||||
|
// console.log('originalEndPoint', originalEndPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}else if(position === 'left'){
|
}else if(position === 'left'){
|
||||||
@ -262,7 +264,69 @@ const movingLineFromSkeleton = (roofId, canvas) => {
|
|||||||
line.startPoint = newStartPoint;
|
line.startPoint = newStartPoint;
|
||||||
line.endPoint = newEndPoint;
|
line.endPoint = newEndPoint;
|
||||||
});
|
});
|
||||||
return newPoints;
|
|
||||||
|
/**
|
||||||
|
* 직선다각형을 이루지 못하는 좌표를 삭제합니다.
|
||||||
|
* @param {Array<object>} points - 폴리곤 좌표 배열
|
||||||
|
* @returns {Array<object>} 정리된 좌표 배열
|
||||||
|
*/
|
||||||
|
function removeNonOrthogonalPoints(points) {
|
||||||
|
if (!points || points.length < 3) return points;
|
||||||
|
|
||||||
|
const EPSILON = 1.0;
|
||||||
|
|
||||||
|
const isOrthogonal = (p1, p2) =>
|
||||||
|
Math.abs(p1.x - p2.x) < EPSILON || Math.abs(p1.y - p2.y) < EPSILON;
|
||||||
|
|
||||||
|
let current = [...points];
|
||||||
|
let changed = true;
|
||||||
|
|
||||||
|
// 1. 대각선을 만드는 점 제거
|
||||||
|
while (changed && current.length >= 3) {
|
||||||
|
changed = false;
|
||||||
|
for (let i = 0; i < current.length; i++) {
|
||||||
|
const pPrev = current[(i - 1 + current.length) % current.length];
|
||||||
|
const pCurr = current[i];
|
||||||
|
const pNext = current[(i + 1) % current.length];
|
||||||
|
|
||||||
|
// 현재 점(pCurr)을 기준으로 앞뒤 연결이 모두 직교하지 않거나,
|
||||||
|
// 현재 점을 제거했을 때 앞뒤 점(pPrev, pNext)이 직교하게 된다면 현재 점이 불필요한 "꺾임"일 수 있음.
|
||||||
|
if (!isOrthogonal(pPrev, pCurr) || !isOrthogonal(pCurr, pNext)) {
|
||||||
|
if (isOrthogonal(pPrev, pNext)) {
|
||||||
|
current.splice(i, 1);
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 일직선상의 중간 점 제거 (수평 또는 수직선상에 세 점이 있는 경우)
|
||||||
|
changed = true;
|
||||||
|
while (changed && current.length >= 3) {
|
||||||
|
changed = false;
|
||||||
|
for (let i = 0; i < current.length; i++) {
|
||||||
|
const p1 = current[i];
|
||||||
|
const p2 = current[(i + 1) % current.length];
|
||||||
|
const p3 = current[(i + 2) % current.length];
|
||||||
|
|
||||||
|
if ((Math.abs(p1.x - p2.x) < EPSILON && Math.abs(p2.x - p3.x) < EPSILON) ||
|
||||||
|
(Math.abs(p1.y - p2.y) < EPSILON && Math.abs(p2.y - p3.y) < EPSILON)) {
|
||||||
|
current.splice((i + 1) % current.length, 1);
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const cleaned = removeNonOrthogonalPoints(newPoints);
|
||||||
|
console.log(cleaned); // 결과: 4개의 점만 남음 (P1, P2, P3, P4)
|
||||||
|
|
||||||
|
return cleaned;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,7 +440,7 @@ export const skeletonBuilder = (roofId, canvas, textMode) => {
|
|||||||
canvas.set('skeleton', cleanSkeleton)
|
canvas.set('skeleton', cleanSkeleton)
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
|
|
||||||
console.log('skeleton rendered.', canvas)
|
//console.log('skeleton rendered.', canvas)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('스켈레톤 생성 중 오류 발생:', e)
|
console.error('스켈레톤 생성 중 오류 발생:', e)
|
||||||
if (canvas.skeletonStates) {
|
if (canvas.skeletonStates) {
|
||||||
@ -470,9 +534,14 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
|||||||
line.attributes.type === 'gable' && isSameLine(Begin.X, Begin.Y, End.X, End.Y, line)
|
line.attributes.type === 'gable' && isSameLine(Begin.X, Begin.Y, End.X, End.Y, line)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (gableBaseLine) {
|
if (gableBaseLine) {
|
||||||
// Store current state before processing
|
// Store current state before processing - avoid circular refs by only picking needed data
|
||||||
const beforeGableProcessing = JSON.parse(JSON.stringify(skeletonLines));
|
const beforeGableProcessing = skeletonLines.map(line => ({
|
||||||
|
p1: { x: line.p1.x, y: line.p1.y },
|
||||||
|
p2: { x: line.p2.x, y: line.p2.y },
|
||||||
|
attributes: { ...line.attributes },
|
||||||
|
lineStyle: { ...line.lineStyle }
|
||||||
|
}));
|
||||||
|
|
||||||
// if(canvas.skeletonLines.length > 0){
|
// if(canvas.skeletonLines.length > 0){
|
||||||
// skeletonLines = canvas.skeletonLines;
|
// skeletonLines = canvas.skeletonLines;
|
||||||
@ -623,51 +692,51 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
|||||||
const sortRoofLines = ensureCounterClockwiseLines(roofLines)
|
const sortRoofLines = ensureCounterClockwiseLines(roofLines)
|
||||||
|
|
||||||
// roofLines의 방향에 맞춰 currentRoofLines의 방향을 조정
|
// roofLines의 방향에 맞춰 currentRoofLines의 방향을 조정
|
||||||
const alignLineDirection = (sourceLines, targetLines) => {
|
// const alignLineDirection = (sourceLines, targetLines) => {
|
||||||
return sourceLines.map((sourceLine) => {
|
// return sourceLines.map((sourceLine) => {
|
||||||
// 가장 가까운 targetLine 찾기
|
// // 가장 가까운 targetLine 찾기
|
||||||
const nearestTarget = targetLines.reduce((nearest, targetLine) => {
|
// const nearestTarget = targetLines.reduce((nearest, targetLine) => {
|
||||||
const sourceCenter = {
|
// const sourceCenter = {
|
||||||
x: (sourceLine.x1 + sourceLine.x2) / 2,
|
// x: (sourceLine.x1 + sourceLine.x2) / 2,
|
||||||
y: (sourceLine.y1 + sourceLine.y2) / 2,
|
// y: (sourceLine.y1 + sourceLine.y2) / 2,
|
||||||
}
|
// }
|
||||||
const targetCenter = {
|
// const targetCenter = {
|
||||||
x: (targetLine.x1 + targetLine.x2) / 2,
|
// x: (targetLine.x1 + targetLine.x2) / 2,
|
||||||
y: (targetLine.y1 + targetLine.y2) / 2,
|
// y: (targetLine.y1 + targetLine.y2) / 2,
|
||||||
}
|
// }
|
||||||
const distance = Math.hypot(sourceCenter.x - targetCenter.x, sourceCenter.y - targetCenter.y)
|
// const distance = Math.hypot(sourceCenter.x - targetCenter.x, sourceCenter.y - targetCenter.y)
|
||||||
|
//
|
||||||
return !nearest || distance < nearest.distance ? { line: targetLine, distance } : nearest
|
// return !nearest || distance < nearest.distance ? { line: targetLine, distance } : nearest
|
||||||
}, null)?.line
|
// }, null)?.line
|
||||||
|
//
|
||||||
if (!nearestTarget) return sourceLine
|
// if (!nearestTarget) return sourceLine
|
||||||
|
//
|
||||||
// 방향이 반대인지 확인 (벡터 내적을 사용)
|
// // 방향이 반대인지 확인 (벡터 내적을 사용)
|
||||||
const sourceVec = {
|
// const sourceVec = {
|
||||||
x: sourceLine.x2 - sourceLine.x1,
|
// x: sourceLine.x2 - sourceLine.x1,
|
||||||
y: sourceLine.y2 - sourceLine.y1,
|
// y: sourceLine.y2 - sourceLine.y1,
|
||||||
}
|
// }
|
||||||
const targetVec = {
|
// const targetVec = {
|
||||||
x: nearestTarget.x2 - nearestTarget.x1,
|
// x: nearestTarget.x2 - nearestTarget.x1,
|
||||||
y: nearestTarget.y2 - nearestTarget.y1,
|
// y: nearestTarget.y2 - nearestTarget.y1,
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
const dotProduct = sourceVec.x * targetVec.x + sourceVec.y * targetVec.y
|
// const dotProduct = sourceVec.x * targetVec.x + sourceVec.y * targetVec.y
|
||||||
|
//
|
||||||
// 내적이 음수이면 방향이 반대이므로 뒤집기
|
// // 내적이 음수이면 방향이 반대이므로 뒤집기
|
||||||
if (dotProduct < 0) {
|
// if (dotProduct < 0) {
|
||||||
return {
|
// return {
|
||||||
...sourceLine,
|
// ...sourceLine,
|
||||||
x1: sourceLine.x2,
|
// x1: sourceLine.x2,
|
||||||
y1: sourceLine.y2,
|
// y1: sourceLine.y2,
|
||||||
x2: sourceLine.x1,
|
// x2: sourceLine.x1,
|
||||||
y2: sourceLine.y1,
|
// y2: sourceLine.y1,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return sourceLine
|
// return sourceLine
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
console.log('wallBaseLines', wall.baseLines)
|
console.log('wallBaseLines', wall.baseLines)
|
||||||
|
|
||||||
@ -693,10 +762,32 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
|||||||
console.log('wallBaseLine:', wallBaseLine.x1, wallBaseLine.y1, wallBaseLine.x2, wallBaseLine.y2)
|
console.log('wallBaseLine:', wallBaseLine.x1, wallBaseLine.y1, wallBaseLine.x2, wallBaseLine.y2)
|
||||||
console.log('isSamePoint result:', isSameLine2(wallBaseLine, wallLine))
|
console.log('isSamePoint result:', isSameLine2(wallBaseLine, wallLine))
|
||||||
|
|
||||||
|
const isCollinear = (l1, l2, tolerance = 0.1) => {
|
||||||
|
const slope1 = Math.abs(l1.x2 - l1.x1) < tolerance ? Infinity : (l1.y2 - l1.y1) / (l1.x2 - l1.x1)
|
||||||
|
const slope2 = Math.abs(l2.x2 - l2.x1) < tolerance ? Infinity : (l2.y2 - l2.y1) / (l2.x2 - l2.x1)
|
||||||
|
|
||||||
|
if (slope1 === Infinity && slope2 === Infinity) {
|
||||||
|
return Math.abs(l1.x1 - l2.x1) < tolerance
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.abs(slope1 - slope2) > tolerance) return false
|
||||||
|
|
||||||
|
const yIntercept1 = l1.y1 - slope1 * l1.x1
|
||||||
|
const yIntercept2 = l2.y1 - slope2 * l2.x1
|
||||||
|
|
||||||
|
return Math.abs(yIntercept1 - yIntercept2) < tolerance
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCollinear(wallBaseLine, wallLine)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (isSameLine2(wallBaseLine, wallLine)) {
|
if (isSameLine2(wallBaseLine, wallLine)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const movedStart = Math.abs(wallBaseLine.x1 - wallLine.x1) > EPSILON || Math.abs(wallBaseLine.y1 - wallLine.y1) > EPSILON
|
const movedStart = Math.abs(wallBaseLine.x1 - wallLine.x1) > EPSILON || Math.abs(wallBaseLine.y1 - wallLine.y1) > EPSILON
|
||||||
const movedEnd = Math.abs(wallBaseLine.x2 - wallLine.x2) > EPSILON || Math.abs(wallBaseLine.y2 - wallLine.y2) > EPSILON
|
const movedEnd = Math.abs(wallBaseLine.x2 - wallLine.x2) > EPSILON || Math.abs(wallBaseLine.y2 - wallLine.y2) > EPSILON
|
||||||
|
|
||||||
@ -854,10 +945,13 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
|||||||
} else {
|
} else {
|
||||||
getAddLine({ y: inLine.y2, x: inLine.x2 }, { y: bStartY, x: wallLine.x2 }, 'pink')
|
getAddLine({ y: inLine.y2, x: inLine.x2 }, { y: bStartY, x: wallLine.x2 }, 'pink')
|
||||||
}
|
}
|
||||||
|
getAddLine({ y: bStartY, x: wallLine.x2 }, { y: roofLine.y1, x: wallLine.x1 }, 'magenta')
|
||||||
|
getAddLine({ y: newLine.y1, x: newLine.x1 }, { y: newLine.y2, x: wallLine.x2 }, 'Gray')
|
||||||
|
findPoints.push({ y: aStartY, x: newPStart.x, position: 'left_out_start' })
|
||||||
|
}else{
|
||||||
|
newPStart.y = roofLine.y1
|
||||||
}
|
}
|
||||||
getAddLine({ y: bStartY, x: wallLine.x2 }, { y: roofLine.y1, x: wallLine.x1 }, 'magenta')
|
|
||||||
getAddLine({ y: newLine.y1, x: newLine.x1 }, { y: newLine.y2, x: wallLine.x2 }, 'Gray')
|
|
||||||
findPoints.push({ y: aStartY, x: newPStart.x, position: 'left_out_start' })
|
|
||||||
} else {
|
} else {
|
||||||
const cLineY = Big(wallBaseLine.x1).minus(wallLine.x1).abs().toNumber()
|
const cLineY = Big(wallBaseLine.x1).minus(wallLine.x1).abs().toNumber()
|
||||||
newPStart.y = Big(newPStart.y).minus(cLineY).toNumber()
|
newPStart.y = Big(newPStart.y).minus(cLineY).toNumber()
|
||||||
@ -909,10 +1003,13 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
|||||||
} else {
|
} else {
|
||||||
getAddLine({ y: inLine.y1, x: inLine.x1 }, { y: bStartY, x: wallLine.x1 }, 'pink')
|
getAddLine({ y: inLine.y1, x: inLine.x1 }, { y: bStartY, x: wallLine.x1 }, 'pink')
|
||||||
}
|
}
|
||||||
|
getAddLine({ y: bStartY, x: wallLine.x1 }, { y: roofLine.y2, x: wallLine.x2 }, 'magenta')
|
||||||
|
getAddLine({ y: newLine.y2, x: newLine.x2 }, { y: newLine.y1, x: wallLine.x1 }, 'Gray')
|
||||||
|
findPoints.push({ y: aStartY, x: newPEnd.x, position: 'left_out_end' })
|
||||||
|
}else{
|
||||||
|
newPEnd.y = roofLine.y2
|
||||||
}
|
}
|
||||||
getAddLine({ y: bStartY, x: wallLine.x1 }, { y: roofLine.y2, x: wallLine.x2 }, 'magenta')
|
|
||||||
getAddLine({ y: newLine.y2, x: newLine.x2 }, { y: newLine.y1, x: wallLine.x1 }, 'Gray')
|
|
||||||
findPoints.push({ y: aStartY, x: newPEnd.x, position: 'left_out_end' })
|
|
||||||
} else {
|
} else {
|
||||||
const cLineY = Big(wallBaseLine.x2).minus(wallLine.x2).abs().toNumber()
|
const cLineY = Big(wallBaseLine.x2).minus(wallLine.x2).abs().toNumber()
|
||||||
newPEnd.y = Big(newPEnd.y).plus(cLineY).toNumber()
|
newPEnd.y = Big(newPEnd.y).plus(cLineY).toNumber()
|
||||||
@ -1024,10 +1121,13 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
|||||||
} else {
|
} else {
|
||||||
getAddLine({ y: inLine.y1, x: inLine.x1 }, { y: bStartY, x: wallLine.x2 }, 'pink')
|
getAddLine({ y: inLine.y1, x: inLine.x1 }, { y: bStartY, x: wallLine.x2 }, 'pink')
|
||||||
}
|
}
|
||||||
|
getAddLine({ y: bStartY, x: wallLine.x2 }, { y: roofLine.y1, x: wallLine.x1 }, 'magenta')
|
||||||
|
getAddLine({ y: newLine.y1, x: newLine.x1 }, { y: newLine.y2, x: wallLine.x2 }, 'Gray')
|
||||||
|
findPoints.push({ y: aStartY, x: newPEnd.x, position: 'right_out_start' })
|
||||||
|
}else{
|
||||||
|
newPStart.y = roofLine.y1
|
||||||
}
|
}
|
||||||
getAddLine({ y: bStartY, x: wallLine.x2 }, { y: roofLine.y1, x: wallLine.x1 }, 'magenta')
|
|
||||||
getAddLine({ y: newLine.y1, x: newLine.x1 }, { y: newLine.y2, x: wallLine.x2 }, 'Gray')
|
|
||||||
findPoints.push({ y: aStartY, x: newPEnd.x, position: 'right_out_start' })
|
|
||||||
} else {
|
} else {
|
||||||
const cLineY = Big(wallBaseLine.x1).minus(wallLine.x1).abs().toNumber()
|
const cLineY = Big(wallBaseLine.x1).minus(wallLine.x1).abs().toNumber()
|
||||||
newPStart.y = Big(newPStart.y).plus(cLineY).toNumber()
|
newPStart.y = Big(newPStart.y).plus(cLineY).toNumber()
|
||||||
@ -1213,10 +1313,13 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
|||||||
} else {
|
} else {
|
||||||
getAddLine({ x: inLine.x1, y: inLine.y1 }, { x: bStartX, y: wallLine.y1 }, 'pink')
|
getAddLine({ x: inLine.x1, y: inLine.y1 }, { x: bStartX, y: wallLine.y1 }, 'pink')
|
||||||
}
|
}
|
||||||
|
getAddLine({ x: bStartX, y: wallLine.y1 }, { x: roofLine.x1, y: wallLine.y1 }, 'magenta')
|
||||||
|
getAddLine({ x: newLine.x1, y: newLine.y1 }, { x: newLine.x1, y: wallLine.y1 }, 'Gray')
|
||||||
|
findPoints.push({ x: aStartX, y: newPEnd.y, position: 'top_out_start' })
|
||||||
|
}else{ //라인머지
|
||||||
|
newPStart.x = roofLine.x1
|
||||||
}
|
}
|
||||||
getAddLine({ x: bStartX, y: wallLine.y1 }, { x: roofLine.x1, y: wallLine.y1 }, 'magenta')
|
|
||||||
getAddLine({ x: newLine.x1, y: newLine.y1 }, { x: newLine.x1, y: wallLine.y1 }, 'Gray')
|
|
||||||
findPoints.push({ x: aStartX, y: newPEnd.y, position: 'top_out_start' })
|
|
||||||
} else {
|
} else {
|
||||||
const cLineX = Big(wallBaseLine.y1).minus(wallLine.y1).abs().toNumber()
|
const cLineX = Big(wallBaseLine.y1).minus(wallLine.y1).abs().toNumber()
|
||||||
newPStart.x = Big(newPStart.x).plus(cLineX).toNumber()
|
newPStart.x = Big(newPStart.x).plus(cLineX).toNumber()
|
||||||
@ -1265,10 +1368,13 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
|||||||
} else {
|
} else {
|
||||||
getAddLine({ x: inLine.x1, y: inLine.y1 }, { x: bStartX, y: wallLine.y1 }, 'pink')
|
getAddLine({ x: inLine.x1, y: inLine.y1 }, { x: bStartX, y: wallLine.y1 }, 'pink')
|
||||||
}
|
}
|
||||||
|
getAddLine({ x: bStartX, y: wallLine.y1 }, { x: roofLine.x2, y: wallLine.y2 }, 'magenta')
|
||||||
|
getAddLine({ x: newLine.x2, y: newLine.y2 }, { x: newLine.x1, y: wallLine.y1 }, 'Gray')
|
||||||
|
findPoints.push({ x: aStartX, y: newPEnd.y, position: 'top_out_end' })
|
||||||
|
}else{
|
||||||
|
newPEnd.x = roofLine.x2
|
||||||
}
|
}
|
||||||
getAddLine({ x: bStartX, y: wallLine.y1 }, { x: roofLine.x2, y: wallLine.y2 }, 'magenta')
|
|
||||||
getAddLine({ x: newLine.x2, y: newLine.y2 }, { x: newLine.x1, y: wallLine.y1 }, 'Gray')
|
|
||||||
findPoints.push({ x: aStartX, y: newPEnd.y, position: 'top_out_end' })
|
|
||||||
} else {
|
} else {
|
||||||
const cLineX = Big(wallLine.y2).minus(wallBaseLine.y2).abs().toNumber()
|
const cLineX = Big(wallLine.y2).minus(wallBaseLine.y2).abs().toNumber()
|
||||||
newPEnd.x = Big(newPEnd.x).minus(cLineX).toNumber()
|
newPEnd.x = Big(newPEnd.x).minus(cLineX).toNumber()
|
||||||
@ -1375,10 +1481,13 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
|||||||
} else {
|
} else {
|
||||||
getAddLine({ x: inLine.x1, y: inLine.y1 }, { x: bStartX, y: wallLine.y1 }, 'pink')
|
getAddLine({ x: inLine.x1, y: inLine.y1 }, { x: bStartX, y: wallLine.y1 }, 'pink')
|
||||||
}
|
}
|
||||||
|
getAddLine({ x: bStartX, y: wallLine.y1 }, { x: roofLine.x1, y: wallLine.y1 }, 'magenta')
|
||||||
|
getAddLine({ x: newLine.x1, y: newLine.y1 }, { x: newLine.x1, y: wallLine.y1 }, 'Gray')
|
||||||
|
findPoints.push({ x: aStartX, y: newPEnd.y, position: 'bottom_out_start' })
|
||||||
|
}else {
|
||||||
|
newPStart.x = roofLine.x1
|
||||||
}
|
}
|
||||||
getAddLine({ x: bStartX, y: wallLine.y1 }, { x: roofLine.x1, y: wallLine.y1 }, 'magenta')
|
|
||||||
getAddLine({ x: newLine.x1, y: newLine.y1 }, { x: newLine.x1, y: wallLine.y1 }, 'Gray')
|
|
||||||
findPoints.push({ x: aStartX, y: newPEnd.y, position: 'bottom_out_start' })
|
|
||||||
} else {
|
} else {
|
||||||
const cLineX = Big(wallBaseLine.y1).minus(wallLine.y1).abs().toNumber()
|
const cLineX = Big(wallBaseLine.y1).minus(wallLine.y1).abs().toNumber()
|
||||||
newPStart.x = Big(newPStart.x).minus(cLineX).toNumber()
|
newPStart.x = Big(newPStart.x).minus(cLineX).toNumber()
|
||||||
@ -1429,10 +1538,13 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
|||||||
} else {
|
} else {
|
||||||
getAddLine({ x: inLine.x1, y: inLine.y1 }, { x: bStartX, y: wallLine.y1 }, 'pink')
|
getAddLine({ x: inLine.x1, y: inLine.y1 }, { x: bStartX, y: wallLine.y1 }, 'pink')
|
||||||
}
|
}
|
||||||
|
getAddLine({ x: bStartX, y: wallLine.y1 }, { x: roofLine.x2, y: wallLine.y2 }, 'magenta')
|
||||||
|
getAddLine({ x: newLine.x2, y: newLine.y2 }, { x: newLine.x1, y: wallLine.y1 }, 'Gray')
|
||||||
|
findPoints.push({ x: aStartX, y: newPEnd.y, position: 'bottom_out_end' })
|
||||||
|
}else{
|
||||||
|
newPEnd.x = roofLine.x2
|
||||||
}
|
}
|
||||||
getAddLine({ x: bStartX, y: wallLine.y1 }, { x: roofLine.x2, y: wallLine.y2 }, 'magenta')
|
|
||||||
getAddLine({ x: newLine.x2, y: newLine.y2 }, { x: newLine.x1, y: wallLine.y1 }, 'Gray')
|
|
||||||
findPoints.push({ x: aStartX, y: newPEnd.y, position: 'bottom_out_end' })
|
|
||||||
} else {
|
} else {
|
||||||
const cLineX = Big(wallBaseLine.y2).minus(wallLine.y2).abs().toNumber()
|
const cLineX = Big(wallBaseLine.y2).minus(wallLine.y2).abs().toNumber()
|
||||||
newPEnd.x = Big(newPEnd.x).plus(cLineX).toNumber()
|
newPEnd.x = Big(newPEnd.x).plus(cLineX).toNumber()
|
||||||
@ -3424,58 +3536,78 @@ function getTurnDirection(p1, p2, p3) {
|
|||||||
function isValleyVertex(targetPoint, connectedLine, allLines, isStartVertex) {
|
function isValleyVertex(targetPoint, connectedLine, allLines, isStartVertex) {
|
||||||
const tolerance = 0.1;
|
const tolerance = 0.1;
|
||||||
|
|
||||||
// 1. 연결된 '다른' 라인을 찾습니다.
|
const connectedLineData = {
|
||||||
// isStartVertex가 true면 : 이 점으로 '들어오는' 라인(Previous Line)을 찾아야 함
|
x1: connectedLine.x1 ?? connectedLine.get?.('x1'),
|
||||||
// isStartVertex가 false면 : 이 점에서 '나가는' 라인(Next Line)을 찾아야 함
|
y1: connectedLine.y1 ?? connectedLine.get?.('y1'),
|
||||||
|
x2: connectedLine.x2 ?? connectedLine.get?.('x2'),
|
||||||
|
y2: connectedLine.y2 ?? connectedLine.get?.('y2'),
|
||||||
|
startPoint: connectedLine.startPoint,
|
||||||
|
endPoint: connectedLine.endPoint
|
||||||
|
};
|
||||||
|
|
||||||
let neighborLine = null;
|
let neighborLine = null;
|
||||||
|
|
||||||
if (isStartVertex) {
|
if (isStartVertex) {
|
||||||
// targetPoint가 Start이므로, 어떤 라인의 End가 targetPoint와 같아야 함 (Previous Line)
|
neighborLine = allLines.find(l => {
|
||||||
neighborLine = allLines.find(l =>
|
if (l === connectedLine) return false;
|
||||||
l !== connectedLine &&
|
const lx1 = l.x1 ?? l.get?.('x1');
|
||||||
isSamePoint(l.endPoint || {x:l.x2, y:l.y2}, targetPoint, tolerance)
|
const ly1 = l.y1 ?? l.get?.('y1');
|
||||||
);
|
const lx2 = l.x2 ?? l.get?.('x2');
|
||||||
|
const ly2 = l.y2 ?? l.get?.('y2');
|
||||||
|
const end = l.endPoint || { x: lx2, y: ly2 };
|
||||||
|
return isSamePoint(end, targetPoint, tolerance);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// targetPoint가 End이므로, 어떤 라인의 Start가 targetPoint와 같아야 함 (Next Line)
|
neighborLine = allLines.find(l => {
|
||||||
neighborLine = allLines.find(l =>
|
if (l === connectedLine) return false;
|
||||||
l !== connectedLine &&
|
const lx1 = l.x1 ?? l.get?.('x1');
|
||||||
isSamePoint(l.startPoint || {x:l.x1, y:l.y1}, targetPoint, tolerance)
|
const ly1 = l.y1 ?? l.get?.('y1');
|
||||||
);
|
const lx2 = l.x2 ?? l.get?.('x2');
|
||||||
|
const ly2 = l.y2 ?? l.get?.('y2');
|
||||||
|
const start = l.startPoint || { x: lx1, y: ly1 };
|
||||||
|
return isSamePoint(start, targetPoint, tolerance);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 연결된 라인을 못 찾았거나 끊겨있으면 판단 불가 (일단 false)
|
|
||||||
if (!neighborLine) return false;
|
if (!neighborLine) return false;
|
||||||
|
|
||||||
// 2. 세 점을 구성하여 회전 방향(Turn) 계산
|
const nlx1 = neighborLine.x1 ?? neighborLine.get?.('x1');
|
||||||
// 순서: PrevLine.Start -> [TargetVertex] -> NextLine.End
|
const nly1 = neighborLine.y1 ?? neighborLine.get?.('y1');
|
||||||
|
const nlx2 = neighborLine.x2 ?? neighborLine.get?.('x2');
|
||||||
|
const nly2 = neighborLine.y2 ?? neighborLine.get?.('y2');
|
||||||
|
|
||||||
|
const clx1 = connectedLineData.x1;
|
||||||
|
const cly1 = connectedLineData.y1;
|
||||||
|
const clx2 = connectedLineData.x2;
|
||||||
|
const cly2 = connectedLineData.y2;
|
||||||
|
|
||||||
let p1, p2, p3;
|
let p1, p2, p3;
|
||||||
|
|
||||||
if (isStartVertex) {
|
if (isStartVertex) {
|
||||||
// neighbor(Prev) -> connected(Current)
|
p1 = neighborLine.startPoint || { x: nlx1, y: nly1 };
|
||||||
p1 = neighborLine.startPoint || {x: neighborLine.x1, y: neighborLine.y1};
|
p2 = targetPoint;
|
||||||
p2 = targetPoint; // 접점
|
p3 = connectedLineData.endPoint || { x: clx2, y: cly2 };
|
||||||
p3 = connectedLine.endPoint || {x: connectedLine.x2, y: connectedLine.y2};
|
|
||||||
} else {
|
} else {
|
||||||
// connected(Current) -> neighbor(Next)
|
p1 = connectedLineData.startPoint || { x: clx1, y: cly1 };
|
||||||
p1 = connectedLine.startPoint || {x: connectedLine.x1, y: connectedLine.y1};
|
p2 = targetPoint;
|
||||||
p2 = targetPoint; // 접점
|
p3 = neighborLine.endPoint || { x: nlx2, y: nly2 };
|
||||||
p3 = neighborLine.endPoint || {x: neighborLine.x2, y: neighborLine.y2};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 외적 계산 (Y축이 아래로 증가하는 캔버스 좌표계 + CCW 진행 기준)
|
|
||||||
// 값이 양수(+)면 오른쪽 턴 = 골짜기
|
|
||||||
const crossProduct = getTurnDirection(p1, p2, p3);
|
const crossProduct = getTurnDirection(p1, p2, p3);
|
||||||
|
console.log('crossProduct:', crossProduct);
|
||||||
return crossProduct > 0;
|
return crossProduct > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findInteriorPoint(line, polygonLines) {
|
function findInteriorPoint(line, polygonLines) {
|
||||||
const { x1, y1, x2, y2 } = line;
|
const x1 = line.x1 ?? line.get?.('x1');
|
||||||
|
const y1 = line.y1 ?? line.get?.('y1');
|
||||||
|
const x2 = line.x2 ?? line.get?.('x2');
|
||||||
|
const y2 = line.y2 ?? line.get?.('y2');
|
||||||
|
|
||||||
// line 객체 포맷 통일
|
// line 객체 포맷 통일 (함수 내부용)
|
||||||
const currentLine = {
|
const currentLine = {
|
||||||
...line,
|
...line,
|
||||||
|
x1, y1, x2, y2,
|
||||||
startPoint: { x: x1, y: y1 },
|
startPoint: { x: x1, y: y1 },
|
||||||
endPoint: { x: x2, y: y2 }
|
endPoint: { x: x2, y: y2 }
|
||||||
};
|
};
|
||||||
@ -3486,6 +3618,8 @@ function findInteriorPoint(line, polygonLines) {
|
|||||||
// 2. 끝점이 골짜기인지 확인
|
// 2. 끝점이 골짜기인지 확인
|
||||||
const endIsValley = isValleyVertex(currentLine.endPoint, currentLine, polygonLines, false);
|
const endIsValley = isValleyVertex(currentLine.endPoint, currentLine, polygonLines, false);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
start: startIsValley,
|
start: startIsValley,
|
||||||
end: endIsValley
|
end: endIsValley
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user