Merge branch 'dev' into dev-ds

This commit is contained in:
Daseul Kim 2024-10-15 13:11:51 +09:00
commit 6b8e68e41b
15 changed files with 367 additions and 98 deletions

View File

@ -49,7 +49,7 @@ export default function AuxiliaryDrawing({ setShowAuxiliaryModal }) {
handleFix,
buttonAct,
setButtonAct,
} = useAuxiliaryDrawing()
} = useAuxiliaryDrawing(setShowAuxiliaryModal)
const outerLineProps = {
length1,

View File

@ -10,7 +10,7 @@ import { useEavesGableEdit } from '@/hooks/roofcover/useEavesGableEdit'
export default function EavesGableEdit({ setShowEavesGableEditModal }) {
const { getMessage } = useMessage()
const { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef } = useEavesGableEdit()
const { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef } = useEavesGableEdit(setShowEavesGableEditModal)
const eavesProps = {
pitchRef,
offsetRef,

View File

@ -6,7 +6,7 @@ export default function PropertiesSetting(props) {
const { getMessage } = useMessage()
const { setShowPropertiesSettingModal } = props
const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting()
const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting(setShowPropertiesSettingModal)
return (
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>

View File

@ -39,7 +39,7 @@ export default function WallLineSetting(props) {
outerLineDiagonalLengthRef,
handleRollback,
handleFix,
} = useOuterLineWall()
} = useOuterLineWall(setShowOutlineModal)
const outerLineProps = {
length1,
@ -171,7 +171,7 @@ export default function WallLineSetting(props) {
<button
className="btn-frame modal act"
onClick={() => {
handleFix(setShowOutlineModal)
handleFix()
setShowPropertiesSettingModal(true)
}}
>

View File

@ -2,76 +2,12 @@ import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useState } from 'react'
import QSelectBox from '@/components/common/select/QSelectBox'
import { useRoofAllocationSetting } from '@/hooks/roofcover/useRoofAllocationSetting'
export default function RoofAllocationSetting({ setShowRoofAllocationSettingModal }) {
const { getMessage } = useMessage()
const [selectedRoofMaterial, setSelectedRoofMaterial] = useState(null)
const [values, setValues] = useState([
{
id: '1',
type: 'A',
roofMaterial: { name: '기와1' },
width: { name: '200' },
length: { name: '250' },
rafter: { name: '300' },
alignType: 'stairs',
},
])
const roofMaterials = [
{
id: 'A',
name: '기와1',
type: 'A',
width: '200',
length: '200',
alignType: 'parallel',
},
{
id: 'B',
name: '기와2',
type: 'B',
rafter: '200',
alignType: 'parallel',
},
{
id: 'C',
name: '기와3',
type: 'C',
hajebichi: '200',
alignType: 'stairs',
},
{
id: 'D',
name: '기와4',
type: 'D',
length: '200',
alignType: 'stairs',
},
]
const widths = [
{ name: '200', id: 'q' },
{ name: '250', id: 'q1' },
{ name: '300', id: 'q2' },
]
const lengths = [
{ name: '200', id: 'w' },
{ name: '250', id: 'w1' },
{ name: '300', id: 'w2' },
]
const rafters = [
{ name: '200', id: 'e' },
{ name: '250', id: 'e1' },
{ name: '300', id: 'e2' },
]
const onAddRoofMaterial = () => {
setValues([...values, selectedRoofMaterial])
}
const onDeleteRoofMaterial = (id) => {
setValues(values.filter((value) => value.id !== id))
}
const { handleSave, onAddRoofMaterial, onDeleteRoofMaterial, values, roofMaterials, selectedRoofMaterial, setSelectedRoofMaterial } =
useRoofAllocationSetting(setShowRoofAllocationSettingModal)
return (
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
@ -103,7 +39,7 @@ export default function RoofAllocationSetting({ setShowRoofAllocationSettingModa
{values.map((value, index) => (
<div className="grid-option-box" key={index}>
<div className="d-check-radio pop no-text">
<input type="radio" name="radio01" id="ra01" />
<input type="radio" name="radio01" />
<label htmlFor="ra01"></label>
</div>
<div className="grid-option-block-form">
@ -213,7 +149,9 @@ export default function RoofAllocationSetting({ setShowRoofAllocationSettingModa
))}
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">{getMessage('modal.roof.alloc.apply')}</button>
<button className="btn-frame modal act" onClick={handleSave}>
{getMessage('modal.roof.alloc.apply')}
</button>
</div>
</div>
</div>

View File

@ -7,7 +7,8 @@ import { useMessage } from '@/hooks/useMessage'
import { useRoofShapePassivitySetting } from '@/hooks/roofcover/useRoofShapePassivitySetting'
export default function RoofShapePassivitySetting({ setShowRoofShapePassivitySettingModal }) {
const { handleSave, handleConfirm, handleRollback, buttons, type, setType, TYPES, offsetRef, pitchRef } = useRoofShapePassivitySetting()
const { handleSave, handleConfirm, handleRollback, buttons, type, setType, TYPES, offsetRef, pitchRef } =
useRoofShapePassivitySetting(setShowRoofShapePassivitySettingModal)
const { getMessage } = useMessage()
const eavesProps = {

View File

@ -37,7 +37,7 @@ export default function RoofShapeSetting({ setShowRoofShapeSettingModal }) {
buttonMenu,
handleConfirm,
handleRollBack,
} = useRoofShapeSetting()
} = useRoofShapeSetting(setShowRoofShapeSettingModal)
const ridgeProps = { pitch, setPitch, eavesOffset, setEavesOffset }
const patternProps = { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset }

View File

@ -28,7 +28,7 @@ import { fabric } from 'fabric'
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
// 보조선 작성
export function useAuxiliaryDrawing() {
export function useAuxiliaryDrawing(setShowAuxiliaryModal) {
const canvas = useRecoilValue(canvasState)
const { addCanvasMouseEventListener, addDocumentEventListener, removeMouseLine, initEvent } = useEvent()
const { getIntersectMousePoint } = useMouse()
@ -613,11 +613,15 @@ export function useAuxiliaryDrawing() {
addCanvasMouseEventListener('mouse:move', mouseMove)
}
const handleFix = (fn) => {
const handleFix = () => {
if (!confirm('지붕선 완료하시겠습니까?')) {
return
}
fn(close)
const roofBases = canvas.getObjects().find((obj) => obj.name === 'roofBase')
roofBases.innerLines = [...lineHistory.current]
setShowAuxiliaryModal(close)
}
return {

View File

@ -31,7 +31,7 @@ import { calculateAngle } from '@/util/qpolygon-utils'
import { fabric } from 'fabric'
//외벽선 그리기
export function useOuterLineWall() {
export function useOuterLineWall(setShowOutlineModal) {
const canvas = useRecoilValue(canvasState)
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent } =
useEvent()
@ -68,8 +68,6 @@ export function useOuterLineWall() {
const isFix = useRef(false)
const closeModalFn = useRef(null)
useEffect(() => {
if (adsorptionPointAddMode || tempGridMode) {
return
@ -209,7 +207,7 @@ export function useOuterLineWall() {
removeAllMouseEventListeners()
removeAllDocumentEventListeners()
canvas?.renderAll()
closeModalFn.current(false)
setShowOutlineModal(false)
}
if (points.length < 3) {
@ -749,7 +747,7 @@ export function useOuterLineWall() {
setPoints((prev) => prev.slice(0, prev.length - 1))
}
const handleFix = (fn) => {
const handleFix = () => {
if (points.length < 3) {
return
}
@ -779,7 +777,6 @@ export function useOuterLineWall() {
})
isFix.current = true
closeModalFn.current = fn
}
return {

View File

@ -8,7 +8,7 @@ import { useLine } from '@/hooks/useLine'
import { outerLinePointsState } from '@/store/outerLineAtom'
// 외벽선 속성 설정
export function usePropertiesSetting() {
export function usePropertiesSetting(setShowPropertiesSettingModal) {
const canvas = useRecoilValue(canvasState)
const currentObject = useRecoilValue(currentObjectState)
@ -161,7 +161,7 @@ export function usePropertiesSetting() {
canvas.renderAll()
setPoints([])
fn(false)
setShowPropertiesSettingModal(false)
}
return { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal }

View File

@ -0,0 +1,127 @@
import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { useState } from 'react'
import { setSurfaceShapePattern } from '@/util/canvas-util'
import { splitPolygonWithLines } from '@/util/qpolygon-utils'
// 지붕면 할당
export function useRoofAllocationSetting(setShowRoofAllocationSettingModal) {
const canvas = useRecoilValue(canvasState)
const roofMaterials = [
{
id: 'A',
name: '기와1',
type: 'A',
width: '200',
length: '200',
alignType: 'parallel',
},
{
id: 'B',
name: '기와2',
type: 'B',
rafter: '200',
alignType: 'parallel',
},
{
id: 'C',
name: '기와3',
type: 'C',
hajebichi: '200',
alignType: 'stairs',
},
{
id: 'D',
name: '기와4',
type: 'D',
length: '200',
alignType: 'stairs',
},
]
const widths = [
{ name: '200', id: 'q' },
{ name: '250', id: 'q1' },
{ name: '300', id: 'q2' },
]
const lengths = [
{ name: '200', id: 'w' },
{ name: '250', id: 'w1' },
{ name: '300', id: 'w2' },
]
const rafters = [
{ name: '200', id: 'e' },
{ name: '250', id: 'e1' },
{ name: '300', id: 'e2' },
]
const [values, setValues] = useState([
{
id: 'A',
type: 'A',
roofMaterial: { name: '기와1' },
width: { name: '200' },
length: { name: '250' },
rafter: { name: '300' },
alignType: 'stairs',
},
])
const [radioValue, setRadioValue] = useState('A')
const [selectedRoofMaterial, setSelectedRoofMaterial] = useState(roofMaterials[0])
const onAddRoofMaterial = () => {
setValues([...values, selectedRoofMaterial])
}
const onDeleteRoofMaterial = (id) => {
setValues(values.filter((value) => value.id !== id))
}
// 선택한 지붕재로 할당
const handleSave = () => {
const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine')
roofBases.forEach((roofBase) => {
splitPolygonWithLines(roofBase)
roofBase.innerLines.forEach((line) => {
canvas.remove(line)
})
canvas.remove(roofBase)
})
wallLines.forEach((wallLine) => {
canvas.remove(wallLine)
})
const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof')
roofs.forEach((roof) => {
setSurfaceShapePattern(roof)
})
setShowRoofAllocationSettingModal(false)
}
const handleRadioOnChange = (e) => {
setRadioValue(e.target)
}
return {
handleSave,
onAddRoofMaterial,
onDeleteRoofMaterial,
handleRadioOnChange,
widths,
lengths,
rafters,
values,
roofMaterials,
selectedRoofMaterial,
setSelectedRoofMaterial,
radioValue,
setRadioValue,
}
}

View File

@ -9,7 +9,7 @@ import { useMode } from '@/hooks/useMode'
import { usePolygon } from '@/hooks/usePolygon'
//지붕형상 수동 설정
export function useRoofShapePassivitySetting() {
export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingModal) {
const TYPES = {
EAVES: 'eaves',
GABLE: 'gable',
@ -152,7 +152,7 @@ export function useRoofShapePassivitySetting() {
canvas.renderAll()
}
const handleSave = (fn) => {
const handleSave = () => {
const exceptObjs = canvas.getObjects().filter((obj) => obj.name !== 'outerLine' && obj.parent?.name !== 'outerLine')
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
exceptObjs.forEach((obj) => {
@ -169,7 +169,7 @@ export function useRoofShapePassivitySetting() {
const roof = drawRoofPolygon(wall)
canvas.renderAll()
fn(false)
setShowRoofShapePassivitySettingModal(false)
}
return { handleSave, handleConfirm, buttons, type, setType, TYPES, offsetRef, pitchRef, handleRollback }
}

View File

@ -8,7 +8,7 @@ import { useMode } from '@/hooks/useMode'
import { useLine } from '@/hooks/useLine'
// 지붕형상 설정
export function useRoofShapeSetting() {
export function useRoofShapeSetting(setShowRoofShapeSettingModal) {
const [shapeNum, setShapeNum] = useState(1)
const [buttonAct, setButtonAct] = useState(1)
const { getMessage } = useMessage()
@ -99,11 +99,7 @@ export function useRoofShapeSetting() {
{ id: 6, name: getMessage('shed') },
]
/**
*
* @param fn 모달 닫기 위한 함수
*/
const handleSave = (fn) => {
const handleSave = () => {
//기존 wallLine 삭제
let outerLines
@ -243,7 +239,7 @@ export function useRoofShapeSetting() {
canvas?.renderAll()
roof.drawHelpLine()
fn && fn(false)
setShowRoofShapeSettingModal(false)
}
const initLineSetting = () => {

View File

@ -3,6 +3,7 @@ import { useRecoilValue } from 'recoil'
import { fabric } from 'fabric'
import { getDirectionByPoint } from '@/util/canvas-util'
import { QPolygon } from '@/components/fabric/QPolygon'
import { isSamePoint } from '@/util/qpolygon-utils'
export const usePolygon = () => {
const canvas = useRecoilValue(canvasState)
@ -97,9 +98,214 @@ export const usePolygon = () => {
canvas.renderAll()
}
//polygon 나누기
const splitPolygonWithLines = (polygon) => {
const roofs = []
const allLines = [...polygon.innerLines]
allLines.forEach((line) => {
line.startPoint = { x: line.x1, y: line.y1 }
line.endPoint = { x: line.x2, y: line.y2 }
})
// allLines에 x1,y1,x2,y2를 비교해서 중복되는 값을 제거한다.
allLines.forEach((line, index) => {
const startPoint = line.startPoint
const endPoint = line.endPoint
allLines.forEach((line2, index2) => {
if (index !== index2) {
if (
(isSamePoint(startPoint, line2.startPoint) && isSamePoint(endPoint, line2.endPoint)) ||
(isSamePoint(endPoint, line2.startPoint) && isSamePoint(startPoint, line2.endPoint))
) {
allLines.splice(index2, 1)
}
}
})
})
/**
* 좌표 테스트용
*/
/*allLines.forEach((line) => {
const text = new fabric.Text(`(${line.startPoint.x},${line.startPoint.y})`, {
left: line.startPoint.x,
top: line.startPoint.y,
fontSize: 15,
})
polygon.canvas.add(text)
polygon.canvas.renderAll()
const text2 = new fabric.Text(`(${line.endPoint.x},${line.endPoint.y})`, {
left: line.endPoint.x,
top: line.endPoint.y,
fontSize: 15,
})
polygon.canvas.add(text2)
polygon.canvas.renderAll()
})
polygon.points.forEach((point, index) => {
const text = new fabric.Text(`(${point.x},${point.y})`, {
left: point.x,
top: point.y,
fontSize: 15,
})
polygon.canvas.add(text)
polygon.canvas.renderAll()
})*/
/**
* 좌표 테스트용
*/
polygon.points.forEach((point, index) => {
allLines.forEach((line) => {
if (line.endPoint.x === point.x && line.endPoint.y === point.y) {
const temp = line.startPoint
line.startPoint = line.endPoint
line.endPoint = temp
}
})
})
polygon.points.forEach((point, index) => {
const routes = []
// 시작점은 시작 hip라인의 출발점
const startPoint = point
// 도착점은 마지막 hip라인의 끝나는 점
const endPoint = polygon.points[(index + 1) % polygon.points.length]
const startLine = allLines.find((line) => line.startPoint.x === startPoint.x && line.startPoint.y === startPoint.y)
const endLine = allLines.find((line) => line.startPoint.x === endPoint.x && line.startPoint.y === endPoint.y)
const arrivalPoint = endLine.endPoint
routes.push(startLine.startPoint)
routes.push(startLine.endPoint)
//hip끼리 만나는 경우는 아무것도 안해도됨
if (!isSamePoint(startLine.endPoint, arrivalPoint)) {
// polygon line까지 추가
const allLinesCopy = [...allLines, ...polygon.lines]
// hip이 만나지 않는 경우 갈 수 있는 길을 다 돌아야함
let currentPoint = startLine.endPoint
let currentLine = startLine
let movedLines = []
let subMovedLines = []
while (!isSamePoint(currentPoint, arrivalPoint)) {
// startHip에서 만나는 출발선 두개. 두개의 선을 출발하여 arrivalPoint에 도착할 때 까지 count를 세고, 더 낮은 count를 가진 길을 선택한다.
let connectedLines = allLinesCopy.filter((line) => isSamePoint(line.startPoint, currentPoint) || isSamePoint(line.endPoint, currentPoint))
connectedLines = connectedLines.filter((line) => line !== currentLine)
connectedLines = connectedLines.filter((line) => !subMovedLines.includes(line))
//마지막 선이 endLine의 startPoint와 같은경우 그 전까지 movedLine을 제거한다.
const endLineMeetLineCnt = connectedLines.filter((line) => {
return isSamePoint(line.endPoint, endLine.startPoint) || isSamePoint(line.startPoint, endLine.startPoint)
}).length
if (endLineMeetLineCnt !== 0) {
movedLines.push(subMovedLines)
console.log(movedLines, index)
}
connectedLines = connectedLines.filter((line) => {
return !isSamePoint(line.endPoint, endLine.startPoint) && !isSamePoint(line.startPoint, endLine.startPoint)
})
if (connectedLines.length === 0) {
return
}
let tempPoints = []
for (let i = 0; i < connectedLines.length; i++) {
if (isSamePoint(connectedLines[i].startPoint, currentPoint)) {
tempPoints.push({ point: connectedLines[i].endPoint, index: i, line: connectedLines[i] })
} else {
tempPoints.push({ point: connectedLines[i].startPoint, index: i, line: connectedLines[i] })
}
}
//tempPoints에서 arrivalPoint와 가장 가까운 점을 찾는다.
let minDistance = Number.MAX_SAFE_INTEGER
let minIndex = 0
tempPoints.forEach((tempPoint, index) => {
const distance = Math.sqrt(Math.pow(tempPoint.point.x - arrivalPoint.x, 2) + Math.pow(tempPoint.point.y - arrivalPoint.y, 2))
if (distance < minDistance) {
minDistance = distance
minIndex = tempPoint.index
}
})
currentPoint = tempPoints[minIndex].point
currentLine = tempPoints[minIndex].line
if (currentLine !== startLine) {
subMovedLines.push(currentLine)
}
routes.push(currentPoint)
}
}
routes.push(endLine.startPoint)
roofs.push(routes)
})
// 중복 제거
roofs.forEach((roofPoint, index) => {
const samePointLengthRoofPoints = roofs.filter((roof) => roof.length === roofPoint.length && roof !== roofPoint)
samePointLengthRoofPoints.forEach((samePointRoof) => {
if (arraysHaveSamePoints(samePointRoof, roofPoint)) {
roofs.splice(roofs.indexOf(samePointRoof), 1)
}
})
})
roofs.forEach((roofPoint, index) => {
let defense
const direction = getDirectionByPoint(roofPoint[0], roofPoint[roofPoint.length - 1])
switch (direction) {
case 'top':
defense = 'east'
break
case 'right':
defense = 'south'
break
case 'bottom':
defense = 'west'
break
case 'left':
defense = 'north'
break
}
const roof = new QPolygon(roofPoint, {
fontSize: polygon.fontSize,
stroke: 'black',
fill: 'transparent',
strokeWidth: 3,
name: 'roof',
selectable: false,
defense: defense,
})
polygon.canvas.add(roof)
polygon.canvas.renderAll()
})
}
return {
addPolygon,
addPolygonByLines,
removePolygon,
splitPolygonWithLines,
}
}

View File

@ -1150,7 +1150,7 @@ export const splitPolygonWithLines = (polygon) => {
fill: 'transparent',
strokeWidth: 3,
name: 'roof',
selectable: false,
selectable: true,
defense: defense,
})