삼각도머

This commit is contained in:
yjnoh 2025-03-05 17:14:03 +09:00
parent 652516146b
commit 8fb523cf3d
3 changed files with 242 additions and 132 deletions

View File

@ -5,7 +5,14 @@ import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { BATCH_TYPE, INPUT_TYPE, POLYGON_TYPE } from '@/common/common'
import { useEvent } from '@/hooks/useEvent'
import { pointsToTurfPolygon, polygonToTurfPolygon, rectToPolygon, triangleToPolygon, getDegreeByChon } from '@/util/canvas-util'
import {
pointsToTurfPolygon,
polygonToTurfPolygon,
rectToPolygon,
triangleToPolygon,
getDegreeByChon,
toFixedWithoutRounding,
} from '@/util/canvas-util'
import { useSwal } from '@/hooks/useSwal'
import * as turf from '@turf/turf'
import { usePolygon } from '@/hooks/usePolygon'
@ -13,6 +20,7 @@ import { QPolygon } from '@/components/fabric/QPolygon'
import { v4 as uuidv4 } from 'uuid'
import { fontSelector } from '@/store/fontAtom'
import { useRoofFn } from '@/hooks/common/useRoofFn'
import { roofDisplaySelector } from '@/store/settingAtom'
export function useObjectBatch({ isHidden, setIsHidden }) {
const { getMessage } = useMessage()
@ -23,6 +31,9 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
const { drawDirectionArrow } = usePolygon()
const { setSurfaceShapePattern } = useRoofFn()
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
const roofDisplay = useRecoilValue(roofDisplaySelector)
const { addPolygon } = usePolygon()
useEffect(() => {
if (canvas) {
@ -293,6 +304,15 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
if (buttonAct === 3) {
let groupDormerPoints = [] //나중에 offset을 위한 포인트 저장용
let bottomLength = 0,
bottomOffsetLength = 0,
planeHypotenuse = 0,
planeOffsetHypotenuse = 0,
actualBottomLength = 0,
actualBottomOffsetLength = 0,
actualHypotenuse = 0,
actualOffsetHypotenuse = 0
addCanvasMouseEventListener('mouse:move', (e) => {
isDown = true
if (!isDown) return
@ -306,57 +326,51 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
}
})
console.log('selectedSurface', selectedSurface)
if (selectedSurface) {
const roofAngle = selectedSurface.roofMaterial.angle
const roofAngle = selectedSurface.roofMaterial.angle
theta = Math.atan(Math.tan((roofAngle * Math.PI) / 180) / Math.tan((dormerAngle * Math.PI) / 180))
theta = Math.atan(Math.tan((roofAngle * Math.PI) / 180) / Math.tan((dormerAngle * Math.PI) / 180))
//센터 삼각형용
bottomLength = Number((Math.tan(theta) * height).toFixed())
const bottomLength = Number((Math.tan(theta) * height).toFixed())
const bottomOffsetLength = Number((Math.tan(theta) * (height + offsetRef)).toFixed())
//좌우 삼각형용
bottomOffsetLength = Number((Math.tan(theta) * (height + offsetRef)).toFixed())
let angle = 0
if (directionRef === 'left') {
//서
angle = 90
} else if (directionRef === 'right') {
//동
angle = 270
} else if (directionRef === 'up') {
//북
angle = 180
}
planeHypotenuse = Math.sqrt(Math.pow(height, 2) + Math.pow(bottomLength, 2))
dormer = new fabric.Triangle({
fill: 'white',
stroke: 'red',
strokeDashArray: [5, 5],
strokeWidth: 1,
width: bottomLength * 2,
height: height,
left: pointer.x,
top: pointer.y,
selectable: true,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
name: dormerTempName,
originX: 'center',
originY: 'top',
angle: angle,
})
canvas?.add(dormer)
actualBottomLength = Math.sqrt(
Math.pow(Math.tan(theta) * height, 2) + Math.pow(Math.tan(theta) * height * Math.tan((dormerAngle * Math.PI) / 180), 2),
)
actualHypotenuse = Math.sqrt(Math.pow(height, 2) + Math.pow(actualBottomLength, 2))
if (offsetRef > 0) {
dormerOffset = new fabric.Triangle({
fill: 'gray',
actualBottomOffsetLength = Math.sqrt(
Math.pow(Math.tan(theta) * (height + offsetRef), 2) +
Math.pow(Math.tan(theta) * (height + offsetRef) * Math.tan((dormerAngle * Math.PI) / 180), 2),
)
planeOffsetHypotenuse = Math.sqrt(Math.pow(height + offsetRef, 2) + Math.pow(bottomOffsetLength, 2))
actualOffsetHypotenuse = Math.sqrt(Math.pow(height + offsetRef, 2) + Math.pow(actualBottomOffsetLength, 2))
let angle = 0
if (directionRef === 'left') {
//서
angle = 90
} else if (directionRef === 'right') {
//동
angle = 270
} else if (directionRef === 'up') {
//북
angle = 180
}
dormer = new fabric.Triangle({
fill: 'white',
stroke: 'red',
strokeDashArray: [5, 5],
strokeWidth: 1,
width: bottomOffsetLength * 2,
height: height + offsetRef,
width: bottomLength * 2,
height: height,
left: pointer.x,
top: pointer.y,
selectable: true,
@ -369,9 +383,33 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
originX: 'center',
originY: 'top',
angle: angle,
objectId: id,
})
canvas?.add(dormerOffset)
canvas?.add(dormer)
if (offsetRef > 0) {
dormerOffset = new fabric.Triangle({
fill: 'gray',
stroke: 'red',
strokeDashArray: [5, 5],
strokeWidth: 1,
width: bottomOffsetLength * 2,
height: height + offsetRef,
left: pointer.x,
top: pointer.y,
selectable: true,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
name: dormerTempName,
originX: 'center',
originY: 'top',
angle: angle,
objectId: id,
})
canvas?.add(dormerOffset)
}
}
})
@ -418,68 +456,120 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
strokeDashArray: [0],
}) //오프셋이 있을땐 같이 도머로 만든다
const leftTriangle = new QPolygon(leftPoints, {
fill: 'white',
stroke: 'black',
strokeWidth: 1,
selectable: true,
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
viewLengthText: true,
// direction: direction,
originX: 'center',
originY: 'center',
name: dormerName,
pitch: pitch,
fontSize: lengthTextFont.fontSize.value,
fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
fontWeight: lengthTextFont.fontWeight.value,
groupPoints: groupPoints,
dormerAttributes: {
height: height,
width: width,
const leftTriangle = addPolygon(
leftPoints,
{
fill: 'white',
stroke: 'black',
strokeWidth: 1,
selectable: true,
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
viewLengthText: true,
// direction: direction,
originX: 'center',
originY: 'center',
name: dormerName,
pitch: pitch,
offsetRef: offsetRef,
offsetWidthRef: offsetWidthRef,
directionRef: directionRef,
fontSize: lengthTextFont.fontSize.value,
fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
fontWeight: lengthTextFont.fontWeight.value,
groupPoints: groupPoints,
dormerAttributes: {
height: height,
width: width,
pitch: pitch,
offsetRef: offsetRef,
offsetWidthRef: offsetWidthRef,
directionRef: directionRef,
},
lines: [
{
attributes: {
planeSize: toFixedWithoutRounding(planeOffsetHypotenuse, 1) * 10,
actualSize: toFixedWithoutRounding(actualOffsetHypotenuse, 1) * 10,
},
},
{
attributes: {
planeSize: toFixedWithoutRounding(bottomOffsetLength, 1) * 10,
actualSize: toFixedWithoutRounding(actualBottomOffsetLength, 1) * 10,
},
},
{
attributes: {
planeSize: toFixedWithoutRounding(height + offsetRef, 1) * 10,
actualSize: toFixedWithoutRounding(height + offsetRef, 1) * 10,
},
},
],
},
false,
)
leftTriangle.texts.forEach((text) => {
text.bringToFront()
})
const rightTriangle = new QPolygon(rightPoints, {
fill: 'white',
stroke: 'black',
strokeWidth: 1,
selectable: true,
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
viewLengthText: true,
// direction: direction,
originX: 'center',
originY: 'center',
name: dormerName,
pitch: pitch,
fontSize: lengthTextFont.fontSize.value,
fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
fontWeight: lengthTextFont.fontWeight.value,
groupPoints: groupPoints,
dormerAttributes: {
height: height,
width: width,
const rightTriangle = addPolygon(
rightPoints,
{
fill: 'white',
stroke: 'black',
strokeWidth: 1,
selectable: true,
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
viewLengthText: true,
// direction: direction,
originX: 'center',
originY: 'center',
name: dormerName,
pitch: pitch,
offsetRef: offsetRef,
offsetWidthRef: offsetWidthRef,
directionRef: directionRef,
fontSize: lengthTextFont.fontSize.value,
fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
fontWeight: lengthTextFont.fontWeight.value,
groupPoints: groupPoints,
dormerAttributes: {
height: height,
width: width,
pitch: pitch,
offsetRef: offsetRef,
offsetWidthRef: offsetWidthRef,
directionRef: directionRef,
},
lines: [
{
attributes: {
planeSize: toFixedWithoutRounding(height + offsetRef, 1) * 10,
actualSize: toFixedWithoutRounding(height + offsetRef, 1) * 10,
},
},
{
attributes: {
planeSize: toFixedWithoutRounding(bottomOffsetLength, 1) * 10,
actualSize: toFixedWithoutRounding(actualBottomOffsetLength, 1) * 10,
},
},
{
attributes: {
planeSize: toFixedWithoutRounding(planeOffsetHypotenuse, 1) * 10,
actualSize: toFixedWithoutRounding(actualOffsetHypotenuse, 1) * 10,
},
},
],
},
})
false,
)
// canvas?.add(leftTriangle)
// canvas?.add(rightTriangle)
//패턴
setSurfaceShapePattern(leftTriangle)
setSurfaceShapePattern(rightTriangle)
setSurfaceShapePattern(leftTriangle, roofDisplay.column, false, selectedSurface.roofMaterial, true)
setSurfaceShapePattern(rightTriangle, roofDisplay.column, false, selectedSurface.roofMaterial, true)
//방향
// drawDirectionArrow(leftTriangle)
@ -492,33 +582,57 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
if (offsetRef > 0) {
canvas?.remove(dormer)
offsetPolygon = new QPolygon(triangleToPolygon(dormer), {
selectable: true,
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
viewLengthText: true,
name: 'triangleDormerOffset',
id: id,
fill: 'rgba(255, 255, 255, 0.6)',
stroke: 'black',
strokeWidth: 1,
originX: 'center',
originY: 'top',
fontSize: lengthTextFont.fontSize.value,
fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
fontWeight: lengthTextFont.fontWeight.value,
angle: originAngle,
pitch: pitch,
dormerAttributes: {
height: height,
width: width,
offsetPolygon = addPolygon(
triangleToPolygon(dormer),
{
selectable: true,
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
viewLengthText: true,
name: 'triangleDormerOffset',
id: id,
fill: 'rgba(255, 255, 255, 0.6)',
stroke: 'black',
strokeWidth: 1,
originX: 'center',
originY: 'top',
fontSize: lengthTextFont.fontSize.value,
fontStyle: lengthTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
fontWeight: lengthTextFont.fontWeight.value,
angle: originAngle,
pitch: pitch,
offsetRef: offsetRef,
offsetWidthRef: offsetWidthRef,
directionRef: directionRef,
dormerAttributes: {
height: height,
width: width,
pitch: pitch,
offsetRef: offsetRef,
offsetWidthRef: offsetWidthRef,
directionRef: directionRef,
},
lines: [
{
attributes: {
planeSize: toFixedWithoutRounding(planeHypotenuse, 1) * 10,
actualSize: toFixedWithoutRounding(actualHypotenuse, 1) * 10,
},
},
{
attributes: {
planeSize: toFixedWithoutRounding(bottomLength * 2, 1) * 10,
actualSize: toFixedWithoutRounding(bottomLength * 2, 1) * 10,
},
},
{
attributes: {
planeSize: toFixedWithoutRounding(planeHypotenuse, 1) * 10,
actualSize: toFixedWithoutRounding(actualHypotenuse, 1) * 10,
},
},
],
},
})
false,
)
}
const groupPolygon = offsetPolygon ? [leftTriangle, rightTriangle, offsetPolygon] : [leftTriangle, rightTriangle]
@ -534,10 +648,6 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
})
canvas?.add(objectGroup)
objectGroup.getObjects().forEach((obj, index) => {
console.log(`최초 pathOffset ${index}`, obj.get('pathOffset'))
})
objectGroup._objects.forEach((obj) => {
if (obj.hasOwnProperty('texts')) {
obj.texts.forEach((text) => {
@ -548,7 +658,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
isDown = false
initEvent()
dbClickEvent()
// dbClickEvent()
if (setIsHidden) setIsHidden(false)
}
})
@ -805,7 +915,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
isDown = false
initEvent()
dbClickEvent()
// dbClickEvent()
}
})
}

View File

@ -26,7 +26,7 @@ import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
const { getMessage } = useMessage()
const { drawDirectionArrow } = usePolygon()
const { drawDirectionArrow, addPolygon } = usePolygon()
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
const resetOuterLinePoints = useResetRecoilState(outerLinePointsState)
const resetPlacementShapeDrawingPoints = useResetRecoilState(placementShapeDrawingPointsState)
@ -178,7 +178,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
}
//회전, flip등이 먹은 기준으로 새로생성
const batchSurface = new QPolygon(obj.getCurrentPoints(), {
const batchSurface = addPolygon(obj.getCurrentPoints(), {
fill: 'transparent',
stroke: 'red',
strokeWidth: 3,

View File

@ -17,16 +17,16 @@ export const usePolygon = () => {
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const pitchText = useRecoilValue(pitchTextSelector)
const addPolygon = (points, options) => {
const addPolygon = (points, options, isAddCanvas = true) => {
const polygon = new QPolygon(points, {
...options,
fontSize: lengthTextFontOptions.fontSize.value,
fill: options.fill || 'transparent',
stroke: options.stroke || '#000000',
selectable: true,
// selectable: true,
})
canvas?.add(polygon)
if (isAddCanvas) canvas?.add(polygon)
addLengthText(polygon)
return polygon