From 4cad5cfd50de0eb995d1c2cf639f19c3033a0567 Mon Sep 17 00:00:00 2001 From: Daseul Kim Date: Wed, 6 Nov 2024 15:19:44 +0900 Subject: [PATCH 01/21] =?UTF-8?q?refactor:=20QInput=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20type=20text=EB=A1=9C=20=ED=86=B5=EC=9D=BC,?= =?UTF-8?q?=20=EC=88=AB=EC=9E=90=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80?= =?UTF-8?q?=EC=82=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Playground.jsx | 4 +- src/components/common/input/QInput.jsx | 65 +++++++++++++++----------- 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx index 5cd4588c..a908ba0f 100644 --- a/src/components/Playground.jsx +++ b/src/components/Playground.jsx @@ -39,7 +39,7 @@ export default function Playground() { const [color, setColor] = useState('#ff0000') const [textInput, setTextInput] = useState('') - const [numberInput, setNumberInput] = useState(null) + const [numberInput, setNumberInput] = useState('') const [radioInput, setRadioInput] = useState('') const [checkboxInput, setCheckboxInput] = useState([]) const [selectedValue, setSelectedValue] = useState('') @@ -171,7 +171,7 @@ export default function Playground() { From b0a9e91d077e161208a329a66442ec2fcb97990f Mon Sep 17 00:00:00 2001 From: minsik Date: Wed, 6 Nov 2024 15:47:04 +0900 Subject: [PATCH 05/21] =?UTF-8?q?=EC=B4=88=EA=B8=B0=20position=20=EC=84=B8?= =?UTF-8?q?=ED=8C=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/draggable/WithDraggable.jsx | 12 ++++++------ .../placementSurface/PlacementSurfaceSetting.jsx | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/common/draggable/WithDraggable.jsx b/src/components/common/draggable/WithDraggable.jsx index 29952981..76656837 100644 --- a/src/components/common/draggable/WithDraggable.jsx +++ b/src/components/common/draggable/WithDraggable.jsx @@ -1,18 +1,18 @@ 'use client' -import { useEffect, useState } from 'react' +import { useState } from 'react' import Draggable from 'react-draggable' -export default function WithDraggable({ isShow, children, pos, handle = '' }) { - const [position, setPosition] = useState({ x: 0, y: 0 }) +export default function WithDraggable({ isShow, children, pos = { x: 0, y: 0 }, handle = '' }) { + const [position, setPosition] = useState(pos) const handleOnDrag = (e, data) => { e.stopPropagation() setPosition({ x: data.x, y: data.y }) } - useEffect(() => { - setPosition({ ...pos }) - }, []) + // useEffect(() => { + // setPosition({ ...pos }) + // }, []) return ( <> diff --git a/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx b/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx index c22d2248..431e0f85 100644 --- a/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx +++ b/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx @@ -240,7 +240,7 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } }) }, []) return ( - +

{getMessage('plan.menu.placement.surface.arrangement')}

From c53653d0819915325297fd6bab8f7b60f71e5e42 Mon Sep 17 00:00:00 2001 From: minsik Date: Wed, 6 Nov 2024 15:47:54 +0900 Subject: [PATCH 06/21] =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/setting01/SettingModal01.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/floor-plan/modal/setting01/SettingModal01.jsx b/src/components/floor-plan/modal/setting01/SettingModal01.jsx index e1bef1f0..222226c1 100644 --- a/src/components/floor-plan/modal/setting01/SettingModal01.jsx +++ b/src/components/floor-plan/modal/setting01/SettingModal01.jsx @@ -11,12 +11,12 @@ import { useRecoilValue } from 'recoil' import { usePopup } from '@/hooks/usePopup' export default function SettingModal01(props) { - const { setShowDotLineGridModal, setShowFontSettingModal, id, isConfig } = props - console.log(props) + const { id } = props const [buttonAct, setButtonAct] = useState(1) const { getMessage } = useMessage() const canGridOptionSeletorValue = useRecoilValue(canGridOptionSeletor) - const { addPopup, closePopup } = usePopup() + const { closePopup } = usePopup() + const handleBtnClick = (num) => { setButtonAct(num) } From 4e1cbd08d8f7c9089f51daf2b800924624044360 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Wed, 6 Nov 2024 16:03:55 +0900 Subject: [PATCH 07/21] =?UTF-8?q?Polygon=20=EC=84=A0=ED=83=9D=20=EC=8B=9C?= =?UTF-8?q?=20stroke=20red?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useCanvasEvent.js | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/hooks/useCanvasEvent.js b/src/hooks/useCanvasEvent.js index 4bab1fd6..9b25eedd 100644 --- a/src/hooks/useCanvasEvent.js +++ b/src/hooks/useCanvasEvent.js @@ -209,13 +209,52 @@ export function useCanvasEvent() { created: (e) => { const target = e.selected[0] setCurrentObject(target) + const { selected } = e + + if (selected.length > 0) { + selected.forEach((obj) => { + if (obj.type === 'QPolygon') { + obj.set({ stroke: 'red' }) + } + }) + canvas.renderAll() + } }, cleared: (e) => { setCurrentObject(null) + const { deselected } = e + + if (deselected.length > 0) { + deselected.forEach((obj) => { + if (obj.type === 'QPolygon') { + obj.set({ stroke: 'black' }) + } + }) + } + canvas.renderAll() }, updated: (e) => { const target = e.selected[0] setCurrentObject(target) + const { selected, deselected } = e + + if (deselected.length > 0) { + deselected.forEach((obj) => { + if (obj.type === 'QPolygon') { + obj.set({ stroke: 'black' }) + } + }) + } + + if (selected.length > 0) { + selected.forEach((obj) => { + if (obj.type === 'QPolygon') { + obj.set({ stroke: 'red' }) + } + }) + } + + canvas.renderAll() }, } From d8a69306f3aeb51be38a5dd0b961ca3083111ccd Mon Sep 17 00:00:00 2001 From: basssy Date: Wed, 6 Nov 2024 16:16:25 +0900 Subject: [PATCH 08/21] =?UTF-8?q?=EB=AC=BC=EA=B1=B4=20=EB=AA=A9=EB=A1=9D?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EC=86=8C=EC=8A=A4=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/Stuff.jsx | 130 ++++++++---------- .../management/StuffSearchCondition.jsx | 30 +--- 2 files changed, 64 insertions(+), 96 deletions(-) diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index 2603cc04..8c97347d 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -5,7 +5,7 @@ import { useRouter, usePathname } from 'next/navigation' import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' import StuffQGrid from './StuffQGrid' -import { useRecoilValue, useRecoilState, useSetRecoilState } from 'recoil' +import { useRecoilValue, useRecoilState, useSetRecoilState, useResetRecoilState } from 'recoil' import { stuffSearchState } from '@/store/stuffAtom' import { queryStringFormatter, isEmptyArray } from '@/util/common-utils' import dayjs from 'dayjs' @@ -19,7 +19,7 @@ import { sessionStore } from '@/store/commonAtom' import { SessionContext } from '@/app/SessionProvider' export default function Stuff() { - const sessionState = useRecoilValue(sessionStore) + const resetStuffRecoil = useResetRecoilState(stuffSearchState) const { session } = useContext(SessionContext) const setAppMessageState = useSetRecoilState(appMessageStore) const stuffSearchParams = useRecoilValue(stuffSearchState) @@ -34,9 +34,6 @@ export default function Stuff() { const { get } = useAxios(globalLocaleState) const gridRef = useRef() - // const [selectedRowData, setSelectedRowData] = useState([]) - // const [selectedRowDataCount, setSelectedRowDataCount] = useState(0) - const router = useRouter() const pathname = usePathname() @@ -67,10 +64,6 @@ export default function Stuff() { field: 'lastEditDatetime', minWidth: 200, headerName: getMessage('stuff.gridHeader.lastEditDatetime'), - // headerCheckboxSelection: true, - // headerCheckboxSelectionCurrentPageOnly: true, //페이징시 현재 페이지만 체크되도록 - // checkboxSelection: true, - // showDisabledCheckboxes: true, cellStyle: { justifyContent: 'center' }, valueFormatter: function (params) { if (params.value) { @@ -169,77 +162,67 @@ export default function Stuff() { // 진입시 그리드 데이터 조회 useEffect(() => { - if (isObjectNotEmpty(session)) { - if (stuffSearchParams?.code === 'S') { - const params = { - // saleStoreId: stuffSearchParams.schSelSaleStoreId, - saleStoreId: session.storeId, - schObjectNo: stuffSearchParams?.schObjectNo, - schAddress: stuffSearchParams?.schAddress, - schObjectName: stuffSearchParams?.schObjectName, - schSaleStoreName: stuffSearchParams?.schSaleStoreName, - schReceiveUser: stuffSearchParams?.schReceiveUser, - schDispCompanyName: stuffSearchParams?.schDispCompanyName, - schDateType: stuffSearchParams.schDateType, - schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), - schToDt: dayjs(new Date()).format('YYYY-MM-DD'), - startRow: (pageNo - 1) * pageSize + 1, - endRow: pageNo * pageSize, - schSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId - ? stuffSearchParams.schOtherSelSaleStoreId - : stuffSearchParams.schSelSaleStoreId, - schSortType: stuffSearchParams.schSortType, - } - async function fetchData() { - const apiUrl = `/api/object/list?${queryStringFormatter(params)}` - await get({ - url: apiUrl, - }).then((res) => { - if (!isEmptyArray(res)) { - setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) - setTotalCount(res[0].totCnt) - } - }) - } - if (stuffSearchParams?.schSelSaleStoreId !== '') { - fetchData() - } - } else if (stuffSearchParams?.code === 'M') { - //메인화면에서 진입 - const params = { - saleStoreId: session?.storeId, - schObjectNo: stuffSearchParams.schObjectNo, - schAddress: '', - schObjectName: '', - schSaleStoreName: '', - schReceiveUser: '', - schDispCompanyName: '', - schDateType: 'U', - schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), - schToDt: dayjs(new Date()).format('YYYY-MM-DD'), - startRow: (pageNo - 1) * pageSize + 1, - endRow: pageNo * pageSize, - schSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId - ? stuffSearchParams.schOtherSelSaleStoreId - : stuffSearchParams.schSelSaleStoreId, - schSortType: 'R', - } - setStuffSearch({ - ...params, + if (stuffSearchParams?.code === 'S') { + const params = { + saleStoreId: session.storeId, + schObjectNo: stuffSearchParams?.schObjectNo, + schAddress: stuffSearchParams?.schAddress, + schObjectName: stuffSearchParams?.schObjectName, + schSaleStoreName: stuffSearchParams?.schSaleStoreName, + schReceiveUser: stuffSearchParams?.schReceiveUser, + schDispCompanyName: stuffSearchParams?.schDispCompanyName, + schDateType: stuffSearchParams.schDateType, + schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), + schToDt: dayjs(new Date()).format('YYYY-MM-DD'), + startRow: (pageNo - 1) * pageSize + 1, + endRow: pageNo * pageSize, + schSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId ? stuffSearchParams.schOtherSelSaleStoreId : stuffSearchParams.schSelSaleStoreId, + schSortType: stuffSearchParams.schSortType, + } + + async function fetchData() { + const apiUrl = `/api/object/list?${queryStringFormatter(params)}` + await get({ + url: apiUrl, + }).then((res) => { + if (!isEmptyArray(res)) { + setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) + setTotalCount(res[0].totCnt) + } }) } - } - }, [pageNo, session, stuffSearchParams]) - useEffect(() => { - if (stuffSearchParams?.code === 'E') { + fetchData() + } else if (stuffSearchParams?.code === 'M') { + const params = { + saleStoreId: session?.storeId, + schObjectNo: stuffSearchParams.schObjectNo, + schAddress: '', + schObjectName: '', + schSaleStoreName: '', + schReceiveUser: '', + schDispCompanyName: '', + schDateType: 'U', + schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), + schToDt: dayjs(new Date()).format('YYYY-MM-DD'), + startRow: (pageNo - 1) * pageSize + 1, + endRow: pageNo * pageSize, + schSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId ? stuffSearchParams.schOtherSelSaleStoreId : stuffSearchParams.schSelSaleStoreId, + schSortType: 'R', + } + setStuffSearch({ + ...params, + }) + } else if (stuffSearchParams?.code === 'E') { stuffSearchParams.startRow = 1 stuffSearchParams.endRow = 1 * pageSize stuffSearchParams.schSortType = defaultSortType - setPageNo(1) + setStuffSearch({ + ...stuffSearch, + code: 'FINISH', + }) - //조회를 눌렀을때 async function fetchData() { const apiUrl = `/api/object/list?saleStoreId=${session?.storeId}&${queryStringFormatter(stuffSearchParams)}` await get({ url: apiUrl }).then((res) => { @@ -252,7 +235,10 @@ export default function Stuff() { } }) } + fetchData() + } else if (stuffSearchParams?.code === 'C') { + resetStuffRecoil() } }, [stuffSearchParams]) diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index 659ab696..1d40b61a 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -94,13 +94,13 @@ export default function StuffSearchCondition() { }) } else { setStuffSearch({ - schObjectNo: objectNo ? objectNo : '', - schSaleStoreName: saleStoreName ? saleStoreName : '', - schAddress: address ? address : '', - schObjectName: objectName ? objectName : '', - schDispCompanyName: dispCompanyName ? dispCompanyName : '', + schObjectNo: objectNo, + schSaleStoreName: saleStoreName, + schAddress: address, + schObjectName: objectName, + schDispCompanyName: dispCompanyName, schSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : stuffSearch.schSelSaleStoreId, - schReceiveUser: receiveUser ? receiveUser : '', + schReceiveUser: receiveUser, schDateType: dateType, schFromDt: dayjs(startDate).format('YYYY-MM-DD'), schToDt: dayjs(endDate).format('YYYY-MM-DD'), @@ -131,14 +131,12 @@ export default function StuffSearchCondition() { setDateType('U') setStartDate(dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD')) setEndDate(dayjs(new Date()).format('YYYY-MM-DD')) - // if (sessionState?.storeId === 'T01') { if (session?.storeId === 'T01') { setSchSelSaleStoreId('') handleClear1() //판매대리점선택 자동완성 클리어 resetStuffRecoil() setStuffSearch({ ...stuffSearch, - code: 'C', schSelSaleStoreId: '', schOtherSelSaleStoreId: '', }) @@ -156,23 +154,17 @@ export default function StuffSearchCondition() { } useEffect(() => { - // if (isObjectNotEmpty(sessionState)) { if (isObjectNotEmpty(session)) { // storeId가 T01 이거나 storeLvl이 1차점일때만 판매대리점 선택 활성화 let url - // if (sessionState?.storeId === 'T01') { if (session?.storeId === 'T01') { //T01일떄 - // url = `/api/object/saleStore/${sessionState?.storeId}/firstList?userId=${sessionState?.userId}` url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}` } else { - // if (sessionState.storeLvl === '1') { if (session.storeLvl === '1') { //T01아닌 1차점일때 - // url = `/api/object/saleStore/${sessionState?.storeId}/list?firstFlg=1&userId=${sessionState?.userId}` url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${sessionState?.userId}` } else { - // url = `/api/object/saleStore/${sessionState?.storeId}/list?firstFlg=1&userId=${sessionState?.userId}` url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` } } @@ -187,7 +179,6 @@ export default function StuffSearchCondition() { let allList let favList let otherList - // if (sessionState?.storeId === 'T01') { if (session?.storeId === 'T01') { allList = res allList.sort((a, b) => (a.saleStoreId !== 'T01') - (b.saleStoreId !== 'T01') || a.saleStoreId - b.saleStoreId) @@ -195,17 +186,14 @@ export default function StuffSearchCondition() { setSchSelSaleStoreList(allList) setFavoriteStoreList(favList) setShowSaleStoreList(favList) - // setSchSelSaleStoreId(sessionState?.storeId) setSchSelSaleStoreId(session?.storeId) setStuffSearch({ ...stuffSearch, code: 'S', - // schSelSaleStoreId: sessionState?.storeId, schSelSaleStoreId: session?.storeId, }) //T01일때 2차 판매점 호출하기 디폴트로 1차점을 본인으로 셋팅해서 세션storeId사용 - // url = `/api/object/saleStore/${sessionState?.storeId}/list?firstFlg=0&userId=${sessionState?.userId}` url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=0&userId=${session?.userId}` get({ url: url }).then((res) => { @@ -222,7 +210,6 @@ export default function StuffSearchCondition() { } }) } else { - // if (sessionState?.storeLvl === '1') { if (session?.storeLvl === '1') { allList = res favList = res.filter((row) => row.priority !== 'B') @@ -250,7 +237,6 @@ export default function StuffSearchCondition() { setOtherSaleStoreList(otherList) //선택한 2차점 세션으로 자동셋팅 - // setOtherSaleStoreId(sessionState?.storeId) setOtherSaleStoreId(session?.storeId) setStuffSearch({ ...stuffSearch, @@ -262,7 +248,6 @@ export default function StuffSearchCondition() { } }) } - // }, [sessionState]) }, [session]) //초기화 눌렀을 때 1차판매점 자동완성도.. @@ -296,7 +281,6 @@ export default function StuffSearchCondition() { stuffSearch.schSelSaleStoreId = key.saleStoreId //T01아닌 1차점은 본인으로 디폴트셋팅이고 수정할수없어서 여기안옴 //고른 1차점의 saleStoreId로 2차점 API호출하기 - // let url = `/api/object/saleStore/${key.saleStoreId}/list?firstFlg=0&userId=${sessionState?.userId}` let url = `/api/object/saleStore/${key.saleStoreId}/list?firstFlg=0&userId=${session?.userId}` let otherList get({ url: url }).then((res) => { @@ -620,7 +604,6 @@ export default function StuffSearchCondition() { value={'U'} onChange={(e) => { setDateType(e.target.value) - //setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value }) }} /> @@ -634,7 +617,6 @@ export default function StuffSearchCondition() { value={'R'} onChange={(e) => { setDateType(e.target.value) - //setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value }) }} /> From 23a5e2d2a73c9b8ad5934de48642fd17a51a7343 Mon Sep 17 00:00:00 2001 From: basssy Date: Thu, 7 Nov 2024 08:33:23 +0900 Subject: [PATCH 09/21] =?UTF-8?q?=EA=B2=AC=EC=A0=81=EC=84=9C=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=ED=99=94=EB=A9=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/estimate/Estimate.jsx | 27 +++++++++------- src/components/management/StuffDetail.jsx | 11 +------ .../estimate/useEstimateController.js | 31 ++++++++++++++++--- 3 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index 813962b3..f12d7c69 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -1,9 +1,9 @@ 'use client' -import { useEffect, useState, useRef } from 'react' +import { useEffect, useState, useContext } from 'react' import { useRecoilValue } from 'recoil' import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' -import { sessionStore } from '@/store/commonAtom' +import { SessionContext } from '@/app/SessionProvider' import { useMessage } from '@/hooks/useMessage' import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import SingleDatePicker from '../common/datepicker/SingleDatePicker' @@ -21,10 +21,6 @@ export default function Estimate({ params }) { const [planNo, setPlanNo] = useState('') //플랜번호 const [files, setFiles] = useState([]) // 보내는 첨부파일 - //체크박스 - const [checkItems, setCheckItems] = useState(new Set()) - const [checkedList, setCheckedList] = useState([]) - const [showContentCode, setShowContentCode] = useState('ATTR001') //견적특이사항 접고 펼치기 @@ -40,7 +36,7 @@ export default function Estimate({ params }) { setStartDate, } - const sessionState = useRecoilValue(sessionStore) + const { session } = useContext(SessionContext) const objectRecoil = useRecoilValue(floorPlanObjectState) //견적서 상세데이터 @@ -127,6 +123,19 @@ export default function Estimate({ params }) { event.stopPropagation() } + // 첨부파일 state에 넣기 + useEffect(() => { + // console.log(files) + if (files.length > 0) { + files.map((row) => { + setState({ fileList: row.data }) + }) + } else { + console.log('첨부파일 없음') + setState({ fileList: [] }) + } + }, [files]) + return (
@@ -206,7 +215,6 @@ export default function Estimate({ params }) { defaultValue={state?.charger} onChange={(e) => { //담당자 charger - // console.log('담당자:::::', e.target.value) setState({ charger: e.target.value }) }} /> @@ -227,7 +235,6 @@ export default function Estimate({ params }) { defaultValue={state?.objectName} onChange={(e) => { //안건명 objectName - // console.log('안건명::::', e.target.value) setState({ objectName: e.target.value }) }} /> @@ -244,7 +251,6 @@ export default function Estimate({ params }) { if (isObjectNotEmpty(e)) { setState({ objectNameOmit: e.clCodeNm }) } else { - // console.log('XXX') setState({ objectNameOmit: '' }) } }} @@ -342,7 +348,6 @@ export default function Estimate({ params }) { defaultValue={state?.remarks} onChange={(e) => { //비고 - // console.log('비고:::::', e.target.value) setState({ remarks: e.target.value }) }} /> diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 9a455216..61cdc1df 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -11,7 +11,6 @@ import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty } from '@/util/common-u import { useMessage } from '@/hooks/useMessage' import { useForm } from 'react-hook-form' import { useRecoilValue, useSetRecoilState } from 'recoil' -import { sessionStore } from '@/store/commonAtom' import { SessionContext } from '@/app/SessionProvider' import FindAddressPop from './popup/FindAddressPop' import PlanRequestPop from './popup/PlanRequestPop' @@ -28,7 +27,6 @@ export default function StuffDetail() { const [selOptions, setSelOptions] = useState('') //선택한 1차점 const [otherSelOptions, setOtherSelOptions] = useState('') //선택한 1차점외 - const sessionState = useRecoilValue(sessionStore) const { session } = useContext(SessionContext) const router = useRouter() @@ -320,12 +318,11 @@ export default function StuffDetail() { let firstList let otherList let favList - // if (sessionState?.storeId === 'T01') { if (session?.storeId === 'T01') { url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}` } else { if (session.storeLvl === '1') { - url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${sessionState?.userId}` + url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` } else { url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` } @@ -400,7 +397,6 @@ export default function StuffDetail() { } }) } - // }, [objectNo, sessionState]) }, [objectNo, session]) useEffect(() => { @@ -1279,9 +1275,7 @@ export default function StuffDetail() { //1차점 or 2차점 안고르고 임시저장하면 if (params.saleStoreId == '') { - // params.saleStoreId = sessionState.storeId params.saleStoreId = session.storeId - // params.saleStoreLevel = sessionState.storeLvl params.saleStoreLevel = session.storeLvl } @@ -1445,7 +1439,6 @@ export default function StuffDetail() {
- {/* {sessionState?.storeId === 'T01' && ( */} {session?.storeId === 'T01' && ( <>
@@ -1479,7 +1472,6 @@ export default function StuffDetail() { )} - {/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl === '1' && ( */} {session?.storeId !== 'T01' && session?.storeLvl === '1' && ( <>
@@ -1511,7 +1503,6 @@ export default function StuffDetail() {
)} - {/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl !== '1' && ( */} {session?.storeId !== 'T01' && session?.storeLvl !== '1' && ( <>
diff --git a/src/hooks/floorPlan/estimate/useEstimateController.js b/src/hooks/floorPlan/estimate/useEstimateController.js index 87fa15ca..2b92a14a 100644 --- a/src/hooks/floorPlan/estimate/useEstimateController.js +++ b/src/hooks/floorPlan/estimate/useEstimateController.js @@ -1,9 +1,11 @@ import { useAxios } from '@/hooks/useAxios' -import { useEffect, useReducer, useState } from 'react' +import { useContext, useEffect, useReducer, useState } from 'react' import { useRecoilState, useRecoilValue } from 'recoil' import { globalLocaleStore } from '@/store/localeAtom' import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { isObjectNotEmpty } from '@/util/common-utils' +import { SessionContext } from '@/app/SessionProvider' + const reducer = (prevState, nextState) => { return { ...prevState, ...nextState } } @@ -41,6 +43,7 @@ const defaultEstimateData = { unit: '', }, ], + fileList: [], } // Helper functions @@ -51,14 +54,14 @@ const updateItemInList = (itemList, itemId, updates) => { } export const useEstimateController = (planNo) => { + const { session } = useContext(SessionContext) const globalLocaleState = useRecoilValue(globalLocaleStore) const objectRecoil = useRecoilValue(floorPlanObjectState) const [estimateData, setEstimateData] = useRecoilState(estimateState) - const { get, post } = useAxios(globalLocaleState) + const { get, post, promisePost } = useAxios(globalLocaleState) const [isLoading, setIsLoading] = useState(false) - const { promisePost } = useAxios() const [state, setState] = useReducer(reducer, defaultEstimateData) useEffect(() => { @@ -123,12 +126,32 @@ export const useEstimateController = (planNo) => { } useEffect(() => { - setEstimateData({ ...state }) + setEstimateData({ ...state, userId: session.userId }) + //sapSalesStoreCd 추가예정 필수값 + // setEstimateData({ ...state, userId: session.userId, sapSalesStoreCd : session.sapSalesStoreCd }) }, [state]) //견적서 저장 const handleEstimateSubmit = async () => { console.log('::담긴 estimateData:::', estimateData) + //1. 첨부파일 저장 + const formData = new FormData() + formData.append('file', estimateData.fileList) + formData.append('objectNo', estimateData.objectNo) + formData.append('planNo', estimateData.planNo) + formData.append('category', '10') + formData.append('userId', estimateData.userId) + for (const value of formData.values()) { + console.log('formData::', value) + } + + await promisePost({ url: '/api/file/fileUpload', data: formData }).then((res) => { + console.log('파일저장::::::::::', res) + }) + + //2. 상세데이터 저장 + + console.log('상세저장시작!!') return try { const result = await promisePost({ From b94be836df97f5e6df42b74acf23ced7944d0801 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Thu, 7 Nov 2024 10:27:25 +0900 Subject: [PATCH 10/21] chore: remove unused files --- src/app/intro/page.jsx | 12 ---- src/components/Intro.jsx | 142 --------------------------------------- src/util/session-util.js | 12 ---- 3 files changed, 166 deletions(-) delete mode 100644 src/app/intro/page.jsx delete mode 100644 src/components/Intro.jsx delete mode 100644 src/util/session-util.js diff --git a/src/app/intro/page.jsx b/src/app/intro/page.jsx deleted file mode 100644 index ebf1081b..00000000 --- a/src/app/intro/page.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import Intro from '@/components/Intro' -import { initCheck } from '@/util/session-util' - -export default async function IntroPage() { - return ( - <> -
- -
- - ) -} diff --git a/src/components/Intro.jsx b/src/components/Intro.jsx deleted file mode 100644 index a6825af7..00000000 --- a/src/components/Intro.jsx +++ /dev/null @@ -1,142 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' - -import Link from 'next/link' - -import { useRecoilState } from 'recoil' -import { modalContent, modalState } from '@/store/modalAtom' - -import { useAxios } from '@/hooks/useAxios' - -import { Button } from '@nextui-org/react' - -import SingleDatePicker from './common/datepicker/SingleDatePicker' -import RangeDatePicker from './common/datepicker/RangeDatePicker' -import QGrid from './common/grid/QGrid' -import { useSwal } from '@/hooks/useSwal' - -export default function Intro() { - const { get } = useAxios() - const { swalFire } = useSwal() - - // const [open, setOpen] = useState(false) - const [startDate, setStartDate] = useState(new Date()) - const singleDatePickerProps = { - startDate, - setStartDate, - } - - const [dateRange, setDateRange] = useState([null, null]) - const [startRangeDate, endRangeDate] = dateRange - const rangeDatePickerProps = { - startRangeDate, - endRangeDate, - setDateRange, - } - - // const gridProps = { - // isPageable: false, - // } - const [gridProps, setGridProps] = useState({ - gridData: [], - isPageable: false, - }) - - const [open, setOpen] = useRecoilState(modalState) - const [contents, setContent] = useRecoilState(modalContent) - - const modelProps = { - open, - setOpen, - } - - const ipsum = ( - <> -

title

-

- 저작자·발명가·과학기술자와 예술가의 권리는 법률로써 보호한다. 이 헌법은 1988년 2월 25일부터 시행한다. 다만, 이 헌법을 시행하기 위하여 필요한 - 법률의 제정·개정과 이 헌법에 의한 대통령 및 국회의원의 선거 기타 이 헌법시행에 관한 준비는 이 헌법시행 전에 할 수 있다. -

-

- 국가는 주택개발정책등을 통하여 모든 국민이 쾌적한 주거생활을 할 수 있도록 노력하여야 한다. 통신·방송의 시설기준과 신문의 기능을 보장하기 - 위하여 필요한 사항은 법률로 정한다. -

-

- 국회에서 의결된 법률안은 정부에 이송되어 15일 이내에 대통령이 공포한다. 선거에 관한 경비는 법률이 정하는 경우를 제외하고는 정당 또는 - 후보자에게 부담시킬 수 없다. -

- - ) - - useEffect(() => { - async function fetchData() { - // const response = await fetch('https://www.ag-grid.com/example-assets/space-mission-data.json') - // const data = await response.json() - const data = await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' }) - setGridProps({ ...gridProps, gridData: data }) - } - fetchData() - }, []) - - return ( - <> -
- - - -
-
-
Single Date Picker
-
- -
-
-
-
Range Date Picker
-
- -
-
-
-
QGrid
-
- -
-
-
-
QModal
-
- {/* - {ipsum} */} - -
-
-
-
QToast
-
- -
-
- - ) -} diff --git a/src/util/session-util.js b/src/util/session-util.js deleted file mode 100644 index 6f818e43..00000000 --- a/src/util/session-util.js +++ /dev/null @@ -1,12 +0,0 @@ -import { checkSession } from '@/lib/user' -import { redirect } from 'next/navigation' - -export const initCheck = async () => { - const { session } = await checkSession() - - if (!session.isLoggedIn) { - redirect('/login') - } - - return session -} From 7365279bdaae61095ab47837aa156c9fa3d92653 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 7 Nov 2024 10:52:11 +0900 Subject: [PATCH 11/21] =?UTF-8?q?=EC=A7=80=EB=B6=95=ED=98=95=EC=83=81?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=ED=8E=B8=EB=A5=98=20=EC=A7=80=EB=B6=95=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EC=8B=9C=20=EB=B0=A9=ED=96=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/roofcover/useRoofShapeSetting.js | 7 ++++++- src/hooks/useMode.js | 3 +++ src/util/qpolygon-utils.js | 6 ++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index 2823415d..21948de0 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -170,6 +170,7 @@ export function useRoofShapeSetting(id) { //기존 wallLine 삭제 let outerLines + let direction switch (shapeNum) { case 1: { @@ -196,6 +197,7 @@ export function useRoofShapeSetting(id) { // 서쪽 initLineSetting() outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + direction = 'west' outerLines.forEach((line) => { setWestAndEastRoof(line) @@ -240,6 +242,7 @@ export function useRoofShapeSetting(id) { case 6: { initLineSetting() outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + direction = 'east' outerLines.forEach((line) => { setWestAndEastRoof(line) @@ -285,6 +288,7 @@ export function useRoofShapeSetting(id) { case 7: { initLineSetting() outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + direction = 'south' outerLines.forEach((line) => { setSouthAndNorthRoof(line) @@ -329,6 +333,7 @@ export function useRoofShapeSetting(id) { case 8: { initLineSetting() outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + direction = 'north' outerLines.forEach((line) => { setSouthAndNorthRoof(line) @@ -389,7 +394,7 @@ export function useRoofShapeSetting(id) { canvas.remove(obj) }) - const polygon = addPolygonByLines(outerLines, { name: POLYGON_TYPE.WALL }) + const polygon = addPolygonByLines(outerLines, { name: POLYGON_TYPE.WALL, direction }) polygon.lines = [...outerLines] addPitchTextsByOuterLines() diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 486bc8e9..6f90b028 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -1746,6 +1746,9 @@ export function useMode() { return { x1: point.x, y1: point.y } }), ) + if (wall.direction) { + roof.direction = wall.direction + } roof.name = POLYGON_TYPE.ROOF roof.setWall(wall) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index e373df8d..90deebfc 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1340,6 +1340,7 @@ export const splitPolygonWithLines = (polygon) => { }) const newRoofs = removeDuplicatePolygons(roofs) + newRoofs.forEach((roofPoint, index) => { let defense, pitch const polygonLines = [...polygon.lines] @@ -1378,7 +1379,8 @@ export const splitPolygonWithLines = (polygon) => { } }) - const direction = representLine.direction + const direction = newRoofs.length === 1 ? polygon.direction : representLine.direction + const polygonDirection = polygon.direction switch (direction) { case 'top': @@ -1406,7 +1408,7 @@ export const splitPolygonWithLines = (polygon) => { originY: 'center', selectable: true, defense: defense, - direction: defense, + direction: newRoofs.length === 1 ? polygonDirection : defense, pitch: pitch, }) From ee59b0498a4de27a61b82b1fe5336a791ec9b630 Mon Sep 17 00:00:00 2001 From: basssy Date: Thu, 7 Nov 2024 11:35:18 +0900 Subject: [PATCH 12/21] =?UTF-8?q?=EA=B2=AC=EC=A0=81=EC=84=9C=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=B2=A8=EB=B6=80=ED=8C=8C=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/estimate/Estimate.jsx | 60 ++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index f12d7c69..f794cb50 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -3,7 +3,6 @@ import { useEffect, useState, useContext } from 'react' import { useRecoilValue } from 'recoil' import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' -import { SessionContext } from '@/app/SessionProvider' import { useMessage } from '@/hooks/useMessage' import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import SingleDatePicker from '../common/datepicker/SingleDatePicker' @@ -15,11 +14,15 @@ import dayjs from 'dayjs' import { useCommonCode } from '@/hooks/common/useCommonCode' import Select from 'react-select' import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController' +import { SessionContext } from '@/app/SessionProvider' export default function Estimate({ params }) { + const { session } = useContext(SessionContext) const [objectNo, setObjectNo] = useState('') //물건번호 const [planNo, setPlanNo] = useState('') //플랜번호 + const [files, setFiles] = useState([]) // 보내는 첨부파일 + const [originFiles, setOriginFiles] = useState([]) //기존 첨부파일 const [showContentCode, setShowContentCode] = useState('ATTR001') @@ -36,7 +39,6 @@ export default function Estimate({ params }) { setStartDate, } - const { session } = useContext(SessionContext) const objectRecoil = useRecoilValue(floorPlanObjectState) //견적서 상세데이터 @@ -48,16 +50,14 @@ export default function Estimate({ params }) { const [specialNoteList, setSpecialNoteList] = useState([]) const globalLocaleState = useRecoilValue(globalLocaleStore) - const { get, post } = useAxios(globalLocaleState) + const { get, promisePost } = useAxios(globalLocaleState) const { getMessage } = useMessage() const { setMenuNumber } = useCanvasMenu() + //새로 추가한 첨부파일 props const fileUploadProps = { - // objectNo: '', - // planNo: params.pid, - // category: '10', uploadFiles: files, setUploadFiles: setFiles, } @@ -123,24 +123,42 @@ export default function Estimate({ params }) { event.stopPropagation() } - // 첨부파일 state에 넣기 + // 추가한 첨부파일 state에 넣기 useEffect(() => { - // console.log(files) - if (files.length > 0) { + if (isNotEmptyArray(files)) { files.map((row) => { setState({ fileList: row.data }) }) } else { - console.log('첨부파일 없음') setState({ fileList: [] }) } }, [files]) + //상세에서 내려온 첨부파일 set 만들기 + useEffect(() => { + if (isNotEmptyArray(state.fileList)) { + setOriginFiles(state.fileList) + } + }, [state?.fileList]) + + // 기존첨부파일 삭제 + const deleteOriginFile = async (objectNo, no) => { + const delParams = { + userId: session.userId, + objectNo: objectNo, + no: no, + } + await promisePost({ url: 'api/file/fileDelete', data: delParams }).then((res) => { + if (res.status === 204) { + setOriginFiles(originFiles.filter((file) => file.objectNo === objectNo && file.no !== no)) + } + }) + } + return (
{/* 물건번호, 견적서번호, 등록일, 변경일시 시작 */} - {/*
*/}
@@ -395,6 +413,23 @@ export default function Estimate({ params }) { {getMessage('estimate.detail.header.fileList2')} + +
+
    + {isNotEmptyArray(originFiles) && + originFiles.map((originFile) => { + return ( +
  • + + {originFile.faileName} + + +
  • + ) + })} +
+
+ @@ -444,7 +479,7 @@ export default function Estimate({ params }) { ) })}
- {/* 견적특이사항 선택한 내용?영역시작 */} + {/* 견적특이사항 선택한 내용 영역시작 */}
{specialNoteList.map((row) => { if (row.code === showContentCode) { @@ -575,7 +610,6 @@ export default function Estimate({ params }) {
{/* 기본정보끝 */} - {/* */}
) From 3e5e5963a42ec38462948cf3e3c2d21964f6d88c Mon Sep 17 00:00:00 2001 From: basssy Date: Thu, 7 Nov 2024 11:45:13 +0900 Subject: [PATCH 13/21] =?UTF-8?q?=EB=AC=BC=EA=B1=B4=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=86=8C=EC=8A=A4=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/Stuff.jsx | 2 -- .../management/StuffSearchCondition.jsx | 16 +++++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index 8c97347d..bdd3e1d0 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -9,13 +9,11 @@ import { useRecoilValue, useRecoilState, useSetRecoilState, useResetRecoilState import { stuffSearchState } from '@/store/stuffAtom' import { queryStringFormatter, isEmptyArray } from '@/util/common-utils' import dayjs from 'dayjs' -import { isObjectNotEmpty } from '@/util/common-utils' import { convertNumberToPriceDecimal } from '@/util/common-utils' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import KO from '@/locales/ko.json' import JA from '@/locales/ja.json' import QPagination from '../common/pagination/QPagination' -import { sessionStore } from '@/store/commonAtom' import { SessionContext } from '@/app/SessionProvider' export default function Stuff() { diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index 1d40b61a..9b76dca0 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -12,7 +12,6 @@ import { isEmptyArray } from '@/util/common-utils' import dayjs from 'dayjs' import Link from 'next/link' import SingleDatePicker from '../common/datepicker/SingleDatePicker' -import { sessionStore } from '@/store/commonAtom' import { useMessage } from '@/hooks/useMessage' import { isObjectNotEmpty } from '@/util/common-utils' @@ -20,7 +19,6 @@ import { SessionContext } from '@/app/SessionProvider' export default function StuffSearchCondition() { const { session } = useContext(SessionContext) - const sessionState = useRecoilValue(sessionStore) const setAppMessageState = useSetRecoilState(appMessageStore) const globalLocaleState = useRecoilValue(globalLocaleStore) const { getMessage } = useMessage() @@ -163,7 +161,7 @@ export default function StuffSearchCondition() { } else { if (session.storeLvl === '1') { //T01아닌 1차점일때 - url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${sessionState?.userId}` + url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` } else { url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` } @@ -385,7 +383,7 @@ export default function StuffSearchCondition() { ref={objectNoRef} className="input-light" defaultValue={stuffSearch?.schObjectNo ? stuffSearch.schObjectNo : objectNo} - onChange={(e) => { + onChange={() => { setObjectNo(objectNoRef.current.value) }} onKeyUp={handleByOnKeyUp} @@ -400,7 +398,7 @@ export default function StuffSearchCondition() { ref={saleStoreNameRef} className="input-light" defaultValue={stuffSearch?.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName} - onChange={(e) => { + onChange={() => { setSaleStoreName(saleStoreNameRef.current.value) }} onKeyUp={handleByOnKeyUp} @@ -415,7 +413,7 @@ export default function StuffSearchCondition() { ref={addressRef} className="input-light" defaultValue={stuffSearch?.schAddress ? stuffSearch.schAddress : address} - onChange={(e) => { + onChange={() => { setAddress(addressRef.current.value) }} onKeyUp={handleByOnKeyUp} @@ -430,7 +428,7 @@ export default function StuffSearchCondition() { ref={dispCompanyNameRef} className="input-light" defaultValue={stuffSearch?.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName} - onChange={(e) => { + onChange={() => { setDispCompanyName(dispCompanyNameRef.current.value) }} onKeyUp={handleByOnKeyUp} @@ -447,7 +445,7 @@ export default function StuffSearchCondition() { ref={objectNameRef} className="input-light" defaultValue={stuffSearch?.schObjectName ? stuffSearch.schObjectName : objectName} - onChange={(e) => { + onChange={() => { setobjectName(objectNameRef.current.value) }} onKeyUp={handleByOnKeyUp} @@ -462,7 +460,7 @@ export default function StuffSearchCondition() { className="input-light" ref={receiveUserRef} defaultValue={stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser} - onChange={(e) => { + onChange={() => { setReceiveUser(receiveUserRef.current.value) }} onKeyUp={handleByOnKeyUp} From d6041b43226de27b9015525dc1d5a1370b7fb41d Mon Sep 17 00:00:00 2001 From: basssy Date: Thu, 7 Nov 2024 13:08:50 +0900 Subject: [PATCH 14/21] =?UTF-8?q?=EB=AC=BC=EA=B1=B4=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/Stuff.jsx | 4 +++- src/components/management/StuffSearchCondition.jsx | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index bdd3e1d0..58b1c002 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -190,7 +190,9 @@ export default function Stuff() { }) } - fetchData() + if (stuffSearch.schSelSaleStoreId !== '') { + fetchData() + } } else if (stuffSearchParams?.code === 'M') { const params = { saleStoreId: session?.storeId, diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index 9b76dca0..7bd8f456 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -321,6 +321,12 @@ export default function StuffSearchCondition() { useEffect(() => { setStartDate(stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD')) setEndDate(stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD')) + setObjectNo(stuffSearch.schObjectNo ? stuffSearch.schObjectNo : objectNo) + setSaleStoreName(stuffSearch.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName) + setAddress(stuffSearch.schAddress ? stuffSearch.schAddress : address) + setobjectName(stuffSearch.schObjectName ? stuffSearch.schObjectName : objectName) + setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName) + setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser) }, [stuffSearch]) useEffect(() => { From 78a6ba1ed79bf37dabc10831ade9054a7d1a730e Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 7 Nov 2024 13:40:39 +0900 Subject: [PATCH 15/21] =?UTF-8?q?=ED=8E=B8=EB=A5=98=EC=A7=80=EB=B6=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 2 +- src/components/fabric/QPolygon.js | 49 ++++++++++++++++++++------- src/hooks/useMode.js | 26 +++++++++----- src/util/qpolygon-utils.js | 56 +++++++++++++++++++++++++++++-- 4 files changed, 109 insertions(+), 24 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index fad075bd..82ba40c1 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -431,7 +431,7 @@ export default function Roof2(props) { { x: 450, y: 850 }, ] - const polygon = new QPolygon(rectangleType2, { + const polygon = new QPolygon(type2, { fill: 'transparent', stroke: 'green', strokeWidth: 1, diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 44cbfb37..8e450e77 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -2,7 +2,7 @@ import { fabric } from 'fabric' import { v4 as uuidv4 } from 'uuid' import { QLine } from '@/components/fabric/QLine' import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util' -import { calculateAngle, drawRidgeRoof, drawHippedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' +import { calculateAngle, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' import * as turf from '@turf/turf' import { LINE_TYPE } from '@/common/common' @@ -187,7 +187,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { 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 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) @@ -199,18 +199,41 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { ) { console.log('박공 지붕') } else if (hasShed) { - //편류지붕 - let shedIndex = 0 - types.forEach((type, i) => { - if (type === LINE_TYPE.WALLLINE.SHED) { - shedIndex = i - } + const sheds = this.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED) + const areLinesParallel = function (line1, line2) { + const angle1 = calculateAngle(line1.startPoint, line1.endPoint) + const angle2 = calculateAngle(line2.startPoint, line2.endPoint) + return angle1 === angle2 + } + + let isShedRoof = true + sheds.forEach((shed, i) => { + isShedRoof = areLinesParallel(shed, sheds[(i + 1) % sheds.length]) }) - 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('편류지붕') + if (isShedRoof) { + const eaves = this.lines + .filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.EAVES) + .filter((line) => { + const angle1 = calculateAngle(sheds[0].startPoint, sheds[0].endPoint) + const angle2 = calculateAngle(line.startPoint, line.endPoint) + if (Math.abs(angle1 - angle2) === 180) { + return line + } + }) + if (eaves.length > 0) { + const gables = this.lines.filter((line) => sheds.includes(line) === false && eaves.includes(line) === false) + const isGable = gables.every((line) => gableType.includes(line.attributes.type)) + console.log('isGable : ', isGable) + if (isGable) { + drawShedRoof(this.id, this.canvas) + } else { + drawRidgeRoof(this.id, this.canvas) + } + } else { + drawRidgeRoof(this.id, this.canvas) + } + } else { + drawRidgeRoof(this.id, this.canvas) } } else { drawRidgeRoof(this.id, this.canvas) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 486bc8e9..1b91fb7e 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -36,7 +36,7 @@ import { QPolygon } from '@/components/fabric/QPolygon' import offsetPolygon from '@/util/qpolygon-utils' import { isObjectNotEmpty } from '@/util/common-utils' import * as turf from '@turf/turf' -import { INPUT_TYPE, LINE_TYPE, Mode, POLYGON_TYPE } from '@/common/common' +import { INPUT_TYPE, Mode, POLYGON_TYPE } from '@/common/common' export function useMode() { const [mode, setMode] = useRecoilState(modeState) @@ -1515,9 +1515,17 @@ export function useMode() { pitch: 4, sleeve: true, } - /*if (index === 1 || index === 3) { + /*if (index === 1) { line.attributes = { - type: LINE_TYPE.WALLLINE.WALL, + type: LINE_TYPE.WALLLINE.SHED, + offset: 30, //출폭 + width: 30, //폭 + pitch: 4, //구배 + sleeve: true, //소매 + } + } else if (index === 5 || index === 3) { + line.attributes = { + type: LINE_TYPE.WALLLINE.EAVES, offset: 50, //출폭 width: 30, //폭 pitch: 4, //구배 @@ -1525,8 +1533,8 @@ export function useMode() { } } else { line.attributes = { - type: LINE_TYPE.WALLLINE.EAVES, - offset: 40, + type: LINE_TYPE.WALLLINE.GABLE, + offset: 20, width: 50, pitch: 4, sleeve: true, @@ -1750,8 +1758,13 @@ export function useMode() { roof.setWall(wall) roof.lines.forEach((line, index) => { + const lineLength = Math.sqrt( + Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), + ) line.attributes = { roofId: roof.id, + planeSize: lineLength, + actualSize: lineLength, wallLine: wall.lines[index].id, type: wall.lines[index].attributes.type, offset: wall.lines[index].attributes.offset, @@ -1770,9 +1783,6 @@ export function useMode() { line.attributes.currentRoof = roof.lines[index].id }) - console.log('drawRoofPolygon roof : ', roof) - console.log('drawRoofPolygon wall : ', wall) - setRoof(roof) setWall(wall) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index e373df8d..a45fa6aa 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1477,6 +1477,42 @@ function calculateAngleBetweenLines(line1, line2) { return (angleInRadians * 180) / Math.PI } +/** + * 한쪽흐름 지붕 + * @param roofId + * @param canvas + */ +export const drawShedRoof = (roofId, canvas) => { + const roof = canvas?.getObjects().find((object) => object.id === roofId) + const hasNonParallelLines = roof.lines.filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2) + if (hasNonParallelLines.length > 0) { + alert('대각선이 존재합니다.') + return + } + + const sheds = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED) + const eaves = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.EAVES) + const gables = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.GABLE) + + console.log('gable', gables) + + let shedDegree = sheds[0].attributes.degree || 0 + const shedChon = sheds[0].attributes.pitch || 0 + + if (shedDegree === 0) { + shedDegree = getDegreeByChon(shedChon) + } + const getHeight = function (adjust, degree) { + return Math.tan(degree * (Math.PI / 180)) * adjust + } + + gables.forEach((gable) => { + const adjust = gable.attributes.planeSize + const height = getHeight(adjust, shedDegree) + gable.attributes.actualSize = Math.round(Math.sqrt(Math.pow(adjust, 2) + Math.pow(height, 2))) + }) +} + export const drawRidgeRoof = (roofId, canvas) => { const roof = canvas?.getObjects().find((object) => object.id === roofId) const hasNonParallelLines = roof.lines.filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2) @@ -1904,8 +1940,6 @@ const drawHips = (roof, canvas) => { attributes: { roofId: roof.id, currentRoof: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, }, }) canvas.add(hip2) @@ -3505,8 +3539,13 @@ export const changeCurrentRoof = (currentRoof, canvas) => { newRoof.setWall(wall) newRoof.lines.forEach((line, index) => { + const lineLength = Math.sqrt( + Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), + ) line.attributes = { roofId: newRoof.id, + planeSize: lineLength, + actualSize: lineLength, wallLine: wall.lines[index].id, type: wall.lines[index].attributes.type, offset: wall.lines[index].attributes.offset, @@ -3561,6 +3600,19 @@ const reDrawPolygon = (polygon, canvas) => { line.attributes = l.attributes } }) + const lineLength = Math.sqrt( + Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), + ) + if (line.attributes !== undefined) { + line.attributes.planeSize = lineLength + line.attributes.actualSize = line + } else { + line.attributes = { + roofId: newPolygon.id, + planeSize: lineLength, + actualSize: lineLength, + } + } }) canvas?.add(newPolygon) From 16262f4c3eadb4726aaf0ad31a26df3392d85e3f Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 7 Nov 2024 14:08:49 +0900 Subject: [PATCH 16/21] =?UTF-8?q?children=20=EA=B2=80=EC=83=89=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QPolygon.js | 12 ++++++++++-- src/util/canvas-util.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 44cbfb37..d5746d5f 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -1,7 +1,14 @@ import { fabric } from 'fabric' import { v4 as uuidv4 } from 'uuid' import { QLine } from '@/components/fabric/QLine' -import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util' +import { + distanceBetweenPoints, + findTopTwoIndexesByDistance, + getAllRelatedObjects, + getDirectionByPoint, + sortedPointLessEightPoint, + sortedPoints, +} from '@/util/canvas-util' import { calculateAngle, drawRidgeRoof, drawHippedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' import * as turf from '@turf/turf' import { LINE_TYPE } from '@/common/common' @@ -131,7 +138,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { }) this.on('removed', () => { - const children = this.canvas.getObjects().filter((obj) => obj.parentId === this.id) + const children = getAllRelatedObjects(this.id, this.canvas) children.forEach((child) => { this.canvas.remove(child) }) @@ -169,6 +176,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { offset: 0, }, parent: this, + parentId: this.id, direction: getDirectionByPoint(point, nextPoint), idx: i + 1, }) diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 1a78f991..a78beb15 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -925,3 +925,32 @@ export function checkLineOrientation(line) { return 'diagonal' // 대각선 } } + +// 최상위 parentId를 통해 모든 하위 객체를 찾는 함수 +export const getAllRelatedObjects = (id, canvas) => { + const result = [] + const map = new Map() + + // Create a map of objects by their id + canvas.getObjects().forEach((obj) => { + map.set(obj.id, obj) + }) + + // Helper function to recursively find all related objects + function findRelatedObjects(id) { + const obj = map.get(id) + if (obj) { + result.push(obj) + canvas.getObjects().forEach((o) => { + if (o.parentId === id) { + findRelatedObjects(o.id) + } + }) + } + } + + // Start the search with the given parentId + findRelatedObjects(id) + + return result +} From bf8986b509f83a216fff118984509e290c04f14a Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 7 Nov 2024 14:38:05 +0900 Subject: [PATCH 17/21] =?UTF-8?q?=EC=A7=80=EB=B6=95=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=8B=9C=20=EA=B8=B8=EC=9D=B4,=20innerlines=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 212 +++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 114 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index e9d12a9b..16a73098 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1807,6 +1807,9 @@ const drawRidge = (roof, canvas) => { attributes: { roofId: roof.id }, }, ) + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + canvas.add(ridge) roof.ridges.push(ridge) roof.innerLines.push(ridge) @@ -1847,6 +1850,8 @@ const drawRidge = (roof, canvas) => { roof.ridges = roof.ridges.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) roof.innerLines = roof.innerLines.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2)) roof.innerLines = roof.innerLines.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) + newRidge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + newRidge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 canvas.add(newRidge) roof.ridges.push(newRidge) roof.innerLines.push(newRidge) @@ -1922,7 +1927,7 @@ const drawHips = (roof, canvas) => { stroke: 'red', strokeWidth: 1, name: LINE_TYPE.SUBLINE.HIP, - attributes: { roofId: roof.id, currentRoof: currentRoof.id }, + attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 }, }) canvas.add(hip1) const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 @@ -1939,10 +1944,7 @@ const drawHips = (roof, canvas) => { stroke: 'red', strokeWidth: 1, name: LINE_TYPE.SUBLINE.HIP, - attributes: { - roofId: roof.id, - currentRoof: currentRoof.id, - }, + attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 }, }) canvas.add(hip2) const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 @@ -2013,12 +2015,7 @@ const drawHips = (roof, canvas) => { stroke: 'red', strokeWidth: 1, name: LINE_TYPE.SUBLINE.HIP, - attributes: { - roofId: roof.id, - currentRoof: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, - }, + attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 }, }) canvas.add(hip) const hipBase = ((Math.abs(hip.x1 - hip.x2) + Math.abs(hip.y1 - hip.y2)) / 2) * 10 @@ -2076,92 +2073,6 @@ const checkValley = (polygon, line1, line2) => { return isValley } -const getPointInPolygon = (polygon, point, isInclude = false) => { - let inside = false - let minX = Math.min(polygon[0].x, polygon[1].x, polygon[2].x, polygon[3].x), - maxX = Math.max(polygon[0].x, polygon[1].x, polygon[2].x, polygon[3].x), - minY = Math.min(polygon[0].y, polygon[1].y, polygon[2].y, polygon[3].y), - maxY = Math.max(polygon[0].y, polygon[1].y, polygon[2].y, polygon[3].y) - if (!isInclude && minX < point.x && point.x < maxX && minY < point.y && point.y < maxY) { - inside = true - } - if (isInclude && minX <= point.x && point.x <= maxX && minY <= point.y && point.y <= maxY) { - inside = true - } - return inside -} - -/** - * 라인과 마주하는 다른 라인과의 가장 가까운 거리를 구한다. - * @param polygon - * @param currentLine 현재 라인 - * @param dVector 현재 라인의 방향 - * @returns {*[]|null} - */ -const getAcrossLine = (polygon, currentLine, dVector) => { - let acrossLine - switch (dVector) { - case 45: - acrossLine = polygon.lines - .filter((line) => line.x1 > currentLine.x1 && line.y1 <= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - case 135: - acrossLine = polygon.lines - .filter((line) => line.x1 > currentLine.x1 && line.y1 >= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - case 225: - acrossLine = polygon.lines - .filter((line) => line.x1 < currentLine.x1 && line.y1 >= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - case 315: - acrossLine = polygon.lines - .filter((line) => line.x1 < currentLine.x1 && line.y1 <= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - } - return acrossLine -} - -/* - 추녀마루(hip) 중복방지를 위해 마루와 함께 그려진 추녀마루를 확인한다 - */ -const isAlreadyHip = (polygon, line) => { - let isAlreadyHip = false - polygon.hips.forEach((hip) => { - if (line.x1 === hip.x1 && line.y1 === hip.y1) { - isAlreadyHip = true - } - }) - return isAlreadyHip -} - /* 3개 이상 이어지지 않은 라인 포인트 계산 모임지붕에서 point는 3개 이상의 라인과 접해야 함. @@ -2252,6 +2163,8 @@ const connectLinePoint = (polygon) => { stroke: 'purple', strokeWidth: 1, }) + line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 + line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 polygon.canvas.add(line) polygon.innerLines.push(line) }) @@ -2308,6 +2221,8 @@ const connectLinePoint = (polygon) => { stroke: 'purple', strokeWidth: 1, }) + line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 + line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 polygon.canvas.add(line) polygon.innerLines.push(line) }) @@ -2612,6 +2527,8 @@ const changeEavesRoof = (currentRoof, canvas) => { hipX2 = midX - addHipX2 hipY2 = midY - addHipY2 } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 } hipLines.forEach((hip) => { @@ -2789,6 +2706,8 @@ const changeGableRoof = (currentRoof, canvas) => { }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 let hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX, midY], { fontSize: roof.fontSize, @@ -2850,6 +2769,14 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { if (wallLine.length > 0) { wallLine = wallLine[0] } + let prevRoof, nextRoof + roof.lines.forEach((r, index) => { + if (r.id === currentRoof.id) { + currentRoof = r + prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1] + nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1] + } + }) const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심 const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심 @@ -2963,6 +2890,8 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 } const hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX + hipX2, midY + hipY2], { @@ -2973,10 +2902,15 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoof: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, }, }) + const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree + const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree + + const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) canvas?.add(hip1) roof.innerLines.push(hip1) @@ -2992,6 +2926,10 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { actualSize: currentRoof.length, }, }) + const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip2) roof.innerLines.push(hip2) @@ -3010,7 +2948,7 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { }) }) - hipLines.forEach((hip) => { + hipLines.forEach((hip, i) => { const gableLine = new QLine([hip.x2, hip.y2, currentRoof.attributes.ridgeCoordinate.x1, currentRoof.attributes.ridgeCoordinate.y1], { fontSize: roof.fontSize, stroke: 'red', @@ -3019,10 +2957,15 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoof: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const gableDegree = i === 0 ? prevDegree : nextDegree + const gableBase = ((Math.abs(gableLine.x1 - gableLine.x2) + Math.abs(gableLine.y1 - gableLine.y2)) / 2) * 10 + const gableHeight = Math.round(gableBase / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + gableLine.attributes.planeSize = + Math.round(Math.sqrt(Math.pow(gableLine.x1 - gableLine.x2, 2) + Math.pow(gableLine.y1 - gableLine.y2, 2))) * 10 + gableLine.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gableLine.attributes.planeSize, 2) + Math.pow(gableHeight, 2))) canvas?.add(gableLine) roof.innerLines.push(gableLine) }) @@ -3052,6 +2995,18 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { wallLine = wallLine[0] } + let prevRoof, nextRoof + roof.lines.forEach((r, index) => { + if (r.id === currentRoof.id) { + currentRoof = r + prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1] + nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1] + } + }) + + const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree + const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree + const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심 const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심 const midWallX = (wallLine.x1 + wallLine.x2) / 2 // 벽의 X 중심 @@ -3173,6 +3128,8 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { hipX2 = midX - xWidth hipY2 = midY - yWidth } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 } let hipX1 = (Math.sign(currentRoof.x1 - midX) * currentRoof.attributes.width) / 2 @@ -3186,10 +3143,14 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const gableDegree = currentRoof.attributes.degree > 0 ? currentRoof.attributes.degree : getDegreeByChon(currentRoof.attributes.pitch) + const gable1Base = ((Math.abs(gable1.x1 - gable1.x2) + Math.abs(gable1.y1 - gable1.y2)) / 2) * 10 + const gable1Height = Math.round(gable1Base / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + gable1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable1.x1 - gable1.x2, 2) + Math.pow(gable1.y1 - gable1.y2, 2))) * 10 + gable1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable1.attributes.planeSize, 2) + Math.pow(gable1Height, 2))) canvas?.add(gable1) roof.innerLines.push(gable1) @@ -3204,10 +3165,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const gable2Base = ((Math.abs(gable2.x1 - gable2.x2) + Math.abs(gable2.y1 - gable2.y2)) / 2) * 10 + const gable2Height = Math.round(gable2Base / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + gable2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable2.x1 - gable2.x2, 2) + Math.pow(gable2.y1 - gable2.y2, 2))) * 10 + gable2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable2.attributes.planeSize, 2) + Math.pow(gable2Height, 2))) canvas?.add(gable2) roof.innerLines.push(gable2) @@ -3219,10 +3183,11 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + gable3.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 + gable3.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 canvas?.add(gable3) roof.innerLines.push(gable3) @@ -3234,10 +3199,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) canvas?.add(hip1) roof.innerLines.push(hip1) @@ -3249,10 +3217,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip2) roof.innerLines.push(hip2) } @@ -3348,6 +3319,9 @@ const changeWallRoof = (currentRoof, canvas) => { canvas?.remove(line) }) + const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree + const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree + if (currentRoof.attributes.sleeve && currentRoof.attributes.width > 0 && prevRoof.attributes.offset > 0 && nextRoof.attributes.offset > 0) { const prevSignX = Math.sign(prevRoof.x1 - prevRoof.x2) const prevSignY = Math.sign(prevRoof.y1 - prevRoof.y2) @@ -3453,6 +3427,8 @@ const changeWallRoof = (currentRoof, canvas) => { y2: ridge.y2 - diffY, }) } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 let hip1 = new QLine([currentRoof.x1, currentRoof.y1, wallMidX, wallMidY], { fontSize: roof.fontSize, @@ -3462,10 +3438,14 @@ const changeWallRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) + let hip2 = new QLine([currentRoof.x2, currentRoof.y2, wallMidX, wallMidY], { fontSize: roof.fontSize, stroke: 'red', @@ -3478,6 +3458,10 @@ const changeWallRoof = (currentRoof, canvas) => { actualSize: currentRoof.length, }, }) + const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip1) canvas?.add(hip2) roof.innerLines.push(hip1) From 7f1a2f54f7e90740900fcf2411286b8e24f7566d Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 7 Nov 2024 14:49:24 +0900 Subject: [PATCH 18/21] =?UTF-8?q?import=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QPolygon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index f5e7eaae..339c9203 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -9,7 +9,7 @@ import { sortedPointLessEightPoint, sortedPoints, } from '@/util/canvas-util' -import { calculateAngle, drawRidgeRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' +import { calculateAngle, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' import * as turf from '@turf/turf' import { LINE_TYPE } from '@/common/common' From dcd364bca07d8595987c86da31e4c3108e08785b Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 7 Nov 2024 16:49:05 +0900 Subject: [PATCH 19/21] =?UTF-8?q?splitPolygonWithLines=20usePolygon?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95=20=EB=B0=A9=ED=96=A5=20?= =?UTF-8?q?index=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/common.js | 2 + .../roofcover/useRoofAllocationSetting.js | 3 +- src/hooks/useCanvasEvent.js | 12 +- src/hooks/usePolygon.js | 335 +++++++++++++++++- src/util/qpolygon-utils.js | 242 +------------ 5 files changed, 338 insertions(+), 256 deletions(-) diff --git a/src/common/common.js b/src/common/common.js index cf60295b..d0016af1 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -159,6 +159,8 @@ export const SAVE_KEY = [ 'groupName', 'lineDirection', 'groupId', + 'planeSize', + 'actualSize', ] export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype] diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index c229549e..921e737a 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -2,7 +2,6 @@ import { useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' import { useEffect, useState } from 'react' import { setSurfaceShapePattern } from '@/util/canvas-util' -import { splitPolygonWithLines } from '@/util/qpolygon-utils' import { useSwal } from '@/hooks/useSwal' import { usePolygon } from '@/hooks/usePolygon' import { roofDisplaySelector } from '@/store/settingAtom' @@ -13,7 +12,7 @@ import { POLYGON_TYPE } from '@/common/common' export function useRoofAllocationSetting(id) { const canvas = useRecoilValue(canvasState) const roofDisplay = useRecoilValue(roofDisplaySelector) - const { drawDirectionArrow } = usePolygon() + const { drawDirectionArrow, addLengthText, splitPolygonWithLines } = usePolygon() const { closePopup } = usePopup() const { swalFire } = useSwal() diff --git a/src/hooks/useCanvasEvent.js b/src/hooks/useCanvasEvent.js index 9b25eedd..42266c8a 100644 --- a/src/hooks/useCanvasEvent.js +++ b/src/hooks/useCanvasEvent.js @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import { useRecoilState, useRecoilValue } from 'recoil' import { v4 as uuidv4 } from 'uuid' -import { canvasSizeState, canvasState, canvasZoomState, currentObjectState, fontFamilyState, fontSizeState } from '@/store/canvasAtom' +import { canvasSizeState, canvasState, canvasZoomState, currentObjectState } from '@/store/canvasAtom' import { QPolygon } from '@/components/fabric/QPolygon' import { usePlan } from '@/hooks/usePlan' import { fontSelector } from '@/store/fontAtom' @@ -12,8 +12,6 @@ export function useCanvasEvent() { const [canvasForEvent, setCanvasForEvent] = useState(null) const [currentObject, setCurrentObject] = useRecoilState(currentObjectState) const canvasSize = useRecoilValue(canvasSizeState) - const fontSize = useRecoilValue(fontSizeState) - const fontFamily = useRecoilValue(fontFamilyState) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) const lengthTextOption = useRecoilValue(fontSelector('lengthText')) const { modifiedPlanFlag, setModifiedPlanFlag } = usePlan() @@ -211,7 +209,7 @@ export function useCanvasEvent() { setCurrentObject(target) const { selected } = e - if (selected.length > 0) { + if (selected?.length > 0) { selected.forEach((obj) => { if (obj.type === 'QPolygon') { obj.set({ stroke: 'red' }) @@ -224,7 +222,7 @@ export function useCanvasEvent() { setCurrentObject(null) const { deselected } = e - if (deselected.length > 0) { + if (deselected?.length > 0) { deselected.forEach((obj) => { if (obj.type === 'QPolygon') { obj.set({ stroke: 'black' }) @@ -238,7 +236,7 @@ export function useCanvasEvent() { setCurrentObject(target) const { selected, deselected } = e - if (deselected.length > 0) { + if (deselected?.length > 0) { deselected.forEach((obj) => { if (obj.type === 'QPolygon') { obj.set({ stroke: 'black' }) @@ -246,7 +244,7 @@ export function useCanvasEvent() { }) } - if (selected.length > 0) { + if (selected?.length > 0) { selected.forEach((obj) => { if (obj.type === 'QPolygon') { obj.set({ stroke: 'red' }) diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 5a7d3062..9ea8b3b7 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -1,11 +1,13 @@ import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, fontFamilyState, fontSizeState, pitchTextSelector } from '@/store/canvasAtom' import { useRecoilValue } from 'recoil' import { fabric } from 'fabric' -import { getDegreeByChon, getDirectionByPoint } from '@/util/canvas-util' +import { getDegreeByChon, getDirectionByPoint, isPointOnLine } from '@/util/canvas-util' import { QPolygon } from '@/components/fabric/QPolygon' -import { isSamePoint } from '@/util/qpolygon-utils' +import { isSamePoint, removeDuplicatePolygons } from '@/util/qpolygon-utils' import { flowDisplaySelector } from '@/store/settingAtom' import { fontSelector } from '@/store/fontAtom' +import { QLine } from '@/components/fabric/QLine' +import { POLYGON_TYPE } from '@/common/common' export const usePolygon = () => { const canvas = useRecoilValue(canvasState) @@ -25,6 +27,7 @@ export const usePolygon = () => { }) canvas?.add(polygon) + addLengthText(polygon) return polygon } @@ -40,7 +43,64 @@ export const usePolygon = () => { } const addLengthText = (polygon) => { - const points = polygon.get('points') + const lengthTexts = canvas.getObjects().filter((obj) => obj.name === 'lengthText' && obj.parentId === polygon.id) + lengthTexts.forEach((text) => { + canvas.remove(text) + }) + const lines = polygon.lines + + lines.forEach((line, i) => { + const length = line.getLength() + const { planeSize, actualSize } = line.attributes + const scaleX = line.scaleX + const scaleY = line.scaleY + const x1 = line.left + const y1 = line.top + const x2 = line.left + line.width * scaleX + const y2 = line.top + line.height * scaleY + + let left, top + + if (line.direction === 'left' || line.direction === 'right') { + left = (x1 + x2) / 2 + top = (y1 + y2) / 2 + 10 + } else if (line.direction === 'top' || line.direction === 'bottom') { + left = (x1 + x2) / 2 + 10 + top = (y1 + y2) / 2 + } + + const minX = line.left + const maxX = line.left + line.width + const minY = line.top + const maxY = line.top + line.length + const degree = (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI + + const text = new fabric.Textbox(actualSize ? actualSize.toString() : planeSize ? planeSize.toString() : length.toString(), { + left: left, + top: top, + fontSize: lengthTextFontOptions.fontSize.value, + minX, + maxX, + minY, + maxY, + parentDirection: line.direction, + parentDegree: degree, + parentId: polygon.id, + planeSize, + actualSize, + editable: false, + selectable: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + parent: polygon, + name: 'lengthText', + }) + + canvas.add(text) + }) + + /*const points = polygon.get('points') points.forEach((start, i) => { const end = points[(i + 1) % points.length] const dx = end.x - start.x @@ -71,12 +131,12 @@ export const usePolygon = () => { lockScalingY: true, idx: i, name: 'lengthText', - parent: this, + parent: polygon, }) // this.texts.push(text) canvas.add(text) - }) + })*/ canvas.renderAll() } @@ -409,7 +469,8 @@ export const usePolygon = () => { const addTextByArrows = (arrows, txt, canvas) => { arrows.forEach((arrow, index) => { - const textStr = `${txt}${index + 1} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})` + // const textStr = `${txt}${index + 1} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})` + const textStr = `${txt} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})` const text = new fabric.Text(`${textStr}`, { fontSize: flowFontOptions.fontSize.value, @@ -432,10 +493,272 @@ export const usePolygon = () => { }) } + const splitPolygonWithLines = (polygon) => { + polygon.set({ visible: false }) + let innerLines = [...polygon.innerLines] + let polygonLines = [...polygon.lines] + const roofs = [] + + let delIndexs = [] + let newLines = [] + + polygonLines.forEach((line, index) => { + line.tempIndex = index + innerLines.forEach((innerLine) => { + let newLine1, newLine2 + if (isPointOnLine(line, innerLine.startPoint)) { + // 해당 line을 startPoint로 나눈 line2개를 canvas에 추가 하고 기존 line을 제거한다. + newLine1 = new QLine([line.x1, line.y1, innerLine.startPoint.x, innerLine.startPoint.y], { + fontSize: polygon.fontSize, + stroke: 'black', + strokeWidth: 3, + }) + + newLine2 = new QLine([innerLine.startPoint.x, innerLine.startPoint.y, line.x2, line.y2], { + fontSize: polygon.fontSize, + stroke: 'black', + strokeWidth: 3, + }) + delIndexs.push(polygonLines.indexOf(line)) + canvas.remove(polygonLines[polygonLines.indexOf(line)]) + if (newLine1.length / 10 > 10) { + newLines.push(newLine1) + } + if (newLine2.length / 10 > 10) { + newLines.push(newLine2) + } + } + if (isPointOnLine(line, innerLine.endPoint)) { + newLine1 = new QLine([line.x1, line.y1, innerLine.endPoint.x, innerLine.endPoint.y], { + fontSize: polygon.fontSize, + stroke: 'black', + strokeWidth: 3, + }) + + newLine2 = new QLine([innerLine.endPoint.x, innerLine.endPoint.y, line.x2, line.y2], { + fontSize: polygon.fontSize, + stroke: 'black', + strokeWidth: 3, + }) + delIndexs.push(polygonLines.indexOf(line)) + canvas.remove(polygonLines[polygonLines.indexOf(line)]) + if (newLine1.length / 10 > 10) { + newLines.push(newLine1) + } + if (newLine2.length / 10 > 10) { + newLines.push(newLine2) + } + } + }) + }) + polygonLines = polygonLines.filter((line) => !delIndexs.includes(line.tempIndex)) + polygonLines = [...polygonLines, ...newLines] + + const allLines = [...polygonLines, ...innerLines] + + /** + * 왼쪽 상단을 startPoint로 전부 변경 + */ + allLines.forEach((line) => { + let startPoint // 시작점 + let endPoint // 끝점 + if (line.x1 < line.x2) { + startPoint = { x: line.x1, y: line.y1 } + endPoint = { x: line.x2, y: line.y2 } + } else if (line.x1 > line.x2) { + startPoint = { x: line.x2, y: line.y2 } + endPoint = { x: line.x1, y: line.y1 } + } else { + if (line.y1 < line.y2) { + startPoint = { x: line.x1, y: line.y1 } + endPoint = { x: line.x2, y: line.y2 } + } else { + startPoint = { x: line.x2, y: line.y2 } + endPoint = { x: line.x1, y: line.y1 } + } + } + + line.startPoint = startPoint + line.endPoint = endPoint + }) + + polygonLines.forEach((line) => { + const startPoint = line.startPoint // 시작점 + let arrivalPoint = line.endPoint // 도착점 + + let currentPoint = startPoint + const roofPoints = [startPoint] + + const startLine = line + const visitPoints = [startPoint] + const visitLines = [startLine] + let cnt = 0 + + while (!isSamePoint(currentPoint, arrivalPoint)) { + let nextLines = allLines.filter( + (line2) => + (isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) && + line !== line2 && + innerLines.includes(line2) && + !visitLines.includes(line2), + ) + + if (nextLines.length === 0) { + nextLines = allLines.filter( + (line2) => + (isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) && + line !== line2 && + !visitLines.includes(line2), + ) + } + + if (!nextLines) { + break + } + + let comparisonPoints = [] + + nextLines.forEach((nextLine) => { + if (isSamePoint(nextLine.startPoint, currentPoint)) { + comparisonPoints.push(nextLine.endPoint) + } else { + comparisonPoints.push(nextLine.startPoint) + } + }) + + comparisonPoints = comparisonPoints.filter((point) => !visitPoints.some((visitPoint) => isSamePoint(visitPoint, point))) + comparisonPoints = comparisonPoints.filter((point) => !isSamePoint(point, currentPoint)) + + const minDistancePoint = comparisonPoints.reduce((prev, current) => { + const prevDistance = Math.sqrt(Math.pow(prev.x - arrivalPoint.x, 2) + Math.pow(prev.y - arrivalPoint.y, 2)) + const currentDistance = Math.sqrt(Math.pow(current.x - arrivalPoint.x, 2) + Math.pow(current.y - arrivalPoint.y, 2)) + + return prevDistance < currentDistance ? prev : current + }, comparisonPoints[0]) + + nextLines.forEach((nextLine) => { + if (isSamePoint(nextLine.startPoint, minDistancePoint) || isSamePoint(nextLine.endPoint, minDistancePoint)) { + visitLines.push(nextLine) + } + }) + + currentPoint = { ...minDistancePoint } + roofPoints.push(currentPoint) + cnt++ + if (cnt > 100) { + throw new Error('무한루프') + } + } + roofs.push(roofPoints) + }) + + const newRoofs = removeDuplicatePolygons(roofs) + + newRoofs.forEach((roofPoint, index) => { + let defense, pitch + const polygonLines = [...polygon.lines] + + let representLines = [] + let representLine + + // 지붕을 그리면서 기존 polygon의 line중 연결된 line을 찾는다. + polygonLines.forEach((line) => { + let startFlag = false + let endFlag = false + const startPoint = line.startPoint + const endPoint = line.endPoint + roofPoint.forEach((point, index) => { + if (isSamePoint(point, startPoint)) { + startFlag = true + } + if (isSamePoint(point, endPoint)) { + endFlag = true + } + }) + + if (startFlag && endFlag) { + if (!representLines.includes(line)) { + representLines.push(line) + } + } + }) + + // representLines중 가장 긴 line을 찾는다. + representLines.forEach((line) => { + if (!representLine) { + representLine = line + } else { + if (representLine.length < line.length) { + representLine = line + } + } + }) + + const direction = newRoofs.length === 1 ? polygon.direction : representLine.direction + const polygonDirection = polygon.direction + + switch (direction) { + case 'top': + defense = 'east' + break + case 'right': + defense = 'south' + break + case 'bottom': + defense = 'west' + break + case 'left': + defense = 'north' + break + } + pitch = polygon.lines[index].attributes?.pitch ?? 0 + + const roof = new QPolygon(roofPoint, { + fontSize: polygon.fontSize, + stroke: 'black', + fill: 'transparent', + strokeWidth: 3, + name: POLYGON_TYPE.ROOF, + originX: 'center', + originY: 'center', + selectable: true, + defense: defense, + direction: newRoofs.length === 1 ? polygonDirection : defense, + pitch: pitch, + }) + + //allLines중 생성된 roof와 관련있는 line을 찾는다. + + roof.lines = [...polygon.lines, ...polygon.innerLines].filter((line) => { + let startFlag = false + let endFlag = false + const startPoint = line.startPoint + const endPoint = line.endPoint + roofPoint.forEach((point, index) => { + if (isSamePoint(point, startPoint)) { + startFlag = true + } + if (isSamePoint(point, endPoint)) { + endFlag = true + } + }) + + return startFlag && endFlag + }) + + canvas.add(roof) + addLengthText(roof) + canvas.remove(polygon) + canvas.renderAll() + }) + } + return { addPolygon, addPolygonByLines, removePolygon, drawDirectionArrow, + addLengthText, + splitPolygonWithLines, } } diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 16a73098..66c1b509 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1177,246 +1177,6 @@ export default function offsetPolygon(vertices, offset) { polygon.canvas.renderAll() }) }*/ -export const splitPolygonWithLines = (polygon) => { - const canvas = polygon.canvas - polygon.set({ visible: false }) - let innerLines = [...polygon.innerLines] - let polygonLines = [...polygon.lines] - const roofs = [] - - let delIndexs = [] - let newLines = [] - - polygonLines.forEach((line, index) => { - line.tempIndex = index - innerLines.forEach((innerLine) => { - let newLine1, newLine2 - if (isPointOnLine(line, innerLine.startPoint)) { - // 해당 line을 startPoint로 나눈 line2개를 canvas에 추가 하고 기존 line을 제거한다. - newLine1 = new QLine([line.x1, line.y1, innerLine.startPoint.x, innerLine.startPoint.y], { - fontSize: polygon.fontSize, - stroke: 'black', - strokeWidth: 3, - }) - - newLine2 = new QLine([innerLine.startPoint.x, innerLine.startPoint.y, line.x2, line.y2], { - fontSize: polygon.fontSize, - stroke: 'black', - strokeWidth: 3, - }) - delIndexs.push(polygonLines.indexOf(line)) - canvas.remove(polygonLines[polygonLines.indexOf(line)]) - if (newLine1.length / 10 > 10) { - newLines.push(newLine1) - } - if (newLine2.length / 10 > 10) { - newLines.push(newLine2) - } - } - if (isPointOnLine(line, innerLine.endPoint)) { - newLine1 = new QLine([line.x1, line.y1, innerLine.endPoint.x, innerLine.endPoint.y], { - fontSize: polygon.fontSize, - stroke: 'black', - strokeWidth: 3, - }) - - newLine2 = new QLine([innerLine.endPoint.x, innerLine.endPoint.y, line.x2, line.y2], { - fontSize: polygon.fontSize, - stroke: 'black', - strokeWidth: 3, - }) - delIndexs.push(polygonLines.indexOf(line)) - canvas.remove(polygonLines[polygonLines.indexOf(line)]) - if (newLine1.length / 10 > 10) { - newLines.push(newLine1) - } - if (newLine2.length / 10 > 10) { - newLines.push(newLine2) - } - } - }) - }) - polygonLines = polygonLines.filter((line) => !delIndexs.includes(line.tempIndex)) - polygonLines = [...polygonLines, ...newLines] - - const allLines = [...polygonLines, ...innerLines] - - /** - * 왼쪽 상단을 startPoint로 전부 변경 - */ - allLines.forEach((line) => { - let startPoint // 시작점 - let endPoint // 끝점 - if (line.x1 < line.x2) { - startPoint = { x: line.x1, y: line.y1 } - endPoint = { x: line.x2, y: line.y2 } - } else if (line.x1 > line.x2) { - startPoint = { x: line.x2, y: line.y2 } - endPoint = { x: line.x1, y: line.y1 } - } else { - if (line.y1 < line.y2) { - startPoint = { x: line.x1, y: line.y1 } - endPoint = { x: line.x2, y: line.y2 } - } else { - startPoint = { x: line.x2, y: line.y2 } - endPoint = { x: line.x1, y: line.y1 } - } - } - - line.startPoint = startPoint - line.endPoint = endPoint - }) - - polygonLines.forEach((line) => { - const startPoint = line.startPoint // 시작점 - let arrivalPoint = line.endPoint // 도착점 - - let currentPoint = startPoint - const roofPoints = [startPoint] - - const startLine = line - const visitPoints = [startPoint] - const visitLines = [startLine] - let cnt = 0 - - while (!isSamePoint(currentPoint, arrivalPoint)) { - line.set({ stroke: 'red' }) - canvas.renderAll() - let nextLines = allLines.filter( - (line2) => - (isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) && - line !== line2 && - innerLines.includes(line2) && - !visitLines.includes(line2), - ) - - if (nextLines.length === 0) { - nextLines = allLines.filter( - (line2) => - (isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) && - line !== line2 && - !visitLines.includes(line2), - ) - } - - if (!nextLines) { - break - } - - let comparisonPoints = [] - - nextLines.forEach((nextLine) => { - if (isSamePoint(nextLine.startPoint, currentPoint)) { - comparisonPoints.push(nextLine.endPoint) - } else { - comparisonPoints.push(nextLine.startPoint) - } - }) - - comparisonPoints = comparisonPoints.filter((point) => !visitPoints.some((visitPoint) => isSamePoint(visitPoint, point))) - comparisonPoints = comparisonPoints.filter((point) => !isSamePoint(point, currentPoint)) - - const minDistancePoint = comparisonPoints.reduce((prev, current) => { - const prevDistance = Math.sqrt(Math.pow(prev.x - arrivalPoint.x, 2) + Math.pow(prev.y - arrivalPoint.y, 2)) - const currentDistance = Math.sqrt(Math.pow(current.x - arrivalPoint.x, 2) + Math.pow(current.y - arrivalPoint.y, 2)) - - return prevDistance < currentDistance ? prev : current - }, comparisonPoints[0]) - - nextLines.forEach((nextLine) => { - if (isSamePoint(nextLine.startPoint, minDistancePoint) || isSamePoint(nextLine.endPoint, minDistancePoint)) { - visitLines.push(nextLine) - } - }) - - currentPoint = { ...minDistancePoint } - roofPoints.push(currentPoint) - cnt++ - if (cnt > 100) { - throw new Error('무한루프') - } - } - roofs.push(roofPoints) - }) - - const newRoofs = removeDuplicatePolygons(roofs) - - newRoofs.forEach((roofPoint, index) => { - let defense, pitch - const polygonLines = [...polygon.lines] - - let representLines = [] - let representLine - - // 지붕을 그리면서 기존 polygon의 line중 연결된 line을 찾는다. - polygonLines.forEach((line) => { - let startFlag = false - let endFlag = false - const startPoint = line.startPoint - const endPoint = line.endPoint - roofPoint.forEach((point, index) => { - if (isSamePoint(point, startPoint)) { - startFlag = true - } - if (isSamePoint(point, endPoint)) { - endFlag = true - } - }) - - if (startFlag && endFlag) { - representLines.push(line) - } - }) - - // representLines중 가장 긴 line을 찾는다. - representLines.forEach((line) => { - if (!representLine) { - representLine = line - } else { - if (representLine.length < line.length) { - representLine = line - } - } - }) - - const direction = newRoofs.length === 1 ? polygon.direction : representLine.direction - const polygonDirection = polygon.direction - - switch (direction) { - case 'top': - defense = 'east' - break - case 'right': - defense = 'south' - break - case 'bottom': - defense = 'west' - break - case 'left': - defense = 'north' - break - } - pitch = polygon.lines[index].attributes?.pitch ?? 0 - - const roof = new QPolygon(roofPoint, { - fontSize: polygon.fontSize, - stroke: 'black', - fill: 'transparent', - strokeWidth: 3, - name: POLYGON_TYPE.ROOF, - originX: 'center', - originY: 'center', - selectable: true, - defense: defense, - direction: newRoofs.length === 1 ? polygonDirection : defense, - pitch: pitch, - }) - - polygon.canvas.add(roof) - canvas.remove(polygon) - polygon.canvas.renderAll() - }) -} function normalizePoint(point) { return { @@ -1434,7 +1194,7 @@ function arePolygonsEqual(polygon1, polygon2) { return normalizedPolygon1.every((point, index) => arePointsEqual(point, normalizedPolygon2[index])) } -function removeDuplicatePolygons(polygons) { +export function removeDuplicatePolygons(polygons) { const uniquePolygons = [] polygons.forEach((polygon) => { From c0396c9d6f3d9ec657c3998ec8b363521fb4c099 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 7 Nov 2024 17:05:29 +0900 Subject: [PATCH 20/21] =?UTF-8?q?=EB=B3=B4=EC=A1=B0=EC=84=A0=20actualSize?= =?UTF-8?q?=200=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QPolygon.js | 3 ++- src/hooks/roofcover/useAuxiliaryDrawing.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 339c9203..3db4f743 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -138,7 +138,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { }) this.on('removed', () => { - const children = getAllRelatedObjects(this.id, this.canvas) + // const children = getAllRelatedObjects(this.id, this.canvas) + const children = this.canvas.getObjects().filter((obj) => obj.parentId === this.id && obj.name === 'lengthText') children.forEach((child) => { this.canvas.remove(child) }) diff --git a/src/hooks/roofcover/useAuxiliaryDrawing.js b/src/hooks/roofcover/useAuxiliaryDrawing.js index e9aa7d93..6e95e79c 100644 --- a/src/hooks/roofcover/useAuxiliaryDrawing.js +++ b/src/hooks/roofcover/useAuxiliaryDrawing.js @@ -815,7 +815,7 @@ export function useAuxiliaryDrawing(id) { roofBase.lines.some((line) => isPointOnLine(line, { x: line.x2, y: line.y2 })) if (inPolygon1 && inPolygon2) { - line.attributes = { ...line.attributes, roofId: roofBase.id } + line.attributes = { ...line.attributes, roofId: roofBase.id, actualSize: 0, planeSize: line.getLength() } return true } }) From 72c7fc263a6726bcbbf9b88985fb25e68288ed9e Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 7 Nov 2024 17:07:11 +0900 Subject: [PATCH 21/21] =?UTF-8?q?=EB=A7=88=EB=A3=A8=20=EA=B3=84=EC=82=B0?= =?UTF-8?q?=20=EC=88=98=EC=8B=9D=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QPolygon.js | 1 - src/hooks/useMode.js | 2 +- src/util/qpolygon-utils.js | 32 +++++++++++++++---------------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 339c9203..873d2c6a 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -231,7 +231,6 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { if (eaves.length > 0) { const gables = this.lines.filter((line) => sheds.includes(line) === false && eaves.includes(line) === false) const isGable = gables.every((line) => gableType.includes(line.attributes.type)) - console.log('isGable : ', isGable) if (isGable) { drawShedRoof(this.id, this.canvas) } else { diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 703b622d..84c4fac6 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -36,7 +36,7 @@ import { QPolygon } from '@/components/fabric/QPolygon' import offsetPolygon from '@/util/qpolygon-utils' import { isObjectNotEmpty } from '@/util/common-utils' import * as turf from '@turf/turf' -import { INPUT_TYPE, Mode, POLYGON_TYPE } from '@/common/common' +import { INPUT_TYPE, LINE_TYPE, Mode, POLYGON_TYPE } from '@/common/common' export function useMode() { const [mode, setMode] = useRecoilState(modeState) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 16a73098..d3f02ef8 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1807,8 +1807,8 @@ const drawRidge = (roof, canvas) => { attributes: { roofId: roof.id }, }, ) - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) canvas.add(ridge) roof.ridges.push(ridge) @@ -1850,8 +1850,8 @@ const drawRidge = (roof, canvas) => { roof.ridges = roof.ridges.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) roof.innerLines = roof.innerLines.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2)) roof.innerLines = roof.innerLines.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) - newRidge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - newRidge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + newRidge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + newRidge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) canvas.add(newRidge) roof.ridges.push(newRidge) roof.innerLines.push(newRidge) @@ -2221,8 +2221,8 @@ const connectLinePoint = (polygon) => { stroke: 'purple', strokeWidth: 1, }) - line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 - line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 + line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) + line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) polygon.canvas.add(line) polygon.innerLines.push(line) }) @@ -2527,8 +2527,8 @@ const changeEavesRoof = (currentRoof, canvas) => { hipX2 = midX - addHipX2 hipY2 = midY - addHipY2 } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) } hipLines.forEach((hip) => { @@ -2706,8 +2706,8 @@ const changeGableRoof = (currentRoof, canvas) => { }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) let hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX, midY], { fontSize: roof.fontSize, @@ -2890,8 +2890,8 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) } const hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX + hipX2, midY + hipY2], { @@ -3128,8 +3128,8 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { hipX2 = midX - xWidth hipY2 = midY - yWidth } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) } let hipX1 = (Math.sign(currentRoof.x1 - midX) * currentRoof.attributes.width) / 2 @@ -3427,8 +3427,8 @@ const changeWallRoof = (currentRoof, canvas) => { y2: ridge.y2 - diffY, }) } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) let hip1 = new QLine([currentRoof.x1, currentRoof.y1, wallMidX, wallMidY], { fontSize: roof.fontSize,