Merge branch 'dev' of https://git.jetbrains.space/nalpari/q-cast-iii/qcast-front into qcast-pub
This commit is contained in:
commit
40fa42b19b
@ -19,9 +19,12 @@ Allpainted : allPainted
|
|||||||
출폭: offset
|
출폭: offset
|
||||||
폭: width
|
폭: width
|
||||||
경사(구배): pitch
|
경사(구배): pitch
|
||||||
|
각도: degree
|
||||||
이구배: doublePitch
|
이구배: doublePitch
|
||||||
소매: sleeve
|
소매: sleeve
|
||||||
개구: openSpace
|
개구: openSpace
|
||||||
도머: dormer
|
도머: dormer
|
||||||
그림자: shadow
|
그림자: shadow
|
||||||
치수선: dimensionLine
|
치수선: dimensionLine
|
||||||
|
복도치수: planeSize
|
||||||
|
실제치수: actualSize
|
||||||
|
|||||||
@ -1,16 +1,7 @@
|
|||||||
import Roof2 from '@/components/Roof2'
|
import Roof2 from '@/components/Roof2'
|
||||||
// import { initCheck } from '@/util/session-util'
|
|
||||||
import RoofSelect from '@/app/roof2/RoofSelect'
|
import RoofSelect from '@/app/roof2/RoofSelect'
|
||||||
|
|
||||||
export default async function Roof2Page() {
|
export default async function Roof2Page() {
|
||||||
// const session = await initCheck()
|
|
||||||
const roof2Props = {
|
|
||||||
// name: session.name || '',
|
|
||||||
// userId: session.userId || '',
|
|
||||||
// email: session.email || '',
|
|
||||||
// isLoggedIn: session.isLoggedIn,
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
@ -19,7 +10,7 @@ export default async function Roof2Page() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-center my-8 pt-20">
|
<div className="flex flex-col justify-center my-8 pt-20">
|
||||||
<Roof2 {...roof2Props} />
|
<Roof2 />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -65,6 +65,7 @@ export const LINE_TYPE = {
|
|||||||
HIPANDGABLE: 'hipAndGable',
|
HIPANDGABLE: 'hipAndGable',
|
||||||
JERKINHEAD: 'jerkinhead',
|
JERKINHEAD: 'jerkinhead',
|
||||||
SHED: 'shed',
|
SHED: 'shed',
|
||||||
|
ETC: 'etc',
|
||||||
},
|
},
|
||||||
SUBLINE: {
|
SUBLINE: {
|
||||||
/**
|
/**
|
||||||
@ -116,6 +117,7 @@ export const INPUT_TYPE = {
|
|||||||
|
|
||||||
export const POLYGON_TYPE = {
|
export const POLYGON_TYPE = {
|
||||||
ROOF: 'roof',
|
ROOF: 'roof',
|
||||||
|
WALL: 'wall',
|
||||||
TRESTLE: 'trestle',
|
TRESTLE: 'trestle',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useCanvas } from '@/hooks/useCanvas'
|
|||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { useMode } from '@/hooks/useMode'
|
import { useMode } from '@/hooks/useMode'
|
||||||
import { Mode } from '@/common/common'
|
import { LINE_TYPE, Mode } from '@/common/common'
|
||||||
import { Button, Input } from '@nextui-org/react'
|
import { Button, Input } from '@nextui-org/react'
|
||||||
import RangeSlider from './ui/RangeSlider'
|
import RangeSlider from './ui/RangeSlider'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
@ -39,7 +39,7 @@ import QEmptyContextMenu from '@/components/common/context-menu/QEmptyContextMen
|
|||||||
import InitSettingsModal from './InitSettingsModal'
|
import InitSettingsModal from './InitSettingsModal'
|
||||||
import GridSettingsModal from './GridSettingsModal'
|
import GridSettingsModal from './GridSettingsModal'
|
||||||
import { SurfaceShapeModal } from '@/components/ui/SurfaceShape'
|
import { SurfaceShapeModal } from '@/components/ui/SurfaceShape'
|
||||||
import { drawDirectionStringToArrow } from '@/util/qpolygon-utils'
|
import { changeCurrentRoof, drawDirectionStringToArrow } from '@/util/qpolygon-utils'
|
||||||
import ThumbnailList from '@/components/ui/ThumbnailLIst'
|
import ThumbnailList from '@/components/ui/ThumbnailLIst'
|
||||||
import ObjectPlacement from '@/components/ui/ObjectPlacement'
|
import ObjectPlacement from '@/components/ui/ObjectPlacement'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
@ -409,6 +409,20 @@ export default function Roof2(props) {
|
|||||||
{ x: 600, y: 100 },
|
{ x: 600, y: 100 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const rectangleType1 = [
|
||||||
|
{ x: 100, y: 100 },
|
||||||
|
{ x: 100, y: 600 },
|
||||||
|
{ x: 300, y: 600 },
|
||||||
|
{ x: 300, y: 100 },
|
||||||
|
]
|
||||||
|
|
||||||
|
const rectangleType2 = [
|
||||||
|
{ x: 100, y: 100 },
|
||||||
|
{ x: 100, y: 300 },
|
||||||
|
{ x: 600, y: 300 },
|
||||||
|
{ x: 600, y: 100 },
|
||||||
|
]
|
||||||
|
|
||||||
const types = [type1, type2, type3, type4, type1A, type1B, eightPoint, eightPoint2, eightPoint3, eightPoint4, twelvePoint]
|
const types = [type1, type2, type3, type4, type1A, type1B, eightPoint, eightPoint2, eightPoint3, eightPoint4, twelvePoint]
|
||||||
const newP = [
|
const newP = [
|
||||||
{ x: 450, y: 450 },
|
{ x: 450, y: 450 },
|
||||||
@ -417,7 +431,7 @@ export default function Roof2(props) {
|
|||||||
{ x: 450, y: 850 },
|
{ x: 450, y: 850 },
|
||||||
]
|
]
|
||||||
|
|
||||||
const polygon = new QPolygon(twelvePoint, {
|
const polygon = new QPolygon(rectangleType2, {
|
||||||
fill: 'transparent',
|
fill: 'transparent',
|
||||||
stroke: 'green',
|
stroke: 'green',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
@ -658,17 +672,52 @@ export default function Roof2(props) {
|
|||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
const setAllGableRoof = () => {
|
const setHipRoof = () => {
|
||||||
let offset = Number(prompt('gable roof offset', '50'))
|
const polygon = canvas?.getObjects().find((obj) => obj.name === 'roof')
|
||||||
|
const currentRoof = polygon.lines[2]
|
||||||
|
currentRoof.attributes.type = LINE_TYPE.WALLLINE.EAVES
|
||||||
|
currentRoof.attributes.offset = 50
|
||||||
|
changeCurrentRoof(currentRoof, canvas)
|
||||||
|
}
|
||||||
|
const setGableRoof = () => {
|
||||||
|
const polygon = canvas?.getObjects().find((obj) => obj.name === 'roof')
|
||||||
|
const currentRoof = polygon.lines[2]
|
||||||
|
currentRoof.attributes.type = LINE_TYPE.WALLLINE.GABLE
|
||||||
|
currentRoof.attributes.offset = 30
|
||||||
|
changeCurrentRoof(currentRoof, canvas)
|
||||||
|
}
|
||||||
|
const setHipAndGableRoof = () => {
|
||||||
|
let offset = Number(prompt('팔작지붕 폭', '50'))
|
||||||
if (!isNaN(offset) && offset > 0) {
|
if (!isNaN(offset) && offset > 0) {
|
||||||
const polygon = canvas?.getObjects()
|
const polygon = canvas?.getObjects().find((obj) => obj.name === 'roof')
|
||||||
console.log('gable roof offset : ', offset)
|
const currentRoof = polygon.lines[2]
|
||||||
console.log('polygon : ', polygon)
|
currentRoof.attributes.type = LINE_TYPE.WALLLINE.HIPANDGABLE
|
||||||
changeAllGableRoof(polygon, offset, canvas)
|
currentRoof.attributes.width = offset
|
||||||
|
changeCurrentRoof(currentRoof, canvas)
|
||||||
} else {
|
} else {
|
||||||
alert('offset 은 0 보다 커야 함')
|
alert('폭은 0 보다 커야 함')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const setJerkInHeadRoof = () => {
|
||||||
|
let offset = Number(prompt('팔작지붕 폭', '50'))
|
||||||
|
if (!isNaN(offset) && offset > 0) {
|
||||||
|
const polygon = canvas?.getObjects().find((obj) => obj.name === 'roof')
|
||||||
|
const currentRoof = polygon.lines[2]
|
||||||
|
currentRoof.attributes.type = LINE_TYPE.WALLLINE.JERKINHEAD
|
||||||
|
currentRoof.attributes.width = offset
|
||||||
|
changeCurrentRoof(currentRoof, canvas)
|
||||||
|
} else {
|
||||||
|
alert('폭은 0 보다 커야 함')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const setWallRoof = () => {
|
||||||
|
let offset = Number(prompt('소매 폭', '0'))
|
||||||
|
const polygon = canvas?.getObjects().find((obj) => obj.name === 'roof')
|
||||||
|
const currentRoof = polygon.lines[2]
|
||||||
|
currentRoof.attributes.type = LINE_TYPE.WALLLINE.WALL
|
||||||
|
currentRoof.attributes.width = offset
|
||||||
|
changeCurrentRoof(currentRoof, canvas)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{canvas && (
|
{canvas && (
|
||||||
@ -788,16 +837,28 @@ export default function Roof2(props) {
|
|||||||
<Button className="m-1 p-2" onClick={makePolygon}>
|
<Button className="m-1 p-2" onClick={makePolygon}>
|
||||||
다각형 추가
|
다각형 추가
|
||||||
</Button>
|
</Button>
|
||||||
{templateType === 0 && (
|
{/*{templateType === 0 && (*/}
|
||||||
<>
|
{/* <>*/}
|
||||||
<Button className="m-1 p-2" onClick={makeQPolygon}>
|
<Button className="m-1 p-2" onClick={makeQPolygon}>
|
||||||
QPolygon
|
QPolygon
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
{/* </>*/}
|
||||||
)}
|
{/*)}*/}
|
||||||
<Button className={'m-1 p-2'} onClick={setAllGableRoof}>
|
<Button className={'m-1 p-2'} onClick={setHipRoof}>
|
||||||
|
용마루지붕
|
||||||
|
</Button>
|
||||||
|
<Button className={'m-1 p-2'} onClick={setHipAndGableRoof}>
|
||||||
팔작지붕
|
팔작지붕
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button className={'m-1 p-2'} onClick={setGableRoof}>
|
||||||
|
박공지붕
|
||||||
|
</Button>
|
||||||
|
<Button className={'m-1 p-2'} onClick={setJerkInHeadRoof}>
|
||||||
|
반절처지붕
|
||||||
|
</Button>
|
||||||
|
<Button className={'m-1 p-2'} onClick={setWallRoof}>
|
||||||
|
벽지붕
|
||||||
|
</Button>
|
||||||
<Button className="m-1 p-2" onClick={() => saveImage(uuidv4(), userId, setThumbnails)}>
|
<Button className="m-1 p-2" onClick={() => saveImage(uuidv4(), userId, setThumbnails)}>
|
||||||
저장
|
저장
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -2,26 +2,36 @@ import { fabric } from 'fabric'
|
|||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util'
|
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util'
|
||||||
import { calculateAngle, drawHippedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils'
|
import { calculateAngle, drawRidgeRoof, drawHippedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils'
|
||||||
import * as turf from '@turf/turf'
|
import * as turf from '@turf/turf'
|
||||||
|
import { LINE_TYPE } from '@/common/common'
|
||||||
|
|
||||||
export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||||
type: 'QPolygon',
|
type: 'QPolygon',
|
||||||
lines: [],
|
// lines: [],
|
||||||
texts: [],
|
// texts: [],
|
||||||
id: null,
|
id: null,
|
||||||
length: 0,
|
length: 0,
|
||||||
hips: [],
|
// hips: [],
|
||||||
ridges: [],
|
// ridges: [],
|
||||||
connectRidges: [],
|
// connectRidges: [],
|
||||||
cells: [],
|
// cells: [],
|
||||||
parentId: null,
|
parentId: null,
|
||||||
innerLines: [],
|
// innerLines: [],
|
||||||
children: [],
|
// children: [],
|
||||||
initOptions: null,
|
initOptions: null,
|
||||||
direction: null,
|
direction: null,
|
||||||
arrow: null,
|
arrow: null,
|
||||||
initialize: function (points, options, canvas) {
|
initialize: function (points, options, canvas) {
|
||||||
|
this.lines = []
|
||||||
|
this.texts = []
|
||||||
|
this.hips = []
|
||||||
|
this.ridges = []
|
||||||
|
this.connectRidges = []
|
||||||
|
this.cells = []
|
||||||
|
this.innerLines = []
|
||||||
|
this.children = []
|
||||||
|
|
||||||
// 소수점 전부 제거
|
// 소수점 전부 제거
|
||||||
points.forEach((point) => {
|
points.forEach((point) => {
|
||||||
point.x = Number(point.x.toFixed(1))
|
point.x = Number(point.x.toFixed(1))
|
||||||
@ -153,9 +163,42 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 보조선 그리기
|
// 보조선 그리기
|
||||||
drawHelpLine(chon = 4) {
|
drawHelpLine() {
|
||||||
// drawHelpLineInHexagon(this, chon)
|
// drawHelpLineInHexagon(this, pitch)
|
||||||
drawHippedRoof(this, chon)
|
const types = []
|
||||||
|
this.lines.forEach((line) => types.push(line.attributes.type))
|
||||||
|
|
||||||
|
const eavesType = [LINE_TYPE.WALLLINE.EAVES, LINE_TYPE.WALLLINE.HIPANDGABLE]
|
||||||
|
const gableType = [LINE_TYPE.WALLLINE.GABLE, LINE_TYPE.WALLLINE.JERKINHEAD]
|
||||||
|
|
||||||
|
const isEaves = types.every((type) => eavesType.includes(type))
|
||||||
|
const gableOdd = types.filter((type, i) => i % 2 === 0)
|
||||||
|
const gableEven = types.filter((type, i) => i % 2 === 1)
|
||||||
|
const hasShed = types.includes(LINE_TYPE.WALLLINE.SHED)
|
||||||
|
|
||||||
|
// A형, B형 박공 지붕
|
||||||
|
if (
|
||||||
|
(gableOdd.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && gableEven.every((type) => gableType.includes(type))) ||
|
||||||
|
(gableEven.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && gableOdd.every((type) => gableType.includes(type)))
|
||||||
|
) {
|
||||||
|
console.log('박공 지붕')
|
||||||
|
} else if (hasShed) {
|
||||||
|
//편류지붕
|
||||||
|
let shedIndex = 0
|
||||||
|
types.forEach((type, i) => {
|
||||||
|
if (type === LINE_TYPE.WALLLINE.SHED) {
|
||||||
|
shedIndex = i
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const shedOdd = types.filter((type, i) => i % 2 === shedIndex % 2).filter((type) => type !== LINE_TYPE.WALLLINE.SHED)
|
||||||
|
const shedEven = types.filter((type, i) => i % 2 !== shedIndex % 2)
|
||||||
|
types.forEach((type, i) => console.log(type, i, i % 2, shedIndex % 2, i % 2 === shedIndex % 2))
|
||||||
|
if (shedOdd.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && shedEven.every((type) => type === LINE_TYPE.WALLLINE.GABLE)) {
|
||||||
|
console.log('편류지붕')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
drawRidgeRoof(this.id, this.canvas)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
addLengthText() {
|
addLengthText() {
|
||||||
|
|||||||
@ -32,6 +32,8 @@ import { menusState, menuTypeState } from '@/store/menuAtom'
|
|||||||
import useMenu from '@/hooks/common/useMenu'
|
import useMenu from '@/hooks/common/useMenu'
|
||||||
import { MENU } from '@/common/common'
|
import { MENU } from '@/common/common'
|
||||||
|
|
||||||
|
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
|
||||||
|
|
||||||
export default function CanvasMenu(props) {
|
export default function CanvasMenu(props) {
|
||||||
const { menuNumber, setMenuNumber } = props
|
const { menuNumber, setMenuNumber } = props
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
@ -51,6 +53,7 @@ export default function CanvasMenu(props) {
|
|||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { handleZoomClear, handleZoom } = useCanvasEvent()
|
const { handleZoomClear, handleZoom } = useCanvasEvent()
|
||||||
const { handleMenu } = useMenu()
|
const { handleMenu } = useMenu()
|
||||||
|
const { handleEstimateSubmit } = useEstimateController()
|
||||||
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { currentCanvasPlan, saveCanvas } = usePlan()
|
const { currentCanvasPlan, saveCanvas } = usePlan()
|
||||||
@ -226,7 +229,7 @@ export default function CanvasMenu(props) {
|
|||||||
<span className="ico ico01"></span>
|
<span className="ico ico01"></span>
|
||||||
<span>{getMessage('plan.menu.estimate.docDown')}</span>
|
<span>{getMessage('plan.menu.estimate.docDown')}</span>
|
||||||
</button>
|
</button>
|
||||||
<button className="btn-frame gray ico-flx">
|
<button className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}>
|
||||||
<span className="ico ico02"></span>
|
<span className="ico ico02"></span>
|
||||||
<span>{getMessage('plan.menu.estimate.save')}</span>
|
<span>{getMessage('plan.menu.estimate.save')}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
60
src/hooks/floorPlan/estimate/useEstimateController.js
Normal file
60
src/hooks/floorPlan/estimate/useEstimateController.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
|
import { useReducer } from 'react'
|
||||||
|
|
||||||
|
const reducer = (prevState, nextState) => {
|
||||||
|
return { ...prevState, ...nextState }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const ESTIMATE_API_ENDPOINT = '/api/estimates' // API 엔드포인트 정의
|
||||||
|
|
||||||
|
const defaultEstimateData = {
|
||||||
|
name: '',
|
||||||
|
objectName: '',
|
||||||
|
estimateDate: '',
|
||||||
|
itemList: [{ id: 1, name: '' }],
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
const updateItemInList = (itemList, id, updates) => {
|
||||||
|
return itemList.map((item) => (item.id === id ? { ...item, ...updates } : item))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useEstimateController = () => {
|
||||||
|
const { promisePost } = useAxios()
|
||||||
|
const [state, setState] = useReducer(reducer, defaultEstimateData)
|
||||||
|
|
||||||
|
const updateItem = (id, updates) => {
|
||||||
|
setState({
|
||||||
|
itemList: updateItemInList(state.itemList, id, updates),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const addItem = () => {
|
||||||
|
const newId = Math.max(...state.itemList.map((item) => item.id)) + 1
|
||||||
|
setState({
|
||||||
|
itemList: [...state.itemList, { id: newId, name: '' }],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEstimateSubmit = async () => {
|
||||||
|
try {
|
||||||
|
const result = await promisePost({
|
||||||
|
url: ESTIMATE_API_ENDPOINT,
|
||||||
|
data: state,
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to submit estimate:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
state,
|
||||||
|
setState,
|
||||||
|
updateItem,
|
||||||
|
addItem,
|
||||||
|
handleEstimateSubmit,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -225,9 +225,9 @@ export function useCanvasSetting() {
|
|||||||
const option1 = settingModalFirstOptions.option1
|
const option1 = settingModalFirstOptions.option1
|
||||||
|
|
||||||
// 'allocDisplay' 할당 표시
|
// 'allocDisplay' 할당 표시
|
||||||
// 'outlineDisplay' 외벽선 표시 'outerLine', 'wallLine'
|
// 'outlineDisplay' 외벽선 표시 'outerLine', POLYGON_TYPE.WALL
|
||||||
// 'gridDisplay' 그리드 표시 'lindGrid', 'dotGrid'
|
// 'gridDisplay' 그리드 표시 'lindGrid', 'dotGrid'
|
||||||
// 'lineDisplay' 지붕선 표시 'roof', 'roofBase'
|
// 'lineDisplay' 지붕선 표시 'roof', POLYGON_TYPE.ROOF
|
||||||
// 'wordDisplay' 문자 표시
|
// 'wordDisplay' 문자 표시
|
||||||
// 'circuitNumDisplay' 회로번호 표시
|
// 'circuitNumDisplay' 회로번호 표시
|
||||||
// 'flowDisplay' 흐름방향 표시 'arrow'
|
// 'flowDisplay' 흐름방향 표시 'arrow'
|
||||||
@ -244,13 +244,13 @@ export function useCanvasSetting() {
|
|||||||
optionName = ['1']
|
optionName = ['1']
|
||||||
break
|
break
|
||||||
case 'outlineDisplay': //외벽선 표시
|
case 'outlineDisplay': //외벽선 표시
|
||||||
optionName = ['outerLine', 'wallLine']
|
optionName = ['outerLine', POLYGON_TYPE.WALL]
|
||||||
break
|
break
|
||||||
case 'gridDisplay': //그리드 표시
|
case 'gridDisplay': //그리드 표시
|
||||||
optionName = ['lindGrid', 'dotGrid']
|
optionName = ['lindGrid', 'dotGrid']
|
||||||
break
|
break
|
||||||
case 'lineDisplay': //지붕선 표시
|
case 'lineDisplay': //지붕선 표시
|
||||||
optionName = ['roof', 'roofBase']
|
optionName = ['roof', POLYGON_TYPE.ROOF]
|
||||||
break
|
break
|
||||||
case 'wordDisplay': //문자 표시
|
case 'wordDisplay': //문자 표시
|
||||||
optionName = ['6']
|
optionName = ['6']
|
||||||
|
|||||||
@ -12,9 +12,9 @@ export function useFirstOption() {
|
|||||||
const option1 = settingModalFirstOptions.option1
|
const option1 = settingModalFirstOptions.option1
|
||||||
|
|
||||||
// 'allocDisplay' 할당 표시
|
// 'allocDisplay' 할당 표시
|
||||||
// 'outlineDisplay' 외벽선 표시 'outerLine', 'wallLine'
|
// 'outlineDisplay' 외벽선 표시 'outerLine', POLYGON_TYPE.WALL
|
||||||
// 'gridDisplay' 그리드 표시 'lindGrid', 'dotGrid'
|
// 'gridDisplay' 그리드 표시 'lindGrid', 'dotGrid'
|
||||||
// 'lineDisplay' 지붕선 표시 'roof', 'roofBase'
|
// 'lineDisplay' 지붕선 표시 'roof', POLYGON_TYPE.ROOF
|
||||||
// 'wordDisplay' 문자 표시
|
// 'wordDisplay' 문자 표시
|
||||||
// 'circuitNumDisplay' 회로번호 표시
|
// 'circuitNumDisplay' 회로번호 표시
|
||||||
// 'flowDisplay' 흐름방향 표시 'arrow'
|
// 'flowDisplay' 흐름방향 표시 'arrow'
|
||||||
@ -30,13 +30,13 @@ export function useFirstOption() {
|
|||||||
optionName = ['1']
|
optionName = ['1']
|
||||||
break
|
break
|
||||||
case 'outlineDisplay': //외벽선 표시
|
case 'outlineDisplay': //외벽선 표시
|
||||||
optionName = ['outerLine', 'wallLine']
|
optionName = ['outerLine', POLYGON_TYPE.WALL]
|
||||||
break
|
break
|
||||||
case 'gridDisplay': //그리드 표시
|
case 'gridDisplay': //그리드 표시
|
||||||
optionName = ['lineGrid', 'dotGrid', 'adsorptionPoint', 'tempGrid']
|
optionName = ['lineGrid', 'dotGrid', 'adsorptionPoint', 'tempGrid']
|
||||||
break
|
break
|
||||||
case 'lineDisplay': //지붕선 표시
|
case 'lineDisplay': //지붕선 표시
|
||||||
optionName = ['roof', 'roofBase']
|
optionName = ['roof', POLYGON_TYPE.ROOF]
|
||||||
break
|
break
|
||||||
case 'wordDisplay': //문자 표시
|
case 'wordDisplay': //문자 표시
|
||||||
optionName = ['6']
|
optionName = ['6']
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import {
|
|||||||
outerLineLength2State,
|
outerLineLength2State,
|
||||||
outerLineTypeState,
|
outerLineTypeState,
|
||||||
} from '@/store/outerLineAtom'
|
} from '@/store/outerLineAtom'
|
||||||
import { calculateIntersection, distanceBetweenPoints, findClosestPoint, polygonToTurfPolygon } from '@/util/canvas-util'
|
import { calculateIntersection, distanceBetweenPoints, findClosestPoint, isPointOnLine, polygonToTurfPolygon } from '@/util/canvas-util'
|
||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
|
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
@ -23,6 +23,7 @@ import { booleanPointInPolygon } from '@turf/turf'
|
|||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { calculateAngle } from '@/util/qpolygon-utils'
|
import { calculateAngle } from '@/util/qpolygon-utils'
|
||||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||||
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
|
|
||||||
// 보조선 작성
|
// 보조선 작성
|
||||||
export function useAuxiliaryDrawing(id) {
|
export function useAuxiliaryDrawing(id) {
|
||||||
@ -80,7 +81,7 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// innerLines가 있을경우 삭제
|
// innerLines가 있을경우 삭제
|
||||||
const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roofBase')
|
const roofs = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
if (roofs.length === 0) {
|
if (roofs.length === 0) {
|
||||||
swalFire({ text: '지붕형상이 없습니다.' })
|
swalFire({ text: '지붕형상이 없습니다.' })
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
@ -561,7 +562,7 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
|
const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
/*const allLines = [...auxiliaryLines]
|
/*const allLines = [...auxiliaryLines]
|
||||||
|
|
||||||
roofBases.forEach((roofBase) => {
|
roofBases.forEach((roofBase) => {
|
||||||
@ -611,9 +612,41 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
lineHistory.current.push(newLine)
|
lineHistory.current.push(newLine)
|
||||||
|
lineHistory.current = lineHistory.current.filter((history) => history !== line1)
|
||||||
removeLine(line1)
|
removeLine(line1)
|
||||||
intersectionPoints.current.push(...interSectionPointsWithRoofLines)
|
intersectionPoints.current.push(...interSectionPointsWithRoofLines)
|
||||||
return
|
return
|
||||||
|
} else if (interSectionPointsWithRoofLines.length === 1) {
|
||||||
|
//지붕선과 만나는 점이 하나일 경우
|
||||||
|
const distance1 = distanceBetweenPoints({ x: line1.x1, y: line1.y1 }, interSectionPointsWithRoofLines[0])
|
||||||
|
const distance2 = distanceBetweenPoints({ x: line1.x2, y: line1.y2 }, interSectionPointsWithRoofLines[0])
|
||||||
|
|
||||||
|
if (!(distance1 === 0 || distance2 === 0)) {
|
||||||
|
if (distance1 >= distance2) {
|
||||||
|
const newLine = addLine([line1.x1, line1.y1, interSectionPointsWithRoofLines[0].x, interSectionPointsWithRoofLines[0].y], {
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: false,
|
||||||
|
name: 'auxiliaryLine',
|
||||||
|
isFixed: true,
|
||||||
|
})
|
||||||
|
lineHistory.current.push(newLine)
|
||||||
|
lineHistory.current = lineHistory.current.filter((history) => history !== line1)
|
||||||
|
removeLine(line1)
|
||||||
|
} else {
|
||||||
|
const newLine = addLine([line1.x2, line1.y2, interSectionPointsWithRoofLines[0].x, interSectionPointsWithRoofLines[0].y], {
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: false,
|
||||||
|
name: 'auxiliaryLine',
|
||||||
|
isFixed: true,
|
||||||
|
})
|
||||||
|
lineHistory.current.push(newLine)
|
||||||
|
lineHistory.current = lineHistory.current.filter((history) => history !== line1)
|
||||||
|
removeLine(line1)
|
||||||
|
}
|
||||||
|
intersectionPoints.current.push(interSectionPointsWithRoofLines[0])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//보조선과 만나는 점을 찾는다.
|
//보조선과 만나는 점을 찾는다.
|
||||||
@ -659,6 +692,7 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
lineHistory.current.push(newLine)
|
lineHistory.current.push(newLine)
|
||||||
|
lineHistory.current = lineHistory.current.filter((history) => history !== line1)
|
||||||
removeLine(line1)
|
removeLine(line1)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -742,7 +776,7 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
|
const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
|
|
||||||
//lineHistory.current에 있는 선들 중 startPoint와 endPoint가 겹치는 line은 제거
|
//lineHistory.current에 있는 선들 중 startPoint와 endPoint가 겹치는 line은 제거
|
||||||
// 겹치는 선 하나는 canvas에서 제거한다.
|
// 겹치는 선 하나는 canvas에서 제거한다.
|
||||||
@ -772,9 +806,13 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
})
|
})
|
||||||
const roofInnerLines = innerLines.filter((line) => {
|
const roofInnerLines = innerLines.filter((line) => {
|
||||||
const inPolygon1 =
|
const inPolygon1 =
|
||||||
tempPolygonPoints.some((point) => point.x === line.x1 && point.y === line.y1) || roofBase.inPolygon({ x: line.x1, y: line.y1 })
|
tempPolygonPoints.some((point) => point.x === line.x1 && point.y === line.y1) ||
|
||||||
|
roofBase.inPolygon({ x: line.x1, y: line.y1 }) ||
|
||||||
|
roofBase.lines.some((line) => isPointOnLine(line, { x: line.x1, y: line.y1 }))
|
||||||
const inPolygon2 =
|
const inPolygon2 =
|
||||||
tempPolygonPoints.some((point) => point.x === line.x2 && point.y === line.y2) || roofBase.inPolygon({ x: line.x2, y: line.y2 })
|
tempPolygonPoints.some((point) => point.x === line.x2 && point.y === line.y2) ||
|
||||||
|
roofBase.inPolygon({ x: line.x2, y: line.y2 }) ||
|
||||||
|
roofBase.lines.some((line) => isPointOnLine(line, { x: line.x2, y: line.y2 }))
|
||||||
|
|
||||||
if (inPolygon1 && inPolygon2) {
|
if (inPolygon1 && inPolygon2) {
|
||||||
line.attributes = { ...line.attributes, roofId: roofBase.id }
|
line.attributes = { ...line.attributes, roofId: roofBase.id }
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil'
|
|||||||
import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, pitchTextSelector } from '@/store/canvasAtom'
|
import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, pitchTextSelector } from '@/store/canvasAtom'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import { LINE_TYPE } from '@/common/common'
|
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||||
import { useLine } from '@/hooks/useLine'
|
import { useLine } from '@/hooks/useLine'
|
||||||
import { useMode } from '@/hooks/useMode'
|
import { useMode } from '@/hooks/useMode'
|
||||||
import { outerLineFixState } from '@/store/outerLineAtom'
|
import { outerLineFixState } from '@/store/outerLineAtom'
|
||||||
@ -54,7 +54,7 @@ export function useEavesGableEdit(id) {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine')
|
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
|
||||||
wallLines.forEach((wallLine) => {
|
wallLines.forEach((wallLine) => {
|
||||||
convertPolygonToLines(wallLine)
|
convertPolygonToLines(wallLine)
|
||||||
})
|
})
|
||||||
@ -160,7 +160,7 @@ export function useEavesGableEdit(id) {
|
|||||||
attributes,
|
attributes,
|
||||||
})
|
})
|
||||||
|
|
||||||
const roofBases = canvas?.getObjects().filter((obj) => obj.name === 'roofBase')
|
const roofBases = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
|
|
||||||
roofBases.forEach((roof) => {
|
roofBases.forEach((roof) => {
|
||||||
roof.innerLines.forEach((line) => {
|
roof.innerLines.forEach((line) => {
|
||||||
@ -169,7 +169,7 @@ export function useEavesGableEdit(id) {
|
|||||||
canvas.remove(roof)
|
canvas.remove(roof)
|
||||||
})
|
})
|
||||||
|
|
||||||
const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine')
|
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
|
||||||
const removeTargets = canvas.getObjects().filter((obj) => obj.name === 'pitchText')
|
const removeTargets = canvas.getObjects().filter((obj) => obj.name === 'pitchText')
|
||||||
removeTargets.forEach((obj) => {
|
removeTargets.forEach((obj) => {
|
||||||
canvas.remove(obj)
|
canvas.remove(obj)
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { usePopup } from '@/hooks/usePopup'
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
|
|
||||||
//동선이동 형 올림 내림
|
//동선이동 형 올림 내림
|
||||||
export function useMovementSetting(id) {
|
export function useMovementSetting(id) {
|
||||||
@ -41,7 +42,7 @@ export function useMovementSetting(id) {
|
|||||||
}, [type])
|
}, [type])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine') // 기존 wallLine의 visible false
|
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL) // 기존 wallLine의 visible false
|
||||||
wallLines.forEach((line) => {
|
wallLines.forEach((line) => {
|
||||||
line.set({ visible: false })
|
line.set({ visible: false })
|
||||||
})
|
})
|
||||||
@ -55,7 +56,7 @@ export function useMovementSetting(id) {
|
|||||||
addCanvasMouseEventListener('mouse:move', mouseMoveEvent)
|
addCanvasMouseEventListener('mouse:move', mouseMoveEvent)
|
||||||
return () => {
|
return () => {
|
||||||
initEvent()
|
initEvent()
|
||||||
const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine')
|
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
|
||||||
wallLines.forEach((line) => {
|
wallLines.forEach((line) => {
|
||||||
line.set({ visible: true })
|
line.set({ visible: true })
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import { LINE_TYPE } from '@/common/common'
|
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||||
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
||||||
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
||||||
import { useMode } from '@/hooks/useMode'
|
import { useMode } from '@/hooks/useMode'
|
||||||
@ -135,7 +135,7 @@ export function usePropertiesSetting(id) {
|
|||||||
hideLine(line)
|
hideLine(line)
|
||||||
})
|
})
|
||||||
|
|
||||||
const wall = addPolygonByLines(lines, { name: 'wallLine', fill: 'transparent', stroke: 'black' })
|
const wall = addPolygonByLines(lines, { name: POLYGON_TYPE.WALL, fill: 'transparent', stroke: 'black' })
|
||||||
|
|
||||||
wall.lines = [...lines]
|
wall.lines = [...lines]
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { useSwal } from '@/hooks/useSwal'
|
|||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
import { roofDisplaySelector } from '@/store/settingAtom'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
|
|
||||||
// 지붕면 할당
|
// 지붕면 할당
|
||||||
export function useRoofAllocationSetting(id) {
|
export function useRoofAllocationSetting(id) {
|
||||||
@ -81,12 +82,12 @@ export function useRoofAllocationSetting(id) {
|
|||||||
const [selectedRoofMaterial, setSelectedRoofMaterial] = useState(roofMaterials[0])
|
const [selectedRoofMaterial, setSelectedRoofMaterial] = useState(roofMaterials[0])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
|
const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
if (roofBases.length === 0) {
|
if (roofBases.length === 0) {
|
||||||
swalFire({ text: '할당할 지붕이 없습니다.' })
|
swalFire({ text: '할당할 지붕이 없습니다.' })
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
}
|
}
|
||||||
// if (type === 'roofBase') {
|
// if (type === POLYGON_TYPE.ROOF) {
|
||||||
// // 지붕면 할당
|
// // 지붕면 할당
|
||||||
//
|
//
|
||||||
// } else if ('roof') {
|
// } else if ('roof') {
|
||||||
@ -104,8 +105,8 @@ export function useRoofAllocationSetting(id) {
|
|||||||
|
|
||||||
// 선택한 지붕재로 할당
|
// 선택한 지붕재로 할당
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
|
const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine')
|
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
|
||||||
roofBases.forEach((roofBase) => {
|
roofBases.forEach((roofBase) => {
|
||||||
try {
|
try {
|
||||||
splitPolygonWithLines(roofBase)
|
splitPolygonWithLines(roofBase)
|
||||||
@ -117,7 +118,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
canvas.remove(line)
|
canvas.remove(line)
|
||||||
})
|
})
|
||||||
|
|
||||||
canvas.remove(roofBase)
|
// canvas.remove(roofBase)
|
||||||
})
|
})
|
||||||
|
|
||||||
wallLines.forEach((wallLine) => {
|
wallLines.forEach((wallLine) => {
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useEffect, useRef, useState } from 'react'
|
|||||||
import { useLine } from '@/hooks/useLine'
|
import { useLine } from '@/hooks/useLine'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import { LINE_TYPE } from '@/common/common'
|
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||||
import { useMode } from '@/hooks/useMode'
|
import { useMode } from '@/hooks/useMode'
|
||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
import { outerLineFixState } from '@/store/outerLineAtom'
|
import { outerLineFixState } from '@/store/outerLineAtom'
|
||||||
@ -60,7 +60,7 @@ export function useRoofShapePassivitySetting(id) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isLoading) return
|
if (!isLoading) return
|
||||||
addCanvasMouseEventListener('mouse:down', mouseDown)
|
addCanvasMouseEventListener('mouse:down', mouseDown)
|
||||||
const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine')
|
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
|
||||||
|
|
||||||
canvas?.remove(...wallLines)
|
canvas?.remove(...wallLines)
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ export function useRoofShapePassivitySetting(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleLineToPolygon = () => {
|
const handleLineToPolygon = () => {
|
||||||
const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
|
const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
const exceptObjs = canvas.getObjects().filter((obj) => obj.name !== 'outerLine' && obj.parent?.name !== 'outerLine')
|
const exceptObjs = canvas.getObjects().filter((obj) => obj.name !== 'outerLine' && obj.parent?.name !== 'outerLine')
|
||||||
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
exceptObjs.forEach((obj) => {
|
exceptObjs.forEach((obj) => {
|
||||||
@ -199,10 +199,10 @@ export function useRoofShapePassivitySetting(id) {
|
|||||||
let wall
|
let wall
|
||||||
|
|
||||||
if (isFix.current) {
|
if (isFix.current) {
|
||||||
wall = addPolygonByLines(lines, { name: 'wallLine', fill: 'transparent', stroke: 'black' })
|
wall = addPolygonByLines(lines, { name: POLYGON_TYPE.WALL, fill: 'transparent', stroke: 'black' })
|
||||||
} else {
|
} else {
|
||||||
// 그냥 닫을 경우 처리
|
// 그냥 닫을 경우 처리
|
||||||
wall = addPolygonByLines([...initLines.current], { name: 'wallLine', fill: 'transparent', stroke: 'black' })
|
wall = addPolygonByLines([...initLines.current], { name: POLYGON_TYPE.WALL, fill: 'transparent', stroke: 'black' })
|
||||||
lines.forEach((line, idx) => {
|
lines.forEach((line, idx) => {
|
||||||
line.attributes = initLines.current[idx].attributes
|
line.attributes = initLines.current[idx].attributes
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from 'react'
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, currentMenuState, currentObjectState, pitchTextSelector } from '@/store/canvasAtom'
|
import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, currentMenuState, currentObjectState, pitchTextSelector } from '@/store/canvasAtom'
|
||||||
import { LINE_TYPE } from '@/common/common'
|
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
import { useMode } from '@/hooks/useMode'
|
import { useMode } from '@/hooks/useMode'
|
||||||
import { useLine } from '@/hooks/useLine'
|
import { useLine } from '@/hooks/useLine'
|
||||||
@ -129,7 +129,7 @@ export function useRoofShapeSetting(id) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (shapeNum === 4) {
|
if (shapeNum === 4) {
|
||||||
canvas?.remove(canvas.getObjects().find((obj) => obj.name === 'wallLine'))
|
canvas?.remove(canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.WALL))
|
||||||
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
outerLines.forEach((line) => {
|
outerLines.forEach((line) => {
|
||||||
showLine(line)
|
showLine(line)
|
||||||
@ -376,20 +376,20 @@ export function useRoofShapeSetting(id) {
|
|||||||
// 기존 wallLine, roofBase 제거
|
// 기존 wallLine, roofBase 제거
|
||||||
canvas
|
canvas
|
||||||
.getObjects()
|
.getObjects()
|
||||||
.filter((obj) => obj.name === 'wallLine')
|
.filter((obj) => obj.name === POLYGON_TYPE.WALL)
|
||||||
.forEach((line) => {
|
.forEach((line) => {
|
||||||
canvas.remove(line)
|
canvas.remove(line)
|
||||||
})
|
})
|
||||||
|
|
||||||
canvas
|
canvas
|
||||||
.getObjects()
|
.getObjects()
|
||||||
.filter((obj) => obj.name === 'roofBase')
|
.filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
.forEach((obj) => {
|
.forEach((obj) => {
|
||||||
canvas.remove(...obj.innerLines)
|
canvas.remove(...obj.innerLines)
|
||||||
canvas.remove(obj)
|
canvas.remove(obj)
|
||||||
})
|
})
|
||||||
|
|
||||||
const polygon = addPolygonByLines(outerLines, { name: 'wallLine' })
|
const polygon = addPolygonByLines(outerLines, { name: POLYGON_TYPE.WALL })
|
||||||
polygon.lines = [...outerLines]
|
polygon.lines = [...outerLines]
|
||||||
|
|
||||||
addPitchTextsByOuterLines()
|
addPitchTextsByOuterLines()
|
||||||
|
|||||||
@ -36,10 +36,7 @@ import { QPolygon } from '@/components/fabric/QPolygon'
|
|||||||
import offsetPolygon from '@/util/qpolygon-utils'
|
import offsetPolygon from '@/util/qpolygon-utils'
|
||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||||
import * as turf from '@turf/turf'
|
import * as turf from '@turf/turf'
|
||||||
import { INPUT_TYPE, Mode } from '@/common/common'
|
import { INPUT_TYPE, LINE_TYPE, Mode, POLYGON_TYPE } from '@/common/common'
|
||||||
import { m } from 'framer-motion'
|
|
||||||
import { set } from 'react-hook-form'
|
|
||||||
import { FaWineGlassEmpty } from 'react-icons/fa6'
|
|
||||||
|
|
||||||
export function useMode() {
|
export function useMode() {
|
||||||
const [mode, setMode] = useRecoilState(modeState)
|
const [mode, setMode] = useRecoilState(modeState)
|
||||||
@ -1509,6 +1506,59 @@ export function useMode() {
|
|||||||
*벽 지붕 외곽선 생성 polygon을 입력받아 만들기
|
*벽 지붕 외곽선 생성 polygon을 입력받아 만들기
|
||||||
*/
|
*/
|
||||||
const handleOuterlinesTest2 = (polygon, offset = 50) => {
|
const handleOuterlinesTest2 = (polygon, offset = 50) => {
|
||||||
|
// TODO [ljyoung] : offset 입력 처리 후 제거 해야함.
|
||||||
|
polygon.lines.forEach((line, index) => {
|
||||||
|
line.attributes = {
|
||||||
|
type: LINE_TYPE.WALLLINE.EAVES,
|
||||||
|
offset: 40,
|
||||||
|
width: 50,
|
||||||
|
pitch: 4,
|
||||||
|
sleeve: true,
|
||||||
|
}
|
||||||
|
/*if (index === 1 || index === 3) {
|
||||||
|
line.attributes = {
|
||||||
|
type: LINE_TYPE.WALLLINE.WALL,
|
||||||
|
offset: 50, //출폭
|
||||||
|
width: 30, //폭
|
||||||
|
pitch: 4, //구배
|
||||||
|
sleeve: true, //소매
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
line.attributes = {
|
||||||
|
type: LINE_TYPE.WALLLINE.EAVES,
|
||||||
|
offset: 40,
|
||||||
|
width: 50,
|
||||||
|
pitch: 4,
|
||||||
|
sleeve: true,
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
/* if (index === 1) {
|
||||||
|
line.attributes = {
|
||||||
|
type: LINE_TYPE.WALLLINE.SHED,
|
||||||
|
offset: 20, //출폭
|
||||||
|
width: 30, //폭
|
||||||
|
pitch: 4, //구배
|
||||||
|
sleeve: true, //소매
|
||||||
|
}
|
||||||
|
} else if (index === 3) {
|
||||||
|
line.attributes = {
|
||||||
|
type: LINE_TYPE.WALLLINE.EAVES,
|
||||||
|
offset: 50, //출폭
|
||||||
|
width: 30, //폭
|
||||||
|
pitch: 4, //구배
|
||||||
|
sleeve: true, //소매
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
line.attributes = {
|
||||||
|
type: LINE_TYPE.WALLLINE.GABLE,
|
||||||
|
offset: 30,
|
||||||
|
width: 50,
|
||||||
|
pitch: 4,
|
||||||
|
sleeve: true,
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
})
|
||||||
|
|
||||||
const roof = drawRoofPolygon(polygon) //지붕 그리기
|
const roof = drawRoofPolygon(polygon) //지붕 그리기
|
||||||
roof.drawHelpLine()
|
roof.drawHelpLine()
|
||||||
// roof.divideLine()
|
// roof.divideLine()
|
||||||
@ -1677,21 +1727,6 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const drawRoofPolygon = (wall) => {
|
const drawRoofPolygon = (wall) => {
|
||||||
// TODO [ljyoung] : offset 입력 처리 후 제거 해야함.
|
|
||||||
/*wall.lines.forEach((line, index) => {
|
|
||||||
if (index === wall.lines.length - 1 || index === 3) {
|
|
||||||
line.attributes = {
|
|
||||||
type: 'gable',
|
|
||||||
offset: 30,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
line.attributes = {
|
|
||||||
type: 'hip',
|
|
||||||
offset: 50,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})*/
|
|
||||||
|
|
||||||
const polygon = createRoofPolygon(wall.points)
|
const polygon = createRoofPolygon(wall.points)
|
||||||
const originPolygon = new QPolygon(wall.points, { fontSize: 0 })
|
const originPolygon = new QPolygon(wall.points, { fontSize: 0 })
|
||||||
originPolygon.setViewLengthText(false)
|
originPolygon.setViewLengthText(false)
|
||||||
@ -1711,13 +1746,33 @@ export function useMode() {
|
|||||||
return { x1: point.x, y1: point.y }
|
return { x1: point.x, y1: point.y }
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
roof.name = 'roofBase'
|
roof.name = POLYGON_TYPE.ROOF
|
||||||
roof.setWall(wall)
|
roof.setWall(wall)
|
||||||
|
|
||||||
roof.lines.forEach((line, index) => {
|
roof.lines.forEach((line, index) => {
|
||||||
line.attributes = wall.lines[index].attributes
|
line.attributes = {
|
||||||
|
roofId: roof.id,
|
||||||
|
wallLine: wall.lines[index].id,
|
||||||
|
type: wall.lines[index].attributes.type,
|
||||||
|
offset: wall.lines[index].attributes.offset,
|
||||||
|
width: wall.lines[index].attributes.width,
|
||||||
|
pitch: wall.lines[index].attributes.pitch,
|
||||||
|
sleeve: wall.lines[index].attributes.sleeve || false,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
wall.attributes = {
|
||||||
|
roofId: roof.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
wall.lines.forEach((line, index) => {
|
||||||
|
line.attributes.roofId = roof.id
|
||||||
|
line.attributes.currentRoof = roof.lines[index].id
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('drawRoofPolygon roof : ', roof)
|
||||||
|
console.log('drawRoofPolygon wall : ', wall)
|
||||||
|
|
||||||
setRoof(roof)
|
setRoof(roof)
|
||||||
setWall(wall)
|
setWall(wall)
|
||||||
|
|
||||||
|
|||||||
@ -814,7 +814,10 @@
|
|||||||
"estimate.detail.sepcialEstimateProductInfo.calcFormula2": "PKG単価 (W)×PKG容量(W)",
|
"estimate.detail.sepcialEstimateProductInfo.calcFormula2": "PKG単価 (W)×PKG容量(W)",
|
||||||
"estimate.detail.header.showPrice": "価格表示",
|
"estimate.detail.header.showPrice": "価格表示",
|
||||||
"estimate.detail.showPrice.btn1": "Pricing",
|
"estimate.detail.showPrice.btn1": "Pricing",
|
||||||
"estimate.detail.showPrice.description": "クリックして製品の特異性を確認する",
|
"estimate.detail.showPrice.description1": "製品価格 OPEN",
|
||||||
|
"estimate.detail.showPrice.description2": "追加, 変更資材",
|
||||||
|
"estimate.detail.showPrice.description3": "添付必須",
|
||||||
|
"estimate.detail.showPrice.description4": "クリックして製品の特異性を確認する",
|
||||||
"estimate.detail.showPrice.btn2": "製品を追加",
|
"estimate.detail.showPrice.btn2": "製品を追加",
|
||||||
"estimate.detail.showPrice.btn3": "製品削除"
|
"estimate.detail.showPrice.btn3": "製品削除"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -820,7 +820,10 @@
|
|||||||
"estimate.detail.sepcialEstimateProductInfo.calcFormula2": "PKG단가(W) * PKG용량(W)",
|
"estimate.detail.sepcialEstimateProductInfo.calcFormula2": "PKG단가(W) * PKG용량(W)",
|
||||||
"estimate.detail.header.showPrice": "가격표시",
|
"estimate.detail.header.showPrice": "가격표시",
|
||||||
"estimate.detail.showPrice.btn1": "Pricing",
|
"estimate.detail.showPrice.btn1": "Pricing",
|
||||||
"estimate.detail.showPrice.description": "클릭하여 제품 특이사항 확인",
|
"estimate.detail.showPrice.description1": "제품 가격 OPEN",
|
||||||
|
"estimate.detail.showPrice.description2": "추가, 변경 자재",
|
||||||
|
"estimate.detail.showPrice.description3": "첨부필수",
|
||||||
|
"estimate.detail.showPrice.description4": "클릭하여 제품 특이사항 확인",
|
||||||
"estimate.detail.showPrice.btn2": "제품추가",
|
"estimate.detail.showPrice.btn2": "제품추가",
|
||||||
"estimate.detail.showPrice.btn3": "제품삭제"
|
"estimate.detail.showPrice.btn3": "제품삭제"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ export const settingModalFirstOptionsState = atom({
|
|||||||
default: {
|
default: {
|
||||||
option1: [
|
option1: [
|
||||||
{ id: 1, column: 'allocDisplay', name: 'modal.canvas.setting.first.option.alloc', selected: false },
|
{ id: 1, column: 'allocDisplay', name: 'modal.canvas.setting.first.option.alloc', selected: false },
|
||||||
{ id: 2, column: 'outlineDisplay', name: 'modal.canvas.setting.first.option.outline', selected: false },
|
{ id: 2, column: 'outlineDisplay', name: 'modal.canvas.setting.first.option.outline', selected: true },
|
||||||
{ id: 3, column: 'gridDisplay', name: 'modal.canvas.setting.first.option.grid', selected: false },
|
{ id: 3, column: 'gridDisplay', name: 'modal.canvas.setting.first.option.grid', selected: false },
|
||||||
{ id: 4, column: 'lineDisplay', name: 'modal.canvas.setting.first.option.roof.line', selected: false },
|
{ id: 4, column: 'lineDisplay', name: 'modal.canvas.setting.first.option.roof.line', selected: false },
|
||||||
{ id: 5, column: 'wordDisplay', name: 'modal.canvas.setting.first.option.word', selected: false },
|
{ id: 5, column: 'wordDisplay', name: 'modal.canvas.setting.first.option.word', selected: false },
|
||||||
|
|||||||
@ -263,12 +263,12 @@ export const getDegreeByChon = (chon) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* 각도를 입력받아 촌을 반환
|
||||||
|
* @param degree
|
||||||
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
export const getChonByDegree = (degree) => {
|
export const getChonByDegree = (degree) => {
|
||||||
// tan(theta) = height / base
|
return Number((Math.tan((degree * Math.PI) / 180) * 10).toFixed(2))
|
||||||
const radians = (degree * Math.PI) / 180
|
|
||||||
return Number(Number(Math.tan(radians) * 10).toFixed(2))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -521,9 +521,11 @@ export function isPointOnLine(line, point) {
|
|||||||
const a = line.y2 - line.y1
|
const a = line.y2 - line.y1
|
||||||
const b = line.x1 - line.x2
|
const b = line.x1 - line.x2
|
||||||
const c = line.x2 * line.y1 - line.x1 * line.y2
|
const c = line.x2 * line.y1 - line.x1 * line.y2
|
||||||
return a * point.x + b * point.y + c === 0
|
const result = Math.abs(a * point.x + b * point.y + c) / 100
|
||||||
}
|
|
||||||
|
|
||||||
|
// 점이 선 위에 있는지 확인
|
||||||
|
return result <= 10
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 점과 가까운 line 찾기
|
* 점과 가까운 line 찾기
|
||||||
* @param point
|
* @param point
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user