diff --git a/src/common/common.js b/src/common/common.js
index c0fe3701..fd961063 100644
--- a/src/common/common.js
+++ b/src/common/common.js
@@ -223,6 +223,7 @@ export const SAVE_KEY = [
'skeleton',
'viewportTransform',
'outerLineFix',
+ 'adjustRoofLines',
]
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype]
diff --git a/src/components/Main.jsx b/src/components/Main.jsx
index 9afadca7..ad7dd3d3 100644
--- a/src/components/Main.jsx
+++ b/src/components/Main.jsx
@@ -18,8 +18,9 @@ import Config from '@/config/config.export'
export default function MainPage() {
const [sessionState, setSessionState] = useRecoilState(sessionStore)
- const [chagePasswordPopOpen, setChagePasswordPopOpen] = useState(false)
-
+ const [changePasswordPopOpen, setChangePasswordPopOpen] = useState(false)
+ // 데이터 확인 완료 여부 상태 추가
+ const [isSessionLoaded, setIsSessionLoaded] = useState(false)
const router = useRouter()
const { getMessage } = useMessage()
@@ -52,6 +53,14 @@ export default function MainPage() {
}
}
+ useEffect(() => {
+ if (isObjectNotEmpty(sessionState)) {
+ if (sessionState?.pwdInitYn !== 'Y') {
+ setChangePasswordPopOpen(true)
+ }
+ }
+ }, [sessionState])
+
// 라디오 변경 이벤트
const handleOnChangeRadio = (e) => {
setSearchRadioType(e.target.value)
@@ -77,7 +86,7 @@ export default function MainPage() {
useEffect(() => {
if (isObjectNotEmpty(sessionState)) {
if (sessionState?.pwdInitYn !== 'Y') {
- setChagePasswordPopOpen(true)
+ setChangePasswordPopOpen(true)
}
}
}, [sessionState])
@@ -86,10 +95,25 @@ export default function MainPage() {
const [open, setOpen] = useState(false)
const [modalNoticeNo, setModalNoticeNo] = useState('')
+ useEffect(() => {
+ if (isObjectNotEmpty(sessionState)) {
+ if (sessionState?.pwdInitYn !== 'Y') {
+ setChangePasswordPopOpen(true)
+ } else {
+ // pwdInitYn이 'Y'라면 팝업을 닫음 (false)
+ setChangePasswordPopOpen(false)
+ }
+ }
+ }, [sessionState])
+
+ //if (!isSessionLoaded) return null
+
return (
<>
{open && }
- {(!chagePasswordPopOpen && (
+ {changePasswordPopOpen ? (
+
+ ) : (
<>
@@ -131,11 +155,8 @@ export default function MainPage() {
>
- )) || (
- <>
-
- >
)}
+
>
)
}
diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js
index 8d173bc6..b6c299d0 100644
--- a/src/components/fabric/QPolygon.js
+++ b/src/components/fabric/QPolygon.js
@@ -36,6 +36,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.separatePolygon = []
this.toFixed = options.toFixed ?? 1
this.baseLines = []
+ this.adjustRoofLines = []
// this.colorLines = []
// 소수점 전부 제거
@@ -134,7 +135,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.setCoords()
})
- this.on('modified', (e) => {
+ this.on('modified', () => {
this.initLines()
this.addLengthText()
this.setCoords()
@@ -223,7 +224,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
calculateDegree() {
const degrees = []
// polygon.lines를 순회하며 각도를 구해 출력
- this.lines.forEach((line, idx) => {
+ this.lines.forEach((line) => {
const dx = line.x2 - line.x1
const dy = line.y2 - line.y1
const rad = Math.atan2(dy, dx)
@@ -258,6 +259,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
)
.forEach((obj) => this.canvas.remove(obj))
this.innerLines = []
+ this.adjustRoofLines = []
this.canvas.renderAll()
let textMode = 'plane'
@@ -339,18 +341,17 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
if (types.every((type) => type === LINE_TYPE.WALLLINE.EAVES)) {
// 용마루 -- straight-skeleton
- console.log('용마루 지붕')
- ///drawRidgeRoof(this.id, this.canvas, textMode)
+ // console.log('용마루 지붕')
drawSkeletonRidgeRoof(this.id, this.canvas, textMode)
} else if (isGableRoof(types)) {
// A형, B형 박공 지붕
- console.log('패턴 지붕')
+ // console.log('패턴 지붕')
drawGableRoof(this.id, this.canvas, textMode)
} else if (isShedRoof(types, this.lines)) {
- console.log('한쪽흐름 지붕')
+ // console.log('한쪽흐름 지붕')
drawShedRoof(this.id, this.canvas, textMode)
} else {
- console.log('변별로 설정')
+ // console.log('변별로 설정')
drawRoofByAttribute(this.id, this.canvas, textMode)
}
},
@@ -404,7 +405,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
const degree = Big(Math.atan2(dy.toNumber(), dx.toNumber())).times(180).div(Math.PI).toNumber()
- // Create new text object if it doesn't exist
+ // Create a new text object if it doesn't exist
const text = new fabric.Text(length.toString(), {
left: midPoint.x,
top: midPoint.y,
diff --git a/src/components/main/ChangePasswordPop.jsx b/src/components/main/ChangePasswordPop.jsx
index 54075153..efae3bb5 100644
--- a/src/components/main/ChangePasswordPop.jsx
+++ b/src/components/main/ChangePasswordPop.jsx
@@ -114,7 +114,7 @@ export default function ChangePasswordPop(props) {
const result = { ...sessionState, pwdInitYn: 'Y' }
setSession(result)
setSessionState(result)
- props.setChagePasswordPopOpen(false)
+ props.setChangePasswordPopOpen(false)
await login()
},
})
diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js
index 5e65cbcf..69479eef 100644
--- a/src/hooks/roofcover/useRoofAllocationSetting.js
+++ b/src/hooks/roofcover/useRoofAllocationSetting.js
@@ -30,7 +30,6 @@ import { QcastContext } from '@/app/QcastProvider'
import { usePlan } from '@/hooks/usePlan'
import { roofsState } from '@/store/roofAtom'
import { useText } from '@/hooks/useText'
-import { processEaveHelpLines } from '@/util/skeleton-utils'
import { QLine } from '@/components/fabric/QLine'
export function useRoofAllocationSetting(id) {
@@ -114,10 +113,10 @@ export function useRoofAllocationSetting(id) {
*/
const fetchBasicSettings = async (planNo) => {
try {
- const response = await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}/${planNo}` });
-
- let roofsArray = [];
-
+ const response = await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}/${planNo}` })
+
+ let roofsArray = []
+
// API에서 데이터를 성공적으로 가져온 경우
if (response && response.length > 0) {
roofsArray = response.map((item, index) => ({
@@ -133,16 +132,16 @@ export function useRoofAllocationSetting(id) {
roofPitch: item.roofPitch,
roofAngle: item.roofAngle,
selected: index === 0, // 첫 번째 항목을 기본 선택으로 설정
- index: index
- }));
- }
+ index: index,
+ }))
+ }
// API에서 데이터가 없고 기존 roofList가 있는 경우
else if (roofList && roofList.length > 0) {
roofsArray = roofList.map((roof, index) => ({
...roof,
- selected: index === 0 // 첫 번째 항목을 기본 선택으로 설정
- }));
- }
+ selected: index === 0, // 첫 번째 항목을 기본 선택으로 설정
+ }))
+ }
// 둘 다 없는 경우 기본값 설정
else {
roofsArray = [
@@ -156,64 +155,62 @@ export function useRoofAllocationSetting(id) {
roofHajebichi: 0,
roofGap: 'HEI_455',
roofLayout: 'P',
- roofPitch: 4,
- roofAngle: 21.8,
- },
- ]
+ roofPitch: 4,
+ roofAngle: 21.8,
+ },
+ ]
+ }
+
+ /**
+ * 데이터 설정
+ */
+ const selectRoofs = []
+ for (let i = 0; i < roofsArray.length; i++) {
+ roofMaterials?.map((material) => {
+ if (material.roofMatlCd === roofsArray[i].roofMatlCd) {
+ selectRoofs.push({
+ ...material,
+ selected: roofsArray[i].roofApply,
+ index: roofsArray[i].roofSeq,
+ id: roofsArray[i].roofMatlCd,
+ width: roofsArray[i].roofWidth,
+ length: roofsArray[i].roofHeight,
+ hajebichi: roofsArray[i].roofHajebichi,
+ raft: roofsArray[i].roofGap,
+ layout: roofsArray[i].roofLayout,
+ pitch: roofsArray[i].roofPitch,
+ angle: roofsArray[i].roofAngle,
+ })
}
-
-
- /**
- * 데이터 설정
- */
- const selectRoofs = []
- for (let i = 0; i < roofsArray.length; i++) {
- roofMaterials?.map((material) => {
- if (material.roofMatlCd === roofsArray[i].roofMatlCd) {
- selectRoofs.push({
- ...material,
- selected: roofsArray[i].roofApply,
- index: roofsArray[i].roofSeq,
- id: roofsArray[i].roofMatlCd,
- width: roofsArray[i].roofWidth,
- length: roofsArray[i].roofHeight,
- hajebichi: roofsArray[i].roofHajebichi,
- raft: roofsArray[i].roofGap,
- layout: roofsArray[i].roofLayout,
- pitch: roofsArray[i].roofPitch,
- angle: roofsArray[i].roofAngle,
- })
- }
- })
- }
-
- const firstRes = Array.isArray(res) && res.length > 0 ? res[0] : null
-
- setBasicSetting({
- ...basicSetting,
- planNo: firstRes?.planNo ?? planNo,
- roofSizeSet: firstRes?.roofSizeSet ?? 0,
- roofAngleSet: firstRes?.roofAngleSet ?? 0,
- roofsData: roofsArray,
- selectedRoofMaterial: selectRoofs.find((roof) => roof.selected),
})
+ }
- setBasicInfo({
- planNo: '' + (firstRes?.planNo ?? planNo),
- roofSizeSet: '' + (firstRes?.roofSizeSet ?? 0),
- roofAngleSet: '' + (firstRes?.roofAngleSet ?? 0),
- })
- // 데이터 동기화: 렌더링용 필드 기본값 보정
- const normalizedRoofs = selectRoofs.map((roof) => ({
- ...roof,
- width: roof.width ?? '',
- length: roof.length ?? '',
- hajebichi: roof.hajebichi ?? '',
- pitch: roof.pitch ?? '',
- angle: roof.angle ?? '',
- }))
- setCurrentRoofList(normalizedRoofs)
+ const firstRes = Array.isArray(res) && res.length > 0 ? res[0] : null
+ setBasicSetting({
+ ...basicSetting,
+ planNo: firstRes?.planNo ?? planNo,
+ roofSizeSet: firstRes?.roofSizeSet ?? 0,
+ roofAngleSet: firstRes?.roofAngleSet ?? 0,
+ roofsData: roofsArray,
+ selectedRoofMaterial: selectRoofs.find((roof) => roof.selected),
+ })
+
+ setBasicInfo({
+ planNo: '' + (firstRes?.planNo ?? planNo),
+ roofSizeSet: '' + (firstRes?.roofSizeSet ?? 0),
+ roofAngleSet: '' + (firstRes?.roofAngleSet ?? 0),
+ })
+ // 데이터 동기화: 렌더링용 필드 기본값 보정
+ const normalizedRoofs = selectRoofs.map((roof) => ({
+ ...roof,
+ width: roof.width ?? '',
+ length: roof.length ?? '',
+ hajebichi: roof.hajebichi ?? '',
+ pitch: roof.pitch ?? '',
+ angle: roof.angle ?? '',
+ }))
+ setCurrentRoofList(normalizedRoofs)
} catch (error) {
console.error('Data fetching error:', error)
}
@@ -467,7 +464,6 @@ export function useRoofAllocationSetting(id) {
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
roofBases.forEach((roofBase) => {
try {
-
const roofEaveHelpLines = canvas.getObjects().filter((obj) => obj.lineName === 'eaveHelpLine' && obj.roofId === roofBase.id)
if (roofEaveHelpLines.length > 0) {
if (roofBase.lines) {
@@ -534,6 +530,34 @@ export function useRoofAllocationSetting(id) {
}
}
+ if (roofBase.adjustRoofLines.length > 0) {
+ const newRoofLines = []
+ let lineIndex = 1
+ roofBase.lines.forEach((line, idx) => {
+ const adjustLines = roofBase.adjustRoofLines.filter((adjustLine) => adjustLine.roofIdx === line.idx)
+ if (adjustLines.length === 0) {
+ line.idx = lineIndex
+ newRoofLines.push(line)
+ lineIndex++
+ } else {
+ adjustLines.forEach(({ point, roofIdx }) => {
+ const newLine = new QLine(point, {
+ idx: lineIndex,
+ selectable: false,
+ parentId: line.parentId,
+ parent: line.parent,
+ fontSize: line.fontSize,
+ stroke: line.stroke,
+ strokeWidth: line.strokeWidth,
+ attributes: line.attributes,
+ })
+ newRoofLines.push(newLine)
+ lineIndex++
+ })
+ }
+ })
+ roofBase.lines = newRoofLines
+ }
if (roofBase.separatePolygon.length > 0) {
splitPolygonWithSeparate(roofBase.separatePolygon)
} else {
diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js
index 82ad62df..abcd66ce 100644
--- a/src/util/qpolygon-utils.js
+++ b/src/util/qpolygon-utils.js
@@ -3,7 +3,6 @@ import { QLine } from '@/components/fabric/QLine'
import { getAdjacent, getDegreeByChon, isPointOnLine, isPointOnLineNew } 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 Big from 'big.js'
@@ -490,14 +489,6 @@ export const isSamePoint = (a, b) => {
return Math.abs(Math.round(a.x) - Math.round(b.x)) <= 2 && Math.abs(Math.round(a.y) - Math.round(b.y)) <= 2
}
-/**
- * 용마루 지붕
- * @param roofId
- * @param canvas
- * @param textMode
- */
-export const drawEavesRoof = (roofId, canvas, textMode) => {}
-
/**
* 박공지붕(A,B 패턴)
* @param roofId
@@ -509,7 +500,7 @@ export const drawGableRoof = (roofId, canvas, textMode) => {
const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId)
const baseLines = wall.baseLines.filter((line) => line.attributes.planeSize > 0)
- const baseLinePoints = baseLines.map((line) => ({ x: line.x1, y: line.y1 }))
+ // const baseLinePoints = baseLines.map((line) => ({ x: line.x1, y: line.y1 }))
const eavesLines = baseLines.filter((line) => line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
@@ -1492,164 +1483,6 @@ export const drawShedRoof = (roofId, canvas, textMode) => {
canvas.renderAll()
}
-const getInwardNormal = (v1, v2, isCCW) => {
- const dx = v2.x - v1.x
- const dy = v2.y - v1.y
- const length = Math.sqrt(dx * dx + dy * dy)
-
- if (length === 0) return { x: 0, y: 0 }
-
- if (isCCW) {
- return { x: -dy / length, y: dx / length }
- } else {
- return { x: dy / length, y: -dx / length }
- }
-}
-
-const isCounterClockwise = (vertices) => {
- let sum = 0
- for (let i = 0; i < vertices.length; i++) {
- const v1 = vertices[i]
- const v2 = vertices[(i + 1) % vertices.length]
- sum += (v2.x - v1.x) * (v2.y + v1.y)
- }
- return sum < 0
-}
-
-const isPointInPolygon = (point, polygon) => {
- let inside = false
-
- for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
- const xi = polygon[i].x,
- yi = polygon[i].y
- const xj = polygon[j].x,
- yj = polygon[j].y
-
- const intersect = yi > point.y !== yj > point.y && point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi
-
- if (intersect) inside = !inside
- }
-
- return inside
-}
-
-const calculateAngleBisector = (prevVertex, currentVertex, nextVertex, polygonVertices) => {
- const isCCW = isCounterClockwise(polygonVertices)
-
- // 이전 변의 내향 법선
- const norm1 = getInwardNormal(prevVertex, currentVertex, isCCW)
-
- // 다음 변의 내향 법선
- const norm2 = getInwardNormal(currentVertex, nextVertex, isCCW)
-
- // 이등분선 계산
- let bisectorX = norm1.x + norm2.x
- let bisectorY = norm1.y + norm2.y
-
- const length = Math.sqrt(bisectorX * bisectorX + bisectorY * bisectorY)
-
- if (length < 1e-10) {
- // 180도인 경우
- bisectorX = norm1.x
- bisectorY = norm1.y
- } else {
- bisectorX /= length
- bisectorY /= length
- }
-
- const testPoint = {
- x: currentVertex.x + bisectorX * 0.1,
- y: currentVertex.y + bisectorY * 0.1,
- }
-
- if (isPointInPolygon(testPoint, polygonVertices)) {
- // 방향이 외부를 향하면 반전
- bisectorX = -bisectorX
- bisectorY = -bisectorY
- }
-
- return { x: bisectorX, y: bisectorY }
-}
-
-const lineSegmentIntersection = (p1, p2, p3, p4) => {
- const x1 = p1.x,
- y1 = p1.y
- const x2 = p2.x,
- y2 = p2.y
- const x3 = p3.x,
- y3 = p3.y
- const x4 = p4.x,
- y4 = p4.y
-
- const denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
-
- if (Math.abs(denom) < EPSILON) {
- return null // 평행
- }
-
- const t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / denom
- const u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / denom
-
- if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
- return {
- x: Number((x1 + t * (x2 - x1)).toFixed(1)),
- y: Number((y1 + t * (y2 - y1)).toFixed(1)),
- }
- }
-
- return null
-}
-
-/**
- * 두 점 사이의 거리 계산
- */
-const distanceBetweenPoints = (p1, p2) => {
- const dx = p2.x - p1.x
- const dy = p2.y - p1.y
- return Math.sqrt(dx * dx + dy * dy)
-}
-
-const findIntersectionPoint = (startPoint, direction, polygonVertices, divisionLines) => {
- const rayEnd = {
- x: startPoint.x + direction.x * 10000,
- y: startPoint.y + direction.y * 10000,
- }
-
- let closestIntersection = null
- let minDistance = Infinity
-
- // 다각형 변과의 교점
- for (let i = 0; i < polygonVertices.length; i++) {
- const v1 = polygonVertices[i]
- const v2 = polygonVertices[(i + 1) % polygonVertices.length]
-
- const intersection = lineSegmentIntersection(startPoint, rayEnd, v1, v2)
-
- if (intersection) {
- const dist = distanceBetweenPoints(startPoint, intersection)
- if (dist > 0.1 && dist < minDistance) {
- minDistance = dist
- closestIntersection = intersection
- }
- }
- }
-
- // 분할선분과의 교점
- for (const divLine of divisionLines) {
- const intersection = lineSegmentIntersection(startPoint, rayEnd, { x: divLine.x1, y: divLine.y1 }, { x: divLine.x2, y: divLine.y2 })
-
- if (intersection) {
- const dist = distanceBetweenPoints(startPoint, intersection)
- if (dist > 0.1 && dist < minDistance) {
- minDistance = dist
- closestIntersection = intersection
- }
- }
- }
-
- return closestIntersection
-}
-
/**
* 변별로 설정된 지붕을 그린다.
* @param roofId
@@ -2340,7 +2173,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
const tolerance = 1
const dx = Big(roofLine.x2).minus(Big(roofLine.x1)).toNumber()
const dy = Big(roofLine.y2).minus(Big(roofLine.y1)).toNumber()
- const length = Math.sqrt(dx * dx + dy * dy)
const angleDegree = (Math.atan2(dy, dx) * 180) / Math.PI
const normalizedAngle = Math.abs((Math.atan2(dy, dx) * 180) / Math.PI) % 180
let isHorizontal = false,
@@ -2452,7 +2284,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
})
- const currentVector = { x: Math.sign(clamp01(currentLine.x1 - currentLine.x2)), y: Math.sign(clamp01(currentLine.y1 - currentLine.y2)) }
const prevLineVector = { x: Math.sign(prevLine.x1 - prevLine.x2), y: Math.sign(prevLine.y1 - prevLine.y2) }
const nextLineVector = { x: Math.sign(nextLine.x1 - nextLine.x2), y: Math.sign(nextLine.y1 - nextLine.y2) }
//반절마루 생성불가이므로 지붕선만 추가하고 끝냄
@@ -2688,10 +2519,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
let proceedEaves = [] // left: 이전, right:다음, point:그려지는 포인트, length:길이
let proceedRidges = [] // left: 이전, right:다음, point:그려지는 포인트, length:길이
- let hipLines = []
ridgeEaves.forEach((currentLine) => {
- /*const checkLine = createArrow(currentLine, 'blue', roofId)
- canvas.add(checkLine).renderAll()*/
let prevLine, nextLine, currentI, prevI, nextI
baseLines.forEach((baseLine, index) => {
if (baseLine === currentLine) {
@@ -2714,7 +2542,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
})
const analyze = analyzeLine(currentLine)
- const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
let pHipVector = getHalfAngleVector(currentLine, prevLine)
let nHipVector = getHalfAngleVector(currentLine, nextLine)
const pCheckPoint = {
@@ -2736,10 +2563,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
const prevCheckPoint = [currentLine.x1, currentLine.y1, currentLine.x1 + pHipVector.x * 1000, currentLine.y1 + pHipVector.y * 1000]
const nextCheckPoint = [currentLine.x2, currentLine.y2, currentLine.x2 + nHipVector.x * 1000, currentLine.y2 + nHipVector.y * 1000]
- /*const checkLine1 = new fabric.Line(prevCheckPoint, { stroke: 'red', strokeWidth: 4, parentId: roofId, name: 'check' })
- const checkLine2 = new fabric.Line(nextCheckPoint, { stroke: 'green', strokeWidth: 4, parentID: roofId, name: 'check' })
- canvas.add(checkLine1, checkLine2).renderAll()*/
-
const findRoofPoints = (points) => {
const hipEdge = { vertex1: { x: points[0], y: points[1] }, vertex2: { x: points[2], y: points[3] } }
const hipForwardVector = { x: Math.sign(hipEdge.vertex1.x - hipEdge.vertex2.x), y: Math.sign(hipEdge.vertex1.y - hipEdge.vertex2.y) }
@@ -3095,7 +2918,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
if (hipPoint) {
- const hipLength = Math.sqrt((hipPoint.x2 - hipPoint.x1) ** 2 + (hipPoint.y2 - hipPoint.y1) ** 2)
const alreadyLine = proceedEaves.filter((line) => almostEqual(line.point.x1, hipPoint.x1) && almostEqual(line.point.y1, hipPoint.y1))
//겹쳐지는 라인이 있는경우 조정한다.
if (alreadyLine.length === 0) {
@@ -3435,19 +3257,9 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
y: (currentLine.y1 + currentLine.y2) / 2 + Math.sign(nextLine.y2 - nextLine.y1),
}
- /* const checkCurrLine = new fabric.Line([currentLine.x1, currentLine.y1, currentLine.x2, currentLine.y2], {
- stroke: 'cyan',
- strokeWidth: 4,
- parentId: roofId,
- name: 'check',
- })
- canvas.add(checkCurrLine)
- canvas.renderAll()*/
-
//좌우 라인이 서로 다른방향일때
if ((prevLineVector.x !== nextLineVector.x || prevLineVector.y !== nextLineVector.y) && checkWallPolygon.inPolygon(inPolygonPoint)) {
const analyze = analyzeLine(currentLine)
- const roofLine = analyze.roofLine
let beforePrevLine, afterNextLine
baseLines.forEach((baseLine, index) => {
@@ -3487,7 +3299,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
}
- console.log('isOverlap : ', isOverlap)
if (isOverlap) {
const oppLine = isOverlapBefore ? beforePrevLine : afterNextLine
const cMidX = (currentLine.x1 + currentLine.x2) / 2
@@ -3601,7 +3412,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
}
}
- let stdDistance = nextDistance <= prevDistance ? prevDistance : nextDistance
const stdAnalyze = analyzeLine(stdLine)
let stdPoints = []
@@ -3683,11 +3493,9 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
}
}
- console.log('stdAdjustVector', stdAdjustVector)
} else {
const stdAddPrevVector = { x: Math.sign(clamp01(stdLine.x1 - stdLine.x2)), y: Math.sign(clamp01(stdLine.y1 - stdLine.y2)) }
const stdAddNextVector = { x: Math.sign(clamp01(stdLine.x2 - stdLine.x1)), y: Math.sign(clamp01(stdLine.y2 - stdLine.y1)) }
- console.log('stdAddPrevVector', stdAddPrevVector)
stdPoints = [
stdLine.x1 + stdAddPrevVector.x * stdPrevLine.attributes.offset,
stdLine.y1 + stdAddPrevVector.y * stdPrevLine.attributes.offset,
@@ -3695,19 +3503,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
stdLine.y2 + stdAddNextVector.y * stdNextLine.attributes.offset,
]
}
- /*const checkLine = new fabric.Line([stdLine.x1, stdLine.y1, stdLine.x2, stdLine.y2], {
- stroke: 'red',
- strokeWidth: 4,
- parentId: roofId,
- name: 'check',
- })
- const checkLine2 = new fabric.Line(stdPoints, {
- stroke: 'green',
- strokeWidth: 4,
- parentId: roofId,
- name: 'check',
- })
- canvas.add(checkLine, checkLine2).renderAll()*/
//기준지붕선의 반대쪽선
const oppositeLine = []
@@ -3715,7 +3510,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
const endX = Math.max(stdLine.x1, stdLine.x2)
const startY = Math.min(stdLine.y1, stdLine.y2)
const endY = Math.max(stdLine.y1, stdLine.y2)
- console.log('stdFindOppVector', stdFindOppVector)
baseLines
.filter((line) => line !== stdLine && line !== currentLine && line.attributes.type !== LINE_TYPE.WALLLINE.SHED)
.filter((line) => {
@@ -3768,26 +3562,14 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
if (oppositeLine.length > 0) {
const ridgePoints = []
- //지붕선 출발 지점 확인을 위한 기준 포인트
- let ridgeStdPoint = { x: (currentLine.x1 + currentLine.x2) / 2, y: (currentLine.y1 + currentLine.y2) / 2 }
oppositeLine.sort((a, b) => a.distance - b.distance)
oppositeLine.forEach((opposite) => {
const oppLine = opposite.line
- /*const checkOppLine = new fabric.Line([oppLine.x1, oppLine.y1, oppLine.x2, oppLine.y2], {
- stroke: 'yellow',
- strokeWidth: 6,
- parentId: roofId,
- name: 'check',
- })
- canvas.add(checkOppLine)
- canvas.renderAll()*/
-
const oppIndex = baseLines.findIndex((line) => line === oppLine)
//마주하는 라인의 이전 다음 라인.
const oppPrevLine = baseLines[(oppIndex - 1 + baseLines.length) % baseLines.length]
const oppNextLine = baseLines[(oppIndex + 1) % baseLines.length]
- const oppAnalyze = analyzeLine(oppLine)
const oppVector = { x: Math.sign(oppLine.x2 - oppLine.x1), y: Math.sign(oppLine.y2 - oppLine.y1) }
let ridgePoint
@@ -3829,13 +3611,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
ridgePoint[2] = (stdLine.x2 + oppLine.x2) / 2
}
- // 지붕선 출발 지점과의 거리를 통해 가까운쪽이 start point로 처리.
- /*const distRidgeStandard1 = Math.sqrt(Math.pow(ridgeStdPoint.x - ridgePoint[0], 2) + Math.pow(ridgeStdPoint.y - ridgePoint[1], 2))
- const distRidgeStandard2 = Math.sqrt(Math.pow(ridgeStdPoint.x - ridgePoint[2], 2) + Math.pow(ridgeStdPoint.y - ridgePoint[3], 2))
- if (distRidgeStandard1 > distRidgeStandard2) {
- ridgePoint = [ridgePoint[2], ridgePoint[3], ridgePoint[0], ridgePoint[1]]
- }*/
-
if (
(oppPrevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES || oppNextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) &&
!(oppPrevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && oppNextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES)
@@ -4029,10 +3804,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
}
- /* const checkLine1 = new fabric.Line(stdPoints, { stroke: 'red', strokeWidth: 4, parentId: roofId, name: 'check' })
- const checkLine2 = new fabric.Line(ridgePoint, { stroke: 'cyan', strokeWidth: 4, parentId: roofId, name: 'check' })
- canvas.add(checkLine1, checkLine2).renderAll()*/
-
const stdMinX = Math.min(stdPoints[0], stdPoints[2])
const stdMaxX = Math.max(stdPoints[0], stdPoints[2])
const stdMinY = Math.min(stdPoints[1], stdPoints[3])
@@ -4183,21 +3954,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
if (prevLineVector.x === nextLineVector.x && prevLineVector.y === nextLineVector.y) {
const analyze = analyzeLine(currentLine)
const roofLine = analyze.roofLine
- /*const checkRoof = new fabric.Line([roofLine.x1, roofLine.y1, roofLine.x2, roofLine.y2], {
- stroke: 'red',
- strokeWidth: 4,
- parentId: roofId,
- name: 'check',
- })
- canvas.add(checkRoof)
- const checkLine = new fabric.Line([currentLine.x1, currentLine.y1, currentLine.x2, currentLine.y2], {
- stroke: 'blue',
- strokeWidth: 4,
- parentId: roofId,
- name: 'check',
- })
- canvas.add(checkLine)
- canvas.renderAll()*/
const checkVector = { x: Math.sign(prevLine.y2 - prevLine.y1), y: Math.sign(prevLine.x1 - prevLine.x2) }
const checkEdge = { vertex1: { x: roofLine.x1, y: roofLine.y1 }, vertex2: { x: roofLine.x2, y: roofLine.y2 } }
@@ -4211,33 +3967,14 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
return line !== roofLine && line !== prevRoofLine && line !== nextRoofLine
})
.forEach((line) => {
- /*const checkLine = new fabric.Line([line.x1, line.y1, line.x2, line.y2], {
- stroke: 'red',
- strokeWidth: 4,
- parentId: roofId,
- name: 'check',
- })
- canvas.add(checkLine).renderAll()*/
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
const intersect = edgesIntersection(lineEdge, checkEdge)
- /* if (intersect) {
- const checkCircle = new fabric.Circle({
- left: intersect.x,
- top: intersect.y,
- radius: 5,
- fill: 'blue',
- parentId: roofId,
- name: 'check',
- })
- console.log('isPointOnLineNew(line, intersect)', isPointOnLineNew(line, intersect))
- canvas.add(checkCircle).renderAll()
- }*/
+
if (intersect && isPointOnLineNew(line, intersect)) {
intersect.x = almostEqual(intersect.x, roofLine.x1) ? roofLine.x1 : intersect.x
intersect.y = almostEqual(intersect.y, roofLine.y1) ? roofLine.y1 : intersect.y
const distance = Math.sqrt(Math.pow(intersect.x - roofLine.x1, 2) + Math.pow(intersect.y - roofLine.y1, 2))
const vector = { x: Math.sign(intersect.x - roofLine.x1), y: Math.sign(intersect.y - roofLine.y1) }
- console.log('vector', vector, 'checkVector', checkVector)
if (distance > maxDistance && vector.x === checkVector.x && vector.y === checkVector.y) {
maxDistance = distance
correctPoint = intersect
@@ -4274,19 +4011,9 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
const MAX_ITERATIONS = 1000 //무한루프 방지
let iterations = 0
- console.log('baseLines', baseLines)
- console.log('linesAnalysis', linesAnalysis)
-
while (linesAnalysis.length > 0 && iterations < MAX_ITERATIONS) {
iterations++
- /*linesAnalysis.forEach((line) => {
- const point = { x1: line.start.x, y1: line.start.y, x2: line.end.x, y2: line.end.y }
- const checkLine = createArrow(point, 'red', roofId)
- canvas.add(checkLine).renderAll()
- // canvas.remove(checkLine).renderAll()
- })*/
-
const intersections = []
linesAnalysis.forEach((currLine, i) => {
let minDistance = Infinity
@@ -4294,14 +4021,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
let linePoint = null
let partner = null
- /*const checkCLine = new fabric.Line([currLine.start.x, currLine.start.y, currLine.end.x, currLine.end.y], {
- stroke: 'red',
- strokeWidth: 4,
- parentId: roofId,
- name: 'check',
- })
- canvas.add(checkCLine).renderAll()*/
-
const cLength = Math.sqrt(Math.pow(currLine.end.x - currLine.start.x, 2) + Math.pow(currLine.end.y - currLine.start.y, 2))
//남은 길이가 0이면 무시
if (cLength < EPSILON) return
@@ -4312,18 +4031,9 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
if (i === j) return
if (currLine.type === TYPES.GABLE_LINE && nextLine.type === TYPES.GABLE_LINE && currLine.gableId === nextLine.gableId) return
if (nextLine.type === TYPES.GABLE_LINE && nextLine.connectCnt > 1) return
- /*const checkNLine = new fabric.Line([nextLine.start.x, nextLine.start.y, nextLine.end.x, nextLine.end.y], {
- stroke: 'green',
- strokeWidth: 4,
- parentId: roofId,
- name: 'check',
- })
- canvas.add(checkNLine).renderAll()*/
const intersect = lineIntersection(currLine.start, currLine.end, nextLine.start, nextLine.end, canvas)
if (intersect) {
- /*const checkCircle = new fabric.Circle({ left: intersect.x, top: intersect.y, radius: 5, fill: 'blue', parentId: roofId, name: 'check' })
- canvas.add(checkCircle).renderAll()*/
let distance1 = Math.sqrt(Math.pow(intersect.x - currLine.start.x, 2) + Math.pow(intersect.y - currLine.start.y, 2))
let distance2 = Math.sqrt(Math.pow(intersect.x - nextLine.start.x, 2) + Math.pow(intersect.y - nextLine.start.y, 2))
let point = [currLine.start.x, currLine.start.y, intersect.x, intersect.y]
@@ -4348,20 +4058,15 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
partner = j
}
}
- // canvas.remove(checkCircle).renderAll()
}
- // canvas.remove(checkNLine).renderAll()
})
- // canvas.remove(checkCLine).renderAll()
if (intersectPoint) {
intersections.push({ index: i, intersect: intersectPoint, linePoint, partner })
}
})
- console.log('intersections', intersections)
const intersectPoints = intersections
.map((item) => item.intersect)
.filter((point, index, self) => self.findIndex((p) => almostEqual(p.x, point.x) && almostEqual(p.y, point.y)) === index)
- console.log('intersectPoints', intersectPoints)
if (intersectPoints.length === 1 && intersections.length > 1) {
intersections[0].partner = intersections[1].index
@@ -4488,7 +4193,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
if (cLine.type === TYPES.GABLE_LINE || pLine.type === TYPES.GABLE_LINE) {
relationBaseLines = [cLine.left, cLine.right, pLine.left, pLine.right]
- console.log('gableLine newAnalyze start')
const gableLine = cLine.type === TYPES.GABLE_LINE ? cLine : pLine
gableLine.connectCnt++
@@ -4530,7 +4234,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
}
}
- console.log('gableLine newAnalyze end')
} else {
const uniqueBaseLines = [...new Set(relationBaseLines)]
// 연결점에서 새로운 가선분을 생성
@@ -4544,16 +4247,13 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
.filter(([_, count]) => count === 1)
.map(([line, _]) => line)
- console.log('uniqueLines', uniqueLines)
if (uniqueLines.length === 2) {
// 두 변의 이등분선 방향 계산
// uniqueLines.sort((a, b) => a - b)
- console.log('uniqueLines : ', uniqueLines)
const baseLine1 = baseLines[uniqueLines[0]]
const baseLine2 = baseLines[uniqueLines[1]]
let bisector
- console.log('isParallel(baseLine1, baseLine2)', isParallel(baseLine1, baseLine2))
if (isParallel(baseLine1, baseLine2)) {
let cPoint = [cLine.start.x, cLine.start.y, cLine.end.x, cLine.end.y]
let pPoint = [pLine.start.x, pLine.start.y, pLine.end.x, pLine.end.y]
@@ -4601,14 +4301,12 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
})
intersectionsByRoof.sort((a, b) => a.distance - b.distance)
- console.log('intersectionsByRoof : ', intersectionsByRoof)
//기 존재하는 analyze 라인이 있으면 newAnalyzeLine을 생성하지 않고 교체한다.
const otherIs = intersections.filter(
(is) => !processed.has(is.index) && almostEqual(is.intersect.x, intersect.x) && almostEqual(is.intersect.y, intersect.y),
)
- console.log('otherIs', otherIs)
if (otherIs.length > 0) {
const analyze = linesAnalysis[otherIs[0].index]
processed.add(otherIs[0].index)
@@ -4636,20 +4334,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
const prevLine = checkVector.x === vector1.x && checkVector.y === vector1.y ? line2 : line1
const nextLine = checkVector.x === vector1.x && checkVector.y === vector1.y ? line1 : line2
- /*const checkPrevLine = new fabric.Line([prevLine.x1, prevLine.y1, prevLine.x2, prevLine.y2], {
- stroke: 'yellow',
- strokeWidth: 4,
- parentId: roofId,
- name: 'check',
- })
- const checkNextLine = new fabric.Line([nextLine.x1, nextLine.y1, nextLine.x2, nextLine.y2], {
- stroke: 'red',
- strokeWidth: 4,
- parentId: roofId,
- name: 'check',
- })
- canvas.add(checkPrevLine, checkNextLine).renderAll()*/
-
if (!isDiagonal) {
const drivePoint = getRidgeDrivePoint(linePoint, prevLine, nextLine, baseLines)
if (drivePoint !== null) {
@@ -4659,8 +4343,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
}
}
- // const checkNewLine = new fabric.Line(linePoint, { stroke: 'cyan', strokeWidth: 4, parentId: roofId, name: 'check' })
- // canvas.add(checkNewLine).renderAll()
newAnalysis.push({
start: { x: linePoint[0], y: linePoint[1] },
@@ -4685,7 +4367,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
// 처리된 가선분 제외
linesAnalysis = newAnalysis.concat(linesAnalysis.filter((_, index) => !processed.has(index)))
- console.log('lineAnalysis: ', linesAnalysis)
canvas
.getObjects()
@@ -4795,7 +4476,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
.forEach((line) => {
const startOnLine = roof.lines.find((l) => isPointOnLineNew(l, line.start))
const endOnLine = roof.lines.find((l) => isPointOnLineNew(l, line.end))
- console.log('startOnLine, endOnLine: ', startOnLine, endOnLine)
const allLinesPoints = []
innerLines.forEach((innerLine) => {
allLinesPoints.push({ x: innerLine.x1, y: innerLine.y1 }, { x: innerLine.x2, y: innerLine.y2 })
@@ -4823,7 +4503,9 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
//케라바에서 파생된 하단 지붕 라인처리
const downRoofGable = []
//처마에서 파생된 하단 지붕 라인 처리
- let downRoofEaves = []
+ const downRoofEaves = []
+ //roof lines에 조정해야하는 라인 처리
+ // const adjustRoofLines = []
baseLines.forEach((baseLine, index) => {
const nextLine = baseLines[(index + 1) % baseLines.length]
const prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
@@ -4992,7 +4674,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
//1. 현재 라인을 기준으로 지붕선 추가.
//1-1 stdPoint을 현재라인의 지붕 출폭 만큼 조정
const currOffset = currLine.attributes.offset
- const noGableLine = gableLine === prevLine ? nextLine : prevLine
let roofLinePoint = stdPoint
if (currVector.x === 0) {
@@ -5273,9 +4954,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
const vector = Math.sign(currLine.y1 - originPoint.y1)
isFlowInside = isTopIn ? vector < 0 : vector > 0
}
- console.log('isFlowInside', isFlowInside)
const roofCheckPoint = { x: roofLine.x2 + roofVector.x, y: roofLine.y2 + roofVector.y }
- console.log('roofCheck : ', roof.inPolygon(roofCheckPoint))
let otherLine = roof.inPolygon(roofCheckPoint) ? baseLines[nextIndex] : baseLines[prevIndex]
//상단 지붕
@@ -5300,7 +4979,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
})
})
- const upDegree = getDegreeByChon(upLine.attributes.pitch)
const upAnalyze = analyzeLine(upLine)
const upRoofLine = upAnalyze.roofLine
const addUpOffset = flowDistance //상단 지붕선의 추가길이
@@ -5340,10 +5018,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
downHipStartPoint = { x: downRoofPoint[0], y: downRoofPoint[1] }
}
- const checkUpLine = new fabric.Line(upRoofPoint, { stroke: 'red', strokeWidth: 4, parentId: roofId, name: 'check' })
- const checkDownLine = new fabric.Line(downRoofPoint, { stroke: 'yellow', strokeWidth: 4, parentId: roofId, name: 'check' })
- canvas.add(checkUpLine, checkDownLine).renderAll()
-
//상단지붕선과 만나는 innerLines 조정
const upRoofEdge = { vertex1: { x: upRoofPoint[0], y: upRoofPoint[1] }, vertex2: { x: upRoofPoint[2], y: upRoofPoint[3] } }
@@ -5429,11 +5103,16 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
downRoofLines.push(drawHipLine(upHipPoint, canvas, roof, textMode, hipDegree, hipDegree)) //각도 있는 처마지붕선
downRoofLines.push(drawRoofLine([connectPoint.x, connectPoint.y, intersectJoin.x, intersectJoin.y], canvas, roof, textMode)) //각도 없는 처마지붕선
+
+ roof.adjustRoofLines.push({ point: upHipPoint, roofIdx: upRoofLine.idx })
+ roof.adjustRoofLines.push({ point: [connectPoint.x, connectPoint.y, intersectJoin.x, intersectJoin.y], roofIdx: upRoofLine.idx })
} else {
downRoofLines.push(drawRoofLine([upHipStartPoint.x, upHipStartPoint.y, intersectJoin.x, intersectJoin.y], canvas, roof, textMode))
+ roof.adjustRoofLines.push({ point: [upHipStartPoint.x, upHipStartPoint.y, intersectJoin.x, intersectJoin.y], roofIdx: upRoofLine.idx })
}
} else {
downRoofLines.push(drawRoofLine([upHipStartPoint.x, upHipStartPoint.y, intersectJoin.x, intersectJoin.y], canvas, roof, textMode))
+ roof.adjustRoofLines.push({ point: [upHipStartPoint.x, upHipStartPoint.y, intersectJoin.x, intersectJoin.y], roofIdx: upRoofLine.idx })
}
//하단지붕선 추가.
@@ -5461,6 +5140,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
downRoofLines.push(
drawHipLine([intersectDownJoin.x, intersectDownJoin.y, joinEndPoint.x, joinEndPoint.y], canvas, roof, textMode, downDegree, downDegree),
)
+ roof.adjustRoofLines.push({ point: downRoofPoint, roofIdx: downRoofLine.idx })
}
}
})
@@ -5632,24 +5312,6 @@ const clamp01 = (t) => {
return t
}
-/**
- * 실제 각도를 계산한다 대각선인 경우 각도 조정
- * @param points
- * @param degree
- */
-const getRealDegree = (points, degree) => {
- const deltaX = Math.abs(points[2] - points[0])
- const deltaY = Math.abs(points[3] - points[1])
- if (deltaX < 1 || deltaY < 1) {
- return degree
- }
-
- const hypotenuse = Math.sqrt(deltaX ** 2 + deltaY ** 2)
- const adjacent = Math.sqrt(Math.pow(hypotenuse, 2) / 2)
- const height = adjacent * Math.tan((degree * Math.PI) / 180)
- return Math.atan2(height, hypotenuse) * (180 / Math.PI)
-}
-
/**
* 두 라인이 평행한지 확인한다.
* @param line1
@@ -5807,7050 +5469,6 @@ const alreadyPoints = (lines, points) => {
return has
}
-/**
- * 마루가 있는 지붕을 그린다.
- * @param roofId
- * @param canvas
- * @param textMode
- */
-export const drawRidgeRoof = (roofId, canvas, textMode) => {
- let roof = canvas?.getObjects().find((object) => object.id === roofId)
- const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId)
-
- 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
- }
-
- const eavesType = [LINE_TYPE.WALLLINE.EAVES, LINE_TYPE.WALLLINE.HIPANDGABLE]
- const gableType = [LINE_TYPE.WALLLINE.GABLE, LINE_TYPE.WALLLINE.JERKINHEAD]
-
- /** 외벽선 */
- const baseLines = wall.baseLines.filter((line) => line.attributes.planeSize > 0)
- const baseLinePoints = baseLines.map((line) => ({ x: line.x1, y: line.y1 }))
-
- /** 벽취합이 있는 경우 소매가 있다면 지붕 형상을 변경해야 한다. */
- 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)
- }
- })
-
- /** 모양 판단을 위한 라인 처리.
- * 평행한 라인이 나누어져 있는 경우 하나의 선으로 판단 한다.
- */
- const drawBaseLines = []
- baseLines.forEach((currentLine, index) => {
- let nextLine = baseLines[(index + 1) % baseLines.length]
- let prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
- const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint)
- const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
- const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
-
- let { x1, y1, x2, y2 } = currentLine
-
- if (currentAngle !== prevAngle || (currentAngle === prevAngle && currentLine.attributes.type !== prevLine.attributes.type)) {
- if (currentAngle === nextAngle && currentLine.attributes.type === nextLine.attributes.type) {
- let nextIndex = baseLines.findIndex((line) => line === nextLine)
- while (nextIndex !== index) {
- const checkNextLine = baseLines[(nextIndex + 1 + baseLines.length) % baseLines.length]
- const checkAngle = calculateAngle(checkNextLine.startPoint, checkNextLine.endPoint)
- if (currentAngle !== checkAngle) {
- x2 = checkNextLine.x1
- y2 = checkNextLine.y1
- break
- } else {
- nextIndex = nextIndex + 1
- }
- }
- }
- drawBaseLines.push({ x1, y1, x2, y2, line: currentLine, size: calcLinePlaneSize({ x1, y1, x2, y2 }) })
- }
- })
-
- /** baseLine을 기준으로 확인용 polygon 작성 */
- const checkWallPolygon = new QPolygon(baseLinePoints, {})
-
- const drawEavesFirstLines = []
- const drawEavesSecondLines = []
- const drawGableRidgeFirst = []
- const drawGableRidgeSecond = []
- const drawGablePolygonFirst = []
- const drawGablePolygonSecond = []
- const drawHipAndGableFirst = []
- const drawWallRidgeLine = []
-
- /** 모양을 판단한다. */
- drawBaseLines.forEach((currentBaseLine, index) => {
- let prevBaseLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length]
- let nextBaseLine = drawBaseLines[(index + 1) % drawBaseLines.length]
- const currentLine = currentBaseLine.line
- const prevLine = prevBaseLine.line
- const nextLine = nextBaseLine.line
- const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint)
- const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
- const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
-
- // 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 checkScale = Big(10)
- 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(checkScale.times(Math.sign(xVector.toNumber()))).toNumber(),
- y: currentMidY.plus(checkScale.times(Math.sign(yVector.toNumber()))).toNumber(),
- }
-
- /** 현재 라인이 처마유형일 경우 */
- if (currentLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES) {
- if (nextLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES) {
- /**
- * 이전, 다음 라인이 처마일때 라인의 방향이 반대면 ㄷ 모양으로 판단한다.
- */
- if (prevLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES && nextLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES) {
- if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)) {
- /**
- * 다음라인 방향에 포인트를 확인해서 역방향 ㄷ 모양인지 판단한다.
- * @type {{x: *, y: *}}
- */
- if (checkWallPolygon.inPolygon(checkPoints)) {
- drawEavesFirstLines.push({ currentBaseLine, prevBaseLine, nextBaseLine })
- } else {
- drawEavesSecondLines.push({ currentBaseLine, prevBaseLine, nextBaseLine })
- }
- } 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)) {
- if (checkWallPolygon.inPolygon(checkPoints)) {
- drawGablePolygonFirst.push({ currentBaseLine, prevBaseLine, nextBaseLine })
- } else {
- drawGablePolygonSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine })
- }
- drawGableRidgeSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine })
- } else {
- if (currentAngle !== prevAngle && currentAngle !== nextAngle) {
- drawGablePolygonSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine })
- }
- }
- }
- }
-
- if (gableType.includes(currentLine.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 (
- 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 = []
- /** 용마루 */
- let baseRidgeLines = []
- /** 박공지붕 마루*/
- let baseGableRidgeLines = []
-
- /** 박공지붕 라인*/
- let baseGableLines = []
- /** 용마루의 갯수*/
- let baseRidgeCount = 0
-
- // console.log('drawEavesFirstLines :', drawEavesFirstLines)
- // console.log('drawEavesSecondLines :', drawEavesSecondLines)
- console.log('drawGableRidgeFirst: ', drawGableRidgeFirst)
- console.log('drawGableRidgeSecond:', drawGableRidgeSecond)
- console.log('drawGablePolygonFirst :', drawGablePolygonFirst)
- console.log('drawGablePolygonSecond :', drawGablePolygonSecond)
- // console.log('drawHipAndGableFirst :', drawHipAndGableFirst)
- // console.log('drawWallLines :', drawWallRidgeLine)
-
- /** 박공지붕에서 파생되는 마루를 그린다. ㄷ 형태*/
- drawGableRidgeFirst.forEach((current) => {
- const { currentBaseLine, prevBaseLine, nextBaseLine } = current
- const currentLine = currentBaseLine.line
- const prevLine = prevBaseLine.line
- const nextLine = nextBaseLine.line
-
- if (prevBaseLine.size !== prevLine.attributes.planeSize) {
- prevLine.x1 = prevBaseLine.x1
- prevLine.y1 = prevBaseLine.y1
- prevLine.x2 = prevBaseLine.x2
- prevLine.y2 = prevBaseLine.y2
- prevLine.setCoords()
- }
- if (nextBaseLine.size !== nextLine.attributes.planeSize) {
- nextLine.x1 = nextBaseLine.x1
- nextLine.y1 = nextBaseLine.y1
- nextLine.x2 = nextBaseLine.x2
- nextLine.y2 = nextBaseLine.y2
- nextLine.setCoords()
- }
-
- let { x1, x2, y1, y2, size } = currentBaseLine
- let beforePrevBaseLine, afterNextBaseLine
-
- /** 이전 라인의 경사 */
- const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
- /** 다음 라인의 경사 */
- const nextDegree = getDegreeByChon(nextLine.attributes.pitch)
-
- /** 이전 라인의 전라인, 다음 라인의 다음라인을 찾는다 */
- drawBaseLines.forEach((line, index) => {
- if (line === prevBaseLine) {
- beforePrevBaseLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length]
- }
- if (line === nextBaseLine) {
- afterNextBaseLine = drawBaseLines[(index + 1) % drawBaseLines.length]
- }
- })
-
- const beforePrevLine = beforePrevBaseLine?.line
- const afterNextLine = afterNextBaseLine?.line
-
- /** 각 라인의 흐름 방향을 확인한다. */
- const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint)
- const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
- const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
- const beforePrevAngle = calculateAngle(beforePrevLine.startPoint, beforePrevLine.endPoint)
- const afterNextAngle = calculateAngle(afterNextLine.startPoint, afterNextLine.endPoint)
-
- /** 현재라인의 vector*/
- const currentVectorX = Math.sign(Big(x2).minus(Big(x1)).toNumber())
- const currentVectorY = Math.sign(Big(y2).minus(Big(y1)).toNumber())
-
- /** 이전라인의 vector*/
- const prevVectorX = Math.sign(Big(prevLine.x2).minus(Big(prevLine.x1)))
- const prevVectorY = Math.sign(Big(prevLine.y2).minus(Big(prevLine.y1)))
-
- /** 다음라인의 vector*/
- const nextVectorX = Math.sign(Big(nextLine.x2).minus(Big(nextLine.x1)))
- const nextVectorY = Math.sign(Big(nextLine.y2).minus(Big(nextLine.y1)))
-
- /** 현재라인의 기준점*/
- let currentMidX = Big(x1).plus(Big(x2)).div(2).plus(Big(prevVectorX).times(currentLine.attributes.offset))
- let currentMidY = Big(y1).plus(Big(y2)).div(2).plus(Big(prevVectorY).times(currentLine.attributes.offset))
-
- /** 마루 반대 좌표*/
- 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) {
- const addLength = Big(currentLine.y1).minus(Big(currentLine.y2)).abs().div(2)
- const ridgeVector = Math.sign(prevLine.x1 - currentLine.x1)
- oppositeMidX = Big(prevLine.x1).plus(Big(addLength).times(ridgeVector))
-
- const ridgeEdge = {
- vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
- vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
- }
-
- const ridgeVectorX = Math.sign(ridgeEdge.vertex1.x - ridgeEdge.vertex2.x)
- roof.lines
- .filter((line) => line.x1 === line.x2)
- .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) {
- const isVectorX = Math.sign(ridgeEdge.vertex1.x - is.x)
- if (
- isVectorX === ridgeVectorX &&
- ((line.x1 <= currentMidX && line.x2 >= currentMidX) || (line.x2 <= currentMidX && line.x1 >= currentMidX))
- ) {
- currentMidX = Big(is.x)
- currentMidY = Big(is.y)
- }
- }
- })
- } else {
- const addLength = Big(currentLine.x1).minus(Big(currentLine.x2)).abs().div(2)
- const ridgeVector = Math.sign(prevLine.y1 - currentLine.y1)
- oppositeMidY = Big(prevLine.y1).plus(addLength.times(ridgeVector))
-
- const ridgeEdge = {
- vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
- vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
- }
- const ridgeVectorY = Math.sign(ridgeEdge.vertex1.y - ridgeEdge.vertex2.y)
- roof.lines
- .filter((line) => 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(ridgeEdge, lineEdge)
- if (is) {
- const isVectorY = Math.sign(ridgeEdge.vertex1.y - is.y)
- if (
- isVectorY === ridgeVectorY &&
- ((line.x1 <= currentMidX && line.x2 >= currentMidX) || (line.x2 <= currentMidX && line.x1 >= currentMidX))
- ) {
- currentMidX = Big(is.x)
- currentMidY = Big(is.y)
- }
- }
- })
- }
-
- const prevHipEdge = {
- vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
- vertex2: { x: prevLine.x1, y: prevLine.y1 },
- }
- const prevHipVectorX = Math.sign(prevHipEdge.vertex1.x - prevHipEdge.vertex2.x)
- const prevHipVectorY = Math.sign(prevHipEdge.vertex1.y - prevHipEdge.vertex2.y)
- const prevIsPoints = []
- roof.lines
- .filter((line) => (Math.sign(prevLine.x1 - prevLine.x2) === 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(prevHipEdge, lineEdge)
- if (is) {
- const isVectorX = Math.sign(prevHipEdge.vertex1.x - is.x)
- const isVectorY = Math.sign(prevHipEdge.vertex1.y - is.y)
- if (isVectorX === prevHipVectorX && isVectorY === prevHipVectorY) {
- const size = Big(prevHipEdge.vertex1.x)
- .minus(Big(is.x))
- .abs()
- .pow(2)
- .plus(Big(prevHipEdge.vertex1.y).minus(Big(is.y)).abs().pow(2))
- .sqrt()
- .toNumber()
- prevIsPoints.push({ is, size })
- }
- }
- })
-
- if (prevIsPoints.length > 0) {
- const prevIs = prevIsPoints.sort((a, b) => a.size - b.size)[0].is
- const prevHipLine = drawHipLine(
- [prevIs.x, prevIs.y, oppositeMidX.toNumber(), oppositeMidY.toNumber()],
- canvas,
- roof,
- textMode,
-
- prevDegree,
- prevDegree,
- )
- baseHipLines.push({
- x1: prevLine.x1,
- y1: prevLine.y1,
- x2: oppositeMidX.toNumber(),
- y2: oppositeMidY.toNumber(),
- line: prevHipLine,
- })
- }
-
- const nextHipEdge = {
- vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
- vertex2: { x: nextLine.x2, y: nextLine.y2 },
- }
- const nextHipVectorX = Math.sign(nextHipEdge.vertex1.x - nextHipEdge.vertex2.x)
- const nextHipVectorY = Math.sign(nextHipEdge.vertex1.y - nextHipEdge.vertex2.y)
- const nextIsPoints = []
-
- roof.lines
- .filter((line) => (Math.sign(nextLine.x1 - nextLine.x2) === 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(nextHipEdge, lineEdge)
- if (is) {
- const isVectorX = Math.sign(nextHipEdge.vertex1.x - is.x)
- const isVectorY = Math.sign(nextHipEdge.vertex1.y - is.y)
- if (isVectorX === nextHipVectorX && isVectorY === nextHipVectorY) {
- const size = Big(nextHipEdge.vertex1.x)
- .minus(Big(is.x))
- .abs()
- .pow(2)
- .plus(Big(nextHipEdge.vertex1.y).minus(Big(is.y)).abs().pow(2))
- .sqrt()
- .toNumber()
- nextIsPoints.push({ is, size })
- }
- }
- })
- if (nextIsPoints.length > 0) {
- const nextIs = nextIsPoints.sort((a, b) => a.size - b.size)[0].is
- const nextHipLine = drawHipLine(
- [nextIs.x, nextIs.y, oppositeMidX.toNumber(), oppositeMidY.toNumber()],
- canvas,
- roof,
- textMode,
-
- nextDegree,
- nextDegree,
- )
- baseHipLines.push({
- x1: nextLine.x2,
- y1: nextLine.y2,
- x2: oppositeMidX.toNumber(),
- y2: oppositeMidY.toNumber(),
- 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, degree, degree)
- const firstRoofLine = drawHipLine(firstRoofPoint, canvas, roof, textMode, prevDegree, prevDegree)
- const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, degree, degree)
- const secondRoofLine = drawHipLine(secondRoofPoint, canvas, roof, textMode, 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, prevDegree, prevDegree)
- const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, 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(
- [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()],
- canvas,
- roof,
- textMode,
- )
- baseGableRidgeLines.push(ridgeLine)
- baseRidgeCount++
- }
- } else {
- if (beforePrevBaseLine === afterNextBaseLine) {
- const afterNextMidX = Big(afterNextLine.x1).plus(Big(afterNextLine.x2)).div(2)
- const afterNextMidY = Big(afterNextLine.y1).plus(Big(afterNextLine.y2)).div(2)
- const vectorMidX = Math.sign(currentMidX.minus(afterNextMidX))
- const vectorMidY = Math.sign(currentMidY.minus(afterNextMidY))
-
- let oppositeMidX, oppositeMidY
- if (afterNextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
- const checkSize = currentMidX
- .minus(afterNextMidX)
- .pow(2)
- .plus(currentMidY.minus(afterNextMidY).pow(2))
- .sqrt()
- .minus(Big(afterNextLine.attributes.planeSize).div(20))
- .round(1)
- oppositeMidX = currentMidX.plus(checkSize.times(vectorMidX).neg())
- oppositeMidY = currentMidY.plus(checkSize.times(vectorMidY).neg())
-
- const xVector1 = Math.sign(Big(oppositeMidX).minus(Big(afterNextLine.x1)).neg().toNumber())
- const yVector1 = Math.sign(Big(oppositeMidY).minus(Big(afterNextLine.y1)).neg().toNumber())
- const xVector2 = Math.sign(Big(oppositeMidX).minus(Big(afterNextLine.x2)).neg().toNumber())
- const yVector2 = Math.sign(Big(oppositeMidY).minus(Big(afterNextLine.y2)).neg().toNumber())
-
- let addOppositeX1 = 0,
- addOppositeY1 = 0,
- addOppositeX2 = 0,
- addOppositeY2 = 0
-
- if (!checkWallPolygon.inPolygon({ x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() })) {
- const checkScale = currentMidX.minus(oppositeMidX).pow(2).plus(currentMidY.minus(oppositeMidY).pow(2)).sqrt()
- addOppositeX1 = checkScale.times(xVector1).toNumber()
- addOppositeY1 = checkScale.times(yVector1).toNumber()
- addOppositeX2 = checkScale.times(xVector2).toNumber()
- addOppositeY2 = checkScale.times(yVector2).toNumber()
- }
-
- let scale1 = Big(afterNextLine.attributes.offset).pow(2).plus(Big(nextLine.attributes.offset).pow(2)).sqrt()
- scale1 = scale1.eq(0) ? Big(1) : scale1
- let scale2 = Big(afterNextLine.attributes.offset).pow(2).plus(Big(prevLine.attributes.offset).pow(2)).sqrt()
- scale2 = scale2.eq(0) ? Big(1) : scale2
-
- const checkHip1 = {
- x1: Big(afterNextLine.x1).plus(scale1.times(xVector1)).toNumber(),
- y1: Big(afterNextLine.y1).plus(scale1.times(yVector1)).toNumber(),
- x2: oppositeMidX.plus(addOppositeX1).toNumber(),
- y2: oppositeMidY.plus(addOppositeY1).toNumber(),
- }
-
- const checkHip2 = {
- x1: Big(afterNextLine.x2).plus(scale2.times(xVector2)).toNumber(),
- y1: Big(afterNextLine.y2).plus(scale2.times(yVector2)).toNumber(),
- x2: oppositeMidX.plus(addOppositeX2).toNumber(),
- y2: oppositeMidY.plus(addOppositeY2).toNumber(),
- }
-
- const intersection1 = findRoofIntersection(roof, checkHip1, {
- x: oppositeMidX.plus(addOppositeX1),
- y: oppositeMidY.plus(addOppositeY1),
- })
- const intersection2 = findRoofIntersection(roof, checkHip2, {
- x: oppositeMidX.plus(addOppositeX2),
- y: oppositeMidY.plus(addOppositeY2),
- })
-
- const afterNextDegree = getDegreeByChon(afterNextLine.attributes.pitch)
-
- if (intersection1) {
- const hipLine = drawHipLine(
- [intersection1.intersection.x, intersection1.intersection.y, oppositeMidX.plus(addOppositeX1), oppositeMidY.plus(addOppositeY1)],
- canvas,
- roof,
- textMode,
-
- nextDegree,
- afterNextDegree,
- )
- baseHipLines.push({
- x1: afterNextLine.x1,
- y1: afterNextLine.y1,
- x2: oppositeMidX.plus(addOppositeX1).toNumber(),
- y2: oppositeMidY.plus(addOppositeY1).toNumber(),
- line: hipLine,
- })
- }
- if (intersection2) {
- const hipLine = drawHipLine(
- [intersection2.intersection.x, intersection2.intersection.y, oppositeMidX.plus(addOppositeX2), oppositeMidY.plus(addOppositeY2)],
- canvas,
- roof,
- textMode,
-
- prevDegree,
- afterNextDegree,
- )
- baseHipLines.push({
- x1: afterNextLine.x2,
- y1: afterNextLine.y2,
- x2: oppositeMidX.plus(addOppositeX2).toNumber(),
- y2: oppositeMidY.plus(addOppositeY2).toNumber(),
- line: hipLine,
- })
- }
- } else {
- oppositeMidX = Big(afterNextLine.x1).plus(Big(afterNextLine.x2)).div(2).plus(Big(prevVectorX).neg().times(afterNextLine.attributes.offset))
- oppositeMidY = Big(afterNextLine.y1).plus(Big(afterNextLine.y2)).div(2).plus(Big(prevVectorY).neg().times(afterNextLine.attributes.offset))
- }
-
- const vectorOppositeX = Math.sign(currentMidX.minus(oppositeMidX))
- const vectorOppositeY = Math.sign(currentMidY.minus(oppositeMidY))
-
- if (vectorMidX === vectorOppositeX && vectorMidY === vectorOppositeY) {
- if (!roof.inPolygon({ x: currentMidX.toNumber(), y: currentMidY.toNumber() })) {
- const checkEdge = {
- vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
- vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
- }
- const intersectionPoints = []
-
- 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 intersection = edgesIntersection(checkEdge, lineEdge)
- 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))
- ) {
- const size = Big(intersection.x)
- .minus(currentMidX)
- .abs()
- .pow(2)
- .plus(Big(intersection.y).minus(currentMidY).abs().pow(2))
- .sqrt()
- .toNumber()
- intersectionPoints.push({ intersection, size })
- }
- })
-
- if (intersectionPoints.length > 0) {
- const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection
- currentMidX = Big(intersection.x)
- currentMidY = Big(intersection.y)
- }
- }
-
- if (!roof.inPolygon({ x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() })) {
- const checkEdge = {
- vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
- vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
- }
- const intersectionPoints = []
-
- 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 intersection = edgesIntersection(checkEdge, lineEdge)
- 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))
- ) {
- const size = Big(intersection.x)
- .minus(oppositeMidX)
- .abs()
- .pow(2)
- .plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2))
- .sqrt()
- .toNumber()
- intersectionPoints.push({ intersection, size })
- }
- })
-
- if (intersectionPoints.length > 0) {
- const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection
- oppositeMidX = Big(intersection.x)
- oppositeMidY = Big(intersection.y)
- }
- }
-
- 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, degree, degree)
- const firstRoofLine = drawHipLine(firstRoofPoint, canvas, roof, textMode, prevDegree, prevDegree)
- const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, degree, degree)
- const secondRoofLine = drawHipLine(secondRoofPoint, canvas, roof, textMode, 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, prevDegree, prevDegree)
- const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, 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))
- const vectorMidY = Math.sign(Big(nextLine.y2).minus(nextLine.y1))
-
- let prevOppositeMidX, prevOppositeMidY, nextOppositeMidX, nextOppositeMidY
- const beforePrevOffset =
- currentAngle === beforePrevAngle
- ? Big(beforePrevLine.attributes.offset)
- : Big(beforePrevLine.attributes.offset).plus(currentLine.attributes.offset)
- const afterNextOffset =
- currentAngle === afterNextAngle
- ? Big(afterNextLine.attributes.offset)
- : Big(afterNextLine.attributes.offset).plus(currentLine.attributes.offset)
- const prevSize = Big(calcLinePlaneSize(prevLine)).div(10)
- const nextSize = Big(calcLinePlaneSize(nextLine)).div(10)
-
- let prevHipCoords, nextHipCoords
-
- /** 다음 라인이 그 다음 라인과의 사이에 추녀마루가 존재 하는지 확인. 처마-처마 인 경우 추녀마루*/
- if (eavesType.includes(afterNextLine.attributes?.type)) {
- /** 현재 라인의 길이를 기준으로 추녀 마루의 길이를 삼각함수를 사용하여 판단한다.*/
- let hipLength = Big(size).div(10).div(2).pow(2).plus(Big(size).div(10).div(2).pow(2)).sqrt()
-
- const nextHalfVector = getHalfAngleVector(nextLine, afterNextLine)
- let nextHipVector = { x: nextHalfVector.x, y: nextHalfVector.y }
-
- /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
- const nextCheckPoint = {
- x: Big(nextLine.x2).plus(Big(nextHalfVector.x).times(10)),
- y: Big(nextLine.y2).plus(Big(nextHalfVector.y).times(10)),
- }
- if (!checkWallPolygon.inPolygon(nextCheckPoint)) {
- nextHipVector = { x: Big(nextHipVector.x).neg().toNumber(), y: Big(nextHipVector.y).neg().toNumber() }
- }
-
- const nextEndPoint = {
- x: Big(nextLine.x2).plus(Big(nextHipVector.x).times(hipLength)),
- y: Big(nextLine.y2).plus(Big(nextHipVector.y).times(hipLength)),
- }
-
- let ridgeEdge = {
- vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
- vertex2: {
- x: currentMidX.plus(Big(nextVectorX).times(nextBaseLine.size)).toNumber(),
- y: currentMidY.plus(Big(nextVectorY).times(nextBaseLine.size)).toNumber(),
- },
- }
- let hipEdge = {
- vertex1: { x: nextLine.x2, y: nextLine.y2 },
- vertex2: { x: nextEndPoint.x, y: nextEndPoint.y },
- }
- let intersection = edgesIntersection(ridgeEdge, hipEdge)
- if (intersection) {
- nextHipCoords = { x1: nextLine.x2, y1: nextLine.y2, x2: intersection.x, y2: intersection.y }
- nextOppositeMidY = Big(intersection.y)
- nextOppositeMidX = Big(intersection.x)
- }
- } else {
- if (vectorMidX === 0) {
- nextOppositeMidY = currentMidY.plus(nextSize.plus(afterNextOffset).times(vectorMidY))
- nextOppositeMidX = currentMidX
- } else {
- nextOppositeMidX = currentMidX.plus(nextSize.plus(afterNextOffset).times(vectorMidX))
- nextOppositeMidY = currentMidY
- }
- }
-
- /** 이전 라인이 그 이전 라인과의 사이에 추녀마루가 존재 하는지 확인. 처마-처마 인 경우 추녀마루*/
- if (eavesType.includes(beforePrevLine.attributes?.type)) {
- /** 현재 라인의 길이를 기준으로 추녀 마루의 길이를 삼각함수를 사용하여 판단한다.*/
- let hipLength = Big(size).div(10).div(2).pow(2).plus(Big(size).div(10).div(2).pow(2)).sqrt()
-
- const prevHalfVector = getHalfAngleVector(prevLine, beforePrevLine)
- let prevHipVector = { x: prevHalfVector.x, y: prevHalfVector.y }
-
- /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
- const prevCheckPoint = {
- x: Big(prevLine.x1).plus(Big(prevHalfVector.x).times(10)),
- y: Big(prevLine.y1).plus(Big(prevHalfVector.y).times(10)),
- }
-
- if (!checkWallPolygon.inPolygon(prevCheckPoint)) {
- prevHipVector = { x: Big(prevHipVector.x).neg().toNumber(), y: Big(prevHipVector.y).neg().toNumber() }
- }
-
- const prevEndPoint = {
- x: Big(prevLine.x1).plus(Big(prevHipVector.x).times(hipLength)),
- y: Big(prevLine.y1).plus(Big(prevHipVector.y).times(hipLength)),
- }
-
- let ridgeEdge = {
- vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
- vertex2: {
- x: currentMidX.plus(Big(prevVectorX).times(prevBaseLine.size)).toNumber(),
- y: currentMidY.plus(Big(prevVectorY).times(prevBaseLine.size)).toNumber(),
- },
- }
- let hipEdge = {
- vertex1: { x: prevLine.x1, y: prevLine.y1 },
- vertex2: { x: prevEndPoint.x, y: prevEndPoint.y },
- }
- let intersection = edgesIntersection(ridgeEdge, hipEdge)
- if (intersection) {
- prevHipCoords = { x1: prevLine.x1, y1: prevLine.y1, x2: intersection.x, y2: intersection.y }
- prevOppositeMidY = Big(intersection.y)
- prevOppositeMidX = Big(intersection.x)
- }
- } else {
- if (vectorMidX === 0) {
- prevOppositeMidY = currentMidY.plus(prevSize.plus(beforePrevOffset).times(vectorMidY))
- prevOppositeMidX = currentMidX
- } else {
- prevOppositeMidX = currentMidX.plus(prevSize.plus(beforePrevOffset).times(vectorMidX))
- prevOppositeMidY = currentMidY
- }
- }
-
- const currentMidEdge = {
- vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
- vertex2: {
- x: currentVectorX === 0 ? nextLine.x2 : currentMidX.toNumber(),
- y: currentVectorX === 0 ? currentMidY.toNumber() : nextLine.y2,
- },
- }
-
- let oppositeLines = []
- drawBaseLines
- .filter((line, index) => {
- const currentLine = line.line
- const nextLine = drawBaseLines[(index + 1) % drawBaseLines.length].line
- const prevLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length].line
- const angle = calculateAngle(currentLine.startPoint, currentLine.endPoint)
- const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
- const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
- if (angle === prevAngle || angle === nextAngle) {
- const sameAngleLine = angle === prevAngle ? prevLine : nextLine
- if (gableType.includes(currentLine.attributes.type) && !gableType.includes(sameAngleLine.attributes.type)) {
- 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) {
- if (line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) {
- oppositeLines.push({
- line,
- intersection,
- size: Big(intersection.x)
- .minus(currentMidX)
- .abs()
- .pow(2)
- .plus(Big(intersection.y).minus(currentMidY).abs().pow(2))
- .sqrt()
- .toNumber(),
- })
- }
- }
- })
-
- if (oppositeLines.length > 0) {
- const oppositePoint = oppositeLines.sort((a, b) => a.size - b.size)[0].intersection
- const checkEdge = {
- vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
- vertex2: { x: oppositePoint.x, y: oppositePoint.y },
- }
- const oppositeRoofPoints = []
- roof.lines
- .filter((line) => {
- 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
- }
- })
- .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 &&
- ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) ||
- (line.x1 >= intersection.x && line.x2 <= intersection.x && line.y1 >= intersection.y && line.y2 <= intersection.y))
- ) {
- oppositeRoofPoints.push({
- line,
- intersection,
- size: Big(intersection.x)
- .minus(currentMidX.toNumber())
- .abs()
- .pow(2)
- .plus(Big(intersection.y).minus(currentMidY.toNumber()).abs().pow(2))
- .sqrt()
- .toNumber(),
- })
- }
- })
- const oppositeRoofPoint = oppositeRoofPoints.sort((a, b) => a.size - b.size)[0].intersection
- oppositeMidX = Big(oppositeRoofPoint.x)
- oppositeMidY = Big(oppositeRoofPoint.y)
-
- const currentRoofPoints = []
- roof.lines
- .filter((line) => {
- const angle = calculateAngle(line.startPoint, line.endPoint)
- return currentAngle === angle
- })
- .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 &&
- ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) ||
- (line.x1 >= intersection.x && line.x2 <= intersection.x && line.y1 >= intersection.y && line.y2 <= intersection.y))
- ) {
- currentRoofPoints.push({
- line,
- intersection,
- size: Big(intersection.x)
- .minus(currentMidX.toNumber())
- .abs()
- .pow(2)
- .plus(Big(intersection.y).minus(currentMidY.toNumber()).abs().pow(2))
- .sqrt()
- .toNumber(),
- })
- }
- })
- const currentRoofPoint = currentRoofPoints.sort((a, b) => a.size - b.size)[0].intersection
- currentMidX = Big(currentRoofPoint.x)
- currentMidY = Big(currentRoofPoint.y)
- } else {
- const checkPrevSize = currentMidX.minus(prevOppositeMidX).pow(2).plus(currentMidY.minus(prevOppositeMidY).pow(2)).sqrt()
- const checkNextSize = currentMidX.minus(nextOppositeMidX).pow(2).plus(currentMidY.minus(nextOppositeMidY).pow(2)).sqrt()
-
- /** 두 포인트 중에 current와 가까운 포인트를 사용*/
- if (checkPrevSize.gt(checkNextSize)) {
- if (nextHipCoords) {
- let intersectPoints = []
- const hipEdge = {
- vertex1: { x: nextHipCoords.x2, y: nextHipCoords.y2 },
- vertex2: { x: nextHipCoords.x1, y: nextHipCoords.y1 },
- }
-
- /** 외벽선에서 라인 겹치는 경우에 대한 확인*/
- roof.lines.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(hipEdge, lineEdge)
- if (
- intersection &&
- Math.sign(nextHipCoords.x2 - nextHipCoords.x1) === Math.sign(nextHipCoords.x2 - intersection.x) &&
- Math.sign(nextHipCoords.y2 - nextHipCoords.y1) === Math.sign(nextHipCoords.y2 - intersection.y)
- ) {
- const intersectEdge = {
- vertex1: { x: nextHipCoords.x2, y: nextHipCoords.y2 },
- vertex2: { x: intersection.x, y: intersection.y },
- }
- const is = edgesIntersection(intersectEdge, lineEdge)
- if (!is.isIntersectionOutside) {
- const intersectSize = Big(nextHipCoords.x2)
- .minus(Big(intersection.x))
- .pow(2)
- .plus(Big(nextHipCoords.y2).minus(Big(intersection.y)).pow(2))
- .abs()
- .sqrt()
- .toNumber()
-
- intersectPoints.push({
- intersection,
- size: intersectSize,
- line,
- })
- }
- }
- })
- const intersect = intersectPoints.sort((a, b) => a.size - b.size)[0]
- if (intersect) {
- const degree = getDegreeByChon(intersect.line.attributes.pitch)
- const hipLine = drawHipLine(
- [intersect.intersection.x, intersect.intersection.y, nextOppositeMidX.toNumber(), nextOppositeMidY.toNumber()],
- canvas,
- roof,
- textMode,
-
- degree,
- degree,
- )
- baseHipLines.push({
- x1: nextHipCoords.x1,
- y1: nextHipCoords.y1,
- x2: nextHipCoords.x2,
- y2: nextHipCoords.y2,
- line: hipLine,
- })
- }
- }
- oppositeMidY = nextOppositeMidY
- oppositeMidX = nextOppositeMidX
- } else {
- if (prevHipCoords) {
- let intersectPoints = []
- const hipEdge = {
- vertex1: { x: prevHipCoords.x2, y: prevHipCoords.y2 },
- vertex2: { x: prevHipCoords.x1, y: prevHipCoords.y1 },
- }
-
- /** 외벽선에서 라인 겹치는 경우에 대한 확인*/
- roof.lines.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(hipEdge, lineEdge)
- if (
- intersection &&
- Math.sign(prevHipCoords.x2 - prevHipCoords.x1) === Math.sign(prevHipCoords.x2 - intersection.x) &&
- Math.sign(prevHipCoords.y2 - prevHipCoords.y1) === Math.sign(prevHipCoords.y2 - intersection.y)
- ) {
- const intersectEdge = {
- vertex1: { x: prevHipCoords.x2, y: prevHipCoords.y2 },
- vertex2: { x: intersection.x, y: intersection.y },
- }
- const is = edgesIntersection(intersectEdge, lineEdge)
- if (!is.isIntersectionOutside) {
- const intersectSize = Big(prevHipCoords.x2)
- .minus(Big(intersection.x))
- .pow(2)
- .plus(Big(prevHipCoords.y2).minus(Big(intersection.y)).pow(2))
- .abs()
- .sqrt()
- .toNumber()
-
- intersectPoints.push({
- intersection,
- size: intersectSize,
- line,
- })
- }
- }
- })
- const intersect = intersectPoints.sort((a, b) => a.size - b.size)[0]
-
- if (intersect) {
- const degree = getDegreeByChon(intersect.line.attributes.pitch)
- const hipLine = drawHipLine(
- [intersect.intersection.x, intersect.intersection.y, prevOppositeMidX.toNumber(), prevOppositeMidY.toNumber()],
- canvas,
- roof,
- textMode,
-
- degree,
- degree,
- )
- baseHipLines.push({
- x1: prevHipCoords.x1,
- y1: prevHipCoords.y1,
- x2: prevHipCoords.x2,
- y2: prevHipCoords.y2,
- line: hipLine,
- })
- }
- }
- oppositeMidY = prevOppositeMidY
- oppositeMidX = prevOppositeMidX
- }
- }
-
- /** 포인트가 지붕 밖에 있는 경우 조정 */
- if (!roof.inPolygon({ x: currentMidX.toNumber(), y: currentMidY.toNumber() })) {
- const checkEdge = {
- vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
- vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
- }
- const intersectionPoints = []
-
- 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 intersection = edgesIntersection(checkEdge, lineEdge)
- 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))
- ) {
- const size = Big(intersection.x)
- .minus(currentMidX)
- .abs()
- .pow(2)
- .plus(Big(intersection.y).minus(currentMidY).abs().pow(2))
- .sqrt()
- .toNumber()
- intersectionPoints.push({ intersection, size })
- }
- })
-
- if (intersectionPoints.length > 0) {
- const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection
- currentMidX = Big(intersection.x)
- currentMidY = Big(intersection.y)
- }
- }
-
- if (!roof.inPolygon({ x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() })) {
- const checkEdge = {
- vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
- vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
- }
- const intersectionPoints = []
-
- 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 intersection = edgesIntersection(checkEdge, lineEdge)
- 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))
- ) {
- const size = Big(intersection.x)
- .minus(oppositeMidX)
- .abs()
- .pow(2)
- .plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2))
- .sqrt()
- .toNumber()
- intersectionPoints.push({ intersection, size })
- }
- })
-
- if (intersectionPoints.length > 0) {
- const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection
- oppositeMidX = Big(intersection.x)
- oppositeMidY = Big(intersection.y)
- }
- }
-
- 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, degree, degree)
- const firstRoofLine = drawHipLine(firstRoofPoint, canvas, roof, textMode, prevDegree, prevDegree)
- const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, degree, degree)
- const secondRoofLine = drawHipLine(secondRoofPoint, canvas, roof, textMode, 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, prevDegree, prevDegree)
- const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, 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() },
- vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
- }
- const ridgeVectorX = Math.sign(currentMidX.minus(oppositeMidX).toNumber())
- const ridgeVectorY = Math.sign(currentMidY.minus(oppositeMidY).toNumber())
-
- roof.lines
- .filter((line) => {
- const lineVectorX = Math.sign(Big(line.x2).minus(Big(line.x1)).toNumber())
- const lineVectorY = Math.sign(Big(line.y2).minus(Big(line.y1)).toNumber())
- return (
- (lineVectorX === currentVectorX && lineVectorY !== currentVectorY) || (lineVectorX !== currentVectorX && lineVectorY === currentVectorY)
- )
- })
- .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 && !intersection.isIntersectionOutside) {
- const isVectorX = Math.sign(Big(currentMidX).minus(intersection.x).toNumber())
- const isVectorY = Math.sign(Big(currentMidY).minus(intersection.y).toNumber())
- if (isVectorX === ridgeVectorX && isVectorY === ridgeVectorY) {
- oppositeMidX = Big(intersection.x)
- oppositeMidY = Big(intersection.y)
- }
- }
- })
- if (baseRidgeCount < getMaxRidge(baseLines.length)) {
- const ridgeLine = drawRidgeLine(
- [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()],
- canvas,
- roof,
- textMode,
- )
- baseGableRidgeLines.push(ridgeLine)
- baseRidgeCount++
- }
- }
- }
- })
-
- /** 박공지붕에서 파생되는 마루를 그린다. 첫번째에서 처리 하지 못한 라인이 있는 경우 */
- drawGableRidgeSecond.forEach((current) => {
- const { currentBaseLine, prevBaseLine, nextBaseLine } = current
- const currentLine = currentBaseLine.line
- const prevLine = prevBaseLine.line
- const nextLine = nextBaseLine.line
-
- /** 이전 라인의 경사 */
- const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
- /** 다음 라인의 경사 */
- const nextDegree = getDegreeByChon(nextLine.attributes.pitch)
-
- const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint)
- const currentVectorX = Big(currentLine.x2).minus(currentLine.x1)
- const currentVectorY = Big(currentLine.y2).minus(currentLine.y1)
- const checkVectorX = Big(nextLine.x2).minus(Big(nextLine.x1))
- const checkVectorY = 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 checkSize = Big(10)
-
- /** 현재 라인의 지붕선을 찾는다. */
- 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(),
- })
- }
- }
- })
- }
- 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: {
- x: currentMidX.plus(checkSize.times(Math.sign(checkVectorX.neg().toNumber()))).toNumber(),
- y: currentMidY.plus(checkSize.times(Math.sign(checkVectorY.neg().toNumber()))).toNumber(),
- },
- }
- let oppositeLines = []
- baseLines
- .filter((line) => {
- if (eavesType.includes(line.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
- default:
- return false
- }
- } else {
- 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) => b.size - a.size)[0].line
-
- 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 {
- const ridgeX = Big(currentLine.x1).plus(Big(oppositeLine.x1)).div(2).round()
- ridgePoint = [ridgeX.toNumber(), currentRoof.y1, ridgeX.toNumber(), currentRoof.y2]
- }
- 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]) ||
- segmentsOverlap(line, { x1: ridgePoint[0], y1: ridgePoint[1], x2: ridgePoint[2], y2: ridgePoint[3] }),
- )
- if (baseRidgeCount < getMaxRidge(baseLines.length) && !isAlreadyRidge) {
- const ridgeLine = drawRidgeLine(ridgePoint, canvas, roof, textMode)
- baseGableRidgeLines.push(ridgeLine)
- baseRidgeCount++
- }
- } else {
- 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(),
- },
- }
-
- 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]
- }
- }
- 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,
-
- 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,
-
- 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 {
- 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 uniqueRidgeLines = []
- /** 중복제거 */
- baseGableRidgeLines.forEach((currentLine, index) => {
- if (index === 0) {
- uniqueRidgeLines.push(currentLine)
- } else {
- const duplicateLines = uniqueRidgeLines.filter(
- (line) =>
- (currentLine.x1 === line.x1 && currentLine.y1 === line.y1 && currentLine.x2 === line.x2 && currentLine.y2 === line.y2) ||
- (currentLine.x1 === line.x2 && currentLine.y1 === line.y2 && currentLine.x2 === line.x1 && currentLine.y2 === line.y1),
- )
- if (duplicateLines.length === 0) {
- uniqueRidgeLines.push(currentLine)
- }
- }
- })
-
- baseGableRidgeLines = uniqueRidgeLines
-
- /** 박공지붕 polygon 생성 */
- drawGablePolygonFirst.forEach((current) => {
- const { currentBaseLine, prevBaseLine, nextBaseLine } = current
- const currentLine = currentBaseLine.line
- const prevLine = prevBaseLine.line
- const nextLine = nextBaseLine.line
-
- 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 = getDegreeByChon(currentLine.attributes.pitch)
-
- 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
- }
-
- 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)
-
- 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 },
- }
-
- let polygonPoints = [
- { x: currentRoof.x1, y: currentRoof.y1 },
- { x: currentRoof.x2, y: currentRoof.y2 },
- ]
- const prevHipLines = []
- const nextHipLines = []
- let prevLineRidge, nextLineRidge
-
- 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)
- }
- 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,
- }))
- ) {
- nextHipLines.push(current)
- }
- })
- 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 }
- }
-
- 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)
- )
- })
- }
- })
- nextHipLines.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 !== undefined && nextLineRidge !== undefined) {
- /** 4각*/
- if (prevLineRidge === nextLineRidge) {
- polygonPoints.push({ x: ridgeLine.x1, y: ridgeLine.y1 }, { x: ridgeLine.x2, y: ridgeLine.y2 })
- /** 포인트가 직각 사각형인지 확인하여 아닌경우 직각인 다각형 포인트로 변경한다.*/
- const checkPoints = getSortedPoint(polygonPoints, baseHipLines)
- let hasDiagonal = false
- if (checkPoints < 4) {
- hasDiagonal = true
- } else {
- checkPoints.forEach((point, index) => {
- const nextPoint = checkPoints[(index + 1) % checkPoints.length]
- if (point.x !== nextPoint.x && point.y !== nextPoint.y) {
- hasDiagonal = true
- }
- })
- }
- if (hasDiagonal) {
- const vectorX = Math.sign(currentRoof.x1 - ridgeLine.x1)
- const vectorY = Math.sign(currentRoof.y1 - ridgeLine.y1)
- const ridgeMinX = Math.min(ridgeLine.x1, ridgeLine.x2)
- const ridgeMaxX = Math.max(ridgeLine.x1, ridgeLine.x2)
- const ridgeMinY = Math.min(ridgeLine.y1, ridgeLine.y2)
- const ridgeMaxY = Math.max(ridgeLine.y1, ridgeLine.y2)
- if (
- (!isPointOnLineNew(prevRoof, { x: ridgeLine.x1, y: ridgeLine.y1 }) &&
- !isPointOnLineNew(nextRoof, { x: ridgeLine.x1, y: ridgeLine.y1 })) ||
- (!isPointOnLineNew(prevRoof, { x: ridgeLine.x2, y: ridgeLine.y2 }) && !isPointOnLineNew(nextRoof, { x: ridgeLine.x2, y: ridgeLine.y2 }))
- ) {
- roof.lines
- .filter((line) => line !== currentRoof && line !== prevRoof && line !== nextRoof)
- .filter((line) =>
- ridgeLine.y1 === ridgeLine.y2
- ? vectorY === Math.sign(line.y1 - ridgeLine.y1) &&
- ridgeMinX <= line.x1 &&
- line.x1 <= ridgeMaxX &&
- ridgeMinX <= line.x2 &&
- line.x2 <= ridgeMaxX
- : vectorX === Math.sign(line.x1 - ridgeLine.x1) &&
- ridgeMinY <= line.y1 &&
- line.y1 <= ridgeMaxY &&
- ridgeMinY <= line.y2 &&
- line.y2 <= ridgeMaxY,
- )
- .forEach((line) => {
- if (ridgeLine.y1 === ridgeLine.y2) {
- if (vectorY === Math.sign(line.y1 - ridgeLine.y1)) {
- polygonPoints.push({ x: line.x1, y: line.y1 })
- }
- if (vectorY === Math.sign(line.y2 - ridgeLine.y1)) {
- polygonPoints.push({ x: line.x2, y: line.y2 })
- }
- } else {
- if (vectorX === Math.sign(line.x1 - ridgeLine.x1)) {
- polygonPoints.push({ x: line.x1, y: line.y1 })
- }
- if (vectorX === Math.sign(line.x2 - ridgeLine.x1)) {
- polygonPoints.push({ x: line.x2, y: line.y2 })
- }
- }
- })
- }
- if (
- !isPointOnLineNew(prevRoof, { x: ridgeLine.x2, y: ridgeLine.y2 }) &&
- !isPointOnLineNew(nextRoof, { x: ridgeLine.x2, y: ridgeLine.y2 })
- ) {
- }
- }
- } else {
- /** 6각이상*/
- let isOverLap =
- currentVectorX === 0
- ? (prevLineRidge.y1 <= nextLineRidge.y1 && prevLineRidge.y2 >= nextLineRidge.y1) ||
- (prevLineRidge.y1 >= nextLineRidge.y1 && prevLineRidge.y2 <= nextLineRidge.y1) ||
- (prevLineRidge.y1 <= nextLineRidge.y2 && prevLineRidge.y2 >= nextLineRidge.y2) ||
- (prevLineRidge.y1 >= nextLineRidge.y2 && prevLineRidge.y2 <= nextLineRidge.y2)
- : (prevLineRidge.x1 <= nextLineRidge.x1 && prevLineRidge.x2 >= nextLineRidge.x1) ||
- (prevLineRidge.x1 >= nextLineRidge.x1 && prevLineRidge.x2 <= nextLineRidge.x1) ||
- (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 - currentRoof.x1) : Math.abs(prevLineRidge.y1 - currentRoof.y1)
- const nextDistance = currentVectorX === 0 ? Math.abs(nextLineRidge.x1 - currentRoof.x1) : Math.abs(nextLineRidge.y1 - currentRoof.y1)
-
- /** 현재 지붕 라인과 먼 라인의 포인트를 온전히 사용한다. */
- 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)
- }
-
- /** 다음 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/
- 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 }
- polygonPoints.push(prevRidgePoint2)
- } else {
- polygonPoints.push({ x: prevLineRidge.x1, y: prevLineRidge.y1 }, { x: prevLineRidge.x2, y: prevLineRidge.y2 })
-
- /** 다음라인과 교차한 마루의 포인트*/
- 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)
- }
-
- /** 이전 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/
- 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 }
- polygonPoints.push(nextRidgePoint2)
- }
- } else {
- /** 마루가 겹치지 않을때 */
- const otherRidgeLines = []
-
- baseGableRidgeLines
- .filter((ridge) => ridge !== prevLineRidge && ridge !== nextLineRidge)
- .filter((ridge) => (currentVectorX === 0 ? ridge.x1 === ridge.x2 : ridge.y1 === ridge.y2))
- .filter((ridge) =>
- currentVectorX === 0 ? nextVectorX === Math.sign(nextLine.x1 - ridge.x1) : nextVectorY === Math.sign(nextLine.y1 - ridge.y1),
- )
- .forEach((ridge) => {
- const size = currentVectorX === 0 ? Math.abs(nextLine.x1 - ridge.x1) : Math.abs(nextLine.y1 - ridge.y1)
- otherRidgeLines.push({ ridge, size })
- })
- if (otherRidgeLines.length > 0) {
- const otherRidge = otherRidgeLines.sort((a, b) => a.size - b.size)[0].ridge
- /**
- * otherRidge이 prevRidgeLine, nextRidgeLine 과 currentLine의 사이에 있는지 확인해서 분할하여 작업
- * 지붕의 덮힘이 다르기 때문
- */
- const isInside =
- currentVectorX === 0
- ? Math.abs(currentLine.x1 - otherRidge.x1) < Math.abs(currentLine.x1 - prevLineRidge.x1) &&
- Math.abs(currentLine.x1 - otherRidge.x1) < Math.abs(currentLine.x1 - nextLineRidge.x1)
- : Math.abs(currentLine.y1 - otherRidge.y1) < Math.abs(currentLine.y1 - prevLineRidge.y1) &&
- Math.abs(currentLine.y1 - otherRidge.y1) < Math.abs(currentLine.y1 - nextLineRidge.y1)
-
- if (isInside) {
- polygonPoints.push(
- { x: prevLineRidge.x1, y: prevLineRidge.y1 },
- { x: prevLineRidge.x2, y: prevLineRidge.y2 },
- { x: nextLineRidge.x1, y: nextLineRidge.y1 },
- { x: nextLineRidge.x2, y: nextLineRidge.y2 },
- )
-
- let ridgeAllPoints = [
- { x: prevLineRidge.x1, y: prevLineRidge.y1 },
- { x: prevLineRidge.x2, y: prevLineRidge.y2 },
- { x: nextLineRidge.x1, y: nextLineRidge.y1 },
- { x: nextLineRidge.x2, y: nextLineRidge.y2 },
- ]
- let ridgePoints = []
- ridgeAllPoints.forEach((point) => {
- let isOnLine = false
- roof.lines.forEach((line) => {
- if (isPointOnLine({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }, point)) {
- isOnLine = true
- }
- })
- if (!isOnLine) {
- ridgePoints.push(point)
- }
- })
- if (ridgePoints.length === 2) {
- if (Math.sign(otherRidge.x1 - otherRidge.x2) === 0) {
- polygonPoints.push(
- { x: otherRidge.x1, y: ridgePoints[0].y },
- {
- x: otherRidge.x1,
- y: ridgePoints[1].y,
- },
- )
- } else {
- polygonPoints.push(
- { x: ridgePoints[0].x, y: otherRidge.y1 },
- {
- x: ridgePoints[1].x,
- y: otherRidge.y1,
- },
- )
- }
- }
- } else {
- polygonPoints.push({ x: otherRidge.x1, y: otherRidge.y1 }, { x: otherRidge.x2, y: otherRidge.y2 })
-
- let ridgePoints = [
- { x: prevLineRidge.x1, y: prevLineRidge.y1 },
- { x: prevLineRidge.x2, y: prevLineRidge.y2 },
- { x: nextLineRidge.x1, y: nextLineRidge.y1 },
- { x: nextLineRidge.x2, y: nextLineRidge.y2 },
- ]
-
- ridgePoints.forEach((point) => {
- let isOnLine = false
- roof.lines.forEach((line) => {
- if (isPointOnLine({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }, point)) {
- isOnLine = true
- }
- })
- if (isOnLine) {
- polygonPoints.push(point)
- }
- })
-
- if (Math.sign(otherRidge.x1 - otherRidge.x2) === 0) {
- const prevY =
- (prevLineRidge.y1 <= otherRidge.y1 && otherRidge.y1 <= prevLineRidge.y2) ||
- (prevLineRidge.y1 >= otherRidge.y1 && otherRidge.y1 >= prevLineRidge.y2)
- ? otherRidge.y1
- : otherRidge.y2
- const nextY =
- (nextLineRidge.y1 <= otherRidge.y1 && otherRidge.y1 <= nextLineRidge.y2) ||
- (nextLineRidge.y1 >= otherRidge.y1 && otherRidge.y1 >= nextLineRidge.y2)
- ? otherRidge.y1
- : otherRidge.y2
- polygonPoints.push({ x: prevLineRidge.x1, y: prevY }, { x: nextLineRidge.x1, y: nextY })
- } else {
- const prevX =
- (prevLineRidge.x1 <= otherRidge.x1 && otherRidge.x1 <= prevLineRidge.x2) ||
- (prevLineRidge.x1 >= otherRidge.x1 && otherRidge.x1 >= prevLineRidge.x2)
- ? otherRidge.x1
- : otherRidge.x2
- const nextX =
- (nextLineRidge.x1 <= otherRidge.x1 && otherRidge.x1 <= nextLineRidge.x2) ||
- (nextLineRidge.x1 >= otherRidge.x1 && otherRidge.x1 >= nextLineRidge.x2)
- ? otherRidge.x1
- : otherRidge.x2
- polygonPoints.push({ x: prevX, y: prevLineRidge.y1 }, { x: nextX, y: nextLineRidge.y1 })
- }
- }
- }
- }
- }
- } else {
- if (ridgeLine) {
- const ridgeEdge = { vertex1: { x: ridgeLine.x1, y: ridgeLine.y1 }, vertex2: { x: ridgeLine.x2, y: ridgeLine.y2 } }
- const prevRoofEdge = { vertex1: { x: prevRoof.x1, y: prevRoof.y1 }, vertex2: { x: prevRoof.x2, y: prevRoof.y2 } }
- const nextRoofEdge = { vertex1: { x: nextRoof.x1, y: nextRoof.y1 }, vertex2: { x: nextRoof.x2, y: nextRoof.y2 } }
- const isPrevRoof = edgesIntersection(prevRoofEdge, ridgeEdge)
- const isNextRoof = edgesIntersection(nextRoofEdge, ridgeEdge)
- if (isPrevRoof && isPointOnLine(ridgeLine, isPrevRoof)) {
- polygonPoints.push({ x: isPrevRoof.x, y: isPrevRoof.y })
- } else {
- polygonPoints.push({ x: prevRoof.x1, y: prevRoof.y1 })
- }
- if (isNextRoof && isPointOnLine(ridgeLine, isNextRoof)) {
- polygonPoints.push({ x: isNextRoof.x, y: isNextRoof.y })
- } else {
- polygonPoints.push({ x: nextRoof.x2, y: nextRoof.y2 })
- }
-
- roof.lines
- .filter((line) => line !== currentRoof && line !== prevRoof && line !== nextRoof)
- .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 && isPointOnLine(ridgeLine, intersection)) {
- const size1 = Math.sqrt(Math.pow(line.x1 - intersection.x, 2) + Math.pow(line.y1 - intersection.y, 2))
- const size2 = Math.sqrt(Math.pow(line.x2 - intersection.x, 2) + Math.pow(line.y2 - intersection.y, 2))
- if (size1 < size2) {
- polygonPoints.push({ x: line.x2, y: line.y2 })
- } else {
- polygonPoints.push({ x: line.x1, y: line.y1 })
- }
- polygonPoints.push({ x: intersection.x, y: intersection.y })
- }
- })
- }
- }
- /** 중복되는 포인트 제거 */
- 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)
-
- /*polygonPoints.forEach((point) => {
- const checkCircle = new fabric.Circle({
- left: point.x,
- top: point.y,
- radius: 4,
- fill: 'red',
- parentId: roofId,
- name: 'checkCircle',
- })
- canvas.add(checkCircle)
- canvas.renderAll()
-
- /!** 확인용 라인 제거 *!/
- canvas
- .getObjects()
- .filter((obj) => obj.name === 'checkCircle' || obj.name === 'checkLine')
- .forEach((obj) => canvas.remove(obj))
- canvas.renderAll()
- })*/
-
- 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
- }
-
- let line
- if (isParallel) {
- line = drawRoofLine(points, canvas, roof, textMode)
- baseGableLines.push(line)
- } else {
- line = drawHipLine(points, canvas, roof, textMode, currentDegree, currentDegree)
- baseHipLines.push({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2, line })
- }
- })
- }
- })
-
- drawGablePolygonSecond.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 checkLine = new fabric.Line([x1, y1, x2, y2], {
- stroke: 'red',
- strokeWidth: 4,
- parentId: roofId,
- name: 'checkLine',
- })
- canvas.add(checkLine)
- canvas.renderAll()*/
-
- const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1)
- const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1)
- const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
-
- const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
- const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
-
- 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 && isPointOnLine(line, intersection)) {
- intersectionRoofs.push({
- line,
- intersection,
- size: Math.sqrt(Math.pow(intersection.x - currentMidX.toNumber(), 2) + Math.pow(intersection.y - currentMidY.toNumber(), 2)),
- })
- }
- })
- } 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 && isPointOnLine(line, intersection)) {
- intersectionRoofs.push({
- line,
- intersection,
- size: Math.sqrt(Math.pow(intersection.x - currentMidX.toNumber(), 2) + Math.pow(intersection.y - currentMidY.toNumber(), 2)),
- })
- }
- })
- }
- 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(),
- }
-
- 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 })
- }
- }
- } 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: 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)
-
- 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
- }
- }
-
- let currentRidge
-
- if (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) {
- const minX = Math.min(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2)
- const maxX = Math.max(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2)
-
- if (minX <= prevRidge.x1 && maxX >= prevRidge.x1 && minX <= prevRidge.x2 && maxX >= prevRidge.x2) {
- currentRidge = prevRidge
- }
- }
- }
- if (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) {
- const minX = Math.min(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2)
- const maxX = Math.max(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2)
-
- if (minX <= nextRidge.x1 && maxX >= nextRidge.x1 && minX <= nextRidge.x2 && maxX >= nextRidge.x2) {
- currentRidge = nextRidge
- }
- }
- }
-
- if (currentRidge) {
- 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)
-
- if (!checkRidgePoint) return
- /** 마루에서 현재라인으로 향하는 외벽선까지의 포인트를 확인 하여 처리*/
- let checkEdge
- if (currentVectorX === 0) {
- checkEdge = {
- vertex1: { x: checkRidgePoint.x, y: checkRidgePoint.y },
- vertex2: { x: currentRoof.x1, y: checkRidgePoint.y },
- }
- } else {
- checkEdge = {
- 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 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 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)
- 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, currentDegree, currentDegree)
- if (currentVectorX === 0) {
- if (Math.sign(currentPoint.x - nextPoint.x) === 0) {
- hipLine.attributes.actualSize = hipLine.attributes.planeSize
- }
- } else {
- 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 })
- })
- })
-
- /** 케라바 지붕에 연결된 마루 중 처마라인이 그려지지 않은 경우 확*/
- baseGableRidgeLines.forEach((ridge) => {
- const ridgeVectorX = Math.sign(ridge.x1 - ridge.x2)
- const ridgeVectorY = Math.sign(ridge.y1 - ridge.y2)
-
- const firstGableLines = []
- const secondGableLines = []
-
- baseGableLines
- .filter((line) => (ridgeVectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2))
- .filter((line) => (line.x1 === ridge.x1 && line.y1 === ridge.y1) || (line.x2 === ridge.x1 && line.y2 === ridge.y1))
- .forEach((line) => firstGableLines.push(line))
- baseGableLines
- .filter((line) => (ridgeVectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2))
- .filter((line) => (line.x1 === ridge.x2 && line.y1 === ridge.y2) || (line.x2 === ridge.x2 && line.y2 === ridge.y2))
- .forEach((line) => secondGableLines.push(line))
- .filter((line) => (line.x1 === ridge.x1 && line.y1 === ridge.y1) || (line.x2 === ridge.x1 && line.y2 === ridge.y1))
- .forEach((line) => firstGableLines.push(line))
- baseHipLines
- .filter((line) => (ridgeVectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2))
- .filter((line) => (line.x1 === ridge.x2 && line.y1 === ridge.y2) || (line.x2 === ridge.x2 && line.y2 === ridge.y2))
- .forEach((line) => secondGableLines.push(line))
-
- let degree1, degree2
- if (firstGableLines.length < 2 || secondGableLines.length < 2) {
- drawBaseLines.forEach((currentBaseLine, index) => {
- let prevBaseLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length]
- let nextBaseLine = drawBaseLines[(index + 1) % drawBaseLines.length]
- const currentLine = currentBaseLine.line
- const prevLine = prevBaseLine.line
- const nextLine = nextBaseLine.line
- const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
- const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
-
- if (
- gableType.includes(currentLine.attributes?.type) &&
- eavesType.includes(prevLine.attributes?.type) &&
- eavesType.includes(nextLine.attributes?.type) &&
- Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)
- ) {
- if (
- ridgeVectorX === 0 &&
- currentLine.x1 !== currentLine.x2 &&
- ((currentLine.x1 <= ridge.x1 && ridge.x1 <= currentLine.x2) || (currentLine.x2 <= ridge.x1 && ridge.x1 <= currentLine.x1))
- ) {
- degree1 = getDegreeByChon(prevLine.attributes.pitch)
- degree2 = getDegreeByChon(nextLine.attributes.pitch)
- }
-
- if (
- ridgeVectorY === 0 &&
- currentLine.y1 !== currentLine.y2 &&
- ((currentLine.y1 <= ridge.y1 && ridge.y1 <= currentLine.y2) || (currentLine.y2 <= ridge.y1 && ridge.y1 <= currentLine.y1))
- ) {
- degree1 = getDegreeByChon(prevLine.attributes.pitch)
- degree2 = getDegreeByChon(nextLine.attributes.pitch)
- }
- }
- })
- }
-
- if (firstGableLines.length < 2) {
- const connectRoof = roof.lines.find(
- (line) =>
- (line.x1 <= ridge.x1 && line.x2 >= ridge.x1 && line.y1 <= ridge.y1 && line.y2 >= ridge.y1) ||
- (line.x2 <= ridge.x1 && line.x1 >= ridge.x1 && line.y2 <= ridge.y1 && line.y1 >= ridge.y1),
- )
- if (connectRoof) {
- let hipPoint1 = [connectRoof.x1, connectRoof.y1, ridge.x1, ridge.y1]
- let hipPoint2 = [connectRoof.x2, connectRoof.y2, ridge.x1, ridge.y1]
- let intersectPoints1
- let intersectPoints2
- baseHipLines
- .filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2)
- .forEach((hip) => {
- const line = hip.line
- if (
- (hipPoint1[0] <= line.x1 && line.x1 <= hipPoint1[2] && hipPoint1[1] <= line.y1 && line.y1 <= hipPoint1[3]) ||
- (hipPoint1[2] <= line.x1 && line.x1 <= hipPoint1[0] && hipPoint1[3] <= line.y1 && line.y1 <= hipPoint1[1])
- ) {
- intersectPoints1 = { x: line.x1, y: line.y1 }
- }
- if (
- (hipPoint1[0] <= line.x2 && line.x2 <= hipPoint1[2] && hipPoint1[1] <= line.y2 && line.y2 <= hipPoint1[3]) ||
- (hipPoint1[2] <= line.x2 && line.x2 <= hipPoint1[0] && hipPoint1[3] <= line.y2 && line.y2 <= hipPoint1[1])
- ) {
- intersectPoints1 = { x: line.x2, y: line.y2 }
- }
- if (
- (hipPoint2[0] <= line.x1 && line.x1 <= hipPoint2[2] && hipPoint2[1] <= line.y1 && line.y1 <= hipPoint2[3]) ||
- (hipPoint2[2] <= line.x1 && line.x1 <= hipPoint2[0] && hipPoint2[3] <= line.y1 && line.y1 <= hipPoint2[1])
- ) {
- intersectPoints2 = { x: line.x1, y: line.y1 }
- }
- if (
- (hipPoint2[0] <= line.x2 && line.x2 <= hipPoint2[2] && hipPoint2[1] <= line.y2 && line.y2 <= hipPoint2[3]) ||
- (hipPoint2[2] <= line.x2 && line.x2 <= hipPoint2[0] && hipPoint2[3] <= line.y2 && line.y2 <= hipPoint2[1])
- ) {
- intersectPoints2 = { x: line.x2, y: line.y2 }
- }
- })
- if (intersectPoints1) {
- hipPoint1 = [intersectPoints1.x, intersectPoints1.y, ridge.x1, ridge.y1]
- }
- if (intersectPoints2) {
- hipPoint2 = [intersectPoints2.x, intersectPoints2.y, ridge.x1, ridge.y1]
- }
-
- if (hipPoint1) {
- 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 (gableLines.length === 0 && hipLines.length === 0) {
- const hipLine1 = drawHipLine(hipPoint1, canvas, roof, textMode, degree1, degree1)
- baseHipLines.push({ x1: hipLine1.x1, y1: hipLine1.y1, x2: hipLine1.x2, y2: hipLine1.y2, line: hipLine1 })
- }
- }
- if (hipPoint2) {
- 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, degree2, degree2)
- baseHipLines.push({ x1: hipLine2.x1, y1: hipLine2.y1, x2: hipLine2.x2, y2: hipLine2.y2, line: hipLine2 })
- }
- }
- }
- }
- if (secondGableLines.length < 2) {
- const connectRoof = roof.lines.find(
- (line) =>
- (line.x1 <= ridge.x2 && line.x2 >= ridge.x2 && line.y1 <= ridge.y2 && line.y2 >= ridge.y2) ||
- (line.x2 <= ridge.x2 && line.x1 >= ridge.x2 && line.y2 <= ridge.y2 && line.y1 >= ridge.y2),
- )
- if (connectRoof) {
- let hipPoint1 = [connectRoof.x1, connectRoof.y1, ridge.x2, ridge.y2]
- let hipPoint2 = [connectRoof.x2, connectRoof.y2, ridge.x2, ridge.y2]
- let intersectPoints1
- let intersectPoints2
-
- baseHipLines
- .filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2)
- .forEach((hip) => {
- const line = hip.line
- if (
- (hipPoint1[0] <= line.x1 && line.x1 <= hipPoint1[2] && hipPoint1[1] <= line.y1 && line.y1 <= hipPoint1[3]) ||
- (hipPoint1[2] <= line.x1 && line.x1 <= hipPoint1[0] && hipPoint1[3] <= line.y1 && line.y1 <= hipPoint1[1])
- ) {
- intersectPoints1 = { x: line.x1, y: line.y1 }
- }
- if (
- (hipPoint1[0] <= line.x2 && line.x2 <= hipPoint1[2] && hipPoint1[1] <= line.y2 && line.y2 <= hipPoint1[3]) ||
- (hipPoint1[2] <= line.x2 && line.x2 <= hipPoint1[0] && hipPoint1[3] <= line.y2 && line.y2 <= hipPoint1[1])
- ) {
- intersectPoints1 = { x: line.x2, y: line.y2 }
- }
- if (
- (hipPoint2[0] <= line.x1 && line.x1 <= hipPoint2[2] && hipPoint2[1] <= line.y1 && line.y1 <= hipPoint2[3]) ||
- (hipPoint2[2] <= line.x1 && line.x1 <= hipPoint2[0] && hipPoint2[3] <= line.y1 && line.y1 <= hipPoint2[1])
- ) {
- intersectPoints2 = { x: line.x1, y: line.y1 }
- }
- if (
- (hipPoint2[0] <= line.x2 && line.x2 <= hipPoint2[2] && hipPoint2[1] <= line.y2 && line.y2 <= hipPoint2[3]) ||
- (hipPoint2[2] <= line.x2 && line.x2 <= hipPoint2[0] && hipPoint2[3] <= line.y2 && line.y2 <= hipPoint2[1])
- ) {
- intersectPoints2 = { x: line.x2, y: line.y2 }
- }
- })
-
- if (intersectPoints1) {
- hipPoint1 = [intersectPoints1.x, intersectPoints1.y, ridge.x2, ridge.y2]
- }
- if (intersectPoints2) {
- hipPoint2 = [intersectPoints2.x, intersectPoints2.y, ridge.x2, ridge.y2]
- }
-
- if (hipPoint1) {
- 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 (hipLines.length === 0 && gableLines.length === 0) {
- const hipLine1 = drawHipLine(hipPoint1, canvas, roof, textMode, degree1, degree1)
- baseHipLines.push({ x1: hipLine1.x1, y1: hipLine1.y1, x2: hipLine1.x2, y2: hipLine1.y2, line: hipLine1 })
- }
- }
- if (hipPoint2) {
- 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, degree2, degree2)
- baseHipLines.push({ x1: hipLine2.x1, y1: hipLine2.y1, x2: hipLine2.x2, y2: hipLine2.y2, line: hipLine2 })
- }
- }
- }
- }
- })
-
- /** 팔작지붕 */
- 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()
-
- /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
- 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, prevDegree, currentDegree)
- const nextHipLine = drawHipLine(nextPoint, canvas, roof, textMode, 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, prevDegree, currentDegree)
- const nextGableLine = drawHipLine(nextGablePoint, canvas, roof, textMode, 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(midX).abs().pow(2).plus(Big(isBefore.y).minus(midY).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(midX).abs().pow(2).plus(Big(isAfter.y).minus(midY).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
- }
-
- 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(midX).abs().pow(2).plus(Big(isOppPrev.y).minus(midY).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(midX).abs().pow(2).plus(Big(isOppNext.y).minus(midY).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, prevDegree, prevDegree)
- const nextHipLine = drawHipLine(nextHipPoint, canvas, roof, textMode, 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) => {
- // 확인용 라인, 포인트 제거
- const { currentBaseLine, prevBaseLine, nextBaseLine } = current
- const currentLine = currentBaseLine.line
- const prevLine = prevBaseLine.line
- const nextLine = nextBaseLine.line
- let { x1, x2, y1, y2, size } = currentBaseLine
- let beforePrevLine, afterNextLine
-
- /** 이전 라인의 경사 */
- const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
- /** 다음 라인의 경사 */
- const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
-
- /** 이전 라인의 전라인, 다음 라인의 다음라인을 찾는다 */
- drawBaseLines.forEach((line, index) => {
- if (line === prevBaseLine) {
- beforePrevLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length]
- }
- if (line === nextBaseLine) {
- afterNextLine = drawBaseLines[(index + 1) % drawBaseLines.length]
- }
- })
-
- /** 이전, 다음라인의 사잇각의 vector를 구한다. */
- let prevVector = getHalfAngleVector(prevLine, currentLine)
- let nextVector = getHalfAngleVector(currentLine, nextLine)
-
- let prevHipVector = { x: prevVector.x, y: prevVector.y }
- let nextHipVector = { x: nextVector.x, y: nextVector.y }
-
- /** 각 라인의 흐름 방향을 확인한다. */
- const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint)
- const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
- const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
- const beforePrevAngle = calculateAngle(beforePrevLine.line.startPoint, beforePrevLine.line.endPoint)
- const afterNextAngle = calculateAngle(afterNextLine.line.startPoint, afterNextLine.line.endPoint)
-
- /** 현재 라인의 길이 추녀마루 길이의 기준이 된다. */
- let currentSize = Big(size).div(10)
-
- /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
- const prevCheckPoint = {
- x: Big(x1).plus(Big(prevHipVector.x).times(10)),
- y: Big(y1).plus(Big(prevHipVector.y).times(10)),
- }
- if (!checkWallPolygon.inPolygon(prevCheckPoint)) {
- prevHipVector = { x: -prevHipVector.x, y: -prevHipVector.y }
- }
-
- /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
- const nextCheckPoint = {
- x: Big(x2).plus(Big(nextHipVector.x).times(10)),
- y: Big(y2).plus(Big(nextHipVector.y).times(10)),
- }
- if (!checkWallPolygon.inPolygon(nextCheckPoint)) {
- nextHipVector = { x: -nextHipVector.x, y: -nextHipVector.y }
- }
-
- /** 현재 라인의 길이를 기준으로 추녀 마루의 길이를 삼각함수를 사용하여 판단한다.*/
- let hipLength = currentSize.div(2).pow(2).plus(currentSize.div(2).pow(2)).sqrt()
-
- /**
- * 현재 라인에서 2번째 전 라인과 2번째 후 라인의 각도가 같을때 -_- 와 같은 형태로 판단하고
- * 맞은 편 외벽선까지의 거리를 확인후 currentSize 를 조정한다.
- */
- if (beforePrevLine === afterNextLine || (currentAngle === beforePrevAngle && currentAngle === afterNextAngle)) {
- console.log('4각 ::::::::: ')
- const xVector = Big(nextLine.x2).minus(Big(nextLine.x1))
- const yVector = Big(nextLine.y2).minus(Big(nextLine.y1))
- const currentMidX = Big(x1).plus(Big(x2)).div(2)
- const currentMidY = Big(y1).plus(Big(y2)).div(2)
-
- const midLineEdge = {
- vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
- vertex2: {
- x: currentMidX.plus(currentSize.times(Math.sign(xVector))).toNumber(),
- y: currentMidY.plus(currentSize.times(Math.sign(yVector))).toNumber(),
- },
- }
-
- /** 현재 라인의 중심 지점에서 현재라인의 길이만큼 다음라인의 방향만큼 거리를 확인한다*/
- baseLines
- .filter((line) => line !== currentLine)
- .forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(midLineEdge, lineEdge)
- /** 현재라인의 길이만큼 거리가 모자라면 해당 길이 만큼을 현재라인의 길이로 판단하고 나머지 계산을 진행한다.*/
- if (intersection && !intersection.isIntersectionOutside) {
- const intersectionSize = Big(intersection.x)
- .minus(Big(currentMidX))
- .plus(Big(intersection.y).minus(Big(currentMidY)))
- .abs()
- if (intersectionSize.lt(currentSize)) {
- currentSize = intersectionSize
- }
- }
- })
-
- hipLength = currentSize.div(2).pow(2).plus(currentSize.div(2).pow(2)).sqrt()
- } else {
- if (currentAngle !== beforePrevAngle && currentAngle !== afterNextAngle && beforePrevLine !== afterNextLine) {
- const beforePrevX1 = beforePrevLine.x1,
- beforePrevY1 = beforePrevLine.y1
- const afterNextX2 = afterNextLine.x2,
- afterNextY2 = afterNextLine.y2
-
- /** beforePrevLine 과 afterNextLine 을 연결하는 사각형의 경우 6각으로 판단 */
- const connectBAPoint = { x1: afterNextX2, y1: afterNextY2, x2: beforePrevX1, y2: beforePrevY1 }
- const isConnect =
- baseLines.filter(
- (line) =>
- line.x1 === connectBAPoint.x1 && line.y1 === connectBAPoint.y1 && line.x2 === connectBAPoint.x2 && line.y2 === connectBAPoint.y2,
- ).length > 0
-
- /** 6각 */
- if (isConnect) {
- const checkScale = currentSize.pow(2).plus(currentSize.pow(2)).sqrt()
- const intersectBaseLine = []
- if (baseHipLines.filter((line) => line.x1 === x1 && line.y1 === y1).length === 0) {
- const prevEndPoint = {
- x: Big(x1).plus(Big(prevHipVector.x).times(checkScale)),
- y: Big(y1).plus(Big(prevHipVector.y).times(checkScale)),
- }
- baseLines
- .filter((line) => line !== currentLine && line !== prevLine && line !== nextLine)
- .forEach((line) => {
- const intersection = edgesIntersection(
- { vertex1: { x: x1, y: y1 }, vertex2: prevEndPoint },
- { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
- )
- if (intersection && !intersection.isIntersectionOutside) {
- intersectBaseLine.push({
- intersection,
- distance: Big(intersection.x)
- .minus(Big(x1))
- .pow(2)
- .plus(Big(intersection.y).minus(Big(y1)).pow(2))
- .sqrt(),
- })
- }
- })
- }
- if (baseHipLines.filter((line) => line.x1 === x2 && line.y1 === y2).length === 0) {
- const nextEndPoint = {
- x: Big(x2).plus(Big(nextHipVector.x).times(checkScale)),
- y: Big(y2).plus(Big(nextHipVector.y).times(checkScale)),
- }
- baseLines
- .filter((line) => line !== currentLine && line !== prevLine && line !== nextLine)
- .forEach((line) => {
- const intersection = edgesIntersection(
- { vertex1: { x: x2, y: y2 }, vertex2: nextEndPoint },
- { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
- )
- if (intersection && !intersection.isIntersectionOutside) {
- intersectBaseLine.push({
- intersection,
- distance: Big(intersection.x)
- .minus(Big(x2))
- .pow(2)
- .plus(Big(intersection.y).minus(Big(y2)).pow(2))
- .sqrt(),
- })
- }
- })
- }
- const intersection = intersectBaseLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectBaseLine[0])
- if (intersection) {
- hipLength = intersection.distance
- }
- } else {
- const rightAngleLine = baseLines
- .filter(
- (line) =>
- line !== currentLine &&
- line !== prevLine &&
- line !== nextLine &&
- (prevAngle === calculateAngle(line.startPoint, line.endPoint) || nextAngle === calculateAngle(line.startPoint, line.endPoint)),
- )
- .filter((line) => {
- const index = baseLines.indexOf(line)
- const prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
- const nextLine = baseLines[(index + 1) % baseLines.length]
- const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
- const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
- switch (prevAngle) {
- case 90:
- return nextAngle === -90
- case -90:
- return nextAngle === 90
- case 0:
- return nextAngle === 180
- case 180:
- return nextAngle === 0
- }
- })
-
- const oppositeCurrentLine = baseLines
- .filter((line) => {
- 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 index = baseLines.indexOf(line)
- const prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
- const nextLine = baseLines[(index + 1) % baseLines.length]
- const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
- const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
- switch (prevAngle) {
- case 90:
- return nextAngle === -90
- case -90:
- return nextAngle === 90
- case 0:
- return nextAngle === 180
- case 180:
- return nextAngle === 0
- }
- })
-
- let checkHipPoints
- if (baseHipLines.filter((line) => line.x1 === x1 && line.y1 === y1).length === 0) {
- checkHipPoints = [
- x1,
- y1,
- Big(x1).plus(Big(prevHipVector.x).times(hipLength)).round(2).toNumber(),
- Big(y1).plus(Big(prevHipVector.y).times(hipLength)).round(2).toNumber(),
- ]
- }
-
- if (baseHipLines.filter((line) => line.x1 === x2 && line.y1 === y2).length === 0) {
- checkHipPoints = [
- x2,
- y2,
- Big(x2).plus(Big(nextHipVector.x).times(hipLength)).round(2).toNumber(),
- Big(y2).plus(Big(nextHipVector.y).times(hipLength)).round(2).toNumber(),
- ]
- }
-
- if (checkHipPoints) {
- const intersectPoints = []
- rightAngleLine.forEach((line) => {
- const intersection = edgesIntersection(
- {
- vertex1: { x: checkHipPoints[0], y: checkHipPoints[1] },
- vertex2: { x: checkHipPoints[2], y: checkHipPoints[3] },
- },
- { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
- )
- if (intersection) {
- intersectPoints.push({
- intersection,
- distance: Big(intersection.x)
- .minus(Big(checkHipPoints[0]))
- .pow(2)
- .plus(Big(intersection.y).minus(Big(checkHipPoints[1])).pow(2))
- .sqrt()
- .toNumber(),
- })
- }
- })
-
- oppositeCurrentLine.forEach((line) => {
- const intersection = edgesIntersection(
- {
- vertex1: { x: checkHipPoints[0], y: checkHipPoints[1] },
- vertex2: { x: checkHipPoints[2], y: checkHipPoints[3] },
- },
- { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
- )
- if (intersection) {
- intersectPoints.push({
- intersection,
- distance: Big(intersection.x)
- .minus(Big(checkHipPoints[0]))
- .pow(2)
- .plus(Big(intersection.y).minus(Big(checkHipPoints[1])).pow(2))
- .sqrt()
- .toNumber(),
- })
- }
- })
-
- 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) {
- const prevEndPoint = {
- x: Big(x1).plus(Big(prevHipVector.x).times(hipLength)).round(1),
- 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) =>
- isPointOnLineNew({ x1: x1, y1: y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber() }, { x: line.x1, y: line.y1 }) ||
- isPointOnLineNew({ x1: x1, y1: y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber() }, { x: line.x2, y: line.y2 }),
- )
-
- if (overlapLine) {
- let size1, size2
- if (
- isPointOnLineNew({ x1: x1, y1: y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber() }, { x: overlapLine.x1, y: overlapLine.y1 })
- ) {
- size1 = Math.sqrt(Math.pow(x1 - overlapLine.x1, 2) + Math.pow(y1 - overlapLine.y1, 2))
- }
- if (
- isPointOnLineNew({ x1: x1, y1: y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber() }, { x: overlapLine.x2, y: overlapLine.y2 })
- ) {
- size2 = Math.sqrt(Math.pow(x1 - overlapLine.x2, 2) + Math.pow(y1 - overlapLine.y2, 2))
- }
- if (size1 && size2) {
- if (size1 < size2) {
- prevEndPoint.x = Big(overlapLine.x1)
- prevEndPoint.y = Big(overlapLine.y1)
- } else {
- prevEndPoint.x = Big(overlapLine.x2)
- prevEndPoint.y = Big(overlapLine.y2)
- }
- } else {
- if (size1) {
- prevEndPoint.x = Big(overlapLine.x1)
- prevEndPoint.y = Big(overlapLine.y1)
- }
- if (size2) {
- prevEndPoint.x = Big(overlapLine.x2)
- prevEndPoint.y = Big(overlapLine.y2)
- }
- }
- }
- const intersectRidgeLine = []
- baseRidgeLines.forEach((line) => {
- const intersection = edgesIntersection(
- { vertex1: { x: x1, y: y1 }, vertex2: prevEndPoint },
- { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
- )
- if (intersection && !intersection.isIntersectionOutside) {
- intersectRidgeLine.push({
- intersection,
- distance: Big(intersection.x)
- .minus(Big(x1))
- .pow(2)
- .plus(Big(intersection.y).minus(Big(y1)).pow(2))
- .sqrt(),
- })
- }
- })
- const intersectRidge = intersectRidgeLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectRidgeLine[0])
-
- if (intersectRidge) {
- prevEndPoint.x = Big(intersectRidge.intersection.x).round(1)
- prevEndPoint.y = Big(intersectRidge.intersection.y).round(1)
- }
-
- const xVector = Math.sign(Big(prevEndPoint.x).minus(Big(x1)).neg().toNumber())
- const yVector = Math.sign(Big(prevEndPoint.y).minus(Big(y1)).neg().toNumber())
- /** 지붕 선까지의 곂침에 따른 길이를 파악하기 위한 scale*/
- let scale = Big(currentLine.attributes.offset).pow(2).plus(Big(prevLine.attributes.offset).pow(2)).sqrt()
- scale = scale.eq(0) ? Big(1) : scale
-
- /** scale 만큼 추녀마루를 늘려서 겹치는 포인트를 확인한다. */
- const hipEdge = {
- vertex1: { x: Big(x1).plus(scale.times(xVector)).toNumber(), y: Big(y1).plus(scale.times(yVector)).toNumber() },
- vertex2: prevEndPoint,
- }
-
- let intersectPoints = []
- /** 외벽선에서 추녀 마루가 겹치는 경우에 대한 확인*/
- roof.lines.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(hipEdge, lineEdge)
- if (
- intersection &&
- isPointOnLineNew(line, { x: intersection.x, y: intersection.y }) &&
- Math.sign(prevEndPoint.x - x1) === Math.sign(prevEndPoint.x - intersection.x) &&
- Math.sign(prevEndPoint.y - y1) === Math.sign(prevEndPoint.y - intersection.y)
- ) {
- const intersectSize = prevEndPoint.x
- .minus(Big(intersection.x))
- .pow(2)
- .plus(prevEndPoint.y.minus(Big(intersection.y)).pow(2))
- .abs()
- .sqrt()
- .toNumber()
-
- intersectPoints.push({
- intersection,
- size: intersectSize,
- })
- }
- })
-
- intersectPoints = intersectPoints.reduce((prev, current) => {
- return prev.size < current.size ? prev : current
- }, intersectPoints[0])
-
- /** 겹치는 외벽선이 있을때 추녀마루를 외벽선 까지 늘려서 수정*/
- if (intersectPoints && intersectPoints.intersection) {
- prevHipLine = drawHipLine(
- [intersectPoints.intersection.x, intersectPoints.intersection.y, prevEndPoint.x.toNumber(), prevEndPoint.y.toNumber()],
- canvas,
- roof,
- textMode,
-
- prevDegree,
- currentDegree,
- )
- baseHipLines.push({ x1, y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber(), line: prevHipLine })
- }
- }
- if (baseHipLines.filter((line) => line.x1 === x2 && line.y1 === y2).length === 0) {
- const nextEndPoint = {
- x: Big(x2).plus(Big(nextHipVector.x).times(hipLength)).round(1),
- 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() }))
- const overlapLine = baseHipLines.find(
- (line) =>
- isPointOnLineNew({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber() }, { x: line.x1, y: line.y1 }) ||
- isPointOnLineNew({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber() }, { x: line.x2, y: line.y2 }),
- )
- if (overlapLine) {
- let size1, size2
- if (
- isPointOnLineNew({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber() }, { x: overlapLine.x1, y: overlapLine.y1 })
- ) {
- size1 = Math.sqrt(Math.pow(x2 - overlapLine.x1, 2) + Math.pow(y2 - overlapLine.y1, 2))
- }
- if (
- isPointOnLineNew({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber() }, { x: overlapLine.x2, y: overlapLine.y2 })
- ) {
- size2 = Math.sqrt(Math.pow(x2 - overlapLine.x2, 2) + Math.pow(y2 - overlapLine.y2, 2))
- }
- if (size1 && size2) {
- if (size1 < size2) {
- nextEndPoint.x = Big(overlapLine.x1)
- nextEndPoint.y = Big(overlapLine.y1)
- } else {
- nextEndPoint.x = Big(overlapLine.x2)
- nextEndPoint.y = Big(overlapLine.y2)
- }
- } else {
- if (size1) {
- nextEndPoint.x = Big(overlapLine.x1)
- nextEndPoint.y = Big(overlapLine.y1)
- }
- if (size2) {
- nextEndPoint.x = Big(overlapLine.x2)
- nextEndPoint.y = Big(overlapLine.y2)
- }
- }
- }
-
- const intersectRidgeLine = []
- baseRidgeLines.forEach((line) => {
- const intersection = edgesIntersection(
- { vertex1: { x: x2, y: y2 }, vertex2: nextEndPoint },
- { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
- )
-
- if (intersection && !intersection.isIntersectionOutside) {
- intersectRidgeLine.push({
- intersection,
- distance: Big(intersection.x)
- .minus(Big(x1))
- .pow(2)
- .plus(Big(intersection.y).minus(Big(y1)).pow(2))
- .sqrt(),
- })
- }
- })
- const intersectRidge = intersectRidgeLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectRidgeLine[0])
-
- if (intersectRidge) {
- nextEndPoint.x = Big(intersectRidge.intersection.x).round(1)
- nextEndPoint.y = Big(intersectRidge.intersection.y).round(1)
- }
-
- const xVector = Math.sign(Big(nextEndPoint.x).minus(Big(x2)).neg().toNumber())
- const yVector = Math.sign(Big(nextEndPoint.y).minus(Big(y2)).neg().toNumber())
- let scale = Big(currentLine.attributes.offset).pow(2).plus(Big(nextLine.attributes.offset).pow(2)).sqrt()
- scale = scale.eq(0) ? Big(1) : scale
-
- const hipEdge = {
- vertex1: { x: Big(x2).plus(scale.times(xVector)).toNumber(), y: Big(y2).plus(scale.times(yVector)).toNumber() },
- vertex2: nextEndPoint,
- }
-
- let intersectPoints = []
- roof.lines.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(hipEdge, lineEdge)
- if (
- intersection &&
- isPointOnLineNew(line, { x: intersection.x, y: intersection.y }) &&
- Math.sign(nextEndPoint.x - x2) === Math.sign(nextEndPoint.x - intersection.x) &&
- Math.sign(nextEndPoint.y - y2) === Math.sign(nextEndPoint.y - intersection.y)
- ) {
- const intersectSize = nextEndPoint.x
- .minus(Big(intersection.x))
- .pow(2)
- .plus(nextEndPoint.y.minus(Big(intersection.y)).pow(2))
- .abs()
- .sqrt()
- .toNumber()
-
- intersectPoints.push({
- intersection,
- size: intersectSize,
- })
- }
- })
-
- intersectPoints = intersectPoints.reduce((prev, current) => {
- return prev.size < current.size ? prev : current
- }, intersectPoints[0])
-
- if (intersectPoints && intersectPoints.intersection) {
- nextHipLine = drawHipLine(
- [intersectPoints.intersection.x, intersectPoints.intersection.y, nextEndPoint.x.toNumber(), nextEndPoint.y.toNumber()],
- canvas,
- roof,
- textMode,
-
- prevDegree,
- currentDegree,
- )
- baseHipLines.push({
- x1: x2,
- y1: y2,
- x2: nextEndPoint.x.toNumber(),
- y2: nextEndPoint.y.toNumber(),
- line: nextHipLine,
- })
- }
- }
-
- /** 두 선이 교차하면 해당 포인트까지로 선 조정*/
- if (prevHipLine !== undefined && nextHipLine !== undefined) {
- const prevEdge = {
- vertex1: { x: prevHipLine.x1, y: prevHipLine.y1 },
- vertex2: { x: prevHipLine.x2, y: prevHipLine.y2 },
- }
- const nextEdge = {
- vertex1: { x: nextHipLine.x1, y: nextHipLine.y1 },
- vertex2: { x: nextHipLine.x2, y: nextHipLine.y2 },
- }
- const intersection = edgesIntersection(prevEdge, nextEdge)
- if (intersection) {
- /** 포인트 조정*/
- baseHipLines
- .filter((line) => line.line === prevHipLine || line.line === nextHipLine)
- .forEach((line) => {
- line.x2 = intersection.x
- line.y2 = intersection.y
- line.line.set({ x2: intersection.x, y2: intersection.y })
- })
- prevHipLine.x2 = intersection.x
- prevHipLine.y2 = intersection.y
- const prevSize = reCalculateSize(prevHipLine)
-
- prevHipLine.attributes.planeSize = prevSize.planeSize
- prevHipLine.attributes.actualSize = prevSize.actualSize
- prevHipLine.fire('modified')
-
- nextHipLine.x2 = intersection.x
- nextHipLine.y2 = intersection.y
- const nextSize = reCalculateSize(nextHipLine)
-
- nextHipLine.attributes.planeSize = nextSize.planeSize
- nextHipLine.attributes.actualSize = nextSize.actualSize
- nextHipLine.fire('modified')
- canvas.renderAll()
- }
- }
-
- /** 두 추녀마루가 한점에서 만나는 경우 해당 점을 기점으로 마루를 작성한다.*/
- if (
- prevHipLine !== undefined &&
- nextHipLine !== undefined &&
- Big(prevHipLine.x2).minus(Big(nextHipLine.x2)).abs().lte(1) &&
- Big(prevHipLine.y2).minus(Big(nextHipLine.y2)).abs().lte(1)
- ) {
- const startPoint = { x: prevHipLine.x2, y: prevHipLine.y2 }
- let ridgeSize = 0
-
- const currentMidX = Big(currentLine.x2).plus(Big(currentLine.x1)).div(2)
- const currentMidY = Big(currentLine.y2).plus(Big(currentLine.y1)).div(2)
-
- 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 (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 {
- 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 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(oppositeRoofPoint.y).minus(Big(startPoint.y)).abs().pow(2))
- .minus(width)
- .sqrt()
- }
- }
- } else {
- 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 (currentAngle === oppositeAngle) {
- const oppositeEdge = {
- vertex1: { x: oppositeLine.x1, y: oppositeLine.y1 },
- vertex2: { x: oppositeLine.x2, y: oppositeLine.y2 },
- }
- const intersection = edgesIntersection(oppositeEdge, checkEdge)
- if (intersection) {
- 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 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
- }
- })
- .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(prev.intersection.y).minus(Big(startPoint.y)).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)
- .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
-
- /** 이전, 다음 라인중 길이가 짧은 길이*/
- 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)))
- .toNumber(),
- Big(startPoint.y)
- .minus(ridgeSize.times(Math.sign(yVector)))
- .toNumber(),
- ]
-
- const oppositeHipPoints = []
- const ridgeEdge = { vertex1: { x: points[0], y: points[1] }, vertex2: { x: points[2], y: points[3] } }
- if (prevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
- let hipVector = getHalfAngleVector(prevLine, beforePrevLine.line)
- /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
- const checkPoint = {
- x: Big(prevLine.x1).plus(Big(hipVector.x).times(10)),
- y: Big(prevLine.y1).plus(Big(hipVector.y).times(10)),
- }
- if (!checkWallPolygon.inPolygon(checkPoint)) {
- hipVector = { x: -hipVector.x, y: -hipVector.y }
- }
-
- const hipEdge = {
- vertex1: { x: prevLine.x1, y: prevLine.y1 },
- vertex2: {
- x: Big(prevLine.x1).plus(Big(hipVector.x).times(prevLine.attributes.planeSize)).toNumber(),
- y: Big(prevLine.y1).plus(Big(hipVector.y).times(prevLine.attributes.planeSize)).toNumber(),
- },
- }
- const intersection = edgesIntersection(ridgeEdge, hipEdge)
- if (intersection) {
- const size = Big(points[0] - intersection.x)
- .abs()
- .pow(2)
- .plus(
- Big(points[1] - intersection.y)
- .abs()
- .pow(2),
- )
- .sqrt()
- .toNumber()
- oppositeHipPoints.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 hipVector = getHalfAngleVector(nextLine, afterNextLine.line)
- /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
- const checkPoint = {
- x: Big(nextLine.x1).plus(Big(hipVector.x).times(10)),
- y: Big(nextLine.y1).plus(Big(hipVector.y).times(10)),
- }
- if (!checkWallPolygon.inPolygon(checkPoint)) {
- hipVector = { x: -hipVector.x, y: -hipVector.y }
- }
-
- const hipEdge = {
- vertex1: { x: nextLine.x2, y: nextLine.y2 },
- vertex2: {
- x: Big(nextLine.x2).plus(Big(hipVector.x).times(nextLine.attributes.planeSize)).toNumber(),
- y: Big(nextLine.y2).plus(Big(hipVector.y).times(nextLine.attributes.planeSize)).toNumber(),
- },
- }
- const intersection = edgesIntersection(ridgeEdge, hipEdge)
- if (intersection) {
- const size = Big(points[0] - intersection.x)
- .abs()
- .pow(2)
- .plus(
- Big(points[1] - intersection.y)
- .abs()
- .pow(2),
- )
- .sqrt()
- .toNumber()
- oppositeHipPoints.push({ x: intersection.x, y: intersection.y, size })
- }
- }
- if (oppositeHipPoints.length > 0) {
- const oppositeHipPoint = oppositeHipPoints.sort((a, b) => a.size - b.size)[0]
- points[2] = oppositeHipPoint.x
- points[3] = oppositeHipPoint.y
- }
-
- /** 동일 라인이 있는지 확인. */
- if (
- baseRidgeLines.filter((line) => {
- const ridgeMinX = Math.min(points[0], points[2])
- const ridgeMaxX = Math.max(points[0], points[2])
- const ridgeMinY = Math.min(points[1], points[3])
- const ridgeMaxY = Math.max(points[1], points[3])
- 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)
-
- return ridgeMinX === lineMinX && ridgeMaxX === lineMaxX && ridgeMinY === lineMinY && ridgeMaxY === lineMaxY
- }).length > 0
- ) {
- return
- }
-
- const ridgeLine = drawRidgeLine(points, canvas, roof, textMode)
- if (
- oppositeHipPoints.length === 0 &&
- (gableType.includes(beforePrevLine.line.attributes.type) || gableType.includes(afterNextLine.line.attributes.type))
- ) {
- baseGableRidgeLines.push(ridgeLine)
- } else {
- baseRidgeLines.push(ridgeLine)
- }
- baseRidgeCount = baseRidgeCount + 1
-
- /** 포인트 조정*/
- baseHipLines
- .filter((line) => line.line === prevHipLine || line.line === nextHipLine)
- .forEach((line) => {
- line.x2 = points[0]
- line.y2 = points[1]
- line.line.set({ x2: points[0], y2: points[1] })
- // line.line.fire('modified')
- })
- prevHipLine.x2 = points[0]
- prevHipLine.y2 = points[1]
- const prevSize = reCalculateSize(prevHipLine)
- prevHipLine.attributes.planeSize = prevSize.planeSize
- prevHipLine.attributes.actualSize = prevSize.actualSize
- prevHipLine.fire('modified')
- nextHipLine.x2 = points[0]
- nextHipLine.y2 = points[1]
- const nextSize = reCalculateSize(nextHipLine)
- nextHipLine.attributes.planeSize = nextSize.planeSize
- nextHipLine.attributes.actualSize = nextSize.actualSize
- nextHipLine.fire('modified')
- canvas.renderAll()
-
- if (
- oppositeHipPoints.length === 0 &&
- (gableType.includes(beforePrevLine.line.attributes.type) || gableType.includes(afterNextLine.line.attributes.type))
- ) {
- const oppositeLine = gableType.includes(beforePrevLine.line.attributes.type) ? beforePrevLine.line : afterNextLine.line
- 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 firstHipLine = gableVector === prevVector ? prevHipLine : nextHipLine
- const firstDegree =
- gableVector === Math.sign(ridgeLine.x1 - prevLine.x1)
- ? getDegreeByChon(prevLine.attributes.pitch)
- : getDegreeByChon(nextLine.attributes.pitch)
-
- const oppositeRoofPoints = [
- ridgeLine.x2,
- ridgeLine.y2,
- ridgeLine.x1 === firstHipLine.x1 ? firstHipLine.x2 : firstHipLine.x1,
- ridgeLine.y2,
- ]
- const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, firstDegree, firstDegree)
- baseHipLines.push({
- x1: oppositeRoofLine.x1,
- y1: oppositeRoofLine.y1,
- x2: oppositeRoofLine.x2,
- y2: oppositeRoofLine.y2,
- line: oppositeRoofLine,
- })
-
- const connectRoofPoints = [oppositeRoofLine.x2, oppositeRoofLine.y2]
- if (ridgeLine.x1 === firstHipLine.x1) {
- connectRoofPoints.push(firstHipLine.x2, firstHipLine.y2)
- } else {
- connectRoofPoints.push(firstHipLine.x1, firstHipLine.y1)
- }
- const connectRoofLine = drawRoofLine(connectRoofPoints, canvas, roof, textMode)
- baseHipLines.push({
- x1: connectRoofLine.x1,
- y1: connectRoofLine.y1,
- x2: connectRoofLine.x2,
- y2: connectRoofLine.y2,
- line: connectRoofLine,
- })
-
- /** 다른 방향의 추녀마루 */
- const secondHipLine = gableVector === prevVector ? nextHipLine : prevHipLine
- const secondDegree =
- gableVector === Math.sign(ridgeLine.x1 - prevLine.x1)
- ? getDegreeByChon(nextLine.attributes.pitch)
- : getDegreeByChon(prevLine.attributes.pitch)
-
- const intersections = []
- const checkEdge = {
- vertex1: { x: ridgeLine.x2, y: ridgeLine.y2 },
- vertex2: { x: ridgeLine.x1 === secondHipLine.x1 ? secondHipLine.x2 : secondHipLine.x1, y: ridgeLine.y2 },
- }
-
- baseGableRidgeLines
- .filter((ridge) => ridge !== ridgeLine)
- .forEach((ridge) => {
- const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }
- const intersection = edgesIntersection(ridgeEdge, checkEdge)
- if (intersection && !intersections.includes(intersection)) {
- const size = Big(intersection.x)
- .minus(Big(ridgeLine.x2))
- .pow(2)
- .plus(Big(intersection.y).minus(Big(ridgeLine.y2)).pow(2))
- .sqrt()
- .toNumber()
- intersections.push({ intersection, size, ridge })
- }
- })
- intersections.sort((a, b) => a.size - b.size)
-
- if (intersections.length > 0) {
- const intersection = intersections[0].intersection
- const intersectRidge = intersections[0].ridge
- const oppositeRoofPoints = [ridgeLine.x2, ridgeLine.y2, intersection.x, intersection.y]
- const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, secondDegree, secondDegree)
- baseHipLines.push({
- x1: oppositeLine.x1,
- y1: oppositeLine.y1,
- x2: oppositeLine.x2,
- y2: oppositeLine.y2,
- line: oppositeRoofLine,
- })
-
- const ridgeVector = Math.sign(ridgeLine.y1 - ridgeLine.y2)
- const connectRoofPoints = [oppositeRoofLine.x2, oppositeRoofLine.y2]
- if (ridgeVector === Math.sign(oppositeRoofLine.y1 - intersectRidge.y2)) {
- connectRoofPoints.push(intersectRidge.x2, intersectRidge.y2)
- } else {
- connectRoofPoints.push(intersectRidge.x1, intersectRidge.y1)
- }
-
- const connectRoofLine = drawRoofLine(connectRoofPoints, canvas, roof, textMode)
- baseHipLines.push({
- x1: connectRoofLine.x1,
- y1: connectRoofLine.y1,
- x2: connectRoofLine.x2,
- y2: connectRoofLine.y2,
- line: connectRoofLine,
- })
- }
- } 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 firstHipLine = gableVector === prevVector ? prevHipLine : nextHipLine
- const firstDegree =
- gableVector === Math.sign(ridgeLine.y1 - prevLine.y1)
- ? getDegreeByChon(prevLine.attributes.pitch)
- : getDegreeByChon(nextLine.attributes.pitch)
-
- const oppositeRoofPoints = [
- ridgeLine.x2,
- ridgeLine.y2,
- ridgeLine.x2,
- ridgeLine.y1 === firstHipLine.y1 ? firstHipLine.y2 : firstHipLine.y1,
- ]
- const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, firstDegree, firstDegree)
- baseHipLines.push({
- x1: oppositeRoofLine.x1,
- y1: oppositeRoofLine.y1,
- x2: oppositeRoofLine.x2,
- y2: oppositeRoofLine.y2,
- line: oppositeRoofLine,
- })
-
- const connectRoofPoints = [oppositeRoofLine.x2, oppositeRoofLine.y2]
- if (ridgeLine.y1 === firstHipLine.y1) {
- connectRoofPoints.push(firstHipLine.x2, firstHipLine.y2)
- } else {
- connectRoofPoints.push(firstHipLine.x1, firstHipLine.y1)
- }
-
- const connectRoofLine = drawRoofLine(connectRoofPoints, canvas, roof, textMode)
- baseHipLines.push({
- x1: connectRoofLine.x1,
- y1: connectRoofLine.y1,
- x2: connectRoofLine.x2,
- y2: connectRoofLine.y2,
- line: connectRoofLine,
- })
-
- /** 다른 방향의 추녀마루 */
- const secondHipLine = gableVector === prevVector ? nextHipLine : prevHipLine
- const secondDegree =
- gableVector === Math.sign(ridgeLine.y1 - prevLine.y1)
- ? getDegreeByChon(nextLine.attributes.pitch)
- : getDegreeByChon(prevLine.attributes.pitch)
-
- const intersections = []
- const checkEdge = {
- vertex1: { x: ridgeLine.x2, y: ridgeLine.y2 },
- vertex2: { x: ridgeLine.x2, y: ridgeLine.y1 === secondHipLine.y1 ? secondHipLine.y2 : secondHipLine.y1 },
- }
- baseGableRidgeLines
- .filter((ridge) => ridge !== ridgeLine)
- .forEach((ridge) => {
- const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }
- const intersection = edgesIntersection(ridgeEdge, checkEdge)
- if (intersection && !intersections.includes(intersection)) {
- const size = Big(intersection.x)
- .minus(Big(ridgeLine.x2))
- .pow(2)
- .plus(Big(intersection.y).minus(Big(ridgeLine.y2)).pow(2))
- .sqrt()
- .toNumber()
- intersections.push({ intersection, size, ridge })
- }
- })
- intersections.sort((a, b) => a.size - b.size)
- if (intersections.length > 0) {
- const intersection = intersections[0].intersection
- const intersectRidge = intersections[0].ridge
- const oppositeRoofPoints = [ridgeLine.x2, ridgeLine.y2, intersection.x, intersection.y]
- const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, secondDegree, secondDegree)
- baseHipLines.push({
- x1: oppositeLine.x1,
- y1: oppositeLine.y1,
- x2: oppositeLine.x2,
- y2: oppositeLine.y2,
- line: oppositeRoofLine,
- })
-
- const ridgeVector = Math.sign(ridgeLine.x1 - ridgeLine.x2)
- const connectRoofPoints = [oppositeRoofLine.x2, oppositeRoofLine.y2]
- if (ridgeVector === Math.sign(oppositeRoofLine.x1 - intersectRidge.x2)) {
- connectRoofPoints.push(intersectRidge.x2, intersectRidge.y2)
- } else {
- connectRoofPoints.push(intersectRidge.x1, intersectRidge.y1)
- }
-
- const connectRoofLine = drawRoofLine(connectRoofPoints, canvas, roof, textMode)
- baseHipLines.push({
- x1: connectRoofLine.x1,
- y1: connectRoofLine.y1,
- x2: connectRoofLine.x2,
- y2: connectRoofLine.y2,
- line: connectRoofLine,
- })
- }
- }
- }
- }
- }
- })
-
- /** 중복제거 */
- baseRidgeLines.forEach((ridge) => {
- baseRidgeLines
- .filter((ridge2) => ridge !== ridge2)
- .forEach((ridge2) => {
- let overlap = segmentsOverlap(ridge, ridge2)
- if (overlap) {
- roof.canvas.remove(ridge)
- roof.canvas.remove(ridge2)
- baseRidgeLines = baseRidgeLines.filter((r) => r !== ridge && r !== ridge2)
-
- baseRidgeCount = baseRidgeCount - 2
-
- let x1 = Math.min(ridge.x1, ridge2.x1, ridge.x2, ridge2.x2)
- let x2 = Math.max(ridge.x1, ridge2.x1, ridge.x2, ridge2.x2)
- let y1 = Math.min(ridge.y1, ridge2.y1, ridge.y2, ridge2.y2)
- let y2 = Math.max(ridge.y1, ridge2.y1, ridge.y2, ridge2.y2)
-
- const newRidge = drawRidgeLine([x1, y1, x2, y2], canvas, roof, textMode)
- baseRidgeLines.push(newRidge)
- baseRidgeCount = baseRidgeCount + 1
- }
- })
- })
-
- /** ㄴ 모양 처마에 추녀마루를 그린다. */
- drawEavesSecondLines.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 prevDegree = getDegreeByChon(prevLine.attributes.pitch)
- /** 다음 라인의 경사 */
- const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
-
- /** 이전, 다음라인의 사잇각의 vector를 구한다. */
- let prevVector = getHalfAngleVector(prevLine, currentLine)
- let nextVector = getHalfAngleVector(currentLine, nextLine)
-
- let prevHipVector = { x: prevVector.x, y: prevVector.y }
- let nextHipVector = { x: nextVector.x, y: nextVector.y }
-
- /** 각 라인의 흐름 방향을 확인한다. */
- const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint)
-
- /** 현재 라인의 길이 추녀마루 길이의 기준이 된다. */
- let hipLength = Big(x2)
- .minus(Big(x1))
- .plus(Big(y2).minus(Big(y1)))
- .abs()
-
- /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
- const prevCheckPoint = {
- x: Big(x1).plus(Big(prevHipVector.x).times(10)),
- y: Big(y1).plus(Big(prevHipVector.y).times(10)),
- }
- if (!checkWallPolygon.inPolygon(prevCheckPoint)) {
- prevHipVector = { x: -prevHipVector.x, y: -prevHipVector.y }
- }
-
- /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
- const nextCheckPoint = {
- x: Big(x2).plus(Big(nextHipVector.x).times(10)),
- y: Big(y2).plus(Big(nextHipVector.y).times(10)),
- }
- if (!checkWallPolygon.inPolygon(nextCheckPoint)) {
- nextHipVector = { x: -nextHipVector.x, y: -nextHipVector.y }
- }
-
- let prevHipLine, nextHipLine
- /** 이전라인과의 연결지점에 추녀마루를 그린다. */
- 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),
- }
-
- const prevEndEdge = { vertex1: { x: x1, y: y1 }, vertex2: prevEndPoint }
-
- const intersectBaseLine = []
- baseLines
- .filter((line) => line !== currentLine && line !== prevLine && line !== nextLine)
- .filter((line) => {
- if (currentAngle === 0 || currentAngle === 180) {
- return Math.sign(line.y1 - y1) === nextHipVector.y || Math.sign(line.y2 - y1) === nextHipVector.y
- } else {
- 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 && Math.sign(intersection.x - x1) === nextHipVector.x && Math.sign(intersection.y - y1) === nextHipVector.y) {
- const size = Big(intersection.x - x1)
- .abs()
- .pow(2)
- .plus(
- Big(intersection.y - y1)
- .pow(2)
- .abs(),
- )
- .sqrt()
- if (size.gt(0)) {
- intersectBaseLine.push({
- intersection,
- size,
- })
- }
- }
- })
-
- const intersectBase = intersectBaseLine.reduce((prev, current) => {
- return prev.size < current.size ? prev : current
- }, intersectBaseLine[0])
-
- if (intersectBase) {
- prevEndPoint = {
- x: Big(x1)
- .plus(Big(nextHipVector.x).times(intersectBase.size.div(2)))
- .round(2),
- y: Big(y1)
- .plus(Big(nextHipVector.y).times(intersectBase.size.div(2)))
- .round(2),
- }
- }
-
- const intersectRidgeLine = []
- baseRidgeLines.forEach((line) => {
- const intersection = edgesIntersection(
- { vertex1: { x: x1, y: y1 }, vertex2: prevEndPoint },
- { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
- )
- if (intersection && !intersection.isIntersectionOutside) {
- intersectRidgeLine.push({
- intersection,
- distance: Big(intersection.x)
- .minus(Big(x1))
- .abs()
- .pow(2)
- .plus(Big(intersection.y).minus(Big(y1)).pow(2).abs())
- .sqrt(),
- })
- }
- })
-
- const intersectRidge = intersectRidgeLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectRidgeLine[0])
-
- if (intersectRidge) {
- prevEndPoint.x = Big(intersectRidge.intersection.x).round(1)
- prevEndPoint.y = Big(intersectRidge.intersection.y).round(1)
- }
-
- const xVector = Math.sign(Big(prevEndPoint.x).minus(Big(x1)).neg().toNumber())
- const yVector = Math.sign(Big(prevEndPoint.y).minus(Big(y1)).neg().toNumber())
- /** 지붕 선까지의 곂침에 따른 길이를 파악하기 위한 scale*/
- let scale = Big(currentLine.attributes.offset).pow(2).plus(Big(prevLine.attributes.offset).pow(2)).sqrt()
- scale = scale.eq(0) ? Big(1) : scale
-
- /** scale 만큼 추녀마루를 늘려서 겹치는 포인트를 확인한다. */
- const hipEdge = {
- vertex1: { x: Big(x1).plus(scale.times(xVector)).toNumber(), y: Big(y1).plus(scale.times(yVector)).toNumber() },
- vertex2: prevEndPoint,
- }
-
- let intersectPoints = []
- /** 외벽선에서 추녀 마루가 겹치는 경우에 대한 확인*/
- roof.lines.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(hipEdge, lineEdge)
- if (
- intersection &&
- !intersection.isIntersectionOutside &&
- Math.sign(prevEndPoint.x - x1) === Math.sign(prevEndPoint.x - intersection.x) &&
- Math.sign(prevEndPoint.y - y1) === Math.sign(prevEndPoint.y - intersection.y)
- ) {
- const intersectSize = prevEndPoint.x
- .minus(Big(intersection.x))
- .abs()
- .pow(2)
- .plus(prevEndPoint.y.minus(Big(intersection.y)).pow(2).abs())
- .sqrt()
- .toNumber()
-
- intersectPoints.push({
- intersection,
- size: intersectSize,
- })
- }
- })
-
- intersectPoints = intersectPoints.reduce((prev, current) => {
- return prev.size < current.size ? prev : current
- }, intersectPoints[0])
-
- /** 겹치는 외벽선이 있을때 추녀마루를 외벽선 까지 늘려서 수정*/
- if (intersectPoints && intersectPoints.intersection) {
- prevHipLine = drawHipLine(
- [intersectPoints.intersection.x, intersectPoints.intersection.y, prevEndPoint.x.toNumber(), prevEndPoint.y.toNumber()],
- canvas,
- roof,
- textMode,
-
- prevDegree,
- currentDegree,
- )
- baseHipLines.push({ x1, y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber(), line: prevHipLine })
- }
- }
- /** 다음라인과의 연결지점에 추녀마루를 그린다. */
- 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),
- }
-
- const nextEndEdge = {
- vertex1: { x: x2, y: y2 },
- vertex2: nextEndPoint,
- }
-
- const intersectBaseLine = []
- baseLines
- .filter((line) => line !== currentLine && line !== prevLine && line !== nextLine)
- .filter((line) => {
- if (currentAngle === 0 || currentAngle === 180) {
- return Math.sign(line.y1 - y1) === nextHipVector.y || Math.sign(line.y2 - y1) === nextHipVector.y
- } else {
- 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 && Math.sign(intersection.x - x2) === nextHipVector.x && Math.sign(intersection.y - y2) === nextHipVector.y) {
- const size = Big(intersection.x - x2)
- .abs()
- .pow(2)
- .plus(
- Big(intersection.y - y2)
- .abs()
- .pow(2),
- )
- .sqrt()
- if (size.gt(0)) {
- intersectBaseLine.push({
- intersection,
- size,
- })
- }
- }
- })
-
- const intersectBase = intersectBaseLine.reduce((prev, current) => {
- return prev.size.lt(current.size) ? prev : current
- }, intersectBaseLine[0])
-
- if (intersectBase) {
- const size = Big(getAdjacent(intersectBase.size))
- nextEndPoint = {
- x: Big(x2)
- .plus(Big(nextHipVector.x).times(size.div(2)))
- .round(2),
- y: Big(y2)
- .plus(Big(nextHipVector.y).times(size.div(2)))
- .round(2),
- }
- }
-
- const intersectRidgeLine = []
- baseRidgeLines.forEach((line) => {
- const intersection = edgesIntersection(
- { vertex1: { x: x2, y: y2 }, vertex2: nextEndPoint },
- { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
- )
- 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)
- .minus(Big(x1))
- .pow(2)
- .plus(Big(intersection.y).minus(Big(y1)).pow(2))
- .sqrt(),
- })
- }
- })
-
- const intersectRidge = intersectRidgeLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectRidgeLine[0])
-
- if (intersectRidge) {
- nextEndPoint.x = Big(intersectRidge.intersection.x).round(1)
- nextEndPoint.y = Big(intersectRidge.intersection.y).round(1)
- }
-
- const xVector = Math.sign(Big(nextEndPoint.x).minus(Big(x2)).neg().toNumber())
- const yVector = Math.sign(Big(nextEndPoint.y).minus(Big(y2)).neg().toNumber())
- let scale = Big(currentLine.attributes.offset).pow(2).plus(Big(nextLine.attributes.offset).pow(2)).sqrt()
- scale = scale.eq(0) ? Big(1) : scale
-
- const hipEdge = {
- vertex1: { x: Big(x2).plus(scale.times(xVector)).toNumber(), y: Big(y2).plus(scale.times(yVector)).toNumber() },
- vertex2: nextEndPoint,
- }
-
- let intersectPoints = []
- roof.lines.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(hipEdge, lineEdge)
- if (
- intersection &&
- !intersection.isIntersectionOutside &&
- Math.sign(nextEndPoint.x - x2) === Math.sign(nextEndPoint.x - intersection.x) &&
- Math.sign(nextEndPoint.y - y2) === Math.sign(nextEndPoint.y - intersection.y)
- ) {
- const intersectSize = nextEndPoint.x
- .minus(Big(intersection.x))
- .pow(2)
- .plus(nextEndPoint.y.minus(Big(intersection.y)).pow(2))
- .abs()
- .sqrt()
- .toNumber()
-
- intersectPoints.push({
- intersection,
- size: intersectSize,
- })
- }
- })
-
- intersectPoints = intersectPoints.reduce((prev, current) => {
- return prev.size < current.size ? prev : current
- }, intersectPoints[0])
-
- if (intersectPoints && intersectPoints.intersection) {
- nextHipLine = drawHipLine(
- [intersectPoints.intersection.x, intersectPoints.intersection.y, nextEndPoint.x.toNumber(), nextEndPoint.y.toNumber()],
- canvas,
- roof,
- textMode,
-
- prevDegree,
- currentDegree,
- )
- baseHipLines.push({
- x1: x2,
- y1: y2,
- x2: nextEndPoint.x.toNumber(),
- y2: nextEndPoint.y.toNumber(),
- line: nextHipLine,
- })
- }
- }
- })
-
- /** baseHipLine 이 ridge에 붙지 않은 경우 확인 */
- baseHipLines.forEach((hipLine) => {
- const ridgeCount = baseRidgeLines.filter(
- (ridgeLine) => (hipLine.x2 === ridgeLine.x1 && hipLine.y2 === ridgeLine.y1) || (hipLine.x2 === ridgeLine.x2 && hipLine.y2 === ridgeLine.y2),
- ).length
- if (ridgeCount === 0) {
- const hipXVector = Big(hipLine.x2).minus(hipLine.x1)
- const hipYVector = Big(hipLine.y2).minus(hipLine.y1)
- const hipSize = hipXVector.abs().pow(2).plus(hipYVector.abs().pow(2)).sqrt()
-
- const intersectRidgePoints = []
-
- const hipLineEdge = { vertex1: { x: hipLine.x1, y: hipLine.y1 }, vertex2: { x: hipLine.x2, y: hipLine.y2 } }
- baseRidgeLines.forEach((ridgeLine) => {
- const ridgeLineEdge = {
- vertex1: { x: ridgeLine.x1, y: ridgeLine.y1 },
- vertex2: { x: ridgeLine.x2, y: ridgeLine.y2 },
- }
- const intersection = edgesIntersection(hipLineEdge, ridgeLineEdge)
-
- if (intersection) {
- const intersectXVector = Big(intersection.x).minus(Big(hipLine.x1))
- const intersectYVector = Big(intersection.y).minus(Big(hipLine.y1))
- const intersectSize = intersectXVector.pow(2).plus(intersectYVector.pow(2)).sqrt()
-
- if (!intersection.isIntersectionOutside) {
- intersectRidgePoints.push({
- x: intersection.x,
- y: intersection.y,
- size: intersectSize,
- })
- } else if (
- ((intersection.x === ridgeLine.x1 && intersection.y === ridgeLine.y1) ||
- (intersection.x === ridgeLine.x2 && intersection.y === ridgeLine.y2)) &&
- Math.sign(hipXVector.toNumber()) === Math.sign(intersectXVector.toNumber()) &&
- Math.sign(hipYVector.toNumber()) === Math.sign(intersectYVector.toNumber()) &&
- intersectSize.gt(0) &&
- intersectSize.lt(hipSize)
- ) {
- intersectRidgePoints.push({
- x: intersection.x,
- y: intersection.y,
- size: intersectSize,
- })
- }
- }
- })
- intersectRidgePoints.sort((prev, current) => prev.size.minus(current.size).toNumber())
- if (intersectRidgePoints.length > 0) {
- hipLine.x2 = intersectRidgePoints[0].x
- hipLine.y2 = intersectRidgePoints[0].y
- hipLine.line.set({ x2: intersectRidgePoints[0].x, y2: intersectRidgePoints[0].y })
- const hipSize = reCalculateSize(hipLine.line)
- hipLine.line.attributes.planeSize = hipSize.planeSize
- hipLine.line.attributes.actualSize = hipSize.actualSize
- hipLine.line.fire('modified')
- }
- }
- })
-
- /** 지붕선에 맞닫지 않은 부분을 확인하여 처리 한다.*/
- /** 1. 그려진 마루 중 추녀마루가 부재하는 경우를 판단. 부재는 연결된 라인이 홀수인 경우로 판단한다.*/
- let unFinishedRidge = []
- baseRidgeLines.forEach((current) => {
- let checkPoint = [
- { x: current.x1, y: current.y1, line: current, cnt: 0, onRoofLine: false },
- { x: current.x2, y: current.y2, line: current, cnt: 0, onRoofLine: false },
- ]
- baseHipLines.forEach((line) => {
- if ((line.x1 === current.x1 && line.y1 === current.y1) || (line.x2 === current.x1 && line.y2 === current.y1)) {
- checkPoint[0].cnt = checkPoint[0].cnt + 1
- }
- if ((line.x1 === current.x2 && line.y1 === current.y2) || (line.x2 === current.x2 && line.y2 === current.y2)) {
- checkPoint[1].cnt = checkPoint[1].cnt + 1
- }
- })
-
- /** 마루의 포인트가 지붕선 위에 있는경우는 제외 (케라바 등)*/
- roof.lines.forEach((line) => {
- if (
- line.x1 === line.x2 &&
- checkPoint[0].x === line.x1 &&
- ((line.y1 <= checkPoint[0].y && line.y2 >= checkPoint[0].y) || (line.y1 >= checkPoint[0].y && line.y2 <= checkPoint[0].y))
- ) {
- checkPoint[0].onRoofLine = true
- }
- if (
- line.y1 === line.y2 &&
- checkPoint[0].y === line.y1 &&
- ((line.x1 <= checkPoint[0].x && line.x2 >= checkPoint[0].x) || (line.x1 >= checkPoint[0].x && line.x2 <= checkPoint[0].x))
- ) {
- checkPoint[0].onRoofLine = true
- }
- if (
- line.x1 === line.x2 &&
- checkPoint[1].x === line.x1 &&
- ((line.y1 <= checkPoint[1].y && line.y2 >= checkPoint[1].y) || (line.y1 >= checkPoint[1].y && line.y2 <= checkPoint[1].y))
- ) {
- checkPoint[1].onRoofLine = true
- }
- if (
- line.y1 === line.y2 &&
- checkPoint[1].y === line.y1 &&
- ((line.x1 <= checkPoint[1].x && line.x2 >= checkPoint[1].x) || (line.x1 >= checkPoint[1].x && line.x2 <= checkPoint[1].x))
- ) {
- checkPoint[1].onRoofLine = true
- }
- })
- if ((checkPoint[0].cnt === 0 || checkPoint[0].cnt % 2 !== 0) && !checkPoint[0].onRoofLine) {
- unFinishedRidge.push(checkPoint[0])
- }
- if ((checkPoint[1].cnt === 0 || checkPoint[1].cnt % 2 !== 0) && !checkPoint[1].onRoofLine) {
- unFinishedRidge.push(checkPoint[1])
- }
- })
-
- /** 2. 그려진 추녀마루 중 완성되지 않은 것을 찾는다. 완성되지 않았다는 것은 연결된 포인트가 홀수인 경우로 판단한다.*/
- const findUnFinishedPoints = (baseHipLines) => {
- let unFinishedPoint = []
- baseHipLines.forEach((current) => {
- let checkPoint = [
- { x: current.x1, y: current.y1, checked: true, line: current.line },
- { x: current.x2, y: current.y2, checked: true, line: current.line },
- ]
- baseLines.forEach((line) => {
- if ((line.x1 === current.x1 && line.y1 === current.y1) || (line.x2 === current.x1 && line.y2 === current.y1)) {
- checkPoint[0].checked = false
- }
- if ((line.x1 === current.x2 && line.y1 === current.y2) || (line.x2 === current.x2 && line.y2 === current.y2)) {
- checkPoint[1].checked = false
- }
- })
-
- const samePoints = []
- checkPoint
- .filter((point) => point.checked)
- .forEach((point) => {
- baseHipLines.forEach((line) => {
- if (line.x1 === point.x && line.y1 === point.y) {
- samePoints.push({ x: point.x, y: point.y, line: line })
- }
- if (line.x2 === point.x && line.y2 === point.y) {
- samePoints.push({ x: point.x, y: point.y, line: line })
- }
- })
- })
- if (samePoints.length > 0 && samePoints.length % 2 !== 0) {
- unFinishedPoint.push(samePoints[0])
- }
- })
- return unFinishedPoint
- }
-
- let unFinishedPoint = findUnFinishedPoints(baseHipLines)
-
- /**3. 라인이 부재인 마루의 모자란 라인을 찾는다. 라인은 그려진 추녀마루 중에 완성되지 않은 추녀마루와 확인한다.*/
- /**3-1 라인을 그릴때 각도가 필요하기 때문에 각도를 구한다. 각도는 전체 지부의 각도가 같다면 하나로 처리 */
- let degreeAllLine = []
- baseLines
- .filter((line) => eavesType.includes(line.attributes.type))
- .forEach((line) => {
- const pitch = line.attributes.pitch
- degreeAllLine.push(getDegreeByChon(pitch))
- })
-
- let currentDegree, prevDegree
- degreeAllLine = [...new Set(degreeAllLine)]
- currentDegree = degreeAllLine[0]
- if (degreeAllLine.length === 1) {
- prevDegree = currentDegree
- } else {
- prevDegree = degreeAllLine[1]
- }
-
- /** 라인이 부재한 마루에 라인을 찾아 그린다.*/
- unFinishedRidge.forEach((current) => {
- let checkPoints = []
-
- unFinishedPoint
- .filter(
- (point) =>
- point.x !== current.x &&
- point.y !== current.y &&
- Big(point.x)
- .minus(Big(current.x))
- .abs()
- .minus(Big(point.y).minus(Big(current.y)).abs())
- .abs()
- .lt(1),
- )
- .forEach((point) => {
- const pointEdge = { vertex1: { x: point.x, y: point.y }, vertex2: { x: current.x, y: current.y } }
- let isIntersection = false
- baseLines.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(pointEdge, lineEdge)
- if (intersection && !intersection.isIntersectionOutside) {
- isIntersection = true
- }
- })
- if (!isIntersection) {
- checkPoints.push({
- point,
- size: Big(point.x)
- .minus(Big(current.x))
- .abs()
- .pow(2)
- .plus(Big(point.y).minus(Big(current.y)).abs().pow(2))
- .sqrt(),
- })
- }
- })
- if (checkPoints.length > 0) {
- checkPoints.sort((a, b) => a.size - b.size)
- const maxCnt = Big(2).minus(Big(current.cnt)).toNumber()
- for (let i = 0; i < maxCnt; i++) {
- const checkPoint = checkPoints[i]
- if (checkPoint) {
- let point = [checkPoint.point.x, checkPoint.point.y, current.x, current.y]
- let hipBasePoint
-
- baseHipLines.forEach((line) => {
- const checkAngel1 = calculateAngle({ x: point[0], y: point[1] }, { x: point[2], y: point[3] })
- const checkAngel2 = calculateAngle(
- { x: line.line.x1, y: line.line.y1 },
- {
- x: line.line.x2,
- y: line.line.y2,
- },
- )
-
- 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
- const isOverlap = segmentsOverlap(line.line, { x1: point[0], y1: point[1], x2: point[2], y2: point[3] })
- const isSameLine =
- (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 (checkPointCnt === 1 && (isConnectLine || isOverlap || isSameLine)) {
- /** 겹치는 추녀마루와 하나의 선으로 변경*/
- const mergePoint = [
- { x: point[0], y: point[1] },
- { x: point[2], y: point[3] },
- { x: line.line.x1, y: line.line.y1 },
- { x: line.line.x2, y: line.line.y2 },
- ]
- /** baseHipLines도 조정*/
- mergePoint.sort((a, b) => a.x - b.x)
-
- hipBasePoint = { x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }
- point = [mergePoint[0].x, mergePoint[0].y, mergePoint[3].x, mergePoint[3].y]
- const theta = Big(
- Math.acos(
- Big(line.line.attributes.planeSize).div(
- line.line.attributes.actualSize === 0 || line.line.attributes.actualSize === '' || line.line.attributes.actualSize === undefined
- ? line.line.attributes.planeSize
- : line.line.attributes.actualSize,
- ),
- ),
- )
- .times(180)
- .div(Math.PI)
- .round(1)
- prevDegree = theta.toNumber()
- currentDegree = theta.toNumber()
- canvas.remove(line.line)
- baseHipLines = baseHipLines.filter((baseLine) => baseLine.line !== line.line)
- }
- })
-
- const hipLine = drawHipLine(point, canvas, roof, textMode, prevDegree, currentDegree)
- if (hipBasePoint) {
- baseHipLines.push({ x1: hipBasePoint.x1, y1: hipBasePoint.y1, x2: point[2], y2: point[3], line: hipLine })
- } else {
- baseHipLines.push({ x1: point[0], y1: point[1], x2: point[2], y2: point[3], line: hipLine })
- }
- current.cnt = current.cnt + 1
- }
- }
- }
-
- /** 라인이 다 그려지지 않은 경우 */
- if (current.cnt % 2 !== 0) {
- let basePoints = baseLinePoints
- .filter((point) =>
- Big(point.x)
- .minus(Big(current.x))
- .abs()
- .minus(Big(point.y).minus(Big(current.y)).abs())
- .abs()
- .lt(1),
- )
- .filter((point) => {
- const pointEdge = { vertex1: { x: current.x, y: current.y }, vertex2: { x: point.x, y: point.y } }
-
- const intersectPoints = []
- baseLines.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(pointEdge, lineEdge)
- if (intersection && !intersection.isIntersectionOutside) {
- intersectPoints.push(intersection)
- }
- })
- return (
- !intersectPoints.filter(
- (intersect) => !(Big(intersect.x).minus(Big(point.x)).abs().lt(1) && Big(intersect.y).minus(Big(point.y)).abs().lt(1)),
- ).length > 0
- )
- })
-
- /** hip을 그리기 위한 기본 길이*/
- let hipSize = Big(0)
- if (basePoints.length > 0) {
- basePoints.sort((a, b) => {
- const aSize = Big(a.x)
- .minus(Big(current.x))
- .abs()
- .pow(2)
- .plus(Big(a.y).minus(Big(current.y)).abs().pow(2))
- .sqrt()
- const bSize = Big(b.x)
- .minus(Big(current.x))
- .abs()
- .pow(2)
- .plus(Big(b.y).minus(Big(current.y)).abs().pow(2))
- .sqrt()
- return aSize - bSize
- })
- const baseHips = baseHipLines.filter((line) => line.x1 === basePoints[0].x && line.y1 === basePoints[0].y)
- if (baseHips.length > 0) {
- hipSize = Big(baseHips[0].line.attributes.planeSize)
- }
- }
-
- if (hipSize.eq(0)) {
- const ridge = current.line
- basePoints = baseHipLines
- .filter((line) => (line.x2 === ridge.x1 && line.y2 === ridge.y1) || (line.x2 === ridge.x2 && line.y2 === ridge.y2))
- .filter((line) => baseLines.filter((baseLine) => baseLine.x1 === line.x1 && baseLine.y1 === line.y1).length > 0)
- basePoints.sort((a, b) => a.line.attributes.planeSize - b.line.attributes.planeSize)
- if (basePoints.length > 0 && basePoints[0].line) {
- hipSize = Big(basePoints[0].line.attributes.planeSize)
- } else {
- hipSize = Big(0) // 또는 기본값 설정
- }
- }
- hipSize = hipSize.pow(2).div(2).sqrt().round().div(10).toNumber()
-
- /** 현재 라인을 기준으로 45, 135, 225, 315 방향을 확인하기 위한 좌표, hip은 45도 방향으로만 그린다. */
- const checkEdge45 = {
- vertex1: { x: current.x, y: current.y },
- vertex2: { x: current.x + hipSize, y: current.y - hipSize },
- }
- const checkEdge135 = {
- vertex1: { x: current.x, y: current.y },
- vertex2: { x: current.x + hipSize, y: current.y + hipSize },
- }
- const checkEdge225 = {
- vertex1: { x: current.x, y: current.y },
- vertex2: { x: current.x - hipSize, y: current.y + hipSize },
- }
- const checkEdge315 = {
- vertex1: { x: current.x, y: current.y },
- vertex2: { x: current.x - hipSize, y: current.y - hipSize },
- }
-
- let intersectPoints = []
- let notIntersect45 = true,
- notIntersect135 = true,
- notIntersect225 = true,
- notIntersect315 = true
- baseLines.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection45 = edgesIntersection(checkEdge45, lineEdge)
- const intersection135 = edgesIntersection(checkEdge135, lineEdge)
- const intersection225 = edgesIntersection(checkEdge225, lineEdge)
- const intersection315 = edgesIntersection(checkEdge315, lineEdge)
-
- if (intersection45 && !intersection45.isIntersectionOutside) {
- intersectPoints.push(intersection45)
- notIntersect45 = false
- }
- if (intersection135 && !intersection135.isIntersectionOutside) {
- intersectPoints.push(intersection135)
- notIntersect135 = false
- }
- if (intersection225 && !intersection225.isIntersectionOutside) {
- intersectPoints.push(intersection225)
- notIntersect225 = false
- }
- if (intersection315 && !intersection315.isIntersectionOutside) {
- intersectPoints.push(intersection315)
- notIntersect315 = false
- }
- })
- /** baseLine과 교차하지 않는 포인트를 추가한다.*/
- if (notIntersect45) {
- intersectPoints.push(checkEdge45.vertex2)
- }
- if (notIntersect135) {
- intersectPoints.push(checkEdge135.vertex2)
- }
- if (notIntersect225) {
- intersectPoints.push(checkEdge225.vertex2)
- }
- if (notIntersect315) {
- intersectPoints.push(checkEdge315.vertex2)
- }
- /** baseLine의 각 좌표와 교차하는 경우로 한정*/
- intersectPoints = intersectPoints.filter((is) => baseLinePoints.filter((point) => point.x === is.x && point.y === is.y).length > 0)
- /** baseLine과 교차하는 좌표의 경우 이미 그려진 추녀마루가 존재한다면 제외한다. */
- intersectPoints = intersectPoints.filter((point) => baseHipLines.filter((hip) => hip.x1 === point.x && hip.y1 === point.y).length === 0)
- /** 중복제거 */
- intersectPoints = intersectPoints.filter((point, index, self) => index === self.findIndex((p) => p.x === point.x && p.y === point.y))
-
- intersectPoints.forEach((is) => {
- const points = [current.x, current.y, is.x, is.y]
- /** 추녀마루의 연결점이 처마라인이 아닌경우 return */
- let hasGable = false
- baseLines
- .filter((line) => (line.x1 === points[2] && line.y1 === points[3]) || (line.x2 === points[2] && line.y2 === points[3]))
- .forEach((line) => {
- if (!eavesType.includes(line.attributes.type)) {
- hasGable = true
- }
- })
- if (hasGable) return
- const pointEdge = { vertex1: { x: points[0], y: points[1] }, vertex2: { x: points[2], y: points[3] } }
- const vectorX = Math.sign(Big(points[2]).minus(Big(points[0])).toNumber())
- const vectorY = Math.sign(Big(points[3]).minus(Big(points[1])).toNumber())
- const roofIntersections = []
- roof.lines.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(pointEdge, lineEdge)
- if (intersection) {
- const vectorIntersectionX = Math.sign(Big(intersection.x).minus(Big(points[0])).toNumber())
- const vectorIntersectionY = Math.sign(Big(intersection.y).minus(Big(points[1])).toNumber())
- if (vectorIntersectionX === vectorX && vectorIntersectionY === vectorY) {
- roofIntersections.push({
- x: intersection.x,
- y: intersection.y,
- size: calcLinePlaneSize({ x1: points[0], y1: points[1], x2: intersection.x, y2: intersection.y }),
- })
- }
- }
- })
- roofIntersections.sort((a, b) => a.size - b.size)
-
- const hipLine = drawHipLine(
- [points[0], points[1], roofIntersections[0].x, roofIntersections[0].y],
- canvas,
- roof,
- textMode,
-
- prevDegree,
- currentDegree,
- )
- baseHipLines.push({ x1: points[0], y1: points[1], x2: points[2], y2: points[3], line: hipLine })
- current.cnt = current.cnt + 1
- })
- }
- })
-
- /** hip이 짝수개가 맞다아있는데 마루와 연결되지 않는 포인트를 찾는다. 그려지지 않은 마루를 찾기 위함.*/
- let noRidgeHipPoints = baseHipLines
- .filter((current) => current.x1 !== current.x2 && current.y1 !== current.y2)
- .filter((current) => {
- const lines = baseHipLines
- .filter((line) => line !== current)
- .filter((line) => (line.x1 === current.x2 && line.y1 === current.y2) || (line.x2 === current.x2 && line.y2 === current.y2))
-
- return lines.length !== 0 && lines.length % 2 !== 0
- })
- .filter(
- (current) =>
- baseRidgeLines.filter((line) => (line.x1 === current.x2 && line.y1 === current.y2) || (line.x2 === current.x2 && line.y2 === current.y2))
- .length === 0 &&
- baseGableRidgeLines.filter((line) => (line.x1 === current.x2 && line.y1 === current.y2) || (line.x2 === current.x2 && line.y2 === current.y2))
- .length === 0,
- )
-
- noRidgeHipPoints.forEach((current) => {
- const orthogonalPoints = noRidgeHipPoints.filter((point) => {
- if (point !== current && ((current.x2 === point.x2 && current.y2 !== point.y2) || (current.x2 !== point.x2 && current.y2 === point.y2))) {
- return true
- }
- })
-
- /** 직교 하는 포인트가 존재 할때 마루를 그린다. */
- if (orthogonalPoints.length > 0 && baseRidgeCount < getMaxRidge(baseLines.length)) {
- baseRidgeCount = baseRidgeCount + 1
- const points = [current.x2, current.y2, orthogonalPoints[0].x2, orthogonalPoints[0].y2]
- const ridgeLine = drawRidgeLine(points, canvas, roof, textMode)
- baseRidgeLines.push(ridgeLine)
- }
- })
-
- /** 중복제거*/
- baseRidgeLines.forEach((current) => {
- const sameRidge = baseRidgeLines.filter(
- (line) =>
- line !== current &&
- ((line.x1 === current.x1 && line.y1 === current.y1 && line.x2 === current.x2 && line.y2 === current.y2) ||
- (line.x1 === current.x2 && line.y1 === current.y2 && line.x2 === current.x1 && line.y2 === current.y1)),
- )
- if (sameRidge.length > 0) {
- sameRidge.forEach((duplicateLine) => {
- const index = baseRidgeLines.indexOf(duplicateLine)
- if (index !== -1) {
- baseRidgeLines.splice(index, 1)
- }
- canvas.remove(duplicateLine)
- })
- }
- })
-
- /** 직교 하는 포인트가 없는 경우 남은 포인트 처리 */
- const checkEdgeLines = []
- 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 } },
- )
- })
- })
-
- /** 연결되지 않은 포인트를 찾아서 해당 포인트를 가지고 있는 라인을 찾는다. */
- let unFinishedPoints = []
- let unFinishedLines = []
- let intersectPoints = []
- baseHipLines.forEach((line) => {
- if (baseLinePoints.filter((point) => point.x === line.x1 && point.y === line.y1).length === 0) {
- unFinishedPoints.push({ x: line.x1, y: line.y1 })
- }
- if (baseLinePoints.filter((point) => point.x === line.x2 && point.y === line.y2).length === 0) {
- unFinishedPoints.push({ x: line.x2, y: line.y2 })
- }
- })
- unFinishedPoints
- .filter((point) => unFinishedPoints.filter((p) => p !== point && p.x === point.x && p.y === point.y).length === 0)
- .forEach((point) => {
- baseHipLines
- .filter((line) => (line.x1 === point.x && line.y1 === point.y) || (line.x2 === point.x && line.y2 === point.y))
- .forEach((line) => unFinishedLines.push(line))
- })
-
- unFinishedLines.forEach((line) => {
- const xVector = Math.sign(Big(line.x2).minus(Big(line.x1)))
- const yVector = Math.sign(Big(line.y2).minus(Big(line.y1)))
- let lineIntersectPoints = []
- checkEdgeLines.forEach((edge) => {
- const intersectEdge = edgesIntersection(edge, {
- vertex1: { x: line.x1, y: line.y1 },
- vertex2: { x: line.x2, y: line.y2 },
- })
- if (intersectEdge) {
- const isXVector = Math.sign(Big(intersectEdge.x).minus(Big(line.x1))) === xVector
- const isYVector = Math.sign(Big(intersectEdge.y).minus(Big(line.y1))) === yVector
- if (isXVector && isYVector) {
- lineIntersectPoints.push({
- intersection: intersectEdge,
- size: Big(intersectEdge.x)
- .minus(Big(line.x1))
- .abs()
- .pow(2)
- .plus(Big(intersectEdge.y).minus(Big(line.y1)).abs().pow(2))
- .sqrt()
- .round(1)
- .toNumber(),
- })
- }
- }
- })
-
- lineIntersectPoints = lineIntersectPoints.filter(
- (point, index, self) => index === self.findIndex((p) => p.intersection.x === point.intersection.x && p.intersection.y === point.intersection.y),
- )
- lineIntersectPoints.sort((a, b) => a.size - b.size)
- if (lineIntersectPoints.length > 0) {
- intersectPoints.push({ intersection: lineIntersectPoints[0].intersection, line })
- }
- })
-
- /** 마루를 그릴수 있는지 찾는다. */
- noRidgeHipPoints.forEach((hipPoint) => {
- const ridgePoints = []
- intersectPoints
- .filter(
- (intersectPoint) =>
- (intersectPoint.intersection.x !== hipPoint.x2 && intersectPoint.intersection.y === hipPoint.y2) ||
- (intersectPoint.intersection.x === hipPoint.x2 && intersectPoint.intersection.y !== hipPoint.y2),
- )
- .forEach((intersectPoint) => {
- ridgePoints.push({
- intersection: intersectPoint,
- distance: Big(intersectPoint.intersection.x)
- .minus(Big(hipPoint.x2))
- .abs()
- .pow(2)
- .plus(Big(intersectPoint.intersection.y).minus(Big(hipPoint.y2)).abs().pow(2))
- .sqrt()
- .round(1)
- .toNumber(),
- })
- })
- ridgePoints.sort((a, b) => a.distance - b.distance)
-
- if (ridgePoints.length > 0 && baseRidgeCount < getMaxRidge(baseLines.length)) {
- const intersection = ridgePoints[0].intersection
- const isPoint = intersection.intersection
- const points = [hipPoint.x2, hipPoint.y2, isPoint.x, isPoint.y]
- const ridgeLine = drawRidgeLine(points, canvas, roof, textMode)
- baseRidgeCount = baseRidgeCount + 1
- baseRidgeLines.push(ridgeLine)
-
- let baseHipLine = baseHipLines.filter((line) => line === intersection.line)[0]
- baseHipLine.x2 = isPoint.x
- baseHipLines.y2 = isPoint.y
- /** 보조선 라인 조정*/
- const hipLine = intersection.line.line
- /** 평면길이 */
- const planeSize = calcLinePlaneSize({
- x1: hipLine.x1,
- y1: hipLine.y1,
- x2: isPoint.x,
- y2: isPoint.y,
- })
- /** 실제길이 */
- const actualSize =
- prevDegree === currentDegree
- ? calcLineActualSize(
- {
- x1: hipLine.x1,
- y1: hipLine.y1,
- x2: isPoint.x,
- y2: isPoint.y,
- },
- currentDegree,
- )
- : 0
- hipLine.set({
- x2: isPoint.x,
- y2: isPoint.y,
- attributes: { roofId: roof.id, planeSize, actualSize },
- })
- hipLine.fire('modified')
- intersectPoints = intersectPoints.filter((isp) => isp !== intersection)
- noRidgeHipPoints = noRidgeHipPoints.filter((hip) => hip !== hipPoint)
- } else {
- const linePoints = []
- intersectPoints.forEach((intersectPoint) => {
- const intersection = intersectPoint.intersection
- const xVector = Math.sign(Big(intersection.x).minus(Big(hipPoint.x2)))
- const yVector = Math.sign(Big(intersection.y).minus(Big(hipPoint.y2)))
-
- const checkEdge = {
- vertex1: { x: intersection.x, y: intersection.y },
- vertex2: {
- x: Big(intersection.x).plus(Big(xVector).times(10)).toNumber(),
- y: Big(intersection.y).plus(Big(yVector).times(10)).toNumber(),
- },
- }
- const intersectX = edgesIntersection(
- {
- vertex1: { x: hipPoint.x2, y: hipPoint.y2 },
- vertex2: { x: Big(hipPoint.x2).plus(Big(xVector).neg().times(10)).toNumber(), y: hipPoint.y2 },
- },
- checkEdge,
- )
- const intersectY = edgesIntersection(
- {
- vertex1: { x: hipPoint.x2, y: hipPoint.y2 },
- vertex2: { x: hipPoint.x2, y: Big(hipPoint.y2).plus(Big(yVector).neg().times(10)).toNumber() },
- },
- checkEdge,
- )
-
- let distanceX = Infinity,
- distanceY = Infinity
-
- if (intersectX) {
- distanceX = Big(intersectX.x)
- .minus(Big(intersection.x))
- .abs()
- .pow(2)
- .plus(Big(intersectX.y).minus(Big(intersection.y)).abs().pow(2))
- .sqrt()
- .round(1)
- .toNumber()
- }
- if (intersectY) {
- distanceY = Big(intersectY.x)
- .minus(Big(intersection.x))
- .abs()
- .pow(2)
- .plus(Big(intersectY.y).minus(Big(intersection.y)).abs().pow(2))
- .sqrt()
- .round(1)
- .toNumber()
- }
-
- if (distanceX < distanceY) {
- linePoints.push({ intersection: intersectX, intersectPoint })
- }
- if (distanceX > distanceY) {
- linePoints.push({ intersection: intersectY, intersectPoint })
- }
- })
-
- const linePoint = linePoints.reduce((prev, current) => {
- const prevDistance = Big(prev.intersection.x)
- .minus(Big(hipPoint.x2))
- .abs()
- .pow(2)
- .plus(Big(prev.intersection.y).minus(Big(hipPoint.y2)).abs().pow(2))
- .sqrt()
- const currentDistance = Big(current.intersection.x)
- .minus(Big(hipPoint.x2))
- .abs()
- .pow(2)
- .plus(Big(current.intersection.y).minus(Big(hipPoint.y2)).abs().pow(2))
- .sqrt()
- if (prevDistance < currentDistance) {
- return prev
- } else {
- return current
- }
- }, linePoints[0])
-
- if (!linePoint) return
- const hipStartPoint = [hipPoint.x2, hipPoint.y2, linePoint.intersection.x, linePoint.intersection.y]
- /** 직선인 경우 마루를 그린다.*/
- if (
- ((hipStartPoint[0] === hipStartPoint[2] && hipStartPoint[1] !== hipStartPoint[3]) ||
- (hipStartPoint[0] !== hipStartPoint[2] && hipStartPoint[1] === hipStartPoint[3])) &&
- baseRidgeCount < getMaxRidge(baseLines.length)
- ) {
- const ridgeLine = drawRidgeLine(hipStartPoint, canvas, roof, textMode)
- baseRidgeCount = baseRidgeCount + 1
- baseRidgeLines.push(ridgeLine)
- noRidgeHipPoints = noRidgeHipPoints.filter((hip) => hip !== hipPoint)
- }
- /** 대각선인경우 hip을 그린다. */
- if (
- Big(hipStartPoint[0])
- .minus(Big(hipStartPoint[2]))
- .abs()
- .minus(Big(hipStartPoint[1]).minus(Big(hipStartPoint[3])).abs())
- .abs()
- .lt(1)
- ) {
- // console.log('힙1')
- const hipLine = drawHipLine(hipStartPoint, canvas, roof, textMode, prevDegree, currentDegree)
- baseHipLines.push({
- x1: hipStartPoint[0],
- y1: hipStartPoint[1],
- x2: hipStartPoint[2],
- y2: hipStartPoint[3],
- line: hipLine,
- })
- noRidgeHipPoints = noRidgeHipPoints.filter((hip) => hip !== hipPoint)
- }
-
- const isStartPoint = [
- linePoint.intersection.x,
- linePoint.intersection.y,
- linePoint.intersectPoint.intersection.x,
- linePoint.intersectPoint.intersection.y,
- ]
- if (
- ((isStartPoint[0] === isStartPoint[2] && isStartPoint[1] !== isStartPoint[3]) ||
- (isStartPoint[0] !== isStartPoint[2] && isStartPoint[1] === isStartPoint[3])) &&
- baseRidgeCount < getMaxRidge(baseLines.length)
- ) {
- const ridgeLine = drawRidgeLine(isStartPoint, canvas, roof, textMode)
- baseRidgeCount = baseRidgeCount + 1
- baseRidgeLines.push(ridgeLine)
- }
- if (
- Big(isStartPoint[0])
- .minus(Big(isStartPoint[2]))
- .abs()
- .minus(Big(isStartPoint[1]).minus(Big(isStartPoint[3])).abs())
- .abs()
- .lt(1)
- ) {
- const hipLine = drawHipLine(isStartPoint, canvas, roof, textMode, prevDegree, currentDegree)
- baseHipLines.push({
- x1: isStartPoint[0],
- y1: isStartPoint[1],
- x2: isStartPoint[2],
- y2: isStartPoint[3],
- line: hipLine,
- })
- }
- }
- })
-
- 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
- .filter(
- (hip) => baseLinePoints.filter((point) => (point.x === hip.x1 && point.y === hip.y1) || (point.x === hip.x2 && point.y === hip.y2)).length > 0,
- )
- .filter((hip) => {
- const hipEdge = { vertex1: { x: hip.line.x1, y: hip.line.y1 }, vertex2: { x: hip.line.x2, y: hip.line.y2 } }
- const hipVectorX = Math.sign(Big(hip.x1).minus(Big(hip.x2)))
- const hipVectorY = Math.sign(Big(hip.y1).minus(Big(hip.y2)))
- let isIntersect = false
- roof.lines.forEach((line) => {
- const edge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(edge, hipEdge)
- if (intersection && !intersection.isIntersectionOutside) {
- const isVectorX = Math.sign(Big(intersection.x).minus(Big(hip.x2)))
- const isVectorY = Math.sign(Big(intersection.y).minus(Big(hip.y2)))
- if (isVectorX === hipVectorX && isVectorY === hipVectorY) {
- isIntersect = true
- }
- }
- })
- return !isIntersect
- })
- .forEach((hip) => {
- const hipLine = hip.line
- if (hipLine) {
- const hipVectorX = Big(hipLine.x2).plus(Big(hipLine.attributes.planeSize).times(Big(hipLine.x1).minus(Big(hipLine.x2)).neg().s))
- const hipVectorY = Big(hipLine.y2).plus(Big(hipLine.attributes.planeSize).times(Big(hipLine.y1).minus(Big(hipLine.y2)).neg().s))
- const overlapLineX = roof.lines
- .filter((roofLine) => roofLine.x1 !== roofLine.x2 && roofLine.y1 === hipLine.y2 && roofLine.y2 === hipLine.y2)
- .filter((roofLine) => {
- const minX = Math.min(roofLine.x1, roofLine.x2, hipLine.x2)
- const maxX = Math.max(roofLine.x1, roofLine.x2, hipLine.x2)
- const checkLineEdge = { vertex1: { x: minX, y: hipLine.y2 }, vertex2: { x: maxX, y: hipLine.y2 } }
- let isIntersect = false
- baseHipLines.forEach((baseHipLine) => {
- const edge = {
- vertex1: { x: baseHipLine.x1, y: baseHipLine.y1 },
- vertex2: { x: baseHipLine.x2, y: baseHipLine.y2 },
- }
- const intersection = edgesIntersection(edge, checkLineEdge)
- if (intersection && !intersection.isIntersectionOutside) {
- const isVectorX = Math.sign(Big(intersection.x).minus(Big(baseHipLine.x2)))
- const isVectorY = Math.sign(Big(intersection.y).minus(Big(baseHipLine.y2)))
- if (isVectorX === hipVectorX && isVectorY === hipVectorY) {
- isIntersect = true
- }
- }
- })
- baseRidgeLines.forEach((baseRidgeLine) => {
- const edge = {
- vertex1: { x: baseRidgeLine.x1, y: baseRidgeLine.y1 },
- vertex2: { x: baseRidgeLine.x2, y: baseRidgeLine.y2 },
- }
- const intersection = edgesIntersection(edge, checkLineEdge)
- if (intersection && !intersection.isIntersectionOutside) {
- const isVectorX = Math.sign(Big(intersection.x).minus(Big(hipLine.x2)))
- const isVectorY = Math.sign(Big(intersection.y).minus(Big(hipLine.y2)))
- if (isVectorX === hipVectorX && isVectorY === hipVectorY) {
- isIntersect = true
- }
- }
- })
- return !isIntersect
- })
- const overlapLineY = roof.lines
- .filter((roofLine) => roofLine.y1 !== roofLine.y2 && roofLine.x1 === hipLine.x2 && roofLine.x2 === hipLine.x2)
- .filter((roofLine) => {
- const minY = Math.min(roofLine.y1, roofLine.y2, hipLine.y2)
- const maxY = Math.max(roofLine.y1, roofLine.y2, hipLine.y2)
- const checkLineEdge = { vertex1: { x: hipLine.x2, y: minY }, vertex2: { x: hipLine.x2, y: maxY } }
- let isIntersect = false
- baseHipLines.forEach((baseHipLine) => {
- const edge = {
- vertex1: { x: baseHipLine.x1, y: baseHipLine.y1 },
- vertex2: { x: baseHipLine.x2, y: baseHipLine.y2 },
- }
- const intersection = edgesIntersection(edge, checkLineEdge)
- if (intersection && !intersection.isIntersectionOutside) {
- const isVectorX = Math.sign(Big(intersection.x).minus(Big(hipLine.x2)))
- const isVectorY = Math.sign(Big(intersection.y).minus(Big(hipLine.y2)))
- if (isVectorX === hipVectorX && isVectorY === hipVectorY) {
- isIntersect = true
- }
- }
- })
- baseRidgeLines.forEach((baseRidgeLine) => {
- const edge = {
- vertex1: { x: baseRidgeLine.x1, y: baseRidgeLine.y1 },
- vertex2: { x: baseRidgeLine.x2, y: baseRidgeLine.y2 },
- }
- const intersection = edgesIntersection(edge, checkLineEdge)
- if (intersection && !intersection.isIntersectionOutside) {
- const isVectorX = Math.sign(Big(intersection.x).minus(Big(hipLine.x2)))
- const isVectorY = Math.sign(Big(intersection.y).minus(Big(hipLine.y2)))
- if (isVectorX === hipVectorX && isVectorY === hipVectorY) {
- isIntersect = true
- }
- }
- })
- return !isIntersect
- })
-
- overlapLineX.reduce((prev, current) => {
- const prevDistance = Big(prev.x1)
- .minus(Big(hipLine.x2))
- .abs()
- .lt(Big(prev.x2).minus(Big(hipLine.x2)).abs())
- ? Big(prev.x1).minus(Big(hipLine.x2)).abs()
- : Big(prev.x2).minus(Big(hipLine.x2)).abs()
- const currentDistance = Big(current.x1)
- .minus(Big(hipLine.x2))
- .abs()
- .lt(Big(current.x2).minus(Big(hipLine.x2)).abs())
- ? Big(current.x1).minus(Big(hipLine.x2)).abs()
- : Big(current.x2).minus(Big(hipLine.x2)).abs()
-
- return prevDistance.lt(currentDistance) ? prev : current
- }, overlapLineX[0])
-
- overlapLineY.reduce((prev, current) => {
- const prevDistance = Big(prev.y1)
- .minus(Big(hipLine.y2))
- .abs()
- .lt(Big(prev.y2).minus(Big(hipLine.y2)).abs())
- ? Big(prev.y1).minus(Big(hipLine.y2)).abs()
- : Big(prev.y2).minus(Big(hipLine.y2)).abs()
- const currentDistance = Big(current.y1)
- .minus(Big(hipLine.y2))
- .abs()
- .lt(Big(current.y2).minus(Big(hipLine.y2)).abs())
- ? Big(current.y1).minus(Big(hipLine.y2)).abs()
- : Big(current.y2).minus(Big(hipLine.y2)).abs()
- return prevDistance.lt(currentDistance) ? prev : current
- }, overlapLineY[0])
-
- if (overlapLineX.length > 0) {
- const overlapLine = overlapLineX[0]
- const maxX = Math.max(overlapLine.x1, overlapLine.x2)
- const point = [hipLine.x2, hipLine.y2, maxX, hipLine.y2]
- const addLine = drawHipLine(point, canvas, roof, textMode, prevDegree, currentDegree)
- baseHipLines.push({ x1: point[0], y1: point[1], x2: point[2], y2: point[3], line: addLine })
- }
- if (overlapLineY.length > 0) {
- const overlapLine = overlapLineY[0]
- const maxY = Math.max(overlapLine.y1, overlapLine.y2)
- const point = [hipLine.x2, hipLine.y2, hipLine.x2, maxY]
- const addLine = drawHipLine(point, canvas, roof, textMode, prevDegree, currentDegree)
- baseHipLines.push({ x1: point[0], y1: point[1], x2: point[2], y2: point[3], line: addLine })
- }
- }
-
- const modifiedBaseLine = baseLines.filter((line) => (hip.x2 === line.x1 && hip.y2 === line.y1) || (hip.x2 === line.x2 && hip.y2 === line.y2))
- if (modifiedBaseLine.length === 0) return
- const verticalLine = modifiedBaseLine.find(
- (line) =>
- (hip.x2 === line.attributes.originPoint.x1 && hip.x2 === line.attributes.originPoint.x2) ||
- (hip.y2 === line.attributes.originPoint.y1 && hip.y2 === line.attributes.originPoint.y2),
- )
- const horizonLine = modifiedBaseLine.find((line) => line !== verticalLine)
-
- const horizonRoof = roof.lines.find((line) => {
- const originPoint = horizonLine.attributes.originPoint
- if (originPoint.y1 === originPoint.y2) {
- return (
- line.y1 === line.y2 &&
- Math.sign(originPoint.x1 - originPoint.x2) === Math.sign(line.x1 - line.x2) &&
- Big(originPoint.y1).minus(Big(line.y1)).abs().minus(horizonLine.attributes.offset).abs().lt(1)
- )
- } else {
- return (
- line.x1 === line.x2 &&
- Math.sign(originPoint.y1 - originPoint.y2) === Math.sign(line.y1 - line.y2) &&
- Big(originPoint.x1).minus(Big(line.x1)).abs().minus(horizonLine.attributes.offset).abs().lt(1)
- )
- }
- })
-
- if (horizonRoof) {
- let horizonPoint
- if (horizonRoof.y1 === horizonRoof.y2) {
- const minX = Math.min(horizonRoof.x1, horizonRoof.x2, horizonLine.attributes.originPoint.x1, horizonLine.attributes.originPoint.x2)
- const maxX = Math.max(horizonRoof.x1, horizonRoof.x2, horizonLine.attributes.originPoint.x1, horizonLine.attributes.originPoint.x2)
- horizonPoint = [minX, horizonRoof.y1, maxX, horizonRoof.y1]
- } else {
- const minY = Math.min(horizonRoof.y1, horizonRoof.y2, horizonLine.attributes.originPoint.y1, horizonLine.attributes.originPoint.y2)
- const maxY = Math.max(horizonRoof.y1, horizonRoof.y2, horizonLine.attributes.originPoint.y1, horizonLine.attributes.originPoint.y2)
- horizonPoint = [horizonRoof.x1, minY, horizonRoof.x1, maxY]
- }
- let addLine
- const alreadyHorizonLines = baseHipLines.find(
- (hipLine) =>
- hipLine.x1 === horizonPoint[0] && hipLine.y1 === horizonPoint[1] && hipLine.x2 === horizonPoint[2] && hipLine.y2 === horizonPoint[3],
- )
- if (!alreadyHorizonLines) {
- addLine = drawHipLine(horizonPoint, canvas, roof, textMode, prevDegree, currentDegree)
- baseHipLines.push({
- x1: horizonPoint[0],
- y1: horizonPoint[1],
- x2: horizonPoint[2],
- y2: horizonPoint[3],
- line: addLine,
- })
- } else {
- addLine = alreadyHorizonLines
- }
-
- let verticalPoint
- if (addLine.y1 === addLine.y2) {
- verticalPoint = [hip.x2, hip.y2, hip.x2, addLine.y1]
- } else {
- verticalPoint = [hip.x2, hip.y2, addLine.x1, hip.y2]
- }
- const alreadyVerticalLine = baseHipLines.find(
- (hipLine) =>
- hipLine.x1 === verticalPoint[0] && hipLine.y1 === verticalPoint[1] && hipLine.x2 === verticalPoint[2] && hipLine.y2 === verticalPoint[3],
- )
- if (!alreadyVerticalLine) {
- addLine = drawHipLine(verticalPoint, canvas, roof, textMode, prevDegree, currentDegree)
- baseHipLines.push({
- x1: verticalPoint[0],
- y1: verticalPoint[1],
- x2: verticalPoint[2],
- y2: verticalPoint[3],
- line: addLine,
- })
- }
- }
- })
-
- ridgeAllPoints.forEach((current) => {
- ridgeAllPoints
- .filter((point) => point !== current)
- .forEach((point) => {
- let checkRidgeLine, checkHipLine
- /** 직선인 경우 마루 확인*/
- if (
- baseRidgeCount < getMaxRidge(baseLines.length) &&
- ((point.x === current.x && point.y !== current.y) || (point.x !== current.x && point.y === current.y))
- ) {
- checkRidgeLine = { x1: current.x, y1: current.y, x2: point.x, y2: point.y }
- }
- /** 대각선인 경우 hip 확인*/
- const hipX = Big(current.x).minus(Big(point.x)).abs()
- const hipY = Big(current.y).minus(Big(point.y)).abs()
- if (hipX.eq(hipY) && hipX.gt(0) && hipY.gt(0)) {
- checkHipLine = { x1: current.x, y1: current.y, x2: point.x, y2: point.y }
- }
-
- if (checkRidgeLine) {
- const ridgePoints = [checkRidgeLine.x1, checkRidgeLine.y1, checkRidgeLine.x2, checkRidgeLine.y2]
-
- let baseIntersection = false
- const ridgeInterSection = []
- const ridgeEdge = {
- vertex1: { x: ridgePoints[0], y: ridgePoints[1] },
- vertex2: { x: ridgePoints[2], y: ridgePoints[3] },
- }
- baseLines.forEach((line) => {
- const intersection = edgesIntersection(ridgeEdge, {
- vertex1: { x: line.x1, y: line.y1 },
- vertex2: { x: line.x2, y: line.y2 },
- })
- if (intersection && !intersection.isIntersectionOutside) {
- ridgeInterSection.push(intersection)
- }
- })
- baseRidgeLines.forEach((line) => {
- const intersection = edgesIntersection(ridgeEdge, {
- vertex1: { x: line.x1, y: line.y1 },
- vertex2: { x: line.x2, y: line.y2 },
- })
- if (intersection && !intersection.isIntersectionOutside) {
- ridgeInterSection.push(intersection)
- }
- })
- baseHipLines.forEach((line) => {
- const intersection = edgesIntersection(ridgeEdge, {
- vertex1: { x: line.x1, y: line.y1 },
- vertex2: { x: line.x2, y: line.y2 },
- })
- if (intersection && !intersection.isIntersectionOutside) {
- ridgeInterSection.push(intersection)
- }
- })
- const otherRidgeInterSection = ridgeInterSection.filter(
- (intersection) =>
- !(
- (intersection.x === ridgePoints[0] && intersection.y === ridgePoints[1]) ||
- (intersection.x === ridgePoints[2] && intersection.y === ridgePoints[3])
- ),
- )
- const alreadyRidges = baseRidgeLines.filter(
- (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 (
- !baseIntersection &&
- alreadyRidges.length === 0 &&
- otherRidgeInterSection.length === 0 &&
- baseRidgeCount < getMaxRidge(baseLines.length)
- ) {
- baseRidgeCount = baseRidgeCount + 1
- const ridgeLine = drawRidgeLine(ridgePoints, canvas, roof, textMode)
- baseRidgeLines.push(ridgeLine)
- }
- }
- if (checkHipLine) {
- const hipPoints = [checkHipLine.x1, checkHipLine.y1, checkHipLine.x2, checkHipLine.y2]
-
- let baseIntersection = false
- let hipInterSection = []
- const hipEdge = {
- vertex1: { x: hipPoints[0], y: hipPoints[1] },
- vertex2: { x: hipPoints[2], y: hipPoints[3] },
- }
- baseLines.forEach((line) => {
- const intersection = edgesIntersection(hipEdge, {
- vertex1: { x: line.x1, y: line.y1 },
- vertex2: { x: line.x2, y: line.y2 },
- })
- if (intersection && !intersection.isIntersectionOutside && eavesType.includes(line.attributes.type)) {
- baseIntersection = true
- }
- })
- baseRidgeLines.forEach((line) => {
- const intersection = edgesIntersection(hipEdge, {
- vertex1: { x: line.x1, y: line.y1 },
- vertex2: { x: line.x2, y: line.y2 },
- })
- if (intersection && !intersection.isIntersectionOutside) {
- hipInterSection.push(intersection)
- }
- })
- baseHipLines.forEach((line) => {
- const intersection = edgesIntersection(hipEdge, {
- vertex1: { x: line.x1, y: line.y1 },
- vertex2: { x: line.x2, y: line.y2 },
- })
- if (intersection && !intersection.isIntersectionOutside) {
- hipInterSection.push(intersection)
- }
- })
- const otherHipInterSection = hipInterSection.filter(
- (intersection) =>
- !(
- (intersection.x === hipPoints[0] && intersection.y === hipPoints[1]) ||
- (intersection.x === hipPoints[2] && intersection.y === hipPoints[3])
- ),
- )
- const alreadyHips = baseHipLines.filter(
- (line) =>
- (line.x1 === hipPoints[0] && line.y1 === hipPoints[1] && line.x2 === hipPoints[2] && line.y2 === hipPoints[3]) ||
- (line.x1 === hipPoints[2] && line.y1 === hipPoints[3] && line.x2 === hipPoints[0] && line.y2 === hipPoints[1]),
- )
-
- if (!baseIntersection && alreadyHips.length === 0 && otherHipInterSection.length === 0) {
- const hipLine = drawHipLine(hipPoints, canvas, roof, textMode, prevDegree, currentDegree)
- baseHipLines.push({ x1: hipPoints[0], y1: hipPoints[1], x2: hipPoints[2], y2: hipPoints[3], line: hipLine })
- }
- }
- })
- })
-
- const innerLines = [...baseRidgeLines, ...baseGableRidgeLines, ...baseGableLines, ...baseHipLines.map((line) => line.line)]
- const uniqueInnerLines = []
-
- innerLines.forEach((currentLine) => {
- if (currentLine.length === 0) {
- canvas.remove(currentLine)
- } else {
- const sameLines = uniqueInnerLines.filter(
- (line) =>
- line !== currentLine &&
- ((line.x1 === currentLine.x1 && line.y1 === currentLine.y1 && line.x2 === currentLine.x2 && line.y2 === currentLine.y2) ||
- (line.x1 === currentLine.x2 && line.y1 === currentLine.y2 && line.x2 === currentLine.x1 && line.y2 === currentLine.y1)),
- )
-
- if (sameLines.length === 0) {
- uniqueInnerLines.push(currentLine)
- } else {
- canvas.remove(currentLine)
- }
- }
- })
- canvas.renderAll()
- roof.innerLines = uniqueInnerLines
-
- roof.innerLines.forEach((line) => {
- line.bringToFront()
- })
- /** 확인용 라인 제거 */
- canvas
- .getObjects()
- .filter((obj) => obj.name === 'checkCircle' || obj.name === 'checkLine')
- .forEach((obj) => canvas.remove(obj))
- canvas.renderAll()
-
- /*
- drawCenterLine(roof, canvas, textMode)
- */
-}
/**
* 추녀 마루를 그린다.
@@ -12887,7 +5505,6 @@ const drawHipLine = (points, canvas, roof, textMode, prevDegree, currentDegree)
textMode: textMode,
attributes: {
roofId: roof.id,
- // currentRoofId: currentRoof.id,
planeSize: calcLinePlaneSize({
x1: points[0],
y1: points[1],
@@ -12915,52 +5532,6 @@ const drawHipLine = (points, canvas, roof, textMode, prevDegree, currentDegree)
return hip
}
-/**
- * 라인의 흐름 방향에서 마주치는 지붕선의 포인트를 찾는다.
- * @param roof
- * @param baseLine
- * @param endPoint
- * @returns {*}
- */
-const findRoofIntersection = (roof, baseLine, endPoint) => {
- let intersectPoints = []
- const { x1, y1, x2, y2 } = baseLine
-
- const baseEdge = {
- vertex1: { x: x1, y: y1 },
- vertex2: { x: x2, y: y2 },
- }
-
- /** 외벽선에서 라인 겹치는 경우에 대한 확인*/
- roof.lines.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersection = edgesIntersection(baseEdge, lineEdge)
- if (
- intersection &&
- !intersection.isIntersectionOutside &&
- Math.sign(endPoint.x - baseLine.x1) === Math.sign(endPoint.x - intersection.x) &&
- Math.sign(endPoint.y - baseLine.y1) === Math.sign(endPoint.y - intersection.y)
- ) {
- const intersectSize = endPoint.x
- .minus(Big(intersection.x))
- .pow(2)
- .plus(endPoint.y.minus(Big(intersection.y)).pow(2))
- .abs()
- .sqrt()
- .toNumber()
-
- intersectPoints.push({
- intersection,
- size: intersectSize,
- })
- }
- })
-
- return intersectPoints.reduce((prev, current) => {
- return prev.size < current.size ? prev : current
- }, intersectPoints[0])
-}
-
/**
* 마루를 그린다.
* @param points
@@ -13081,35 +5652,6 @@ const getHalfAngleVector = (line1, line2) => {
return normalizeVector(summedVector)
}
-/**
- * 두 선분이 겹치는지 확인
- * @param line1
- * @param line2
- * @returns {boolean}
- */
-export const segmentsOverlap = (line1, line2) => {
- if (line1.y1 === line1.y2 && line2.y1 === line2.y2 && line1.y1 === line2.y1) {
- if ((line1.x1 <= line2.x1 && line1.x2 >= line2.x1) || (line1.x1 <= line2.x2 && line1.x2 >= line2.x2)) {
- return true
- }
- }
- if (line1.x1 === line1.x2 && line2.x1 === line2.x2 && line1.x1 === line2.x1) {
- if ((line1.y1 <= line2.y1 && line1.y2 >= line2.y1) || (line1.y1 <= line2.y2 && line1.y2 >= line2.y2)) {
- return true
- }
- }
- return false
-}
-
-/**
- * 최대 생성 마루 갯수
- * @param length
- * @returns {number}
- */
-const getMaxRidge = (length) => {
- return (length - 4) / 2 + 1
-}
-
/**
* 지붕 모양 을 변경한다.
* @param polygon
@@ -13169,7 +5711,7 @@ const reDrawPolygon = (polygon, canvas) => {
* @param canvas
* @param textMode
*/
-const drawCenterLine = (roof, canvas, textMode) => {
+/*const drawCenterLine = (roof, canvas, textMode) => {
//현재 지붕의 centerLine을 다 지운다.
canvas
.getObjects()
@@ -13390,7 +5932,7 @@ const drawCenterLine = (roof, canvas, textMode) => {
}
}
})
-}
+}*/
function arePointsEqual(point1, point2) {
return Math.abs(point1.x - point2.x) <= 1 && Math.abs(point1.y - point2.y) <= 1
@@ -13406,7 +5948,7 @@ export const toGeoJSON = (pointsArray) => {
return coordinates
}
-export const inPolygon = (polygonPoints, rectPoints) => {
+/*export const inPolygon = (polygonPoints, rectPoints) => {
const polygonCoordinates = toGeoJSON(polygonPoints)
const rectCoordinates = toGeoJSON(rectPoints)
@@ -13426,7 +5968,7 @@ export const inPolygon = (polygonPoints, rectPoints) => {
})
return allPointsInsidePolygon && noPolygonPointsInsideRect
-}
+}*/
/**
* 포인트를 기준으로 선의 길이를 구한다. 선의 길이는 10을 곱하여 사용한다.
@@ -13466,7 +6008,7 @@ export const createLinesFromPolygon = (points) => {
}
/** 포인트 정렬 가장왼쪽, 가장위 부터 */
-const getSortedPoint = (points, lines) => {
+/*const getSortedPoint = (points, lines) => {
const startPoint = points
.filter((point) => point.x === Math.min(...points.map((point) => point.x)))
.reduce((prev, curr) => {
@@ -13541,8 +6083,9 @@ const getSortedPoint = (points, lines) => {
}
}
return sortedPoints
-}
+}*/
+/*
const reCalculateSize = (line) => {
const oldPlaneSize = line.attributes.planeSize
const oldActualSize = line.attributes.actualSize
@@ -13571,6 +6114,7 @@ const reCalculateSize = (line) => {
)
return { planeSize, actualSize }
}
+*/
/**
* 직교 다각형(축에 평행한 변들로만 구성된 다각형)의 점들을 시계방향으로 정렬