diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index 616143fe..7700ae42 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -26,10 +26,9 @@ export const QLine = fabric.util.createClass(fabric.Line, { }) this.idx = options.idx ?? 0 - + this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 }) this.setLength() - this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 }) this.startPoint = { x: this.x1, y: this.y1 } this.endPoint = { x: this.x2, y: this.y2 } diff --git a/src/components/floor-plan/modal/grid/DotLineGrid.jsx b/src/components/floor-plan/modal/grid/DotLineGrid.jsx index 06a911f6..6b63f3d7 100644 --- a/src/components/floor-plan/modal/grid/DotLineGrid.jsx +++ b/src/components/floor-plan/modal/grid/DotLineGrid.jsx @@ -57,7 +57,7 @@ export default function DotLineGrid(props) { // 데이터를 최초 한 번만 조회 useEffect(() => { console.log('DotLineGrid useEffect 실행') - fetchGridSettings() + // fetchGridSettings() }, [objectNo]) const HandleClickClose = () => { @@ -118,9 +118,9 @@ export default function DotLineGrid(props) { dotGridDisplay: dotLineGridSetting.DOT, lineGridDisplay: dotLineGridSetting.LINE, gridType: dotLineGridSetting.INTERVAL.type, - gridHorizon: dotLineGridSetting.INTERVAL.horizontalInterval, - gridVertical: dotLineGridSetting.INTERVAL.verticalInterval, - gridRatio: dotLineGridSetting.INTERVAL.ratioInterval, + gridHorizon: dotLineGridSetting.INTERVAL.horizontalInterval / 10, + gridVertical: dotLineGridSetting.INTERVAL.verticalInterval / 10, + gridRatio: dotLineGridSetting.INTERVAL.ratioInterval / 10, gridDimen: dotLineGridSetting.INTERVAL.dimension, } diff --git a/src/hooks/roofcover/useEavesGableEdit.js b/src/hooks/roofcover/useEavesGableEdit.js index 083d8e03..c43e71f3 100644 --- a/src/hooks/roofcover/useEavesGableEdit.js +++ b/src/hooks/roofcover/useEavesGableEdit.js @@ -22,7 +22,7 @@ export function useEavesGableEdit(setShowEavesGableEditModal) { } const [type, setType] = useState(TYPES.EAVES) const typeRef = useRef(TYPES.EAVES) - const { removeLine } = useLine() + const { removeLine, addPitchTextsByOuterLines } = useLine() const { swalFire } = useSwal() const { drawRoofPolygon } = useMode() @@ -167,6 +167,7 @@ export function useEavesGableEdit(setShowEavesGableEditModal) { const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine') wallLines.forEach((wallLine) => { + addPitchTextsByOuterLines() const roof = drawRoofPolygon(wallLine) canvas?.renderAll() diff --git a/src/hooks/roofcover/usePropertiesSetting.js b/src/hooks/roofcover/usePropertiesSetting.js index ad703356..315a6e8c 100644 --- a/src/hooks/roofcover/usePropertiesSetting.js +++ b/src/hooks/roofcover/usePropertiesSetting.js @@ -17,7 +17,7 @@ export function usePropertiesSetting(setShowPropertiesSettingModal) { const setPoints = useResetRecoilState(outerLinePointsState) const { addPolygonByLines } = usePolygon() - const { removeLine, hideLine } = useLine() + const { removeLine, hideLine, addPitchTextsByOuterLines } = useLine() useEffect(() => { const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') @@ -129,14 +129,13 @@ export function usePropertiesSetting(setShowPropertiesSettingModal) { stroke: '#000000', strokeWidth: 4, }) - - hideLine(line) }) const wall = addPolygonByLines(lines, { name: 'wallLine', fill: 'transparent', stroke: 'black' }) wall.lines = [...lines] + addPitchTextsByOuterLines() const roof = drawRoofPolygon(wall) setPoints([]) diff --git a/src/hooks/roofcover/useRoofShapePassivitySetting.js b/src/hooks/roofcover/useRoofShapePassivitySetting.js index f7b8b9fd..a04b6e0b 100644 --- a/src/hooks/roofcover/useRoofShapePassivitySetting.js +++ b/src/hooks/roofcover/useRoofShapePassivitySetting.js @@ -19,7 +19,7 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod } const canvas = useRecoilValue(canvasState) const { getMessage } = useMessage() - const { showLine, hideLine } = useLine() + const { showLine, hideLine, addPitchTextsByOuterLines } = useLine() const { swalFire } = useSwal() const { addCanvasMouseEventListener, initEvent } = useEvent() const { drawRoofPolygon } = useMode() @@ -212,6 +212,7 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod if (isFix.current) { // 완료 한 경우에는 지붕까지 그려줌 + addPitchTextsByOuterLines() const roof = drawRoofPolygon(wall) } diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index 016cd365..05564c28 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -28,7 +28,7 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { const [hasSleeve, setHasSleeve] = useState('0') const currentObject = useRecoilValue(currentObjectState) const { drawRoofPolygon } = useMode() - const { hideLine, showLine } = useLine() + const { hideLine, showLine, removePitchText, addPitchText, addPitchTextsByOuterLines } = useLine() const setCurrentMenu = useSetRecoilState(currentMenuState) const outerLineFix = useRecoilValue(outerLineFixState) @@ -41,6 +41,36 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { swalFire({ text: '외벽선이 없습니다.' }) setShowRoofShapeSettingModal(false) } + + return () => { + const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + const pitchTexts = canvas.getObjects().filter((obj) => obj.name === 'pitchText') + canvas.remove(...pitchTexts) + outerLines.forEach((line) => { + let stroke, strokeWidth + if (line.attributes) { + if (line.attributes.type === LINE_TYPE.WALLLINE.EAVES || line.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) { + stroke = '#45CD7D' + strokeWidth = 4 + } else if (line.attributes.type === LINE_TYPE.WALLLINE.GABLE || line.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { + stroke = '#3FBAE6' + strokeWidth = 4 + } else { + stroke = '#000000' + strokeWidth = 4 + } + + line.set({ + stroke, + strokeWidth, + }) + + addPitchText(line) + line.setViewLengthText(false) + } + }) + canvas.renderAll() + } }, []) useEffect(() => { @@ -54,13 +84,13 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { return } - const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + /*const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') outerLines.forEach((line) => { line.set({ stroke: '#000000', strokeWidth: 4, }) - }) + })*/ currentObject.set({ stroke: '#EA10AC', @@ -132,7 +162,7 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { case 4: { outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') outerLines.forEach((line) => { - hideLine(line) + // hideLine(line) }) break } @@ -144,23 +174,41 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { outerLines.forEach((line) => { setWestAndEastRoof(line) - if (line.direction === 'bottom') { - line.attributes = { - offset: eavesOffset / 10, - pitch: pitch, - type: LINE_TYPE.WALLLINE.EAVES, + if (outerLines[0].direction === 'bottom') { + if (line.direction === 'bottom') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'top') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } + } + } else { + if (line.direction === 'top') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'bottom') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } } } - if (line.direction === 'top') { - line.attributes = { - offset: shedWidth / 10, - pitch: pitch, - type: LINE_TYPE.WALLLINE.SHED, - } - } - - hideLine(line) + // hideLine(line) }) break } @@ -170,23 +218,42 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { outerLines.forEach((line) => { setWestAndEastRoof(line) - if (line.direction === 'top') { - line.attributes = { - offset: eavesOffset / 10, - pitch: pitch, - type: LINE_TYPE.WALLLINE.EAVES, + + if (outerLines[0].direction === 'bottom') { + if (line.direction === 'top') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'bottom') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } + } + } else { + if (line.direction === 'bottom') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'top') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } } } - if (line.direction === 'bottom') { - line.attributes = { - offset: shedWidth / 10, - pitch: pitch, - type: LINE_TYPE.WALLLINE.SHED, - } - } - - hideLine(line) + // hideLine(line) }) break } @@ -196,22 +263,41 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { outerLines.forEach((line) => { setSouthAndNorthRoof(line) - if (line.direction === 'right') { - line.attributes = { - offset: eavesOffset / 10, - pitch: pitch, - type: LINE_TYPE.WALLLINE.EAVES, + if (outerLines[0].direction === 'bottom') { + if (line.direction === 'right') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'left') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } + } + } else { + if (line.direction === 'left') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'right') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } } } - if (line.direction === 'left') { - line.attributes = { - offset: shedWidth / 10, - pitch: pitch, - type: LINE_TYPE.WALLLINE.SHED, - } - } - hideLine(line) + // hideLine(line) }) break } @@ -222,23 +308,41 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { outerLines.forEach((line) => { setSouthAndNorthRoof(line) - if (line.direction === 'left') { - line.attributes = { - offset: eavesOffset / 10, - pitch: pitch, - type: LINE_TYPE.WALLLINE.EAVES, + if (outerLines[0].direction === 'bottom') { + if (line.direction === 'left') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'right') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } + } + } else { + if (line.direction === 'right') { + line.attributes = { + offset: eavesOffset / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.EAVES, + } + } + + if (line.direction === 'left') { + line.attributes = { + offset: shedWidth / 10, + pitch: pitch, + type: LINE_TYPE.WALLLINE.SHED, + } } } - if (line.direction === 'right') { - line.attributes = { - offset: shedWidth / 10, - pitch: pitch, - type: LINE_TYPE.WALLLINE.SHED, - } - } - - hideLine(line) + // hideLine(line) }) break } @@ -247,14 +351,23 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { // 기존 wallLine, roofBase 제거 canvas .getObjects() - .filter((obj) => obj.name === 'wallLine' || obj.name === 'roofBase') + .filter((obj) => obj.name === 'wallLine') .forEach((line) => { canvas.remove(line) }) + canvas + .getObjects() + .filter((obj) => obj.name === 'roofBase') + .forEach((obj) => { + canvas.remove(...obj.innerLines) + canvas.remove(obj) + }) + const polygon = addPolygonByLines(outerLines, { name: 'wallLine' }) polygon.lines = [...outerLines] + addPitchTextsByOuterLines() const roof = drawRoofPolygon(polygon) canvas?.renderAll() @@ -322,7 +435,7 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { pitch: pitch, type: LINE_TYPE.WALLLINE.EAVES, } - hideLine(line) + // hideLine(line) }) return outerLines @@ -345,7 +458,7 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { type: LINE_TYPE.WALLLINE.EAVES, } } - hideLine(line) + // hideLine(line) }) return outerLines @@ -368,7 +481,7 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { type: LINE_TYPE.WALLLINE.EAVES, } } - hideLine(line) + // hideLine(line) }) return outerLines @@ -390,6 +503,9 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { pitch: pitch, offset: eavesOffset / 10, } + addPitchText(currentObject) + selectedLine.set({ strokeWidth: 4 }) + selectedLine.set({ stroke: '#45CD7D' }) break } case 2: { @@ -398,6 +514,8 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { type: LINE_TYPE.WALLLINE.GABLE, offset: gableOffset / 10, } + selectedLine.set({ strokeWidth: 4 }) + selectedLine.set({ stroke: '#3FBAE6' }) break } case 3: { @@ -417,6 +535,9 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { offset: eavesOffset / 10, width: hipAndGableWidth / 10, } + addPitchText(currentObject) + selectedLine.set({ strokeWidth: 4 }) + selectedLine.set({ stroke: '#45CD7D' }) break } case 5: { @@ -427,6 +548,9 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { width: jerkinHeadWidth / 10, pitch: jerkinHeadPitch, } + addPitchText(currentObject) + selectedLine.set({ strokeWidth: 4 }) + selectedLine.set({ stroke: '#3FBAE6' }) break } case 6: { @@ -440,6 +564,7 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { } selectedLine.attributes = attributes history.current.push(selectedLine) + canvas.renderAll() nextLineFocus(selectedLine) } @@ -458,6 +583,11 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) { } const lastLine = history.current.pop() + currentObject.set({ + stroke: '#000000', + strokeWidth: 4, + }) + lastLine.set({ stroke: '#000000', strokeWidth: 4, diff --git a/src/hooks/surface/usePlacementShapeDrawing.js b/src/hooks/surface/usePlacementShapeDrawing.js index 40d25bf0..91725a1c 100644 --- a/src/hooks/surface/usePlacementShapeDrawing.js +++ b/src/hooks/surface/usePlacementShapeDrawing.js @@ -5,6 +5,7 @@ import { adsorptionRangeState, canvasState, dotLineIntervalSelector, + globalPitchState, verticalHorizontalModeState, } from '@/store/canvasAtom' import { useEvent } from '@/hooks/useEvent' @@ -67,6 +68,8 @@ export function usePlacementShapeDrawing(setShowPlaceShapeDrawingModal) { const isFix = useRef(false) + const globalPitch = useRecoilValue(globalPitchState) + useEffect(() => { if (adsorptionPointAddMode || tempGridMode) { return @@ -215,6 +218,7 @@ export function usePlacementShapeDrawing(setShowPlaceShapeDrawingModal) { originX: 'center', originY: 'center', direction: 'south', + pitch: globalPitch, }) setSurfaceShapePattern(roof) @@ -224,6 +228,7 @@ export function usePlacementShapeDrawing(setShowPlaceShapeDrawingModal) { removeLine(line) }) + setPoints([]) canvas?.renderAll() setShowPlaceShapeDrawingModal(false) } diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js index be421c8e..23e017bd 100644 --- a/src/hooks/surface/useSurfaceShapeBatch.js +++ b/src/hooks/surface/useSurfaceShapeBatch.js @@ -1,7 +1,7 @@ 'use client' import { useRecoilValue } from 'recoil' -import { canvasState } from '@/store/canvasAtom' +import { canvasState, globalPitchState } from '@/store/canvasAtom' import { MENU, BATCH_TYPE, POLYGON_TYPE } from '@/common/common' import { getIntersectionPoint, setSurfaceShapePattern } from '@/util/canvas-util' import { degreesToRadians } from '@turf/turf' @@ -14,6 +14,7 @@ export function useSurfaceShapeBatch() { const { getMessage } = useMessage() const canvas = useRecoilValue(canvasState) + const globalPitch = useRecoilValue(globalPitchState) const { swalFire } = useSwal() const { addCanvasMouseEventListener, initEvent } = useEvent() @@ -83,6 +84,7 @@ export function useSurfaceShapeBatch() { angle: surfaceRefs.rotate, originX: 'center', originY: 'center', + pitch: globalPitch, } obj = new QPolygon(points, options) diff --git a/src/hooks/useLine.js b/src/hooks/useLine.js index a313d127..210c1ac6 100644 --- a/src/hooks/useLine.js +++ b/src/hooks/useLine.js @@ -71,10 +71,67 @@ export const useLine = () => { return Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10 } + const addPitchText = (line) => { + removePitchText(line) + const { startPoint, endPoint, direction, attributes } = line + + let left, top + + if (direction === 'top') { + left = (startPoint.x + endPoint.x) / 2 + top = (startPoint.y + endPoint.y) / 2 - 50 + } else if (direction === 'bottom') { + left = (startPoint.x + endPoint.x) / 2 + top = (startPoint.y + endPoint.y) / 2 - 50 + } else if (direction === 'left') { + left = (startPoint.x + endPoint.x) / 2 + 50 + top = (startPoint.y + endPoint.y) / 2 - 30 + } else if (direction === 'right') { + left = (startPoint.x + endPoint.x) / 2 + 50 + top = (startPoint.y + endPoint.y) / 2 - 30 + } + + const text = new fabric.Text( + `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}${attributes.pitch ? '-∠' + attributes.pitch : ''}`, + { + left, + top, + fontSize: 20, + fill: 'black', + name: 'pitchText', + parentId: line.id, + }, + ) + + canvas.add(text) + } + + const removePitchText = (line) => { + const { id } = line + const pitchText = canvas.getObjects().filter((obj) => obj.name === 'pitchText' && obj.parentId === id) + + // 기존 pitchText가 있으면 삭제 + if (pitchText.length > 0) { + canvas.remove(pitchText) + } + } + + const addPitchTextsByOuterLines = () => { + canvas + .getObjects() + .filter((obj) => obj.name === 'outerLine') + .forEach((line) => { + addPitchText(line) + }) + } + return { addLine, removeLine, hideLine, showLine, + addPitchText, + removePitchText, + addPitchTextsByOuterLines, } } diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 858c13f7..be42ef52 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -1715,7 +1715,7 @@ export function useMode() { roof.setWall(wall) roof.lines.forEach((line, index) => { - line.attributes = { type: wall.lines[index].attributes.type } + line.attributes = wall.lines[index].attributes }) setRoof(roof) diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 514c6592..3fbf1388 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -199,6 +199,7 @@ export const usePolygon = () => { parent: polygon, stickeyPoint: stickeyPoint, visible: isFlowDisplay, + pitch: polygon.pitch, }) polygon.arrow = arrow @@ -399,7 +400,7 @@ export const usePolygon = () => { const addTextByArrows = (arrows, txt, canvas) => { arrows.forEach((arrow, index) => { - const text = new fabric.Text(`${txt}${index + 1}`, { + const text = new fabric.Text(`${txt}${index + 1} (${arrow.pitch}寸)`, { fontSize: arrow.parent.fontSize, fill: 'black', originX: 'center', diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index bfdf78a4..c5ddc9cb 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1127,7 +1127,7 @@ export const splitPolygonWithLines = (polygon) => { }) roofs.forEach((roofPoint, index) => { - let defense + let defense, pitch const direction = getDirectionByPoint(roofPoint[0], roofPoint[roofPoint.length - 1]) switch (direction) { @@ -1144,6 +1144,7 @@ export const splitPolygonWithLines = (polygon) => { defense = 'north' break } + pitch = polygon.lines[index].attributes?.pitch ?? 0 const roof = new QPolygon(roofPoint, { fontSize: polygon.fontSize, @@ -1156,6 +1157,7 @@ export const splitPolygonWithLines = (polygon) => { selectable: true, defense: defense, direction: defense, + pitch: pitch, }) polygon.canvas.add(roof)