diff --git a/src/components/common/input/CalcInput.jsx b/src/components/common/input/CalcInput.jsx
index 17af010e..14118b87 100644
--- a/src/components/common/input/CalcInput.jsx
+++ b/src/components/common/input/CalcInput.jsx
@@ -50,26 +50,42 @@ export const CalculatorInput = forwardRef(
// 소수점 이하 2자리 제한 로직 추가
const shouldPreventInput = (value) => {
- const decimalParts = (value || '').split('.')
+ if (!value) return false
+ const decimalParts = value.toString().split('.')
return decimalParts.length > 1 && decimalParts[1].length >= 2
}
+ // 숫자 추가 함수
+ const appendNumber = (current, num) => {
+ // 현재 값이 0이고 소수점이 없을 때 0이 아닌 숫자를 입력하면 대체
+ if (current === '0' && num !== '.' && !current.includes('.')) {
+ return num.toString()
+ }
+ // 0. 다음에 0을 입력하는 경우 허용
+ if (current === '0' && num === '0') {
+ return '0.'
+ }
+ return current + num
+ }
+
if (hasOperation) {
// 연산자 이후 숫자 입력 시
- if (calculator.currentOperand === '0' || calculator.shouldResetDisplay) {
+ if (calculator.shouldResetDisplay) {
calculator.currentOperand = num.toString()
calculator.shouldResetDisplay = false
- }else if (!shouldPreventInput(calculator.currentOperand)) { //소수점 이하2자리
- calculator.currentOperand = (calculator.currentOperand || '') + num
+ } else if (num === '.') {
+ if (!calculator.currentOperand.includes('.')) {
+ calculator.currentOperand = calculator.currentOperand || '0' + '.'
+ }
+ } else if (!shouldPreventInput(calculator.currentOperand)) {
+ calculator.currentOperand = appendNumber(calculator.currentOperand || '0', num)
}
- // else {
- // calculator.currentOperand = (calculator.currentOperand || '') + num
- // }
+
newDisplayValue = calculator.previousOperand + calculator.operation + calculator.currentOperand
setDisplayValue(newDisplayValue)
} else {
// 첫 번째 숫자 입력 시
- if (displayValue === '0' || calculator.shouldResetDisplay) {
+ if (calculator.shouldResetDisplay) {
calculator.currentOperand = num.toString()
calculator.shouldResetDisplay = false
newDisplayValue = calculator.currentOperand
@@ -77,8 +93,17 @@ export const CalculatorInput = forwardRef(
if (!hasOperation) {
onChange(calculator.currentOperand)
}
- } else if (!shouldPreventInput(calculator.currentOperand)) { //소수점 이하2자리
- calculator.currentOperand = (calculator.currentOperand || '') + num
+ } else if (num === '.') {
+ if (!calculator.currentOperand.includes('.')) {
+ calculator.currentOperand = (calculator.currentOperand || '0') + '.'
+ newDisplayValue = calculator.currentOperand
+ setDisplayValue(newDisplayValue)
+ if (!hasOperation) {
+ onChange(newDisplayValue)
+ }
+ }
+ } else if (!shouldPreventInput(calculator.currentOperand)) {
+ calculator.currentOperand = appendNumber(calculator.currentOperand || '0', num)
newDisplayValue = calculator.currentOperand
setDisplayValue(newDisplayValue)
if (!hasOperation) {
diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx
index d8b127fc..4cdffbed 100644
--- a/src/components/estimate/Estimate.jsx
+++ b/src/components/estimate/Estimate.jsx
@@ -1693,13 +1693,13 @@ export default function Estimate({}) {
{/* 파일첨부 끝 */}
{/* 견적특이사항 시작 */}
-
-
{getMessage('estimate.detail.header.specialEstimate')}
-
-
-
-
-
+ {/*
*/}
+ {/*
{getMessage('estimate.detail.header.specialEstimate')}
*/}
+ {/*
*/}
+ {/* */}
+ {/* */}
+ {/*
*/}
+ {/*
*/}
{/* 견적 특이사항 코드영역시작 */}
diff --git a/src/components/floor-plan/modal/basic/step/Module.jsx b/src/components/floor-plan/modal/basic/step/Module.jsx
index 426724eb..a708f749 100644
--- a/src/components/floor-plan/modal/basic/step/Module.jsx
+++ b/src/components/floor-plan/modal/basic/step/Module.jsx
@@ -235,11 +235,23 @@ export default function Module({ setTabNum }) {
- setInputVerticalSnowCover(normalizeDecimal(e.target.value))}*/}
+ {/*/>*/}
+ setInputVerticalSnowCover(normalizeDecimal(e.target.value))}
+ onChange={(value) => setInputVerticalSnowCover(value)}
+ options={{
+ allowNegative: false,
+ allowDecimal: false
+ }}
/>
cm
diff --git a/src/components/floor-plan/modal/basic/step/Orientation.jsx b/src/components/floor-plan/modal/basic/step/Orientation.jsx
index fdf599be..4feeb41b 100644
--- a/src/components/floor-plan/modal/basic/step/Orientation.jsx
+++ b/src/components/floor-plan/modal/basic/step/Orientation.jsx
@@ -638,7 +638,7 @@ export const Orientation = forwardRef((props, ref) => {
name=""
label=""
className="input-origin block"
- value={inputInstallHeight}
+ value={inputVerticalSnowCover}
onChange={(value) => handleChangeVerticalSnowCover(value)}
options={{
allowNegative: false,
diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx
index dfcc547c..cc9d71ea 100644
--- a/src/components/management/StuffDetail.jsx
+++ b/src/components/management/StuffDetail.jsx
@@ -2125,12 +2125,12 @@ export default function StuffDetail() {
{/* {...register('verticalSnowCover')}*/}
{/*/>*/}
{}}
+ onChange={(value) => form.setValue('verticalSnowCover', value)}
options={{
allowNegative: false,
allowDecimal: false
@@ -2197,12 +2197,12 @@ export default function StuffDetail() {
{/* {...register('installHeight')}*/}
{/*/>*/}
{}}
+ onChange={(value) => form.setValue('installHeight', value)}
options={{
allowNegative: false,
allowDecimal: false
@@ -2721,12 +2721,12 @@ export default function StuffDetail() {
{/* {...register('verticalSnowCover')}*/}
{/*/>*/}
{}}
+ onChange={(value) => form.setValue('verticalSnowCover', value)}
options={{
allowNegative: false,
allowDecimal: false
@@ -2797,12 +2797,12 @@ export default function StuffDetail() {
{/*/>*/}
{}}
+ onChange={(value) => form.setValue('installHeight', value)}
options={{
allowNegative: false,
allowDecimal: false
diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js
index 93b78a62..3811e438 100644
--- a/src/util/qpolygon-utils.js
+++ b/src/util/qpolygon-utils.js
@@ -4848,6 +4848,9 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
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) }
+ const midX = (baseLine.x1 + baseLine.x2) / 2
+ const midY = (baseLine.y1 + baseLine.y2) / 2
+ const checkPoint = { x: midX + nextLineVector.x, y: midY + nextLineVector.y }
//반절마루 생성불가이므로 지붕선 분기를 해야하는지 확인 후 처리.
if (
prevLineVector.x === nextLineVector.x &&
@@ -4855,198 +4858,408 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
baseLine.attributes.type === LINE_TYPE.WALLLINE.EAVES &&
(prevLine.attributes.type === LINE_TYPE.WALLLINE.GABLE || nextLine.attributes.type === LINE_TYPE.WALLLINE.GABLE)
) {
- downRoofGable.push({ currLine: baseLine, currIndex: index })
+ downRoofGable.push({ currLine: baseLine, currIndex: index, type: 'A' })
+ }
+
+ if (
+ (prevLineVector.x !== nextLineVector.x || prevLineVector.y !== nextLineVector.y) &&
+ checkWallPolygon.inPolygon(checkPoint) &&
+ prevLine.attributes.type === LINE_TYPE.WALLLINE.GABLE &&
+ nextLine.attributes.type === LINE_TYPE.WALLLINE.GABLE
+ ) {
+ downRoofGable.push({ currLine: baseLine, currIndex: index, type: 'B' })
}
})
const downRoofLines = [] // 하단지붕 파생 라인 처리후 innerLines에 추가.
- downRoofGable.forEach(({ currLine, currIndex }) => {
- // 라인의 방향
- const currVector = { x: Math.sign(clamp01(currLine.x1 - currLine.x2)), y: Math.sign(clamp01(currLine.y1 - currLine.y2)) }
+ //A타입 하단 지붕 prevLine과 nextLine이 같은 방향으로 가는 경우
+ downRoofGable
+ .filter((l) => l.type === 'A')
+ .forEach(({ currLine, currIndex }) => {
+ // 라인의 방향
+ const currVector = { x: Math.sign(clamp01(currLine.x1 - currLine.x2)), y: Math.sign(clamp01(currLine.y1 - currLine.y2)) }
- //어느쪽이 기준인지 확인.
- //대각선 제외
- if (currVector.x !== 0 && currVector.y !== 0) return
+ //어느쪽이 기준인지 확인.
+ //대각선 제외
+ if (currVector.x !== 0 && currVector.y !== 0) return
- const prevLine = baseLines[(currIndex - 1 + baseLines.length) % baseLines.length]
- const nextLine = baseLines[(currIndex + 1) % baseLines.length]
+ const prevLine = baseLines[(currIndex - 1 + baseLines.length) % baseLines.length]
+ const nextLine = baseLines[(currIndex + 1) % baseLines.length]
- const prevVector = { x: Math.sign(clamp01(prevLine.x1 - prevLine.x2)), y: Math.sign(clamp01(prevLine.y1 - prevLine.y2)) }
- const nextVector = { x: Math.sign(clamp01(nextLine.x1 - nextLine.x2)), y: Math.sign(clamp01(nextLine.y1 - nextLine.y2)) }
+ const prevVector = { x: Math.sign(clamp01(prevLine.x1 - prevLine.x2)), y: Math.sign(clamp01(prevLine.y1 - prevLine.y2)) }
+ const nextVector = { x: Math.sign(clamp01(nextLine.x1 - nextLine.x2)), y: Math.sign(clamp01(nextLine.y1 - nextLine.y2)) }
- let gableLine
- //가로선
- if (currVector.y === 0) {
- if (currVector.x === 1) {
- if (prevVector.y === 1 && nextVector.y === 1) {
- gableLine = nextLine
+ let gableLine
+ //가로선
+ if (currVector.y === 0) {
+ if (currVector.x === 1) {
+ if (prevVector.y === 1 && nextVector.y === 1) {
+ gableLine = nextLine
+ }
+ if (prevVector.y === -1 && nextVector.y === -1) {
+ gableLine = prevLine
+ }
}
- if (prevVector.y === -1 && nextVector.y === -1) {
- gableLine = prevLine
+ if (currVector.x === -1) {
+ if (prevVector.y === 1 && nextVector.y === 1) {
+ gableLine = prevLine
+ }
+ if (prevVector.y === -1 && nextVector.y === -1) {
+ gableLine = nextLine
+ }
}
}
- if (currVector.x === -1) {
- if (prevVector.y === 1 && nextVector.y === 1) {
- gableLine = prevLine
+
+ //세로선
+ if (currVector.x === 0) {
+ if (currVector.y === 1) {
+ if (prevVector.x === 1 && nextVector.x === 1) {
+ gableLine = prevLine
+ }
+ if (prevVector.x === -1 && nextVector.x === -1) {
+ gableLine = nextLine
+ }
}
- if (prevVector.y === -1 && nextVector.y === -1) {
- gableLine = nextLine
+ if (currVector.y === -1) {
+ if (prevVector.x === 1 && nextVector.x === 1) {
+ gableLine = nextLine
+ }
+ if (prevVector.x === -1 && nextVector.x === -1) {
+ gableLine = prevLine
+ }
}
}
- }
- //세로선
- if (currVector.x === 0) {
- if (currVector.y === 1) {
- if (prevVector.x === 1 && nextVector.x === 1) {
- gableLine = prevLine
- }
- if (prevVector.x === -1 && nextVector.x === -1) {
- gableLine = nextLine
- }
+ //기준점
+ let stdPoint = []
+ //반대쪽 라인을 찾기위한 vector
+ let oppFindVector
+ if (gableLine === prevLine) {
+ stdPoint.push(currLine.x1, currLine.y1)
+ stdPoint.push(currLine.x2 + -currVector.x * nextLine.attributes.offset, currLine.y2 + -currVector.y * nextLine.attributes.offset)
+ oppFindVector = { x: Math.sign(clamp01(nextLine.x2 - nextLine.x1)), y: Math.sign(clamp01(nextLine.y2 - nextLine.y1)) }
+ } else {
+ stdPoint.push(currLine.x2, currLine.y2)
+ stdPoint.push(currLine.x1 + currVector.x * prevLine.attributes.offset, currLine.y1 + currVector.y * prevLine.attributes.offset)
+ oppFindVector = { x: Math.sign(clamp01(prevLine.x1 - prevLine.x2)), y: Math.sign(clamp01(prevLine.y1 - prevLine.y2)) }
}
- if (currVector.y === -1) {
- if (prevVector.x === 1 && nextVector.x === 1) {
- gableLine = nextLine
- }
- if (prevVector.x === -1 && nextVector.x === -1) {
- gableLine = prevLine
- }
- }
- }
- //기준점
- let stdPoint = []
- //반대쪽 라인을 찾기위한 vector
- let oppFindVector
- if (gableLine === prevLine) {
- stdPoint.push(currLine.x1, currLine.y1)
- stdPoint.push(currLine.x2 + -currVector.x * nextLine.attributes.offset, currLine.y2 + -currVector.y * nextLine.attributes.offset)
- oppFindVector = { x: Math.sign(clamp01(nextLine.x2 - nextLine.x1)), y: Math.sign(clamp01(nextLine.y2 - nextLine.y1)) }
- } else {
- stdPoint.push(currLine.x2, currLine.y2)
- stdPoint.push(currLine.x1 + currVector.x * prevLine.attributes.offset, currLine.y1 + currVector.y * prevLine.attributes.offset)
- oppFindVector = { x: Math.sign(clamp01(prevLine.x1 - prevLine.x2)), y: Math.sign(clamp01(prevLine.y1 - prevLine.y2)) }
- }
-
- //반대쪽 라인들 (마루선을 위함)
- const oppLines = baseLines.filter((line) => {
- const lineVector = { x: Math.sign(clamp01(line.x1 - line.x2)), y: Math.sign(clamp01(line.y1 - line.y2)) }
- const oppVector =
- lineVector.x === 0 ? { x: Math.sign(clamp01(line.x1 - stdPoint[0])), y: 0 } : { x: 0, y: Math.sign(clamp01(line.y1 - stdPoint[1])) }
-
- const rightDirection =
- (currVector.x === lineVector.x && currVector.y !== lineVector.y) || (currVector.x !== lineVector.x && currVector.y === lineVector.y)
- const rightOpp = oppFindVector.x === oppVector.x && oppFindVector.y === oppVector.y
- return rightDirection && rightOpp
- })
-
- const innerRidge = innerLines
- .filter((line) => line.name === LINE_TYPE.SUBLINE.RIDGE)
- .filter((line) => {
+ //반대쪽 라인들 (마루선을 위함)
+ const oppLines = baseLines.filter((line) => {
const lineVector = { x: Math.sign(clamp01(line.x1 - line.x2)), y: Math.sign(clamp01(line.y1 - line.y2)) }
- //마루선을 찾는다.
- if ((currVector.x === 0 && lineVector.x === 0) || (currVector.y === 0 && lineVector.y === 0)) {
- //세로선
- if (lineVector.x === 0) {
- const minY = Math.min(line.y1, line.y2)
- const maxY = Math.max(line.y1, line.y2)
- // 기준 라인 안에 들어있는 경우에만 처리.
- if (
- Math.min(stdPoint[1], stdPoint[3]) <= minY &&
- maxY <= Math.max(stdPoint[1], stdPoint[3]) &&
- Math.min(stdPoint[0], ...oppLines.map((line) => line.x1)) <= line.x1 &&
- line.x1 <= Math.max(stdPoint[0], ...oppLines.map((line) => line.x1))
- ) {
- return true
+ const oppVector =
+ lineVector.x === 0 ? { x: Math.sign(clamp01(line.x1 - stdPoint[0])), y: 0 } : { x: 0, y: Math.sign(clamp01(line.y1 - stdPoint[1])) }
+
+ const rightDirection =
+ (currVector.x === lineVector.x && currVector.y !== lineVector.y) || (currVector.x !== lineVector.x && currVector.y === lineVector.y)
+ const rightOpp = oppFindVector.x === oppVector.x && oppFindVector.y === oppVector.y
+ return rightDirection && rightOpp
+ })
+
+ const innerRidge = innerLines
+ .filter((line) => line.name === LINE_TYPE.SUBLINE.RIDGE)
+ .filter((line) => {
+ const lineVector = { x: Math.sign(clamp01(line.x1 - line.x2)), y: Math.sign(clamp01(line.y1 - line.y2)) }
+ //마루선을 찾는다.
+ if ((currVector.x === 0 && lineVector.x === 0) || (currVector.y === 0 && lineVector.y === 0)) {
+ //세로선
+ if (lineVector.x === 0) {
+ const minY = Math.min(line.y1, line.y2)
+ const maxY = Math.max(line.y1, line.y2)
+ // 기준 라인 안에 들어있는 경우에만 처리.
+ if (
+ Math.min(stdPoint[1], stdPoint[3]) <= minY &&
+ maxY <= Math.max(stdPoint[1], stdPoint[3]) &&
+ Math.min(stdPoint[0], ...oppLines.map((line) => line.x1)) <= line.x1 &&
+ line.x1 <= Math.max(stdPoint[0], ...oppLines.map((line) => line.x1))
+ ) {
+ return true
+ }
+ }
+ //가로선
+ if (lineVector.y === 0) {
+ const minX = Math.min(line.x1, line.x2)
+ const maxX = Math.max(line.x1, line.x2)
+ // 기준 라인 안에 들어있는 경우에만 처리
+ if (
+ Math.min(stdPoint[0], stdPoint[2]) <= minX &&
+ maxX <= Math.max(stdPoint[0], stdPoint[2]) &&
+ Math.min(stdPoint[1], ...oppLines.map((line) => line.y1)) <= line.y1 &&
+ line.y1 <= Math.max(stdPoint[1], ...oppLines.map((line) => line.y1))
+ ) {
+ return true
+ }
}
}
- //가로선
- if (lineVector.y === 0) {
- const minX = Math.min(line.x1, line.x2)
- const maxX = Math.max(line.x1, line.x2)
- // 기준 라인 안에 들어있는 경우에만 처리
- if (
- Math.min(stdPoint[0], stdPoint[2]) <= minX &&
- maxX <= Math.max(stdPoint[0], stdPoint[2]) &&
- Math.min(stdPoint[1], ...oppLines.map((line) => line.y1)) <= line.y1 &&
- line.y1 <= Math.max(stdPoint[1], ...oppLines.map((line) => line.y1))
- ) {
- return true
+ })
+
+ //1. 현재 라인을 기준으로 지붕선 추가.
+ //1-1 stdPoint을 현재라인의 지붕 출폭 만큼 조정
+ const currOffset = currLine.attributes.offset
+ const noGableLine = gableLine === prevLine ? nextLine : prevLine
+
+ let roofLinePoint = stdPoint
+ if (currVector.x === 0) {
+ //세로일때
+ //x축 조정
+ roofLinePoint[0] = roofLinePoint[0] + currVector.y * currOffset
+ roofLinePoint[2] = roofLinePoint[2] + currVector.y * currOffset
+ } else if (currVector.y === 0) {
+ //가로일때
+ //y축 조정
+ roofLinePoint[1] = roofLinePoint[1] - currVector.x * currOffset
+ roofLinePoint[3] = roofLinePoint[3] - currVector.x * currOffset
+ }
+
+ //지붕선추가.
+ downRoofLines.push(drawRoofLine(roofLinePoint, canvas, roof, textMode))
+
+ //1-2 지붕선에서 oppLine으로 향하는 중 가장 가까운 마루선까지의 연결선 생성
+ const findRidgeEdge = {
+ vertex1: { x: roofLinePoint[0], y: roofLinePoint[1] },
+ vertex2: { x: roofLinePoint[0] + oppFindVector.x, y: roofLinePoint[1] + oppFindVector.y },
+ }
+ let minDistance = Infinity
+ let minPoint
+ let isLine
+ innerRidge.forEach((line) => {
+ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
+ const intersect = edgesIntersection(lineEdge, findRidgeEdge)
+ if (intersect) {
+ let distance = Infinity
+ if (currVector.x === 0) {
+ const lineDistance1 = Math.abs(line.y1 - roofLinePoint[1])
+ const lineDistance2 = Math.abs(line.y2 - roofLinePoint[1])
+ distance = Math.min(lineDistance1, lineDistance2)
+ } else if (currVector.y === 0) {
+ const lineDistance1 = Math.abs(line.x1 - roofLinePoint[0])
+ const lineDistance2 = Math.abs(line.x2 - roofLinePoint[0])
+ distance = Math.min(lineDistance1, lineDistance2)
+ }
+ if (distance < minDistance) {
+ minDistance = distance
+ minPoint = intersect
+ isLine = line
+ }
+ }
+ })
+ if (minPoint) {
+ const hipPoint = [roofLinePoint[0], roofLinePoint[1], minPoint.x, minPoint.y]
+ downRoofLines.push(
+ drawHipLine(hipPoint, canvas, roof, textMode, null, getDegreeByChon(currLine.attributes.pitch), getDegreeByChon(currLine.attributes.pitch)),
+ )
+
+ if (isLine) {
+ const newRidgePoint = [minPoint.x, minPoint.y]
+ const distance1 = Math.sqrt(Math.pow(minPoint.x - isLine.x1, 2) + Math.pow(minPoint.y - isLine.y1, 2))
+ const distance2 = Math.sqrt(Math.pow(minPoint.x - isLine.x2, 2) + Math.pow(minPoint.y - isLine.y2, 2))
+ if (distance2 < distance1) {
+ newRidgePoint.push(isLine.x1, isLine.y1)
+ } else {
+ newRidgePoint.push(isLine.x2, isLine.y2)
+ }
+ downRoofLines.push(drawRoofLine(newRidgePoint, canvas, roof, textMode))
+ }
+ }
+ })
+
+ // B타입 하단지붕 prevLine과 nextLine의 방향이 반대인데 현재 라인이 지붕 안쪽으로 들어가는 모양.
+ downRoofGable
+ .filter((l) => l.type === 'B')
+ .forEach(({ currLine, currIndex }) => {
+ const checkLine = new fabric.Line([currLine.x1, currLine.y1, currLine.x2, currLine.y2], {
+ stroke: 'red',
+ strokeWidth: 4,
+ parentId: roofId,
+ name: 'check',
+ })
+ canvas.add(checkLine).renderAll()
+
+ // 라인의 방향
+ const currVector = { x: Math.sign(clamp01(currLine.x1 - currLine.x2)), y: Math.sign(clamp01(currLine.y1 - currLine.y2)) }
+
+ //어느쪽이 기준인지 확인.
+ //대각선 제외
+ if (currVector.x !== 0 && currVector.y !== 0) return
+
+ const prevLine = baseLines[(currIndex - 1 + baseLines.length) % baseLines.length]
+ const nextLine = baseLines[(currIndex + 1) % baseLines.length]
+
+ const prevVector = { x: Math.sign(clamp01(prevLine.x1 - prevLine.x2)), y: Math.sign(clamp01(prevLine.y1 - prevLine.y2)) }
+ const nextVector = { x: Math.sign(clamp01(nextLine.x1 - nextLine.x2)), y: Math.sign(clamp01(nextLine.y1 - nextLine.y2)) }
+
+ const minX = Math.min(currLine.x1, currLine.x2)
+ const maxX = Math.max(currLine.x1, currLine.x2)
+ const minY = Math.min(currLine.y1, currLine.y2)
+ const maxY = Math.max(currLine.y1, currLine.y2)
+ const midX = (currLine.x1 + currLine.x2) / 2
+ const midY = (currLine.y1 + currLine.y2) / 2
+ let ridgeFindVector = { x: nextVector.x, y: nextVector.y }
+ if (!checkWallPolygon.inPolygon({ x: midX, y: midY })) {
+ ridgeFindVector = { x: prevVector.x, y: prevVector.y }
+ }
+
+ // 마루를 따라 생성되어야 하는 지붕선 추가.
+ const oppLines = innerLines
+ .filter((l) => l.name === LINE_TYPE.SUBLINE.RIDGE)
+ .filter((line) => {
+ const lineVector = { x: Math.sign(clamp01(line.x1 - line.x2)), y: Math.sign(clamp01(line.y1 - line.y2)) }
+ let oppVector
+ if (currVector.x === 0) {
+ if (currVector.y === 1) {
+ oppVector = { x: Math.sign(clamp01(currLine.x1 - line.x1)), y: 0 }
+ } else if (currVector.y === -1) {
+ oppVector = { x: Math.sign(clamp01(line.x1 - currLine.x1)), y: 0 }
}
+ } else if (currVector.y === 0) {
+ if (currVector.x === 1) {
+ oppVector = { x: 0, y: Math.sign(clamp01(line.y1 - currLine.y1)) }
+ } else if (currVector.x === -1) {
+ oppVector = { x: 0, y: Math.sign(clamp01(currLine.y1 - line.y1)) }
+ }
+ }
+
+ 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)
+
+ const isInside = lineVector.y === 0 ? minX <= lineMinX && lineMaxX <= maxX : minY <= lineMinY && lineMaxY <= maxY
+
+ const rightOpp = ridgeFindVector.x === oppVector.x && ridgeFindVector.y === oppVector.y
+ return rightOpp && isInside
+ })
+
+ // 현재 라인의 지붕선 추가.
+ const currOffset = currLine.attributes.offset
+ const roofPoint = [
+ currLine.x1 + -nextVector.x * currOffset,
+ currLine.y1 + -nextVector.y * currOffset,
+ currLine.x2 + -nextVector.x * currOffset,
+ currLine.y2 + -nextVector.y * currOffset,
+ ]
+ downRoofLines.push(drawRoofLine(roofPoint, canvas, roof, textMode))
+
+ // 현재 라인 좌표의 시작과 끝 포인트에서 직교하는 포인트와 라인을 찾는다
+ let orthogonalStartPoint,
+ orthogonalStartDistance = Infinity,
+ orthogonalStartLine
+ let orthogonalEndPoint,
+ orthogonalEndDistance = Infinity,
+ orthogonalEndLine
+ oppLines.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()
+
+ if (currVector.x === 0) {
+ //세로선
+ // 시작포인트와 가까운 포인트의 길이
+ const lineStartDist =
+ Math.abs(currLine.y1 - line.y1) < Math.abs(currLine.y1 - line.y2) ? Math.abs(currLine.y1 - line.y1) : Math.abs(currLine.y1 - line.y2)
+ const lineStartPoint =
+ Math.abs(currLine.y1 - line.y1) < Math.abs(currLine.y1 - line.y2) ? { x: line.x1, y: currLine.y1 } : { x: line.x2, y: currLine.y1 }
+ if (lineStartDist < orthogonalStartDistance) {
+ orthogonalStartDistance = lineStartDist
+ orthogonalStartPoint = lineStartPoint
+ orthogonalStartLine = line
+ }
+ // 종료포인트와 가까운 포인트의 길이
+ const lineEndDist =
+ Math.abs(currLine.y2 - line.y1) < Math.abs(currLine.y2 - line.y2) ? Math.abs(currLine.y2 - line.y2) : Math.abs(currLine.y2 - line.y1)
+ const lineEndPoint =
+ Math.abs(currLine.y2 - line.y1) < Math.abs(currLine.y2 - line.y2) ? { x: line.x2, y: currLine.y2 } : { x: line.x1, y: currLine.y2 }
+ if (lineEndDist < orthogonalEndDistance) {
+ orthogonalEndDistance = lineEndDist
+ orthogonalEndPoint = lineEndPoint
+ orthogonalEndLine = line
+ }
+ } else if (currVector.y === 0) {
+ //가로선
+ // 시작포인트와 가까운 포인트의 길이
+ const lineStartDist =
+ Math.abs(currLine.x1 - line.x1) < Math.abs(currLine.x1 - line.x2) ? Math.abs(currLine.x1 - line.x1) : Math.abs(currLine.x1 - line.x2)
+ const lineStartPoint =
+ Math.abs(currLine.x1 - line.x1) < Math.abs(currLine.x1 - line.x2) ? { x: currLine.x1, y: line.y1 } : { x: currLine.x1, y: line.y2 }
+ if (lineStartDist < orthogonalStartDistance) {
+ orthogonalStartDistance = lineStartDist
+ orthogonalStartPoint = lineStartPoint
+ orthogonalStartLine = line
+ }
+ //종료포인트와 가까운 포인트의 길이
+ const lineEndDist =
+ Math.abs(currLine.x2 - line.x1) < Math.abs(currLine.x2 - line.x2) ? Math.abs(currLine.x2 - line.x1) : Math.abs(currLine.x2 - line.x2)
+ const lineEndPoint =
+ Math.abs(currLine.x2 - line.x1) < Math.abs(currLine.x2 - line.x2) ? { x: currLine.x2, y: line.y1 } : { x: currLine.x2, y: line.y2 }
+ if (lineEndDist < orthogonalEndDistance) {
+ orthogonalEndDistance = lineEndDist
+ orthogonalEndPoint = lineEndPoint
+ orthogonalEndLine = line
}
}
})
- //1. 현재 라인을 기준으로 지붕선 추가.
- //1-1 stdPoint을 현재라인의 지붕 출폭 만큼 조정
- const currOffset = currLine.attributes.offset
- const noGableLine = gableLine === prevLine ? nextLine : prevLine
+ //직교 라인이 있는 경우
+ if (orthogonalStartLine !== undefined && orthogonalEndLine !== undefined) {
+ if (orthogonalStartLine === orthogonalEndLine) {
+ //직교 라인이 1개일때 처리
+ downRoofLines.push(
+ drawRoofLine([orthogonalStartPoint.x, orthogonalStartPoint.y, orthogonalEndPoint.x, orthogonalEndPoint.y], canvas, roof, textMode),
+ )
+ } else {
+ //직교 라인이 2개일때 처리
+ // 시작 라인 처리
+ const startDist1 = Math.sqrt(
+ Math.pow(orthogonalStartPoint.x - orthogonalStartLine.x1, 2) + Math.pow(orthogonalStartPoint.y - orthogonalStartLine.y1, 2),
+ )
+ const startDist2 = Math.sqrt(
+ Math.pow(orthogonalStartPoint.x - orthogonalStartLine.x2, 2) + Math.pow(orthogonalStartPoint.y - orthogonalStartLine.y2, 2),
+ )
+ const otherStartPoint =
+ startDist1 > startDist2
+ ? { x: orthogonalStartLine.x1, y: orthogonalStartLine.y1 }
+ : { x: orthogonalStartLine.x2, y: orthogonalStartLine.y2 }
+ downRoofLines.push(
+ drawRoofLine([orthogonalStartPoint.x, orthogonalStartPoint.y, otherStartPoint.x, otherStartPoint.y], canvas, roof, textMode),
+ )
- let roofLinePoint = stdPoint
- if (currVector.x === 0) {
- //세로일때
- //x축 조정
- roofLinePoint[0] = roofLinePoint[0] + currVector.y * currOffset
- roofLinePoint[2] = roofLinePoint[2] + currVector.y * currOffset
- } else if (currVector.y === 0) {
- //가로일때
- //y축 조정
- roofLinePoint[1] = roofLinePoint[1] - currVector.x * currOffset
- roofLinePoint[3] = roofLinePoint[3] - currVector.x * currOffset
- }
-
- //지붕선추가.
- downRoofLines.push(drawRoofLine(roofLinePoint, canvas, roof, textMode))
-
- //1-2 지붕선에서 oppLine으로 향하는 중 가장 가까운 마루선까지의 연결선 생성
- const findRidgeEdge = {
- vertex1: { x: roofLinePoint[0], y: roofLinePoint[1] },
- vertex2: { x: roofLinePoint[0] + oppFindVector.x, y: roofLinePoint[1] + oppFindVector.y },
- }
- let minDistance = Infinity
- let minPoint
- let isLine
- innerRidge.forEach((line) => {
- const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
- const intersect = edgesIntersection(lineEdge, findRidgeEdge)
- if (intersect) {
- let distance = Infinity
- if (currVector.x === 0) {
- const lineDistance1 = Math.abs(line.y1 - roofLinePoint[1])
- const lineDistance2 = Math.abs(line.y2 - roofLinePoint[1])
- distance = Math.min(lineDistance1, lineDistance2)
- } else if (currVector.y === 0) {
- const lineDistance1 = Math.abs(line.x1 - roofLinePoint[0])
- const lineDistance2 = Math.abs(line.x2 - roofLinePoint[0])
- distance = Math.min(lineDistance1, lineDistance2)
- }
- if (distance < minDistance) {
- minDistance = distance
- minPoint = intersect
- isLine = line
+ const endDist1 = Math.sqrt(
+ Math.pow(orthogonalEndPoint.x - orthogonalEndLine.x1, 2) + Math.pow(orthogonalEndPoint.y - orthogonalEndLine.y1, 2),
+ )
+ const endDist2 = Math.sqrt(
+ Math.pow(orthogonalEndPoint.x - orthogonalEndLine.x2, 2) + Math.pow(orthogonalEndPoint.y - orthogonalEndLine.y2, 2),
+ )
+ const otherEndPoint =
+ endDist1 > endDist2 ? { x: orthogonalEndLine.x1, y: orthogonalEndLine.y1 } : { x: orthogonalEndLine.x2, y: orthogonalEndLine.y2 }
+ downRoofLines.push(drawRoofLine([orthogonalEndPoint.x, orthogonalEndPoint.y, otherEndPoint.x, otherEndPoint.y], canvas, roof, textMode))
}
+
+ //지붕선(roofPoint)에서 직교포인트까지 연결하는 라인을 추가한다.
+ const orthogonalPoint1 = [roofPoint[0], roofPoint[1], orthogonalStartPoint.x, orthogonalStartPoint.y]
+ const orthogonalPoint2 = [roofPoint[2], roofPoint[3], orthogonalEndPoint.x, orthogonalEndPoint.y]
+ downRoofLines.push(
+ drawHipLine(
+ orthogonalPoint1,
+ canvas,
+ roof,
+ textMode,
+ null,
+ getDegreeByChon(currLine.attributes.pitch),
+ getDegreeByChon(currLine.attributes.pitch),
+ ),
+ )
+ downRoofLines.push(
+ drawHipLine(
+ orthogonalPoint2,
+ canvas,
+ roof,
+ textMode,
+ null,
+ getDegreeByChon(currLine.attributes.pitch),
+ getDegreeByChon(currLine.attributes.pitch),
+ ),
+ )
}
})
- if (minPoint) {
- const hipPoint = [roofLinePoint[0], roofLinePoint[1], minPoint.x, minPoint.y]
- downRoofLines.push(
- drawHipLine(hipPoint, canvas, roof, textMode, null, getDegreeByChon(currLine.attributes.pitch), getDegreeByChon(currLine.attributes.pitch)),
- )
-
- if (isLine) {
- const newRidgePoint = [minPoint.x, minPoint.y]
- const distance1 = Math.sqrt(Math.pow(minPoint.x - isLine.x1, 2) + Math.pow(minPoint.y - isLine.y1, 2))
- const distance2 = Math.sqrt(Math.pow(minPoint.x - isLine.x2, 2) + Math.pow(minPoint.y - isLine.y2, 2))
- if (distance2 < distance1) {
- newRidgePoint.push(isLine.x1, isLine.y1)
- } else {
- newRidgePoint.push(isLine.x2, isLine.y2)
- }
- downRoofLines.push(drawRoofLine(newRidgePoint, canvas, roof, textMode))
- }
- }
- })
//추가된 하단 지붕 라인 innerLines에 추가.
innerLines.push(...downRoofLines)
@@ -5107,7 +5320,13 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
}
startPoint = point
}
- innerLines.push(drawHipLine([startPoint.x, startPoint.y, currentLine.x2, currentLine.y2], canvas, roof, textMode, null, nextDegree, nextDegree))
+ if (splitPoint.length === 1) {
+ innerLines.push(drawRoofLine([startPoint.x, startPoint.y, currentLine.x2, currentLine.y2], canvas, roof, textMode))
+ } else {
+ innerLines.push(
+ drawHipLine([startPoint.x, startPoint.y, currentLine.x2, currentLine.y2], canvas, roof, textMode, null, nextDegree, nextDegree),
+ )
+ }
} else {
innerLines.push(drawRoofLine([currentLine.x1, currentLine.y1, currentLine.x2, currentLine.y2], canvas, roof, textMode))
}