@@ -45,7 +34,7 @@ export default function FlowLine({ FLOW_LINE_REF }) {
@@ -68,12 +57,7 @@ export default function FlowLine({ FLOW_LINE_REF }) {
diff --git a/src/components/main/ChangePasswordPop.jsx b/src/components/main/ChangePasswordPop.jsx
index 188a3fe7..2af060e7 100644
--- a/src/components/main/ChangePasswordPop.jsx
+++ b/src/components/main/ChangePasswordPop.jsx
@@ -72,21 +72,25 @@ export default function ChangePasswordPop(props) {
chgPwd: _password1,
}
- await patch({ url: '/api/login/v1.0/user/change-password', data: param }).then((res) => {
- if (res.result.code === 200) {
- if (res.result.resultCode === 'S') {
- alert(getMessage('main.popup.login.success'))
- setSessionState({ ...sessionState, pwdInitYn: 'Y' })
- //메인으로 이동
- props.setChagePasswordPopOpen(false)
- router.push('/')
+ await patch({ url: '/api/login/v1.0/user/change-password', data: param })
+ .then((res) => {
+ if (res?.result?.code === 200) {
+ if (res?.result?.resultCode === 'S') {
+ alert(getMessage('main.popup.login.success'))
+ //로그인 화면으로 이동해서 다시 로그인해야되서 setSessionState필요없음
+ // setSessionState({ ...sessionState, pwdInitYn: 'Y' })
+ props.setChagePasswordPopOpen(false)
+ router.push('/login')
+ } else {
+ alert(res?.result?.resultMsg)
+ }
} else {
- alert(res.result.resultMsg)
+ console.log('code not 200 error')
}
- } else {
- console.log('error')
- }
- })
+ })
+ .catch((error) => {
+ console.log('catch::::::::', error)
+ })
}
return (
diff --git a/src/hooks/roofcover/useMovementSetting.js b/src/hooks/roofcover/useMovementSetting.js
index 509c53f3..ced2e72b 100644
--- a/src/hooks/roofcover/useMovementSetting.js
+++ b/src/hooks/roofcover/useMovementSetting.js
@@ -4,8 +4,7 @@ import { usePopup } from '@/hooks/usePopup'
import { useMessage } from '@/hooks/useMessage'
import { useEffect, useRef, useState } from 'react'
import { useEvent } from '@/hooks/useEvent'
-import { POLYGON_TYPE } from '@/common/common'
-import { OUTER_LINE_TYPE } from '@/store/outerLineAtom'
+import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
//동선이동 형 올림 내림
export function useMovementSetting(id) {
@@ -28,8 +27,8 @@ export function useMovementSetting(id) {
const typeRef = useRef(type)
const FLOW_LINE_REF = {
- DOWN_LEFT_INPUT_REF: useRef(null),
- UP_RIGHT_INPUT_REF: useRef(null),
+ POINTER_INPUT_REF: useRef(null),
+ FILLED_INPUT_REF: useRef(null),
DOWN_LEFT_RADIO_REF: useRef(null),
UP_RIGHT_RADIO_REF: useRef(null),
}
@@ -42,37 +41,42 @@ export function useMovementSetting(id) {
}
useEffect(() => {
- removeFlowLine()
typeRef.current = type
- const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') // 기존 outerLine의 selectable true
- outerLines.forEach((line) => {
- line.set({ stroke: 'black' })
- line.set({ visible: false })
- })
canvas.getObjects().forEach((obj) => {
obj.set({ selectable: false })
})
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) // 기존 wallLine의 visible false
roofs.forEach((roof) => {
+ roof.set({ selectable: false })
+ roof.set({ strokeWidth: 1 })
+ roof.set({ stroke: '#000000' })
roof.innerLines.forEach((line) => {
line.bringToFront()
line.set({ selectable: false })
line.set({ strokeWidth: 1 })
+ line.set({ stroke: '#000000' })
+ })
+ roof.separatePolygon?.forEach((polygon) => {
+ polygon.bringToFront()
+ polygon.set({ selectable: false })
+ polygon.set({ strokeWidth: 1 })
+ polygon.set({ stroke: '#000000' })
})
})
if (type === TYPE.FLOW_LINE) {
roofs.forEach((roof) => {
roof.innerLines.forEach((line) => {
- line.bringToFront()
- line.set({ selectable: true })
- line.set({ strokeWidth: 4 })
+ if (line.name === LINE_TYPE.SUBLINE.RIDGE) {
+ line.bringToFront()
+ line.set({ selectable: true })
+ line.set({ strokeWidth: 4 })
+ line.set({ stroke: '#1083E3' })
+ }
})
})
} else if (type === TYPE.UP_DOWN) {
- const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') // 기존 outerLine의 selectable true
- outerLines.forEach((line) => {
- line.set({ stroke: 'black' })
- line.set({ visible: true })
+ const wallLine = canvas.getObjects().filter((obj) => obj.name === 'wallLine') // 기존 outerLine의 selectable true
+ wallLine.forEach((line) => {
line.bringToFront()
line.set({ selectable: true })
})
@@ -81,26 +85,48 @@ export function useMovementSetting(id) {
}, [type])
useEffect(() => {
- /*const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL) // 기존 wallLine의 visible false
- wallLines.forEach((line) => {
- line.set({ visible: false })
- })*/
-
canvas.renderAll()
addCanvasMouseEventListener('mouse:move', mouseMoveEvent)
addCanvasMouseEventListener('mouse:down', mouseDownEvent)
+
return () => {
initEvent()
- removeFlowLine()
+
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
wallLines.forEach((line) => {
line.set({ visible: true })
})
- const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') // 기존 outerLine의 selectable true
- outerLines.forEach((line) => {
- line.set({ stroke: 'black' })
- line.set({ visible: false })
+ const wallLine = canvas.getObjects().filter((obj) => obj.name === 'wallLine') // 기존 outerLine의 selectable true
+ wallLine.forEach((line) => {
+ let wallStroke, wallStrokeWidth
+ switch (line.attributes.type) {
+ case LINE_TYPE.WALLLINE.EAVES:
+ wallStroke = '#45CD7D'
+ wallStrokeWidth = 4
+ break
+ case LINE_TYPE.WALLLINE.HIPANDGABLE:
+ wallStroke = '#45CD7D'
+ wallStrokeWidth = 4
+ break
+ case LINE_TYPE.WALLLINE.GABLE:
+ wallStroke = '#3FBAE6'
+ wallStrokeWidth = 4
+ break
+ case LINE_TYPE.WALLLINE.JERKINHEAD:
+ wallStroke = '#3FBAE6'
+ wallStrokeWidth = 4
+ break
+ case LINE_TYPE.WALLLINE.SHED:
+ wallStroke = '#000000'
+ wallStrokeWidth = 4
+ break
+ case LINE_TYPE.WALLLINE.WALL:
+ wallStroke = '#000000'
+ wallStrokeWidth = 4
+ break
+ }
+ line.set({ selectable: false, stroke: wallStroke, strokeWidth: wallStrokeWidth })
})
canvas.renderAll()
@@ -108,19 +134,14 @@ export function useMovementSetting(id) {
}, [])
useEffect(() => {
- const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') // 기존 outerLine의 selectable true
- outerLines.forEach((line) => {
- line.set({ stroke: 'black' })
- })
selectedObject.current = null
-
if (!currentObject) {
return
}
clearRef()
selectedObject.current = currentObject
- if (currentObject.name === OUTER_LINE_TYPE.OUTER_LINE) {
+ if (currentObject.name === 'wallLine') {
currentObject.set({ stroke: '#EA10AC' })
currentObject.bringToFront()
}
@@ -129,34 +150,26 @@ export function useMovementSetting(id) {
const clearRef = () => {
if (type === TYPE.FLOW_LINE) {
- FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value = ''
- FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value = ''
- FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = false
+ FLOW_LINE_REF.FILLED_INPUT_REF.current.value = ''
+ FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = false
}
if (type === TYPE.UP_DOWN) {
UP_DOWN_REF.UP_INPUT_REF.current.value = ''
UP_DOWN_REF.DOWN_INPUT_REF.current.value = ''
- UP_DOWN_REF.UP_RADIO_REF.current.checked = false
+ UP_DOWN_REF.UP_RADIO_REF.current.checked = true
UP_DOWN_REF.DOWN_RADIO_REF.current.checked = false
}
}
const mouseDownEvent = (e) => {
if (typeRef.current === TYPE.FLOW_LINE) {
- flowLineDownEvent(e)
+ saveFlowLine(e)
} else {
updownDownEvent(e)
}
}
- const removeFlowLine = () => {
- const flowLine = canvas.getObjects().filter((obj) => obj.name === 'flowLine')
- flowLine.forEach((line) => {
- canvas.remove(line)
- })
- }
-
const mouseMoveEvent = (e) => {
if (typeRef.current === TYPE.FLOW_LINE) {
flowLineMoveEvent(e)
@@ -165,61 +178,92 @@ export function useMovementSetting(id) {
}
}
//동선 이동 마우스 클릭 이벤트
- const flowLineDownEvent = (e) => {
+ const saveFlowLine = (e) => {
const target = selectedObject.current
if (!target) {
return
}
- const direction = target.direction
-
- removeFlowLine()
-
let newPoint = []
- if (direction === 'left' || direction === 'right') {
- if (FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked) {
- newPoint = [
- target.x1,
- target.y1 + Number(FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value / 10),
- target.x2,
- target.y2 + Number(FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value / 10),
- ]
- } else {
- newPoint = [
- target.x1,
- target.y1 - Number(FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value / 10),
- target.x2,
- target.y2 - Number(FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value / 10),
- ]
- }
+ if (Math.sign(target.x1 - target.x2) !== 0) {
+ newPoint = [
+ target.x1,
+ target.y1 - Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
+ target.x2,
+ target.y2 - Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
+ ]
} else {
- if (FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked) {
- newPoint = [
- target.x1 - Number(FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value / 10),
- target.y1,
- target.x2 - Number(FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value / 10),
- target.y2,
- ]
- } else {
- newPoint = [
- target.x1 + Number(FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value / 10),
- target.y1,
- target.x2 + Number(FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value / 10),
- target.y2,
- ]
- }
+ newPoint = [
+ target.x1 + Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
+ target.y1,
+ target.x2 + Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
+ target.y2,
+ ]
}
- const cloned = new fabric.Line(newPoint, {
- stroke: 'red',
- strokeWidth: 4,
- name: 'flowLine',
- currentLine: target,
- })
+ clearRef()
+ const cloned = new fabric.Line(newPoint, {})
+ let currentObject = selectedObject.current
+ const currentX1 = currentObject.x1,
+ currentY1 = currentObject.y1,
+ currentX2 = currentObject.x2,
+ currentY2 = currentObject.y2
+
+ const roof = canvas.getObjects().find((obj) => obj.id === currentObject.attributes.roofId)
+ if (roof.separatePolygon.length > 0) {
+ const separatePolygon = roof.separatePolygon
+ separatePolygon
+ .filter((polygon) =>
+ polygon.points.some((point) => (point.x === currentX1 && point.y === currentY1) || (point.x === currentX2 && point.y === currentY2)),
+ )
+ .forEach((polygon) => {
+ const newPoints = polygon.points.map((point) => {
+ if (point.x === currentX1 && point.y === currentY1) {
+ return { x: newPoint[0], y: newPoint[1] }
+ } else if (point.x === currentX2 && point.y === currentY2) {
+ return { x: newPoint[2], y: newPoint[3] }
+ } else {
+ return point
+ }
+ })
+ polygon.set({ points: newPoints })
+ })
+ } else {
+ roof.innerLines
+ .filter((line) => currentObject !== line)
+ .filter(
+ (line) =>
+ (line.x1 === currentX1 && line.y1 === currentY1) ||
+ (line.x2 === currentX1 && line.y2 === currentY1) ||
+ (line.x1 === currentX2 && line.y1 === currentY2) ||
+ (line.x2 === currentX2 && line.y2 === currentY2),
+ )
+ .forEach((line) => {
+ console.log('line : ', line)
+ if (line.x1 === currentX1 && line.y1 === currentY1) {
+ line.set({ x1: newPoint[0], y1: newPoint[1] })
+ } else if (line.x2 === currentX1 && line.y2 === currentY1) {
+ line.set({ x2: newPoint[0], y2: newPoint[1] })
+ } else if (line.x1 === currentX2 && line.y1 === currentY2) {
+ line.set({ x1: newPoint[2], y1: newPoint[3] })
+ } else if (line.x2 === currentX2 && line.y2 === currentY2) {
+ line.set({ x2: newPoint[2], y2: newPoint[3] })
+ }
+ line.setCoords()
+ })
+ }
+
+ currentObject.set({ x1: cloned.x1, y1: cloned.y1, x2: cloned.x2, y2: cloned.y2 })
+ currentObject.setCoords()
+
+ console.log('currentObject : ', currentObject.x1, currentObject.y1, currentObject.x2, currentObject.y2)
- canvas.add(cloned)
canvas.renderAll()
canvas.discardActiveObject()
+
+ if (roof.separatePolygon.length > 0) {
+ console.log('roof.separatePolygon : ', roof.separatePolygon)
+ }
}
//형 올림내림 마우스 클릭 이벤트
@@ -231,35 +275,25 @@ export function useMovementSetting(id) {
if (!target) {
return
}
- const direction = target.direction
const { top: targetTop, left: targetLeft } = target
const currentX = canvas.getPointer(e.e).x
const currentY = Math.floor(canvas.getPointer(e.e).y)
- if (direction === 'left' || direction === 'right') {
+ if (Math.sign(target.x1 - target.x2) !== 0) {
if (targetTop > currentY) {
- console.log('targetTop > currentY')
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = true
- FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value = ''
-
- FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetTop - currentY)) / 10000).toFixed(5) * 100000)
+ FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(targetTop - currentY)) / 10000).toFixed(5) * 100000)
} else {
FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
- FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value = ''
-
- FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetTop - currentY)) / 10000).toFixed(5) * 100000)
+ FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(targetTop - currentY)) / 10000).toFixed(5) * 100000)
}
} else {
if (targetLeft > currentX) {
- FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
- FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value = ''
-
- FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetLeft - currentX)) / 10000).toFixed(5) * 100000)
- } else {
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = true
- FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value = ''
-
- FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetLeft - currentX)) / 10000).toFixed(5) * 100000)
+ FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(currentX - targetLeft)) / 10000).toFixed(5) * 100000)
+ } else {
+ FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
+ FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(currentX - targetLeft)) / 10000).toFixed(5) * 100000)
}
}
@@ -307,24 +341,7 @@ export function useMovementSetting(id) {
const handleSave = () => {
if (type === TYPE.FLOW_LINE) {
- const flowLine = canvas.getObjects().find((obj) => obj.name === 'flowLine')
-
- const currentLine = flowLine.currentLine
- if (!flowLine || !currentLine) {
- return
- }
-
- currentLine.set({
- x1: flowLine.x1,
- y1: flowLine.y1,
- x2: flowLine.x2,
- y2: flowLine.y2,
- })
- currentLine.startPoint = { x: flowLine.x1, y: flowLine.y1 }
- currentLine.endPoint = { x: flowLine.x2, y: flowLine.y2 }
-
- canvas.remove(flowLine)
- canvas.renderAll()
+ saveFlowLine()
} else {
// 형 올림내림
if (UP_DOWN_REF.UP_RADIO_REF.current.checked) {
diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js
index 6f6f3ad7..99819ad6 100644
--- a/src/hooks/useMode.js
+++ b/src/hooks/useMode.js
@@ -1806,7 +1806,8 @@ export function useMode() {
break
}
const wallLine = new fabric.Line([line.x1, line.y1, line.x2, line.y2], {
- attributes: { wallId: wall.id },
+ name: 'wallLine',
+ attributes: { wallId: wall.id, roofId: roof.id },
stroke: wallStroke,
strokeWidth: wallStrokeWidth,
selectable: false,
diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js
index 4f1e9178..b2253953 100644
--- a/src/util/qpolygon-utils.js
+++ b/src/util/qpolygon-utils.js
@@ -1,6 +1,6 @@
import { fabric } from 'fabric'
import { QLine } from '@/components/fabric/QLine'
-import { calculateIntersection, distanceBetweenPoints, findClosestPoint, getDegreeByChon, getDirectionByPoint } from '@/util/canvas-util'
+import { getDegreeByChon } from '@/util/canvas-util'
import { QPolygon } from '@/components/fabric/QPolygon'
import * as turf from '@turf/turf'
@@ -15,445 +15,6 @@ export const defineQPloygon = () => {
}
}
-export const drawHelpLineInHexagon = (polygon, pitch) => {
- const centerLines = drawCenterLines(polygon)
-
- let helpLines = []
-
- const interSectionPoints = []
- const tempInterSectionPoints = []
-
- const ridgeStartPoints = []
- const ridgeEndPoints = []
-
- let centerInterSectionPoints = []
-
- // polygon.lines = polygon.lines.sort((a, b) => a.length - b.length)
- polygon.wall.lines = getOneSideLines(polygon.wall)
-
- const maxLength = Math.max(...polygon.lines.map((line) => line.length))
-
- polygon.points.forEach((point, index) => {
- const wallPoint = polygon.wall.points[index]
-
- const angle = Math.atan2(wallPoint.y - point.y, wallPoint.x - point.x)
-
- const degree = fabric.util.radiansToDegrees(angle)
-
- const newX2 = Math.floor(point.x + maxLength * Math.cos(angle))
- const newY2 = Math.floor(point.y + maxLength * Math.sin(angle))
-
- const helpLine = new QLine([point.x, point.y, newX2, newY2], {
- fontSize: polygon.fontSize,
- stroke: 'green',
- startPoint: point,
- degree: degree,
- idx: index,
- })
-
- // polygon.canvas?.add(helpLine)
-
- helpLines.push(helpLine)
- })
-
- helpLines.forEach((line, index) => {
- for (let i = index + 1; i < helpLines.length; i++) {
- const nextLine = helpLines[i]
- if (!line.connectedPoint) {
- line.connectedPoint = null
- line.connectedPoints = []
- }
- if (!nextLine.connectedPoint) {
- nextLine.connectedPoint = null
- nextLine.connectedPoints = []
- }
-
- const interSectionPoint = calculateIntersection(line, nextLine)
-
- if (
- interSectionPoint &&
- polygon.inPolygon(interSectionPoint) &&
- polygon.wall.inPolygon(interSectionPoint) &&
- Math.abs(distanceBetweenPoints(line.startPoint, interSectionPoint) - distanceBetweenPoints(nextLine.startPoint, interSectionPoint)) < 2
- ) {
- const area = calculateTriangleArea(line.startPoint, nextLine.startPoint, interSectionPoint)
- const currentLineConnectedPoint = line.connectedPoint
- const nextLineConnectedPoint = nextLine.connectedPoint
-
- if (area <= 1) {
- return
- }
-
- if (currentLineConnectedPoint && currentLineConnectedPoint.area < area) {
- return
- }
-
- //startPoint는 line의 startPoint와 nextLine의 startPoint를 비교하여 x가 같은경우 y가 더 작은 값, y가 같은경우 x가 더 작은 값을 선택한다.
- const startPoint =
- line.startPoint.x === nextLine.startPoint.x
- ? line.startPoint.y < nextLine.startPoint.y
- ? line.startPoint
- : nextLine.startPoint
- : line.startPoint.x < nextLine.startPoint.x
- ? line.startPoint
- : nextLine.startPoint
-
- const endPoint =
- line.startPoint.x === nextLine.startPoint.x
- ? line.startPoint.y > nextLine.startPoint.y
- ? line.startPoint
- : nextLine.startPoint
- : line.startPoint.x > nextLine.startPoint.x
- ? line.startPoint
- : nextLine.startPoint
-
- line.connectedPoint = { interSectionPoint, area, startPoint, endPoint }
- line.connectedPoints.push({ interSectionPoint, area, startPoint, endPoint })
- nextLine.connectedPoint = { interSectionPoint, area, startPoint, endPoint }
- nextLine.connectedPoints.push({ interSectionPoint, area, startPoint, endPoint })
- }
- }
- })
-
- helpLines.forEach((line) => {
- if (line.connectedPoint) {
- tempInterSectionPoints.push(line.connectedPoint)
- }
- })
-
- // interSectionPoints에서 interSectionPoint가 중복인 값이 있는 경우만 선택한다.
- tempInterSectionPoints.forEach((point) => {
- // intersectionPoint가 중복인 경우
- const isDuplicated =
- tempInterSectionPoints.filter((p) => p.interSectionPoint.x === point.interSectionPoint.x && p.interSectionPoint.y === point.interSectionPoint.y)
- .length > 1
- if (isDuplicated) {
- interSectionPoints.push(point)
- }
- })
-
- // interSectionPoints에서 interSectionPoint 기준으로 중복을 제거한다.
- const uniqueInterSectionPoints = Array.from(
- new Set(interSectionPoints.map((point) => `${point.interSectionPoint.x},${point.interSectionPoint.y}`)),
- ).map((key) => {
- const { interSectionPoint, area, startPoint, endPoint } = interSectionPoints.find(
- (point) => `${point.interSectionPoint.x},${point.interSectionPoint.y}` === key,
- )
- return { interSectionPoint, area, startPoint, endPoint }
- })
-
- uniqueInterSectionPoints.forEach((point) => {
- ridgeStartPoints.push(point.interSectionPoint)
-
- const line = new QLine([point.startPoint.x, point.startPoint.y, point.interSectionPoint.x, point.interSectionPoint.y], {
- stroke: 'purple',
- fontSize: polygon.fontSize,
- name: 'hip',
- })
-
- const line2 = new QLine([point.endPoint.x, point.endPoint.y, point.interSectionPoint.x, point.interSectionPoint.y], {
- stroke: 'purple',
- fontSize: polygon.fontSize,
- name: 'hip',
- })
-
- line.startPoint = point.startPoint
- line.endPoint = point.interSectionPoint
-
- line2.startPoint = point.endPoint
- line2.endPoint = point.interSectionPoint
-
- polygon.hips.push(line)
- polygon.hips.push(line2)
-
- polygon.canvas.add(line)
- polygon.canvas.add(line2)
- })
-
- const removedIdx = []
-
- helpLines.forEach((line) => {
- const connectedPoints = line.connectedPoints
- connectedPoints.forEach((connectedPoint) => {
- uniqueInterSectionPoints.forEach((point) => {
- const interSectionPoint = point.interSectionPoint
-
- if (connectedPoint.interSectionPoint.x === interSectionPoint.x && connectedPoint.interSectionPoint.y === interSectionPoint.y) {
- removedIdx.push(line.idx)
- }
- })
- })
- })
-
- let notIntersectedLines = helpLines.filter((line) => !removedIdx.includes(line.idx))
-
- notIntersectedLines = notIntersectedLines.map((line) => {
- return { ...line, centerInterSectionPoints: [] }
- })
-
- notIntersectedLines.forEach((line) => {
- centerLines.forEach((centerLine) => {
- const interSectionPoint = calculateIntersection(line, centerLine)
-
- if (interSectionPoint && polygon.inPolygon(interSectionPoint) && polygon.wall.inPolygon(interSectionPoint)) {
- line.centerInterSectionPoints.push(interSectionPoint)
- interSectionPoint.lineIdx = line.idx
- centerInterSectionPoints.push(interSectionPoint)
- }
- })
- })
-
- // centerInterSectionPoints에서 ridgeStartPoints와 x가 같거나 y가 같은것중 가장 가까운 점들을 찾는다.
- ridgeStartPoints.forEach((point) => {
- const xPoints = centerInterSectionPoints.filter((centerPoint) => Math.abs(centerPoint.x - point.x) < 2)
-
- const yPoints = centerInterSectionPoints.filter((centerPoint) => Math.abs(centerPoint.y - point.y) < 2)
- let closestPoint
- if (xPoints.length === 0) {
- closestPoint = findClosestPoint(point, yPoints)
- } else if (yPoints.length === 0) {
- closestPoint = findClosestPoint(point, xPoints)
- }
-
- if (closestPoint) {
- const line = new QLine([point.x, point.y, closestPoint.x, closestPoint.y], {
- stroke: 'purple',
- fontSize: polygon.fontSize,
- name: 'ridge',
- direction: getDirectionByPoint(point, closestPoint),
- })
-
- line.startPoint = point
- line.endPoint = closestPoint
-
- polygon.ridges.push(line)
- polygon.canvas.add(line)
- ridgeEndPoints.push(closestPoint)
-
- notIntersectedLines = notIntersectedLines.filter((line) => line.idx !== closestPoint.lineIdx)
- }
- })
-
- centerInterSectionPoints = []
- notIntersectedLines.forEach((line) => {
- centerInterSectionPoints.push(...line.centerInterSectionPoints)
- })
-
- // ridgeEndPoints끼리 이어준다.
- const remainingPoints = [...ridgeEndPoints]
-
- // ridgeEndPoint에서 centerInterSectionPoints와 45도인 점을 찾아 이어준다.
-
- ridgeEndPoints.forEach((ridgePoint) => {
- const filteredCenterInterSectionPoints = centerInterSectionPoints.filter((centerPoint) => {
- const degree = calculateAngle(ridgePoint, centerPoint)
- return Math.abs(degree) === 45 || Math.abs(degree) === 135
- })[0]
-
- if (filteredCenterInterSectionPoints) {
- const line = new QLine([ridgePoint.x, ridgePoint.y, filteredCenterInterSectionPoints.x, filteredCenterInterSectionPoints.y], {
- stroke: 'purple',
- fontSize: polygon.fontSize,
- name: 'hip',
- })
-
- if (line.length === 0) {
- return
- }
-
- line.startPoint = ridgePoint
- line.endPoint = filteredCenterInterSectionPoints
-
- polygon.hips.push(line)
- polygon.canvas.add(line)
-
- ridgeStartPoints.push(filteredCenterInterSectionPoints)
-
- polygon.points.forEach((point) => {
- const degree = calculateAngle(ridgePoint, point)
-
- if (Math.abs(degree) % 45 < 1) {
- const line = new QLine([ridgePoint.x, ridgePoint.y, point.x, point.y], {
- stroke: 'purple',
- fontSize: polygon.fontSize,
- name: 'hip',
- })
-
- polygon.hips.push(line)
- polygon.canvas.add(line)
- }
- })
- }
- })
-
- // ridgeEndPoint끼리 연결한다.
- while (remainingPoints.length > 1) {
- const startPoint = remainingPoints.shift()
- const endPoint = remainingPoints.shift()
-
- if (!(startPoint.x === endPoint.x && startPoint.y === endPoint.y)) {
- const line = new QLine([startPoint.x, startPoint.y, endPoint.x, endPoint.y], {
- stroke: 'purple',
- fontSize: polygon.fontSize,
- name: 'connectRidge',
- })
-
- line.startPoint = startPoint
- line.endPoint = endPoint
-
- polygon.connectRidges.push(line)
-
- polygon.points.forEach((point) => {
- const degree = calculateAngle(startPoint, point)
-
- if (Math.abs(degree) === 45 || Math.abs(degree) === 135) {
- const line = new QLine([startPoint.x, startPoint.y, point.x, point.y], {
- stroke: 'purple',
- fontSize: polygon.fontSize,
- name: 'hip',
- })
-
- line.startPoint = startPoint
- line.endPoint = point
-
- polygon.hips.push(line)
- polygon.canvas.add(line)
- }
- })
-
- polygon.points.forEach((point) => {
- const degree = calculateAngle(endPoint, point)
-
- if (Math.abs(degree) === 45 || Math.abs(degree) === 135) {
- const line = new QLine([endPoint.x, endPoint.y, point.x, point.y], {
- stroke: 'purple',
- fontSize: polygon.fontSize,
- name: 'hip',
- })
-
- line.startPoint = endPoint
- line.endPoint = point
-
- polygon.hips.push(line)
- polygon.canvas.add(line)
- }
- })
-
- polygon.canvas.add(line)
- } else {
- polygon.points.forEach((point) => {
- const degree = calculateAngle(startPoint, point)
-
- if (Math.abs(degree) === 45 || Math.abs(degree) === 135) {
- const line = new QLine([startPoint.x, startPoint.y, point.x, point.y], {
- stroke: 'purple',
- fontSize: polygon.fontSize,
- name: 'hip',
- })
-
- line.startPoint = startPoint
- line.endPoint = point
-
- polygon.hips.push(line)
- polygon.canvas.add(line)
- }
- })
- }
- }
-}
-
-export const drawCenterLines = (polygon) => {
- const centerLines = []
-
- const oneSideLines = polygon.lines.map((line) => getOneSideLine(line))
-
- const horizontalLines = oneSideLines.filter((line) => line.direction === 'right')
- const verticalLines = oneSideLines.filter((line) => line.direction === 'bottom')
- // horizontalLines 를 y1 좌표 기준으로 정렬한다.
- horizontalLines.sort((a, b) => a.y1 - b.y1)
- // verticalLines 를 x1 좌표 기준으로 정렬한다.
- verticalLines.sort((a, b) => a.x1 - b.x1)
-
- let maxHorizontalLineLength = 0
- let maxVerticalLineLength = 0
- // 모든 가로선의 중심선을 긋는다.
- horizontalLines.forEach((line, index) => {
- const nextLine = horizontalLines[(index + 1) % horizontalLines.length]
-
- polygon.canvas.renderAll()
-
- const startCenterX = Math.min(line.x1, nextLine.x1)
- const startCenterY = (line.y1 + nextLine.y1) / 2
-
- const endCenterX = line.x2 > nextLine.x2 ? line.x2 : nextLine.x2
- const endCenterY = startCenterY
-
- const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], {
- fontSize: polygon.fontSize,
- stroke: 'red',
- strokeWidth: 1,
- direction: 'horizontal',
- })
-
- centerLines.push(centerLine)
- })
-
- // 모든 세로선의 중심선을 긋는다.
- verticalLines.forEach((line, index) => {
- const nextLine = verticalLines[(index + 1) % verticalLines.length]
-
- const startCenterX = (line.x1 + nextLine.x1) / 2
- const startCenterY = Math.min(line.y1, nextLine.y1)
-
- const endCenterX = startCenterX
- let endCenterY = line.y2 > nextLine.y2 ? line.y2 : nextLine.y2
-
- const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], {
- fontSize: polygon.fontSize,
- stroke: 'blue',
- strokeWidth: 1,
- direction: 'vertical',
- })
-
- centerLines.push(centerLine)
- })
-
- return centerLines
-}
-
-const getOneSideLines = (polygon) => {
- return [...polygon.lines].map((line) => {
- let newX1, newY1, newX2, newY2
- if (line.direction === 'top') {
- newX1 = line.x2
- newY1 = line.y2
- newX2 = line.x1
- newY2 = line.y1
-
- line.x1 = newX1
- line.y1 = newY1
- line.x2 = newX2
- line.y2 = newY2
- line.direction = 'bottom'
- line.startPoint = { x: newX1, y: newY1 }
- line.endPoint = { x: newX2, y: newY2 }
- } else if (line.direction === 'left') {
- newX1 = line.x2
- newY1 = line.y2
- newX2 = line.x1
- newY2 = line.y1
-
- line.x1 = newX1
- line.y1 = newY1
- line.x2 = newX2
- line.y2 = newY2
- line.direction = 'right'
- line.startPoint = { x: newX1, y: newY1 }
- line.endPoint = { x: newX2, y: newY2 }
- }
- return line
- })
-}
export const calculateAngle = (point1, point2) => {
const deltaX = point2.x - point1.x
const deltaY = point2.y - point1.y
@@ -461,267 +22,6 @@ export const calculateAngle = (point1, point2) => {
return angleInRadians * (180 / Math.PI)
}
-/**
- * 3개의 점을 이용해 직각 이등변 삼각형인지 확인
- * @param point1
- * @param point2
- * @param point3
- * @returns {boolean}
- */
-const isRightIsoscelesTriangle = (point1, point2, point3) => {
- const distance = (p1, p2) => Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2))
-
- const d1 = distance(point1, point2)
- const d2 = distance(point2, point3)
- const d3 = distance(point3, point1)
-
- const distances = [d1, d2, d3].sort((a, b) => a - b)
-
- // Check if the two smaller distances are equal and the largest distance is the hypotenuse
- return distances[0] === distances[1] && Math.abs(Math.pow(distances[0], 2) * 2 - Math.pow(distances[2], 2)) < 1
-}
-
-/**
- * 세개의 점으로 삼각형의 넓이를 구한다.
- * @param point1
- * @param point2
- * @param point3
- * @returns {number}
- */
-const calculateTriangleArea = (point1, point2, point3) => {
- const { x: x1, y: y1 } = point1
- const { x: x2, y: y2 } = point2
- const { x: x3, y: y3 } = point3
-
- return Math.abs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2
-}
-
-// polygon을 나눈다.
-export const dividePolygon = (polygon) => {
- let hips = polygon.hips
- const ridges = polygon.ridges.map((ridge) => getOneSideLine(ridge))
- const connectRidges = polygon.connectRidges
- const polygonLines = polygon.lines
-
- hips.forEach((hip) => {
- // hips의 startPoint와 endPoint를 polygon의 points와 비교하여 같은 점이 endPoint일 경우 startPoint로 변경한다.
- const startPoint = polygon.points.find((point) => point.x === hip.endPoint.x && point.y === hip.endPoint.y)
- if (startPoint) {
- const temp = hip.startPoint
- hip.startPoint = hip.endPoint
- hip.endPoint = temp
- }
- })
- hips = [...hips, ...connectRidges]
-
- polygonLines.forEach((line, index) => {
- let ridge
-
- const startPoint = line.startPoint
- const endPoint = line.endPoint
- let polygonPoints = []
-
- polygonPoints.push(startPoint)
-
- polygonPoints.push(endPoint)
-
- const startHip = hips.find((hip) => hip.startPoint.x === startPoint.x && hip.startPoint.y === startPoint.y)
- const endHip = hips.find((hip) => hip.startPoint.x === endPoint.x && hip.startPoint.y === endPoint.y)
-
- if (!startHip || !endHip) {
- return
- }
-
- if (startHip && endHip && startHip.endPoint.x === endHip.endPoint.x && startHip.endPoint.y === endHip.endPoint.y) {
- polygonPoints.push(startHip.endPoint)
-
- const newPolygon = new QPolygon(polygonPoints, {
- fontSize: polygon.fontSize,
- parentId: polygon.id,
- name: 'roof',
- selectable: false,
- stroke: 'black',
- fill: 'transparent',
- strokeWidth: 3,
- })
-
- polygon.canvas.add(newPolygon)
- return
- }
-
- let connectedRidge
- const restRidgeConnection = connectRidges[0]
-
- if (!restRidgeConnection || restRidgeConnection.length === 0) {
- connectedRidge = ridges.find(
- (ridge) =>
- (ridge.startPoint.x === startHip.endPoint.x &&
- ridge.startPoint.y === startHip.endPoint.y &&
- ridge.endPoint.x === endHip.endPoint.x &&
- ridge.endPoint.y === endHip.endPoint.y) ||
- (ridge.startPoint.x === endHip.endPoint.x &&
- ridge.startPoint.y === endHip.endPoint.y &&
- ridge.endPoint.x === startHip.endPoint.x &&
- ridge.endPoint.y === startHip.endPoint.y),
- )
- } else {
- connectedRidge = ridges.find(
- (ridge) =>
- (ridge.startPoint.x === startHip.endPoint.x && ridge.startPoint.y === startHip.endPoint.y) ||
- (ridge.endPoint.x === startHip.endPoint.x && ridge.endPoint.y === startHip.endPoint.y),
- )
- }
-
- const hipStartPoint = startHip.endPoint
- const hipEndPoint = endHip.endPoint
-
- if (connectedRidge.startPoint.x === hipStartPoint.x && connectedRidge.startPoint.y === hipStartPoint.y) {
- if (connectedRidge.endPoint.x === hipEndPoint.x && connectedRidge.endPoint.y === hipEndPoint.y) {
- polygonPoints.push(connectedRidge.endPoint)
- polygonPoints.push(connectedRidge.startPoint)
-
- const newPolygon = new QPolygon(polygonPoints, {
- fontSize: polygon.fontSize,
- parentId: polygon.id,
- name: 'roof',
- selectable: false,
- stroke: 'black',
- fill: 'transparent',
- strokeWidth: 3,
- })
-
- polygon.canvas.add(newPolygon)
- return
- }
- } else if (connectedRidge.endPoint.x === hipStartPoint.x && connectedRidge.endPoint.y === hipStartPoint.y) {
- if (connectedRidge.startPoint.x === hipEndPoint.x && connectedRidge.startPoint.y === hipEndPoint.y) {
- polygonPoints.push(connectedRidge.startPoint)
- polygonPoints.push(connectedRidge.endPoint)
-
- const newPolygon = new QPolygon(polygonPoints, {
- fontSize: polygon.fontSize,
- parentId: polygon.id,
- name: 'roof',
- selectable: false,
- stroke: 'black',
- fill: 'transparent',
- strokeWidth: 3,
- sort: true,
- })
-
- polygon.canvas.add(newPolygon)
- return
- }
- }
-
- // 지붕이 꺾여있는 경우
-
- if (
- (restRidgeConnection.startPoint.x === startHip.endPoint.x && restRidgeConnection.startPoint.y === startHip.endPoint.y) ||
- (restRidgeConnection.endPoint.x === startHip.endPoint.x && restRidgeConnection.endPoint.y === startHip.endPoint.y)
- ) {
- polygonPoints = [startPoint, startHip.endPoint]
- let lastPoint
-
- if (restRidgeConnection.startPoint.x === startHip.endPoint.x && restRidgeConnection.startPoint.y === startHip.endPoint.y) {
- lastPoint = restRidgeConnection.endPoint
- polygonPoints.push(restRidgeConnection.endPoint)
- } else {
- lastPoint = restRidgeConnection.startPoint
- polygonPoints.push(restRidgeConnection.startPoint)
- }
-
- connectedRidge = ridges.find(
- (ridge) =>
- (ridge.startPoint.x === lastPoint.x && ridge.startPoint.y === lastPoint.y) ||
- (ridge.endPoint.x === lastPoint.x && ridge.endPoint.y === lastPoint.y),
- )
-
- if (connectedRidge.startPoint.x === lastPoint.x && connectedRidge.startPoint.y === lastPoint.y) {
- polygonPoints.push(connectedRidge.endPoint)
- } else {
- polygonPoints.push(connectedRidge.startPoint)
- }
-
- polygonPoints.push(endPoint)
- } else {
- polygonPoints = [endPoint, endHip.endPoint]
- let lastPoint
-
- if (restRidgeConnection.startPoint.x === endHip.endPoint.x && restRidgeConnection.startPoint.y === endHip.endPoint.y) {
- lastPoint = restRidgeConnection.endPoint
- polygonPoints.push(restRidgeConnection.endPoint)
- } else {
- lastPoint = restRidgeConnection.startPoint
- polygonPoints.push(restRidgeConnection.startPoint)
- }
-
- connectedRidge = ridges.find(
- (ridge) =>
- (ridge.startPoint.x === lastPoint.x && ridge.startPoint.y === lastPoint.y) ||
- (ridge.endPoint.x === lastPoint.x && ridge.endPoint.y === lastPoint.y),
- )
-
- if (connectedRidge.startPoint.x === startHip.endPoint.x && connectedRidge.startPoint.y === startHip.endPoint.y) {
- lastPoint = connectedRidge.startPoint
- polygonPoints.push(connectedRidge.startPoint)
- } else {
- lastPoint = connectedRidge.endPoint
- polygonPoints.push(connectedRidge.endPoint)
- }
-
- polygonPoints.push(startPoint)
- }
-
- const newPolygon = new QPolygon(polygonPoints, {
- fontSize: polygon.fontSize,
- parentId: polygon.id,
- name: 'roof',
- selectable: false,
- stroke: 'black',
- fill: 'transparent',
- strokeWidth: 3,
- })
-
- polygon.canvas.add(newPolygon)
- })
-}
-
-const getOneSideLine = (line) => {
- // left, top 방향의 line은 right, bottom 방향의 line으로 변경한다.
- const newLine = { ...line }
- let newX1, newY1, newX2, newY2
- if (newLine.direction === 'top') {
- newX1 = newLine.x2
- newY1 = newLine.y2
- newX2 = newLine.x1
- newY2 = newLine.y1
-
- newLine.x1 = newX1
- newLine.y1 = newY1
- newLine.x2 = newX2
- newLine.y2 = newY2
- newLine.direction = 'bottom'
- newLine.startPoint = { x: newX1, y: newY1 }
- newLine.endPoint = { x: newX2, y: newY2 }
- } else if (line.direction === 'left') {
- newX1 = newLine.x2
- newY1 = newLine.y2
- newX2 = newLine.x1
- newY2 = newLine.y1
-
- newLine.x1 = newX1
- newLine.y1 = newY1
- newLine.x2 = newX2
- newLine.y2 = newY2
- newLine.direction = 'right'
- newLine.startPoint = { x: newX1, y: newY1 }
- newLine.endPoint = { x: newX2, y: newY2 }
- }
-
- return newLine
-}
-
function inwardEdgeNormal(vertex1, vertex2) {
// Assuming that polygon vertices are in clockwise order
const dx = vertex2.x - vertex1.x
@@ -735,7 +35,7 @@ function inwardEdgeNormal(vertex1, vertex2) {
}
function outwardEdgeNormal(vertex1, vertex2) {
- var n = inwardEdgeNormal(vertex1, vertex2)
+ const n = inwardEdgeNormal(vertex1, vertex2)
return {
x: -n.x,
@@ -786,14 +86,12 @@ function createPolygon(vertices) {
}
}
-// based on http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/, edgeA => "line a", edgeB => "line b"
-
function edgesIntersection(edgeA, edgeB) {
const den =
(edgeB.vertex2.y - edgeB.vertex1.y) * (edgeA.vertex2.x - edgeA.vertex1.x) -
(edgeB.vertex2.x - edgeB.vertex1.x) * (edgeA.vertex2.y - edgeA.vertex1.y)
- if (den == 0) {
+ if (den === 0) {
return null // lines are parallel or coincident
}
@@ -818,8 +116,8 @@ function edgesIntersection(edgeA, edgeB) {
}
function appendArc(arcSegments, vertices, center, radius, startVertex, endVertex, isPaddingBoundary) {
- var startAngle = Math.atan2(startVertex.y - center.y, startVertex.x - center.x)
- var endAngle = Math.atan2(endVertex.y - center.y, endVertex.x - center.x)
+ let startAngle = Math.atan2(startVertex.y - center.y, startVertex.x - center.x)
+ let endAngle = Math.atan2(endVertex.y - center.y, endVertex.x - center.x)
if (startAngle < 0) {
startAngle += TWO_PI
@@ -959,218 +257,6 @@ export default function offsetPolygon(vertices, offset) {
}
}
-/*export const splitPolygonWithLines = (polygon) => {
- const roofs = []
- const allLines = [...polygon.innerLines]
-
- const polygonLines = polygon.lines
- const innerLines = polygon.innerLines
-
- allLines.forEach((line) => {
- line.startPoint = { x: line.x1, y: line.y1 }
- line.endPoint = { x: line.x2, y: line.y2 }
- })
-
- // allLines에 x1,y1,x2,y2를 비교해서 중복되는 값을 제거한다.
- allLines.forEach((line, index) => {
- const startPoint = line.startPoint
- const endPoint = line.endPoint
-
- allLines.forEach((line2, index2) => {
- if (index !== index2) {
- if (
- (isSamePoint(startPoint, line2.startPoint) && isSamePoint(endPoint, line2.endPoint)) ||
- (isSamePoint(endPoint, line2.startPoint) && isSamePoint(startPoint, line2.endPoint))
- ) {
- allLines.splice(index2, 1)
- }
- }
- })
- })
-
- /!**
- * 좌표 테스트용
- *!/
- /!*allLines.forEach((line) => {
- const text = new fabric.Text(`(${line.startPoint.x},${line.startPoint.y})`, {
- left: line.startPoint.x,
- top: line.startPoint.y,
- fontSize: 15,
- })
-
- polygon.canvas.add(text)
- polygon.canvas.renderAll()
-
- const text2 = new fabric.Text(`(${line.endPoint.x},${line.endPoint.y})`, {
- left: line.endPoint.x,
- top: line.endPoint.y,
- fontSize: 15,
- })
-
- polygon.canvas.add(text2)
- polygon.canvas.renderAll()
- })
-
- polygon.points.forEach((point, index) => {
- const text = new fabric.Text(`(${point.x},${point.y})`, {
- left: point.x,
- top: point.y,
- fontSize: 15,
- })
-
- polygon.canvas.add(text)
- polygon.canvas.renderAll()
- })*!/
- /!**
- * 좌표 테스트용 끝
- *!/
-
- polygon.points.forEach((point, index) => {
- allLines.forEach((line) => {
- if (line.endPoint.x === point.x && line.endPoint.y === point.y) {
- const temp = line.startPoint
- line.startPoint = line.endPoint
- line.endPoint = temp
- }
- })
- })
-
- polygon.points.forEach((point, index) => {
- const routes = []
-
- // 시작점은 시작 hip라인의 출발점
- const startPoint = { x: Math.round(point.x), y: Math.round(point.y) }
- // 도착점은 마지막 hip라인의 끝나는 점
- let endPoint = polygon.points[(index + 1) % polygon.points.length]
- endPoint = { x: Math.round(endPoint.x), y: Math.round(endPoint.y) }
-
- const startLine = allLines.find((line) => line.startPoint.x === startPoint.x && line.startPoint.y === startPoint.y)
- const endLine = allLines.find((line) => line.startPoint.x === endPoint.x && line.startPoint.y === endPoint.y)
-
- const arrivalPoint = endLine.endPoint
- routes.push(startLine.startPoint)
- routes.push(startLine.endPoint)
-
- //hip끼리 만나는 경우는 아무것도 안해도됨
- if (!isSamePoint(startLine.endPoint, arrivalPoint)) {
- // polygon line까지 추가
- const allLinesCopy = [...allLines, ...polygon.lines]
- // hip이 만나지 않는 경우 갈 수 있는 길을 다 돌아야함
- let currentPoint = startLine.endPoint
- let currentLine = startLine
- let movedLines = []
- let subMovedLines = []
- while (!isSamePoint(currentPoint, arrivalPoint)) {
- // startHip에서 만나는 출발선 두개. 두개의 선을 출발하여 arrivalPoint에 도착할 때 까지 count를 세고, 더 낮은 count를 가진 길을 선택한다.
- let connectedLines = allLinesCopy.filter((line) => isSamePoint(line.startPoint, currentPoint) || isSamePoint(line.endPoint, currentPoint))
-
- connectedLines = connectedLines.filter((line) => line !== currentLine)
-
- connectedLines = connectedLines.filter((line) => !subMovedLines.includes(line))
-
- //마지막 선이 endLine의 startPoint와 같은경우 그 전까지 movedLine을 제거한다.
- const endLineMeetLineCnt = connectedLines.filter((line) => {
- return isSamePoint(line.endPoint, endLine.startPoint) || isSamePoint(line.startPoint, endLine.startPoint)
- }).length
-
- if (endLineMeetLineCnt !== 0) {
- movedLines.push(subMovedLines)
-
- console.log(movedLines, index)
- }
-
- connectedLines = connectedLines.filter((line) => {
- return !isSamePoint(line.endPoint, endLine.startPoint) && !isSamePoint(line.startPoint, endLine.startPoint)
- })
-
- if (connectedLines.length === 0) {
- return
- }
-
- let tempPoints = []
-
- for (let i = 0; i < connectedLines.length; i++) {
- if (isSamePoint(connectedLines[i].startPoint, currentPoint)) {
- tempPoints.push({ point: connectedLines[i].endPoint, index: i, line: connectedLines[i] })
- } else {
- tempPoints.push({ point: connectedLines[i].startPoint, index: i, line: connectedLines[i] })
- }
- }
-
- //tempPoints에서 arrivalPoint와 가장 가까운 점을 찾는다.
- let minDistance = Number.MAX_SAFE_INTEGER
- let minIndex = 0
- tempPoints.forEach((tempPoint, index) => {
- const distance = Math.sqrt(Math.pow(tempPoint.point.x - arrivalPoint.x, 2) + Math.pow(tempPoint.point.y - arrivalPoint.y, 2))
- if (distance < minDistance) {
- minDistance = distance
- minIndex = tempPoint.index
- }
- })
-
- currentPoint = tempPoints[minIndex].point
- currentLine = tempPoints[minIndex].line
- if (currentLine !== startLine) {
- subMovedLines.push(currentLine)
- }
- routes.push(currentPoint)
- }
- }
-
- routes.push(endLine.startPoint)
- roofs.push(routes)
- })
-
- // 중복 제거
- roofs.forEach((roofPoint, index) => {
- const samePointLengthRoofPoints = roofs.filter((roof) => roof.length === roofPoint.length && roof !== roofPoint)
-
- samePointLengthRoofPoints.forEach((samePointRoof) => {
- if (arraysHaveSamePoints(samePointRoof, roofPoint)) {
- roofs.splice(roofs.indexOf(samePointRoof), 1)
- }
- })
- })
-
- roofs.forEach((roofPoint, index) => {
- let defense, pitch
- const direction = getDirectionByPoint(roofPoint[0], roofPoint[roofPoint.length - 1])
-
- switch (direction) {
- case 'top':
- defense = 'east'
- break
- case 'right':
- defense = 'south'
- break
- case 'bottom':
- defense = 'west'
- break
- case 'left':
- defense = 'north'
- break
- }
- pitch = polygon.lines[index].attributes?.pitch ?? 0
-
- const roof = new QPolygon(roofPoint, {
- fontSize: polygon.fontSize,
- stroke: 'black',
- fill: 'transparent',
- strokeWidth: 3,
- name: POLYGON_TYPE.ROOF,
- originX: 'center',
- originY: 'center',
- selectable: true,
- defense: defense,
- direction: defense,
- pitch: pitch,
- })
-
- polygon.canvas.add(roof)
- polygon.canvas.renderAll()
- })
-}*/
-
function normalizePoint(point) {
return {
x: Math.round(point.x),
@@ -1204,34 +290,6 @@ export const isSamePoint = (a, b) => {
return Math.abs(Math.round(a.x) - Math.round(b.x)) <= 2 && Math.abs(Math.round(a.y) - Math.round(b.y)) <= 2
}
-/**
- * Calculate the angle between two lines.
- * @param {Object} line1 - The first line defined by two points {x1, y1} and {x2, y2}.
- * @param {Object} line2 - The second line defined by two points {x1, y1} and {x2, y2}.
- * @returns {number} - The angle between the two lines in degrees.
- */
-function calculateAngleBetweenLines(line1, line2) {
- const { x1: x1_1, y1: y1_1, x2: x2_1, y2: y2_1 } = line1
- const { x1: x1_2, y1: y1_2, x2: x2_2, y2: y2_2 } = line2
-
- // Calculate direction vectors
- const vector1 = { x: x2_1 - x1_1, y: y2_1 - y1_1 }
- const vector2 = { x: x2_2 - x1_2, y: y2_2 - y1_2 }
-
- // Calculate dot product and magnitudes
- const dotProduct = vector1.x * vector2.x + vector1.y * vector2.y
- const magnitude1 = Math.sqrt(vector1.x * vector1.x + vector1.y * vector1.y)
- const magnitude2 = Math.sqrt(vector2.x * vector2.x + vector2.y * vector2.y)
-
- // Calculate the cosine of the angle
- const cosTheta = dotProduct / (magnitude1 * magnitude2)
-
- // Calculate the angle in radians and then convert to degrees
- const angleInRadians = Math.acos(cosTheta)
-
- return (angleInRadians * 180) / Math.PI
-}
-
/**
* 박공지붕(templateA, templateB)을 그린다.
* @param roofId
@@ -1253,7 +311,7 @@ export const drawGabledRoof = (roofId, canvas) => {
const minY = Math.min(...roofPoints.map((point) => point.y))
const maxY = Math.max(...roofPoints.map((point) => point.y))
- // 맞은편 라인을 찾기 위해 현재 polygon으로 만들수 있는 최대한의 길이를 구한다.
+ // 맞은편 라인을 찾기 위해 현재 polygon 으로 만들수 있는 최대한의 길이를 구한다.
const checkLength = Math.abs(Math.sqrt(Math.pow(maxX - minX, 2) + Math.pow(maxY - minY, 2)))
// 처마라인의 기본속성 입력
@@ -1267,13 +325,11 @@ export const drawGabledRoof = (roofId, canvas) => {
const ridges = []
eaves.sort((a, b) => a.length - b.length)
- eaves.forEach((eave, index) => {
+ eaves.forEach((eave) => {
if (ridges.length < ridgeCount) {
const index = eave.index,
currentRoof = eave.roof
const currentWall = wallLines[index]
- // const prevRoof = index === 0 ? roofLines[wallLines.length - 1] : roofLines[index - 1]
- // const nextRoof = index === roofLines.length - 1 ? roofLines[0] : index === roofLines.length ? roofLines[1] : roofLines[index + 1]
//현재 지붕의 중심 좌표
const midX = Math.round(((currentRoof.x1 + currentRoof.x2) / 2) * 10) / 10
@@ -1281,7 +337,7 @@ export const drawGabledRoof = (roofId, canvas) => {
const deltaX = currentWall.x2 - currentWall.x1
const deltaY = currentWall.y2 - currentWall.y1
const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
- // currentWall과 직각인 기울기 계산
+ // currentWall 과 직각인 기울기 계산
const perpendicularDeltaX = deltaY / length
const perpendicularDeltaY = -deltaX / length
// midX와 midY를 기준으로 직각 기울기를 사용하여 midWallX와 midWallY 계산
@@ -1376,14 +432,15 @@ export const drawGabledRoof = (roofId, canvas) => {
const ridge = new QLine([centerLineX1, centerLineY1, centerLineX2, centerLineY2], {
fontSize: roof.fontSize,
- stroke: 'blue',
- strokeWidth: 1,
+ stroke: '#1083E3',
+ strokeWidth: 2,
name: LINE_TYPE.SUBLINE.RIDGE,
attributes: { roofId: roof.id, currentRoof: currentRoof.id },
})
canvas.add(ridge)
canvas.renderAll()
ridges.push(ridge)
+ roof.innerLines.push(ridge)
}
})
eaves.forEach((eave) => {
@@ -1398,7 +455,7 @@ export const drawGabledRoof = (roofId, canvas) => {
const deltaX = currentWall.x2 - currentWall.x1
const deltaY = currentWall.y2 - currentWall.y1
const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
- // currentWall과 직각인 기울기 계산
+ // currentWall 과 직각인 기울기 계산
const perpendicularDeltaX = deltaY / length
const perpendicularDeltaY = -deltaX / length
// midX와 midY를 기준으로 직각 기울기를 사용하여 midWallX와 midWallY 계산
@@ -1409,7 +466,7 @@ export const drawGabledRoof = (roofId, canvas) => {
let points = []
const intersectRidge = []
- // 현재 roof가 wall보다 작을때 이전, 다음 지붕의 offset만큼 포인트를 조정한다.
+ // 현재 roof 가 wall 보다 작을때 이전, 다음 지붕의 offset 만큼 포인트를 조정한다.
if (currentRoof.attributes.planeSize > currentWall.attributes.planeSize) {
points.push({ x: currentRoof.x1, y: currentRoof.y1 }, { x: currentRoof.x2, y: currentRoof.y2 })
} else if (currentRoof.attributes.planeSize === currentWall.attributes.planeSize) {
@@ -1481,15 +538,8 @@ export const drawGabledRoof = (roofId, canvas) => {
}
})
- intersectRidge.forEach((intersect, index) => {
+ intersectRidge.forEach((intersect) => {
const line = intersect.line
- const ridge = new fabric.Line([line.x1, line.y1, line.x2, line.y2], {
- stroke: 'red',
- strokeWidth: 2,
- selectable: false,
- })
- canvas.add(ridge)
- canvas.renderAll()
if (currentRoof.attributes.planeSize > currentWall.attributes.planeSize) {
points.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 })
} else if (currentRoof.attributes.planeSize === currentWall.attributes.planeSize) {
@@ -1545,8 +595,8 @@ export const drawGabledRoof = (roofId, canvas) => {
points.push({ x: lineX1, y: lineY1 }, { x: lineX2, y: lineY2 })
}
- canvas.remove(ridge)
- canvas.renderAll()
+ // canvas.remove(ridge)
+ // canvas.renderAll()
})
points = points.filter((point, index, self) => index === self.findIndex((p) => p.x === point.x && p.y === point.y))
@@ -1558,6 +608,7 @@ export const drawGabledRoof = (roofId, canvas) => {
const sortedPoints = [startPoint]
points.forEach((p, index) => {
const lastPoint = sortedPoints[sortedPoints.length - 1]
+ console.log('lastPoint', lastPoint)
if (index === 0) {
const underStartPoint = points.filter((point) => point.y > startPoint.y)
const nextPoint = underStartPoint
@@ -1667,7 +718,7 @@ export const drawGabledRoof = (roofId, canvas) => {
}
})
//기준선 제거
- ridges.forEach((ridge) => canvas.remove(ridge))
+ // ridges.forEach((ridge) => canvas.remove(ridge))
}
/**
@@ -1684,7 +735,6 @@ export const drawShedRoof = (roofId, canvas) => {
}
const sheds = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED)
- // const eaves = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
const gables = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.GABLE)
let shedDegree = sheds[0].attributes.degree || 0
@@ -1753,12 +803,8 @@ const drawRidge = (roof, canvas) => {
currentRoof = item.roof
const prevRoof = index === 0 ? roofLines[wallLines.length - 1] : roofLines[index - 1]
const nextRoof = index === roofLines.length - 1 ? roofLines[0] : index === roofLines.length ? roofLines[1] : roofLines[index + 1]
- // const beforePrevRoof = index <= 1 ? roofLines[roofLines.length - 2 + index] : roofLines[index - 2]
- // const afterNextRoof = index >= roofLines.length - 2 ? roofLines[(index + 2) % roofLines.length] : roofLines[index + 2]
let startXPoint, startYPoint, endXPoint, endYPoint
- // console.log('currentRoof : ', currentRoof.direction, currentRoof.attributes.planeSize)
-
let wallLine = wallLines.filter((w) => w.id === currentRoof.attributes.wallLine)
if (wallLine.length > 0) {
wallLine = wallLine[0]
@@ -1942,7 +988,7 @@ const drawRidge = (roof, canvas) => {
})
//겹쳐지는 마루는 하나로 합침
- roof.ridges.forEach((ridge, index) => {
+ roof.ridges.forEach((ridge) => {
roof.ridges
.filter((ridge2) => !(ridge.x1 === ridge2.x1 && ridge.y1 === ridge2.y1 && ridge.x2 === ridge2.x2 && ridge.y2 === ridge2.y2))
.forEach((ridge2) => {
@@ -2026,7 +1072,7 @@ const drawHips = (roof, canvas) => {
const roofLines = roof.lines
const ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roof.id)
- //마루에서 시작되는 hip을 먼저 그립니다.
+ //마루에서 시작되는 hip 을 먼저 그립니다.
roofLines
.filter((roof) => roof.attributes.type === LINE_TYPE.WALLLINE.EAVES && roof.attributes.ridgeCoordinate !== undefined)
.forEach((currentRoof, index) => {
@@ -2086,7 +1132,7 @@ const drawHips = (roof, canvas) => {
const hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roof.id)
- //마루에서 시작되지 않는 hip을 그립니다.
+ //마루에서 시작되지 않는 hip 을 그립니다.
roofLines
.filter((roof) => {
let isHip = false
@@ -2159,50 +1205,9 @@ const drawHips = (roof, canvas) => {
}
/**
- * 라인 사이가 지붕골 인지 확인.
- * @param polygon
- * @param line1
- * @param line2
- * @returns {boolean}
- */
-const checkValley = (polygon, line1, line2) => {
- let points = [
- { x: line1.x1, y: line1.y1 },
- { x: line1.x2, y: line1.y2 },
- { x: line2.x1, y: line2.y1 },
- { x: line2.x2, y: line2.y2 },
- ]
-
- const uniquePointsMap = new Map()
- points.forEach((point) => {
- const key = `${point.x},${point.y}`
- if (!uniquePointsMap.has(key)) {
- uniquePointsMap.set(key, point)
- }
- })
- points = Array.from(uniquePointsMap.values())
-
- const centroidX = points.reduce((acc, point) => acc + point.x, 0) / points.length
- const centroidY = points.reduce((acc, point) => acc + point.y, 0) / points.length
-
- let isValley = false
- const pPoints = polygon.points
- pPoints.forEach((point, index) => {
- let j = (index + 1) % pPoints.length
- let xi = pPoints[index].x + polygon.left,
- yi = pPoints[index].y + polygon.top
- let xj = pPoints[j].x + polygon.left,
- yj = pPoints[j].y + polygon.top
-
- let intersect = yi > centroidY !== yj > centroidY && centroidX < ((xj - xi) * (centroidY - yi)) / (yj - yi) + xi
- if (intersect) isValley = !isValley
- })
- return isValley
-}
-
-/*
- 3개 이상 이어지지 않은 라인 포인트 계산
- 모임지붕에서 point는 3개 이상의 라인과 접해야 함.
+ * 3개 이상 이어지지 않은 라인 포인트 계산
+ * 모임지붕에서 point 는 3개 이상의 라인과 접해야 함.
+ * @param polygon
*/
const connectLinePoint = (polygon) => {
// 연결되지 않은 모든 라인의 포인트를 구한다.
@@ -2560,9 +1565,8 @@ const changeEavesRoof = (currentRoof, canvas) => {
?.getObjects()
.filter(
(object) =>
- object.attributes !== undefined &&
- object.attributes.roofId === roofId &&
- object.attributes.currentRoof === currentRoof.id &&
+ object.attributes?.roofId === roofId &&
+ object.attributes?.currentRoof === currentRoof.id &&
object.x1 !== undefined &&
object.x2 !== undefined,
)
@@ -2724,9 +1728,8 @@ const changeGableRoof = (currentRoof, canvas) => {
?.getObjects()
.filter(
(object) =>
- object.attributes !== undefined &&
- object.attributes.roofId === roofId &&
- object.attributes.currentRoof === currentRoof.id &&
+ object.attributes?.roofId === roofId &&
+ object.attributes?.currentRoof === currentRoof.id &&
object.x1 !== undefined &&
object.x2 !== undefined,
)
@@ -2847,7 +1850,6 @@ const changeGableRoof = (currentRoof, canvas) => {
const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180))
hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10
hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2)))
- // roof.innerLines.push(hip1)
let hip2 = new QLine([currentRoof.x2, currentRoof.y2, midX, midY], {
fontSize: roof.fontSize,
@@ -2866,7 +1868,6 @@ const changeGableRoof = (currentRoof, canvas) => {
const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180))
hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10
hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2)))
- // roof.innerLines.push(hip2)
hip1.set({ visible: false })
hip1.setViewLengthText(false)
hip2.set({ visible: false })
@@ -2922,9 +1923,8 @@ const changeHipAndGableRoof = (currentRoof, canvas) => {
?.getObjects()
.filter(
(object) =>
- object.attributes !== undefined &&
- object.attributes.roofId === roofId &&
- object.attributes.currentRoof === currentRoof.id &&
+ object.attributes?.roofId === roofId &&
+ object.attributes?.currentRoof === currentRoof.id &&
object.x1 !== undefined &&
object.x2 !== undefined,
)
@@ -3352,7 +2352,6 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10
hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2)))
canvas?.add(hip2)
- // roof.innerLines.push(hip2)
hip1.set({ visible: false })
hip1.setViewLengthText(false)
@@ -3433,9 +2432,8 @@ const changeWallRoof = (currentRoof, canvas) => {
?.getObjects()
.filter(
(object) =>
- object.attributes !== undefined &&
- object.attributes.roofId === roofId &&
- object.attributes.currentRoof === currentRoof.id &&
+ object.attributes?.roofId === roofId &&
+ object.attributes?.currentRoof === currentRoof.id &&
object.x1 !== undefined &&
object.x2 !== undefined,
)
@@ -3713,8 +2711,8 @@ const reDrawPolygon = (polygon, canvas) => {
const newLines = newPolygon.lines
- newLines.forEach((line, index) => {
- lines.forEach((l, i) => {
+ newLines.forEach((line) => {
+ lines.forEach((l) => {
if (line.x1 === l.x1 && line.y1 === l.y1) {
line.id = l.id
line.attributes = l.attributes
@@ -3801,21 +2799,6 @@ function arePointsEqual(point1, point2) {
return Math.abs(point1.x - point2.x) <= 1 && Math.abs(point1.y - point2.y) <= 1
}
-function arraysHaveSamePoints(array1, array2) {
- if (array1.length !== array2.length) return false
-
- const sortedArray1 = array1.slice().sort((a, b) => a.x - b.x || a.y - b.y)
- const sortedArray2 = array2.slice().sort((a, b) => a.x - b.x || a.y - b.y)
-
- for (let i = 0; i < sortedArray1.length; i++) {
- if (!arePointsEqual(sortedArray1[i], sortedArray2[i])) {
- return false
- }
- }
-
- return true
-}
-
export const toGeoJSON = (pointsArray) => {
// 객체 배열을 GeoJSON 형식의 좌표 배열로 변환
const coordinates = pointsArray.map((point) => [point.x, point.y])
@@ -3834,14 +2817,14 @@ export const inPolygon = (polygonPoints, rectPoints) => {
const rectFeature = turf.polygon([rectCoordinates])
// 사각형의 모든 꼭짓점이 다각형 내부에 있는지 확인
- const allPointsInsidePolygon = rectCoordinates.every((coord) => {
- const point = turf.point(coord)
+ const allPointsInsidePolygon = rectCoordinates.every((coordinate) => {
+ const point = turf.point(coordinate)
return turf.booleanPointInPolygon(point, polygonFeature)
})
// 다각형의 모든 점이 사각형 내부에 있지 않은지 확인
- const noPolygonPointsInsideRect = polygonCoordinates.every((coord) => {
- const point = turf.point(coord)
+ const noPolygonPointsInsideRect = polygonCoordinates.every((coordinate) => {
+ const point = turf.point(coordinate)
return !turf.booleanPointInPolygon(point, rectFeature)
})