diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js
index 7b817f8f..def5f45e 100644
--- a/src/components/fabric/QPolygon.js
+++ b/src/components/fabric/QPolygon.js
@@ -244,21 +244,10 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
const types = []
this.lines.forEach((line) => types.push(line.attributes.type))
- const eavesType = [LINE_TYPE.WALLLINE.EAVES, LINE_TYPE.WALLLINE.HIPANDGABLE]
const gableType = [LINE_TYPE.WALLLINE.GABLE, LINE_TYPE.WALLLINE.JERKINHEAD]
- // const isEaves = types.every((type) => eavesType.includes(type))
- const gableOdd = types.filter((type, i) => i % 2 === 0)
- const gableEven = types.filter((type, i) => i % 2 === 1)
const hasShed = types.includes(LINE_TYPE.WALLLINE.SHED)
- // A형, B형 박공 지붕
- /* if (
- (gableOdd.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && gableEven.every((type) => gableType.includes(type))) ||
- (gableEven.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && gableOdd.every((type) => gableType.includes(type)))
- ) {
- drawGabledRoof(this.id, this.canvas, textMode)
- } else*/
if (hasShed) {
const sheds = this.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED)
const areLinesParallel = function (line1, line2) {
diff --git a/src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx b/src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx
index 0f80f9ec..31cf3909 100644
--- a/src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx
+++ b/src/components/floor-plan/modal/eavesGable/type/WallMerge.jsx
@@ -18,7 +18,7 @@ export default function WallMerge({ offsetRef, radioTypeRef }) {
@@ -31,7 +31,7 @@ export default function WallMerge({ offsetRef, radioTypeRef }) {
diff --git a/src/hooks/roofcover/useEavesGableEdit.js b/src/hooks/roofcover/useEavesGableEdit.js
index 11ac5684..b6fcb8cf 100644
--- a/src/hooks/roofcover/useEavesGableEdit.js
+++ b/src/hooks/roofcover/useEavesGableEdit.js
@@ -61,8 +61,7 @@ export function useEavesGableEdit(id) {
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
wallLines.forEach((wallLine) => {
- const id = wallLine.id
- wallLine.lines = outerLines.filter((line) => line.attributes?.wallId === id)
+ wallLine.lines = outerLines.filter((line) => line.attributes?.wallId === wallLine.id).sort((a, b) => a.idx - b.idx)
})
wallLines.forEach((wallLine) => {
convertPolygonToLines(wallLine)
@@ -77,6 +76,38 @@ export function useEavesGableEdit(id) {
convertLinesToPolygon(wallLine)
})
initEvent()
+
+ const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
+
+ outerLines.forEach((line) => {
+ let stroke, strokeWidth
+ if (line.attributes) {
+ if (line.attributes.type === LINE_TYPE.WALLLINE.EAVES || line.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) {
+ stroke = '#45CD7D'
+ strokeWidth = 4
+ } else if (line.attributes.type === LINE_TYPE.WALLLINE.GABLE || line.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ stroke = '#3FBAE6'
+ strokeWidth = 4
+ } else {
+ stroke = '#000000'
+ strokeWidth = 4
+ }
+
+ line.set({
+ visible: true,
+ stroke,
+ strokeWidth,
+ selectable: false,
+ })
+
+ line.bringToFront()
+ }
+ })
+ const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
+ roofs.forEach((roof) => {
+ roof.innerLines.forEach((line) => line.set({ selectable: true }))
+ })
+ canvas.renderAll()
}
}, [])
@@ -106,6 +137,7 @@ export function useEavesGableEdit(id) {
}
const mouseDownEvent = (e) => {
+ canvas.discardActiveObject()
if (!e.target || (e.target && e.target.name !== 'outerLine')) {
return
}
diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js
index f1451bd1..4945fdd7 100644
--- a/src/hooks/useCanvas.js
+++ b/src/hooks/useCanvas.js
@@ -3,18 +3,16 @@ import { fabric } from 'fabric'
import { actionHandler, anchorWrapper, polygonPositionHandler } from '@/util/canvas-util'
-import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
+import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
import { canvasSizeState, canvasState, canvasZoomState, fontSizeState } from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine'
import { QPolygon } from '@/components/fabric/QPolygon'
import { defineQLine } from '@/util/qline-utils'
-import { defineQPloygon } from '@/util/qpolygon-utils'
+import { defineQPolygon } from '@/util/qpolygon-utils'
import { writeImage } from '@/lib/canvas'
import { useCanvasEvent } from '@/hooks/useCanvasEvent'
-import { useAxios } from '@/hooks/useAxios'
import { useFont } from '@/hooks/common/useFont'
-import { OBJECT_PROTOTYPE, POLYGON_TYPE, RELOAD_TYPE_PROTOTYPE, SAVE_KEY } from '@/common/common'
-import { usePlan } from './usePlan'
+import { OBJECT_PROTOTYPE, SAVE_KEY } from '@/common/common'
import { imageDisplaySelector } from '@/store/settingAtom'
export function useCanvas(id) {
@@ -140,7 +138,7 @@ export function useCanvas(id) {
QPolygon.prototype.canvas = canvas
QLine.prototype.canvas = canvas
defineQLine()
- defineQPloygon()
+ defineQPolygon()
}
/**
@@ -376,6 +374,8 @@ export function useCanvas(id) {
/**
* 이미지로 저장하는 함수
* @param {string} title - 저장할 이미지 이름
+ * @param userId
+ * @param setThumbnails
*/
const saveImage = async (title = 'canvas', userId, setThumbnails) => {
removeMouseLines()
diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js
index 7b99948b..8f1a72ce 100644
--- a/src/util/qpolygon-utils.js
+++ b/src/util/qpolygon-utils.js
@@ -1,16 +1,15 @@
import { fabric } from 'fabric'
import { QLine } from '@/components/fabric/QLine'
-import { getDegreeByChon, isPointOnLine } from '@/util/canvas-util'
+import { getAdjacent, getDegreeByChon, isPointOnLine } from '@/util/canvas-util'
import { QPolygon } from '@/components/fabric/QPolygon'
import * as turf from '@turf/turf'
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
-import { OUTER_LINE_TYPE } from '@/store/outerLineAtom'
import Big from 'big.js'
const TWO_PI = Math.PI * 2
-export const defineQPloygon = () => {
+export const defineQPolygon = () => {
fabric.QPolygon.fromObject = function (object, callback) {
fabric.Object._fromObject('QPolygon', object, callback, 'points')
}
@@ -378,15 +377,7 @@ export const drawShedRoof = (roofId, canvas, textMode) => {
const gables = roof.lines.filter((line) => line.attributes?.type === LINE_TYPE.WALLLINE.GABLE)
const eaves = roof.lines.filter((line) => line.attributes?.type === LINE_TYPE.WALLLINE.EAVES)
- let shedDegree = sheds[0].attributes.degree || 0
- const shedChon = sheds[0].attributes.pitch || 0
-
- if (shedDegree === 0) {
- shedDegree = getDegreeByChon(shedChon)
- }
- const getHeight = function (adjust, degree) {
- return Math.tan(degree * (Math.PI / 180)) * adjust
- }
+ const shedDegree = getDegreeByChon(sheds[0].attributes.pitch)
gables.forEach(
(gable) =>
@@ -429,9 +420,6 @@ export const drawShedRoof = (roofId, canvas, textMode) => {
x2 = eave.x1
}
points.sort((a, b) => a - b)
- // const planeSize = Math.round(Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)) * 10)
- const planeSize = calcLinePlaneSize({ x1, y1, x2, y2 })
- // const actualSize = Math.round(Math.sqrt (Math.pow(planeSize, 2) + Math.pow(getHeight(planeSize, shedDegree), 2)) * 10)
const actualSize = calcLineActualSize({ x1, y1, x2, y2 }, shedDegree)
const line = new QLine([x1, y1, x2, y2], {
@@ -465,12 +453,9 @@ export const drawShedRoof = (roofId, canvas, textMode) => {
* @param textMode
*/
export const drawRidgeRoof = (roofId, canvas, textMode) => {
- const roof = canvas?.getObjects().find((object) => object.id === roofId)
+ let roof = canvas?.getObjects().find((object) => object.id === roofId)
const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId)
- console.log('wall.lines : ', wall.lines)
- console.log('wall.baseLines : ', wall.baseLines)
-
const hasNonParallelLines = roof.lines.filter((line) => Big(line.x1).minus(Big(line.x2)).gt(1) && Big(line.y1).minus(Big(line.y2)).gt(1))
if (hasNonParallelLines.length > 0) {
return
@@ -483,6 +468,231 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const baseLines = wall.baseLines.filter((line) => line.attributes.planeSize > 0)
const baseLinePoints = baseLines.map((line) => ({ x: line.x1, y: line.y1 }))
+ /** 벽취합이 있는 경우 소매가 있다면 지붕 형상을 변경해야 한다. */
+ console.log('baseLines :', baseLines)
+ console.log('roof : ', roof)
+ baseLines
+ .filter((line) => line.attributes.type === LINE_TYPE.WALLLINE.WALL && line.attributes.offset > 0)
+ .forEach((currentLine) => {
+ const prevLine = baseLines.find((line) => line.x2 === currentLine.x1 && line.y2 === currentLine.y1)
+ const nextLine = baseLines.find((line) => line.x1 === currentLine.x2 && line.y1 === currentLine.y2)
+
+ const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2).toNumber()
+ const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2).toNumber()
+ const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1)
+ const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1)
+
+ /** 현재 라인의 지붕 라인을 찾는다. */
+ const intersectionRoofs = []
+ let currentRoof
+ if (currentVectorX === 0) {
+ const checkEdge = {
+ vertex1: { x: prevLine.x1, y: currentMidY },
+ vertex2: { x: currentMidX, y: currentMidY },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ } else {
+ const checkEdge = {
+ vertex1: { x: currentMidX, y: prevLine.y1 },
+ vertex2: { x: currentMidX, y: currentMidY },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ }
+ if (intersectionRoofs.length > 0) {
+ currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line
+ }
+ if (currentRoof) {
+ const prevRoof = roof.lines.find((line) => line.x2 === currentRoof.x1 && line.y2 === currentRoof.y1)
+ const nextRoof = roof.lines.find((line) => line.x1 === currentRoof.x2 && line.y1 === currentRoof.y2)
+
+ const prevOffset = prevLine.attributes.offset
+ const nextOffset = nextLine.attributes.offset
+
+ currentRoof.set({ x1: currentLine.x1, y1: currentLine.y1, x2: currentLine.x2, y2: currentLine.y2 })
+
+ if (prevLine.attributes.type !== LINE_TYPE.WALLLINE.WALL && prevOffset > 0) {
+ const addPoint1 = []
+ const addPoint2 = []
+ if (Math.sign(prevLine.y2 - prevLine.y1) === 0) {
+ addPoint1.push(prevRoof.x2, prevRoof.y2, prevRoof.x2, currentRoof.y1)
+ addPoint2.push(addPoint1[2], addPoint1[3], currentRoof.x1, currentRoof.y1)
+ } else {
+ addPoint1.push(prevRoof.x2, prevRoof.y2, currentRoof.x1, prevRoof.y2)
+ addPoint2.push(addPoint1[2], addPoint1[3], currentRoof.x1, currentRoof.y1)
+ }
+ const addRoofLine1 = new QLine(addPoint1, {
+ name: 'addRoofLine',
+ parentId: roof.id,
+ fontSize: roof.fontSize,
+ stroke: '#1083E3',
+ strokeWidth: 2,
+ textMode: textMode,
+ attributes: {
+ roofId: roofId,
+ type: LINE_TYPE.WALLLINE.ETC,
+ planeSize: calcLinePlaneSize({
+ x1: addPoint1[0],
+ y1: addPoint1[1],
+ x2: addPoint1[2],
+ y2: addPoint1[3],
+ }),
+ actualSize: calcLinePlaneSize({
+ x1: addPoint1[0],
+ y1: addPoint1[1],
+ x2: addPoint1[2],
+ y2: addPoint1[3],
+ }),
+ },
+ })
+
+ const addRoofLine2 = new QLine(addPoint2, {
+ name: 'addRoofLine',
+ parentId: roof.id,
+ fontSize: roof.fontSize,
+ stroke: '#1083E3',
+ strokeWidth: 2,
+ textMode: textMode,
+ attributes: {
+ roofId: roofId,
+ type: LINE_TYPE.WALLLINE.ETC,
+ planeSize: calcLinePlaneSize({
+ x1: addPoint2[0],
+ y1: addPoint2[1],
+ x2: addPoint2[2],
+ y2: addPoint2[3],
+ }),
+ actualSize: calcLinePlaneSize({
+ x1: addPoint2[0],
+ y1: addPoint2[1],
+ x2: addPoint2[2],
+ y2: addPoint2[3],
+ }),
+ },
+ })
+ canvas.add(addRoofLine1, addRoofLine2)
+ canvas.renderAll()
+
+ const prevIndex = roof.lines.indexOf(prevRoof)
+ if (prevIndex === roof.lines.length - 1) {
+ roof.lines.unshift(addRoofLine1, addRoofLine2)
+ } else {
+ roof.lines.splice(prevIndex + 1, 0, addRoofLine1, addRoofLine2)
+ }
+ } else if (prevLine.attributes.type === LINE_TYPE.WALLLINE.WALL || prevOffset === 0) {
+ prevRoof.set({ x2: currentLine.x1, y2: currentLine.y1 })
+ }
+ if (nextLine.attributes.type !== LINE_TYPE.WALLLINE.WALL && nextOffset > 0) {
+ const addPoint1 = []
+ const addPoint2 = []
+ if (Math.sign(nextLine.y2 - nextLine.y1) === 0) {
+ addPoint1.push(currentRoof.x2, currentRoof.y2, nextRoof.x1, currentRoof.y2)
+ addPoint2.push(addPoint1[2], addPoint1[3], nextRoof.x1, nextRoof.y1)
+ } else {
+ addPoint1.push(currentRoof.x2, currentRoof.y2, currentRoof.x2, nextRoof.y1)
+ addPoint2.push(addPoint1[2], addPoint1[3], nextRoof.x1, nextRoof.y1)
+ }
+
+ const addRoofLine1 = new QLine(addPoint1, {
+ name: 'addRoofLine',
+ parentId: roof.id,
+ fontSize: roof.fontSize,
+ stroke: '#1083E3',
+ strokeWidth: 2,
+ textMode: textMode,
+ attributes: {
+ roofId: roofId,
+ type: LINE_TYPE.WALLLINE.ETC,
+ planeSize: calcLinePlaneSize({
+ x1: addPoint1[0],
+ y1: addPoint1[1],
+ x2: addPoint1[2],
+ y2: addPoint1[3],
+ }),
+ actualSize: calcLinePlaneSize({
+ x1: addPoint1[0],
+ y1: addPoint1[1],
+ x2: addPoint1[2],
+ y2: addPoint1[3],
+ }),
+ },
+ })
+
+ const addRoofLine2 = new QLine(addPoint2, {
+ name: 'addRoofLine',
+ parentId: roof.id,
+ fontSize: roof.fontSize,
+ stroke: '#1083E3',
+ strokeWidth: 2,
+ textMode: textMode,
+ attributes: {
+ roofId: roofId,
+ type: LINE_TYPE.WALLLINE.ETC,
+ planeSize: calcLinePlaneSize({
+ x1: addPoint2[0],
+ y1: addPoint2[1],
+ x2: addPoint2[2],
+ y2: addPoint2[3],
+ }),
+ actualSize: calcLinePlaneSize({
+ x1: addPoint2[0],
+ y1: addPoint2[1],
+ x2: addPoint2[2],
+ y2: addPoint2[3],
+ }),
+ },
+ })
+ canvas.add(addRoofLine1, addRoofLine2)
+ canvas.renderAll()
+
+ const nextIndex = roof.lines.indexOf(nextRoof)
+ if (nextIndex === 0) {
+ roof.lines.push(addRoofLine1, addRoofLine2)
+ } else {
+ roof.lines.splice(nextIndex, 0, addRoofLine1, addRoofLine2)
+ }
+ } else if (nextLine.attributes.type === LINE_TYPE.WALLLINE.WALL) {
+ if (Math.sign(nextLine.y2 - nextLine.y1) === 0) {
+ nextRoof.set({ x1: currentLine.x2, y1: nextRoof.y1 })
+ } else {
+ nextRoof.set({ x1: nextRoof.x1, y1: currentLine.y2 })
+ }
+ currentRoof.set({ x2: nextRoof.x1, y2: nextRoof.y1 })
+ } else if (nextOffset === 0) {
+ nextRoof.set({ x1: currentLine.x2, y1: currentLine.y2 })
+ }
+
+ roof = reDrawPolygon(roof, canvas)
+ }
+ })
+
/** 모양 판단을 위한 라인 처리.
* 평행한 라인이 나누어져 있는 경우 하나의 선으로 판단 한다.
*/
@@ -541,6 +751,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const drawGablePolygonFirst = []
const drawGablePolygonSecond = []
const drawHipAndGableFirst = []
+ const drawWallRidgeLine = []
/** 모양을 판단한다. */
drawBaseLines.forEach((currentBaseLine, index) => {
@@ -584,22 +795,17 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
} else {
drawEavesSecondLines.push({ currentBaseLine, prevBaseLine, nextBaseLine })
}
+ } else if (eavesType.includes(nextLine.attributes?.type)) {
+ drawEavesSecondLines.push({ currentBaseLine, prevBaseLine, nextBaseLine })
}
} else if (gableType.includes(nextLine.attributes?.type) && gableType.includes(prevLine.attributes?.type)) {
if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)) {
- const checkPoints = {
- x: currentMidX.plus(checkScale.times(Math.sign(xVector.toNumber()))).toNumber(),
- y: currentMidY.plus(checkScale.times(Math.sign(yVector.toNumber()))).toNumber(),
- }
-
if (checkWallPolygon.inPolygon(checkPoints)) {
drawGablePolygonFirst.push({ currentBaseLine, prevBaseLine, nextBaseLine })
} else {
drawGablePolygonSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine })
}
- // if (!checkWallPolygon.inPolygon(checkPoints)) {
drawGableRidgeSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine })
- // }
} else {
if (currentAngle !== prevAngle && currentAngle !== nextAngle) {
drawGablePolygonSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine })
@@ -609,29 +815,42 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}
if (gableType.includes(currentLine.attributes?.type)) {
- if (eavesType.includes(nextLine.attributes?.type)) {
- if (
- eavesType.includes(prevLine.attributes?.type) &&
- eavesType.includes(nextLine.attributes?.type) &&
- Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)
- ) {
- if (checkWallPolygon.inPolygon(checkPoints)) {
- drawGableRidgeFirst.push({ currentBaseLine, prevBaseLine, nextBaseLine })
- } else {
- drawGableRidgeSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine })
- }
+ if (
+ eavesType.includes(prevLine.attributes?.type) &&
+ eavesType.includes(nextLine.attributes?.type) &&
+ Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)
+ ) {
+ if (checkWallPolygon.inPolygon(checkPoints)) {
+ drawGableRidgeFirst.push({ currentBaseLine, prevBaseLine, nextBaseLine })
+ } else {
+ drawGableRidgeSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine })
}
}
}
- if (LINE_TYPE.WALLLINE.HIPANDGABLE === currentLine.attributes?.type) {
+ if (
+ LINE_TYPE.WALLLINE.HIPANDGABLE === currentLine.attributes?.type &&
+ eavesType.includes(nextLine.attributes?.type) &&
+ eavesType.includes(prevLine.attributes?.type)
+ ) {
drawHipAndGableFirst.push({ currentBaseLine, prevBaseLine, nextBaseLine })
}
+
+ if (
+ LINE_TYPE.WALLLINE.WALL === currentLine.attributes?.type &&
+ eavesType.includes(nextLine.attributes?.type) &&
+ eavesType.includes(prevLine.attributes?.type)
+ ) {
+ if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180) && checkWallPolygon.inPolygon(checkPoints)) {
+ drawWallRidgeLine.push({ currentBaseLine, prevBaseLine, nextBaseLine })
+ }
+ }
})
drawEavesFirstLines.sort((a, b) => a.currentBaseLine.size - b.currentBaseLine.size)
drawGableRidgeFirst.sort((a, b) => a.currentBaseLine.size - b.currentBaseLine.size)
drawGableRidgeSecond.sort((a, b) => a.currentBaseLine.size - b.currentBaseLine.size)
+ drawWallRidgeLine.sort((a, b) => a.currentBaseLine.size - b.currentBaseLine.size)
/** 추녀마루 */
let baseHipLines = []
@@ -651,6 +870,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
console.log('drawGableRidgeSecond:', drawGableRidgeSecond)
console.log('drawGablePolygonFirst :', drawGablePolygonFirst)
console.log('drawGablePolygonSecond :', drawGablePolygonSecond)
+ console.log('drawHipAndGableFirst :', drawHipAndGableFirst)
+ console.log('drawWallLines :', drawWallRidgeLine)
/** 박공지붕에서 파생되는 마루를 그린다. ㄷ 형태*/
drawGableRidgeFirst.forEach((current) => {
@@ -663,11 +884,9 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
let beforePrevBaseLine, afterNextBaseLine
/** 이전 라인의 경사 */
- const prevDegree = prevLine.attributes.pitch > 0 ? getDegreeByChon(prevLine.attributes.pitch) : prevLine.attributes.degree
+ const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
/** 다음 라인의 경사 */
- const nextDegree = nextLine.attributes.pitch > 0 ? getDegreeByChon(nextLine.attributes.pitch) : nextLine.attributes.degree
- /** 현재 라인의 경사 */
- const currentDegree = currentLine.attributes.pitch > 0 ? getDegreeByChon(currentLine.attributes.pitch) : currentLine.attributes.degree
+ const nextDegree = getDegreeByChon(nextLine.attributes.pitch)
/** 이전 라인의 전라인, 다음 라인의 다음라인을 찾는다 */
drawBaseLines.forEach((line, index) => {
@@ -709,6 +928,60 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
let oppositeMidX = currentMidX,
oppositeMidY = currentMidY
+ /** 현재 라인의 지붕 라인을 찾는다. */
+ const intersectionRoofs = []
+ let currentRoof
+ if (currentVectorX === 0) {
+ const checkEdge = {
+ vertex1: { x: prevLine.x1, y: currentMidY.toNumber() },
+ vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ } else {
+ const checkEdge = {
+ vertex1: { x: currentMidX.toNumber(), y: prevLine.y1 },
+ vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ }
+ if (intersectionRoofs.length > 0) {
+ currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line
+ }
+
+ /** 현재 라인의 지붕선에서 이전 지붕선, 다음 지붕선으로 향하는 vector*/
+ const prevRoofVectorX = Math.sign(currentRoof.x2 - currentRoof.x1)
+ const prevRoofVectorY = Math.sign(currentRoof.y2 - currentRoof.y1)
+ const nextRoofVectorX = Math.sign(currentRoof.x1 - currentRoof.x2)
+ const nextRoofVectorY = Math.sign(currentRoof.y1 - currentRoof.y2)
+
/** 한개의 지붕선을 둘로 나누어서 처리 하는 경우 */
if (prevAngle === beforePrevAngle || nextAngle === afterNextAngle) {
if (currentVectorX === 0) {
@@ -861,6 +1134,73 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
line: nextHipLine,
})
}
+ const vectorOppositeX = Math.sign(currentMidX.minus(oppositeMidX))
+ const vectorOppositeY = Math.sign(currentMidY.minus(oppositeMidY))
+
+ /** 반철처 인 경우 처리 */
+ if (currentLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ const width = Big(currentLine.attributes.width).div(2)
+ const degree = getDegreeByChon(currentLine.attributes.pitch)
+ const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
+ const nextDegree = getDegreeByChon(nextLine.attributes.pitch)
+ if (vectorOppositeY === 0) {
+ currentMidX = currentMidX.minus(Big(width).times(vectorOppositeX))
+ } else {
+ currentMidY = currentMidY.minus(Big(width).times(vectorOppositeY))
+ }
+
+ /** 현재 라인에서 반철처 부분을 그린다.*/
+ let firstHipPoint, secondHipPoint, connectHipPoint, firstRoofPoint, secondRoofPoint
+ if (vectorOppositeY === 0) {
+ firstHipPoint = [
+ currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(),
+ currentMidY.minus(Big(width).times(prevRoofVectorY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+
+ secondHipPoint = [
+ currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(),
+ currentMidY.minus(Big(width).times(nextRoofVectorY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+ } else {
+ firstHipPoint = [
+ currentMidX.plus(Big(width).times(prevRoofVectorX)).toNumber(),
+ currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+
+ secondHipPoint = [
+ currentMidX.plus(Big(width).times(nextRoofVectorX)).toNumber(),
+ currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+ }
+ connectHipPoint = [firstHipPoint[0], firstHipPoint[1], secondHipPoint[0], secondHipPoint[1]]
+ firstRoofPoint = [currentRoof.x1, currentRoof.y1, firstHipPoint[0], firstHipPoint[1]]
+ secondRoofPoint = [currentRoof.x2, currentRoof.y2, secondHipPoint[0], secondHipPoint[1]]
+ const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, null, degree, degree)
+ const firstRoofLine = drawHipLine(firstRoofPoint, canvas, roof, textMode, null, prevDegree, prevDegree)
+ const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, null, degree, degree)
+ const secondRoofLine = drawHipLine(secondRoofPoint, canvas, roof, textMode, null, nextDegree, nextDegree)
+ const connectHipLine = drawRoofLine(connectHipPoint, canvas, roof, textMode)
+ baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine })
+ baseHipLines.push({ x1: firstRoofLine.x1, y1: firstRoofLine.y1, x2: firstRoofLine.x2, y2: firstRoofLine.y2, line: firstRoofLine })
+ baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine })
+ baseHipLines.push({ x1: secondRoofLine.x1, y1: secondRoofLine.y1, x2: secondRoofLine.x2, y2: secondRoofLine.y2, line: secondRoofLine })
+ baseHipLines.push({ x1: connectHipLine.x1, y1: connectHipLine.y1, x2: connectHipLine.x2, y2: connectHipLine.y2, line: connectHipLine })
+ } else {
+ const firstHipPoint = [currentRoof.x1, currentRoof.y1, currentMidX.toNumber(), currentMidY.toNumber()]
+ const secondHipPoint = [currentRoof.x2, currentRoof.y2, currentMidX.toNumber(), currentMidY.toNumber()]
+ const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, null, prevDegree, prevDegree)
+ const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, null, nextDegree, nextDegree)
+ baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine })
+ baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine })
+ }
if (baseRidgeCount < getMaxRidge(baseLines.length)) {
const ridgeLine = drawRidgeLine(
@@ -880,7 +1220,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const vectorMidY = Math.sign(currentMidY.minus(afterNextMidY))
let oppositeMidX, oppositeMidY
- if (eavesType.includes(afterNextLine.attributes?.type)) {
+ if (afterNextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
const checkSize = currentMidX
.minus(afterNextMidX)
.pow(2)
@@ -937,8 +1277,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
y: oppositeMidY.plus(addOppositeY2),
})
- const afterNextDegree =
- afterNextLine.attributes.pitch > 0 ? getDegreeByChon(afterNextLine.attributes.pitch) : afterNextLine.attributes.degree
+ const afterNextDegree = getDegreeByChon(afterNextLine.attributes.pitch)
if (intersection1) {
const hipLine = drawHipLine(
@@ -984,7 +1323,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const vectorOppositeX = Math.sign(currentMidX.minus(oppositeMidX))
const vectorOppositeY = Math.sign(currentMidY.minus(oppositeMidY))
- if (vectorMidX === vectorOppositeX && vectorMidY === vectorOppositeY && baseRidgeCount < getMaxRidge(baseLines.length)) {
+ if (vectorMidX === vectorOppositeX && vectorMidY === vectorOppositeY) {
if (!roof.inPolygon({ x: currentMidX.toNumber(), y: currentMidY.toNumber() })) {
const checkEdge = {
vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
@@ -1055,14 +1394,99 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}
}
- const ridge = drawRidgeLine(
- [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()],
- canvas,
- roof,
- textMode,
- )
- baseGableRidgeLines.push(ridge)
- baseRidgeCount++
+ if (afterNextLine.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) {
+ const width = afterNextLine.attributes.width
+ if (vectorOppositeY === 0) {
+ oppositeMidX = oppositeMidX.plus(Big(width).times(vectorOppositeX))
+ } else {
+ oppositeMidY = oppositeMidY.plus(Big(width).times(vectorOppositeY))
+ }
+ }
+
+ if (afterNextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ const width = Big(afterNextLine.attributes.width).div(2).toNumber()
+ if (vectorOppositeY === 0) {
+ oppositeMidX = oppositeMidX.plus(Big(width).times(vectorOppositeX))
+ } else {
+ oppositeMidY = oppositeMidY.plus(Big(width).times(vectorOppositeY))
+ }
+ }
+
+ /** 반철처 인 경우 처리 */
+ if (currentLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ const width = Big(currentLine.attributes.width).div(2)
+ const degree = getDegreeByChon(currentLine.attributes.pitch)
+ const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
+ const nextDegree = getDegreeByChon(nextLine.attributes.pitch)
+ if (vectorMidY === 0) {
+ currentMidX = currentMidX.minus(Big(width).times(vectorOppositeX))
+ } else {
+ currentMidY = currentMidY.minus(Big(width).times(vectorOppositeY))
+ }
+
+ /** 현재 라인에서 반철처 부분을 그린다.*/
+ let firstHipPoint, secondHipPoint, connectHipPoint, firstRoofPoint, secondRoofPoint
+ if (vectorMidY === 0) {
+ firstHipPoint = [
+ currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(),
+ currentMidY.minus(Big(width).times(prevRoofVectorY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+
+ secondHipPoint = [
+ currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(),
+ currentMidY.minus(Big(width).times(nextRoofVectorY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+ } else {
+ firstHipPoint = [
+ currentMidX.minus(Big(width).times(prevRoofVectorX)).toNumber(),
+ currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+
+ secondHipPoint = [
+ currentMidX.minus(Big(width).times(nextRoofVectorX)).toNumber(),
+ currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+ }
+ connectHipPoint = [firstHipPoint[0], firstHipPoint[1], secondHipPoint[0], secondHipPoint[1]]
+ firstRoofPoint = [currentRoof.x1, currentRoof.y1, firstHipPoint[0], firstHipPoint[1]]
+ secondRoofPoint = [currentRoof.x2, currentRoof.y2, secondHipPoint[0], secondHipPoint[1]]
+ const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, null, degree, degree)
+ const firstRoofLine = drawHipLine(firstRoofPoint, canvas, roof, textMode, null, prevDegree, prevDegree)
+ const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, null, degree, degree)
+ const secondRoofLine = drawHipLine(secondRoofPoint, canvas, roof, textMode, null, nextDegree, nextDegree)
+ const connectHipLine = drawRoofLine(connectHipPoint, canvas, roof, textMode)
+ baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine })
+ baseHipLines.push({ x1: firstRoofLine.x1, y1: firstRoofLine.y1, x2: firstRoofLine.x2, y2: firstRoofLine.y2, line: firstRoofLine })
+ baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine })
+ baseHipLines.push({ x1: secondRoofLine.x1, y1: secondRoofLine.y1, x2: secondRoofLine.x2, y2: secondRoofLine.y2, line: secondRoofLine })
+ baseHipLines.push({ x1: connectHipLine.x1, y1: connectHipLine.y1, x2: connectHipLine.x2, y2: connectHipLine.y2, line: connectHipLine })
+ } else {
+ const firstHipPoint = [currentRoof.x1, currentRoof.y1, currentMidX.toNumber(), currentMidY.toNumber()]
+ const secondHipPoint = [currentRoof.x2, currentRoof.y2, currentMidX.toNumber(), currentMidY.toNumber()]
+ const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, null, prevDegree, prevDegree)
+ const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, null, nextDegree, nextDegree)
+ baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine })
+ baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine })
+ }
+
+ if (baseRidgeCount < getMaxRidge(baseLines.length)) {
+ const ridge = drawRidgeLine(
+ [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()],
+ canvas,
+ roof,
+ textMode,
+ )
+ baseGableRidgeLines.push(ridge)
+ baseRidgeCount++
+ }
}
} else {
const vectorMidX = Math.sign(Big(nextLine.x2).minus(nextLine.x1))
@@ -1357,8 +1781,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
})
const intersect = intersectPoints.sort((a, b) => a.size - b.size)[0]
if (intersect) {
- const degree =
- intersect.line.attributes.pitch > 0 ? getDegreeByChon(intersect.line.attributes.pitch) : intersect.line.attributes.degree
+ const degree = getDegreeByChon(intersect.line.attributes.pitch)
const hipLine = drawHipLine(
[intersect.intersection.x, intersect.intersection.y, nextOppositeMidX.toNumber(), nextOppositeMidY.toNumber()],
canvas,
@@ -1421,8 +1844,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const intersect = intersectPoints.sort((a, b) => a.size - b.size)[0]
if (intersect) {
- const degree =
- intersect.line.attributes.pitch > 0 ? getDegreeByChon(intersect.line.attributes.pitch) : intersect.line.attributes.degree
+ const degree = getDegreeByChon(intersect.line.attributes.pitch)
const hipLine = drawHipLine(
[intersect.intersection.x, intersect.intersection.y, prevOppositeMidX.toNumber(), prevOppositeMidY.toNumber()],
canvas,
@@ -1445,8 +1867,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
oppositeMidX = prevOppositeMidX
}
}
- }
- if (baseRidgeCount < getMaxRidge(baseLines.length)) {
+
/** 포인트가 지붕 밖에 있는 경우 조정 */
if (!roof.inPolygon({ x: currentMidX.toNumber(), y: currentMidY.toNumber() })) {
const checkEdge = {
@@ -1518,6 +1939,74 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}
}
+ const vectorOppositeX = Math.sign(currentMidX.minus(oppositeMidX))
+ const vectorOppositeY = Math.sign(currentMidY.minus(oppositeMidY))
+
+ /** 반철처 인 경우 처리 */
+ if (currentLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ const width = Big(currentLine.attributes.width).div(2)
+ const degree = getDegreeByChon(currentLine.attributes.pitch)
+ const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
+ const nextDegree = getDegreeByChon(nextLine.attributes.pitch)
+ if (vectorOppositeY === 0) {
+ currentMidX = currentMidX.minus(Big(width).times(vectorOppositeX))
+ } else {
+ currentMidY = currentMidY.minus(Big(width).times(vectorOppositeY))
+ }
+
+ /** 현재 라인에서 반철처 부분을 그린다.*/
+ let firstHipPoint, secondHipPoint, connectHipPoint, firstRoofPoint, secondRoofPoint
+ if (vectorOppositeY === 0) {
+ firstHipPoint = [
+ currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(),
+ currentMidY.minus(Big(width).times(prevRoofVectorY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+
+ secondHipPoint = [
+ currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(),
+ currentMidY.minus(Big(width).times(nextRoofVectorY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+ } else {
+ firstHipPoint = [
+ currentMidX.minus(Big(width).times(prevRoofVectorX)).toNumber(),
+ currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+
+ secondHipPoint = [
+ currentMidX.minus(Big(width).times(nextRoofVectorX)).toNumber(),
+ currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(),
+ currentMidX.toNumber(),
+ currentMidY.toNumber(),
+ ]
+ }
+ connectHipPoint = [firstHipPoint[0], firstHipPoint[1], secondHipPoint[0], secondHipPoint[1]]
+ firstRoofPoint = [currentRoof.x1, currentRoof.y1, firstHipPoint[0], firstHipPoint[1]]
+ secondRoofPoint = [currentRoof.x2, currentRoof.y2, secondHipPoint[0], secondHipPoint[1]]
+ const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, null, degree, degree)
+ const firstRoofLine = drawHipLine(firstRoofPoint, canvas, roof, textMode, null, prevDegree, prevDegree)
+ const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, null, degree, degree)
+ const secondRoofLine = drawHipLine(secondRoofPoint, canvas, roof, textMode, null, nextDegree, nextDegree)
+ const connectHipLine = drawRoofLine(connectHipPoint, canvas, roof, textMode)
+ baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine })
+ baseHipLines.push({ x1: firstRoofLine.x1, y1: firstRoofLine.y1, x2: firstRoofLine.x2, y2: firstRoofLine.y2, line: firstRoofLine })
+ baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine })
+ baseHipLines.push({ x1: secondRoofLine.x1, y1: secondRoofLine.y1, x2: secondRoofLine.x2, y2: secondRoofLine.y2, line: secondRoofLine })
+ baseHipLines.push({ x1: connectHipLine.x1, y1: connectHipLine.y1, x2: connectHipLine.x2, y2: connectHipLine.y2, line: connectHipLine })
+ } else {
+ const firstHipPoint = [currentRoof.x1, currentRoof.y1, currentMidX.toNumber(), currentMidY.toNumber()]
+ const secondHipPoint = [currentRoof.x2, currentRoof.y2, currentMidX.toNumber(), currentMidY.toNumber()]
+ const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, null, prevDegree, prevDegree)
+ const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, null, nextDegree, nextDegree)
+ baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine })
+ baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine })
+ }
+
/** 마루가 맞은편 외벽선에 닿는 경우 해당 부분까지로 한정한다. */
const ridgeEdge = {
vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
@@ -1546,14 +2035,16 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}
}
})
- const ridgeLine = drawRidgeLine(
- [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()],
- canvas,
- roof,
- textMode,
- )
- baseGableRidgeLines.push(ridgeLine)
- baseRidgeCount++
+ if (baseRidgeCount < getMaxRidge(baseLines.length)) {
+ const ridgeLine = drawRidgeLine(
+ [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()],
+ canvas,
+ roof,
+ textMode,
+ )
+ baseGableRidgeLines.push(ridgeLine)
+ baseRidgeCount++
+ }
}
}
})
@@ -1565,12 +2056,19 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const prevLine = prevBaseLine.line
const nextLine = nextBaseLine.line
+ const checkLine = new fabric.Line([currentLine.x1, currentLine.y1, currentLine.x2, currentLine.y2], {
+ stroke: 'red',
+ strokeWidth: 4,
+ parentId: roofId,
+ name: 'checkLine',
+ })
+ canvas.add(checkLine)
+ canvas.renderAll()
+
/** 이전 라인의 경사 */
- const prevDegree = prevLine.attributes.pitch > 0 ? getDegreeByChon(prevLine.attributes.pitch) : prevLine.attributes.degree
+ const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
/** 다음 라인의 경사 */
- const nextDegree = nextLine.attributes.pitch > 0 ? getDegreeByChon(nextLine.attributes.pitch) : nextLine.attributes.degree
- /** 현재 라인의 경사 */
- const currentDegree = currentLine.attributes.pitch > 0 ? getDegreeByChon(currentLine.attributes.pitch) : currentLine.attributes.degree
+ const nextDegree = getDegreeByChon(nextLine.attributes.pitch)
const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint)
const currentVectorX = Big(currentLine.x2).minus(currentLine.x1)
@@ -1581,11 +2079,63 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2)
const checkSize = Big(10)
- const checkPoints = {
- x: currentMidX.plus(checkSize.times(Math.sign(checkVectorX.toNumber()))).toNumber(),
- y: currentMidY.plus(checkSize.times(Math.sign(checkVectorY.toNumber()))).toNumber(),
+ /** 현재 라인의 지붕선을 찾는다. */
+ const intersectionRoofs = []
+ if (currentVectorX.eq(0)) {
+ const checkEdge = {
+ vertex1: { x: prevLine.x1, y: currentMidY.toNumber() },
+ vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
+ }
+ roof.lines
+ .filter(
+ (line) =>
+ Math.sign(line.x2 - line.x1) === Math.sign(currentVectorX.toNumber()) &&
+ Math.sign(line.y2 - line.y1) === Math.sign(currentVectorY.toNumber()),
+ )
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber(),
+ })
+ }
+ }
+ })
+ } else {
+ const checkEdge = {
+ vertex1: { x: currentMidX.toNumber(), y: prevLine.y1 },
+ vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
+ }
+ roof.lines
+ .filter(
+ (line) =>
+ Math.sign(line.x2 - line.x1) === Math.sign(currentVectorX.toNumber()) &&
+ Math.sign(line.y2 - line.y1) === Math.sign(currentVectorY.toNumber()),
+ )
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber(),
+ })
+ }
+ }
+ })
}
- if (!checkWallPolygon.inPolygon(checkPoints)) {
+ let currentRoof
+ if (intersectionRoofs.length > 0) {
+ currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line
+ }
+
+ if (currentLine.attributes.type === LINE_TYPE.WALLLINE.EAVES || currentLine.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) {
const currentMidEdge = {
vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
vertex2: {
@@ -1593,16 +2143,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
y: currentMidY.plus(checkSize.times(Math.sign(checkVectorY.neg().toNumber()))).toNumber(),
},
}
-
let oppositeLines = []
baseLines
- .filter((line, index) => {
- let nextLine = baseLines[(index + 1) % baseLines.length]
- let prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
- if (
- (gableType.includes(nextLine.attributes.type) && gableType.includes(prevLine.attributes.type)) ||
- (eavesType.includes(nextLine.attributes.type) && eavesType.includes(prevLine.attributes.type))
- ) {
+ .filter((line) => {
+ if (eavesType.includes(line.attributes.type)) {
const angle = calculateAngle(line.startPoint, line.endPoint)
switch (currentAngle) {
case 90:
@@ -1613,9 +2157,12 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
return angle === 180
case 180:
return angle === 0
+ default:
+ return false
}
+ } else {
+ return false
}
- return false
})
.forEach((line) => {
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
@@ -1632,207 +2179,297 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
if (oppositeLines.length === 0) {
return
}
- const oppositeLine = oppositeLines.sort((a, b) => a.size - b.size)[0]
+ const oppositeLine = oppositeLines.sort((a, b) => b.size - a.size)[0].line
- let points = []
- if (eavesType.includes(oppositeLine.line.attributes.type)) {
- const oppositeCurrentLine = oppositeLine.line
- let oppositePrevLine, oppositeNextLine
- baseLines.forEach((line, index) => {
- if (line === oppositeCurrentLine) {
- oppositePrevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
- oppositeNextLine = baseLines[(index + 1) % baseLines.length]
- }
- })
- if (gableType.includes(oppositeNextLine.attributes.type) && gableType.includes(oppositePrevLine.attributes.type)) {
- if (currentVectorX.eq(0)) {
- const centerX = currentMidX.plus(oppositeLine.intersection.x).div(2).toNumber()
- points = [centerX, currentLine.y1, centerX, currentLine.y2]
- } else {
- const centerY = currentMidY.plus(oppositeLine.intersection.y).div(2).toNumber()
- points = [currentLine.x1, centerY, currentLine.x2, centerY]
- }
- }
- if (eavesType.includes(oppositeNextLine.attributes.type) && eavesType.includes(oppositePrevLine.attributes.type)) {
- /** 이전, 다음라인의 사잇각의 vector를 구한다. */
- let prevVector = getHalfAngleVector(oppositePrevLine, oppositeCurrentLine)
- let nextVector = getHalfAngleVector(oppositeCurrentLine, oppositeNextLine)
-
- let prevHipVector = { x: Big(prevVector.x), y: Big(prevVector.y) }
- let nextHipVector = { x: Big(nextVector.x), y: Big(nextVector.y) }
-
- /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
- const prevCheckPoint = {
- x: Big(oppositeCurrentLine.x1).plus(Big(prevHipVector.x).times(10)),
- y: Big(oppositeCurrentLine.y1).plus(Big(prevHipVector.y).times(10)),
- }
- if (!checkWallPolygon.inPolygon(prevCheckPoint)) {
- prevHipVector = { x: Big(prevHipVector.x).neg(), y: Big(prevHipVector.y).neg() }
- }
-
- /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
- const nextCheckPoint = {
- x: Big(oppositeCurrentLine.x2).plus(Big(nextHipVector.x).times(10)),
- y: Big(oppositeCurrentLine.y2).plus(Big(nextHipVector.y).times(10)),
- }
- if (!checkWallPolygon.inPolygon(nextCheckPoint)) {
- nextHipVector = { x: Big(nextHipVector.x).neg(), y: Big(nextHipVector.y).neg() }
- }
-
- /** 현재 라인의 길이를 기준으로 추녀 마루의 길이를 삼각함수를 사용하여 판단한다.*/
- let hipLength = Big(oppositeCurrentLine.attributes.planeSize)
- .div(2)
- .pow(2)
- .plus(Big(oppositeCurrentLine.attributes.planeSize).div(2).pow(2))
- .sqrt()
- .div(10)
- .round(2)
-
- const ridgeEndPoint = {
- x: Big(oppositeCurrentLine.x1).plus(hipLength.times(prevHipVector.x)).round(1),
- y: Big(oppositeCurrentLine.y1).plus(hipLength.times(prevHipVector.y)).round(1),
- }
-
- const prevHypotenuse = Big(oppositePrevLine.attributes.offset).pow(2).plus(Big(oppositeCurrentLine.attributes.offset).pow(2)).sqrt()
- const prevHipPoints = {
- x1: Big(oppositeCurrentLine.x1).plus(prevHypotenuse.times(prevHipVector.x.neg())).round(1).toNumber(),
- y1: Big(oppositeCurrentLine.y1).plus(prevHypotenuse.times(prevHipVector.y.neg())).round(1).toNumber(),
- x2: ridgeEndPoint.x.toNumber(),
- y2: ridgeEndPoint.y.toNumber(),
- }
-
- const nextHypotenuse = Big(oppositeNextLine.attributes.offset).pow(2).plus(Big(oppositeCurrentLine.attributes.offset).pow(2)).sqrt()
- const nextHipPoints = {
- x1: Big(oppositeCurrentLine.x2).plus(nextHypotenuse.times(nextHipVector.x.neg())).round(1).toNumber(),
- y1: Big(oppositeCurrentLine.y2).plus(nextHypotenuse.times(nextHipVector.y.neg())).round(1).toNumber(),
- x2: ridgeEndPoint.x.toNumber(),
- y2: ridgeEndPoint.y.toNumber(),
- }
-
- const prevIntersection = findRoofIntersection(roof, prevHipPoints, ridgeEndPoint)
- const nextIntersection = findRoofIntersection(roof, nextHipPoints, ridgeEndPoint)
-
- if (prevIntersection) {
- const prevHip = drawHipLine(
- [prevIntersection.intersection.x, prevIntersection.intersection.y, ridgeEndPoint.x.toNumber(), ridgeEndPoint.y.toNumber()],
- canvas,
- roof,
- textMode,
- null,
- prevDegree,
- prevDegree,
- )
- baseHipLines.push({
- x1: oppositeCurrentLine.x1,
- y1: oppositeCurrentLine.y1,
- x2: ridgeEndPoint.x,
- y2: ridgeEndPoint.y,
- line: prevHip,
- })
- }
- if (nextIntersection) {
- const nextHip = drawHipLine(
- [nextIntersection.intersection.x, nextIntersection.intersection.y, ridgeEndPoint.x.toNumber(), ridgeEndPoint.y.toNumber()],
- canvas,
- roof,
- textMode,
- null,
- nextDegree,
- nextDegree,
- )
- baseHipLines.push({
- x1: ridgeEndPoint.x,
- y1: ridgeEndPoint.y,
- x2: oppositeCurrentLine.x2,
- y2: oppositeCurrentLine.y2,
- line: nextHip,
- })
- }
-
- const ridgeVectorX = Math.sign(currentMidX.minus(ridgeEndPoint.x).toNumber())
- const ridgeVectorY = Math.sign(currentMidY.minus(ridgeEndPoint.y).toNumber())
- const ridgePoints = {
- x1: currentMidX.plus(Big(currentLine.attributes.offset).times(ridgeVectorX)).toNumber(),
- y1: currentMidY.plus(Big(currentLine.attributes.offset).times(ridgeVectorY)).toNumber(),
- x2: ridgeEndPoint.x.toNumber(),
- y2: ridgeEndPoint.y.toNumber(),
- }
- const ridgeIntersection = findRoofIntersection(roof, ridgePoints, {
- x: Big(ridgePoints.x2),
- y: Big(ridgePoints.y2),
- })
- if (ridgeIntersection) {
- points = [ridgeIntersection.intersection.x, ridgeIntersection.intersection.y, ridgeEndPoint.x, ridgeEndPoint.y]
- }
- }
+ let ridgePoint
+ if (currentVectorY.eq(0)) {
+ const ridgeY = Big(currentLine.y1).plus(Big(oppositeLine.y1)).div(2).round()
+ ridgePoint = [currentRoof.x1, ridgeY.toNumber(), currentRoof.x2, ridgeY.toNumber()]
} else {
- if (currentVectorX.eq(0)) {
- points = [oppositeLine.intersection.x, currentLine.y1, oppositeLine.intersection.x, currentLine.y2]
- } else {
- points = [currentLine.x1, oppositeLine.intersection.y, currentLine.x2, oppositeLine.intersection.y]
- }
+ const ridgeX = Big(currentLine.x1).plus(Big(oppositeLine.x1)).div(2).round()
+ ridgePoint = [ridgeX.toNumber(), currentRoof.y1, ridgeX.toNumber(), currentRoof.y2]
}
-
- if (baseRidgeCount < getMaxRidge(baseLines.length)) {
- const ridgeLine = drawRidgeLine(points, canvas, roof, textMode)
+ const isAlreadyRidge = baseGableRidgeLines.find(
+ (line) =>
+ (line.x1 === ridgePoint[0] && line.y1 === ridgePoint[1] && line.x2 === ridgePoint[2] && line.y2 === ridgePoint[3]) ||
+ (line.x1 === ridgePoint[2] && line.y1 === ridgePoint[3] && line.x2 === ridgePoint[0] && line.y2 === ridgePoint[1]),
+ )
+ if (baseRidgeCount < getMaxRidge(baseLines.length) && !isAlreadyRidge) {
+ const ridgeLine = drawRidgeLine(ridgePoint, canvas, roof, textMode)
baseGableRidgeLines.push(ridgeLine)
baseRidgeCount++
}
} else {
- const oppositeLines = baseLines.filter((line) => {
- const lineAngle = calculateAngle(line.startPoint, line.endPoint)
- switch (currentAngle) {
- case 90:
- return lineAngle === -90
- case -90:
- return lineAngle === 90
- case 0:
- return lineAngle === 180
- case 180:
- return lineAngle === 0
+ const checkPoints = {
+ x: currentMidX.plus(checkSize.times(Math.sign(checkVectorX.toNumber()))).toNumber(),
+ y: currentMidY.plus(checkSize.times(Math.sign(checkVectorY.toNumber()))).toNumber(),
+ }
+ if (!checkWallPolygon.inPolygon(checkPoints)) {
+ const currentMidEdge = {
+ vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
+ vertex2: {
+ x: currentMidX.plus(checkSize.times(Math.sign(checkVectorX.neg().toNumber()))).toNumber(),
+ y: currentMidY.plus(checkSize.times(Math.sign(checkVectorY.neg().toNumber()))).toNumber(),
+ },
}
- })
- if (oppositeLines.length > 0 && baseRidgeCount < getMaxRidge(baseLines.length)) {
- let ridgePoints = []
- const oppositeLine = oppositeLines.sort((a, b) => {
- let diffCurrentA, diffCurrentB
- if (Math.sign(currentVectorX) === 0) {
- diffCurrentA = currentMidY.minus(a.y1).abs()
- diffCurrentB = currentMidY.minus(b.y1).abs()
- } else {
- diffCurrentA = currentMidX.minus(a.x1).abs()
- diffCurrentB = currentMidX.minus(b.x1).abs()
+ let oppositeLines = []
+ baseLines
+ .filter((line, index) => {
+ let nextLine = baseLines[(index + 1) % baseLines.length]
+ let prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
+ if (
+ (gableType.includes(nextLine.attributes.type) && gableType.includes(prevLine.attributes.type)) ||
+ (eavesType.includes(nextLine.attributes.type) && eavesType.includes(prevLine.attributes.type))
+ ) {
+ const angle = calculateAngle(line.startPoint, line.endPoint)
+ switch (currentAngle) {
+ case 90:
+ return angle === -90
+ case -90:
+ return angle === 90
+ case 0:
+ return angle === 180
+ case 180:
+ return angle === 0
+ }
+ }
+ return false
+ })
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(currentMidEdge, lineEdge)
+ if (intersection) {
+ oppositeLines.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ })
+
+ if (oppositeLines.length === 0) {
+ return
+ }
+ const oppositeLine = oppositeLines.sort((a, b) => a.size - b.size)[0]
+
+ let points = []
+ if (eavesType.includes(oppositeLine.line.attributes.type)) {
+ const oppositeCurrentLine = oppositeLine.line
+ let oppositePrevLine, oppositeNextLine
+ baseLines.forEach((line, index) => {
+ if (line === oppositeCurrentLine) {
+ oppositePrevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
+ oppositeNextLine = baseLines[(index + 1) % baseLines.length]
+ }
+ })
+ if (gableType.includes(oppositeNextLine.attributes.type) && gableType.includes(oppositePrevLine.attributes.type)) {
+ if (currentVectorX.eq(0)) {
+ const centerX = currentMidX.plus(oppositeLine.intersection.x).div(2).toNumber()
+ points = [centerX, currentLine.y1, centerX, currentLine.y2]
+ } else {
+ const centerY = currentMidY.plus(oppositeLine.intersection.y).div(2).toNumber()
+ points = [currentLine.x1, centerY, currentLine.x2, centerY]
+ }
}
- return diffCurrentA.minus(diffCurrentB).toNumber()
- })[0]
+ if (eavesType.includes(oppositeNextLine.attributes.type) && eavesType.includes(oppositePrevLine.attributes.type)) {
+ /** 이전, 다음라인의 사잇각의 vector를 구한다. */
+ let prevVector = getHalfAngleVector(oppositePrevLine, oppositeCurrentLine)
+ let nextVector = getHalfAngleVector(oppositeCurrentLine, oppositeNextLine)
- const prevOffset = prevLine.attributes.offset
- const nextOffset = nextLine.attributes.offset
- if (Math.sign(currentVectorX) === 0) {
- const prevY = Big(currentLine.y1)
- .plus(Big(Math.sign(currentVectorY)).neg().times(prevOffset))
- .toNumber()
- const nextY = Big(currentLine.y2)
- .plus(Big(Math.sign(currentVectorY)).times(nextOffset))
- .toNumber()
- const midX = Big(currentLine.x1).plus(oppositeLine.x1).div(2).toNumber()
- ridgePoints = [midX, prevY, midX, nextY]
+ let prevHipVector = { x: Big(prevVector.x), y: Big(prevVector.y) }
+ let nextHipVector = { x: Big(nextVector.x), y: Big(nextVector.y) }
+
+ /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
+ const prevCheckPoint = {
+ x: Big(oppositeCurrentLine.x1).plus(Big(prevHipVector.x).times(10)),
+ y: Big(oppositeCurrentLine.y1).plus(Big(prevHipVector.y).times(10)),
+ }
+ if (!checkWallPolygon.inPolygon(prevCheckPoint)) {
+ prevHipVector = { x: Big(prevHipVector.x).neg(), y: Big(prevHipVector.y).neg() }
+ }
+
+ /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
+ const nextCheckPoint = {
+ x: Big(oppositeCurrentLine.x2).plus(Big(nextHipVector.x).times(10)),
+ y: Big(oppositeCurrentLine.y2).plus(Big(nextHipVector.y).times(10)),
+ }
+ if (!checkWallPolygon.inPolygon(nextCheckPoint)) {
+ nextHipVector = { x: Big(nextHipVector.x).neg(), y: Big(nextHipVector.y).neg() }
+ }
+
+ /** 현재 라인의 길이를 기준으로 추녀 마루의 길이를 삼각함수를 사용하여 판단한다.*/
+ let hipLength = Big(oppositeCurrentLine.attributes.planeSize)
+ .div(2)
+ .pow(2)
+ .plus(Big(oppositeCurrentLine.attributes.planeSize).div(2).pow(2))
+ .sqrt()
+ .div(10)
+ .round(2)
+
+ const ridgeEndPoint = {
+ x: Big(oppositeCurrentLine.x1).plus(hipLength.times(prevHipVector.x)).round(1),
+ y: Big(oppositeCurrentLine.y1).plus(hipLength.times(prevHipVector.y)).round(1),
+ }
+
+ const prevHypotenuse = Big(oppositePrevLine.attributes.offset).pow(2).plus(Big(oppositeCurrentLine.attributes.offset).pow(2)).sqrt()
+ const prevHipPoints = {
+ x1: Big(oppositeCurrentLine.x1).plus(prevHypotenuse.times(prevHipVector.x.neg())).round(1).toNumber(),
+ y1: Big(oppositeCurrentLine.y1).plus(prevHypotenuse.times(prevHipVector.y.neg())).round(1).toNumber(),
+ x2: ridgeEndPoint.x.toNumber(),
+ y2: ridgeEndPoint.y.toNumber(),
+ }
+
+ const nextHypotenuse = Big(oppositeNextLine.attributes.offset).pow(2).plus(Big(oppositeCurrentLine.attributes.offset).pow(2)).sqrt()
+ const nextHipPoints = {
+ x1: Big(oppositeCurrentLine.x2).plus(nextHypotenuse.times(nextHipVector.x.neg())).round(1).toNumber(),
+ y1: Big(oppositeCurrentLine.y2).plus(nextHypotenuse.times(nextHipVector.y.neg())).round(1).toNumber(),
+ x2: ridgeEndPoint.x.toNumber(),
+ y2: ridgeEndPoint.y.toNumber(),
+ }
+
+ const prevIntersection = findRoofIntersection(roof, prevHipPoints, ridgeEndPoint)
+ const nextIntersection = findRoofIntersection(roof, nextHipPoints, ridgeEndPoint)
+
+ if (prevIntersection) {
+ const prevHip = drawHipLine(
+ [prevIntersection.intersection.x, prevIntersection.intersection.y, ridgeEndPoint.x.toNumber(), ridgeEndPoint.y.toNumber()],
+ canvas,
+ roof,
+ textMode,
+ null,
+ prevDegree,
+ prevDegree,
+ )
+ baseHipLines.push({
+ x1: oppositeCurrentLine.x1,
+ y1: oppositeCurrentLine.y1,
+ x2: ridgeEndPoint.x,
+ y2: ridgeEndPoint.y,
+ line: prevHip,
+ })
+ }
+ if (nextIntersection) {
+ const nextHip = drawHipLine(
+ [nextIntersection.intersection.x, nextIntersection.intersection.y, ridgeEndPoint.x.toNumber(), ridgeEndPoint.y.toNumber()],
+ canvas,
+ roof,
+ textMode,
+ null,
+ nextDegree,
+ nextDegree,
+ )
+ baseHipLines.push({
+ x1: ridgeEndPoint.x,
+ y1: ridgeEndPoint.y,
+ x2: oppositeCurrentLine.x2,
+ y2: oppositeCurrentLine.y2,
+ line: nextHip,
+ })
+ }
+
+ const ridgeVectorX = Math.sign(currentMidX.minus(ridgeEndPoint.x).toNumber())
+ const ridgeVectorY = Math.sign(currentMidY.minus(ridgeEndPoint.y).toNumber())
+ const ridgePoints = {
+ x1: currentMidX.plus(Big(currentLine.attributes.offset).times(ridgeVectorX)).toNumber(),
+ y1: currentMidY.plus(Big(currentLine.attributes.offset).times(ridgeVectorY)).toNumber(),
+ x2: ridgeEndPoint.x.toNumber(),
+ y2: ridgeEndPoint.y.toNumber(),
+ }
+ const ridgeIntersection = findRoofIntersection(roof, ridgePoints, {
+ x: Big(ridgePoints.x2),
+ y: Big(ridgePoints.y2),
+ })
+ if (ridgeIntersection) {
+ points = [ridgeIntersection.intersection.x, ridgeIntersection.intersection.y, ridgeEndPoint.x, ridgeEndPoint.y]
+ }
+ }
} else {
- const prevX = Big(currentLine.x1)
- .plus(Big(Math.sign(currentVectorX)).neg().times(prevOffset))
- .toNumber()
- const nextX = Big(currentLine.x2)
- .plus(Big(Math.sign(currentVectorX)).times(nextOffset))
- .toNumber()
- const midY = Big(currentLine.y1).plus(oppositeLine.y1).div(2).toNumber()
- ridgePoints = [prevX, midY, nextX, midY]
+ if (currentVectorX.eq(0)) {
+ points = [oppositeLine.intersection.x, currentLine.y1, oppositeLine.intersection.x, currentLine.y2]
+ } else {
+ points = [currentLine.x1, oppositeLine.intersection.y, currentLine.x2, oppositeLine.intersection.y]
+ }
+ }
+
+ const isAlreadyRidge = baseGableRidgeLines.find(
+ (line) =>
+ (line.x1 === points[0] && line.y1 === points[1] && line.x2 === points[2] && line.y2 === points[3]) ||
+ (line.x1 === points[2] && line.y1 === points[3] && line.x2 === points[0] && line.y2 === points[1]),
+ )
+ if (baseRidgeCount < getMaxRidge(baseLines.length) && !isAlreadyRidge) {
+ const ridgeLine = drawRidgeLine(points, canvas, roof, textMode)
+ baseGableRidgeLines.push(ridgeLine)
+ baseRidgeCount++
+ }
+ } else {
+ const oppositeLines = baseLines.filter((line) => {
+ const lineAngle = calculateAngle(line.startPoint, line.endPoint)
+ switch (currentAngle) {
+ case 90:
+ return lineAngle === -90
+ case -90:
+ return lineAngle === 90
+ case 0:
+ return lineAngle === 180
+ case 180:
+ return lineAngle === 0
+ }
+ })
+
+ if (oppositeLines.length > 0 && baseRidgeCount < getMaxRidge(baseLines.length)) {
+ let ridgePoints = []
+ const oppositeLine = oppositeLines.sort((a, b) => {
+ let diffCurrentA, diffCurrentB
+ if (Math.sign(currentVectorX) === 0) {
+ diffCurrentA = currentMidY.minus(a.y1).abs()
+ diffCurrentB = currentMidY.minus(b.y1).abs()
+ } else {
+ diffCurrentA = currentMidX.minus(a.x1).abs()
+ diffCurrentB = currentMidX.minus(b.x1).abs()
+ }
+ return diffCurrentA.minus(diffCurrentB).toNumber()
+ })[0]
+
+ const prevOffset = prevLine.attributes.offset
+ const nextOffset = nextLine.attributes.offset
+ if (Math.sign(currentVectorX) === 0) {
+ const prevY = Big(currentLine.y1)
+ .plus(Big(Math.sign(currentVectorY)).neg().times(prevOffset))
+ .toNumber()
+ const nextY = Big(currentLine.y2)
+ .plus(Big(Math.sign(currentVectorY)).times(nextOffset))
+ .toNumber()
+ const midX = Big(currentLine.x1).plus(oppositeLine.x1).div(2).toNumber()
+ ridgePoints = [midX, prevY, midX, nextY]
+ } else {
+ const prevX = Big(currentLine.x1)
+ .plus(Big(Math.sign(currentVectorX)).neg().times(prevOffset))
+ .toNumber()
+ const nextX = Big(currentLine.x2)
+ .plus(Big(Math.sign(currentVectorX)).times(nextOffset))
+ .toNumber()
+ const midY = Big(currentLine.y1).plus(oppositeLine.y1).div(2).toNumber()
+ ridgePoints = [prevX, midY, nextX, midY]
+ }
+ const isAlreadyRidge = baseGableRidgeLines.find(
+ (line) =>
+ (line.x1 === ridgePoints[0] && line.y1 === ridgePoints[1] && line.x2 === ridgePoints[2] && line.y2 === ridgePoints[3]) ||
+ (line.x1 === ridgePoints[2] && line.y1 === ridgePoints[3] && line.x2 === ridgePoints[0] && line.y2 === ridgePoints[1]),
+ )
+ if (!isAlreadyRidge) {
+ const ridge = drawRidgeLine(ridgePoints, canvas, roof, textMode)
+ baseGableRidgeLines.push(ridge)
+ baseRidgeCount++
+ }
}
- const ridge = drawRidgeLine(ridgePoints, canvas, roof, textMode)
- baseGableRidgeLines.push(ridge)
- baseRidgeCount++
}
}
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'checkLine' || obj.name === 'checkCircle')
+ .forEach((obj) => canvas.remove(obj))
+ canvas.renderAll()
})
const uniqueRidgeLines = []
@@ -1854,23 +2491,21 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
baseGableRidgeLines = uniqueRidgeLines
+ console.log('baseGableRidgeLines : ', baseGableRidgeLines)
+
/** 박공지붕 polygon 생성 */
drawGablePolygonFirst.forEach((current) => {
const { currentBaseLine, prevBaseLine, nextBaseLine } = current
const currentLine = currentBaseLine.line
const prevLine = prevBaseLine.line
const nextLine = nextBaseLine.line
- let { x1, x2, y1, y2 } = currentBaseLine
- let prevLineRidges = [],
- nextLineRidges = []
const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1)
const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1)
const nextVectorX = Math.sign(nextLine.x1 - nextLine.x2)
const nextVectorY = Math.sign(nextLine.y1 - nextLine.y2)
- const currentDegree = currentLine.attributes.pitch > 0 ? getDegreeByChon(currentLine.attributes.pitch) : currentLine.attributes.degree
+ const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
- let roofX1, roofY1, roofX2, roofY2
const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2)
const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2)
const intersectionRoofs = []
@@ -1915,258 +2550,215 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}
})
}
+ let currentRoof, prevRoof, nextRoof
if (intersectionRoofs.length > 0) {
- const currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line
- roofX1 = Big(currentRoof.x1)
- roofY1 = Big(currentRoof.y1)
- roofX2 = Big(currentRoof.x2)
- roofY2 = Big(currentRoof.y2)
+ currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line
}
- let prevRoofLine, nextRoofLine
+ if (currentRoof) {
+ prevRoof = roof.lines.find((line) => line.x2 === currentRoof.x1 && line.y2 === currentRoof.y1)
+ nextRoof = roof.lines.find((line) => line.x1 === currentRoof.x2 && line.y1 === currentRoof.y2)
- roof.lines
- .filter((line) => (currentVectorX === 0 ? line.y1 === line.y2 : line.x1 === line.x2))
- .forEach((line) => {
- if (
- (roofX1.minus(line.x1).abs().lte(1) && roofY1.minus(line.y1).abs().lte(1)) ||
- (roofX1.minus(line.x2).abs().lte(1) && roofY1.minus(line.y2).abs().lte(1))
- ) {
- prevRoofLine = line
- }
- if (
- (roofX2.minus(line.x1).abs().lte(1) && roofY2.minus(line.y1).abs().lte(1)) ||
- (roofX2.minus(line.x2).abs().lte(1) && roofY2.minus(line.y2).abs().lte(1))
- ) {
- nextRoofLine = line
- }
- })
- const prevRoofEdge = {
- vertex1: { x: prevRoofLine.x2, y: prevRoofLine.y2 },
- vertex2: { x: prevRoofLine.x1, y: prevRoofLine.y1 },
- }
- const nextRoofEdge = {
- vertex1: { x: nextRoofLine.x1, y: nextRoofLine.y1 },
- vertex2: { x: nextRoofLine.x2, y: nextRoofLine.y2 },
- }
-
- baseGableRidgeLines.forEach((ridge) => {
- const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }
- const prevIs = edgesIntersection(prevRoofEdge, ridgeEdge)
- const nextIs = edgesIntersection(nextRoofEdge, ridgeEdge)
- if (
- prevIs &&
- ((Math.abs(ridgeEdge.vertex1.x - prevIs.x) < 1 && Math.abs(ridgeEdge.vertex1.y - prevIs.y) < 1) ||
- (Math.abs(ridgeEdge.vertex2.x - prevIs.x) < 1 && Math.abs(ridgeEdge.vertex2.y - prevIs.y) < 1))
- ) {
- prevLineRidges.push({
- ridge,
- size: calcLinePlaneSize({ x1: roofX1, y1: roofY1, x2: prevIs.x, y2: prevIs.y }),
- })
+ const prevRoofEdge = {
+ vertex1: { x: prevRoof.x2, y: prevRoof.y2 },
+ vertex2: { x: prevRoof.x1, y: prevRoof.y1 },
+ }
+ const nextRoofEdge = {
+ vertex1: { x: nextRoof.x1, y: nextRoof.y1 },
+ vertex2: { x: nextRoof.x2, y: nextRoof.y2 },
}
- if (
- nextIs &&
- ((Math.abs(ridgeEdge.vertex1.x - nextIs.x) < 1 && Math.abs(ridgeEdge.vertex1.y - nextIs.y) < 1) ||
- (Math.abs(ridgeEdge.vertex2.x - nextIs.x) < 1 && Math.abs(ridgeEdge.vertex2.y - nextIs.y) < 1))
- ) {
- nextLineRidges.push({
- ridge,
- size: calcLinePlaneSize({ x1: roofX2, y1: roofY2, x2: nextIs.x, y2: nextIs.y }),
- })
- }
- })
-
- const polygonPoints = []
-
- let prevLineRidge, nextLineRidge
- if (prevLineRidges.length > 0) {
- prevLineRidges = prevLineRidges
- .filter((line) => {
- const ridge = line.ridge
- if (currentVectorX === 0) {
- return ridge.y1 === roofY1.toNumber() || ridge.y2 === roofY1.toNumber()
- } else {
- return ridge.x1 === roofX1.toNumber() || ridge.x2 === roofX1.toNumber()
- }
- })
- .sort((a, b) => a.size - b.size)
- prevLineRidge = prevLineRidges[0].ridge
- }
- if (nextLineRidges.length > 0) {
- nextLineRidges = nextLineRidges
- .filter((line) => {
- const ridge = line.ridge
- if (currentVectorX === 0) {
- return ridge.y1 === roofY2.toNumber() || ridge.y2 === roofY2.toNumber()
- } else {
- return ridge.x1 === roofX2.toNumber() || ridge.x2 === roofX2.toNumber()
- }
- })
- .sort((a, b) => a.size - b.size)
- nextLineRidge = nextLineRidges[0].ridge
- }
- const ridgeLine = prevLineRidge === undefined ? nextLineRidge : prevLineRidge
-
- /** 마루선이 한쪽만 존재 연결될 경우 다각형을 그린다.*/
- if (prevLineRidge === undefined || nextLineRidge === undefined) {
- const points = [
- { x: roofX1.toNumber(), y: roofY1.toNumber() },
- { x: roofX2.toNumber(), y: roofY2.toNumber() },
- { x: ridgeLine.x1, y: ridgeLine.y1 },
- { x: ridgeLine.x2, y: ridgeLine.y2 },
+ let polygonPoints = [
+ { x: currentRoof.x1, y: currentRoof.y1 },
+ { x: currentRoof.x2, y: currentRoof.y2 },
]
- const minX = Math.min(ridgeLine.x1, ridgeLine.x2, roofX1.toNumber(), roofX2.toNumber())
- const minY = Math.min(ridgeLine.y1, ridgeLine.y2, roofY1.toNumber(), roofY2.toNumber())
+ const prevHipLines = []
+ const nextHipLine = []
+ let prevLineRidge, nextLineRidge
- let polygonPoints = []
-
- polygonPoints.push(points.find((point) => point.x === minX && point.y === minY))
-
- let i = 0
- let length = points.length
- while (i < length - 1) {
- const currentPoint = polygonPoints[i]
- if (i === 0) {
- polygonPoints.push(points.find((point) => point.x === currentPoint.x && point.y > currentPoint.y))
- i++
- } else {
- const prevPoint = polygonPoints[(i - 1 + polygonPoints.length) % polygonPoints.length]
- const vectorX = Math.sign(prevPoint.x - currentPoint.x)
- const vectorY = Math.sign(prevPoint.y - currentPoint.y)
- if (i % 2 === 1) {
- /** 가로선 찾기 */
- const nextPoint = points.find((point) => point.y === currentPoint.y && point.x !== currentPoint.x)
- if (nextPoint === undefined) {
- const connectLine = roof.lines.find((line) => line.y1 === line.y2 && line.x1 === currentPoint.x && line.y1 === currentPoint.y)
- if (connectLine) {
- polygonPoints.push(
- connectLine.x1 === currentPoint.x && connectLine.y1 === currentPoint.y
- ? { x: connectLine.x2, y: connectLine.y2 }
- : { x: connectLine.x1, y: connectLine.y1 },
- )
- } else {
- const intersectLine = roof.lines.find(
- (line) =>
- line.y1 === currentPoint.y &&
- line.y2 === currentPoint.y &&
- ((line.x1 <= currentPoint.x && line.x2 >= currentPoint.x) || (line.x2 <= currentPoint.x && line.x1 >= currentPoint.x)),
- )
- /** 이전 라인이 위에서 아래로 항하면 오른쪽 포인트 찾기*/
- if (vectorY === 1) {
- polygonPoints.push({ x: intersectLine.x1, y: intersectLine.y1 })
- }
- /** 이전 라인이 아래에서 위로 항하면 왼쪽 포인트 찾기*/
- if (vectorY === -1) {
- polygonPoints.push({ x: intersectLine.x2, y: intersectLine.y2 })
- }
- }
- length = length + 1
- } else {
- polygonPoints.push(nextPoint)
- }
- i++
- } else {
- /** 세로선 찾기*/
- const nextPoint = points.find((point) => point.x === currentPoint.x && point.y !== currentPoint.y)
- if (nextPoint === undefined) {
- const connectLine = roof.lines.find((line) => line.x1 === line.x2 && line.x1 === currentPoint.x && line.y1 === currentPoint.y)
- if (connectLine) {
- polygonPoints.push(
- connectLine.x1 === currentPoint.x && connectLine.y1 === currentPoint.y
- ? { x: connectLine.x2, y: connectLine.y2 }
- : { x: connectLine.x1, y: connectLine.y1 },
- )
- } else {
- const intersectLine = roof.lines.find(
- (line) =>
- line.x1 === currentPoint.x &&
- line.x2 === currentPoint.x &&
- ((line.y1 <= currentPoint.y && line.y2 >= currentPoint.y) || (line.y2 <= currentPoint.y && line.y1 >= currentPoint.y)),
- )
- /** 이전 라인이 왼쪽에서 오른쪽로 항하면 위쪽 포인트 찾기*/
- if (vectorX === -1) {
- polygonPoints.push({ x: intersectLine.x1, y: intersectLine.y1 })
- }
- /** 이전 라인이 오른에서 왼쪽으로 항하면 아래쪽 포인트 찾기*/
- if (vectorX === 1) {
- polygonPoints.push({ x: intersectLine.x2, y: intersectLine.y2 })
- }
- }
- length = length + 1
- } else {
- polygonPoints.push(nextPoint)
- }
- i++
- }
+ baseHipLines.forEach((current) => {
+ const { line } = current
+ if (
+ (Math.abs(line.x1 - currentRoof.x1) <= 1 &&
+ Math.abs(line.y1 - currentRoof.y1) <= 1 &&
+ isPointOnLine(prevRoof, { x: line.x2, y: line.y2 })) ||
+ (Math.abs(line.x2 - currentRoof.x1) <= 1 &&
+ Math.abs(line.y2 - currentRoof.y1) <= 1 &&
+ isPointOnLine(prevRoof, {
+ x: line.x1,
+ y: line.y1,
+ }))
+ ) {
+ prevHipLines.push(current)
}
- }
- polygonPoints = getSortedPoint(polygonPoints)
- polygonPoints.forEach((currentPoint, index) => {
- const nextPoint = polygonPoints[(index + 1) % polygonPoints.length]
- const points = [currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y]
- const isParallel = ridgeLine.x1 === ridgeLine.x2 ? currentPoint.x === nextPoint.x : currentPoint.y === nextPoint.y
-
- let line
- if (isParallel) {
- line = drawRoofLine(points, canvas, roof, textMode)
- baseGableLines.push(line)
- } else {
- line = drawHipLine(points, canvas, roof, textMode, null, currentDegree, currentDegree)
- baseHipLines.push({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2, line })
+ if (
+ (Math.abs(line.x1 - currentRoof.x2) <= 1 &&
+ Math.abs(line.y1 - currentRoof.y2) <= 1 &&
+ isPointOnLine(nextRoof, { x: line.x2, y: line.y2 })) ||
+ (Math.abs(line.x2 - currentRoof.x2) <= 1 &&
+ Math.abs(line.y2 - currentRoof.y2) <= 1 &&
+ isPointOnLine(nextRoof, {
+ x: line.x1,
+ y: line.y1,
+ }))
+ ) {
+ nextHipLine.push(current)
}
})
- } else {
- /** 마루에서 현재라인으로 향하는 외벽선까지의 포인트를 확인 하여 처리*/
- let checkEdge
- if (currentVectorX === 0) {
- checkEdge = {
- vertex1: { x: ridgeLine.x1, y: roofY1.toNumber() },
- vertex2: { x: roofX1.toNumber(), y: roofY1.toNumber() },
- }
- } else {
- checkEdge = {
- vertex1: { x: roofX1.toNumber(), y: ridgeLine.y1 },
- vertex2: { x: roofX1.toNumber(), y: roofY1.toNumber() },
- }
- }
- const checkVectorX = Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x)
- const checkVectorY = Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y)
- const intersectPoints = []
- roof.lines
- .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2))
- .forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const is = edgesIntersection(checkEdge, lineEdge)
- if (is) {
- const isVectorX = Math.sign(checkEdge.vertex1.x - is.x)
- const isVectorY = Math.sign(checkEdge.vertex1.y - is.y)
- const isLineOtherPoint =
- is.x === line.x1 && is.y === line.y1
- ? { x: line.x2, y: line.y2 }
- : {
- x: line.x1,
- y: line.y1,
- }
- const lineVectorX = Math.sign(isLineOtherPoint.x - is.x)
- const lineVectorY = Math.sign(isLineOtherPoint.y - is.y)
- if (checkVectorX === isVectorX && checkVectorY === isVectorY && lineVectorX === currentVectorX && lineVectorY === currentVectorY) {
- intersectPoints.push(is)
- }
+ prevHipLines.forEach((current) => {
+ if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ let findPoint
+ if (Math.abs(current.x1 - currentRoof.x1) <= 1 && Math.abs(current.y1 - currentRoof.y1) <= 1) {
+ findPoint = { x: current.x2, y: current.y2 }
+ } else {
+ findPoint = { x: current.x1, y: current.y1 }
+ }
+ baseHipLines
+ .filter(
+ (line) =>
+ ((Math.abs(line.x1 - findPoint.x) <= 1 && Math.abs(line.y1 - findPoint.y) <= 1) ||
+ (Math.abs(line.x2 - findPoint.x) <= 1 && Math.abs(line.y2 - findPoint.y) <= 1)) &&
+ line.x1 !== line.x2 &&
+ line.y1 !== line.y2,
+ )
+ .forEach((line) => {
+ polygonPoints.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 })
+ let ridgePoint
+ if (Math.abs(line.x1 - findPoint.x) <= 1 && Math.abs(line.y1 - findPoint.y) <= 1) {
+ ridgePoint = { x: line.x2, y: line.y2 }
+ } else {
+ ridgePoint = { x: line.x1, y: line.y1 }
+ }
+ prevLineRidge = baseGableRidgeLines.find(
+ (ridge) =>
+ (Math.abs(ridge.x1 - ridgePoint.x) <= 1 && Math.abs(ridge.y1 - ridgePoint.y) <= 1) ||
+ (Math.abs(ridge.x2 - ridgePoint.x) <= 1 && Math.abs(ridge.y2 - ridgePoint.y) <= 1),
+ )
+ })
+ } else {
+ let ridgePoint
+ if (Math.abs(current.x1 - currentRoof.x1) <= 1 && Math.abs(current.y1 - currentRoof.y1) <= 1) {
+ ridgePoint = { x: current.x2, y: current.y2 }
+ } else {
+ ridgePoint = { x: current.x1, y: current.y1 }
}
- })
- let intersect = intersectPoints[0]
- if (currentVectorX === 0) {
- polygonPoints.push({ x: intersect.x, y: roofY1.toNumber() }, { x: intersect.x, y: roofY2.toNumber() })
- } else {
- polygonPoints.push({ x: roofX1.toNumber(), y: intersect.y }, { x: roofX2.toNumber(), y: intersect.y })
+ prevLineRidge = baseGableRidgeLines.find((ridge) => {
+ return (
+ (Math.abs(ridge.x1 - ridgePoint.x) <= 1 && Math.abs(ridge.y1 - ridgePoint.y) <= 1) ||
+ (Math.abs(ridge.x2 - ridgePoint.x) <= 1 && Math.abs(ridge.y2 - ridgePoint.y) <= 1)
+ )
+ })
+ }
+ })
+ nextHipLine.forEach((current) => {
+ if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ let findPoint
+ if (Math.abs(current.x1 - currentRoof.x2) <= 1 && Math.abs(current.y1 - currentRoof.y2) <= 1) {
+ findPoint = { x: current.x2, y: current.y2 }
+ } else {
+ findPoint = { x: current.x1, y: current.y1 }
+ }
+
+ baseHipLines
+ .filter(
+ (line) =>
+ ((Math.abs(line.x1 - findPoint.x) <= 1 && Math.abs(line.y1 - findPoint.y) <= 1) ||
+ (Math.abs(line.x2 - findPoint.x) <= 1 && Math.abs(line.y2 - findPoint.y) <= 1)) &&
+ line.x1 !== line.x2 &&
+ line.y1 !== line.y2,
+ )
+ .forEach((line) => {
+ polygonPoints.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 })
+ let ridgePoint
+ if (Math.abs(line.x1 - findPoint.x) <= 1 && Math.abs(line.y1 - findPoint.y) <= 1) {
+ ridgePoint = { x: line.x2, y: line.y2 }
+ } else {
+ ridgePoint = { x: line.x1, y: line.y1 }
+ }
+ nextLineRidge = baseGableRidgeLines.find(
+ (ridge) =>
+ (Math.abs(ridge.x1 - ridgePoint.x) <= 1 && Math.abs(ridge.y1 - ridgePoint.y) <= 1) ||
+ (Math.abs(ridge.x2 - ridgePoint.x) <= 1 && Math.abs(ridge.y2 - ridgePoint.y) <= 1),
+ )
+ })
+ } else {
+ let ridgePoint
+ if (Math.abs(current.x1 - currentRoof.x2) <= 1 && Math.abs(current.y1 - currentRoof.y2) <= 1) {
+ ridgePoint = { x: current.x2, y: current.y2 }
+ } else {
+ ridgePoint = { x: current.x1, y: current.y1 }
+ }
+
+ nextLineRidge = baseGableRidgeLines.find(
+ (ridge) =>
+ (Math.abs(ridge.x1 - ridgePoint.x) <= 1 && Math.abs(ridge.y1 - ridgePoint.y) <= 1) ||
+ (Math.abs(ridge.x2 - ridgePoint.x) <= 1 && Math.abs(ridge.y2 - ridgePoint.y) <= 1),
+ )
+ }
+ })
+
+ if (!prevLineRidge) {
+ if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ } else {
+ const isRidgePoints = []
+ baseGableRidgeLines.forEach((ridge) => {
+ const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }
+ const intersection = edgesIntersection(prevRoofEdge, ridgeEdge)
+ if (
+ intersection &&
+ ((ridge.x1 <= intersection.x && intersection.x <= ridge.x2 && ridge.y1 <= intersection.y && intersection.y <= ridge.y2) ||
+ (ridge.x2 <= intersection.x && intersection.x <= ridge.x1 && ridge.y2 <= intersection.y && intersection.y <= ridge.y1))
+ ) {
+ const size = Big(intersection.x)
+ .minus(Big(currentRoof.x1))
+ .abs()
+ .pow(2)
+ .plus(Big(intersection.y).minus(Big(currentRoof.y1)).abs().pow(2))
+ .sqrt()
+ isRidgePoints.push({ intersection, ridge, size })
+ }
+ })
+ if (isRidgePoints.length > 0) {
+ const sortedRidgePoints = isRidgePoints.sort((a, b) => a.size - b.size)
+ prevLineRidge = sortedRidgePoints[0].ridge
+ }
+ }
}
+ if (!nextLineRidge) {
+ if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ } else {
+ const isRidgePoints = []
+ baseGableRidgeLines.forEach((ridge) => {
+ const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }
+ const intersection = edgesIntersection(nextRoofEdge, ridgeEdge)
+ if (
+ intersection &&
+ ((ridge.x1 <= intersection.x && intersection.x <= ridge.x2 && ridge.y1 <= intersection.y && intersection.y <= ridge.y2) ||
+ (ridge.x2 <= intersection.x && intersection.x <= ridge.x1 && ridge.y2 <= intersection.y && intersection.y <= ridge.y1))
+ ) {
+ const size = Big(intersection.x)
+ .minus(Big(currentRoof.x2))
+ .abs()
+ .pow(2)
+ .plus(Big(intersection.y).minus(Big(currentRoof.y2)).abs().pow(2))
+ .sqrt()
+ isRidgePoints.push({ intersection, ridge, size })
+ }
+ })
+ if (isRidgePoints.length > 0) {
+ const sortedRidgePoints = isRidgePoints.sort((a, b) => a.size - b.size)
+ nextLineRidge = sortedRidgePoints[0].ridge
+ }
+ }
+ }
+ const ridgeLine = prevLineRidge === undefined ? nextLineRidge : prevLineRidge
- if (prevLineRidge === nextLineRidge) {
+ if (prevLineRidge !== undefined && nextLineRidge !== undefined) {
/** 4각*/
- polygonPoints.push({ x: prevLineRidge.x1, y: prevLineRidge.y1 }, { x: prevLineRidge.x2, y: prevLineRidge.y2 })
- } else {
+ if (prevLineRidge === nextLineRidge) {
+ polygonPoints.push({ x: ridgeLine.x1, y: ridgeLine.y1 }, { x: ridgeLine.x2, y: ridgeLine.y2 })
+ }
/** 6각이상*/
let isOverLap =
currentVectorX === 0
@@ -2179,83 +2771,102 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
(prevLineRidge.x1 <= nextLineRidge.x2 && prevLineRidge.x2 >= nextLineRidge.x2) ||
(prevLineRidge.x1 >= nextLineRidge.x2 && prevLineRidge.x2 <= nextLineRidge.x2)
if (isOverLap) {
- const prevDistance = currentVectorX === 0 ? Math.abs(prevLineRidge.x1 - roofX1.toNumber()) : Math.abs(prevLineRidge.y1 - roofY1.toNumber())
- const nextDistance = currentVectorX === 0 ? Math.abs(nextLineRidge.x1 - roofX1.toNumber()) : Math.abs(nextLineRidge.y1 - roofY1.toNumber())
- /** 현재 지붕 라인과 먼 라인의 포인트를 온전히 사용한다. */
- if (prevDistance <= nextDistance) {
- polygonPoints.push(
- { x: nextLineRidge.x1, y: nextLineRidge.y1 },
- {
- x: nextLineRidge.x2,
- y: nextLineRidge.y2,
- },
- )
- /** 이전라인과 교차한 마루의 포인트*/
- const prevRidgePoint1 =
- currentVectorX === 0
- ? roofY1.toNumber() === prevLineRidge.y1
- ? { x: prevLineRidge.x1, y: prevLineRidge.y1 }
- : { x: prevLineRidge.x2, y: prevLineRidge.y2 }
- : roofX1.toNumber() === prevLineRidge.x1
- ? { x: prevLineRidge.x1, y: prevLineRidge.y1 }
- : { x: prevLineRidge.x2, y: prevLineRidge.y2 }
+ const prevDistance = currentVectorX === 0 ? Math.abs(prevLineRidge.x1 - currentRoof.x1) : Math.abs(prevLineRidge.y1 - currentRoof.y1)
+ const nextDistance = currentVectorX === 0 ? Math.abs(nextLineRidge.x1 - currentRoof.x1) : Math.abs(nextLineRidge.y1 - currentRoof.y1)
- polygonPoints.push(prevRidgePoint1)
+ /** 현재 지붕 라인과 먼 라인의 포인트를 온전히 사용한다. */
+ if (Math.abs(prevDistance - nextDistance) < 1) {
+ const minX = Math.min(currentRoof.x1, currentRoof.x2, currentLine.x1, currentLine.x2)
+ const maxX = Math.max(currentRoof.x1, currentRoof.x2, currentLine.x1, currentLine.x2)
+ const minY = Math.min(currentRoof.y1, currentRoof.y2, currentLine.y1, currentLine.y2)
+ const maxY = Math.max(currentRoof.y1, currentRoof.y2, currentLine.y1, currentLine.y2)
+ if (currentVectorX === 0) {
+ polygonPoints.push({ x: prevLineRidge.x1, y: minY }, { x: prevLineRidge.x1, y: maxY })
+ } else {
+ polygonPoints.push({ x: minX, y: prevLineRidge.y1 }, { x: maxX, y: prevLineRidge.y1 })
+ }
+ } else if (prevDistance < nextDistance) {
+ polygonPoints.push({ x: nextLineRidge.x1, y: nextLineRidge.y1 }, { x: nextLineRidge.x2, y: nextLineRidge.y2 })
+
+ /** 이전라인과 교차한 마루의 포인트*/
+ let prevRidgePoint1
+ if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ prevRidgePoint1 = polygonPoints.find(
+ (point) =>
+ (point.x === prevLineRidge.x1 && point.y === prevLineRidge.y1) || (point.x === prevLineRidge.x2 && point.y === prevLineRidge.y2),
+ )
+ } else {
+ prevRidgePoint1 =
+ currentVectorX === 0
+ ? currentRoof.y1 === prevLineRidge.y1
+ ? { x: prevLineRidge.x1, y: prevLineRidge.y1 }
+ : { x: prevLineRidge.x2, y: prevLineRidge.y2 }
+ : currentRoof.x1 === prevLineRidge.x1
+ ? { x: prevLineRidge.x1, y: prevLineRidge.y1 }
+ : { x: prevLineRidge.x2, y: prevLineRidge.y2 }
+
+ polygonPoints.push(prevRidgePoint1)
+ }
/** 다음 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/
- const checkRidgePoint =
- currentVectorX === 0
- ? roofY2.toNumber() !== nextLineRidge.y1
- ? { x: nextLineRidge.x1, y: nextLineRidge.y1 }
- : { x: nextLineRidge.x2, y: nextLineRidge.y2 }
- : roofX2.toNumber() !== nextLineRidge.x1
- ? { x: nextLineRidge.x1, y: nextLineRidge.y1 }
- : { x: nextLineRidge.x2, y: nextLineRidge.y2 }
+ let checkRidgePoint
+ if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ const ridgePoint1 = polygonPoints.filter((point) => point.x === nextLineRidge.x1 && point.y === nextLineRidge.y1)
+ checkRidgePoint = ridgePoint1.length > 0 ? { x: nextLineRidge.x2, y: nextLineRidge.y2 } : { x: nextLineRidge.x1, y: nextLineRidge.y1 }
+ } else {
+ checkRidgePoint =
+ currentVectorX === 0
+ ? currentRoof.y2 !== nextLineRidge.y1
+ ? { x: nextLineRidge.x1, y: nextLineRidge.y1 }
+ : { x: nextLineRidge.x2, y: nextLineRidge.y2 }
+ : currentRoof.x2 !== nextLineRidge.x1
+ ? { x: nextLineRidge.x1, y: nextLineRidge.y1 }
+ : { x: nextLineRidge.x2, y: nextLineRidge.y2 }
+ }
const prevRidgePoint2 =
- currentVectorX === 0
- ? { x: prevRidgePoint1.x, y: checkRidgePoint.y }
- : {
- x: checkRidgePoint.x,
- y: prevRidgePoint1.y,
- }
+ currentVectorX === 0 ? { x: prevRidgePoint1.x, y: checkRidgePoint.y } : { x: checkRidgePoint.x, y: prevRidgePoint1.y }
polygonPoints.push(prevRidgePoint2)
} else {
- polygonPoints.push(
- { x: prevLineRidge.x1, y: prevLineRidge.y1 },
- {
- x: prevLineRidge.x2,
- y: prevLineRidge.y2,
- },
- )
+ polygonPoints.push({ x: prevLineRidge.x1, y: prevLineRidge.y1 }, { x: prevLineRidge.x2, y: prevLineRidge.y2 })
/** 다음라인과 교차한 마루의 포인트*/
- const nextRidgePoint1 =
- currentVectorX === 0
- ? roofY2.toNumber() === nextLineRidge.y1
- ? { x: nextLineRidge.x1, y: nextLineRidge.y1 }
- : { x: nextLineRidge.x2, y: nextLineRidge.y2 }
- : roofX2.toNumber() === nextLineRidge.x1
- ? { x: nextLineRidge.x1, y: nextLineRidge.y1 }
- : { x: nextLineRidge.x2, y: nextLineRidge.y2 }
- polygonPoints.push(nextRidgePoint1)
+ let nextRidgePoint1
+ if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ nextRidgePoint1 = polygonPoints.find(
+ (point) =>
+ (point.x === nextLineRidge.x1 && point.y === nextLineRidge.y1) || (point.x === nextLineRidge.x2 && point.y === nextLineRidge.y2),
+ )
+ } else {
+ nextRidgePoint1 =
+ currentVectorX === 0
+ ? currentRoof.y2 === nextLineRidge.y1
+ ? { x: nextLineRidge.x1, y: nextLineRidge.y1 }
+ : { x: nextLineRidge.x2, y: nextLineRidge.y2 }
+ : currentRoof.x2 === nextLineRidge.x1
+ ? { x: nextLineRidge.x1, y: nextLineRidge.y1 }
+ : { x: nextLineRidge.x2, y: nextLineRidge.y2 }
+ polygonPoints.push(nextRidgePoint1)
+ }
/** 이전 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/
- const checkRidgePoint =
- currentVectorX === 0
- ? roofY1.toNumber() !== prevLineRidge.y1
- ? { x: prevLineRidge.x1, y: prevLineRidge.y1 }
- : { x: prevLineRidge.x2, y: prevLineRidge.y2 }
- : roofX1.toNumber() !== prevLineRidge.x1
- ? { x: prevLineRidge.x1, y: prevLineRidge.y1 }
- : { x: prevLineRidge.x2, y: prevLineRidge.y2 }
+ let checkRidgePoint
+ if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ const ridgePoint1 = polygonPoints.filter((point) => point.x === prevLineRidge.x1 && point.y === prevLineRidge.y1)
+ checkRidgePoint = ridgePoint1.length > 0 ? { x: prevLineRidge.x2, y: prevLineRidge.y2 } : { x: prevLineRidge.x1, y: prevLineRidge.y1 }
+ } else {
+ checkRidgePoint =
+ currentVectorX === 0
+ ? currentRoof.y1 !== prevLineRidge.y1
+ ? { x: prevLineRidge.x1, y: prevLineRidge.y1 }
+ : { x: prevLineRidge.x2, y: prevLineRidge.y2 }
+ : currentRoof.x1 !== prevLineRidge.x1
+ ? { x: prevLineRidge.x1, y: prevLineRidge.y1 }
+ : { x: prevLineRidge.x2, y: prevLineRidge.y2 }
+ }
+
const nextRidgePoint2 =
- currentVectorX === 0
- ? { x: nextRidgePoint1.x, y: checkRidgePoint.y }
- : {
- x: checkRidgePoint.x,
- y: nextRidgePoint1.y,
- }
+ currentVectorX === 0 ? { x: nextRidgePoint1.x, y: checkRidgePoint.y } : { x: checkRidgePoint.x, y: nextRidgePoint1.y }
polygonPoints.push(nextRidgePoint2)
}
} else {
@@ -2381,89 +2992,43 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}
}
}
- const sortedPolygonPoints = getSortedPoint(polygonPoints)
-
- /** 외벽선 밖으로 나가있는 포인트*/
- const outsidePoints = polygonPoints.filter((point) => {
- let isOutside = true
- roof.lines.forEach((line) => {
- if (
- (line.x1 <= point.x && line.x2 >= point.x && line.y1 <= point.y && line.y2 >= point.y) ||
- (line.x1 >= point.x && line.x2 <= point.x && line.y1 >= point.y && line.y2 <= point.y)
- ) {
- isOutside = false
- }
- })
- baseGableRidgeLines.forEach((line) => {
- if (
- (line.x1 <= point.x && line.x2 >= point.x && line.y1 <= point.y && line.y2 >= point.y) ||
- (line.x1 >= point.x && line.x2 <= point.x && line.y1 >= point.y && line.y2 <= point.y)
- ) {
- isOutside = false
- }
- })
- return isOutside
+ /** 중복되는 포인트 제거 */
+ const uniquePoints = []
+ polygonPoints.forEach((point) => {
+ const isAlready = uniquePoints.find((uniquePoint) => uniquePoint.x === point.x && uniquePoint.y === point.y)
+ if (!isAlready) {
+ uniquePoints.push(point)
+ }
})
+ polygonPoints = getSortedPoint(uniquePoints, baseHipLines)
- if (outsidePoints.length > 0) {
- sortedPolygonPoints.forEach((currentPoint, index) => {
- if (outsidePoints.includes(currentPoint)) {
- const prevPoint = sortedPolygonPoints[(index - 1 + sortedPolygonPoints.length) % sortedPolygonPoints.length]
- const nextPoint = sortedPolygonPoints[(index + 1) % sortedPolygonPoints.length]
- const vectorX = Math.sign(currentPoint.x - prevPoint.x)
- const vectorY = Math.sign(currentPoint.y - prevPoint.y)
-
- const checkEdge = {
- vertex1: { x: prevPoint.x, y: prevPoint.y },
- vertex2: { x: currentPoint.x, y: currentPoint.y },
- }
- const intersectPoints = []
- roof.lines
- .filter((line) => (vectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2))
- .forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const is = edgesIntersection(checkEdge, lineEdge)
- if (is && !is.isIntersectionOutside) {
- const isVectorX = Math.sign(is.x - prevPoint.x)
- const isVectorY = Math.sign(is.y - prevPoint.y)
- if ((vectorX === 0 && vectorY === isVectorY) || (vectorY === 0 && vectorX === isVectorX)) {
- intersectPoints.push(is)
- }
- }
- })
- if (intersectPoints.length > 0) {
- const intersection = intersectPoints[0]
- if (vectorX === 0) {
- currentPoint.y = intersection.y
- nextPoint.y = intersection.y
- } else {
- currentPoint.x = intersection.x
- nextPoint.x = intersection.x
- }
- }
- }
- })
- }
-
- sortedPolygonPoints.forEach((startPoint, index) => {
- let endPoint
- if (index === sortedPolygonPoints.length - 1) {
- endPoint = sortedPolygonPoints[0]
- } else {
- endPoint = sortedPolygonPoints[index + 1]
+ polygonPoints.forEach((currentPoint, index) => {
+ const nextPoint = polygonPoints[(index + 1) % polygonPoints.length]
+ const points = [currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y]
+ const isParallel = ridgeLine.x1 === ridgeLine.x2 ? currentPoint.x === nextPoint.x : currentPoint.y === nextPoint.y
+ const ridgeLines = baseGableRidgeLines.filter(
+ (line) =>
+ (line.x1 === points[0] && line.y1 === points[1] && line.x2 === points[2] && line.y2 === points[3]) ||
+ (line.x1 === points[2] && line.y1 === points[3] && line.x2 === points[0] && line.y2 === points[1]),
+ )
+ const hipLine = baseHipLines.filter(
+ (line) =>
+ (line.x1 === points[0] && line.y1 === points[1] && line.x2 === points[2] && line.y2 === points[3]) ||
+ (line.x1 === points[2] && line.y1 === points[3] && line.x2 === points[0] && line.y2 === points[1]),
+ )
+ /** 이미 존재하는 라인이면 넘긴다.*/
+ if (ridgeLines.length > 0 || hipLine.length > 0) {
+ return
}
- const hipLine = drawHipLine([startPoint.x, startPoint.y, endPoint.x, endPoint.y], canvas, roof, textMode, null, currentDegree, currentDegree)
- if (currentVectorX === 0) {
- if (Math.sign(startPoint.x - endPoint.x) === 0) {
- hipLine.attributes.actualSize = hipLine.attributes.planeSize
- }
+ let line
+ if (isParallel) {
+ line = drawRoofLine(points, canvas, roof, textMode)
+ baseGableLines.push(line)
} else {
- if (Math.sign(startPoint.y - endPoint.y) === 0) {
- hipLine.attributes.actualSize = hipLine.attributes.planeSize
- }
+ line = drawHipLine(points, canvas, roof, textMode, null, currentDegree, currentDegree)
+ baseHipLines.push({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2, line })
}
- baseHipLines.push({ x1: hipLine.x1, y1: hipLine.y1, x2: hipLine.x2, y2: hipLine.y2, line: hipLine })
})
}
})
@@ -2477,190 +3042,462 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1)
const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1)
- const currentDegree = currentLine.attributes.pitch > 0 ? getDegreeByChon(currentLine.attributes.pitch) : currentLine.attributes.degree
+ const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
- const polygonPoints = []
- if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)) {
- const currentRidge = baseGableRidgeLines.find((line) =>
- currentVectorX === 0
- ? (line.y1 === y1 && line.y2 === y2) || (line.y1 === y2 && line.y2 === y1)
- : (line.x1 === x1 && line.x2 === x2) || (line.x1 === x2 && line.x2 === x1),
- )
- if (currentRidge) {
- const ridgeVectorX = Math.sign(currentRidge.x1 - currentRidge.x2)
- const ridgeVectorY = Math.sign(currentRidge.y1 - currentRidge.y2)
-
- let checkEdge
- if (currentVectorX === 0) {
- checkEdge = {
- vertex1: { x: currentRidge.x1, y: currentRidge.y1 },
- vertex2: { x: currentLine.x1, y: currentRidge.y1 },
+ const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2)
+ const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2)
+ const intersectionRoofs = []
+ if (currentVectorX === 0) {
+ const checkEdge = {
+ vertex1: { x: prevLine.x1, y: currentMidY.toNumber() },
+ vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
+ })
+ }
}
- } else {
- checkEdge = {
- vertex1: { x: currentRidge.x1, y: currentRidge.y1 },
- vertex2: { x: currentRidge.x1, y: currentLine.y1 },
+ })
+ } else {
+ const checkEdge = {
+ vertex1: { x: currentMidX.toNumber(), y: prevLine.y1 },
+ vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ }
+ let currentRoof, prevRoof, nextRoof
+ if (intersectionRoofs.length > 0) {
+ currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line
+ prevRoof = roof.lines.find((line) => line.x2 === currentRoof.x1 && line.y2 === currentRoof.y1)
+ nextRoof = roof.lines.find((line) => line.x1 === currentRoof.x2 && line.y1 === currentRoof.y2)
+ }
+
+ let polygonPoints = []
+ if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)) {
+ const xVector = Big(nextLine.x2).minus(Big(nextLine.x1))
+ const yVector = Big(nextLine.y2).minus(Big(nextLine.y1))
+ const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2)
+ const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2)
+
+ const checkPoints = {
+ x: currentMidX.plus(Big(10).times(Math.sign(xVector.toNumber()))).toNumber(),
+ y: currentMidY.plus(Big(10).times(Math.sign(yVector.toNumber()))).toNumber(),
+ }
+ console.log('checkWallPolygon.inPolygon(checkPoints)', checkWallPolygon.inPolygon(checkPoints))
+
+ if (checkWallPolygon.inPolygon(checkPoints)) {
+ const currentRidge = baseGableRidgeLines.find((line) =>
+ currentVectorX === 0
+ ? (line.y1 === y1 && line.y2 === y2) || (line.y1 === y2 && line.y2 === y1)
+ : (line.x1 === x1 && line.x2 === x2) || (line.x1 === x2 && line.x2 === x1),
+ )
+ if (currentRidge) {
+ const ridgeVectorX = Math.sign(currentRidge.x1 - currentRidge.x2)
+ const ridgeVectorY = Math.sign(currentRidge.y1 - currentRidge.y2)
+
+ let checkEdge
+ if (currentVectorX === 0) {
+ checkEdge = {
+ vertex1: { x: currentRidge.x1, y: currentRidge.y1 },
+ vertex2: { x: currentLine.x1, y: currentRidge.y1 },
+ }
+ } else {
+ checkEdge = {
+ vertex1: { x: currentRidge.x1, y: currentRidge.y1 },
+ vertex2: { x: currentRidge.x1, y: currentLine.y1 },
+ }
+ }
+ const isRoofLines = []
+ roof.lines
+ .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2))
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const is = edgesIntersection(checkEdge, lineEdge)
+ if (is) {
+ const checkVectorX = Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x)
+ const checkVectorY = Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y)
+ const isVectorX = Math.sign(checkEdge.vertex1.x - is.x)
+ const isVectorY = Math.sign(checkEdge.vertex1.y - is.y)
+ if ((ridgeVectorX === 0 && checkVectorX === isVectorX) || (ridgeVectorY === 0 && checkVectorY === isVectorY)) {
+ const size = ridgeVectorX === 0 ? Math.abs(checkEdge.vertex1.x - is.x) : Math.abs(checkEdge.vertex1.y - is.y)
+ isRoofLines.push({ line, size })
+ }
+ }
+ })
+ isRoofLines.sort((a, b) => a.size - b.size)
+ const roofLine = isRoofLines[0].line
+ polygonPoints.push({ x: currentRidge.x1, y: currentRidge.y1 }, { x: currentRidge.x2, y: currentRidge.y2 })
+ if (ridgeVectorX === 0) {
+ polygonPoints.push({ x: roofLine.x1, y: currentRidge.y1 }, { x: roofLine.x1, y: currentRidge.y2 })
+ } else {
+ polygonPoints.push({ x: currentRidge.x1, y: roofLine.y1 }, { x: currentRidge.x2, y: roofLine.y1 })
}
}
- const isRoofLines = []
- roof.lines
- .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2))
- .forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const is = edgesIntersection(checkEdge, lineEdge)
- if (is) {
- const checkVectorX = Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x)
- const checkVectorY = Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y)
- const isVectorX = Math.sign(checkEdge.vertex1.x - is.x)
- const isVectorY = Math.sign(checkEdge.vertex1.y - is.y)
- if ((ridgeVectorX === 0 && checkVectorX === isVectorX) || (ridgeVectorY === 0 && checkVectorY === isVectorY)) {
- const size = ridgeVectorX === 0 ? Math.abs(checkEdge.vertex1.x - is.x) : Math.abs(checkEdge.vertex1.y - is.y)
- isRoofLines.push({ line, size })
- }
- }
- })
- isRoofLines.sort((a, b) => a.size - b.size)
- const roofLine = isRoofLines[0].line
- polygonPoints.push({ x: currentRidge.x1, y: currentRidge.y1 }, { x: currentRidge.x2, y: currentRidge.y2 })
- if (ridgeVectorX === 0) {
- polygonPoints.push({ x: roofLine.x1, y: currentRidge.y1 }, { x: roofLine.x1, y: currentRidge.y2 })
- } else {
- polygonPoints.push({ x: currentRidge.x1, y: roofLine.y1 }, { x: currentRidge.x2, y: roofLine.y1 })
+ } else {
+ const currentRidge = baseGableRidgeLines.find((line) =>
+ currentVectorX === 0
+ ? (Math.abs(line.y1 - currentRoof.y1) < 1 && Math.abs(line.y2 - currentRoof.y2) < 1) ||
+ (Math.abs(line.y1 - currentRoof.y2) < 1 && Math.abs(line.y2 - currentRoof.y1) < 1)
+ : (Math.abs(line.x1 - currentRoof.x1) < 1 && Math.abs(line.x2 - currentRoof.x2) < 1) ||
+ (Math.abs(line.x1 - currentRoof.x2) < 1 && Math.abs(line.x2 - currentRoof.x1) < 1),
+ )
+ if (currentRidge) {
+ if (currentVectorX === 0) {
+ polygonPoints.push({ x: currentRoof.x1, y: currentLine.y1 }, { x: currentRoof.x2, y: currentLine.y2 })
+ polygonPoints.push({ x: currentRidge.x1, y: currentLine.y1 }, { x: currentRidge.x1, y: currentLine.y2 })
+ } else {
+ polygonPoints.push({ x: currentLine.x1, y: currentRoof.y1 }, { x: currentLine.x2, y: currentRoof.y2 })
+ polygonPoints.push({ x: currentLine.x1, y: currentRidge.y1 }, { x: currentLine.x2, y: currentRidge.y1 })
+ }
}
}
} else {
- const prevEdge = { vertex1: { x: prevLine.x1, y: prevLine.y1 }, vertex2: { x: prevLine.x2, y: prevLine.y2 } }
- const prevRidge = baseGableRidgeLines.find((ridge) => {
- const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }
- const is = edgesIntersection(prevEdge, ridgeEdge)
- if (is && !is.isIntersectionOutside) {
- return ridge
- }
- })
+ const prevEdge = { vertex1: { x: prevRoof.x2, y: prevRoof.y2 }, vertex2: { x: prevRoof.x1, y: prevRoof.y1 } }
+ const prevVectorX = Math.sign(prevRoof.x1 - prevRoof.x2)
+ const prevVectorY = Math.sign(prevRoof.y1 - prevRoof.y2)
- const nextEdge = { vertex1: { x: nextLine.x1, y: nextLine.y1 }, vertex2: { x: nextLine.x2, y: nextLine.y2 } }
- const nextRidge = baseGableRidgeLines.find((ridge) => {
- const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }
- const is = edgesIntersection(nextEdge, ridgeEdge)
- if (is && !is.isIntersectionOutside) {
- return ridge
+ let prevRidge, nextRidge
+ if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ const hipLines = []
+ baseHipLines.forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const is = edgesIntersection(prevEdge, lineEdge)
+ if (is) {
+ const size = Big(is.x).minus(prevRoof.x2).abs().pow(2).plus(Big(is.y).minus(prevRoof.y2).abs().pow(2)).sqrt().toNumber()
+ hipLines.push({ line, is, size })
+ }
+ })
+ if (hipLines.length > 0) {
+ hipLines.sort((a, b) => a.size - b.size)
+ const hipLine = hipLines[0]
+ polygonPoints.push({ x: hipLine.is.x, y: hipLine.is.y })
+ const ridgePoint =
+ hipLine.is.x === hipLine.line.x1 && hipLine.is.y === hipLine.line.y1
+ ? { x: hipLine.line.x2, y: hipLine.line.y2 }
+ : { x: hipLine.line.x1, y: hipLine.line.y1 }
+ prevRidge = baseGableRidgeLines.find(
+ (line) => (line.x1 === ridgePoint.x && line.y1 === ridgePoint.y) || (line.x2 === ridgePoint.x && line.y2 === ridgePoint.y),
+ )
}
- })
+ } else {
+ const prevRidges = []
+ baseGableRidgeLines.forEach((ridge) => {
+ const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }
+ const is = edgesIntersection(prevEdge, ridgeEdge)
+ if (is) {
+ const isVectorX = Math.sign(prevRoof.x1 - is.x)
+ const isVectorY = Math.sign(prevRoof.y1 - is.y)
+ if (
+ isVectorX === prevVectorX &&
+ isVectorY === prevVectorY &&
+ ((Math.abs(ridge.x1 - is.x) < 1 && Math.abs(ridge.y1 - is.y) < 1) || (Math.abs(ridge.x2 - is.x) < 1 && Math.abs(ridge.y2 - is.y) < 1))
+ ) {
+ const size = Big(prevRoof.x1).minus(is.x).abs().pow(2).plus(Big(prevRoof.y1).minus(is.y).abs().pow(2)).sqrt().toNumber()
+ prevRidges.push({ ridge, size })
+ }
+ }
+ })
+ if (prevRidges.length > 0) {
+ prevRidges.sort((a, b) => a.size - b.size)
+ prevRidge = prevRidges[0].ridge
+ }
+ }
+
+ const nextEdge = { vertex1: { x: nextRoof.x1, y: nextRoof.y1 }, vertex2: { x: nextRoof.x2, y: nextRoof.y2 } }
+ const nextVectorX = Math.sign(nextLine.x1 - nextLine.x2)
+ const nextVectorY = Math.sign(nextLine.y1 - nextLine.y2)
+ if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ const hipLines = []
+ baseHipLines.forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const is = edgesIntersection(nextEdge, lineEdge)
+ if (is) {
+ const size = Big(is.x).minus(nextRoof.x1).abs().pow(2).plus(Big(is.y).minus(nextRoof.y1).abs().pow(2)).sqrt().toNumber()
+ hipLines.push({ line, is, size })
+ }
+ })
+ if (hipLines.length > 0) {
+ hipLines.sort((a, b) => a.size - b.size)
+ const hipLine = hipLines[0]
+ polygonPoints.push({ x: hipLine.is.x, y: hipLine.is.y })
+ const ridgePoint =
+ hipLine.is.x === hipLine.line.x1 && hipLine.is.y === hipLine.line.y1
+ ? { x: hipLine.line.x2, y: hipLine.line.y2 }
+ : { x: hipLine.line.x1, y: hipLine.line.y1 }
+ nextRidge = baseGableRidgeLines.find(
+ (line) => (line.x1 === ridgePoint.x && line.y1 === ridgePoint.y) || (line.x2 === ridgePoint.x && line.y2 === ridgePoint.y),
+ )
+ }
+ } else {
+ const nextRidges = []
+ baseGableRidgeLines.forEach((ridge) => {
+ const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }
+ const is = edgesIntersection(nextEdge, ridgeEdge)
+ if (is) {
+ const isVectorX = Math.sign(nextRoof.x1 - is.x)
+ const isVectorY = Math.sign(nextRoof.y1 - is.y)
+ if (
+ isVectorX === nextVectorX &&
+ isVectorY === nextVectorY &&
+ ((Math.abs(ridge.x1 - is.x) < 1 && Math.abs(ridge.y1 - is.y) < 1) || (Math.abs(ridge.x2 - is.x) < 1 && Math.abs(ridge.y2 - is.y) < 1))
+ ) {
+ const size = Big(nextLine.x1).minus(is.x).abs().pow(2).plus(Big(nextLine.y1).minus(is.y).abs().pow(2)).sqrt().toNumber()
+ nextRidges.push({ ridge, size })
+ }
+ }
+ })
+ if (nextRidges.length > 0) {
+ nextRidges.sort((a, b) => a.size - b.size)
+ nextRidge = nextRidges[0].ridge
+ }
+ }
+
+ if (prevRidge) {
+ const checkLine = new fabric.Line([prevRidge.x1, prevRidge.y1, prevRidge.x2, prevRidge.y2], {
+ stroke: 'red',
+ strokeWidth: 4,
+ parentId: roofId,
+ name: 'checkLine',
+ })
+ canvas.add(checkLine)
+ canvas.renderAll()
+ }
+ if (nextRidge) {
+ const checkLine = new fabric.Line([nextRidge.x1, nextRidge.y1, nextRidge.x2, nextRidge.y2], {
+ stroke: 'yellow',
+ strokeWidth: 4,
+ parentId: roofId,
+ name: 'checkLine',
+ })
+ canvas.add(checkLine)
+ canvas.renderAll()
+ }
let currentRidge
if (prevRidge) {
- if (
- currentVectorX === 0 &&
- ((prevRidge.y1 <= currentLine.y1 && prevRidge.y2 >= currentLine.y1 && prevRidge.y1 <= currentLine.y2 && prevRidge.y2 >= currentLine.y2) ||
- (prevRidge.y1 >= currentLine.y1 && prevRidge.y2 <= currentLine.y1 && prevRidge.y1 >= currentLine.y2 && prevRidge.y2 <= currentLine.y2))
- ) {
- currentRidge = prevRidge
+ if (currentVectorX === 0) {
+ const minY = Math.min(currentLine.y1, currentLine.y2, currentRoof.y1, currentRoof.y2)
+ const maxY = Math.max(currentLine.y1, currentLine.y2, currentRoof.y1, currentRoof.y2)
+ if (minY <= prevRidge.y1 && maxY >= prevRidge.y1 && minY <= prevRidge.y2 && maxY >= prevRidge.y2) {
+ currentRidge = prevRidge
+ }
}
- if (
- currentVectorY === 0 &&
- ((prevRidge.x1 <= currentLine.x1 && prevRidge.x2 >= currentLine.x1 && prevRidge.x1 <= currentLine.x2 && prevRidge.x2 >= currentLine.x2) ||
- (prevRidge.x1 >= currentLine.x1 && prevRidge.x2 <= currentLine.x1 && prevRidge.x1 >= currentLine.x2 && prevRidge.x2 <= currentLine.x2))
- ) {
- currentRidge = prevRidge
+ if (currentVectorY === 0) {
+ const minX = Math.min(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2)
+ const maxX = Math.max(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2)
+ const checkCircle = new fabric.Circle({
+ left: minX,
+ top: prevRidge.y1,
+ radius: 5,
+ fill: 'blue',
+ parentId: roofId,
+ name: 'checkCircle',
+ })
+ const checkCircle1 = new fabric.Circle({
+ left: maxX,
+ top: prevRidge.y1,
+ radius: 5,
+ fill: 'green',
+ parentId: roofId,
+ name: 'checkCircle',
+ })
+ canvas.add(checkCircle, checkCircle1)
+ canvas.renderAll()
+
+ if (minX <= prevRidge.x1 && maxX >= prevRidge.x1 && minX <= prevRidge.x2 && maxX >= prevRidge.x2) {
+ currentRidge = prevRidge
+ }
}
}
if (nextRidge) {
- if (
- currentVectorX === 0 &&
- ((nextRidge.y1 <= currentLine.y1 && nextRidge.y2 >= currentLine.y1 && nextRidge.y1 <= currentLine.y2 && nextRidge.y2 >= currentLine.y2) ||
- (nextRidge.y1 >= currentLine.y1 && nextRidge.y2 <= currentLine.y1 && nextRidge.y1 >= currentLine.y2 && nextRidge.y2 <= currentLine.y2))
- ) {
- currentRidge = nextRidge
+ if (currentVectorX === 0) {
+ const minY = Math.min(currentLine.y1, currentLine.y2, currentRoof.y1, currentRoof.y2)
+ const maxY = Math.max(currentLine.y1, currentLine.y2, currentRoof.y1, currentRoof.y2)
+ if (minY <= nextRidge.y1 && maxY >= nextRidge.y1 && minY <= nextRidge.y2 && maxY >= nextRidge.y2) {
+ currentRidge = nextRidge
+ }
}
- if (
- currentVectorY === 0 &&
- ((nextRidge.x1 <= currentLine.x1 && nextRidge.x2 >= currentLine.x1 && nextRidge.x1 <= currentLine.x2 && nextRidge.x2 >= currentLine.x2) ||
- (nextRidge.x1 >= currentLine.x1 && nextRidge.x2 <= currentLine.x1 && nextRidge.x1 >= currentLine.x2 && nextRidge.x2 <= currentLine.x2))
- ) {
- currentRidge = nextRidge
+ if (currentVectorY === 0) {
+ const minX = Math.min(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2)
+ const maxX = Math.max(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2)
+
+ const checkCircle = new fabric.Circle({
+ left: minX,
+ top: nextRidge.y1,
+ radius: 5,
+ fill: 'blue',
+ parentId: roofId,
+ name: 'checkCircle',
+ })
+ const checkCircle1 = new fabric.Circle({
+ left: maxX,
+ top: nextRidge.y1,
+ radius: 5,
+ fill: 'green',
+ parentId: roofId,
+ name: 'checkCircle',
+ })
+ canvas.add(checkCircle, checkCircle1)
+ canvas.renderAll()
+ if (minX <= nextRidge.x1 && maxX >= nextRidge.x1 && minX <= nextRidge.x2 && maxX >= nextRidge.x2) {
+ currentRidge = nextRidge
+ }
}
}
+
if (currentRidge) {
+ const checkLine = new fabric.Line([currentRidge.x1, currentRidge.y1, currentRidge.x2, currentRidge.y2], {
+ stroke: 'green',
+ strokeWidth: 4,
+ parentId: roofId,
+ name: 'checkLine',
+ })
+ canvas.add(checkLine)
+ canvas.renderAll()
+
polygonPoints.push({ x: currentRidge.x1, y: currentRidge.y1 }, { x: currentRidge.x2, y: currentRidge.y2 })
+ /** 기준점이 될 포인트를 찾는다. 기준점 = 지붕선이나 hip 등에 붙지 않은 포인트 */
+ const checkRidgePoints = [
+ { x: currentRidge.x1, y: currentRidge.y1, checkPoint: true },
+ { x: currentRidge.x2, y: currentRidge.y2, checkPoint: true },
+ ]
+ const ridgeEdge = { vertex1: { x: currentRidge.x1, y: currentRidge.y1 }, vertex2: { x: currentRidge.x2, y: currentRidge.y2 } }
+ /** 포인트가 지붕선과 붙은 경우 */
+ roof.lines.forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const is = edgesIntersection(ridgeEdge, lineEdge)
+ if (is) {
+ if (Math.abs(is.x - currentRidge.x1) < 1 && Math.abs(is.y - currentRidge.y1) < 1) {
+ checkRidgePoints[0].checkPoint = false
+ }
+ if (Math.abs(is.x - currentRidge.x2) < 1 && Math.abs(is.y - currentRidge.y2) < 1) {
+ checkRidgePoints[1].checkPoint = false
+ }
+ }
+ })
+ /** 포인트가 hip과 붙은 경우 */
+ baseHipLines
+ .filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2)
+ .forEach((line) => {
+ if (
+ (Math.abs(line.x1 - currentRidge.x1) < 1 && Math.abs(line.y1 - currentRidge.y1) < 1) ||
+ (Math.abs(line.x2 - currentRidge.x1) < 1 && Math.abs(line.y2 - currentRidge.y1) < 1)
+ ) {
+ checkRidgePoints[0].checkPoint = false
+ }
+ if (
+ (Math.abs(line.x1 - currentRidge.x2) < 1 && Math.abs(line.y1 - currentRidge.y2) < 1) ||
+ (Math.abs(line.x2 - currentRidge.x2) < 1 && Math.abs(line.y2 - currentRidge.y2) < 1)
+ ) {
+ checkRidgePoints[1].checkPoint = false
+ }
+ })
+
+ const checkRidgePoint = checkRidgePoints.find((point) => point.checkPoint)
+
/** 마루에서 현재라인으로 향하는 외벽선까지의 포인트를 확인 하여 처리*/
let checkEdge
if (currentVectorX === 0) {
checkEdge = {
- vertex1: { x: currentRidge.x1, y: currentRidge.y1 },
- vertex2: { x: currentLine.x1, y: currentRidge.y1 },
+ vertex1: { x: checkRidgePoint.x, y: checkRidgePoint.y },
+ vertex2: { x: currentRoof.x1, y: checkRidgePoint.y },
}
} else {
checkEdge = {
- vertex1: { x: currentRidge.x1, y: currentRidge.y1 },
- vertex2: { x: currentRidge.x1, y: currentLine.y1 },
+ vertex1: { x: checkRidgePoint.x, y: checkRidgePoint.y },
+ vertex2: { x: checkRidgePoint.x, y: currentRoof.y1 },
}
}
+ const currentRoofEdge = { vertex1: { x: currentRoof.x1, y: currentRoof.y1 }, vertex2: { x: currentRoof.x2, y: currentRoof.y2 } }
- const checkVectorX = Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x)
- const checkVectorY = Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y)
- const intersectPoints = []
- roof.lines
- .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2))
- .forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const is = edgesIntersection(checkEdge, lineEdge)
- if (is) {
- const isVectorX = Math.sign(checkEdge.vertex1.x - is.x)
- const isVectorY = Math.sign(checkEdge.vertex1.y - is.y)
- const isLineOtherPoint =
- is.x === line.x1 && is.y === line.y1
- ? { x: line.x2, y: line.y2 }
- : {
- x: line.x1,
- y: line.y1,
- }
- const isInPoint =
- checkVectorX === 0
- ? (currentRidge.x1 <= isLineOtherPoint.x && isLineOtherPoint.x <= currentRidge.x2) ||
- (currentRidge.x1 >= isLineOtherPoint.x && isLineOtherPoint.x >= currentRidge.x2)
- : (currentRidge.y1 <= isLineOtherPoint.y && isLineOtherPoint.y <= currentRidge.y2) ||
- (currentRidge.y1 >= isLineOtherPoint.y && isLineOtherPoint.y >= currentRidge.y2)
- if (checkVectorX === isVectorX && checkVectorY === isVectorY && isInPoint) {
- const size = Big(checkEdge.vertex1.x).minus(is.x).abs().pow(2).plus(Big(checkEdge.vertex1.y).minus(is.y).abs().pow(2)).sqrt()
- intersectPoints.push({ is, size })
- }
- }
- })
- intersectPoints.sort((a, b) => a.size - b.size)
- let intersect = intersectPoints[0].is
- if (currentVectorX === 0) {
- polygonPoints.push({ x: intersect.x, y: currentRidge.y1 }, { x: intersect.x, y: currentRidge.y2 })
- } else {
- polygonPoints.push({ x: currentRidge.x1, y: intersect.y }, { x: currentRidge.x2, y: intersect.y })
+ const isRoofPoint = edgesIntersection(checkEdge, currentRoofEdge)
+ if (isRoofPoint) {
+ if (currentVectorX === 0) {
+ const minY = Math.min(currentRoof.y1, currentRoof.y2, isRoofPoint.y)
+ const maxY = Math.max(currentRoof.y1, currentRoof.y2, isRoofPoint.y)
+ polygonPoints.push({ x: isRoofPoint.x, y: minY }, { x: isRoofPoint.x, y: maxY })
+ } else {
+ const minX = Math.min(currentRoof.x1, currentRoof.x2, isRoofPoint.x)
+ const maxX = Math.max(currentRoof.x1, currentRoof.x2, isRoofPoint.x)
+ polygonPoints.push({ x: minX, y: isRoofPoint.y }, { x: maxX, y: isRoofPoint.y })
+ }
}
}
}
- const sortedPolygonPoints = getSortedPoint(polygonPoints)
- sortedPolygonPoints.forEach((startPoint, index) => {
- let endPoint
- if (index === sortedPolygonPoints.length - 1) {
- endPoint = sortedPolygonPoints[0]
- } else {
- endPoint = sortedPolygonPoints[index + 1]
+ const uniquePoints = []
+ polygonPoints.forEach((point) => {
+ const isAlready = uniquePoints.find((uniquePoint) => uniquePoint.x === point.x && uniquePoint.y === point.y)
+ if (!isAlready) {
+ uniquePoints.push(point)
}
- const hipLine = drawHipLine([startPoint.x, startPoint.y, endPoint.x, endPoint.y], canvas, roof, textMode, null, currentDegree, currentDegree)
+ })
+
+ polygonPoints = getSortedPoint(uniquePoints, baseHipLines)
+ polygonPoints.forEach((currentPoint, index) => {
+ const nextPoint = polygonPoints[(index + 1) % polygonPoints.length]
+ const points = [currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y]
+
+ const ridgeLines = baseGableRidgeLines.filter(
+ (line) =>
+ (line.x1 === points[0] && line.y1 === points[1] && line.x2 === points[2] && line.y2 === points[3]) ||
+ (line.x1 === points[2] && line.y1 === points[3] && line.x2 === points[0] && line.y2 === points[1]),
+ )
+ const hipLines = baseHipLines.filter(
+ (line) =>
+ (line.x1 === points[0] && line.y1 === points[1] && line.x2 === points[2] && line.y2 === points[3]) ||
+ (line.x1 === points[2] && line.y1 === points[3] && line.x2 === points[0] && line.y2 === points[1]),
+ )
+ /** 이미 존재하는 라인이면 넘긴다.*/
+ if (ridgeLines.length > 0 || hipLines.length > 0) {
+ return
+ }
+
+ const hipLine = drawHipLine(points, canvas, roof, textMode, null, currentDegree, currentDegree)
if (currentVectorX === 0) {
- if (Math.sign(startPoint.x - endPoint.x) === 0) {
+ if (Math.sign(currentPoint.x - nextPoint.x) === 0) {
hipLine.attributes.actualSize = hipLine.attributes.planeSize
}
} else {
- if (Math.sign(startPoint.y - endPoint.y) === 0) {
+ if (Math.sign(currentPoint.y - nextPoint.y) === 0) {
hipLine.attributes.actualSize = hipLine.attributes.planeSize
}
}
baseHipLines.push({ x1: hipLine.x1, y1: hipLine.y1, x2: hipLine.x2, y2: hipLine.y2, line: hipLine })
})
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'checkLine' || obj.name === 'checkCircle')
+ .forEach((obj) => canvas.remove(obj))
+ canvas.renderAll()
})
/** 케라바 지붕에 연결된 마루 중 처마라인이 그려지지 않은 경우 확*/
@@ -2711,8 +3548,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
currentLine.x1 !== currentLine.x2 &&
((currentLine.x1 <= ridge.x1 && ridge.x1 <= currentLine.x2) || (currentLine.x2 <= ridge.x1 && ridge.x1 <= currentLine.x1))
) {
- degree1 = prevLine.attributes.pitch > 0 ? getDegreeByChon(prevLine.attributes.pitch) : prevLine.attributes.degree
- degree2 = nextLine.attributes.pitch > 0 ? getDegreeByChon(nextLine.attributes.pitch) : nextLine.attributes.degree
+ degree1 = getDegreeByChon(prevLine.attributes.pitch)
+ degree2 = getDegreeByChon(nextLine.attributes.pitch)
}
if (
@@ -2720,8 +3557,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
currentLine.y1 !== currentLine.y2 &&
((currentLine.y1 <= ridge.y1 && ridge.y1 <= currentLine.y2) || (currentLine.y2 <= ridge.y1 && ridge.y1 <= currentLine.y1))
) {
- degree1 = prevLine.attributes.pitch > 0 ? getDegreeByChon(prevLine.attributes.pitch) : prevLine.attributes.degree
- degree2 = nextLine.attributes.pitch > 0 ? getDegreeByChon(nextLine.attributes.pitch) : nextLine.attributes.degree
+ degree1 = getDegreeByChon(prevLine.attributes.pitch)
+ degree2 = getDegreeByChon(nextLine.attributes.pitch)
}
}
})
@@ -2775,52 +3612,35 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}
if (hipPoint1) {
- let alreadyHip = false
- baseHipLines
- .filter(
- (line) =>
- (line.line.x1 === hipPoint1[0] && line.line.y1 === hipPoint1[1] && line.line.x2 === hipPoint1[2] && line.line.y2 === hipPoint1[3]) ||
- (line.line.x2 === hipPoint1[0] && line.line.y2 === hipPoint1[1] && line.line.x1 === hipPoint1[2] && line.line.y1 === hipPoint1[3]),
- )
- .forEach((line) => {
- alreadyHip = true
- })
- baseGableLines
- .filter(
- (line) =>
- (line.x1 === hipPoint1[0] && line.y1 === hipPoint1[1] && line.x2 === hipPoint1[2] && line.y2 === hipPoint1[3]) ||
- (line.x2 === hipPoint1[0] && line.y2 === hipPoint1[1] && line.x1 === hipPoint1[2] && line.y1 === hipPoint1[3]),
- )
- .forEach((line) => {
- alreadyHip = true
- })
+ const hipLines = baseHipLines.filter(
+ (line) =>
+ (line.line.x1 === hipPoint1[0] && line.line.y1 === hipPoint1[1] && line.line.x2 === hipPoint1[2] && line.line.y2 === hipPoint1[3]) ||
+ (line.line.x2 === hipPoint1[0] && line.line.y2 === hipPoint1[1] && line.line.x1 === hipPoint1[2] && line.line.y1 === hipPoint1[3]),
+ )
- if (!alreadyHip) {
+ const gableLines = baseGableLines.filter(
+ (line) =>
+ (line.x1 === hipPoint1[0] && line.y1 === hipPoint1[1] && line.x2 === hipPoint1[2] && line.y2 === hipPoint1[3]) ||
+ (line.x2 === hipPoint1[0] && line.y2 === hipPoint1[1] && line.x1 === hipPoint1[2] && line.y1 === hipPoint1[3]),
+ )
+
+ if (gableLines.length === 0 && hipLines.length === 0) {
const hipLine1 = drawHipLine(hipPoint1, canvas, roof, textMode, null, degree1, degree1)
baseHipLines.push({ x1: hipLine1.x1, y1: hipLine1.y1, x2: hipLine1.x2, y2: hipLine1.y2, line: hipLine1 })
}
}
if (hipPoint2) {
- let alreadyHip = false
- baseHipLines
- .filter(
- (line) =>
- (line.line.x1 === hipPoint2[0] && line.line.y1 === hipPoint2[1] && line.line.x2 === hipPoint2[2] && line.line.y2 === hipPoint2[3]) ||
- (line.line.x2 === hipPoint2[0] && line.line.y2 === hipPoint2[1] && line.line.x1 === hipPoint2[2] && line.line.y1 === hipPoint2[3]),
- )
- .forEach((line) => {
- alreadyHip = true
- })
- baseGableLines
- .filter(
- (line) =>
- (line.x1 === hipPoint2[0] && line.y1 === hipPoint2[1] && line.x2 === hipPoint2[2] && line.y2 === hipPoint2[3]) ||
- (line.x2 === hipPoint2[0] && line.y2 === hipPoint2[1] && line.x1 === hipPoint2[2] && line.y1 === hipPoint2[3]),
- )
- .forEach((line) => {
- alreadyHip = true
- })
- if (!alreadyHip) {
+ const hipLines = baseHipLines.filter(
+ (line) =>
+ (line.line.x1 === hipPoint2[0] && line.line.y1 === hipPoint2[1] && line.line.x2 === hipPoint2[2] && line.line.y2 === hipPoint2[3]) ||
+ (line.line.x2 === hipPoint2[0] && line.line.y2 === hipPoint2[1] && line.line.x1 === hipPoint2[2] && line.line.y1 === hipPoint2[3]),
+ )
+ const gableLines = baseGableLines.filter(
+ (line) =>
+ (line.x1 === hipPoint2[0] && line.y1 === hipPoint2[1] && line.x2 === hipPoint2[2] && line.y2 === hipPoint2[3]) ||
+ (line.x2 === hipPoint2[0] && line.y2 === hipPoint2[1] && line.x1 === hipPoint2[2] && line.y1 === hipPoint2[3]),
+ )
+ if (hipLines.length === 0 && gableLines.length === 0) {
const hipLine2 = drawHipLine(hipPoint2, canvas, roof, textMode, null, degree2, degree2)
baseHipLines.push({ x1: hipLine2.x1, y1: hipLine2.y1, x2: hipLine2.x2, y2: hipLine2.y2, line: hipLine2 })
}
@@ -2877,52 +3697,34 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}
if (hipPoint1) {
- let alreadyHip = false
- baseHipLines
- .filter(
- (line) =>
- (line.line.x1 === hipPoint1[0] && line.line.y1 === hipPoint1[1] && line.line.x2 === hipPoint1[2] && line.line.y2 === hipPoint1[3]) ||
- (line.line.x2 === hipPoint1[0] && line.line.y2 === hipPoint1[1] && line.line.x1 === hipPoint1[2] && line.line.y1 === hipPoint1[3]),
- )
- .forEach((line) => {
- alreadyHip = true
- })
- baseGableLines
- .filter(
- (line) =>
- (line.x1 === hipPoint1[0] && line.y1 === hipPoint1[1] && line.x2 === hipPoint1[2] && line.y2 === hipPoint1[3]) ||
- (line.x2 === hipPoint1[0] && line.y2 === hipPoint1[1] && line.x1 === hipPoint1[2] && line.y1 === hipPoint1[3]),
- )
- .forEach((line) => {
- alreadyHip = true
- })
+ const hipLines = baseHipLines.filter(
+ (line) =>
+ (line.line.x1 === hipPoint1[0] && line.line.y1 === hipPoint1[1] && line.line.x2 === hipPoint1[2] && line.line.y2 === hipPoint1[3]) ||
+ (line.line.x2 === hipPoint1[0] && line.line.y2 === hipPoint1[1] && line.line.x1 === hipPoint1[2] && line.line.y1 === hipPoint1[3]),
+ )
+ const gableLines = baseGableLines.filter(
+ (line) =>
+ (line.x1 === hipPoint1[0] && line.y1 === hipPoint1[1] && line.x2 === hipPoint1[2] && line.y2 === hipPoint1[3]) ||
+ (line.x2 === hipPoint1[0] && line.y2 === hipPoint1[1] && line.x1 === hipPoint1[2] && line.y1 === hipPoint1[3]),
+ )
- if (!alreadyHip) {
+ if (hipLines.length === 0 && gableLines.length === 0) {
const hipLine1 = drawHipLine(hipPoint1, canvas, roof, textMode, null, degree1, degree1)
baseHipLines.push({ x1: hipLine1.x1, y1: hipLine1.y1, x2: hipLine1.x2, y2: hipLine1.y2, line: hipLine1 })
}
}
if (hipPoint2) {
- let alreadyHip = false
- baseHipLines
- .filter(
- (line) =>
- (line.line.x1 === hipPoint2[0] && line.line.y1 === hipPoint2[1] && line.line.x2 === hipPoint2[2] && line.line.y2 === hipPoint2[3]) ||
- (line.line.x2 === hipPoint2[0] && line.line.y2 === hipPoint2[1] && line.line.x1 === hipPoint2[2] && line.line.y1 === hipPoint2[3]),
- )
- .forEach((line) => {
- alreadyHip = true
- })
- baseGableLines
- .filter(
- (line) =>
- (line.x1 === hipPoint2[0] && line.y1 === hipPoint2[1] && line.x2 === hipPoint2[2] && line.y2 === hipPoint2[3]) ||
- (line.x2 === hipPoint2[0] && line.y2 === hipPoint2[1] && line.x1 === hipPoint2[2] && line.y1 === hipPoint2[3]),
- )
- .forEach((line) => {
- alreadyHip = true
- })
- if (!alreadyHip) {
+ const hipLines = baseHipLines.filter(
+ (line) =>
+ (line.line.x1 === hipPoint2[0] && line.line.y1 === hipPoint2[1] && line.line.x2 === hipPoint2[2] && line.line.y2 === hipPoint2[3]) ||
+ (line.line.x2 === hipPoint2[0] && line.line.y2 === hipPoint2[1] && line.line.x1 === hipPoint2[2] && line.line.y1 === hipPoint2[3]),
+ )
+ const gableLines = baseGableLines.filter(
+ (line) =>
+ (line.x1 === hipPoint2[0] && line.y1 === hipPoint2[1] && line.x2 === hipPoint2[2] && line.y2 === hipPoint2[3]) ||
+ (line.x2 === hipPoint2[0] && line.y2 === hipPoint2[1] && line.x1 === hipPoint2[2] && line.y1 === hipPoint2[3]),
+ )
+ if (hipLines.length === 0 && gableLines.length === 0) {
const hipLine2 = drawHipLine(hipPoint2, canvas, roof, textMode, null, degree2, degree2)
baseHipLines.push({ x1: hipLine2.x1, y1: hipLine2.y1, x2: hipLine2.x2, y2: hipLine2.y2, line: hipLine2 })
}
@@ -2931,6 +3733,928 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}
})
+ /** 팔작지붕 */
+ drawHipAndGableFirst.forEach((current) => {
+ const { currentBaseLine, prevBaseLine, nextBaseLine } = current
+ const currentLine = currentBaseLine.line
+ const prevLine = prevBaseLine.line
+ const nextLine = nextBaseLine.line
+ let { x1, x2, y1, y2 } = currentBaseLine
+ const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
+ const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
+ const nextDegree = getDegreeByChon(nextLine.attributes.pitch)
+
+ let beforePrevLine, afterNextLine
+ drawBaseLines.forEach((line, index) => {
+ if (line === prevBaseLine) {
+ beforePrevLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length]
+ }
+ if (line === nextBaseLine) {
+ afterNextLine = drawBaseLines[(index + 1) % drawBaseLines.length]
+ }
+ })
+ /** 팔작지붕 두께*/
+ const lineWidth =
+ currentLine.attributes.width < Big(currentLine.attributes.planeSize).div(20).toNumber()
+ ? currentLine.attributes.width
+ : Big(currentLine.attributes.planeSize).div(20).toNumber()
+
+ const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1)
+ const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1)
+
+ const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2)
+ const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2)
+ const intersectionRoofs = []
+ if (currentVectorX === 0) {
+ const checkEdge = {
+ vertex1: { x: prevLine.x1, y: currentMidY.toNumber() },
+ vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ } else {
+ const checkEdge = {
+ vertex1: { x: currentMidX.toNumber(), y: prevLine.y1 },
+ vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ }
+
+ let currentRoof, prevRoof, nextRoof
+ if (intersectionRoofs.length > 0) {
+ currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line
+ }
+
+ roof.lines.forEach((line, index) => {
+ if (line === currentRoof) {
+ prevRoof = roof.lines[(index - 1 + roof.lines.length) % roof.lines.length]
+ nextRoof = roof.lines[(index + 1) % roof.lines.length]
+ }
+ })
+
+ // /** 이전, 다음라인의 사잇각의 vector를 구한다. */
+ let prevVector = getHalfAngleVector(prevRoof, currentRoof)
+ let nextVector = getHalfAngleVector(currentRoof, nextRoof)
+
+ let prevHipVector = { x: Math.sign(prevVector.x), y: Math.sign(prevVector.y) }
+ let nextHipVector = { x: Math.sign(nextVector.x), y: Math.sign(nextVector.y) }
+
+ /** 현재 라인의 길이 추녀마루 길이의 기준이 된다. */
+ let hipSize = Big(lineWidth).pow(2).plus(Big(lineWidth).pow(2)).sqrt()
+ console.log('hipSize', hipSize.toNumber())
+
+ /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
+ const prevCheckPoint = {
+ x: Big(currentRoof.x1).plus(Big(prevHipVector.x).times(lineWidth)),
+ y: Big(currentRoof.y1).plus(Big(prevHipVector.y).times(lineWidth)),
+ }
+ if (!roof.inPolygon(prevCheckPoint)) {
+ prevHipVector = { x: Math.sign(prevHipVector.x * -1), y: Math.sign(prevHipVector.y * -1) }
+ }
+
+ /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
+ const nextCheckPoint = {
+ x: Big(currentRoof.x2).plus(Big(nextHipVector.x).times(lineWidth)),
+ y: Big(currentRoof.y2).plus(Big(nextHipVector.y).times(lineWidth)),
+ }
+ if (!roof.inPolygon(nextCheckPoint)) {
+ nextHipVector = { x: Math.sign(nextHipVector.x * -1), y: Math.sign(nextHipVector.y * -1) }
+ }
+
+ /** 처마끝에서 올라오는 라인*/
+ const prevPoint = [
+ currentRoof.x1,
+ currentRoof.y1,
+ Big(currentRoof.x1).plus(Big(prevHipVector.x).times(lineWidth)).toNumber(),
+ Big(currentRoof.y1).plus(Big(prevHipVector.y).times(lineWidth)).toNumber(),
+ ]
+ const nextPoint = [
+ currentRoof.x2,
+ currentRoof.y2,
+ Big(currentRoof.x2).plus(Big(nextHipVector.x).times(lineWidth)).toNumber(),
+ Big(currentRoof.y2).plus(Big(nextHipVector.y).times(lineWidth)).toNumber(),
+ ]
+ const prevHipLine = drawHipLine(prevPoint, canvas, roof, textMode, null, prevDegree, currentDegree)
+ const nextHipLine = drawHipLine(nextPoint, canvas, roof, textMode, null, currentDegree, nextDegree)
+ baseHipLines.push({ x1, y1, x2: prevHipLine.x1, y2: prevHipLine.y1, line: prevHipLine })
+ baseHipLines.push({ x1: x2, y1: y2, x2: nextHipLine.x1, y2: nextHipLine.y1, line: nextHipLine })
+
+ /** 처마끝에서 올라오는 라인에서 가운데로 모이는 라인*/
+ let midX, midY
+ if (currentVectorX === 0) {
+ midX = prevHipLine.x2
+ midY = currentMidY.toNumber()
+ } else {
+ midX = currentMidX.toNumber()
+ midY = prevHipLine.y2
+ }
+ const prevGablePoint = [prevHipLine.x2, prevHipLine.y2, midX, midY]
+ const nextGablePoint = [nextHipLine.x2, nextHipLine.y2, midX, midY]
+
+ const prevGableLine = drawHipLine(prevGablePoint, canvas, roof, textMode, null, prevDegree, currentDegree)
+ const nextGableLine = drawHipLine(nextGablePoint, canvas, roof, textMode, null, currentDegree, nextDegree)
+ baseHipLines.push({ x1: prevGableLine.x1, y1: prevGableLine.y1, x2: prevGableLine.x2, y2: prevGableLine.y2, line: prevGableLine })
+ baseHipLines.push({ x1: nextGableLine.x1, y1: nextGableLine.y1, x2: nextGableLine.x2, y2: nextGableLine.y2, line: nextGableLine })
+
+ let oppositeLine
+ baseLines
+ .filter((line) => line !== currentLine)
+ .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2))
+ .forEach((oppCurrLine) => {
+ let checkEdge
+ if (currentVectorX === 0) {
+ checkEdge = {
+ vertex1: { x: midX, y: midY },
+ vertex2: { x: oppCurrLine.x1, y: midY },
+ }
+ } else {
+ checkEdge = {
+ vertex1: { x: midX, y: midY },
+ vertex2: { x: midX, y: oppCurrLine.y1 },
+ }
+ }
+ const lineEdge = { vertex1: { x: oppCurrLine.x1, y: oppCurrLine.y1 }, vertex2: { x: oppCurrLine.x2, y: oppCurrLine.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection && isPointOnLine(oppCurrLine, intersection)) {
+ const size =
+ calcLinePlaneSize({
+ x1: checkEdge.vertex1.x,
+ y1: checkEdge.vertex1.y,
+ x2: intersection.x,
+ y2: intersection.y,
+ }) / 10
+ oppositeLine = { intersection, size, oppCurrLine }
+ }
+ })
+
+ if (oppositeLine) {
+ const { intersection, size, oppCurrLine } = oppositeLine
+ let oppPrevLine, oppNextLine
+ let oppRoofLine
+
+ let ridgePoints = []
+ let ridgeSize
+
+ const ridgeEdge = {
+ vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
+ vertex2: { x: intersection.x, y: intersection.y },
+ }
+
+ if (prevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
+ let beforePrevVector = getHalfAngleVector(prevLine, beforePrevLine)
+ /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
+ const beforePrevCheckPoint = {
+ x: Big(prevLine.x1).plus(Big(beforePrevVector.x).times(10)),
+ y: Big(prevLine.y1).plus(Big(beforePrevVector.y).times(10)),
+ }
+ if (!checkWallPolygon.inPolygon(beforePrevCheckPoint)) {
+ beforePrevVector = { x: -beforePrevVector.x, y: -beforePrevVector.y }
+ }
+
+ const checkBeforeEdge = {
+ vertex1: { x: prevLine.x1, y: prevLine.y1 },
+ vertex2: {
+ x: Big(prevLine.x1).plus(Big(beforePrevVector.x).times(10)).toNumber(),
+ y: Big(prevLine.y1).plus(Big(beforePrevVector.y).times(10)).toNumber(),
+ },
+ }
+
+ const isBefore = edgesIntersection(checkBeforeEdge, ridgeEdge)
+ if (isBefore) {
+ const size = Big(isBefore.x).minus(currentMidX).abs().pow(2).plus(Big(isBefore.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber()
+ ridgePoints.push({ x: isBefore.x, y: isBefore.y, size })
+ }
+ }
+
+ if (nextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && afterNextLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
+ let afterNextVector = getHalfAngleVector(nextLine, afterNextLine)
+
+ /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
+ const afterNextCheckPoint = {
+ x: Big(nextLine.x2).plus(Big(afterNextVector.x).times(10)),
+ y: Big(nextLine.y2).plus(Big(afterNextVector.y).times(10)),
+ }
+ if (!checkWallPolygon.inPolygon(afterNextCheckPoint)) {
+ afterNextVector = { x: -afterNextVector.x, y: -afterNextVector.y }
+ }
+
+ const checkAfterEdge = {
+ vertex1: { x: nextLine.x2, y: nextLine.y2 },
+ vertex2: {
+ x: Big(nextLine.x2).plus(Big(afterNextVector.x).times(10)).toNumber(),
+ y: Big(nextLine.y2).plus(Big(afterNextVector.y).times(10)).toNumber(),
+ },
+ }
+ const isAfter = edgesIntersection(checkAfterEdge, ridgeEdge)
+ if (isAfter) {
+ const size = Big(isAfter.x).minus(currentMidX).abs().pow(2).plus(Big(isAfter.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber()
+ ridgePoints.push({ x: isAfter.x, y: isAfter.y, size })
+ }
+ }
+
+ baseLines.forEach((line, index) => {
+ if (line === oppCurrLine) {
+ oppPrevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
+ oppNextLine = baseLines[(index + 1) % baseLines.length]
+ }
+ })
+
+ const oppositeRoofs = []
+ const oppositeMidX = Big(oppCurrLine.x1).plus(Big(oppCurrLine.x2)).div(2)
+ const oppositeMidY = Big(oppCurrLine.y1).plus(Big(oppCurrLine.y2)).div(2)
+ const oppositeVectorX = Math.sign(oppCurrLine.x2 - oppCurrLine.x1)
+ const oppositeVectorY = Math.sign(oppCurrLine.y2 - oppCurrLine.y1)
+
+ if (Math.sign(oppCurrLine.x1 - oppCurrLine.x2) === 0) {
+ const checkEdge = {
+ vertex1: { x: oppPrevLine.x1, y: oppositeMidY.toNumber() },
+ vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === oppositeVectorX && Math.sign(line.y2 - line.y1) === oppositeVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ oppositeRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(oppositeMidX).abs().pow(2).plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ } else {
+ const checkEdge = {
+ vertex1: { x: oppositeMidX.toNumber(), y: oppPrevLine.y1 },
+ vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === oppositeVectorX && Math.sign(line.y2 - line.y1) === oppositeVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ oppositeRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(oppositeMidX).abs().pow(2).plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ }
+ if (oppositeRoofs.length > 0) {
+ oppRoofLine = oppositeRoofs.sort((a, b) => a.size - b.size)[0].line
+ }
+
+ console.log('oppositeRoofs', oppositeRoofs)
+ console.log('oppositeRoofLine', oppRoofLine)
+ if (oppCurrLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
+ if (oppRoofLine) {
+ const oppRoofSize = Big(oppRoofLine.attributes.planeSize).div(20)
+ const ridgeEdge = {
+ vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
+ vertex2: { x: intersection.x, y: intersection.y },
+ }
+
+ if (oppPrevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
+ let oppPrevVector = getHalfAngleVector(oppCurrLine, oppPrevLine)
+ oppPrevVector = { x: oppPrevVector.x, y: oppPrevVector.y }
+
+ /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
+ const prevCheckPoint = {
+ x: Big(oppCurrLine.x1).plus(Big(oppPrevVector.x).times(10)),
+ y: Big(oppCurrLine.y1).plus(Big(oppPrevVector.y).times(10)),
+ }
+
+ if (!checkWallPolygon.inPolygon(prevCheckPoint)) {
+ oppPrevVector = { x: -oppPrevVector.x, y: -oppPrevVector.y }
+ }
+
+ const oppPrevHipEdge = {
+ vertex1: {
+ x: oppRoofLine.x1,
+ y: oppRoofLine.y1,
+ },
+ vertex2: {
+ x: Big(oppRoofLine.x1).plus(Big(oppPrevVector.x).times(oppRoofSize)).toNumber(),
+ y: Big(oppRoofLine.y1).plus(Big(oppPrevVector.y).times(oppRoofSize)).toNumber(),
+ },
+ }
+
+ const isOppPrev = edgesIntersection(oppPrevHipEdge, ridgeEdge)
+
+ if (
+ isOppPrev &&
+ isPointOnLine(
+ {
+ x1: oppPrevHipEdge.vertex1.x,
+ y1: oppPrevHipEdge.vertex1.y,
+ x2: oppPrevHipEdge.vertex2.x,
+ y2: oppPrevHipEdge.vertex2.y,
+ },
+ isOppPrev,
+ )
+ ) {
+ const size = Big(isOppPrev.x).minus(currentMidX).abs().pow(2).plus(Big(isOppPrev.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber()
+ ridgePoints.push({ x: isOppPrev.x, y: isOppPrev.y, size })
+ }
+ }
+ if (oppNextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
+ let oppNextVector = getHalfAngleVector(oppCurrLine, oppNextLine)
+ oppNextVector = { x: oppNextVector.x, y: oppNextVector.y }
+
+ /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
+ const nextCheckPoint = {
+ x: Big(oppCurrLine.x2).plus(Big(oppNextVector.x).times(10)),
+ y: Big(oppCurrLine.y2).plus(Big(oppNextVector.y).times(10)),
+ }
+
+ if (!checkWallPolygon.inPolygon(nextCheckPoint)) {
+ oppNextVector = { x: -oppNextVector.x, y: -oppNextVector.y }
+ }
+
+ const oppNextHipEdge = {
+ vertex1: {
+ x: oppRoofLine.x2,
+ y: oppRoofLine.y2,
+ },
+ vertex2: {
+ x: Big(oppRoofLine.x2).plus(Big(oppNextVector.x).times(oppRoofSize)).toNumber(),
+ y: Big(oppRoofLine.y2).plus(Big(oppNextVector.y).times(oppRoofSize)).toNumber(),
+ },
+ }
+ const isOppNext = edgesIntersection(oppNextHipEdge, ridgeEdge)
+ if (
+ isOppNext &&
+ isPointOnLine(
+ {
+ x1: oppNextHipEdge.vertex1.x,
+ y1: oppNextHipEdge.vertex1.y,
+ x2: oppNextHipEdge.vertex2.x,
+ y2: oppNextHipEdge.vertex2.y,
+ },
+ isOppNext,
+ )
+ ) {
+ const size = Big(isOppNext.x).minus(currentMidX).abs().pow(2).plus(Big(isOppNext.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber()
+ ridgePoints.push({ x: isOppNext.x, y: isOppNext.y, size })
+ }
+ }
+ }
+ } else if (oppCurrLine.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) {
+ ridgeSize = Big(size).minus(Big(oppCurrLine.attributes.width)).plus(Big(oppCurrLine.attributes.offset)).toNumber()
+ }
+
+ if (ridgePoints.length > 0) {
+ ridgeSize = ridgePoints.sort((a, b) => a.size - b.size)[0].size
+ }
+
+ if (ridgeSize > 0 && baseRidgeCount < getMaxRidge(baseLines.length)) {
+ const ridgeVectorX = Math.sign(midX - intersection.x)
+ const ridgeVectorY = Math.sign(midY - intersection.y)
+ const ridgePoint = [
+ midX,
+ midY,
+ Big(midX).minus(Big(ridgeSize).times(ridgeVectorX)).toNumber(),
+ Big(midY).minus(Big(ridgeSize).times(ridgeVectorY)).toNumber(),
+ ]
+ const ridgeLine = drawRidgeLine(ridgePoint, canvas, roof, textMode)
+ baseRidgeLines.push(ridgeLine)
+ baseRidgeCount++
+ } else {
+ let ridges = []
+ baseGableRidgeLines
+ .filter(
+ (ridge) =>
+ (Math.abs(ridge.x1 - midX) < 1 && Math.abs(ridge.y1 - midY) < 1) || (Math.abs(ridge.x2 - midX) < 1 && Math.abs(ridge.y2 - midY) < 1),
+ )
+ .forEach((ridge) => ridges.push(ridge))
+ baseRidgeLines
+ .filter(
+ (ridge) =>
+ (Math.abs(ridge.x1 - midX) < 1 && Math.abs(ridge.y1 - midY) < 1) || (Math.abs(ridge.x2 - midX) < 1 && Math.abs(ridge.y2 - midY) < 1),
+ )
+ .forEach((ridge) => ridges.push(ridge))
+ if (ridges.length > 0) {
+ return
+ }
+
+ canvas.remove(prevGableLine)
+ canvas.remove(nextGableLine)
+ baseHipLines = baseHipLines.filter((base) => base.line !== prevGableLine && base.line !== nextGableLine)
+
+ const points = [prevGableLine.x1, prevGableLine.y1, nextGableLine.x1, nextGableLine.y1]
+ const gableLine = drawRoofLine(points, canvas, roof, textMode)
+ baseHipLines.push({ x1: gableLine.x1, y1: gableLine.y1, x2: gableLine.x2, y2: gableLine.y2, line: gableLine })
+ }
+ }
+ })
+
+ /** 벽과 이어진 마루를 그린다. */
+ drawWallRidgeLine.forEach((current) => {
+ const { currentBaseLine, prevBaseLine, nextBaseLine } = current
+ const currentLine = currentBaseLine.line
+ const prevLine = prevBaseLine.line
+ const nextLine = nextBaseLine.line
+ let beforePrevLine, afterNextLine
+ const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
+ const nextDegree = getDegreeByChon(nextLine.attributes.pitch)
+ const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2).toNumber()
+ const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2).toNumber()
+ const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1)
+ const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1)
+
+ /** 이전 라인의 전라인, 다음 라인의 다음라인을 찾는다 */
+ drawBaseLines.forEach((line, index) => {
+ if (line === prevBaseLine) {
+ beforePrevLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length]
+ }
+ if (line === nextBaseLine) {
+ afterNextLine = drawBaseLines[(index + 1) % drawBaseLines.length]
+ }
+ })
+
+ let oppositeLine
+ baseLines
+ .filter((line) => line !== currentLine)
+ .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2))
+ .forEach((oppCurrLine) => {
+ let checkEdge
+ if (currentVectorX === 0) {
+ checkEdge = {
+ vertex1: { x: currentMidX, y: currentMidY },
+ vertex2: { x: oppCurrLine.x1, y: currentMidY },
+ }
+ } else {
+ checkEdge = {
+ vertex1: { x: currentMidX, y: currentMidY },
+ vertex2: { x: currentMidX, y: oppCurrLine.y1 },
+ }
+ }
+ const lineEdge = { vertex1: { x: oppCurrLine.x1, y: oppCurrLine.y1 }, vertex2: { x: oppCurrLine.x2, y: oppCurrLine.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection && isPointOnLine(oppCurrLine, intersection)) {
+ const size =
+ calcLinePlaneSize({
+ x1: checkEdge.vertex1.x,
+ y1: checkEdge.vertex1.y,
+ x2: intersection.x,
+ y2: intersection.y,
+ }) / 10
+ oppositeLine = { intersection, size, oppCurrLine }
+ }
+ })
+
+ const ridgePoints = []
+ if (oppositeLine) {
+ const { intersection, size, oppCurrLine } = oppositeLine
+ ridgePoints.push({ x: intersection.x, y: intersection.y, size })
+ const oppPrevLine = baseLines.find((line) => line.x2 === oppCurrLine.x1 && line.y2 === oppCurrLine.y1)
+ const oppNextLine = baseLines.find((line) => line.x1 === oppCurrLine.x2 && line.y1 === oppCurrLine.y2)
+
+ const oppositeRoofs = []
+ const oppositeMidX = Big(oppCurrLine.x1).plus(Big(oppCurrLine.x2)).div(2)
+ const oppositeMidY = Big(oppCurrLine.y1).plus(Big(oppCurrLine.y2)).div(2)
+ const oppositeVectorX = Math.sign(oppCurrLine.x2 - oppCurrLine.x1)
+ const oppositeVectorY = Math.sign(oppCurrLine.y2 - oppCurrLine.y1)
+
+ let oppRoofLine
+
+ if (Math.sign(oppCurrLine.x1 - oppCurrLine.x2) === 0) {
+ const checkEdge = {
+ vertex1: { x: oppPrevLine.x1, y: oppositeMidY.toNumber() },
+ vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === oppositeVectorX && Math.sign(line.y2 - line.y1) === oppositeVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ oppositeRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(oppositeMidX).abs().pow(2).plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ } else {
+ const checkEdge = {
+ vertex1: { x: oppositeMidX.toNumber(), y: oppPrevLine.y1 },
+ vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === oppositeVectorX && Math.sign(line.y2 - line.y1) === oppositeVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ oppositeRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(oppositeMidX).abs().pow(2).plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ }
+ if (oppositeRoofs.length > 0) {
+ oppRoofLine = oppositeRoofs.sort((a, b) => a.size - b.size)[0].line
+ }
+
+ if (oppRoofLine) {
+ const ridgeEdge = { vertex1: { x: currentMidX, y: currentMidY }, vertex2: { x: intersection.x, y: intersection.y } }
+
+ if (oppCurrLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
+ const oppRoofSize = Big(oppRoofLine.attributes.planeSize).div(20)
+
+ if (oppPrevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
+ let oppPrevVector = getHalfAngleVector(oppCurrLine, oppPrevLine)
+ oppPrevVector = { x: oppPrevVector.x, y: oppPrevVector.y }
+
+ /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
+ const prevCheckPoint = {
+ x: Big(oppCurrLine.x1).plus(Big(oppPrevVector.x).times(10)),
+ y: Big(oppCurrLine.y1).plus(Big(oppPrevVector.y).times(10)),
+ }
+
+ if (!checkWallPolygon.inPolygon(prevCheckPoint)) {
+ oppPrevVector = { x: -oppPrevVector.x, y: -oppPrevVector.y }
+ }
+
+ const oppPrevHipEdge = {
+ vertex1: {
+ x: oppRoofLine.x1,
+ y: oppRoofLine.y1,
+ },
+ vertex2: {
+ x: Big(oppRoofLine.x1).plus(Big(oppPrevVector.x).times(oppRoofSize)).toNumber(),
+ y: Big(oppRoofLine.y1).plus(Big(oppPrevVector.y).times(oppRoofSize)).toNumber(),
+ },
+ }
+
+ const isOppPrev = edgesIntersection(oppPrevHipEdge, ridgeEdge)
+
+ if (
+ isOppPrev &&
+ isPointOnLine(
+ {
+ x1: oppPrevHipEdge.vertex1.x,
+ y1: oppPrevHipEdge.vertex1.y,
+ x2: oppPrevHipEdge.vertex2.x,
+ y2: oppPrevHipEdge.vertex2.y,
+ },
+ isOppPrev,
+ )
+ ) {
+ const size = Big(isOppPrev.x).minus(currentMidX).abs().pow(2).plus(Big(isOppPrev.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber()
+ ridgePoints.push({ x: isOppPrev.x, y: isOppPrev.y, size })
+ }
+ }
+ if (oppNextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
+ let oppNextVector = getHalfAngleVector(oppCurrLine, oppNextLine)
+ oppNextVector = { x: oppNextVector.x, y: oppNextVector.y }
+
+ /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
+ const nextCheckPoint = {
+ x: Big(oppCurrLine.x2).plus(Big(oppNextVector.x).times(10)),
+ y: Big(oppCurrLine.y2).plus(Big(oppNextVector.y).times(10)),
+ }
+
+ if (!checkWallPolygon.inPolygon(nextCheckPoint)) {
+ oppNextVector = { x: -oppNextVector.x, y: -oppNextVector.y }
+ }
+
+ const oppNextHipEdge = {
+ vertex1: {
+ x: oppRoofLine.x2,
+ y: oppRoofLine.y2,
+ },
+ vertex2: {
+ x: Big(oppRoofLine.x2).plus(Big(oppNextVector.x).times(oppRoofSize)).toNumber(),
+ y: Big(oppRoofLine.y2).plus(Big(oppNextVector.y).times(oppRoofSize)).toNumber(),
+ },
+ }
+
+ const isOppNext = edgesIntersection(oppNextHipEdge, ridgeEdge)
+ if (
+ isOppNext &&
+ isPointOnLine(
+ {
+ x1: oppNextHipEdge.vertex1.x,
+ y1: oppNextHipEdge.vertex1.y,
+ x2: oppNextHipEdge.vertex2.x,
+ y2: oppNextHipEdge.vertex2.y,
+ },
+ isOppNext,
+ )
+ ) {
+ const size = Big(isOppNext.x).minus(currentMidX).abs().pow(2).plus(Big(isOppNext.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber()
+ ridgePoints.push({ x: isOppNext.x, y: isOppNext.y, size })
+ }
+ }
+ } else {
+ baseHipLines.forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(ridgeEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ const size = Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt()
+ ridgePoints.push({ x: intersection.x, y: intersection.y, size })
+ }
+ }
+ })
+ }
+
+ if (prevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
+ let beforePrevVector = getHalfAngleVector(prevLine, beforePrevLine)
+ const checkPoint = {
+ x: Big(prevLine.x1).plus(Big(beforePrevVector.x).times(10)),
+ y: Big(prevLine.y1).plus(Big(beforePrevVector.y).times(10)),
+ }
+ if (!checkWallPolygon.inPolygon(checkPoint)) {
+ beforePrevVector = { x: -beforePrevVector.x, y: -beforePrevVector.y }
+ }
+
+ const hipEdge = {
+ vertex1: { x: prevLine.x1, y: prevLine.y1 },
+ vertex2: {
+ x: Big(prevLine.x1).plus(Big(beforePrevVector.x).times(prevLine.attributes.planeSize)).toNumber(),
+ y: Big(prevLine.y1).plus(Big(beforePrevVector.y).times(prevLine.attributes.planeSize)).toNumber(),
+ },
+ }
+
+ const isLines = []
+ drawBaseLines
+ .filter((base) => base !== currentBaseLine && base !== prevBaseLine && base !== beforePrevLine)
+ .forEach((base) => {
+ const lineEdge = { vertex1: { x: base.line.x1, y: base.line.y1 }, vertex2: { x: base.line.x2, y: base.line.y2 } }
+ const intersection = edgesIntersection(hipEdge, lineEdge)
+ if (intersection && isPointOnLine(base.line, intersection)) {
+ const size = Big(intersection.x)
+ .minus(prevLine.x1)
+ .abs()
+ .pow(2)
+ .plus(Big(intersection.y).minus(prevLine.y1).abs().pow(2))
+ .sqrt()
+ .toNumber()
+ isLines.push({ intersection, size })
+ }
+ })
+
+ if (isLines.length > 0) {
+ const hipSize = getAdjacent(isLines.sort((a, b) => a.size - b.size)[0].size / 2)
+ const hipPoint = [
+ prevLine.x1,
+ prevLine.y1,
+ Big(prevLine.x1).plus(Big(beforePrevVector.x).times(hipSize)).toNumber(),
+ Big(prevLine.y1).plus(Big(beforePrevVector.y).times(hipSize)).toNumber(),
+ ]
+
+ const hipEdge = { vertex1: { x: hipPoint[0], y: hipPoint[1] }, vertex2: { x: hipPoint[2], y: hipPoint[3] } }
+ const intersection = edgesIntersection(ridgeEdge, hipEdge)
+ if (
+ intersection &&
+ (isPointOnLine({ x1: hipPoint[0], y1: hipPoint[1], x2: hipPoint[2], y2: hipPoint[3] }, intersection) ||
+ (Math.abs(hipPoint[0] - intersection.x) < 1 && Math.abs(hipPoint[1] - intersection.y) < 1) ||
+ (Math.abs(hipPoint[2] - intersection.x) < 1 && Math.abs(hipPoint[3] - intersection.y) < 1))
+ ) {
+ const size = Big(intersection.x)
+ .minus(currentMidX)
+ .abs()
+ .pow(2)
+ .plus(Big(intersection.y).minus(currentMidY).abs().pow(2))
+ .sqrt()
+ .toNumber()
+ ridgePoints.push({ x: intersection.x, y: intersection.y, size })
+ }
+ }
+ }
+ if (nextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && afterNextLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
+ let afterNextVector = getHalfAngleVector(nextLine, afterNextLine)
+ const checkPoint = {
+ x: Big(nextLine.x1).plus(Big(afterNextVector.x).times(10)),
+ y: Big(nextLine.y1).plus(Big(afterNextVector.y).times(10)),
+ }
+ if (!checkWallPolygon.inPolygon(checkPoint)) {
+ afterNextVector = { x: -afterNextVector.x, y: -afterNextVector.y }
+ }
+
+ const hipEdge = {
+ vertex1: { x: nextLine.x2, y: nextLine.y2 },
+ vertex2: {
+ x: Big(nextLine.x2).plus(Big(afterNextVector.x).times(nextLine.attributes.planeSize)).toNumber(),
+ y: Big(nextLine.y2).plus(Big(afterNextVector.y).times(nextLine.attributes.planeSize)).toNumber(),
+ },
+ }
+
+ const isLines = []
+ drawBaseLines
+ .filter((base) => base !== currentBaseLine && base !== nextBaseLine && base !== afterNextLine)
+ .forEach((base) => {
+ const lineEdge = { vertex1: { x: base.line.x1, y: base.line.y1 }, vertex2: { x: base.line.x2, y: base.line.y2 } }
+ const intersection = edgesIntersection(hipEdge, lineEdge)
+ if (intersection && isPointOnLine(base.line, intersection)) {
+ const size = Big(intersection.x)
+ .minus(nextLine.x2)
+ .abs()
+ .pow(2)
+ .plus(Big(intersection.y).minus(nextLine.y2).abs().pow(2))
+ .sqrt()
+ .toNumber()
+ isLines.push({ intersection, size })
+ }
+ })
+ if (isLines.length > 0) {
+ const hipSize = getAdjacent(isLines.sort((a, b) => a.size - b.size)[0].size / 2)
+ const hipPoint = [
+ nextLine.x2,
+ nextLine.y2,
+ Big(nextLine.x2).plus(Big(afterNextVector.x).times(hipSize)).toNumber(),
+ Big(nextLine.y2).plus(Big(afterNextVector.y).times(hipSize)).toNumber(),
+ ]
+ const hipEdge = { vertex1: { x: hipPoint[0], y: hipPoint[1] }, vertex2: { x: hipPoint[2], y: hipPoint[3] } }
+ const intersection = edgesIntersection(ridgeEdge, hipEdge)
+
+ if (
+ intersection &&
+ (isPointOnLine({ x1: hipPoint[0], y1: hipPoint[1], x2: hipPoint[2], y2: hipPoint[3] }, intersection) ||
+ (Math.abs(hipPoint[0] - intersection.x) < 1 && Math.abs(hipPoint[1] - intersection.y) < 1) ||
+ (Math.abs(hipPoint[2] - intersection.x) < 1 && Math.abs(hipPoint[3] - intersection.y) < 1))
+ ) {
+ const size = Big(intersection.x)
+ .minus(currentMidX)
+ .abs()
+ .pow(2)
+ .plus(Big(intersection.y).minus(currentMidY).abs().pow(2))
+ .sqrt()
+ .toNumber()
+ ridgePoints.push({ x: intersection.x, y: intersection.y, size })
+ }
+ }
+ }
+ }
+ }
+
+ if (ridgePoints.length === 0 || baseRidgeCount >= getMaxRidge(baseLines.length)) return
+ const ridgeEndPoint = ridgePoints.sort((a, b) => a.size - b.size)[0]
+ const ridgePoint = { x1: currentMidX, y1: currentMidY, x2: ridgeEndPoint.x, y2: ridgeEndPoint.y }
+
+ /** 포인트가 지붕밖에 있는 경우 조정*/
+ if (!roof.inPolygon({ x: ridgePoint.x1, y: ridgePoint.y1 })) {
+ const checkEdge = { vertex1: { x: ridgePoint.x2, y: ridgePoint.y2 }, vertex2: { x: ridgePoint.x1, y: ridgePoint.y1 } }
+ const isPoints = []
+ roof.lines.forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection && isPointOnLine(line, intersection)) {
+ if (
+ Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x) === Math.sign(checkEdge.vertex1.x - intersection.x) &&
+ Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y) === Math.sign(checkEdge.vertex1.y - intersection.y)
+ ) {
+ const size = Big(intersection.x)
+ .minus(ridgePoint.x2)
+ .abs()
+ .pow(2)
+ .plus(Big(intersection.y).minus(ridgePoint.y2).abs().pow(2))
+ .sqrt()
+ .toNumber()
+ isPoints.push({ x: intersection.x, y: intersection.y, size })
+ }
+ }
+ })
+ if (isPoints.length > 0) {
+ const newPoint = isPoints.sort((a, b) => a.size - b.size)[0]
+ ridgePoint.x1 = newPoint.x
+ ridgePoint.y1 = newPoint.y
+ }
+ }
+
+ if (!roof.inPolygon({ x: ridgePoint.x2, y: ridgePoint.y2 })) {
+ const checkEdge = { vertex1: { x: ridgePoint.x1, y: ridgePoint.y1 }, vertex2: { x: ridgePoint.x2, y: ridgePoint.y2 } }
+ const isPoints = []
+ roof.lines.forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection && isPointOnLine(line, intersection)) {
+ if (
+ Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x) === Math.sign(checkEdge.vertex1.x - intersection.x) &&
+ Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y) === Math.sign(checkEdge.vertex1.y - intersection.y)
+ ) {
+ const size = Big(intersection.x)
+ .minus(ridgePoint.x1)
+ .abs()
+ .pow(2)
+ .plus(Big(intersection.y).minus(ridgePoint.y1).abs().pow(2))
+ .sqrt()
+ .toNumber()
+ isPoints.push({ x: intersection.x, y: intersection.y, size })
+ }
+ }
+ })
+ if (isPoints.length > 0) {
+ const newPoint = isPoints.sort((a, b) => a.size - b.size)[0]
+ ridgePoint.x2 = newPoint.x
+ ridgePoint.y2 = newPoint.y
+ }
+ }
+
+ const ridge = drawRidgeLine([ridgePoint.x1, ridgePoint.y1, ridgePoint.x2, ridgePoint.y2], canvas, roof, textMode)
+ baseRidgeLines.push(ridge)
+ baseRidgeCount++
+
+ /** 현재 라인의 지붕 라인을 찾는다. */
+ const intersectionRoofs = []
+ let currentRoof
+ if (currentVectorX === 0) {
+ const checkEdge = {
+ vertex1: { x: prevLine.x1, y: currentMidY },
+ vertex2: { x: currentMidX, y: currentMidY },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ } else {
+ const checkEdge = {
+ vertex1: { x: currentMidX, y: prevLine.y1 },
+ vertex2: { x: currentMidX, y: currentMidY },
+ }
+ roof.lines
+ .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY)
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection) {
+ if (isPointOnLine(line, intersection)) {
+ intersectionRoofs.push({
+ line,
+ intersection,
+ size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
+ })
+ }
+ }
+ })
+ }
+ if (intersectionRoofs.length > 0) {
+ currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line
+ }
+ if (currentRoof) {
+ const prevHipPoint = [currentRoof.x1, currentRoof.y1, currentMidX, currentMidY]
+ const nextHipPoint = [currentRoof.x2, currentRoof.y2, currentMidX, currentMidY]
+
+ const prevHipLine = drawHipLine(prevHipPoint, canvas, roof, textMode, null, prevDegree, prevDegree)
+ const nextHipLine = drawHipLine(nextHipPoint, canvas, roof, textMode, null, nextDegree, nextDegree)
+ baseHipLines.push({ x1: prevHipLine.x1, y1: prevHipLine.y1, x2: prevHipLine.x2, y2: prevHipLine.y2, line: prevHipLine })
+ baseHipLines.push({ x1: nextHipLine.x1, y1: nextHipLine.y1, x2: nextHipLine.x2, y2: nextHipLine.y2, line: nextHipLine })
+ }
+ })
+
/** ⨆ 모양 처마에 추녀마루를 그린다. */
drawEavesFirstLines.forEach((current) => {
// 확인용 라인, 포인트 제거
@@ -2942,9 +4666,9 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
let beforePrevLine, afterNextLine
/** 이전 라인의 경사 */
- const prevDegree = prevLine.attributes.pitch > 0 ? getDegreeByChon(prevLine.attributes.pitch) : prevLine.attributes.degree
+ const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
/** 다음 라인의 경사 */
- const currentDegree = currentLine.attributes.pitch > 0 ? getDegreeByChon(currentLine.attributes.pitch) : currentLine.attributes.degree
+ const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
/** 이전 라인의 전라인, 다음 라인의 다음라인을 찾는다 */
drawBaseLines.forEach((line, index) => {
@@ -2960,8 +4684,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
let prevVector = getHalfAngleVector(prevLine, currentLine)
let nextVector = getHalfAngleVector(currentLine, nextLine)
- let prevHipVector = { x: Big(prevVector.x), y: Big(prevVector.y) }
- let nextHipVector = { x: Big(nextVector.x), y: Big(nextVector.y) }
+ let prevHipVector = { x: prevVector.x, y: prevVector.y }
+ let nextHipVector = { x: nextVector.x, y: nextVector.y }
/** 각 라인의 흐름 방향을 확인한다. */
const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint)
@@ -2979,7 +4703,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
y: Big(y1).plus(Big(prevHipVector.y).times(10)),
}
if (!checkWallPolygon.inPolygon(prevCheckPoint)) {
- prevHipVector = { x: Big(prevHipVector.x).neg().toNumber(), y: Big(prevHipVector.y).neg().toNumber() }
+ prevHipVector = { x: -prevHipVector.x, y: -prevHipVector.y }
}
/** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
@@ -2988,12 +4712,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
y: Big(y2).plus(Big(nextHipVector.y).times(10)),
}
if (!checkWallPolygon.inPolygon(nextCheckPoint)) {
- nextHipVector = { x: Big(nextHipVector.x).neg().toNumber(), y: Big(nextHipVector.y).neg().toNumber() }
+ nextHipVector = { x: -nextHipVector.x, y: -nextHipVector.y }
}
/** 현재 라인의 길이를 기준으로 추녀 마루의 길이를 삼각함수를 사용하여 판단한다.*/
let hipLength = currentSize.div(2).pow(2).plus(currentSize.div(2).pow(2)).sqrt()
+ console.log('hipLength 1 :', hipLength.toNumber())
/**
* 현재 라인에서 2번째 전 라인과 2번째 후 라인의 각도가 같을때 -_- 와 같은 형태로 판단하고
* 맞은 편 외벽선까지의 거리를 확인후 currentSize 를 조정한다.
@@ -3023,6 +4748,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const intersectionSize = Big(intersection.x)
.minus(Big(currentMidX))
.plus(Big(intersection.y).minus(Big(currentMidY)))
+ .abs()
if (intersectionSize.lt(currentSize)) {
currentSize = intersectionSize
}
@@ -3033,12 +4759,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
} else {
if (currentAngle !== beforePrevAngle && currentAngle !== afterNextAngle && beforePrevLine !== afterNextLine) {
const beforePrevX1 = beforePrevLine.x1,
- beforePrevY1 = beforePrevLine.y1,
- beforePrevX2 = beforePrevLine.x2,
- beforePrevY2 = beforePrevLine.y2
- const afterNextX1 = afterNextLine.x1,
- afterNextY1 = afterNextLine.y1,
- afterNextX2 = afterNextLine.x2,
+ beforePrevY1 = beforePrevLine.y1
+ const afterNextX2 = afterNextLine.x2,
afterNextY2 = afterNextLine.y2
/** beforePrevLine 과 afterNextLine 을 연결하는 사각형의 경우 6각으로 판단 */
@@ -3050,7 +4772,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
).length > 0
/** 6각 */
- // console.log('isConnect :', isConnect)
+ console.log('isConnect :', isConnect)
if (isConnect) {
const checkScale = currentSize.pow(2).plus(currentSize.pow(2)).sqrt()
const intersectBaseLine = []
@@ -3110,6 +4832,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const rightAngleLine = baseLines
.filter(
(line) =>
+ line !== currentLine &&
line !== prevLine &&
line !== nextLine &&
(prevAngle === calculateAngle(line.startPoint, line.endPoint) || nextAngle === calculateAngle(line.startPoint, line.endPoint)),
@@ -3169,8 +4892,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
checkHipPoints = [
x1,
y1,
- Big(x1).plus(Big(prevHipVector.x).times(hipLength)).round(2),
- Big(y1).plus(Big(prevHipVector.y).times(hipLength)).round(2),
+ Big(x1).plus(Big(prevHipVector.x).times(hipLength)).round(2).toNumber(),
+ Big(y1).plus(Big(prevHipVector.y).times(hipLength)).round(2).toNumber(),
]
}
@@ -3178,8 +4901,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
checkHipPoints = [
x2,
y2,
- Big(x2).plus(Big(nextHipVector.x).times(hipLength)).round(2),
- Big(y2).plus(Big(nextHipVector.y).times(hipLength)).round(2),
+ Big(x2).plus(Big(nextHipVector.x).times(hipLength)).round(2).toNumber(),
+ Big(y2).plus(Big(nextHipVector.y).times(hipLength)).round(2).toNumber(),
]
}
@@ -3200,7 +4923,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
.minus(Big(checkHipPoints[0]))
.pow(2)
.plus(Big(intersection.y).minus(Big(checkHipPoints[1])).pow(2))
- .sqrt(),
+ .sqrt()
+ .toNumber(),
})
}
})
@@ -3220,20 +4944,20 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
.minus(Big(checkHipPoints[0]))
.pow(2)
.plus(Big(intersection.y).minus(Big(checkHipPoints[1])).pow(2))
- .sqrt(),
+ .sqrt()
+ .toNumber(),
})
}
})
- const intersection = intersectPoints.reduce((prev, current) => (prev.distance.lt(current.distance) ? prev : current), intersectPoints[0])
- if (intersection) {
- hipLength = intersection.distance.div(2)
+ if (intersectPoints.length > 0) {
+ const intersection = intersectPoints.sort((a, b) => a.distance - b.distance)[0]
+ hipLength = getAdjacent(intersection.distance) / 2
}
}
}
}
}
-
let prevHipLine, nextHipLine
/** 이전라인과의 연결지점에 추녀마루를 그린다. */
if (baseHipLines.filter((line) => line.x1 === x1 && line.y1 === y1).length === 0) {
@@ -3242,6 +4966,44 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
y: Big(y1).plus(Big(prevHipVector.y).times(hipLength)).round(1),
}
+ if (!roof.inPolygon({ x: prevEndPoint.x.toNumber(), y: prevEndPoint.y.toNumber() })) {
+ const checkEdge = { vertex1: { x: prevEndPoint.x.toNumber(), y: prevEndPoint.y.toNumber() }, vertex2: { x: x1, y: y1 } }
+ const intersectionPoints = []
+ roof.lines.forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection && !intersection.isIntersectionOutside) {
+ const size = Big(intersection.x)
+ .minus(Big(prevEndPoint.x))
+ .pow(2)
+ .plus(Big(intersection.y).minus(Big(prevEndPoint.y)).pow(2))
+ .sqrt()
+ .toNumber()
+ intersectionPoints.push({ intersection, size })
+ }
+ })
+ if (intersectionPoints.length > 0) {
+ const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection
+ prevEndPoint.x = Big(intersection.x)
+ prevEndPoint.y = Big(intersection.y)
+ }
+ }
+ const overlapLine = baseHipLines.find((line) => isPointOnLine(line, { x: prevEndPoint.x.toNumber(), y: prevEndPoint.y.toNumber() }))
+
+ if (overlapLine) {
+ if (
+ isPointOnLine({ x1: x1, y1: y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber() }, { x: overlapLine.x1, y: overlapLine.y1 })
+ ) {
+ prevEndPoint.x = Big(overlapLine.x1)
+ prevEndPoint.y = Big(overlapLine.y1)
+ }
+ if (
+ isPointOnLine({ x1: x1, y1: y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber() }, { x: overlapLine.x2, y: overlapLine.y2 })
+ ) {
+ prevEndPoint.x = Big(overlapLine.x2)
+ prevEndPoint.y = Big(overlapLine.y2)
+ }
+ }
const intersectRidgeLine = []
baseRidgeLines.forEach((line) => {
const intersection = edgesIntersection(
@@ -3328,6 +5090,46 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
y: Big(y2).plus(Big(nextHipVector.y).times(hipLength)).round(1),
}
+ if (!roof.inPolygon({ x: nextEndPoint.x.toNumber(), y: nextEndPoint.y.toNumber() })) {
+ const checkEdge = { vertex1: { x: nextEndPoint.x.toNumber(), y: nextEndPoint.y.toNumber() }, vertex2: { x: x2, y: y2 } }
+ const intersectionPoints = []
+ roof.lines.forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection && !intersection.isIntersectionOutside) {
+ const size = Big(intersection.x)
+ .minus(Big(nextEndPoint.x))
+ .pow(2)
+ .plus(Big(intersection.y).minus(Big(nextEndPoint.y)).pow(2))
+ .sqrt()
+ .toNumber()
+ intersectionPoints.push({ intersection, size })
+ }
+ })
+ if (intersectionPoints.length > 0) {
+ const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection
+ nextEndPoint.x = Big(intersection.x)
+ nextEndPoint.y = Big(intersection.y)
+ }
+ }
+
+ const overlapLine = baseHipLines.find((line) => isPointOnLine(line, { x: nextEndPoint.x.toNumber(), y: nextEndPoint.y.toNumber() }))
+
+ if (overlapLine) {
+ if (
+ isPointOnLine({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber() }, { x: overlapLine.x1, y: overlapLine.y1 })
+ ) {
+ nextEndPoint.x = Big(overlapLine.x1)
+ nextEndPoint.y = Big(overlapLine.y1)
+ }
+ if (
+ isPointOnLine({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber() }, { x: overlapLine.x2, y: overlapLine.y2 })
+ ) {
+ nextEndPoint.x = Big(overlapLine.x2)
+ nextEndPoint.y = Big(overlapLine.y2)
+ }
+ }
+
const intersectRidgeLine = []
baseRidgeLines.forEach((line) => {
const intersection = edgesIntersection(
@@ -3466,181 +5268,234 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const xVector = Big(currentMidX).minus(Big(startPoint.x)).round(0, Big.roundDown)
const yVector = Big(currentMidY).minus(Big(startPoint.y)).round(0, Big.roundDown)
-
- if (gableType.includes(beforePrevLine.line.attributes.type) || gableType.includes(afterNextLine.line.attributes.type)) {
- const oppositeLine = gableType.includes(beforePrevLine.line.attributes.type) ? beforePrevLine.line : afterNextLine.line
- const oppositeAngle = calculateAngle(oppositeLine.startPoint, oppositeLine.endPoint)
- let checkEdge
- if (Math.sign(oppositeLine.x1 - oppositeLine.x2) === 0) {
- checkEdge = { vertex1: startPoint, vertex2: { x: oppositeLine.x1, y: startPoint.y } }
+ if (beforePrevLine === afterNextLine) {
+ console.log('4각 :::::::: ')
+ const oppositeMidX = Big(beforePrevLine.x2).plus(Big(beforePrevLine.x1)).div(2)
+ const oppositeMidY = Big(beforePrevLine.y2).plus(Big(beforePrevLine.y1)).div(2)
+ if (beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
+ ridgeSize = oppositeMidX
+ .minus(Big(startPoint.x))
+ .abs()
+ .pow(2)
+ .plus(oppositeMidY.minus(Big(startPoint.y)).abs().pow(2))
+ .sqrt()
+ .minus(Big(beforePrevLine.line.attributes.planeSize).div(20))
} else {
- checkEdge = { vertex1: startPoint, vertex2: { x: startPoint.x, y: oppositeLine.y1 } }
- }
- if (currentAngle === oppositeAngle) {
- const oppositeEdge = {
- vertex1: { x: oppositeLine.x1, y: oppositeLine.y1 },
- vertex2: { x: oppositeLine.x2, y: oppositeLine.y2 },
+ let width = 0
+ if (beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
+ width = beforePrevLine.line.attributes.width / 2
+ } else if (beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) {
+ width = beforePrevLine.line.attributes.width
}
- const intersection = edgesIntersection(oppositeEdge, checkEdge)
- if (intersection) {
- ridgeSize = Big(intersection.x)
+ const checkEdge = { vertex1: { x: startPoint.x, y: startPoint.y }, vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() } }
+ const vectorX = Math.sign(startPoint.x - oppositeMidX.toNumber())
+ const vectorY = Math.sign(startPoint.y - oppositeMidY.toNumber())
+ const oppositeRoofPoints = []
+ roof.lines.forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdge, lineEdge)
+ if (intersection && Math.sign(startPoint.x - intersection.x) === vectorX && Math.sign(startPoint.y - intersection.y) === vectorY) {
+ const size = Big(intersection.x)
+ .minus(Big(startPoint.x))
+ .pow(2)
+ .plus(Big(intersection.y).minus(Big(startPoint.y)).pow(2))
+ .sqrt()
+ .toNumber()
+ oppositeRoofPoints.push({ intersection, size })
+ }
+ })
+ if (oppositeRoofPoints.length > 0) {
+ const oppositeRoofPoint = oppositeRoofPoints.sort((a, b) => a.size - b.size)[0].intersection
+ ridgeSize = Big(oppositeRoofPoint.x)
.minus(Big(startPoint.x))
+ .abs()
.pow(2)
- .plus(Big(intersection.y).minus(Big(startPoint.y)).pow(2))
+ .plus(Big(oppositeRoofPoint.y).minus(Big(startPoint.y)).abs().pow(2))
+ .minus(width)
.sqrt()
}
- } else {
- const intersectPoints = []
- roof.lines
- .filter(
- (line) =>
- Math.sign(oppositeLine.x1 - oppositeLine.x2) === Math.sign(line.x1 - line.x2) &&
- Math.sign(oppositeLine.y1 - oppositeLine.y2) === Math.sign(line.y1 - line.y2),
- )
- .forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(lineEdge, checkEdge)
- if (intersection) {
- const size = Big(startPoint.x)
- .minus(Big(intersection.x))
- .pow(2)
- .plus(Big(startPoint.y).minus(Big(intersection.y)).pow(2))
- .sqrt()
- .toNumber()
- intersectPoints.push({ intersection, size })
- }
- })
- intersectPoints.sort((a, b) => a.size - b.size)
- if (intersectPoints.length > 0) {
- ridgeSize = Big(intersectPoints[0].size)
- }
}
} else {
- /** baseLines 에서 가장 작은 x1과 가장 큰 x1, 가장 작은 y1과 가장 큰 y1을 계산*/
- let minX = Infinity
- let maxX = -Infinity
- let minY = Infinity
- let maxY = -Infinity
-
- baseLines.forEach((line) => {
- if (line.x1 < minX) {
- minX = line.x1
+ if (gableType.includes(beforePrevLine.line.attributes.type) || gableType.includes(afterNextLine.line.attributes.type)) {
+ const oppositeLine = gableType.includes(beforePrevLine.line.attributes.type) ? beforePrevLine.line : afterNextLine.line
+ const oppositeAngle = calculateAngle(oppositeLine.startPoint, oppositeLine.endPoint)
+ let checkEdge
+ if (Math.sign(oppositeLine.x1 - oppositeLine.x2) === 0) {
+ checkEdge = { vertex1: startPoint, vertex2: { x: oppositeLine.x1, y: startPoint.y } }
+ } else {
+ checkEdge = { vertex1: startPoint, vertex2: { x: startPoint.x, y: oppositeLine.y1 } }
}
- if (line.x1 > maxX) {
- maxX = line.x1
- }
- if (line.y1 < minY) {
- minY = line.y1
- }
- if (line.y1 > maxY) {
- maxY = line.y1
- }
- })
- const checkLength = Big(maxX)
- .minus(Big(minX))
- .pow(2)
- .plus(Big(maxY).minus(Big(minY)).pow(2))
- .sqrt()
-
- const checkEdges = {
- vertex1: { x: startPoint.x, y: startPoint.y },
- vertex2: {
- x: Big(startPoint.x).minus(checkLength.times(Math.sign(xVector))),
- y: Big(startPoint.y).minus(checkLength.times(Math.sign(yVector))),
- },
- }
-
- /** 맞은편 벽 까지의 길이 판단을 위한 교차되는 line*/
- const intersectBaseLine = []
- baseLines
- .filter((line) => {
- /** currentAngle 의 반대 각도인 라인 */
- const angle = calculateAngle(line.startPoint, line.endPoint)
- switch (currentAngle) {
- case 90:
- return angle === -90
- case -90:
- return angle === 90
- case 0:
- return angle === 180
- case 180:
- return angle === 0
+ if (currentAngle === oppositeAngle) {
+ const oppositeEdge = {
+ vertex1: { x: oppositeLine.x1, y: oppositeLine.y1 },
+ vertex2: { x: oppositeLine.x2, y: oppositeLine.y2 },
}
- })
- .filter((line) => {
- const currentMinX = Math.min(x1, x2)
- const currentMaxX = Math.max(x1, x2)
- const currentMinY = Math.min(y1, y2)
- const currentMaxY = Math.max(y1, y2)
- const lineMinX = Math.min(line.x1, line.x2)
- const lineMaxX = Math.max(line.x1, line.x2)
- const lineMinY = Math.min(line.y1, line.y2)
- const lineMaxY = Math.max(line.y1, line.y2)
-
- /** currentLine 의 안쪽에 있거나 currentLine이 line의 안쪽에 있는 라인 */
- if (Big(currentLine.y1).minus(Big(currentLine.y2)).abs().lte(1)) {
- return (
- (currentMinX <= lineMinX && lineMinX <= currentMaxX) ||
- (currentMinX <= lineMaxX && lineMaxX <= currentMaxX) ||
- (lineMinX <= currentMinX && currentMinX <= lineMaxX) ||
- (lineMinX <= currentMaxX && currentMaxX <= lineMaxX)
- )
- } else {
- return (
- (currentMinY <= lineMinY && lineMinY <= currentMaxY) ||
- (currentMinY <= lineMaxY && lineMaxY <= currentMaxY) ||
- (lineMinY <= currentMinY && currentMinY <= lineMaxY) ||
- (lineMinY <= currentMaxY && currentMaxY <= lineMaxY)
- )
- }
- })
- .forEach((line, index) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(checkEdges, lineEdge)
+ const intersection = edgesIntersection(oppositeEdge, checkEdge)
if (intersection) {
- intersectBaseLine.push({ intersection, line })
+ ridgeSize = Big(intersection.x)
+ .minus(Big(startPoint.x))
+ .pow(2)
+ .plus(Big(intersection.y).minus(Big(startPoint.y)).pow(2))
+ .sqrt()
+ }
+ } else {
+ const intersectPoints = []
+ roof.lines
+ .filter(
+ (line) =>
+ Math.sign(oppositeLine.x1 - oppositeLine.x2) === Math.sign(line.x1 - line.x2) &&
+ Math.sign(oppositeLine.y1 - oppositeLine.y2) === Math.sign(line.y1 - line.y2),
+ )
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(lineEdge, checkEdge)
+ if (intersection) {
+ const size = Big(startPoint.x)
+ .minus(Big(intersection.x))
+ .pow(2)
+ .plus(Big(startPoint.y).minus(Big(intersection.y)).pow(2))
+ .sqrt()
+ .toNumber()
+ intersectPoints.push({ intersection, size })
+ }
+ })
+ intersectPoints.sort((a, b) => a.size - b.size)
+ if (intersectPoints.length > 0) {
+ ridgeSize = Big(intersectPoints[0].size)
+ }
+ }
+ } else {
+ /** baseLines 에서 가장 작은 x1과 가장 큰 x1, 가장 작은 y1과 가장 큰 y1을 계산*/
+ let minX = Infinity
+ let maxX = -Infinity
+ let minY = Infinity
+ let maxY = -Infinity
+
+ baseLines.forEach((line) => {
+ if (line.x1 < minX) {
+ minX = line.x1
+ }
+ if (line.x1 > maxX) {
+ maxX = line.x1
+ }
+ if (line.y1 < minY) {
+ minY = line.y1
+ }
+ if (line.y1 > maxY) {
+ maxY = line.y1
}
})
-
- /** 맞은편 라인 */
- const oppositeLine = intersectBaseLine.reduce((prev, current) => {
- const prevDistance = Big(prev.intersection.x)
- .minus(Big(startPoint.x))
+ const checkLength = Big(maxX)
+ .minus(Big(minX))
.pow(2)
- .plus(Big(prev.intersection.y).minus(Big(startPoint.y)).pow(2))
+ .plus(Big(maxY).minus(Big(minY)).pow(2))
.sqrt()
- const currentDistance = Big(current.intersection.x)
- .minus(Big(startPoint.x))
- .pow(2)
- .plus(Big(current.intersection.y).minus(Big(startPoint.y)).pow(2))
- .sqrt()
- return prevDistance < currentDistance ? prev : current
- }, intersectBaseLine[0])
- /** 맞은편 라인까지의 길이 = 전체 길이 - 현재라인의 길이 */
- const oppositeSize = oppositeLine
- ? Big(oppositeLine.intersection.x)
+ const checkEdges = {
+ vertex1: { x: startPoint.x, y: startPoint.y },
+ vertex2: {
+ x: Big(startPoint.x).minus(checkLength.times(Math.sign(xVector))),
+ y: Big(startPoint.y).minus(checkLength.times(Math.sign(yVector))),
+ },
+ }
+
+ /** 맞은편 벽 까지의 길이 판단을 위한 교차되는 line*/
+ const intersectBaseLine = []
+ baseLines
+ .filter((line) => {
+ /** currentAngle 의 반대 각도인 라인 */
+ const angle = calculateAngle(line.startPoint, line.endPoint)
+ switch (currentAngle) {
+ case 90:
+ return angle === -90
+ case -90:
+ return angle === 90
+ case 0:
+ return angle === 180
+ case 180:
+ return angle === 0
+ }
+ })
+ .filter((line) => {
+ const currentMinX = Math.min(x1, x2)
+ const currentMaxX = Math.max(x1, x2)
+ const currentMinY = Math.min(y1, y2)
+ const currentMaxY = Math.max(y1, y2)
+ const lineMinX = Math.min(line.x1, line.x2)
+ const lineMaxX = Math.max(line.x1, line.x2)
+ const lineMinY = Math.min(line.y1, line.y2)
+ const lineMaxY = Math.max(line.y1, line.y2)
+
+ /** currentLine 의 안쪽에 있거나 currentLine이 line의 안쪽에 있는 라인 */
+ if (Big(currentLine.y1).minus(Big(currentLine.y2)).abs().lte(1)) {
+ return (
+ (currentMinX <= lineMinX && lineMinX <= currentMaxX) ||
+ (currentMinX <= lineMaxX && lineMaxX <= currentMaxX) ||
+ (lineMinX <= currentMinX && currentMinX <= lineMaxX) ||
+ (lineMinX <= currentMaxX && currentMaxX <= lineMaxX)
+ )
+ } else {
+ return (
+ (currentMinY <= lineMinY && lineMinY <= currentMaxY) ||
+ (currentMinY <= lineMaxY && lineMaxY <= currentMaxY) ||
+ (lineMinY <= currentMinY && currentMinY <= lineMaxY) ||
+ (lineMinY <= currentMaxY && currentMaxY <= lineMaxY)
+ )
+ }
+ })
+ .forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersection = edgesIntersection(checkEdges, lineEdge)
+ if (intersection) {
+ intersectBaseLine.push({ intersection, line })
+ }
+ })
+
+ /** 맞은편 라인 */
+ const oppositeLine = intersectBaseLine.reduce((prev, current) => {
+ const prevDistance = Big(prev.intersection.x)
.minus(Big(startPoint.x))
.pow(2)
- .plus(Big(oppositeLine.intersection.y).minus(Big(startPoint.y)).pow(2))
+ .plus(Big(prev.intersection.y).minus(Big(startPoint.y)).pow(2))
.sqrt()
- .minus(currentSize.div(2))
- .round(1)
- : Infinity
+ const currentDistance = Big(current.intersection.x)
+ .minus(Big(startPoint.x))
+ .pow(2)
+ .plus(Big(current.intersection.y).minus(Big(startPoint.y)).pow(2))
+ .sqrt()
+ return prevDistance < currentDistance ? prev : current
+ }, intersectBaseLine[0])
- /** 이전, 다음 라인중 길이가 짧은 길이*/
- const lineMinSize = prevBaseLine.size < nextBaseLine.size ? Big(prevBaseLine.size).div(10) : Big(nextBaseLine.size).div(10)
+ /** 맞은편 라인까지의 길이 = 전체 길이 - 현재라인의 길이 */
+ const oppositeSize = oppositeLine
+ ? Big(oppositeLine.intersection.x)
+ .minus(Big(startPoint.x))
+ .pow(2)
+ .plus(Big(oppositeLine.intersection.y).minus(Big(startPoint.y)).pow(2))
+ .sqrt()
+ .minus(currentSize.div(2))
+ .round(1)
+ .toNumber()
+ : Infinity
- /** 마루의 길이는 이전 다음 라인중 짧은것의 길이와 현재라인부터 맞은편 라인까지의 길이에서 현재 라인의 길이를 뺀 것중 짧은 길이 */
- ridgeSize = Big(Math.min(oppositeSize, lineMinSize))
+ /** 이전, 다음 라인중 길이가 짧은 길이*/
+ const lineMinSize =
+ prevBaseLine.size < nextBaseLine.size ? Big(prevBaseLine.size).div(10).toNumber() : Big(nextBaseLine.size).div(10).toNumber()
+ /** 마루의 길이는 이전 다음 라인중 짧은것의 길이와 현재라인부터 맞은편 라인까지의 길이에서 현재 라인의 길이를 뺀 것중 짧은 길이 */
+ ridgeSize = Big(Math.min(oppositeSize, lineMinSize))
+ }
}
if (ridgeSize.gt(0) && baseRidgeCount < getMaxRidge(baseLines.length)) {
const points = [
startPoint.x,
startPoint.y,
- Big(startPoint.x).minus(ridgeSize.times(Math.sign(xVector))),
- Big(startPoint.y).minus(ridgeSize.times(Math.sign(yVector))),
+ Big(startPoint.x)
+ .minus(ridgeSize.times(Math.sign(xVector)))
+ .toNumber(),
+ Big(startPoint.y)
+ .minus(ridgeSize.times(Math.sign(yVector)))
+ .toNumber(),
]
/** 동일 라인이 있는지 확인. */
@@ -3694,21 +5549,15 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
if (gableType.includes(beforePrevLine.line.attributes.type) || gableType.includes(afterNextLine.line.attributes.type)) {
const oppositeLine = gableType.includes(beforePrevLine.line.attributes.type) ? beforePrevLine.line : afterNextLine.line
- const oppositeAngle = calculateAngle(oppositeLine.startPoint, oppositeLine.endPoint)
if (Math.sign(ridgeLine.x1 - ridgeLine.x2) === 0) {
const gableVector = Math.sign(ridgeLine.x1 - oppositeLine.x1)
const prevVector = ridgeLine.x1 === prevHipLine.x1 ? Math.sign(ridgeLine.x1 - prevHipLine.x2) : Math.sign(ridgeLine.x2 - prevHipLine.x1)
- const nextVector = ridgeLine.x1 === nextHipLine.x1 ? Math.sign(ridgeLine.x1 - nextHipLine.x2) : Math.sign(ridgeLine.x2 - nextHipLine.x1)
const firstHipLine = gableVector === prevVector ? prevHipLine : nextHipLine
const firstDegree =
gableVector === Math.sign(ridgeLine.x1 - prevLine.x1)
- ? prevLine.attributes.pitch > 0
- ? getDegreeByChon(prevLine.attributes.pitch)
- : prevLine.attributes.degree
- : nextLine.attributes.pitch > 0
- ? getDegreeByChon(nextLine.attributes.pitch)
- : nextLine.attributes.degree
+ ? getDegreeByChon(prevLine.attributes.pitch)
+ : getDegreeByChon(nextLine.attributes.pitch)
const oppositeRoofPoints = [
ridgeLine.x2,
@@ -3744,12 +5593,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const secondHipLine = gableVector === prevVector ? nextHipLine : prevHipLine
const secondDegree =
gableVector === Math.sign(ridgeLine.x1 - prevLine.x1)
- ? nextLine.attributes.pitch > 0
- ? getDegreeByChon(nextLine.attributes.pitch)
- : nextLine.attributes.degree
- : prevLine.attributes.pitch > 0
- ? getDegreeByChon(prevLine.attributes.pitch)
- : prevLine.attributes.degree
+ ? getDegreeByChon(nextLine.attributes.pitch)
+ : getDegreeByChon(prevLine.attributes.pitch)
const intersections = []
const checkEdge = {
@@ -3807,18 +5652,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
} else {
const gableVector = Math.sign(ridgeLine.y1 - oppositeLine.y1)
const prevVector = ridgeLine.y1 === prevHipLine.y1 ? Math.sign(ridgeLine.y1 - prevHipLine.y2) : Math.sign(ridgeLine.y1 - prevHipLine.y1)
- const nextVector = ridgeLine.y1 === nextHipLine.y1 ? Math.sign(ridgeLine.y1 - nextHipLine.y2) : Math.sign(ridgeLine.y1 - nextHipLine.y1)
/** 마루와 박공지붕을 연결하기위한 추녀마루 라인 */
const firstHipLine = gableVector === prevVector ? prevHipLine : nextHipLine
const firstDegree =
gableVector === Math.sign(ridgeLine.y1 - prevLine.y1)
- ? prevLine.attributes.pitch > 0
- ? getDegreeByChon(prevLine.attributes.pitch)
- : prevLine.attributes.degree
- : nextLine.attributes.pitch > 0
- ? getDegreeByChon(nextLine.attributes.pitch)
- : nextLine.attributes.degree
+ ? getDegreeByChon(prevLine.attributes.pitch)
+ : getDegreeByChon(nextLine.attributes.pitch)
const oppositeRoofPoints = [
ridgeLine.x2,
@@ -3855,12 +5695,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const secondHipLine = gableVector === prevVector ? nextHipLine : prevHipLine
const secondDegree =
gableVector === Math.sign(ridgeLine.y1 - prevLine.y1)
- ? nextLine.attributes.pitch > 0
- ? getDegreeByChon(nextLine.attributes.pitch)
- : nextLine.attributes.degree
- : prevLine.attributes.pitch > 0
- ? getDegreeByChon(prevLine.attributes.pitch)
- : prevLine.attributes.degree
+ ? getDegreeByChon(nextLine.attributes.pitch)
+ : getDegreeByChon(prevLine.attributes.pitch)
const intersections = []
const checkEdge = {
@@ -3917,6 +5753,11 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}
}
}
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'checkLine' || obj.name === 'checkCircle')
+ .forEach((obj) => canvas.remove(obj))
+ canvas.renderAll()
})
/** 중복제거 */
@@ -3950,19 +5791,19 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const currentLine = currentBaseLine.line
const prevLine = prevBaseLine.line
const nextLine = nextBaseLine.line
- let { x1, x2, y1, y2, size } = currentBaseLine
+ let { x1, x2, y1, y2 } = currentBaseLine
/** 이전 라인의 경사 */
- const prevDegree = prevLine.attributes.pitch > 0 ? getDegreeByChon(prevLine.attributes.pitch) : prevLine.attributes.degree
+ const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
/** 다음 라인의 경사 */
- const currentDegree = currentLine.attributes.pitch > 0 ? getDegreeByChon(currentLine.attributes.pitch) : currentLine.attributes.degree
+ const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
/** 이전, 다음라인의 사잇각의 vector를 구한다. */
let prevVector = getHalfAngleVector(prevLine, currentLine)
let nextVector = getHalfAngleVector(currentLine, nextLine)
- let prevHipVector = { x: Big(prevVector.x), y: Big(prevVector.y) }
- let nextHipVector = { x: Big(nextVector.x), y: Big(nextVector.y) }
+ let prevHipVector = { x: prevVector.x, y: prevVector.y }
+ let nextHipVector = { x: nextVector.x, y: nextVector.y }
/** 각 라인의 흐름 방향을 확인한다. */
const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint)
@@ -3979,7 +5820,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
y: Big(y1).plus(Big(prevHipVector.y).times(10)),
}
if (!checkWallPolygon.inPolygon(prevCheckPoint)) {
- prevHipVector = { x: Big(prevHipVector.x).neg(), y: Big(prevHipVector.y).neg() }
+ prevHipVector = { x: -prevHipVector.x, y: -prevHipVector.y }
}
/** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
@@ -3988,12 +5829,12 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
y: Big(y2).plus(Big(nextHipVector.y).times(10)),
}
if (!checkWallPolygon.inPolygon(nextCheckPoint)) {
- nextHipVector = { x: Big(nextHipVector.x).neg(), y: Big(nextHipVector.y).neg() }
+ nextHipVector = { x: -nextHipVector.x, y: -nextHipVector.y }
}
let prevHipLine, nextHipLine
/** 이전라인과의 연결지점에 추녀마루를 그린다. */
- if (baseHipLines.filter((line) => line.x1 === x1 && line.y1 === y1).length === 0 && eavesType.includes(prevLine.attributes.type)) {
+ if (baseHipLines.filter((line) => line.x1 === x1 && line.y1 === y1).length === 0 && prevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
let prevEndPoint = {
x: Big(x1).plus(Big(prevHipVector.x).times(hipLength)).round(2),
y: Big(y1).plus(Big(prevHipVector.y).times(hipLength)).round(2),
@@ -4006,16 +5847,16 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
.filter((line) => line !== currentLine && line !== prevLine && line !== nextLine)
.filter((line) => {
if (currentAngle === 0 || currentAngle === 180) {
- return Big(line.y1).minus(Big(y1)).s === nextHipVector.y.s || Big(line.y2).minus(Big(y1)).s === nextHipVector.y.s
+ return Math.sign(line.y1 - y1) === nextHipVector.y || Math.sign(line.y2 - y1) === nextHipVector.y
} else {
- return Big(line.x1).minus(Big(x1)).s === nextHipVector.x.s || Big(line.x2).minus(Big(x1)).s === nextHipVector.x.s
+ return Math.sign(line.x1 - x1) === nextHipVector.x || Math.sign(line.x2 - x1) === nextHipVector.x
}
})
.forEach((line) => {
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
const intersection = edgesIntersection(prevEndEdge, lineEdge)
- if (intersection && Big(intersection.x - x1).s === nextHipVector.x.s && Big(intersection.y - y1).s === nextHipVector.y.s) {
+ if (intersection && Math.sign(intersection.x - x1) === nextHipVector.x && Math.sign(intersection.y - y1) === nextHipVector.y) {
const size = Big(intersection.x - x1)
.abs()
.pow(2)
@@ -4132,7 +5973,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}
}
/** 다음라인과의 연결지점에 추녀마루를 그린다. */
- if (baseHipLines.filter((line) => line.x1 === x2 && line.y1 === y2).length === 0 && eavesType.includes(nextLine.attributes.type)) {
+ if (baseHipLines.filter((line) => line.x1 === x2 && line.y1 === y2).length === 0 && nextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
let nextEndPoint = {
x: Big(x2).plus(Big(nextHipVector.x).times(hipLength)).round(2),
y: Big(y2).plus(Big(nextHipVector.y).times(hipLength)).round(2),
@@ -4148,16 +5989,16 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
.filter((line) => line !== currentLine && line !== prevLine && line !== nextLine)
.filter((line) => {
if (currentAngle === 0 || currentAngle === 180) {
- return Big(line.y1).minus(Big(y1)).s === nextHipVector.y.s || Big(line.y2).minus(Big(y1)).s === nextHipVector.y.s
+ return Math.sign(line.y1 - y1) === nextHipVector.y || Math.sign(line.y2 - y1) === nextHipVector.y
} else {
- return Big(line.x1).minus(Big(x1)).s === nextHipVector.x.s || Big(line.x2).minus(Big(x1)).s === nextHipVector.x.s
+ return Math.sign(line.x1 - x1) === nextHipVector.x || Math.sign(line.x2 - x1) === nextHipVector.x
}
})
.forEach((line) => {
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
const intersection = edgesIntersection(nextEndEdge, lineEdge)
- if (intersection && Big(intersection.x - x2).s === nextHipVector.x.s && Big(intersection.y - y2).s === nextHipVector.y.s) {
+ if (intersection && Math.sign(intersection.x - x2) === nextHipVector.x && Math.sign(intersection.y - y2) === nextHipVector.y) {
const size = Big(intersection.x - x2)
.abs()
.pow(2)
@@ -4181,15 +6022,24 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}, intersectBaseLine[0])
if (intersectBase) {
+ const size = Big(getAdjacent(intersectBase.size))
nextEndPoint = {
x: Big(x2)
- .plus(Big(nextHipVector.x).times(intersectBase.size.div(2)))
+ .plus(Big(nextHipVector.x).times(size.div(2)))
.round(2),
y: Big(y2)
- .plus(Big(nextHipVector.y).times(intersectBase.size.div(2)))
+ .plus(Big(nextHipVector.y).times(size.div(2)))
.round(2),
}
}
+ const checkLine = new fabric.Line([x2, y2, nextEndPoint.x, nextEndPoint.y], {
+ stroke: 'red',
+ strokeWidth: 4,
+ parentId: roofId,
+ name: 'checkLine',
+ })
+ canvas.add(checkLine)
+ canvas.renderAll()
const intersectRidgeLine = []
baseRidgeLines.forEach((line) => {
@@ -4198,7 +6048,31 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
{ vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
)
- if (intersection && !intersection.isIntersectionOutside) {
+ console.log('intersection : ', intersection)
+ console.log('isPointOnLine(line, intersection)', isPointOnLine(line, intersection))
+ console.log(
+ 'line : ',
+ (line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) ||
+ (line.x2 <= intersection.x && line.x1 >= intersection.x && line.y2 <= intersection.y && line.y1 >= intersection.y),
+ )
+
+ if (intersection) {
+ const checkCircle = new fabric.Circle({
+ left: intersection.x,
+ top: intersection.y,
+ radius: 5,
+ fill: 'blue',
+ parentId: roofId,
+ name: 'checkCircle',
+ })
+ canvas.add(checkCircle)
+ canvas.renderAll()
+ }
+ if (
+ intersection &&
+ ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) ||
+ (line.x2 <= intersection.x && line.x1 >= intersection.x && line.y2 <= intersection.y && line.y1 >= intersection.y))
+ ) {
intersectRidgeLine.push({
intersection,
distance: Big(intersection.x)
@@ -4209,6 +6083,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
})
}
})
+
+ canvas.remove(checkLine)
+ canvas.renderAll()
+
const intersectRidge = intersectRidgeLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectRidgeLine[0])
if (intersectRidge) {
@@ -4449,8 +6327,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
.filter((line) => eavesType.includes(line.attributes.type))
.forEach((line) => {
const pitch = line.attributes.pitch
- const degree = line.attributes.degree
- degreeAllLine.push(pitch > 0 ? getDegreeByChon(pitch) : degree)
+ degreeAllLine.push(getDegreeByChon(pitch))
})
let currentDegree, prevDegree
@@ -4519,6 +6396,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
},
)
+ const checkPointCnt = checkPoints.filter((point) => point.point.x === checkPoint.point.x && point.point.y === checkPoint.point.y).length
const isConnectLine =
((line.line.x1 === point[0] && line.line.y1 === point[1]) || (line.line.x2 === point[0] && line.line.y2 === point[1])) &&
checkAngel1 === checkAngel2
@@ -4527,7 +6405,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
(point[0] === line.x2 && point[1] === line.y2 && point[2] === line.x1 && point[3] === line.y1) ||
(point[0] === line.x1 && point[1] === line.y1 && point[2] === line.x2 && point[3] === line.y2)
- if (isConnectLine || isOverlap || isSameLine) {
+ if (checkPointCnt === 1 && (isConnectLine || isOverlap || isSameLine)) {
/** 겹치는 추녀마루와 하나의 선으로 변경*/
const mergePoint = [
{ x: point[0], y: point[1] },
@@ -4796,18 +6674,16 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
/** 직교 하는 포인트가 없는 경우 남은 포인트 처리 */
const checkEdgeLines = []
noRidgeHipPoints.forEach((current) => {
- noRidgeHipPoints.forEach((current) => {
- noRidgeHipPoints
- .filter((point) => point !== current)
- .forEach((point) => {
- checkEdgeLines.push(
- { vertex1: { x: current.x2, y: current.y2 }, vertex2: { x: current.x2, y: point.y2 } },
- { vertex1: { x: current.x2, y: point.y2 }, vertex2: { x: point.x2, y: point.y2 } },
- { vertex1: { x: point.x2, y: point.y2 }, vertex2: { x: point.x2, y: current.y2 } },
- { vertex1: { x: point.x2, y: current.y2 }, vertex2: { x: current.x2, y: current.y2 } },
- )
- })
- })
+ noRidgeHipPoints
+ .filter((point) => point !== current)
+ .forEach((point) => {
+ checkEdgeLines.push(
+ { vertex1: { x: current.x2, y: current.y2 }, vertex2: { x: current.x2, y: point.y2 } },
+ { vertex1: { x: current.x2, y: point.y2 }, vertex2: { x: point.x2, y: point.y2 } },
+ { vertex1: { x: point.x2, y: point.y2 }, vertex2: { x: point.x2, y: current.y2 } },
+ { vertex1: { x: point.x2, y: current.y2 }, vertex2: { x: current.x2, y: current.y2 } },
+ )
+ })
})
/** 연결되지 않은 포인트를 찾아서 해당 포인트를 가지고 있는 라인을 찾는다. */
@@ -5084,6 +6960,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const ridgeAllPoints = []
baseRidgeLines.forEach((line) => ridgeAllPoints.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 }))
+ baseGableRidgeLines.forEach((line) => ridgeAllPoints.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 }))
/** hip 중에 지붕의 라인과 만나지 않은 선을 확인.*/
baseHipLines
@@ -5451,11 +7328,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
})
})
- /** 중복 제거 */
- baseHipLines.forEach((hipLine) => {
- baseHipLines.filter((hipLine2) => hipLine !== hipLine2).forEach((hipLine2) => {})
- })
-
const innerLines = [...baseRidgeLines, ...baseGableRidgeLines, ...baseGableLines, ...baseHipLines.map((line) => line.line)]
const uniqueInnerLines = []
@@ -5480,7 +7352,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
canvas.renderAll()
roof.innerLines = uniqueInnerLines
- // modifyRidge(roof, canvas, textMode)
+ /** 확인용 라인 제거 */
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'checkCircle' || obj.name === 'checkLine')
+ .forEach((obj) => canvas.remove(obj))
+ canvas.renderAll()
+
/*
drawCenterLine(roof, canvas, textMode)
*/
@@ -5497,6 +7375,21 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
* @param currentDegree
*/
const drawHipLine = (points, canvas, roof, textMode, currentRoof, prevDegree, currentDegree) => {
+ /** 대각선인 경우 경사를 조정해서 계산*/
+ const baseX = Big(points[0]).minus(Big(points[2])).abs()
+ const baseY = Big(points[1]).minus(Big(points[3])).abs()
+ if (baseX.gt(1) && baseY.gt(1)) {
+ const base = calcLinePlaneSize({ x1: points[0], y1: points[1], x2: points[2], y2: points[3] }) / 10
+ const heightX = baseX.times(Math.tan((currentDegree * Math.PI) / 180)).round()
+ const heightY = baseY.times(Math.tan((prevDegree * Math.PI) / 180)).round()
+ const degreeX = Math.atan(heightX.div(base).toNumber()) / (Math.PI / 180)
+ const degreeY = Math.atan(heightY.div(base).toNumber()) / (Math.PI / 180)
+ if (Math.abs(degreeX - degreeY) < 1) {
+ currentDegree = degreeX
+ prevDegree = degreeY
+ }
+ }
+
const hip = new QLine(points, {
parentId: roof.id,
fontSize: roof.fontSize,
@@ -5667,7 +7560,7 @@ const normalizeVector = (v) => {
/** 벡터의 크기(길이)*/
const magnitude = Big(v.x).pow(2).plus(Big(v.y).pow(2)).sqrt()
if (magnitude.eq(0)) return { x: 0, y: 0 } // 크기가 0일 경우 (예외 처리)
- return { x: Big(v.x).div(magnitude).toNumber(), y: Big(v.y).div(magnitude).toNumber() }
+ return { x: Math.sign(Big(v.x).div(magnitude).toNumber()), y: Math.sign(Big(v.y).div(magnitude).toNumber()) }
}
/**
@@ -5721,1593 +7614,16 @@ export const segmentsOverlap = (line1, line2) => {
}
/**
- * 외벽선 속성에 따라서 모양을 수정한다.
- * @param roof
- * @param canvas
- * @param textMode
- */
-const modifyRidge = (roof, canvas, textMode) => {
- const ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roof.id)
- const hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roof.id)
-
- ridgeLines.forEach((ridge) => {
- let ridgeHip1 = hipLines.filter((hip) => hip.x2 === ridge.x1 && hip.y2 === ridge.y1)
- let ridgeHip2 = hipLines.filter((hip) => hip.x2 === ridge.x2 && hip.y2 === ridge.y2)
- if (ridgeHip1.length >= 2) {
- let currentRoof = roof.lines
- .filter((roofLine) => roofLine.attributes !== undefined && roofLine.attributes.ridgeCoordinate !== undefined)
- .find((roofLine) => roofLine.attributes.ridgeCoordinate.x1 === ridge.x1 && roofLine.attributes.ridgeCoordinate.y1 === ridge.y1)
- if (currentRoof === undefined) {
- currentRoof = roof.lines.find(
- (roofLine) =>
- (roofLine.x1 === ridgeHip1[0].x1 &&
- roofLine.y1 === ridgeHip1[0].y1 &&
- roofLine.x2 === ridgeHip1[1].x1 &&
- roofLine.y2 === ridgeHip1[1].y1) ||
- (roofLine.x1 === ridgeHip1[1].x1 &&
- roofLine.y1 === ridgeHip1[1].y1 &&
- roofLine.x2 === ridgeHip1[0].x1 &&
- roofLine.y2 === ridgeHip1[0].y1),
- )
- if (currentRoof !== undefined) {
- currentRoof.attributes.ridgeCoordinate = { x1: ridge.x1, y1: ridge.y1 }
- }
- }
- if (currentRoof !== undefined) {
- switch (currentRoof.attributes.type) {
- case LINE_TYPE.WALLLINE.EAVES:
- changeEavesRoof(currentRoof, canvas, textMode)
- break
- case LINE_TYPE.WALLLINE.GABLE:
- changeGableRoof(currentRoof, canvas, textMode)
- break
- case LINE_TYPE.WALLLINE.HIPANDGABLE:
- changeHipAndGableRoof(currentRoof, canvas, textMode)
- break
- case LINE_TYPE.WALLLINE.JERKINHEAD:
- changeJerkInHeadRoof(currentRoof, canvas, textMode)
- break
- case LINE_TYPE.WALLLINE.WALL:
- changeWallRoof(currentRoof, canvas, textMode)
- break
- }
- }
- }
- if (ridgeHip2.length >= 2) {
- let currentRoof = roof.lines
- .filter((roofLine) => roofLine.attributes !== undefined && roofLine.attributes.ridgeCoordinate !== undefined)
- .find((roofLine) => roofLine.attributes.ridgeCoordinate.x1 === ridge.x2 && roofLine.attributes.ridgeCoordinate.y1 === ridge.y2)
- if (currentRoof === undefined) {
- currentRoof = roof.lines.find(
- (roofLine) =>
- (roofLine.x1 === ridgeHip2[0].x1 &&
- roofLine.y1 === ridgeHip2[0].y1 &&
- roofLine.x2 === ridgeHip2[1].x1 &&
- roofLine.y2 === ridgeHip2[1].y1) ||
- (roofLine.x1 === ridgeHip2[1].x1 &&
- roofLine.y1 === ridgeHip2[1].y1 &&
- roofLine.x2 === ridgeHip2[0].x1 &&
- roofLine.y2 === ridgeHip2[0].y1),
- )
- if (currentRoof !== undefined) {
- currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 }
- }
- }
- if (currentRoof !== undefined) {
- switch (currentRoof.attributes.type) {
- case LINE_TYPE.WALLLINE.EAVES:
- changeEavesRoof(currentRoof, canvas, textMode)
- break
- case LINE_TYPE.WALLLINE.GABLE:
- changeGableRoof(currentRoof, canvas, textMode)
- break
- case LINE_TYPE.WALLLINE.HIPANDGABLE:
- changeHipAndGableRoof(currentRoof, canvas, textMode)
- break
- case LINE_TYPE.WALLLINE.JERKINHEAD:
- changeJerkInHeadRoof(currentRoof, canvas, textMode)
- break
- case LINE_TYPE.WALLLINE.WALL:
- changeWallRoof(currentRoof, canvas, textMode)
- break
- }
- }
- }
- })
-}
-
-/*
- 최대 생성 마루 갯수
+ * 최대 생성 마루 갯수
+ * @param length
+ * @returns {number}
*/
const getMaxRidge = (length) => {
return (length - 4) / 2 + 1
}
/**
- * 처마지붕으로 변경
- * @param currentRoof
- * @param canvas
- * @param textMode
- */
-const changeEavesRoof = (currentRoof, canvas, textMode) => {
- if (currentRoof.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
- const roofId = currentRoof.attributes.roofId
- const wall = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId)
- const roof = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.ROOF && object.id === roofId)
- let hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roofId)
- let ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roofId)
- let wallLine = wall.lines.filter((w) => w.id === currentRoof.attributes.wallLine)
- if (wallLine.length > 0) {
- wallLine = wallLine[0]
- }
- let prevRoof, nextRoof
- roof.lines.forEach((r, index) => {
- if (r.id === currentRoof.id) {
- currentRoof = r
- prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1]
- nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1]
- }
- })
-
- const midX = Big(currentRoof.x1).plus(Big(currentRoof.x2)).div(2) // 지붕의 X 중심
- const midY = Big(currentRoof.y1).plus(Big(currentRoof.y2)).div(2) // 지붕의 Y 중심
- const midWallX = Big(wallLine.x1).plus(Big(wallLine.x2)).div(2)
- const midWallY = Big(wallLine.y1).plus(Big(wallLine.y2)).div(2) // 벽의 Y 중심
- const alpha = midX.minus(midWallX) // 벽과 지붕의 X 거리
- const beta = midY.minus(midWallY) // 벽과 지붕의 Y 거리
- const hypotenuse = alpha.pow(2).plus(beta.pow(2)).sqrt() // 벽과 지붕의 거리
- const hipX2 = midX.plus(alpha.div(hypotenuse).times(Big(currentRoof.length).div(2)).neg())
- const hipY2 = midY.plus(beta.div(hypotenuse).times(Big(currentRoof.length).div(2)).neg())
-
- const innerLines = canvas
- ?.getObjects()
- .filter(
- (object) =>
- object.attributes?.roofId === roofId &&
- object.attributes?.currentRoofId === currentRoof.id &&
- object.x1 !== undefined &&
- object.x2 !== undefined,
- )
-
- innerLines
- .filter(
- (line) =>
- line.name !== LINE_TYPE.SUBLINE.RIDGE &&
- line.name !== LINE_TYPE.SUBLINE.HIP &&
- line.name !== LINE_TYPE.SUBLINE.VALLEY &&
- line.name !== OUTER_LINE_TYPE.OUTER_LINE &&
- line.name !== 'wallLine',
- )
- .forEach((line) => {
- roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id)
- canvas?.remove(line)
- })
-
- ridgeLines = ridgeLines.filter(
- (ridge) =>
- (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) ||
- (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1),
- )
- hipLines = hipLines.filter(
- (hip) => (hip.x1 === currentRoof.x1 && hip.y1 === currentRoof.y1) || (hip.x1 === currentRoof.x2 && hip.y1 === currentRoof.y2),
- )
-
- if (hipLines === undefined || hipLines.length === 0) {
- hipLines = innerLines.filter(
- (line) =>
- (line.x1 === currentRoof.x1 && line.y1 === currentRoof.y1) ||
- (line.x2 === currentRoof.x1 && line.y2 === currentRoof.y1) ||
- (line.x1 === currentRoof.x2 && line.y1 === currentRoof.y2) ||
- (line.x2 === currentRoof.x2 && line.y2 === currentRoof.y2),
- )
- }
-
- if ((ridgeLines === undefined || ridgeLines.length === 0) && hipLines.length >= 2) {
- let points = []
- hipLines.forEach((hip) => {
- points.push({ x: hip.x1, y: hip.y1 })
- points.push({ x: hip.x2, y: hip.y2 })
- })
-
- const pointSet = new Set()
- const duplicatePoints = []
-
- points.forEach((point) => {
- const pointKey = `${point.x},${point.y}`
- if (pointSet.has(pointKey)) {
- duplicatePoints.push(point)
- } else {
- pointSet.add(pointKey)
- }
- })
-
- ridgeLines = innerLines
- .filter((r) => r !== hipLines[0] && r !== hipLines[1])
- .filter(
- (r) => (r.x1 === duplicatePoints[0].x && r.y1 === duplicatePoints[0].y) || (r.x2 === duplicatePoints[0].x && r.y2 === duplicatePoints[0].y),
- )
- if (ridgeLines.length > 0) {
- currentRoof.attributes.ridgeCoordinate = { x1: duplicatePoints[0].x, y1: duplicatePoints[0].y }
- }
- }
-
- if (ridgeLines.length > 0) {
- const ridge = ridgeLines[0]
- if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) {
- ridge.set({
- x1: hipX2.toNumber(),
- y1: hipY2.toNumber(),
- x2: ridge.x2,
- y2: ridge.y2,
- })
- currentRoof.attributes.ridgeCoordinate = { x1: ridge.x1, y1: ridge.y1 }
- }
- if (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1) {
- ridge.set({
- x1: ridge.x1,
- y1: ridge.y1,
- x2: hipX2.toNumber(),
- y2: hipY2.toNumber(),
- })
- currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 }
- }
- //Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
- ridge.attributes.planeSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 })
- ridge.attributes.actualSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 })
- }
-
- hipLines.forEach((hip) => {
- roof.innerLines = roof.innerLines.filter((h) => h.id !== hip.id)
- canvas.remove(hip)
- })
-
- canvas?.renderAll()
-
- const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree
- const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree
- const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree
-
- const hip1 = new QLine([currentRoof.x1, currentRoof.y1, hipX2.toNumber(), hipY2.toNumber()], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.HIP,
- textMode: textMode,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({
- x1: currentRoof.x1,
- y1: currentRoof.y1,
- x2: hipX2.toNumber(),
- y2: hipY2.toNumber(),
- }),
- actualSize:
- prevDegree === currentDegree
- ? calcLineActualSize(
- {
- x1: currentRoof.x1,
- y1: currentRoof.y1,
- x2: hipX2.toNumber(),
- y2: hipY2.toNumber(),
- },
- currentDegree,
- )
- : 0,
- },
- })
- const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
- const hip1Height = Math.round(hip1Base / Math.tan(((90 - currentDegree) * Math.PI) / 180))
- canvas?.add(hip1)
- roof.innerLines.push(hip1)
-
- const hip2 = new QLine([currentRoof.x2, currentRoof.y2, hipX2.toNumber(), hipY2.toNumber()], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.HIP,
- textMode: textMode,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({
- x1: currentRoof.x2,
- y1: currentRoof.y2,
- x2: hipX2.toNumber(),
- y2: hipY2.toNumber(),
- }),
- actualSize:
- currentDegree === nextDegree
- ? calcLineActualSize(
- {
- x1: currentRoof.x2,
- y1: currentRoof.y2,
- x2: hipX2.toNumber(),
- y2: hipY2.toNumber(),
- },
- currentDegree,
- )
- : 0,
- },
- })
- canvas?.add(hip2)
- roof.innerLines.push(hip2)
- }
-}
-
-/**
- * 박공지붕으로 변경
- * @param currentRoof
- * @param canvas
- * @param textMode
- */
-const changeGableRoof = (currentRoof, canvas, textMode) => {
- if (currentRoof.attributes.type === LINE_TYPE.WALLLINE.GABLE) {
- const roofId = currentRoof.attributes.roofId
- const roof = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.ROOF && object.id === roofId)
- let hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roofId)
- let ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roofId)
-
- const midX = Big(currentRoof.x1).plus(Big(currentRoof.x2)).div(2) // 지붕의 X 중심
- const midY = Big(currentRoof.y1).plus(Big(currentRoof.y2)).div(2) // 지붕의 Y 중심
-
- const innerLines = canvas
- ?.getObjects()
- .filter(
- (object) =>
- object.attributes?.roofId === roofId &&
- object.attributes?.currentRoofId === currentRoof.id &&
- object.x1 !== undefined &&
- object.x2 !== undefined,
- )
-
- let prevRoof, nextRoof
- roof.lines.forEach((r, index) => {
- if (r.id === currentRoof.id) {
- currentRoof = r
- prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1]
- nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1]
- }
- })
-
- innerLines
- .filter(
- (line) =>
- line.name !== LINE_TYPE.SUBLINE.RIDGE &&
- line.name !== LINE_TYPE.SUBLINE.HIP &&
- line.name !== LINE_TYPE.SUBLINE.VALLEY &&
- line.name !== OUTER_LINE_TYPE.OUTER_LINE &&
- line.name !== 'wallLine',
- )
- .forEach((line) => {
- roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id)
- canvas?.remove(line)
- })
- canvas.renderAll()
-
- ridgeLines = ridgeLines.filter(
- (ridge) =>
- (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) ||
- (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1),
- )
- hipLines = hipLines.filter(
- (hip) => (hip.x1 === currentRoof.x1 && hip.y1 === currentRoof.y1) || (hip.x1 === currentRoof.x2 && hip.y1 === currentRoof.y2),
- )
-
- if (hipLines === undefined || hipLines.length === 0) {
- hipLines = innerLines.filter(
- (line) =>
- (line.x1 === currentRoof.x1 && line.y1 === currentRoof.y1) ||
- (line.x2 === currentRoof.x1 && line.y2 === currentRoof.y1) ||
- (line.x1 === currentRoof.x2 && line.y1 === currentRoof.y2) ||
- (line.x2 === currentRoof.x2 && line.y2 === currentRoof.y2),
- )
- }
-
- hipLines.forEach((hip) => {
- roof.innerLines = roof.innerLines.filter((h) => h.id !== hip.id)
- canvas.remove(hip)
- })
-
- if ((ridgeLines === undefined || ridgeLines.length === 0) && hipLines.length >= 2) {
- let points = []
- hipLines.forEach((hip) => {
- points.push({ x: hip.x1, y: hip.y1 })
- points.push({ x: hip.x2, y: hip.y2 })
- })
-
- const pointSet = new Set()
- const duplicatePoints = []
-
- points.forEach((point) => {
- const pointKey = `${point.x},${point.y}`
- if (pointSet.has(pointKey)) {
- duplicatePoints.push(point)
- } else {
- pointSet.add(pointKey)
- }
- })
-
- ridgeLines = innerLines
- .filter((r) => r !== hipLines[0] && r !== hipLines[1])
- .filter(
- (r) => (r.x1 === duplicatePoints[0].x && r.y1 === duplicatePoints[0].y) || (r.x2 === duplicatePoints[0].x && r.y2 === duplicatePoints[0].y),
- )
- if (ridgeLines.length > 0) {
- currentRoof.attributes.ridgeCoordinate = { x1: duplicatePoints[0].x, y1: duplicatePoints[0].y }
- }
- }
-
- if (ridgeLines !== undefined && ridgeLines.length > 0) {
- const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree
- const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree
-
- const ridge = ridgeLines[0]
- if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) {
- ridge.set({
- x1: midX.toNumber(),
- y1: midY.toNumber(),
- x2: ridge.x2,
- y2: ridge.y2,
- })
- currentRoof.attributes.ridgeCoordinate = { x1: ridge.x1, y1: ridge.y1 }
- }
- if (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1) {
- ridge.set({
- x1: ridge.x1,
- y1: ridge.y1,
- x2: midX.toNumber(),
- y2: midY.toNumber(),
- })
- currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 }
- }
- ridge.attributes.planeSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 })
- ridge.attributes.actualSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 })
-
- let hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX.toNumber(), midY.toNumber()], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.HIP,
- textMode: textMode,
- attributes: {
- roofId: roofId,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({
- x1: currentRoof.x1,
- y1: currentRoof.y1,
- x2: midX.toNumber(),
- y2: midY.toNumber(),
- }),
- actualSize: calcLineActualSize(
- {
- x1: currentRoof.x1,
- y1: currentRoof.y1,
- x2: midX.toNumber(),
- y2: midY.toNumber(),
- },
- prevDegree,
- ),
- },
- })
- canvas?.add(hip1)
- // const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
- // 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.toNumber(), midY.toNumber()], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.HIP,
- attributes: {
- roofId: roofId,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({
- x1: currentRoof.x2,
- y1: currentRoof.y2,
- x2: midX.toNumber(),
- y2: midY.toNumber(),
- }),
- actualSize: calcLineActualSize(
- {
- x1: currentRoof.x2,
- y1: currentRoof.y2,
- x2: midX.toNumber(),
- y2: midY.toNumber(),
- },
- nextDegree,
- ),
- },
- })
- canvas?.add(hip2)
- // const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10
- // 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)
- canvas?.renderAll()
- }
- }
-}
-
-/**
- * 팔작지붕으로 변경
- * @param currentRoof
- * @param canvas
- * @param textMode
- */
-const changeHipAndGableRoof = (currentRoof, canvas, textMode) => {
- if (
- currentRoof.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE &&
- currentRoof.attributes.width !== undefined &&
- currentRoof.attributes.width > 0
- ) {
- const roofId = currentRoof.attributes.roofId
- const wall = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId)
- const roof = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.ROOF && object.id === roofId)
- let hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roofId)
- let ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roofId)
- let wallLine = wall.lines.filter((w) => w.id === currentRoof.attributes.wallLine)
- if (wallLine.length > 0) {
- wallLine = wallLine[0]
- }
- let prevRoof, nextRoof
- roof.lines.forEach((r, index) => {
- if (r.id === currentRoof.id) {
- currentRoof = r
- prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1]
- nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1]
- }
- })
-
- const midX = Big(currentRoof.x1).plus(Big(currentRoof.x2)).div(2) // 지붕의 X 중심
- const midY = Big(currentRoof.y1).plus(Big(currentRoof.y2)).div(2) // 지붕의 Y 중심
- const midWallX = Big(wallLine.x1).plus(Big(wallLine.x2)).div(2) // 벽의 X 중심
- const midWallY = Big(wallLine.y1).plus(Big(wallLine.y2)).div(2) // 벽의 Y 중심
- const alpha = midX.minus(midWallX) // 벽과 지붕의 X 거리
- const beta = midY.minus(midWallY) // 벽과 지붕의 Y 거리
- // Math.sqrt(Math.pow(alpha, 2) + Math.pow(beta, 2))
- const hypotenuse = alpha.pow(2).plus(beta.pow(2)).sqrt() // 벽과 지붕의 거리
- const xWidth = Big(Math.sign(midX.minus(midWallX).toNumber()))
- .times(alpha.div(hypotenuse))
- .times(currentRoof.attributes.width) // 지붕의 X 너비
- const yWidth = Big(Math.sign(midY.minus(midWallY)))
- .times(beta.div(hypotenuse))
- .times(currentRoof.attributes.width) // 지붕의 Y 너비
- const hipX2 = Big(Math.sign(midX.minus(midWallX).toNumber()))
- .times(alpha.div(hypotenuse))
- .times(currentRoof.length / 2) // 추녀마루의 X 너비
- const hipY2 = Big(Math.sign(midY.minus(midWallY)))
- .times(beta.div(hypotenuse))
- .times(currentRoof.length / 2) // 추녀마루의 Y 너비
-
- // if (Math.sqrt(Math.pow(xWidth, 2) + Math.pow(yWidth, 2)) < Math.sqrt(Math.pow(hipX2, 2) + Math.pow(hipY2, 2))) {
- if (
- xWidth
- .pow(2)
- .plus(yWidth.pow(2))
- .sqrt()
- .lt(hipX2.pow(2).plus(hipY2.pow(2)).sqrt())
- ) {
- const innerLines = canvas
- ?.getObjects()
- .filter(
- (object) =>
- object.attributes?.roofId === roofId &&
- object.attributes?.currentRoofId === currentRoof.id &&
- object.x1 !== undefined &&
- object.x2 !== undefined,
- )
-
- innerLines
- .filter(
- (line) =>
- line.name !== LINE_TYPE.SUBLINE.RIDGE &&
- line.name !== LINE_TYPE.SUBLINE.HIP &&
- line.name !== LINE_TYPE.SUBLINE.VALLEY &&
- line.name !== OUTER_LINE_TYPE.OUTER_LINE &&
- line.name !== 'wallLine',
- )
- .forEach((line) => {
- roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id)
- canvas?.remove(line)
- })
-
- ridgeLines = ridgeLines.filter(
- (ridge) =>
- (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) ||
- (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1),
- )
- hipLines = hipLines.filter(
- (hip) => (hip.x1 === currentRoof.x1 && hip.y1 === currentRoof.y1) || (hip.x1 === currentRoof.x2 && hip.y1 === currentRoof.y2),
- )
-
- if (hipLines === undefined || hipLines.length === 0) {
- hipLines = innerLines.filter(
- (line) =>
- (line.x1 === currentRoof.x1 && line.y1 === currentRoof.y1) ||
- (line.x2 === currentRoof.x1 && line.y2 === currentRoof.y1) ||
- (line.x1 === currentRoof.x2 && line.y1 === currentRoof.y2) ||
- (line.x2 === currentRoof.x2 && line.y2 === currentRoof.y2),
- )
- }
-
- if ((ridgeLines === undefined || ridgeLines.length === 0) && hipLines.length >= 2) {
- let points = []
- hipLines.forEach((hip) => {
- points.push({ x: hip.x1, y: hip.y1 })
- points.push({ x: hip.x2, y: hip.y2 })
- })
-
- const pointSet = new Set()
- const duplicatePoints = []
-
- points.forEach((point) => {
- const pointKey = `${point.x},${point.y}`
- if (pointSet.has(pointKey)) {
- duplicatePoints.push(point)
- } else {
- pointSet.add(pointKey)
- }
- })
-
- ridgeLines = innerLines
- .filter((r) => r !== hipLines[0] && r !== hipLines[1])
- .filter(
- (r) =>
- (r.x1 === duplicatePoints[0].x && r.y1 === duplicatePoints[0].y) || (r.x2 === duplicatePoints[0].x && r.y2 === duplicatePoints[0].y),
- )
- if (ridgeLines.length > 0) {
- currentRoof.attributes.ridgeCoordinate = { x1: duplicatePoints[0].x, y1: duplicatePoints[0].y }
- }
- }
-
- hipLines.forEach((hip) => {
- roof.innerLines = roof.innerLines.filter((h) => h.id !== hip.id)
- canvas.remove(hip)
- })
- hipLines = []
-
- if (ridgeLines.length > 0) {
- const ridge = ridgeLines[0]
- if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) {
- const signX = Math.sign(midX.minus(ridge.x1).toNumber())
- const signY = Math.sign(midY.minus(ridge.y1).toNumber())
- ridge.set({
- x1: midX.minus(xWidth.abs().times(signX)).toNumber(),
- y1: midY.minus(yWidth.abs().times(signY)).toNumber(),
- x2: ridge.x2,
- y2: ridge.y2,
- })
- currentRoof.attributes.ridgeCoordinate = { x1: ridge.x1, y1: ridge.y1 }
- }
- if (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1) {
- const signX = Math.sign(midX.minus(ridge.x2).toNumber())
- const signY = Math.sign(midY.minus(ridge.y2).toNumber())
- ridge.set({
- x1: ridge.x1,
- y1: ridge.y1,
- x2: midX.minus(xWidth.abs().times(signX)).toNumber(),
- y2: midY.minus(yWidth.abs().times(signY)).toNumber(),
- })
- currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 }
- }
- ridge.attributes.planeSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 })
- ridge.attributes.actualSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 })
- }
-
- const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree
-
- const hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX.plus(hipX2).toNumber(), midY.plus(hipY2).toNumber()], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.HIP,
- textMode: textMode,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({
- x1: currentRoof.x1,
- y1: currentRoof.y1,
- x2: midX.plus(hipX2).toNumber(),
- y2: midY.plus(hipY2).toNumber(),
- }),
- actualSize: calcLineActualSize(
- {
- x1: currentRoof.x1,
- y1: currentRoof.y1,
- x2: midX.plus(hipX2).toNumber(),
- y2: midY.plus(hipY2).toNumber(),
- },
- currentDegree,
- ),
- },
- })
-
- // const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
- // 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)))
- canvas?.add(hip1)
- roof.innerLines.push(hip1)
-
- const hip2 = new QLine([currentRoof.x2, currentRoof.y2, midX.plus(hipX2).toNumber(), midY.plus(hipY2).toNumber()], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.HIP,
- textMode: textMode,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({
- x1: currentRoof.x2,
- y1: currentRoof.y2,
- x2: midX.plus(hipX2).toNumber(),
- y2: midY.plus(hipY2).toNumber(),
- }),
- actualSize: calcLineActualSize(
- {
- x1: currentRoof.x2,
- y1: currentRoof.y2,
- x2: midX.plus(hipX2).toNumber(),
- y2: midY.plus(hipY2).toNumber(),
- },
- currentDegree,
- ),
- },
- })
- // const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10
- // 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)))
- canvas?.add(hip2)
- roof.innerLines.push(hip2)
-
- hipLines.push(hip1)
- hipLines.push(hip2)
-
- hipLines.forEach((hip) => {
- const singHipX = Math.sign(hip.x1 - midWallX.toNumber())
- const singHipY = Math.sign(hip.y1 - midWallY.toNumber())
-
- hip.set({
- x1: hip.x1,
- y1: hip.y1,
- x2: hip.x1 - singHipX * currentRoof.attributes.width,
- y2: hip.y1 - singHipY * currentRoof.attributes.width,
- })
- })
-
- hipLines.forEach((hip, i) => {
- const gableLine = new QLine([hip.x2, hip.y2, currentRoof.attributes.ridgeCoordinate.x1, currentRoof.attributes.ridgeCoordinate.y1], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.GABLE,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- textMode: textMode,
- planeSize: calcLinePlaneSize({
- x1: hip.x2,
- y1: hip.y2,
- x2: currentRoof.attributes.ridgeCoordinate.x1,
- y2: currentRoof.attributes.ridgeCoordinate.y1,
- }),
- actualSize: calcLineActualSize(
- {
- x1: hip.x2,
- y1: hip.y2,
- x2: currentRoof.attributes.ridgeCoordinate.x1,
- y2: currentRoof.attributes.ridgeCoordinate.y1,
- },
- currentDegree,
- ),
- },
- })
-
- // const gableBase = ((Math.abs(gableLine.x1 - gableLine.x2) + Math.abs(gableLine.y1 - gableLine.y2)) / 2) * 10
- // const gableHeight = Math.round(gableBase / Math.tan(((90 - gableDegree) * Math.PI) / 180))
- // gableLine.attributes.planeSize =
- // Math.round(Math.sqrt(Math.pow(gableLine.x1 - gableLine.x2, 2) + Math.pow(gableLine.y1 - gableLine.y2, 2))) * 10
- // gableLine.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gableLine.attributes.planeSize, 2) + Math.pow(gableHeight, 2)))
- canvas?.add(gableLine)
- roof.innerLines.push(gableLine)
- })
- }
- }
- canvas?.renderAll()
-}
-
-/**
- * 반절처 지붕으로 변경
- * @param currentRoof
- * @param canvas
- * @param textMode
- */
-const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => {
- if (
- currentRoof.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD &&
- currentRoof.attributes.width !== undefined &&
- currentRoof.attributes.width > 0
- ) {
- const roofId = currentRoof.attributes.roofId
- const wall = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId)
- const roof = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.ROOF && object.id === roofId)
- let hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roofId)
- let ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roofId)
- let wallLine = wall.lines.filter((w) => w.id === currentRoof.attributes.wallLine)
- if (wallLine.length > 0) {
- wallLine = wallLine[0]
- }
-
- let prevRoof, nextRoof
- roof.lines.forEach((r, index) => {
- if (r.id === currentRoof.id) {
- currentRoof = r
- prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1]
- nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1]
- }
- })
-
- const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree
- const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree
-
- const midX = Big(currentRoof.x1).plus(Big(currentRoof.x2)).div(2) // 지붕의 X 중심
- const midY = Big(currentRoof.y1).plus(Big(currentRoof.y2)).div(2) // 지붕의 Y 중심
- const midWallX = Big(wallLine.x1).plus(Big(wallLine.x2)).div(2) // 벽의 X 중심
- const midWallY = Big(wallLine.y1).plus(Big(wallLine.y2)).div(2) // 벽의 Y 중심
- const alpha = midX.minus(midWallX) // 벽과 지붕의 X 거리
- const beta = midY.minus(midWallY) // 벽과 지붕의 Y 거리
- // Math.sqrt(Math.pow(alpha, 2) + Math.pow(beta, 2))
- const hypotenuse = alpha.pow(2).plus(beta.pow(2)).sqrt() // 벽과 지붕의 거리
- const xWidth = Big(Math.sign(midX.minus(midWallX).toNumber()))
- .times(alpha.div(hypotenuse))
- .times(currentRoof.attributes.width / 2) // 지붕의 X 너비
- const yWidth = Big(Math.sign(midY.minus(midWallY)))
- .times(beta.div(hypotenuse))
- .times(currentRoof.attributes.width / 2) // 지붕의 Y 너비
- const addHipX2 = Big(Math.sign(midX.minus(midWallX).toNumber()))
- .times(alpha.div(hypotenuse))
- .times(currentRoof.length / 2) // 추녀마루의 X 너비
- const addHipY2 = Big(Math.sign(midY.minus(midWallY)))
- .times(beta.div(hypotenuse))
- .times(currentRoof.length / 2) // 추녀마루의 Y 너비
- let hipX2 = 0
- let hipY2 = 0
-
- // if (Math.sqrt(Math.pow(xWidth, 2) + Math.pow(yWidth, 2)) < Math.sqrt(Math.pow(addHipX2, 2) + Math.pow(addHipY2, 2))) {
- if (
- xWidth
- .pow(2)
- .plus(yWidth.pow(2))
- .lt(addHipX2.pow(2).plus(addHipY2.pow(2)))
- ) {
- // reDrawPolygon(roof, canvas)
-
- const innerLines = canvas
- ?.getObjects()
- .filter(
- (object) =>
- object.attributes !== undefined &&
- object.attributes.roofId === roofId &&
- object.attributes.currentRoofId === currentRoof.id &&
- object.x1 !== undefined &&
- object.x2 !== undefined,
- )
-
- innerLines
- .filter(
- (line) =>
- line.name !== LINE_TYPE.SUBLINE.RIDGE &&
- line.name !== LINE_TYPE.SUBLINE.HIP &&
- line.name !== LINE_TYPE.SUBLINE.VALLEY &&
- line.name !== OUTER_LINE_TYPE.OUTER_LINE &&
- line.name !== 'wallLine',
- )
- .forEach((line) => {
- roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id)
- canvas?.remove(line)
- })
-
- ridgeLines = ridgeLines.filter(
- (ridge) =>
- (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) ||
- (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1),
- )
- hipLines = hipLines.filter(
- (hip) => (hip.x1 === currentRoof.x1 && hip.y1 === currentRoof.y1) || (hip.x1 === currentRoof.x2 && hip.y1 === currentRoof.y2),
- )
-
- if (hipLines === undefined || hipLines.length === 0) {
- hipLines = innerLines.filter(
- (line) =>
- (line.x1 === currentRoof.x1 && line.y1 === currentRoof.y1) ||
- (line.x2 === currentRoof.x1 && line.y2 === currentRoof.y1) ||
- (line.x1 === currentRoof.x2 && line.y1 === currentRoof.y2) ||
- (line.x2 === currentRoof.x2 && line.y2 === currentRoof.y2),
- )
- }
-
- if ((ridgeLines === undefined || ridgeLines.length === 0) && hipLines.length >= 2) {
- let points = []
- hipLines.forEach((hip) => {
- points.push({ x: hip.x1, y: hip.y1 })
- points.push({ x: hip.x2, y: hip.y2 })
- })
-
- const pointSet = new Set()
- const duplicatePoints = []
-
- points.forEach((point) => {
- const pointKey = `${point.x},${point.y}`
- if (pointSet.has(pointKey)) {
- duplicatePoints.push(point)
- } else {
- pointSet.add(pointKey)
- }
- })
-
- ridgeLines = innerLines
- .filter((r) => r !== hipLines[0] && r !== hipLines[1])
- .filter(
- (r) =>
- (r.x1 === duplicatePoints[0].x && r.y1 === duplicatePoints[0].y) || (r.x2 === duplicatePoints[0].x && r.y2 === duplicatePoints[0].y),
- )
- if (ridgeLines.length > 0) {
- currentRoof.attributes.ridgeCoordinate = { x1: duplicatePoints[0].x, y1: duplicatePoints[0].y }
- }
- }
-
- hipLines.forEach((hip) => {
- roof.innerLines = roof.innerLines.filter((h) => h.id !== hip.id)
- canvas.remove(hip)
- })
-
- if (ridgeLines.length > 0) {
- const ridge = ridgeLines[0]
- if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) {
- const signX = Math.sign(midX.minus(ridge.x1).toNumber())
- const signY = Math.sign(midY.minus(ridge.y1).toNumber())
- ridge.set({
- x1: midX.minus(xWidth.abs().times(signX)).toNumber(),
- y1: midY.minus(yWidth.abs().times(signY)).toNumber(),
- x2: ridge.x2,
- y2: ridge.y2,
- })
-
- currentRoof.attributes.ridgeCoordinate = { x1: ridge.x1, y1: ridge.y1 }
- hipX2 = ridge.x1
- hipY2 = ridge.y1
- }
- if (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1) {
- const signX = Math.sign(midX - ridge.x2)
- const signY = Math.sign(midY - ridge.y2)
- ridge.set({
- x1: ridge.x1,
- y1: ridge.y1,
- x2: midX.minus(xWidth.abs().times(signX)).toNumber(),
- y2: midY.minus(yWidth.abs().times(signY)).toNumber(),
- })
-
- currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 }
- hipX2 = ridge.x2
- hipY2 = ridge.y2
- }
- ridge.attributes.planeSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 })
- ridge.attributes.actualSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 })
- }
-
- let hipX1 = (Math.sign(currentRoof.x1 - midX) * currentRoof.attributes.width) / 2
- let hipY1 = (Math.sign(currentRoof.y1 - midY) * currentRoof.attributes.width) / 2
-
- const gableDegree = currentRoof.attributes.degree > 0 ? currentRoof.attributes.degree : getDegreeByChon(currentRoof.attributes.pitch)
- const gable1 = new QLine([midX.plus(hipX1).toNumber(), midY.plus(hipY1).toNumber(), hipX2, hipY2], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.GABLE,
- textMode: textMode,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({
- x1: midX.plus(hipX1).toNumber(),
- y1: midY.plus(hipY1).toNumber(),
- x2: hipX2,
- y2: hipY2,
- }),
- actualSize: calcLineActualSize(
- {
- x1: midX.plus(hipX1).toNumber(),
- y1: midY.plus(hipY1).toNumber(),
- x2: hipX2,
- y2: hipY2,
- },
- gableDegree,
- ),
- },
- })
- // const gable1Base = ((Math.abs(gable1.x1 - gable1.x2) + Math.abs(gable1.y1 - gable1.y2)) / 2) * 10
- // const gable1Height = Math.round(gable1Base / Math.tan(((90 - gableDegree) * Math.PI) / 180))
- // gable1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable1.x1 - gable1.x2, 2) + Math.pow(gable1.y1 - gable1.y2, 2))) * 10
- // gable1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable1.attributes.planeSize, 2) + Math.pow(gable1Height, 2)))
- canvas?.add(gable1)
- roof.innerLines.push(gable1)
-
- hipX1 = (Math.sign(currentRoof.x2 - midX) * currentRoof.attributes.width) / 2
- hipY1 = (Math.sign(currentRoof.y2 - midY) * currentRoof.attributes.width) / 2
-
- const gable2 = new QLine([midX.plus(hipX1).toNumber(), midY.plus(hipY1).toNumber(), hipX2, hipY2], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.GABLE,
- textMode: textMode,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({
- x1: midX.plus(hipX1).toNumber(),
- y1: midY.plus(hipY1).toNumber(),
- x2: hipX2,
- y2: hipY2,
- }),
- actualSize: calcLineActualSize(
- {
- x1: midX.plus(hipX1).toNumber(),
- y1: midY.plus(hipY1).toNumber(),
- x2: hipX2,
- y2: hipY2,
- },
- gableDegree,
- ),
- },
- })
- // const gable2Base = ((Math.abs(gable2.x1 - gable2.x2) + Math.abs(gable2.y1 - gable2.y2)) / 2) * 10
- // const gable2Height = Math.round(gable2Base / Math.tan(((90 - gableDegree) * Math.PI) / 180))
- // gable2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable2.x1 - gable2.x2, 2) + Math.pow(gable2.y1 - gable2.y2, 2))) * 10
- // gable2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable2.attributes.planeSize, 2) + Math.pow(gable2Height, 2)))
- canvas?.add(gable2)
- roof.innerLines.push(gable2)
-
- const gable3 = new QLine([gable1.x1, gable1.y1, gable2.x1, gable2.y1], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.GABLE,
- textMode: textMode,
- visible: false,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({ x1: gable1.x1, y1: gable1.y1, x2: gable2.x1, y2: gable2.y1 }),
- actualSize: calcLinePlaneSize({ x1: gable1.x1, y1: gable1.y1, x2: gable2.x1, y2: gable2.y1 }),
- },
- })
- // gable3.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10
- // gable3.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10
- canvas?.add(gable3)
- // roof.innerLines.push(gable3)
-
- const hip1 = new QLine([currentRoof.x1, currentRoof.y1, gable1.x1, gable1.y1], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.HIP,
- textMode: textMode,
- visible: false,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: gable1.x1, y2: gable1.y1 }),
- actualSize: calcLineActualSize(
- {
- x1: currentRoof.x1,
- y1: currentRoof.y1,
- x2: gable1.x1,
- y2: gable1.y1,
- },
- prevDegree,
- ),
- },
- })
- // const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
- // 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)))
- canvas?.add(hip1)
- // roof.innerLines.push(hip1)
-
- const hip2 = new QLine([currentRoof.x2, currentRoof.y2, gable2.x1, gable2.y1], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.HIP,
- textMode: textMode,
- visible: false,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: gable2.x1, y2: gable2.y1 }),
- actualSize: calcLineActualSize(
- {
- x1: currentRoof.x2,
- y1: currentRoof.y2,
- x2: gable2.x1,
- y2: gable2.y1,
- },
- nextDegree,
- ),
- },
- })
- // const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10
- // 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)))
- canvas?.add(hip2)
-
- // hip1.set({ visible: false })
- hip1.setViewLengthText(false)
- // gable3.set({ visible: false })
- gable3.setViewLengthText(false)
- // hip2.set({ visible: false })
- hip2.setViewLengthText(false)
- }
- }
-}
-
-/**
- * 벽지붕으로 변경
- * @param currentRoof
- * @param canvas
- * @param textMode
- */
-const changeWallRoof = (currentRoof, canvas, textMode) => {
- const roofId = currentRoof.attributes.roofId
- const roof = canvas?.getObjects().find((object) => object.name === 'roof' && object.id === roofId)
- const roofLines = roof.lines
- let prevRoof, nextRoof
- roofLines.forEach((r, index) => {
- if (r.id === currentRoof.id) {
- currentRoof = r
- prevRoof = roofLines[index === 0 ? roofLines.length - 1 : index - 1]
- nextRoof = roofLines[index === roofLines.length - 1 ? 0 : index + 1]
- }
- })
-
- const wall = canvas?.getObjects().find((object) => object.name === 'wall' && object.attributes.roofId === roofId)
- let wallLine = wall.lines.filter((w) => w.id === currentRoof.attributes.wallLine)
- let hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roofId)
- let ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roofId)
-
- if (wallLine.length > 0) {
- wallLine = wallLine[0]
- }
-
- ridgeLines = ridgeLines.filter(
- (ridge) =>
- (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) ||
- (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1),
- )
- hipLines = hipLines.filter(
- (hip) => (hip.x1 === currentRoof.x1 && hip.y1 === currentRoof.y1) || (hip.x1 === currentRoof.x2 && hip.y1 === currentRoof.y2),
- )
-
- const wallMidX = Big(wallLine.x1).plus(Big(wallLine.x2)).div(2)
- const wallMidY = Big(wallLine.y1).plus(Big(wallLine.y2)).div(2)
- const roofMidX = Big(currentRoof.x1).plus(Big(currentRoof.x2)).div(2)
- const roofMidY = Big(currentRoof.y1).plus(Big(currentRoof.y2)).div(2)
-
- const alpha = wallMidX.minus(roofMidX)
- const beta = wallMidY.minus(roofMidY)
-
- currentRoof.set({
- x1: alpha.plus(currentRoof.x1).toNumber(),
- y1: beta.plus(currentRoof.y1).toNumber(),
- x2: alpha.plus(currentRoof.x2).toNumber(),
- y2: beta.plus(currentRoof.y2).toNumber(),
- })
-
- prevRoof.set({
- x1: prevRoof.x1,
- y1: prevRoof.y1,
- x2: alpha.plus(prevRoof.x2),
- y2: beta.plus(prevRoof.y2),
- })
-
- nextRoof.set({
- x1: alpha.plus(nextRoof.x1),
- y1: beta.plus(nextRoof.y1),
- x2: nextRoof.x2,
- y2: nextRoof.y2,
- })
-
- const innerLines = canvas
- ?.getObjects()
- .filter(
- (object) =>
- object.attributes?.roofId === roofId &&
- object.attributes?.currentRoofId === currentRoof.id &&
- object.x1 !== undefined &&
- object.x2 !== undefined,
- )
-
- innerLines
- .filter(
- (line) =>
- line.name !== LINE_TYPE.SUBLINE.RIDGE &&
- line.name !== LINE_TYPE.SUBLINE.HIP &&
- line.name !== LINE_TYPE.SUBLINE.VALLEY &&
- line.name !== OUTER_LINE_TYPE.OUTER_LINE &&
- line.name !== 'wallLine',
- )
- .forEach((line) => {
- roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id)
- canvas?.remove(line)
- })
-
- const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree
- const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree
-
- if (currentRoof.attributes.sleeve && currentRoof.attributes.width > 0 && prevRoof.attributes.offset > 0 && nextRoof.attributes.offset > 0) {
- const prevSignX = Math.sign(prevRoof.x1 - prevRoof.x2)
- const prevSignY = Math.sign(prevRoof.y1 - prevRoof.y2)
- const nextSignX = Math.sign(nextRoof.x1 - nextRoof.x2)
- const nextSignY = Math.sign(nextRoof.y1 - nextRoof.y2)
-
- const prevWidthX = prevSignX === 0 ? 0 : prevSignX * currentRoof.attributes.width
- const prevWidthY = prevSignY === 0 ? 0 : prevSignY * currentRoof.attributes.width
- const nextWidthX = nextSignX === 0 ? 0 : nextSignX * currentRoof.attributes.width
- const nextWidthY = nextSignY === 0 ? 0 : nextSignY * currentRoof.attributes.width
- const prevX2 = Big(prevRoof.x2).minus(prevWidthX)
- const prevY2 = Big(prevRoof.y2).minus(prevWidthY)
- const nextX1 = Big(nextRoof.x1).plus(nextWidthX)
- const nextY1 = Big(nextRoof.y1).plus(nextWidthY)
-
- currentRoof.set({
- x1: wallLine.x1,
- y1: wallLine.y1,
- x2: wallLine.x2,
- y2: wallLine.y2,
- })
-
- prevRoof.set({
- x1: prevRoof.x1,
- y1: prevRoof.y1,
- x2: prevX2.toNumber(),
- y2: prevY2.toNumber(),
- })
-
- nextRoof.set({
- x1: nextX1.toNumber(),
- y1: nextY1.toNumber(),
- x2: nextRoof.x2,
- y2: nextRoof.y2,
- })
-
- const addPrevWallLine1 = new QLine(
- [prevX2.toNumber(), prevY2.toNumber(), Big(wallLine.x1).minus(prevWidthX).toNumber(), Big(wallLine.y1).minus(prevWidthY).toNumber()],
- {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: 'roofLine',
- textMode: textMode,
- attributes: {
- roofId: roofId,
- type: LINE_TYPE.WALLLINE.ETC,
- planeSize: calcLinePlaneSize({
- x1: prevX2.toNumber(),
- y1: prevY2.toNumber(),
- x2: Big(wallLine.x1).minus(prevWidthX).toNumber(),
- y2: Big(wallLine.y1).minus(prevWidthY).toNumber(),
- }),
- actualSize: calcLinePlaneSize({
- x1: prevX2.toNumber(),
- y1: prevY2.toNumber(),
- x2: Big(wallLine.x1).minus(prevWidthX).toNumber(),
- y2: Big(wallLine.y1).minus(prevWidthY).toNumber(),
- }),
- },
- },
- )
-
- const addPrevWallLine2 = new QLine(
- [
- addPrevWallLine1.x2,
- addPrevWallLine1.y2,
- Big(addPrevWallLine1.x2).plus(prevWidthX).toNumber(),
- Big(addPrevWallLine1.y2).plus(prevWidthY).toNumber(),
- ],
- {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: 'roofLine',
- textMode: textMode,
- attributes: {
- roofId: roofId,
- type: LINE_TYPE.WALLLINE.ETC,
- planeSize: calcLinePlaneSize({
- x1: addPrevWallLine1.x2,
- y1: addPrevWallLine1.y2,
- x2: Big(addPrevWallLine1.x2).plus(prevWidthX).toNumber(),
- y2: Big(addPrevWallLine1.y2).plus(prevWidthY).toNumber(),
- }),
- actualSize: calcLinePlaneSize({
- x1: addPrevWallLine1.x2,
- y1: addPrevWallLine1.y2,
- x2: Big(addPrevWallLine1.x2).plus(prevWidthX).toNumber(),
- y2: Big(addPrevWallLine1.y2).plus(prevWidthY).toNumber(),
- }),
- },
- },
- )
-
- const addNextWallLine1 = new QLine(
- [wallLine.x2, wallLine.y2, Big(wallLine.x2).plus(nextWidthX).toNumber(), Big(wallLine.y2).plus(nextWidthY).toNumber()],
- {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: 'roofLine',
- textMode: textMode,
- attributes: {
- roofId: roofId,
- type: LINE_TYPE.WALLLINE.ETC,
- planeSize: calcLinePlaneSize({
- x1: wallLine.x2,
- y1: wallLine.y2,
- x2: Big(wallLine.x2).plus(nextWidthX).toNumber(),
- y2: Big(wallLine.y2).plus(nextWidthY).toNumber(),
- }),
- actualSize: calcLinePlaneSize({
- x1: wallLine.x2,
- y1: wallLine.y2,
- }),
- },
- },
- )
-
- const addNextWallLine2 = new QLine([addNextWallLine1.x2, addNextWallLine1.y2, nextX1.toNumber(), nextY1.toNumber()], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: 'roofLine',
- attributes: {
- roofId: roofId,
- type: LINE_TYPE.WALLLINE.ETC,
- planeSize: calcLinePlaneSize({
- x1: addNextWallLine1.x2,
- y1: addNextWallLine1.y2,
- x2: nextX1.toNumber(),
- y2: nextY1.toNumber(),
- }),
- actualSize: calcLinePlaneSize({
- x1: addNextWallLine1.x2,
- y1: addNextWallLine1.y2,
- x2: nextX1.toNumber(),
- y2: nextY1.toNumber(),
- }),
- },
- })
-
- canvas?.renderAll()
- const prevIndex = roof.lines.indexOf(prevRoof) + 1
- roof.lines.splice(prevIndex, 0, addPrevWallLine1, addPrevWallLine2)
-
- const nextIndex = roof.lines.indexOf(currentRoof) + 1
- roof.lines.splice(nextIndex, 0, addNextWallLine1, addNextWallLine2)
- }
-
- reDrawPolygon(roof, canvas)
-
- if (ridgeLines.length > 0) {
- const ridge = ridgeLines[0]
- if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) {
- const diffX = Big(ridge.x1).minus(wallMidX)
- const diffY = Big(ridge.y1).minus(wallMidY)
-
- ridge.set({
- x1: Big(ridge.x1).minus(diffX).toNumber(),
- y1: Big(ridge.y1).minus(diffY).toNumber(),
- x2: ridge.x2,
- y2: ridge.y2,
- })
- }
- if (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1) {
- const diffX = Big(ridge.x2).minus(wallMidX)
- const diffY = Big(ridge.y2).minus(wallMidY)
-
- ridge.set({
- x1: ridge.x1,
- y1: ridge.y1,
- x2: Big(ridge.x2).minus(diffX).toNumber(),
- y2: Big(ridge.y2).minus(diffY).toNumber(),
- })
- }
- // ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
- ridge.attributes.planeSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 })
- ridge.attributes.actualSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 })
-
- let hip1 = new QLine([currentRoof.x1, currentRoof.y1, wallMidX.toNumber(), wallMidY.toNumber()], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.HIP,
- textMode: textMode,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({
- x1: currentRoof.x1,
- y1: currentRoof.y1,
- x2: wallMidX.toNumber(),
- y2: wallMidY.toNumber(),
- }),
- actualSize: calcLineActualSize(
- {
- x1: currentRoof.x1,
- y1: currentRoof.y1,
- x2: wallMidX.toNumber(),
- y2: wallMidY.toNumber(),
- },
- prevDegree,
- ),
- },
- })
- // const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
- // 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)))
-
- let hip2 = new QLine([currentRoof.x2, currentRoof.y2, wallMidX.toNumber(), wallMidY.toNumber()], {
- parentId: roof.id,
- fontSize: roof.fontSize,
- stroke: '#1083E3',
- strokeWidth: 2,
- name: LINE_TYPE.SUBLINE.HIP,
- attributes: {
- roofId: roof.id,
- currentRoofId: currentRoof.id,
- planeSize: calcLinePlaneSize({
- x1: currentRoof.x2,
- y1: currentRoof.y2,
- x2: wallMidX.toNumber(),
- y2: wallMidY.toNumber(),
- }),
- actualSize: calcLineActualSize(
- {
- x1: currentRoof.x2,
- y1: currentRoof.y2,
- x2: wallMidX.toNumber(),
- y2: wallMidY.toNumber(),
- },
- nextDegree,
- ),
- },
- })
- // const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10
- // 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)))
- canvas?.add(hip1)
- canvas?.add(hip2)
- roof.innerLines.push(hip1)
- roof.innerLines.push(hip2)
- }
- if (hipLines.length > 0) {
- hipLines.forEach((hip) => {
- roof.innerLines = roof.innerLines.filter((h) => h.id !== hip.id)
- canvas?.remove(hip)
- })
- }
-}
-
-/**
- * 지붕을 변경한다.
- * @param currentRoof
- * @param canvas
- */
-export const changeCurrentRoof = (currentRoof, canvas) => {
- const roofId = currentRoof.attributes.roofId
- const originRoof = canvas?.getObjects().find((object) => object.name === 'roof' && object.id === roofId)
- const wall = canvas?.getObjects().find((object) => object.name === 'wall' && object.attributes.roofId === roofId)
- const wallLine = wall.lines.filter((w) => w.id === currentRoof.attributes.wallLine)[0]
- const innerLines = canvas
- ?.getObjects()
- .filter((object) => object.attributes !== undefined && object.attributes.roofId === roofId && object.x1 !== undefined && object.x2 !== undefined)
-
- wallLine.attributes.type = currentRoof.attributes.type
- wallLine.attributes.offset = currentRoof.attributes.offset
- wallLine.attributes.width = currentRoof.attributes.width
- wallLine.attributes.pitch = currentRoof.attributes.pitch
- wallLine.attributes.sleeve = currentRoof.attributes.sleeve
-
- canvas?.remove(originRoof)
-
- innerLines.filter((line) => line.name !== OUTER_LINE_TYPE.OUTER_LINE).forEach((line) => canvas?.remove(line))
-
- const polygon = createPolygon(wall.points)
- const originPolygon = new QPolygon(wall.points, { fontSize: 0 })
- originPolygon.setViewLengthText(false)
- let offsetPolygon
-
- let result = createRoofMarginPolygon(polygon, wall.lines).vertices
- const allPointsOutside = result.every((point) => !originPolygon.inPolygon(point))
-
- if (allPointsOutside) {
- offsetPolygon = createRoofMarginPolygon(polygon, wall.lines).vertices
- } else {
- offsetPolygon = createRoofPaddingPolygon(polygon, wall.lines).vertices
- }
-
- const newRoof = new QPolygon(offsetPolygon, {
- fill: originRoof.fill,
- stroke: originRoof.stroke,
- strokeWidth: originRoof.strokeWidth,
- selectable: originRoof.selectable,
- fontSize: originRoof.fontSize,
- })
-
- newRoof.name = POLYGON_TYPE.ROOF
- newRoof.setWall(wall)
-
- newRoof.lines.forEach((line, index) => {
- const lineLength = Math.sqrt(
- Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2),
- )
- line.attributes = {
- roofId: newRoof.id,
- planeSize: lineLength,
- actualSize: lineLength,
- wallLine: wall.lines[index].id,
- type: wall.lines[index].attributes.type,
- offset: wall.lines[index].attributes.offset,
- width: wall.lines[index].attributes.width,
- pitch: wall.lines[index].attributes.pitch,
- sleeve: wall.lines[index].attributes.sleeve || false,
- }
- })
- wall.attributes = {
- roofId: newRoof.id,
- }
-
- wall.lines.forEach((line, index) => {
- line.attributes.roofId = newRoof.id
- line.attributes.currentRoofId = newRoof.lines[index].id
- })
- canvas?.add(newRoof)
- canvas?.renderAll()
-
- newRoof.drawHelpLine()
-}
-
-/**
- * 지붕을 변경한다.
+ * 지붕 모양 을 변경한다.
* @param polygon
* @param canvas
*/
@@ -7558,7 +7874,7 @@ const drawCenterLine = (roof, canvas, textMode) => {
}
}
if (points?.length > 0) {
- const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree
+ const currentDegree = getDegreeByChon(currentRoof.attributes.pitch)
const length =
currentDegree !== undefined && currentDegree > 0
? calcLineActualSize({ x1: points[0], y1: points[1], x2: points[2], y2: points[3] }, currentDegree)
@@ -7586,68 +7902,6 @@ const drawCenterLine = (roof, canvas, textMode) => {
})
}
-function createRoofMarginPolygon(polygon, lines, arcSegments = 0) {
- const offsetEdges = []
-
- polygon.edges.forEach((edge, i) => {
- const offset =
- lines[i % lines.length].attributes.offset === undefined || lines[i % lines.length].attributes.offset === 0
- ? 0.1
- : lines[i % lines.length].attributes.offset
- const dx = edge.outwardNormal.x * offset
- const dy = edge.outwardNormal.y * offset
- offsetEdges.push(createOffsetEdge(edge, dx, dy))
- })
-
- const vertices = []
-
- offsetEdges.forEach((thisEdge, i) => {
- const prevEdge = offsetEdges[(i + offsetEdges.length - 1) % offsetEdges.length]
- const vertex = edgesIntersection(prevEdge, thisEdge)
- if (vertex && (!vertex.isIntersectionOutside || arcSegments < 1)) {
- vertices.push({
- x: vertex.x,
- y: vertex.y,
- })
- }
- })
-
- const marginPolygon = createPolygon(vertices)
- marginPolygon.offsetEdges = offsetEdges
- return marginPolygon
-}
-
-function createRoofPaddingPolygon(polygon, lines, arcSegments = 0) {
- const offsetEdges = []
-
- polygon.edges.forEach((edge, i) => {
- const offset =
- lines[i % lines.length].attributes.offset === undefined || lines[i % lines.length].attributes.offset === 0
- ? 0.1
- : lines[i % lines.length].attributes.offset
- const dx = edge.inwardNormal.x * offset
- const dy = edge.inwardNormal.y * offset
- offsetEdges.push(createOffsetEdge(edge, dx, dy))
- })
-
- const vertices = []
-
- offsetEdges.forEach((thisEdge, i) => {
- const prevEdge = offsetEdges[(i + offsetEdges.length - 1) % offsetEdges.length]
- const vertex = edgesIntersection(prevEdge, thisEdge)
- if (vertex && (!vertex.isIntersectionOutside || arcSegments < 1)) {
- vertices.push({
- x: vertex.x,
- y: vertex.y,
- })
- }
- })
-
- const paddingPolygon = createPolygon(vertices)
- paddingPolygon.offsetEdges = offsetEdges
- return paddingPolygon
-}
-
function arePointsEqual(point1, point2) {
return Math.abs(point1.x - point2.x) <= 1 && Math.abs(point1.y - point2.y) <= 1
}
@@ -7701,7 +7955,6 @@ export const calcLinePlaneSize = (points) => {
* @returns number
*/
export const calcLineActualSize = (points, degree = 0) => {
- const { x1, y1, x2, y2 } = points
const planeSize = calcLinePlaneSize(points)
const theta = Big(Math.cos(Big(degree).times(Math.PI).div(180)))
return Big(planeSize).div(theta).round().toNumber()
@@ -7723,7 +7976,7 @@ export const createLinesFromPolygon = (points) => {
}
/** 포인트 정렬 가장왼쪽, 가장위 부터 */
-const getSortedPoint = (points) => {
+const getSortedPoint = (points, lines) => {
const startPoint = points
.filter((point) => point.x === Math.min(...points.map((point) => point.x)))
.reduce((prev, curr) => {
@@ -7733,22 +7986,69 @@ const getSortedPoint = (points) => {
sortedPoints.push(startPoint)
let prevPoint = startPoint
+ let prevDirection
for (let i = 0; i < points.length - 1; i++) {
- const samePoints = []
- points
- .filter((point) => !sortedPoints.includes(point))
- .forEach((point) => {
- if (i % 2 === 1 && prevPoint.y === point.y) {
- samePoints.push({ point, size: Math.abs(point.x - prevPoint.x) })
- }
- if (i % 2 === 0 && prevPoint.x === point.x) {
- samePoints.push({ point, size: Math.abs(point.y - prevPoint.y) })
+ const samePoint = []
+ if (i === 0) {
+ points.forEach((point) => {
+ if (point.x === prevPoint.x && point.y > prevPoint.y) {
+ samePoint.push({ point, direction: 'bottom', size: Math.abs(prevPoint.y - point.y) })
}
})
- const samePoint = samePoints.sort((a, b) => a.size - b.size)[0].point
- sortedPoints.push(samePoint)
- prevPoint = samePoint
+ if (samePoint.length > 0) {
+ samePoint.sort((a, b) => a.size - b.size)
+ sortedPoints.push(samePoint[0].point)
+ prevDirection = samePoint[0].direction
+ prevPoint = samePoint[0].point
+ } else {
+ points.forEach((point) => {
+ if (point.y === prevPoint.y && point.x > prevPoint.x) {
+ samePoint.push({ point, direction: 'right', size: Math.abs(prevPoint.x - point.x) })
+ }
+ })
+ if (samePoint.length > 0) {
+ samePoint.sort((a, b) => a.size - b.size)
+ sortedPoints.push(samePoint[0].point)
+ prevDirection = samePoint[0].direction
+ prevPoint = samePoint[0].point
+ }
+ }
+ } else {
+ points
+ .filter((point) => !sortedPoints.includes(point))
+ .forEach((point) => {
+ if ((prevDirection === 'top' || prevDirection === 'bottom') && point.y === prevPoint.y) {
+ const direction = point.x > prevPoint.x ? 'right' : 'left'
+ const size = Math.abs(point.x - prevPoint.x)
+ samePoint.push({ point, direction, size })
+ }
+ if ((prevDirection === 'left' || prevDirection === 'right') && point.x === prevPoint.x) {
+ const direction = point.y > prevPoint.y ? 'bottom' : 'top'
+ const size = Math.abs(point.y - prevPoint.y)
+ samePoint.push({ point, direction, size })
+ }
+ if (Math.round(Math.abs(point.x - prevPoint.x)) === Math.round(Math.abs(point.y - prevPoint.y))) {
+ const isLinePoint =
+ lines.filter(
+ (line) =>
+ (line.x1 === prevPoint.x && line.y1 === prevPoint.y && line.x2 === point.x && line.y2 === point.y) ||
+ (line.x2 === prevPoint.x && line.y2 === prevPoint.y && line.x1 === point.x && line.y1 === point.y),
+ ).length > 0
+ if (isLinePoint) {
+ const direction = prevDirection
+ const size = Big(point.x).minus(prevPoint.x).abs().pow(2).plus(Big(point.y).minus(prevPoint.y).abs().pow(2)).sqrt().round().toNumber()
+ samePoint.push({ point, direction, size })
+ }
+ }
+ })
+ if (samePoint.length > 0) {
+ samePoint.sort((a, b) => a.size - b.size)
+ sortedPoints.push(samePoint[0].point)
+ prevDirection = samePoint[0].direction
+ prevPoint = samePoint[0].point
+ }
+ }
}
return sortedPoints
}
@@ -7759,7 +8059,6 @@ const reCalculateSize = (line) => {
const theta = Big(Math.acos(Big(oldPlaneSize).div(oldActualSize)))
.times(180)
.div(Math.PI)
- console.log('theta : ', theta.toNumber())
const planeSize = calcLinePlaneSize({
x1: line.x1,
y1: line.y1,