Compare commits
9 Commits
e75db5ace1
...
f2a083f022
| Author | SHA1 | Date | |
|---|---|---|---|
| f2a083f022 | |||
| 786c35e656 | |||
|
|
88bcf27bfb | ||
|
|
617afb8b1f | ||
|
|
414d6fa0c5 | ||
| 6919dac8f1 | |||
|
|
79d873c135 | ||
|
|
0e8ce8b2e2 | ||
|
|
c4d17d2147 |
@ -186,7 +186,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||
this.lines = []
|
||||
|
||||
this.getCurrentPoints().forEach((point, i) => {
|
||||
const nextPoint = this.points[(i + 1) % this.points.length]
|
||||
const nextPoint = this.getCurrentPoints()[(i + 1) % this.points.length]
|
||||
const line = new QLine([point.x, point.y, nextPoint.x, nextPoint.y], {
|
||||
stroke: this.stroke,
|
||||
strokeWidth: this.strokeWidth,
|
||||
|
||||
@ -7,6 +7,7 @@ import { useMessage } from '@/hooks/useMessage'
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { usePolygon } from '@/hooks/usePolygon'
|
||||
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
||||
|
||||
const FLOW_DIRECTION_TYPE = {
|
||||
EIGHT_AZIMUTH: 'eightAzimuth',
|
||||
@ -19,6 +20,8 @@ export default function FlowDirectionSetting(props) {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const { getMessage } = useMessage()
|
||||
|
||||
const { changeSurfaceLineType } = useSurfaceShapeBatch({})
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
canvas?.discardActiveObject()
|
||||
@ -53,6 +56,7 @@ export default function FlowDirectionSetting(props) {
|
||||
})
|
||||
drawDirectionArrow(roof)
|
||||
canvas?.renderAll()
|
||||
changeSurfaceLineType(roof)
|
||||
closePopup(id)
|
||||
}
|
||||
|
||||
|
||||
@ -261,6 +261,15 @@ export function useRoofAllocationSetting(id) {
|
||||
* 지붕재 삭제
|
||||
*/
|
||||
const onDeleteRoofMaterial = (idx) => {
|
||||
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||
|
||||
for (let i = 0; i < roofs.length; i++) {
|
||||
if (roofs[i].roofMaterial.index === idx) {
|
||||
swalFire({ type: 'alert', icon: 'error', text: getMessage('roof.material.can.not.delete') })
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const isSelected = currentRoofList[idx].selected
|
||||
const newRoofList = JSON.parse(JSON.stringify(currentRoofList)).filter((_, index) => index !== idx)
|
||||
if (isSelected) {
|
||||
@ -300,6 +309,7 @@ export function useRoofAllocationSetting(id) {
|
||||
})
|
||||
|
||||
setRoofList(newRoofList)
|
||||
setRoofMaterials(newRoofList)
|
||||
const selectedRoofMaterial = newRoofList.find((roof) => roof.selected)
|
||||
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial, true)
|
||||
drawDirectionArrow(currentObject)
|
||||
@ -308,6 +318,21 @@ export function useRoofAllocationSetting(id) {
|
||||
basicSettingSave()
|
||||
}
|
||||
|
||||
/**
|
||||
* 기존 세팅된 지붕에 지붕재 내용을 바뀐 내용으로 수정
|
||||
* @param newRoofMaterials
|
||||
*/
|
||||
const setRoofMaterials = (newRoofMaterials) => {
|
||||
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||
newRoofMaterials.forEach((roofMaterial) => {
|
||||
const index = roofMaterial.index
|
||||
const tempRoofs = roofs.filter((roof) => roof.roofMaterial?.index === index)
|
||||
tempRoofs.forEach((roof) => {
|
||||
setSurfaceShapePattern(roof, roofDisplay.column, false, roofMaterial)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 지붕면 할당
|
||||
*/
|
||||
@ -411,6 +436,8 @@ export function useRoofAllocationSetting(id) {
|
||||
drawDirectionArrow(roof)
|
||||
})
|
||||
|
||||
setRoofMaterials(newRoofList)
|
||||
|
||||
/** 외곽선 삭제 */
|
||||
const removeTargets = canvas.getObjects().filter((obj) => obj.name === 'outerLinePoint' || obj.name === 'outerLine')
|
||||
removeTargets.forEach((obj) => {
|
||||
|
||||
@ -32,6 +32,7 @@ import {
|
||||
import { usePolygon } from '@/hooks/usePolygon'
|
||||
import { POLYGON_TYPE } from '@/common/common'
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
import { useSurfaceShapeBatch } from './useSurfaceShapeBatch'
|
||||
|
||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||
@ -50,6 +51,8 @@ export function usePlacementShapeDrawing(id) {
|
||||
const { addPolygonByLines, drawDirectionArrow } = usePolygon()
|
||||
const { tempGridMode } = useTempGrid()
|
||||
const { setSurfaceShapePattern } = useRoofFn()
|
||||
const { changeSurfaceLineType } = useSurfaceShapeBatch({})
|
||||
|
||||
const canvasSetting = useRecoilValue(canvasSettingState)
|
||||
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
|
||||
const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState)
|
||||
@ -253,11 +256,14 @@ export function usePlacementShapeDrawing(id) {
|
||||
setPoints([])
|
||||
canvas?.renderAll()
|
||||
|
||||
if (+canvasSetting?.roofSizeSet === 3) {
|
||||
// if (+canvasSetting?.roofSizeSet === 3) {
|
||||
// closePopup(id)
|
||||
// return
|
||||
// }
|
||||
// addPopup(id, 1, <PlacementSurfaceLineProperty id={id} roof={roof} />, false)
|
||||
|
||||
changeSurfaceLineType(roof)
|
||||
closePopup(id)
|
||||
return
|
||||
}
|
||||
addPopup(id, 1, <PlacementSurfaceLineProperty id={id} roof={roof} />, false)
|
||||
}
|
||||
|
||||
if (points.length < 3) {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
||||
import { canvasSettingState, canvasState, currentCanvasPlanState, globalPitchState } from '@/store/canvasAtom'
|
||||
import { MENU, POLYGON_TYPE } from '@/common/common'
|
||||
import { MENU, POLYGON_TYPE, LINE_TYPE } from '@/common/common'
|
||||
import { getIntersectionPoint, toFixedWithoutRounding } from '@/util/canvas-util'
|
||||
import { degreesToRadians } from '@turf/turf'
|
||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||
@ -111,7 +111,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
||||
lockScalingX: true, // X 축 크기 조정 잠금
|
||||
lockScalingY: true, // Y 축 크기 조정 잠금
|
||||
name: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH_TEMP,
|
||||
flipX: xInversion !== yInversion,
|
||||
// flipX: xInversion !== yInversion,
|
||||
// angle: xInversion && yInversion ? Math.abs((rotate + 180) % 360) : Math.abs(rotate),
|
||||
// angle: rotate,
|
||||
originX: 'center',
|
||||
@ -120,6 +120,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
||||
}
|
||||
|
||||
obj = new QPolygon(points, options)
|
||||
|
||||
let imageRotate = 0
|
||||
if (xInversion && !yInversion) {
|
||||
if (rotate % 180 === 0 || rotate < 0) {
|
||||
@ -148,7 +149,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
||||
} else {
|
||||
imageRotate = (rotate + 360) % 360
|
||||
}
|
||||
obj.set({ angle: imageRotate })
|
||||
obj.set({ angle: imageRotate, flipX: xInversion !== yInversion })
|
||||
obj.setCoords() //좌표 변경 적용
|
||||
|
||||
canvas?.add(obj)
|
||||
@ -201,13 +202,15 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
||||
setSurfaceShapePattern(batchSurface, roofDisplay.column)
|
||||
drawDirectionArrow(batchSurface)
|
||||
|
||||
// if (setIsHidden) setIsHidden(false)
|
||||
|
||||
// closePopup(id)
|
||||
initEvent()
|
||||
if (+canvasSetting?.roofSizeSet === 3) return
|
||||
const popupId = uuidv4()
|
||||
addPopup(popupId, 2, <PlacementSurfaceLineProperty roof={batchSurface} id={popupId} setIsHidden={setIsHidden} />)
|
||||
// if (+canvasSetting?.roofSizeSet === 3) return
|
||||
// const popupId = uuidv4()
|
||||
// addPopup(popupId, 2, <PlacementSurfaceLineProperty roof={batchSurface} id={popupId} setIsHidden={setIsHidden} />)
|
||||
|
||||
changeSurfaceLineType(batchSurface)
|
||||
|
||||
if (setIsHidden) setIsHidden(false)
|
||||
})
|
||||
} else {
|
||||
if (setIsHidden) setIsHidden(false)
|
||||
@ -1066,45 +1069,101 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
||||
canvas?.renderAll()
|
||||
}
|
||||
|
||||
const updateFlippedPoints = (polygon) => {
|
||||
if (!(polygon instanceof fabric.Polygon)) {
|
||||
console.error('The object is not a Polygon.')
|
||||
return
|
||||
}
|
||||
/**
|
||||
* 면형상 작도시 라인 속성 넣는 로직
|
||||
* 폴리곤으로 보면 직선방향에 따라 아래쪽인지 윗쪽인지 판단이 가능하다고 생각하여
|
||||
* south -> 밑면은 무조건 right direction이라 가정하고 작업함 좌우반전시 반대로 그려지는 경우도 생기지만 그럴땐 흐름방향에 따라 최대값(최소값)을 찾아
|
||||
* 해당 하는 흐름에 맞게 변경함
|
||||
* @param { } polygon
|
||||
*/
|
||||
|
||||
const { flipX, flipY, width, height, points, left, top, scaleX, scaleY } = polygon
|
||||
|
||||
// 현재 points의 사본 가져오기
|
||||
const newPoints = points.map((point) => {
|
||||
let x = point.x
|
||||
let y = point.y
|
||||
|
||||
// flipX 적용
|
||||
if (flipX) {
|
||||
x = width - x
|
||||
}
|
||||
|
||||
// flipY 적용
|
||||
if (flipY) {
|
||||
y = height - y
|
||||
}
|
||||
|
||||
// 스케일 및 전역 좌표 고려
|
||||
x = (x - width / 2) * scaleX + width / 2
|
||||
y = (y - height / 2) * scaleY + height / 2
|
||||
|
||||
return { x, y }
|
||||
const changeSurfaceLineType = (polygon) => {
|
||||
polygon.lines.forEach((line) => {
|
||||
line.attributes.type = LINE_TYPE.WALLLINE.GABLE
|
||||
})
|
||||
|
||||
// flipX, flipY를 초기화
|
||||
polygon.flipX = false
|
||||
polygon.flipY = false
|
||||
const directionConfig = {
|
||||
south: { evaesDirection: 'right', ridgeDirection: 'left', coord1: 'y1', coord2: 'y2' },
|
||||
north: { evaesDirection: 'left', ridgeDirection: 'right', coord1: 'y1', coord2: 'y2' },
|
||||
east: { evaesDirection: 'top', ridgeDirection: 'bottom', coord1: 'x1', coord2: 'x2' },
|
||||
west: { evaesDirection: 'bottom', ridgeDirection: 'top', coord1: 'x1', coord2: 'x2' },
|
||||
}
|
||||
|
||||
// points 업데이트
|
||||
polygon.set({ points: newPoints })
|
||||
polygon.setCoords()
|
||||
const { evaesDirection, ridgeDirection, coord1, coord2 } = directionConfig[polygon.direction] || directionConfig.west
|
||||
|
||||
return polygon
|
||||
polygon.lines.forEach((line) => {
|
||||
if (line[coord1] === line[coord2]) {
|
||||
if (line.direction === evaesDirection) {
|
||||
line.attributes.type = LINE_TYPE.WALLLINE.EAVES
|
||||
line.stroke = 'rgb(47, 0, 255)'
|
||||
} else if (line.direction === ridgeDirection) {
|
||||
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||
line.stroke = 'rgb(44, 255, 2)'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 진짜 처마 라인인지 확인하는 로직 -> 특정 모양에 따라 처마가 없는 경우가 있는데 위에 로직으로는
|
||||
* 용마루도 처마로 만들어서 재보정
|
||||
*/
|
||||
//직선 찾는 로직
|
||||
const maxLine = polygon.lines.filter((line) => line[coord1] === line[coord2])
|
||||
|
||||
if (maxLine.length > 0) {
|
||||
const maxLineSorted = maxLine.reduce((a, b) => {
|
||||
return (polygon.direction === 'south' || polygon.direction === 'east' ? b : a)[coord1] >
|
||||
(polygon.direction === 'south' || polygon.direction === 'east' ? a : b)[coord1]
|
||||
? b
|
||||
: a
|
||||
})
|
||||
|
||||
if (
|
||||
(polygon.direction === 'south' && maxLineSorted.direction === 'left') ||
|
||||
(polygon.direction === 'north' && maxLineSorted.direction === 'right') ||
|
||||
(polygon.direction === 'east' && maxLineSorted.direction === 'bottom') ||
|
||||
(polygon.direction === 'west' && maxLineSorted.direction === 'top')
|
||||
) {
|
||||
polygon.lines.forEach((line) => {
|
||||
if (line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
|
||||
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||
} else if (line.attributes.type === LINE_TYPE.SUBLINE.RIDGE) {
|
||||
line.attributes.type = LINE_TYPE.WALLLINE.EAVES
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (maxLine.length === 1) {
|
||||
const maxLineCoord = polygon.lines.reduce((a, b) => {
|
||||
return (polygon.direction === 'south' || polygon.direction === 'east' ? b : a)[coord1] >
|
||||
(polygon.direction === 'south' || polygon.direction === 'east' ? a : b)[coord1]
|
||||
? b
|
||||
: a
|
||||
})
|
||||
|
||||
const isRealEavesLine = polygon.lines.find((line) => line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
|
||||
if (isRealEavesLine) {
|
||||
if (polygon.direction === 'south' || polygon.direction === 'north') {
|
||||
const targetCoord =
|
||||
polygon.direction === 'south' ? Math.max(maxLineCoord.y1, maxLineCoord.y2) : Math.min(maxLineCoord.y1, maxLineCoord.y2)
|
||||
const realLineCoord =
|
||||
polygon.direction === 'south' ? Math.max(isRealEavesLine.y1, isRealEavesLine.y2) : Math.min(isRealEavesLine.y1, isRealEavesLine.y2)
|
||||
|
||||
if (targetCoord !== realLineCoord) {
|
||||
isRealEavesLine.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||
}
|
||||
} else if (polygon.direction === 'east' || polygon.direction === 'west') {
|
||||
const targetCoord = polygon.direction === 'east' ? Math.max(maxLineCoord.x1, maxLineCoord.x2) : Math.min(maxLineCoord.x1, maxLineCoord.x2)
|
||||
const realLineCoord =
|
||||
polygon.direction === 'east' ? Math.max(isRealEavesLine.x1, isRealEavesLine.x2) : Math.min(isRealEavesLine.x1, isRealEavesLine.x2)
|
||||
|
||||
if (targetCoord !== realLineCoord) {
|
||||
isRealEavesLine.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
@ -1115,5 +1174,6 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
||||
changeSurfaceLinePropertyEvent,
|
||||
changeSurfaceLineProperty,
|
||||
changeSurfaceLinePropertyReset,
|
||||
changeSurfaceLineType,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1038,5 +1038,6 @@
|
||||
"want.to.complete.auxiliary.creation": "補助線の作成を完了しますか?",
|
||||
"modal.placement.initial.setting.plan.drawing.only.number": "(※数字は[半角]入力のみ可能です。)",
|
||||
"wall.line.not.found": "外壁がありません",
|
||||
"roof.line.not.found": "屋根形状がありません"
|
||||
"roof.line.not.found": "屋根形状がありません",
|
||||
"roof.material.can.not.delete" : "割り当てられた配置面があります。"
|
||||
}
|
||||
|
||||
@ -1038,5 +1038,6 @@
|
||||
"want.to.complete.auxiliary.creation": "보조선 작성을 완료하시겠습니까?",
|
||||
"modal.placement.initial.setting.plan.drawing.only.number": "(※ 숫자는 [반각]입력만 가능합니다.)",
|
||||
"wall.line.not.found": "외벽선이 없습니다.",
|
||||
"roof.line.not.found": "지붕형상이 없습니다."
|
||||
"roof.line.not.found": "지붕형상이 없습니다.",
|
||||
"roof.material.can.not.delete" : "할당된 배치면이 있습니다."
|
||||
}
|
||||
|
||||
@ -348,15 +348,15 @@ export const calculateIntersection = (line1, line2) => {
|
||||
}
|
||||
|
||||
// Determine the min and max for line1 and line2 for both x and y
|
||||
const line1MinX = Math.min(line1.x1, line1.x2)
|
||||
const line1MaxX = Math.max(line1.x1, line1.x2)
|
||||
const line2MinX = Math.min(line2.x1, line2.x2)
|
||||
const line2MaxX = Math.max(line2.x1, line2.x2)
|
||||
const line1MinX = Math.min(line1.x1, line1.x2) - 5
|
||||
const line1MaxX = Math.max(line1.x1, line1.x2) + 5
|
||||
const line2MinX = Math.min(line2.x1, line2.x2) - 5
|
||||
const line2MaxX = Math.max(line2.x1, line2.x2) + 5
|
||||
|
||||
const line1MinY = Math.min(line1.y1, line1.y2)
|
||||
const line1MaxY = Math.max(line1.y1, line1.y2)
|
||||
const line2MinY = Math.min(line2.y1, line2.y2)
|
||||
const line2MaxY = Math.max(line2.y1, line2.y2)
|
||||
const line1MinY = Math.min(line1.y1, line1.y2) - 5
|
||||
const line1MaxY = Math.max(line1.y1, line1.y2) + 5
|
||||
const line2MinY = Math.min(line2.y1, line2.y2) - 5
|
||||
const line2MaxY = Math.max(line2.y1, line2.y2) + 5
|
||||
|
||||
// Check if the intersection X and Y are within the range of both lines
|
||||
if (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user