Merge branch 'qcast-pub' of https://git.jetbrains.space/nalpari/q-cast-iii/qcast-front into dev
This commit is contained in:
commit
f6d66548f2
@ -49,6 +49,7 @@ export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
handleFix,
|
handleFix,
|
||||||
buttonAct,
|
buttonAct,
|
||||||
setButtonAct,
|
setButtonAct,
|
||||||
|
cutAuxiliary,
|
||||||
} = useAuxiliaryDrawing(id)
|
} = useAuxiliaryDrawing(id)
|
||||||
|
|
||||||
const outerLineProps = {
|
const outerLineProps = {
|
||||||
@ -151,6 +152,9 @@ export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
<button className="btn-frame modal mr5" onClick={handleRollback}>
|
<button className="btn-frame modal mr5" onClick={handleRollback}>
|
||||||
{getMessage('modal.cover.outline.rollback')}
|
{getMessage('modal.cover.outline.rollback')}
|
||||||
</button>
|
</button>
|
||||||
|
<button className="btn-frame modal mr5" onClick={cutAuxiliary}>
|
||||||
|
{getMessage('contextmenu.auxiliary.cut')}
|
||||||
|
</button>
|
||||||
<button className="btn-frame modal act" onClick={() => handleFix(id)}>
|
<button className="btn-frame modal act" onClick={() => handleFix(id)}>
|
||||||
{getMessage('apply')}
|
{getMessage('apply')}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import { useRecoilValue } from 'recoil'
|
|||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { currentObjectState } from '@/store/canvasAtom'
|
import { currentObjectState } from '@/store/canvasAtom'
|
||||||
import { useLine } from '@/hooks/useLine'
|
|
||||||
import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing'
|
import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing'
|
||||||
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
|
|
||||||
export default function AuxiliaryEdit(props) {
|
export default function AuxiliaryEdit(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
@ -18,9 +18,13 @@ export default function AuxiliaryEdit(props) {
|
|||||||
const [horizonSize, setHorizonSize] = useState('0')
|
const [horizonSize, setHorizonSize] = useState('0')
|
||||||
const [arrow1, setArrow1] = useState(null)
|
const [arrow1, setArrow1] = useState(null)
|
||||||
const [arrow2, setArrow2] = useState(null)
|
const [arrow2, setArrow2] = useState(null)
|
||||||
const { addLine, removeLine } = useLine()
|
|
||||||
const currentObject = useRecoilValue(currentObjectState)
|
const currentObject = useRecoilValue(currentObjectState)
|
||||||
|
const { swalFire } = useSwal()
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
|
if (!horizonSize || !verticalSize || !arrow1 || !arrow2) {
|
||||||
|
swalFire({ title: '길이와 방향을 입력하세요.', type: 'alert' })
|
||||||
|
return
|
||||||
|
}
|
||||||
if (type === 'copy') {
|
if (type === 'copy') {
|
||||||
if (currentObject) {
|
if (currentObject) {
|
||||||
copy(
|
copy(
|
||||||
|
|||||||
@ -3,12 +3,14 @@ import WithDraggable from '@/components/common/draggable/WithDraggable'
|
|||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { useCanvas } from '@/hooks/useCanvas'
|
||||||
|
|
||||||
export default function AuxiliarySize(props) {
|
export default function AuxiliarySize(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
const { id, pos = contextPopupPosition } = props
|
const { id, pos = contextPopupPosition } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
const { currentObject } = useCanvas()
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm mount`}>
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
@ -26,7 +28,7 @@ export default function AuxiliarySize(props) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="outline-form mb15">
|
<div className="outline-form mb15">
|
||||||
<div className="input-grid mr5" style={{ flex: '1 1 auto' }}>
|
<div className="input-grid mr5" style={{ flex: '1 1 auto' }}>
|
||||||
<input type="text" className="input-origin block" defaultValue={100} />
|
<input type="text" className="input-origin block" defaultValue={currentObject?.length} readOnly={true} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">mm</span>
|
<span className="thin">mm</span>
|
||||||
</div>
|
</div>
|
||||||
@ -45,14 +47,14 @@ export default function AuxiliarySize(props) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="outline-form mb15">
|
<div className="outline-form mb15">
|
||||||
<div className="input-grid mr5" style={{ flex: '1 1 auto' }}>
|
<div className="input-grid mr5" style={{ flex: '1 1 auto' }}>
|
||||||
<input type="text" className="input-origin block" defaultValue={100} />
|
<input type="text" className="input-origin block" defaultValue={100} readOnly={true} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">mm</span>
|
<span className="thin">mm</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span style={{ width: 'auto' }}>{getMessage('length')}</span>
|
<span style={{ width: 'auto' }}>{getMessage('length')}</span>
|
||||||
<div className="input-grid mr5">
|
<div className="input-grid mr5">
|
||||||
<input type="text" className="input-origin block" defaultValue={100} />
|
<input type="text" className="input-origin block" defaultValue={currentObject?.length} readOnly={true} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">mm</span>
|
<span className="thin">mm</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -82,7 +82,7 @@ const PentagonDormer = forwardRef((props, refs) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="discrimination-box">
|
<div className="discrimination-box">
|
||||||
<div className="discrimination-tit">方向の選択</div>
|
<div className="discrimination-tit">{getMessage('modal.object.setting.direction.select')}</div>
|
||||||
<div className="object-direction-wrap">
|
<div className="object-direction-wrap">
|
||||||
<div className="plane-direction">
|
<div className="plane-direction">
|
||||||
<span className="top">{getMessage('commons.north')}</span>
|
<span className="top">{getMessage('commons.north')}</span>
|
||||||
|
|||||||
@ -60,7 +60,7 @@ const TriangleDormer = forwardRef((props, refs) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="discrimination-box">
|
<div className="discrimination-box">
|
||||||
<div className="discrimination-tit">方向の選択</div>
|
<div className="discrimination-tit">{getMessage('modal.object.setting.direction.select')}</div>
|
||||||
<div className="object-direction-wrap">
|
<div className="object-direction-wrap">
|
||||||
<div className="plane-direction">
|
<div className="plane-direction">
|
||||||
<span className="top">{getMessage('commons.north')}</span>
|
<span className="top">{getMessage('commons.north')}</span>
|
||||||
|
|||||||
@ -92,7 +92,7 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
|
|
||||||
addCanvasMouseEventListener('mouse:move', mouseMove)
|
addCanvasMouseEventListener('mouse:move', mouseMove)
|
||||||
addCanvasMouseEventListener('mouse:down', mouseDown)
|
addCanvasMouseEventListener('mouse:down', mouseDown)
|
||||||
addDocumentEventListener('contextmenu', document, cutAuxiliary)
|
// addDocumentEventListener('contextmenu', document, cutAuxiliary)
|
||||||
addDocumentEventListener('keydown', document, keydown[type])
|
addDocumentEventListener('keydown', document, keydown[type])
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@ -135,23 +135,6 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const addBisectorLine = (target) => {
|
|
||||||
const slope = (target.y2 - target.y1) / (target.x2 - target.x1)
|
|
||||||
const bisectorSlope = -1 / slope
|
|
||||||
const length = target.length
|
|
||||||
const dx = length / Math.sqrt(1 + bisectorSlope * bisectorSlope)
|
|
||||||
const dy = bisectorSlope * dx
|
|
||||||
const endX = (target.x1 + target.x2) / 2
|
|
||||||
const endY = (target.y1 + target.y2) / 2
|
|
||||||
|
|
||||||
addLine([dx, dy, endX, endY], {
|
|
||||||
stroke: 'red',
|
|
||||||
strokeWidth: 1,
|
|
||||||
selectable: true,
|
|
||||||
name: 'auxiliaryLine',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const keydown = {
|
const keydown = {
|
||||||
outerLine: (e) => {
|
outerLine: (e) => {
|
||||||
if (mousePointerArr.current.length === 0) {
|
if (mousePointerArr.current.length === 0) {
|
||||||
@ -565,8 +548,24 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
otherAdsorptionPoints.push(intersectionPoint)
|
otherAdsorptionPoints.push(intersectionPoint)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
let innerLinePoints = []
|
||||||
|
canvas
|
||||||
|
.getObjects()
|
||||||
|
.filter((obj) => obj.innerLines)
|
||||||
|
.forEach((polygon) => {
|
||||||
|
polygon.innerLines.forEach((line) => {
|
||||||
|
innerLinePoints.push({ x: line.x1, y: line.y1 })
|
||||||
|
innerLinePoints.push({ x: line.x2, y: line.y2 })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
const adsorptionPoints = [...getAdsorptionPoints(), ...roofAdsorptionPoints.current, ...otherAdsorptionPoints, ...intersectionPoints.current]
|
const adsorptionPoints = [
|
||||||
|
...getAdsorptionPoints(),
|
||||||
|
...roofAdsorptionPoints.current,
|
||||||
|
...otherAdsorptionPoints,
|
||||||
|
...intersectionPoints.current,
|
||||||
|
...innerLinePoints,
|
||||||
|
]
|
||||||
|
|
||||||
let arrivalPoint = { x: pointer.x, y: pointer.y }
|
let arrivalPoint = { x: pointer.x, y: pointer.y }
|
||||||
|
|
||||||
@ -825,7 +824,6 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
|
|
||||||
//lineHistory.current에 있는 선들 중 startPoint와 endPoint가 겹치는 line은 제거
|
//lineHistory.current에 있는 선들 중 startPoint와 endPoint가 겹치는 line은 제거
|
||||||
// 겹치는 선 하나는 canvas에서 제거한다.
|
// 겹치는 선 하나는 canvas에서 제거한다.
|
||||||
|
|
||||||
const tempLines = [...lineHistory.current]
|
const tempLines = [...lineHistory.current]
|
||||||
lineHistory.current = []
|
lineHistory.current = []
|
||||||
tempLines.forEach((line) => {
|
tempLines.forEach((line) => {
|
||||||
@ -849,27 +847,30 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
const tempPolygonPoints = [...roofBase.points].map((obj) => {
|
const tempPolygonPoints = [...roofBase.points].map((obj) => {
|
||||||
return { x: Math.round(obj.x), y: Math.round(obj.y) }
|
return { x: Math.round(obj.x), y: Math.round(obj.y) }
|
||||||
})
|
})
|
||||||
const roofInnerLines = innerLines.filter((line) => {
|
const roofInnerLines = [...roofBase.innerLines, ...innerLines].filter((line) => {
|
||||||
const inPolygon1 =
|
const inPolygon1 =
|
||||||
tempPolygonPoints.some((point) => point.x === line.x1 && point.y === line.y1) ||
|
tempPolygonPoints.some((point) => Math.round(point.x) === Math.round(line.x1) && Math.round(point.y) === Math.round(line.y1)) ||
|
||||||
roofBase.inPolygon({ x: line.x1, y: line.y1 }) ||
|
roofBase.inPolygon({ x: Math.round(line.x1), y: Math.round(line.y1) }) ||
|
||||||
roofBase.lines.some((line) => isPointOnLine(line, { x: line.x1, y: line.y1 }))
|
roofBase.lines.some((line) => isPointOnLine(line, { x: Math.round(line.x1), y: Math.round(line.y1) }))
|
||||||
const inPolygon2 =
|
const inPolygon2 =
|
||||||
tempPolygonPoints.some((point) => point.x === line.x2 && point.y === line.y2) ||
|
tempPolygonPoints.some((point) => Math.round(point.x) === Math.round(line.x2) && Math.round(point.y) === Math.round(line.y2)) ||
|
||||||
roofBase.inPolygon({ x: line.x2, y: line.y2 }) ||
|
roofBase.inPolygon({ x: Math.round(line.x2), y: Math.round(line.y2) }) ||
|
||||||
roofBase.lines.some((line) => isPointOnLine(line, { x: line.x2, y: line.y2 }))
|
roofBase.lines.some((line) => isPointOnLine(line, { x: Math.round(line.x2), y: Math.round(line.y2) }))
|
||||||
|
|
||||||
if (inPolygon1 && inPolygon2) {
|
if (inPolygon1 && inPolygon2) {
|
||||||
line.attributes = { ...line.attributes, roofId: roofBase.id, actualSize: 0, planeSize: line.getLength() }
|
line.attributes = {
|
||||||
|
...line.attributes,
|
||||||
|
roofId: roofBase.id,
|
||||||
|
actualSize: line.attributes?.actualSize ?? 0,
|
||||||
|
planeSize: line.getLength(),
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
roofBase.innerLines = [...roofInnerLines]
|
roofBase.innerLines = lineHistory.current.length !== 0 ? [...roofInnerLines] : roofBase.innerLines
|
||||||
|
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
})
|
})
|
||||||
|
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -903,6 +904,6 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
setButtonAct,
|
setButtonAct,
|
||||||
move,
|
move,
|
||||||
copy,
|
copy,
|
||||||
addBisectorLine,
|
cutAuxiliary,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import { useObjectBatch } from '@/hooks/object/useObjectBatch'
|
|||||||
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
||||||
import { fontSelector, globalFontAtom } from '@/store/fontAtom'
|
import { fontSelector, globalFontAtom } from '@/store/fontAtom'
|
||||||
import { useLine } from '@/hooks/useLine'
|
import { useLine } from '@/hooks/useLine'
|
||||||
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
|
|
||||||
export function useContextMenu() {
|
export function useContextMenu() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
@ -56,6 +57,7 @@ export function useContextMenu() {
|
|||||||
const [globalFont, setGlobalFont] = useRecoilState(globalFontAtom)
|
const [globalFont, setGlobalFont] = useRecoilState(globalFontAtom)
|
||||||
const { addLine, removeLine } = useLine()
|
const { addLine, removeLine } = useLine()
|
||||||
const commonTextFont = useRecoilValue(fontSelector('commonText'))
|
const commonTextFont = useRecoilValue(fontSelector('commonText'))
|
||||||
|
const { swalFire } = useSwal()
|
||||||
|
|
||||||
const currentMenuSetting = () => {
|
const currentMenuSetting = () => {
|
||||||
switch (currentMenu) {
|
switch (currentMenu) {
|
||||||
@ -145,6 +147,9 @@ export function useContextMenu() {
|
|||||||
shortcut: ['d', 'D'],
|
shortcut: ['d', 'D'],
|
||||||
name: `${getMessage('contextmenu.auxiliary.remove')}(D)`,
|
name: `${getMessage('contextmenu.auxiliary.remove')}(D)`,
|
||||||
fn: () => {
|
fn: () => {
|
||||||
|
const roof = canvas.getObjects().filter((obj) => obj.id === currentObject.attributes.roofId)[0]
|
||||||
|
const innerLines = roof.innerLines?.filter((line) => currentObject.id !== line.id)
|
||||||
|
roof.innerLines = [...innerLines]
|
||||||
canvas.remove(currentObject)
|
canvas.remove(currentObject)
|
||||||
canvas.discardActiveObject()
|
canvas.discardActiveObject()
|
||||||
},
|
},
|
||||||
@ -176,21 +181,34 @@ export function useContextMenu() {
|
|||||||
endY = (currentObject.y1 + currentObject.y2) / 2 - dy
|
endY = (currentObject.y1 + currentObject.y2) / 2 - dy
|
||||||
}
|
}
|
||||||
|
|
||||||
addLine([startX, startY, endX, endY], {
|
const line = addLine([startX, startY, endX, endY], {
|
||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
name: 'auxiliaryLine',
|
name: 'auxiliaryLine',
|
||||||
|
attributes: { ...currentObject.attributes },
|
||||||
})
|
})
|
||||||
|
canvas
|
||||||
|
.getObjects()
|
||||||
|
.filter((obj) => obj.id === currentObject.attributes.roofId)[0]
|
||||||
|
.innerLines.push(line)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'auxiliaryCut',
|
|
||||||
name: getMessage('contextmenu.auxiliary.cut'),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'auxiliaryRemoveAll',
|
id: 'auxiliaryRemoveAll',
|
||||||
name: getMessage('contextmenu.auxiliary.remove.all'),
|
name: getMessage('contextmenu.auxiliary.remove.all'),
|
||||||
|
fn: () => {
|
||||||
|
if (!currentObject) {
|
||||||
|
swalFire({ text: '지붕을 선택해주세요.' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const innerLines = canvas.getObjects().filter((obj) => obj.id === currentObject.attributes.roofId)[0].innerLines
|
||||||
|
innerLines.forEach((line) => {
|
||||||
|
canvas.remove(line)
|
||||||
|
})
|
||||||
|
innerLines.length = 0
|
||||||
|
canvas.renderAll()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
])
|
])
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user