임시
This commit is contained in:
parent
ee0517a952
commit
89a6787aee
@ -29,6 +29,8 @@ import { QcastContext } from '@/app/QcastProvider'
|
||||
import { usePlan } from '@/hooks/usePlan'
|
||||
import { roofsState } from '@/store/roofAtom'
|
||||
import { useText } from '@/hooks/useText'
|
||||
import { processEaveHelpLines } from '@/util/skeleton-utils'
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
|
||||
export function useRoofAllocationSetting(id) {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
@ -404,6 +406,56 @@ export function useRoofAllocationSetting(id) {
|
||||
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
|
||||
roofBases.forEach((roofBase) => {
|
||||
try {
|
||||
|
||||
const roofEaveHelpLines = canvas.getObjects().filter(obj =>
|
||||
obj.name === 'eaveHelpLine' && obj.roofId === roofBase.id
|
||||
);
|
||||
|
||||
const mergedEaveLines = processEaveHelpLines(roofEaveHelpLines);
|
||||
// 기존 라인 제거
|
||||
roofEaveHelpLines.forEach(line => canvas.remove(line));
|
||||
|
||||
mergedEaveLines.forEach(line => {
|
||||
const newLine = new QLine([line.x1, line.y1, line.x2, line.y2], {
|
||||
// 필요한 속성들 유지
|
||||
parentId : roofBase.id,
|
||||
fontSize : 10,
|
||||
stroke : 'blue',
|
||||
strokeWidth: 4,
|
||||
name : 'eaveHelpLine',
|
||||
lineName : 'eaveHelpLine',
|
||||
selectable : true,
|
||||
visible : true,
|
||||
roofId : roofBase.id,
|
||||
attributes : {
|
||||
type: 'eaveHelpLine'
|
||||
}
|
||||
// 기타 속성들...
|
||||
});
|
||||
canvas.add(newLine);
|
||||
});
|
||||
|
||||
canvas.renderAll();
|
||||
|
||||
|
||||
if (roofBase.lines) {
|
||||
// Filter out any eaveHelpLines that are already in lines to avoid duplicates
|
||||
const existingEaveLineIds = new Set(roofBase.lines.map(line => line.id));
|
||||
const newEaveLines = mergedEaveLines.filter(line => !existingEaveLineIds.has(line.id));
|
||||
roofBase.lines = [...roofBase.lines, ...newEaveLines];
|
||||
} else {
|
||||
roofBase.lines = [...roofEaveHelpLines];
|
||||
}
|
||||
|
||||
|
||||
if (!roofBase.innerLines) {
|
||||
roofBase.innerLines = [];
|
||||
}
|
||||
|
||||
// Add only eaveHelpLines that belong to this roofBase
|
||||
// const baseEaveHelpLines = roofEaveHelpLines.filter(line => line.roofId === roofBase.id);
|
||||
// roofBase.innerLines = [...new Set([...roofBase.innerLines, ...baseEaveHelpLines])];
|
||||
|
||||
if (roofBase.separatePolygon.length > 0) {
|
||||
splitPolygonWithSeparate(roofBase.separatePolygon)
|
||||
} else {
|
||||
|
||||
@ -437,6 +437,55 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
||||
|
||||
const processedInnerEdges = new Set()
|
||||
|
||||
const textElements = {};
|
||||
|
||||
const coordinateText = (line) => {
|
||||
// Generate a stable ID for this line
|
||||
const lineKey = `${line.x1},${line.y1},${line.x2},${line.y2}`;
|
||||
|
||||
// Remove existing text elements for this line
|
||||
if (textElements[lineKey]) {
|
||||
textElements[lineKey].forEach(text => {
|
||||
if (canvas.getObjects().includes(text)) {
|
||||
canvas.remove(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Create start point text
|
||||
const startText = new fabric.Text(`(${Math.round(line.x1)}, ${Math.round(line.y1)})`, {
|
||||
left: line.x1 + 5,
|
||||
top: line.y1 - 20,
|
||||
fontSize: 10,
|
||||
fill: 'green',
|
||||
fontFamily: 'Arial',
|
||||
selectable: false,
|
||||
hasControls: false,
|
||||
hasBorders: false
|
||||
});
|
||||
|
||||
// Create end point text
|
||||
const endText = new fabric.Text(`(${Math.round(line.x2)}, ${Math.round(line.y2)})`, {
|
||||
left: line.x2 + 5,
|
||||
top: line.y2 - 20,
|
||||
fontSize: 10,
|
||||
fill: 'orange',
|
||||
fontFamily: 'Arial',
|
||||
selectable: false,
|
||||
hasControls: false,
|
||||
hasBorders: false
|
||||
});
|
||||
|
||||
// Add to canvas
|
||||
canvas.add(startText, endText);
|
||||
|
||||
// Store references
|
||||
textElements[lineKey] = [startText, endText];
|
||||
|
||||
// Bring lines to front
|
||||
canvas.bringToFront(startText);
|
||||
canvas.bringToFront(endText);
|
||||
};
|
||||
// 1. 모든 Edge를 순회하며 기본 스켈레톤 선(용마루)을 수집합니다.
|
||||
|
||||
skeleton.Edges.forEach((edgeResult, index) => {
|
||||
@ -556,10 +605,9 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
||||
lineName: (sktLine.attributes.isOuterEdge)?'roofLine': attributes.type,
|
||||
selectable:(!sktLine.attributes.isOuterEdge),
|
||||
visible: (!sktLine.attributes.isOuterEdge),
|
||||
lineNo: (sktLine.attributes.isOuterEdge)? skIndex:0,//그려지는 외곽라인의 순서를 찾아서...
|
||||
});
|
||||
|
||||
|
||||
coordinateText(skeletonLine)
|
||||
canvas.add(skeletonLine);
|
||||
skeletonLine.bringToFront();
|
||||
existingLines.add(lineKey); // 추가된 라인을 추적
|
||||
@ -588,22 +636,22 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
||||
canvas.renderAll();
|
||||
});
|
||||
|
||||
if(roof.moveUpDown??0 > 0) {
|
||||
|
||||
// 같은 라인이 없으므로 새 다각형 라인 생성
|
||||
//라인 편집
|
||||
// let i = 0
|
||||
const currentRoofLines = canvas.getObjects().filter((obj) => obj.lineName === 'roofLine' && obj.attributes.roofId === roofId)
|
||||
let roofLineRects = canvas.getObjects().filter((obj) => obj.name === 'roofLineRect' && obj.roofId === roofId)
|
||||
//라인 편집
|
||||
// let i = 0
|
||||
const currentRoofLines = canvas.getObjects().filter((obj) => obj.lineName === 'roofLine' && obj.attributes.roofId === roofId)
|
||||
let roofLineRects = canvas.getObjects().filter((obj) => obj.name === 'roofLineRect' && obj.roofId === roofId)
|
||||
|
||||
|
||||
|
||||
|
||||
roofLineRects.forEach((roofLineRect) => {
|
||||
canvas.remove(roofLineRect)
|
||||
canvas.renderAll()
|
||||
})
|
||||
|
||||
let helpLines = canvas.getObjects().filter((obj) => obj.lineName === 'helpLine' && obj.roofId === roofId)
|
||||
helpLines.forEach((helpLine) => {
|
||||
canvas.remove(roofLineRect)
|
||||
canvas.renderAll()
|
||||
})
|
||||
|
||||
let helpLines = canvas.getObjects().filter((obj) => obj.lineName === 'helpLine' && obj.roofId === roofId)
|
||||
helpLines.forEach((helpLine) => {
|
||||
canvas.remove(helpLine)
|
||||
canvas.renderAll()
|
||||
})
|
||||
@ -637,29 +685,81 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// function sortCurrentRoofLines(lines) {
|
||||
// return [...lines].sort((a, b) => {
|
||||
// const aX = a.x1 ?? a.get('x1')
|
||||
// const aY = a.y1 ?? a.get('y1')
|
||||
// const bX = b.x1 ?? b.get('x1')
|
||||
// const bY = b.y1 ?? b.get('y1')
|
||||
|
||||
|
||||
// if (aX !== bX) return aX - bX
|
||||
// return aY - bY
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// 각 라인 집합 정렬
|
||||
|
||||
// roofLines의 방향에 맞춰 currentRoofLines의 방향을 조정
|
||||
const alignLineDirection = (sourceLines, targetLines) => {
|
||||
return sourceLines.map(sourceLine => {
|
||||
// 가장 가까운 targetLine 찾기
|
||||
const nearestTarget = targetLines.reduce((nearest, targetLine) => {
|
||||
const sourceCenter = {
|
||||
x: (sourceLine.x1 + sourceLine.x2) / 2,
|
||||
y: (sourceLine.y1 + sourceLine.y2) / 2
|
||||
};
|
||||
const targetCenter = {
|
||||
x: (targetLine.x1 + targetLine.x2) / 2,
|
||||
y: (targetLine.y1 + targetLine.y2) / 2
|
||||
};
|
||||
const distance = Math.hypot(
|
||||
sourceCenter.x - targetCenter.x,
|
||||
sourceCenter.y - targetCenter.y
|
||||
);
|
||||
|
||||
return !nearest || distance < nearest.distance
|
||||
? { line: targetLine, distance }
|
||||
: nearest;
|
||||
}, null)?.line;
|
||||
|
||||
if (!nearestTarget) return sourceLine;
|
||||
|
||||
// 방향이 반대인지 확인 (벡터 내적을 사용)
|
||||
const sourceVec = {
|
||||
x: sourceLine.x2 - sourceLine.x1,
|
||||
y: sourceLine.y2 - sourceLine.y1
|
||||
};
|
||||
const targetVec = {
|
||||
x: nearestTarget.x2 - nearestTarget.x1,
|
||||
y: nearestTarget.y2 - nearestTarget.y1
|
||||
};
|
||||
|
||||
const dotProduct = sourceVec.x * targetVec.x + sourceVec.y * targetVec.y;
|
||||
|
||||
// 내적이 음수이면 방향이 반대이므로 뒤집기
|
||||
if (dotProduct < 0) {
|
||||
return {
|
||||
...sourceLine,
|
||||
x1: sourceLine.x2,
|
||||
y1: sourceLine.y2,
|
||||
x2: sourceLine.x1,
|
||||
y2: sourceLine.y1
|
||||
};
|
||||
}
|
||||
|
||||
return sourceLine;
|
||||
});
|
||||
};
|
||||
|
||||
const sortedWallLines = sortCurrentRoofLines(wall.lines);
|
||||
const sortedCurrentRoofLines = sortCurrentRoofLines(currentRoofLines);
|
||||
// roofLines의 방향에 맞춰 currentRoofLines 조정 후 정렬
|
||||
const alignedCurrentRoofLines = alignLineDirection(currentRoofLines, roofLines);
|
||||
const sortedCurrentRoofLines = sortCurrentRoofLines(alignedCurrentRoofLines);
|
||||
const sortedRoofLines = sortCurrentRoofLines(roofLines);
|
||||
const sortedWallBaseLines = sortCurrentRoofLines(wall.baseLines);
|
||||
|
||||
|
||||
|
||||
|
||||
//wall.lines 는 기본 벽 라인
|
||||
//wall.baseLine은 움직인라인
|
||||
const movedLines = []
|
||||
@ -672,6 +772,23 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
||||
const moveLine = sortedWallBaseLines[index]
|
||||
const wallBaseLine = sortedWallBaseLines[index]
|
||||
|
||||
console.log('=== Line Coordinates ===');
|
||||
console.table({
|
||||
'Point' : ['X', 'Y'],
|
||||
'roofLine' : [roofLine.x1, roofLine.y1],
|
||||
'currentRoofLine': [currentRoofLine.x1, currentRoofLine.y1],
|
||||
'moveLine' : [moveLine.x1, moveLine.y1],
|
||||
'wallBaseLine' : [wallBaseLine.x1, wallBaseLine.y1]
|
||||
});
|
||||
console.log('End Points:');
|
||||
console.table({
|
||||
'Point' : ['X', 'Y'],
|
||||
'roofLine' : [roofLine.x2, roofLine.y2],
|
||||
'currentRoofLine': [currentRoofLine.x2, currentRoofLine.y2],
|
||||
'moveLine' : [moveLine.x2, moveLine.y2],
|
||||
'wallBaseLine' : [wallBaseLine.x2, wallBaseLine.y2]
|
||||
});
|
||||
|
||||
const origin = moveLine.attributes?.originPoint
|
||||
if (!origin) return
|
||||
|
||||
@ -698,184 +815,160 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
|
||||
fontSize : roof.fontSize,
|
||||
stroke : stroke,
|
||||
strokeWidth: 4,
|
||||
name : 'helpLine',
|
||||
lineName : 'helpLine',
|
||||
name : 'eaveHelpLine',
|
||||
lineName : 'eaveHelpLine',
|
||||
selectable : true,
|
||||
visible : true,
|
||||
roofId : roofId,
|
||||
attributes : {
|
||||
type: 'helpLine'
|
||||
type: 'eaveHelpLine'
|
||||
}
|
||||
});
|
||||
|
||||
const coordinateText = new fabric.Text(`(${Math.round(line.x1)}, ${Math.round(line.y1)})`, {
|
||||
left: line.x1 + 5, // 좌표점에서 약간 오른쪽으로 이동
|
||||
top: line.y1 - 20, // 좌표점에서 약간 위로 이동
|
||||
fontSize: 13,
|
||||
fill: 'red',
|
||||
fontFamily: 'Arial',
|
||||
selectable: true,
|
||||
lockMovementX: false,
|
||||
lockMovementY: false,
|
||||
lockRotation: true,
|
||||
lockScalingX: true,
|
||||
lockScalingY: true,
|
||||
name: 'lengthText'
|
||||
})
|
||||
|
||||
canvas?.add(coordinateText)
|
||||
|
||||
coordinateText(line)
|
||||
canvas.add(line)
|
||||
canvas.renderAll();
|
||||
return line
|
||||
}
|
||||
|
||||
//두 포인트가 변경된 라인인
|
||||
if (fullyMoved) {
|
||||
//반시계방향향
|
||||
newPStart = {x:roofLine.x1, y:roofLine.y1}
|
||||
newPEnd = {x:roofLine.x2, y:roofLine.y2}
|
||||
if (fullyMoved) {
|
||||
//반시계방향향
|
||||
newPStart = { x: roofLine.x1, y: roofLine.y1 }
|
||||
newPEnd = { x: roofLine.x2, y: roofLine.y2 }
|
||||
|
||||
console.log("moveFully:::::::::::::", wallBaseLine, newPStart, newPEnd)
|
||||
console.log("moveFully:::::::::::::", wallBaseLine, newPStart, newPEnd)
|
||||
|
||||
if(getOrientation(roofLine) === 'vertical'){
|
||||
if (getOrientation(roofLine) === 'vertical') {
|
||||
|
||||
if(newPEnd.y <= wallBaseLine.y2 && wallBaseLine.y2 <= newPStart.y && newPStart.y <= wallBaseLine.y1){
|
||||
newPStart.y = wallBaseLine.y1;
|
||||
getAddLine({x:newPEnd.x, y:wallBaseLine.y1}, {x: wallBaseLine.x1, y:wallBaseLine.y1 })
|
||||
} else if(wallBaseLine.y2 <= newPEnd.y && newPEnd.y <= wallBaseLine.y1 && wallBaseLine.y1 <= newPStart.y){
|
||||
newPEnd.y = wallBaseLine.y2;
|
||||
getAddLine({x:newPEnd.x, y:wallBaseLine.y2}, {x: wallBaseLine.x2, y:wallBaseLine.y2 })
|
||||
} else if(newPStart.y <= wallBaseLine.y1 && wallBaseLine.y1 <= newPEnd.y && newPEnd.y <= wallBaseLine.y2){
|
||||
newPEnd.y = wallBaseLine.y2;
|
||||
getAddLine({x:newPEnd.x, y:wallBaseLine.y2}, {x: wallBaseLine.x2, y:wallBaseLine.y2 })
|
||||
} else if(wallBaseLine.y1 <= newPStart.y && newPStart.y <= wallBaseLine.y2 && wallBaseLine.y2 <= newPEnd.y){
|
||||
if (newPEnd.y <= wallBaseLine.y2 && wallBaseLine.y2 <= newPStart.y && newPStart.y <= wallBaseLine.y1) {
|
||||
newPStart.y = wallBaseLine.y1;
|
||||
getAddLine({x:newPEnd.x, y:wallBaseLine.y1}, {x: wallBaseLine.x1, y:wallBaseLine.y1 })
|
||||
} else if(wallBaseLine.y2 <= newPEnd.y && newPStart.y <= wallBaseLine.y1 ) { // 위가운데
|
||||
newPEnd.y = wallBaseLine.y2;
|
||||
getAddLine({x:newPEnd.x, y:wallBaseLine.y2}, {x: wallBaseLine.x2, y:wallBaseLine.y2 })
|
||||
newPStart.y = wallBaseLine.y1;
|
||||
getAddLine({x:newPEnd.x, y:wallBaseLine.y1}, {x: wallBaseLine.x1, y:wallBaseLine.y1 })
|
||||
} else if(wallBaseLine.y1 <= newPStart.y && newPEnd.y <= wallBaseLine.y2 ) { // 아래가운데
|
||||
newPEnd.y = wallBaseLine.y1;
|
||||
getAddLine({x:newPEnd.x, y:wallBaseLine.y1}, {x: wallBaseLine.x1, y:wallBaseLine.y1 })
|
||||
newPStart.y = wallBaseLine.y2;
|
||||
getAddLine({x:newPStart.x, y:wallBaseLine.y2}, {x: wallBaseLine.x2, y:wallBaseLine.y2 })
|
||||
}
|
||||
|
||||
|
||||
}else if(getOrientation(roofLine) === 'horizontal') {
|
||||
getAddLine({ x: newPEnd.x, y: wallBaseLine.y1 }, { x: wallBaseLine.x1, y: wallBaseLine.y1 })
|
||||
} else if (wallBaseLine.y2 <= newPEnd.y && newPEnd.y <= wallBaseLine.y1 && wallBaseLine.y1 <= newPStart.y) {
|
||||
newPEnd.y = wallBaseLine.y2;
|
||||
getAddLine({ x: newPEnd.x, y: wallBaseLine.y2 }, { x: wallBaseLine.x2, y: wallBaseLine.y2 })
|
||||
} else if (newPStart.y <= wallBaseLine.y1 && wallBaseLine.y1 <= newPEnd.y && newPEnd.y <= wallBaseLine.y2) {
|
||||
newPEnd.y = wallBaseLine.y2;
|
||||
getAddLine({ x: newPEnd.x, y: wallBaseLine.y2 }, { x: wallBaseLine.x2, y: wallBaseLine.y2 })
|
||||
} else if (wallBaseLine.y1 <= newPStart.y && newPStart.y <= wallBaseLine.y2 && wallBaseLine.y2 <= newPEnd.y) {
|
||||
newPStart.y = wallBaseLine.y1;
|
||||
getAddLine({ x: newPEnd.x, y: wallBaseLine.y1 }, { x: wallBaseLine.x1, y: wallBaseLine.y1 })
|
||||
} else if (wallBaseLine.y2 <= newPEnd.y && newPStart.y <= wallBaseLine.y1) { // 위가운데
|
||||
newPEnd.y = wallBaseLine.y2;
|
||||
getAddLine({ x: newPEnd.x, y: wallBaseLine.y2 }, { x: wallBaseLine.x2, y: wallBaseLine.y2 })
|
||||
newPStart.y = wallBaseLine.y1;
|
||||
getAddLine({ x: newPEnd.x, y: wallBaseLine.y1 }, { x: wallBaseLine.x1, y: wallBaseLine.y1 })
|
||||
} else if (wallBaseLine.y1 <= newPStart.y && newPEnd.y <= wallBaseLine.y2) { // 아래가운데
|
||||
newPEnd.y = wallBaseLine.y1;
|
||||
getAddLine({ x: newPEnd.x, y: wallBaseLine.y1 }, { x: wallBaseLine.x1, y: wallBaseLine.y1 })
|
||||
newPStart.y = wallBaseLine.y2;
|
||||
getAddLine({ x: newPStart.x, y: wallBaseLine.y2 }, { x: wallBaseLine.x2, y: wallBaseLine.y2 })
|
||||
}
|
||||
|
||||
|
||||
if(newPEnd.x <= wallBaseLine.x2 && wallBaseLine.x2 <= newPStart.x && newPStart.x <= wallBaseLine.x1){ //위 왼쪽
|
||||
newPStart.x = wallBaseLine.x1;
|
||||
getAddLine({x:wallBaseLine.x1, y:newPEnd.y}, {x:wallBaseLine.x1, y: wallBaseLine.y1})
|
||||
} else if(wallBaseLine.x2 <= newPEnd.x && newPEnd.x <= wallBaseLine.x1 && wallBaseLine.x1 <= newPStart.x){ //아래오르쪽
|
||||
newPEnd.x = wallBaseLine.x2;
|
||||
getAddLine({x:wallBaseLine.x2, y:newPEnd.y}, {x:wallBaseLine.x2, y: wallBaseLine.y2})
|
||||
} else if (getOrientation(roofLine) === 'horizontal') {
|
||||
|
||||
} else if(newPStart.x <= wallBaseLine.x1 && wallBaseLine.x1 <= newPEnd.x && newPEnd.x <= wallBaseLine.x2){ //위 오른쪽
|
||||
newPEnd.x = wallBaseLine.x2;
|
||||
getAddLine({x:wallBaseLine.x2, y:newPEnd.y}, {x:wallBaseLine.x2, y: wallBaseLine.y2})
|
||||
|
||||
} else if(wallBaseLine.x1 <= newPStart.x && newPStart.x <= wallBaseLine.x2 && wallBaseLine.x2 <= newPEnd.x){ //아래 왼쪽
|
||||
if (newPEnd.x <= wallBaseLine.x2 && wallBaseLine.x2 <= newPStart.x && newPStart.x <= wallBaseLine.x1) { //위 왼쪽
|
||||
newPStart.x = wallBaseLine.x1;
|
||||
getAddLine({x:wallBaseLine.x1, y:newPEnd.y}, {x:wallBaseLine.x1, y: wallBaseLine.y1})
|
||||
getAddLine({ x: wallBaseLine.x1, y: newPEnd.y }, { x: wallBaseLine.x1, y: wallBaseLine.y1 })
|
||||
} else if (wallBaseLine.x2 <= newPEnd.x && newPEnd.x <= wallBaseLine.x1 && wallBaseLine.x1 <= newPStart.x) { //아래오르쪽
|
||||
newPEnd.x = wallBaseLine.x2;
|
||||
getAddLine({ x: wallBaseLine.x2, y: newPEnd.y }, { x: wallBaseLine.x2, y: wallBaseLine.y2 })
|
||||
|
||||
} else if(wallBaseLine.x2 <= newPEnd.x && newPEnd.x <= newPStart.x && newPStart.x <= wallBaseLine.x1 ) { // 위가운데
|
||||
} else if (newPStart.x <= wallBaseLine.x1 && wallBaseLine.x1 <= newPEnd.x && newPEnd.x <= wallBaseLine.x2) { //위 오른쪽
|
||||
newPEnd.x = wallBaseLine.x2;
|
||||
getAddLine({ x: wallBaseLine.x2, y: newPEnd.y }, { x: wallBaseLine.x2, y: wallBaseLine.y2 })
|
||||
|
||||
newPEnd.x = wallBaseLine.x2;
|
||||
getAddLine({x:wallBaseLine.x2, y:newPEnd.y}, {x:wallBaseLine.x2, y: wallBaseLine.y2})
|
||||
newPStart.x = wallBaseLine.x1;
|
||||
getAddLine({x:wallBaseLine.x1, y:newPEnd.y}, {x:wallBaseLine.x1, y: wallBaseLine.y1})
|
||||
} else if (wallBaseLine.x1 <= newPStart.x && newPStart.x <= wallBaseLine.x2 && wallBaseLine.x2 <= newPEnd.x) { //아래 왼쪽
|
||||
newPStart.x = wallBaseLine.x1;
|
||||
getAddLine({ x: wallBaseLine.x1, y: newPEnd.y }, { x: wallBaseLine.x1, y: wallBaseLine.y1 })
|
||||
|
||||
} else if(wallBaseLine.x1 <= newPStart.x &&newPStart.x <= newPEnd.x&&newPEnd.x <= wallBaseLine.x2 ) { // 아래가운데
|
||||
newPEnd.x = wallBaseLine.x1;
|
||||
getAddLine({x:wallBaseLine.x1, y:newPEnd.y}, {x:wallBaseLine.x1, y: wallBaseLine.y1})
|
||||
newPStart.x = wallBaseLine.x2;
|
||||
getAddLine({x:wallBaseLine.x2, y:newPEnd.y}, {x:wallBaseLine.x2, y: wallBaseLine.y2})
|
||||
} else if (wallBaseLine.x2 <= newPEnd.x && newPEnd.x <= newPStart.x && newPStart.x <= wallBaseLine.x1) { // 위가운데
|
||||
|
||||
newPEnd.x = wallBaseLine.x2;
|
||||
getAddLine({ x: wallBaseLine.x2, y: newPEnd.y }, { x: wallBaseLine.x2, y: wallBaseLine.y2 })
|
||||
newPStart.x = wallBaseLine.x1;
|
||||
getAddLine({ x: wallBaseLine.x1, y: newPEnd.y }, { x: wallBaseLine.x1, y: wallBaseLine.y1 })
|
||||
|
||||
} else if (wallBaseLine.x1 <= newPStart.x && newPStart.x <= newPEnd.x && newPEnd.x <= wallBaseLine.x2) { // 아래가운데
|
||||
newPEnd.x = wallBaseLine.x1;
|
||||
getAddLine({ x: wallBaseLine.x1, y: newPEnd.y }, { x: wallBaseLine.x1, y: wallBaseLine.y1 })
|
||||
newPStart.x = wallBaseLine.x2;
|
||||
getAddLine({ x: wallBaseLine.x2, y: newPEnd.y }, { x: wallBaseLine.x2, y: wallBaseLine.y2 })
|
||||
}
|
||||
}
|
||||
}
|
||||
getAddLine(newPStart, newPEnd)
|
||||
movedLines.push({ index, newPStart, newPEnd })
|
||||
|
||||
}
|
||||
|
||||
else if(movedStart) { //end 변경경
|
||||
|
||||
|
||||
newPStart = {x:roofLine.x1, y:roofLine.y1}
|
||||
getAddLine(newPStart, newPEnd, 'red')
|
||||
movedLines.push({ index, newPStart, newPEnd })
|
||||
|
||||
if(getOrientation(roofLine) === 'vertical'){
|
||||
} else if (movedStart) { //end 변경경
|
||||
|
||||
let isCross = false
|
||||
if(Math.abs(currentRoofLine.x2 - roofLine.x1) < 0.1 || Math.abs(currentRoofLine.x1 - roofLine.x2) < 0.1){
|
||||
|
||||
newPStart = { x: roofLine.x1, y: roofLine.y1 }
|
||||
|
||||
if (getOrientation(roofLine) === 'vertical') {
|
||||
|
||||
let isCross = false
|
||||
if (Math.abs(currentRoofLine.x2 - roofLine.x1) < 0.1 || Math.abs(currentRoofLine.x1 - roofLine.x2) < 0.1) {
|
||||
isCross = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
newPEnd = {x:roofLine.x1, y:(isCross)? currentRoofLine.y2:origin.y1}
|
||||
newPEnd = { x: roofLine.x1, y: (isCross) ? currentRoofLine.y1 : origin.y1 }
|
||||
|
||||
}else if(getOrientation(roofLine) === 'horizontal') {
|
||||
} else if (getOrientation(roofLine) === 'horizontal') {
|
||||
|
||||
let isCross = false
|
||||
if(Math.abs(currentRoofLine.y1 - roofLine.y2) < 0.1 || Math.abs(currentRoofLine.y2 - roofLine.y1) < 0.1){
|
||||
let isCross = false
|
||||
if (Math.abs(currentRoofLine.y1 - roofLine.y2) < 0.1 || Math.abs(currentRoofLine.y2 - roofLine.y1) < 0.1) {
|
||||
isCross = true;
|
||||
}
|
||||
|
||||
newPEnd = { x: (isCross) ? currentRoofLine.x1 : origin.x1, y: roofLine.y1 } //수직라인 접점까지지
|
||||
|
||||
}
|
||||
|
||||
newPEnd = {x:(isCross)? currentRoofLine.x2:origin.x1, y:roofLine.y1} //수직라인 접점까지지
|
||||
|
||||
movedLines.push({ index, newPStart, newPEnd })
|
||||
console.log("moveStart:::::::::::::", origin, newPStart, newPEnd)
|
||||
getAddLine(newPStart, newPEnd, 'red')
|
||||
|
||||
|
||||
} else if (movedEnd) { //start변경
|
||||
|
||||
//반시계방향
|
||||
newPStart = { x: roofLine.x2, y: roofLine.y2 }
|
||||
|
||||
if (getOrientation(roofLine) === 'vertical') {
|
||||
|
||||
let isCross = false
|
||||
if (Math.abs(currentRoofLine.x2 - roofLine.x1) < 0.1 || Math.abs(currentRoofLine.x1 - roofLine.x2) < 0.1) {
|
||||
isCross = true;
|
||||
}
|
||||
newPEnd = { x: roofLine.x2, y: (isCross) ? currentRoofLine.y2 : origin.y2 } //수직라인 접점까지지
|
||||
|
||||
} else if (getOrientation(roofLine) === 'horizontal') {
|
||||
|
||||
let isCross = false
|
||||
if (Math.abs(currentRoofLine.y2 - roofLine.y1) < 0.1 || Math.abs(currentRoofLine.y1 - roofLine.y2) < 0.1) {
|
||||
isCross = true;
|
||||
}
|
||||
|
||||
newPEnd = { x: (isCross) ? currentRoofLine.x2 : origin.x2, y: roofLine.y2 } //수직라인 접점까지지
|
||||
|
||||
}
|
||||
console.log("movedEnd:::::::::::::", origin, newPStart, newPEnd)
|
||||
getAddLine(newPStart, newPEnd, 'orange')
|
||||
movedLines.push({ index, newPStart, newPEnd })
|
||||
|
||||
}
|
||||
|
||||
movedLines.push({ index, newPStart, newPEnd })
|
||||
console.log("moveStart:::::::::::::", origin, newPStart, newPEnd)
|
||||
getAddLine(newPStart, newPEnd)
|
||||
canvas.renderAll()
|
||||
|
||||
|
||||
}else if(movedEnd) { //start변경
|
||||
|
||||
//반시계방향
|
||||
newPStart = {x:roofLine.x2, y:roofLine.y2}
|
||||
|
||||
if(getOrientation(roofLine) === 'vertical'){
|
||||
|
||||
let isCross = false
|
||||
if(Math.abs(currentRoofLine.x2 - roofLine.x1) < 0.1 || Math.abs(currentRoofLine.x1 - roofLine.x2) < 0.1){
|
||||
isCross = true;
|
||||
}
|
||||
newPEnd = {x:roofLine.x2, y:(isCross)? currentRoofLine.y1:origin.y2} //수직라인 접점까지지
|
||||
|
||||
}else if(getOrientation(roofLine) === 'horizontal') {
|
||||
|
||||
let isCross = false
|
||||
if(Math.abs(currentRoofLine.y2 - roofLine.y1) < 0.1 || Math.abs(currentRoofLine.y1 - roofLine.y2) < 0.1){
|
||||
isCross = true;
|
||||
}
|
||||
|
||||
newPEnd = {x:(isCross)? currentRoofLine.x1:origin.x2, y:roofLine.y2} //수직라인 접점까지지
|
||||
|
||||
}
|
||||
console.log("movedEnd:::::::::::::", origin, newPStart, newPEnd)
|
||||
getAddLine(newPStart, newPEnd)
|
||||
movedLines.push({ index, newPStart, newPEnd })
|
||||
|
||||
}
|
||||
|
||||
canvas.renderAll()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
//polygon 만들기
|
||||
console.log("innerLines:::::", innerLines)
|
||||
console.log("movedLines", movedLines)
|
||||
|
||||
console.log("innerLines:::::", innerLines)
|
||||
console.log("movedLines", movedLines)
|
||||
}
|
||||
// --- 사용 예시 ---
|
||||
// const polygons = findConnectedLines(movedLines, innerLines, canvas, roofId, roof);
|
||||
// console.log("polygon", polygons);
|
||||
@ -886,18 +979,18 @@ console.log("movedLines", movedLines)
|
||||
let p1,p2,p3, p4
|
||||
let idx = 0;
|
||||
let isMoveLine = false;
|
||||
|
||||
|
||||
if (wallLine.startPoint.x !== wallLine.x1) wallLine.startPoint.x = wallLine.x1
|
||||
if (wallLine.startPoint.y !== wallLine.y1) wallLine.startPoint.y = wallLine.y1
|
||||
if (wallLine.endPoint.x !== wallLine.x2) wallLine.endPoint.x = wallLine.x2
|
||||
if (wallLine.endPoint.y !== wallLine.y2) wallLine.endPoint.y = wallLine.y2
|
||||
|
||||
|
||||
const wallLineStartPoint = {x:wallLine.x1, y:wallLine.y1}
|
||||
const wallLineEndPoint = {x:wallLine.x2, y:wallLine.y2}
|
||||
const moveLine = wall.baseLines[index] //이동한 wall 존재여부 (초기 wall line = base line)
|
||||
|
||||
if(index === 2){
|
||||
|
||||
|
||||
}
|
||||
|
||||
// // 사용자가 라인을 드래그하기 시작할 때
|
||||
@ -910,13 +1003,13 @@ console.log("movedLines", movedLines)
|
||||
// .map((line, index) => ({ index, line }))
|
||||
// .filter(({ line }) => line.attributes.isUserMoved)
|
||||
|
||||
|
||||
|
||||
// Then in your code:
|
||||
|
||||
if (!moveLine?.attributes?.originPoint) return
|
||||
|
||||
const { originPoint } = moveLine.attributes
|
||||
const moved =
|
||||
const moved =
|
||||
(Math.abs(moveLine.x1 - originPoint.x1) > 0.1 ||
|
||||
Math.abs(moveLine.y1 - originPoint.y1) > 0.1 )||(
|
||||
Math.abs(moveLine.x2 - originPoint.x2) > 0.1 ||
|
||||
@ -938,7 +1031,7 @@ console.log("movedLines", movedLines)
|
||||
|
||||
const getPolygonOrientation = baseLines => {
|
||||
if (!baseLines?.length) return 0
|
||||
|
||||
|
||||
const area2 = baseLines.reduce((sum, line) => {
|
||||
const x1 = line.get('x1')
|
||||
const y1 = line.get('y1')
|
||||
@ -946,10 +1039,10 @@ console.log("movedLines", movedLines)
|
||||
const y2 = line.get('y2')
|
||||
return sum + (x2 - x1) * (y2 + y1) // shoelace 변형
|
||||
}, 0)
|
||||
|
||||
|
||||
return Math.sign(area2) // +1: CCW, -1: CW, 0: 불명
|
||||
}
|
||||
|
||||
|
||||
const lineOrientation = (line, polygonOrientation) => {
|
||||
const x1 = line.get('x1')
|
||||
const y1 = line.get('y1')
|
||||
@ -978,7 +1071,7 @@ console.log("movedLines", movedLines)
|
||||
})
|
||||
// 기존 로직도 이어서 실행
|
||||
console.log("moveLine", movedLines)
|
||||
|
||||
|
||||
|
||||
movedLines.forEach(({ index, moveLine, wallLine }) => {
|
||||
console.log(`사용자가 움직인 선 index: ${index}, wallLineId: ${wallLine.id}`)
|
||||
@ -996,7 +1089,7 @@ console.log("movedLines", movedLines)
|
||||
same(a.x2, a.y2, b.x2, b.y2)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
const angleBetween = a => b => {
|
||||
const va = { x: a.x2 - a.x1, y: a.y2 - a.y1 }
|
||||
const vb = { x: b.x2 - b.x1, y: b.y2 - b.y1 }
|
||||
@ -1004,7 +1097,7 @@ console.log("movedLines", movedLines)
|
||||
const mag = Math.hypot(va.x, va.y) * Math.hypot(vb.x, vb.y)
|
||||
return Math.acos(Math.min(Math.max(dot / mag, -1), 1)) * 180 / Math.PI
|
||||
}
|
||||
|
||||
|
||||
const rightAngles = []
|
||||
movedLines.forEach((a, i) => {
|
||||
movedLines.slice(i + 1).forEach(b => {
|
||||
@ -1024,14 +1117,14 @@ console.log("movedLines", movedLines)
|
||||
canvas.add(testLine)
|
||||
canvas.renderAll()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
// movedLines => [{ line: moveLineObj, index }, ...] : 이동된 것만 담김
|
||||
|
||||
if (moved) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -3987,3 +4080,49 @@ function findConnectedLines(aLines, bLines, canvas, roofId, roof) {
|
||||
return results;
|
||||
}
|
||||
|
||||
export const processEaveHelpLines = (lines) => {
|
||||
if (!lines || lines.length === 0) return [];
|
||||
|
||||
// 수직/수평 라인 분류
|
||||
const verticalLines = lines.filter(line => line.x1 === line.x2);
|
||||
const horizontalLines = lines.filter(line => line.y1 === line.y2);
|
||||
|
||||
// 라인 정렬 및 병합
|
||||
const mergedVertical = mergeLines(verticalLines, 'vertical');
|
||||
const mergedHorizontal = mergeLines(horizontalLines, 'horizontal');
|
||||
|
||||
return [...mergedVertical, ...mergedHorizontal];
|
||||
};
|
||||
|
||||
const mergeLines = (lines, direction) => {
|
||||
if (lines.length < 2) return lines;
|
||||
|
||||
// 방향에 따라 정렬
|
||||
lines.sort((a, b) => {
|
||||
const aPos = direction === 'vertical' ? a.y1 : a.x1;
|
||||
const bPos = direction === 'vertical' ? b.y1 : b.x1;
|
||||
return aPos - bPos;
|
||||
});
|
||||
|
||||
const merged = [];
|
||||
let current = { ...lines[0] };
|
||||
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
const isConnected = direction === 'vertical'
|
||||
? current.y2 >= line.y1 - 1
|
||||
: current.x2 >= line.x1 - 1;
|
||||
|
||||
if (isConnected) {
|
||||
// 라인 병합
|
||||
current.y2 = Math.max(current.y2, line.y2);
|
||||
current.x2 = direction === 'vertical' ? current.x1 : current.x2;
|
||||
} else {
|
||||
merged.push(current);
|
||||
current = { ...line };
|
||||
}
|
||||
}
|
||||
merged.push(current);
|
||||
return merged;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user