Compare commits
No commits in common. "a7e9aba26ce2a61457bfd01a4aa3c2cf1ead64b7" and "c631c6344efd5f4e5628afa202ad68c73b19efcd" have entirely different histories.
a7e9aba26c
...
c631c6344e
@ -203,7 +203,6 @@ export const SAVE_KEY = [
|
|||||||
'fontWeight',
|
'fontWeight',
|
||||||
'dormerAttributes',
|
'dormerAttributes',
|
||||||
'toFixed',
|
'toFixed',
|
||||||
'isSortedPoints',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype]
|
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype]
|
||||||
|
|||||||
@ -45,11 +45,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
options.sort = options.sort ?? true
|
options.sort = options.sort ?? true
|
||||||
options.parentId = options.parentId ?? null
|
options.parentId = options.parentId ?? null
|
||||||
|
|
||||||
this.isSortedPoints = false
|
|
||||||
|
|
||||||
if (!options.sort && points.length <= 8) {
|
if (!options.sort && points.length <= 8) {
|
||||||
points = sortedPointLessEightPoint(points)
|
points = sortedPointLessEightPoint(points)
|
||||||
this.isSortedPoints = true
|
|
||||||
} else {
|
} else {
|
||||||
let isDiagonal = false
|
let isDiagonal = false
|
||||||
points.forEach((point, i) => {
|
points.forEach((point, i) => {
|
||||||
@ -65,7 +62,6 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
|
|
||||||
if (!isDiagonal) {
|
if (!isDiagonal) {
|
||||||
points = sortedPoints(points)
|
points = sortedPoints(points)
|
||||||
this.isSortedPoints = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -479,7 +479,7 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
console.log(stepUpListData)
|
console.log(stepUpListData)
|
||||||
stepUpListData[0].pcsItemList.map((item, index) => {
|
stepUpListData[0].pcsItemList.map((item, index) => {
|
||||||
return item.serQtyList
|
return item.serQtyList
|
||||||
.filter((serQty) => serQty.selected && serQty.paralQty > 0)
|
.filter((serQty) => serQty.selected)
|
||||||
.forEach((serQty) => {
|
.forEach((serQty) => {
|
||||||
pcs.push({
|
pcs.push({
|
||||||
pcsMkrCd: item.pcsMkrCd,
|
pcsMkrCd: item.pcsMkrCd,
|
||||||
|
|||||||
@ -573,7 +573,7 @@ export default function StepUp(props) {
|
|||||||
value={seletedMainOption}
|
value={seletedMainOption}
|
||||||
sourceKey="code"
|
sourceKey="code"
|
||||||
targetKey="code"
|
targetKey="code"
|
||||||
showKey={`${globalLocale === 'ja' ? 'nameJp' : 'name'}`}
|
showKey="name"
|
||||||
onChange={(e) => setSeletedMainOption(e)}
|
onChange={(e) => setSeletedMainOption(e)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -586,7 +586,7 @@ export default function StepUp(props) {
|
|||||||
value={seletedSubOption}
|
value={seletedSubOption}
|
||||||
sourceKey="code"
|
sourceKey="code"
|
||||||
targetKey="code"
|
targetKey="code"
|
||||||
showKey={`${globalLocale === 'ja' ? 'nameJp' : 'name'}`}
|
showKey="name"
|
||||||
onChange={(e) => setSeletedSubOption(e)}
|
onChange={(e) => setSeletedSubOption(e)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -19,7 +19,6 @@ import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util'
|
|||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||||
import { usePlan } from '@/hooks/usePlan'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 지붕 레이아웃
|
* 지붕 레이아웃
|
||||||
@ -46,7 +45,6 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
const { setSurfaceShapePattern } = useRoofFn()
|
const { setSurfaceShapePattern } = useRoofFn()
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
||||||
const { saveCanvas } = usePlan()
|
|
||||||
|
|
||||||
const roofRef = {
|
const roofRef = {
|
||||||
roofCd: useRef(null),
|
roofCd: useRef(null),
|
||||||
@ -207,7 +205,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
/**
|
/**
|
||||||
* 배치면초기설정 저장 버튼 클릭
|
* 배치면초기설정 저장 버튼 클릭
|
||||||
*/
|
*/
|
||||||
const handleSaveBtn = async () => {
|
const handleSaveBtn = () => {
|
||||||
const roofInfo = {
|
const roofInfo = {
|
||||||
...currentRoof,
|
...currentRoof,
|
||||||
planNo: basicSetting.planNo,
|
planNo: basicSetting.planNo,
|
||||||
@ -256,7 +254,6 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
|
|
||||||
/* 저장 후 화면 닫기 */
|
/* 저장 후 화면 닫기 */
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
await saveCanvas(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import { useSwal } from '@/hooks/useSwal'
|
|||||||
import { useContext } from 'react'
|
import { useContext } from 'react'
|
||||||
import { QcastContext } from '@/app/QcastProvider'
|
import { QcastContext } from '@/app/QcastProvider'
|
||||||
import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle'
|
import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
|
||||||
|
|
||||||
// 모듈간 같은 행, 열의 마진이 10 이하인 경우는 같은 행, 열로 간주
|
// 모듈간 같은 행, 열의 마진이 10 이하인 경우는 같은 행, 열로 간주
|
||||||
const MODULE_MARGIN = 10
|
const MODULE_MARGIN = 10
|
||||||
@ -27,7 +26,6 @@ export const useTrestle = () => {
|
|||||||
|
|
||||||
const { getSelectedPcsItemList } = useCircuitTrestle()
|
const { getSelectedPcsItemList } = useCircuitTrestle()
|
||||||
const { resetCircuits } = useCircuitTrestle()
|
const { resetCircuits } = useCircuitTrestle()
|
||||||
const { getMessage } = useMessage()
|
|
||||||
|
|
||||||
const apply = () => {
|
const apply = () => {
|
||||||
const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit)
|
const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit)
|
||||||
@ -60,6 +58,7 @@ export const useTrestle = () => {
|
|||||||
}
|
}
|
||||||
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
|
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
|
||||||
if (!construction) {
|
if (!construction) {
|
||||||
|
swalFire({ text: 'construction 존재안함', icon: 'error' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,9 +131,9 @@ export const useTrestle = () => {
|
|||||||
surface.isChidory = isChidory
|
surface.isChidory = isChidory
|
||||||
|
|
||||||
if (plvrYn === 'N' && isChidory) {
|
if (plvrYn === 'N' && isChidory) {
|
||||||
swalFire({ text: getMessage('chidory.can.not.install'), icon: 'error' })
|
swalFire({ text: '치조불가공법입니다.', icon: 'error' })
|
||||||
clear()
|
clear()
|
||||||
throw new Error(getMessage('chidory.can.not.install'))
|
throw new Error('치조불가공법입니다.')
|
||||||
}
|
}
|
||||||
|
|
||||||
surface.set({ isChidory: isChidory })
|
surface.set({ isChidory: isChidory })
|
||||||
|
|||||||
@ -27,7 +27,6 @@ import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
|||||||
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
||||||
import { outerLinePointsState } from '@/store/outerLineAtom'
|
import { outerLinePointsState } from '@/store/outerLineAtom'
|
||||||
import { QcastContext } from '@/app/QcastProvider'
|
import { QcastContext } from '@/app/QcastProvider'
|
||||||
import { usePlan } from '@/hooks/usePlan'
|
|
||||||
|
|
||||||
export function useRoofAllocationSetting(id) {
|
export function useRoofAllocationSetting(id) {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
@ -53,7 +52,6 @@ export function useRoofAllocationSetting(id) {
|
|||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
const { setIsGlobalLoading } = useContext(QcastContext)
|
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||||
const { setSurfaceShapePattern } = useRoofFn()
|
const { setSurfaceShapePattern } = useRoofFn()
|
||||||
const { saveCanvas } = usePlan()
|
|
||||||
|
|
||||||
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
|
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
|
||||||
const resetPoints = useResetRecoilState(outerLinePointsState)
|
const resetPoints = useResetRecoilState(outerLinePointsState)
|
||||||
@ -227,7 +225,6 @@ export function useRoofAllocationSetting(id) {
|
|||||||
await post({ url: `/api/canvas-management/roof-allocation-settings`, data: patternData }).then((res) => {
|
await post({ url: `/api/canvas-management/roof-allocation-settings`, data: patternData }).then((res) => {
|
||||||
swalFire({ text: getMessage(res.returnMessage) })
|
swalFire({ text: getMessage(res.returnMessage) })
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
saveCanvas(false)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
//Recoil 설정
|
//Recoil 설정
|
||||||
|
|||||||
@ -159,7 +159,6 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
addCanvasMouseEventListener('mouse:down', (e) => {
|
addCanvasMouseEventListener('mouse:down', (e) => {
|
||||||
isDrawing = false
|
isDrawing = false
|
||||||
|
|
||||||
const { xInversion, yInversion } = surfaceRefs
|
|
||||||
canvas?.remove(obj)
|
canvas?.remove(obj)
|
||||||
|
|
||||||
//각도 추가
|
//각도 추가
|
||||||
@ -180,7 +179,6 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//회전, flip등이 먹은 기준으로 새로생성
|
//회전, flip등이 먹은 기준으로 새로생성
|
||||||
// const batchSurface = addPolygon(reorderedPoints, {
|
|
||||||
const batchSurface = addPolygon(obj.getCurrentPoints(), {
|
const batchSurface = addPolygon(obj.getCurrentPoints(), {
|
||||||
fill: 'transparent',
|
fill: 'transparent',
|
||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
@ -199,8 +197,6 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
pitch: globalPitch,
|
pitch: globalPitch,
|
||||||
surfaceId: surfaceId,
|
surfaceId: surfaceId,
|
||||||
direction: direction,
|
direction: direction,
|
||||||
isXInversion: xInversion,
|
|
||||||
isYInversion: yInversion,
|
|
||||||
})
|
})
|
||||||
canvas.setActiveObject(batchSurface)
|
canvas.setActiveObject(batchSurface)
|
||||||
setSurfaceShapePattern(batchSurface, roofDisplay.column)
|
setSurfaceShapePattern(batchSurface, roofDisplay.column)
|
||||||
@ -212,9 +208,6 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
// const popupId = uuidv4()
|
// const popupId = uuidv4()
|
||||||
// addPopup(popupId, 2, <PlacementSurfaceLineProperty roof={batchSurface} id={popupId} setIsHidden={setIsHidden} />)
|
// addPopup(popupId, 2, <PlacementSurfaceLineProperty roof={batchSurface} id={popupId} setIsHidden={setIsHidden} />)
|
||||||
|
|
||||||
// console.log('xInversion', xInversion) //상하반전
|
|
||||||
// console.log('yInversion', yInversion) //좌우반전
|
|
||||||
|
|
||||||
changeSurfaceLineType(batchSurface)
|
changeSurfaceLineType(batchSurface)
|
||||||
|
|
||||||
if (setIsHidden) setIsHidden(false)
|
if (setIsHidden) setIsHidden(false)
|
||||||
@ -498,18 +491,18 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
}
|
}
|
||||||
case 10: {
|
case 10: {
|
||||||
points = [
|
points = [
|
||||||
{ x: pointer.x + length1 / 2 - length1, y: pointer.y + length4 / 2 - length5 },
|
|
||||||
{ x: pointer.x + length1 / 2 - length1, y: pointer.y + length4 / 2 },
|
|
||||||
{ x: pointer.x + length1 / 2, y: pointer.y + length4 / 2 },
|
{ x: pointer.x + length1 / 2, y: pointer.y + length4 / 2 },
|
||||||
{
|
{ x: pointer.x + length1 / 2 - length1, y: pointer.y + length4 / 2 },
|
||||||
x: pointer.x + length1 / 2 - length1 + length2 + length3,
|
{ x: pointer.x + length1 / 2 - length1, y: pointer.y + length4 / 2 - length5 },
|
||||||
y: pointer.y + length4 / 2 - length5 - (length4 - length5),
|
{ x: pointer.x + length1 / 2 - length1 + length2, y: pointer.y + length4 / 2 - length5 },
|
||||||
},
|
|
||||||
{
|
{
|
||||||
x: pointer.x + length1 / 2 - length1 + length2,
|
x: pointer.x + length1 / 2 - length1 + length2,
|
||||||
y: pointer.y + length4 / 2 - length5 - (length4 - length5),
|
y: pointer.y + length4 / 2 - length5 - (length4 - length5),
|
||||||
},
|
},
|
||||||
{ x: pointer.x + length1 / 2 - length1 + length2, y: pointer.y + length4 / 2 - length5 },
|
{
|
||||||
|
x: pointer.x + length1 / 2 - length1 + length2 + length3,
|
||||||
|
y: pointer.y + length4 / 2 - length5 - (length4 - length5),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -623,27 +616,27 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
}
|
}
|
||||||
case 14: {
|
case 14: {
|
||||||
points = [
|
points = [
|
||||||
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 - length4 },
|
|
||||||
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 },
|
|
||||||
{ x: pointer.x - length1 / 2 + length2, y: pointer.y + length4 / 2 },
|
{ x: pointer.x - length1 / 2 + length2, y: pointer.y + length4 / 2 },
|
||||||
|
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 },
|
||||||
|
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 - length4 },
|
||||||
|
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length4 },
|
||||||
|
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length4 + length4 },
|
||||||
|
{ x: pointer.x - length1 / 2 + length1 - length3, y: pointer.y + length4 / 2 - length4 + length4 },
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + length2 + (length1 - length2 - length3) / 2,
|
x: pointer.x - length1 / 2 + length2 + (length1 - length2 - length3) / 2,
|
||||||
y: pointer.y + length4 / 2 - length4 + length5,
|
y: pointer.y + length4 / 2 - length4 + length5,
|
||||||
},
|
},
|
||||||
{ x: pointer.x - length1 / 2 + length1 - length3, y: pointer.y + length4 / 2 - length4 + length4 },
|
|
||||||
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length4 + length4 },
|
|
||||||
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length4 },
|
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
case 15: {
|
case 15: {
|
||||||
points = [
|
points = [
|
||||||
{ x: pointer.x - length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 },
|
|
||||||
{ x: pointer.x - length1 / 2, y: pointer.y + length2 - length2 / 2 },
|
{ x: pointer.x - length1 / 2, y: pointer.y + length2 - length2 / 2 },
|
||||||
{ x: pointer.x + length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 + length3 },
|
{ x: pointer.x - length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 },
|
||||||
{ x: pointer.x + length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 },
|
|
||||||
{ x: pointer.x, y: pointer.y + length2 - length2 / 2 - length3 - (length2 - length3) },
|
{ x: pointer.x, y: pointer.y + length2 - length2 / 2 - length3 - (length2 - length3) },
|
||||||
|
{ x: pointer.x + length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 },
|
||||||
|
{ x: pointer.x + length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 + length3 },
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -651,28 +644,28 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
case 16: {
|
case 16: {
|
||||||
points = [
|
points = [
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + (length1 - length2) / 2,
|
x: pointer.x - length1 / 2,
|
||||||
y: pointer.y + length3 / 2 - (length3 - length4) - length4,
|
y: pointer.y + length3 / 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + (length1 - length2) / 2,
|
x: pointer.x - length1 / 2 + (length1 - length2) / 2,
|
||||||
y: pointer.y + length3 / 2 - (length3 - length4),
|
y: pointer.y + length3 / 2 - (length3 - length4),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2,
|
x: pointer.x - length1 / 2 + (length1 - length2) / 2,
|
||||||
y: pointer.y + length3 / 2,
|
y: pointer.y + length3 / 2 - (length3 - length4) - length4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + length1,
|
x: pointer.x - length1 / 2 + (length1 - length2) / 2 + length2,
|
||||||
y: pointer.y + length3 / 2,
|
y: pointer.y + length3 / 2 - (length3 - length4) - length4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + (length1 - length2) / 2 + length2,
|
x: pointer.x - length1 / 2 + (length1 - length2) / 2 + length2,
|
||||||
y: pointer.y + length3 / 2 - (length3 - length4) - length4 + length4,
|
y: pointer.y + length3 / 2 - (length3 - length4) - length4 + length4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + (length1 - length2) / 2 + length2,
|
x: pointer.x - length1 / 2 + length1,
|
||||||
y: pointer.y + length3 / 2 - (length3 - length4) - length4,
|
y: pointer.y + length3 / 2,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
@ -683,25 +676,25 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
const topL = (length1 - length2) / 2 / Math.cos((angle * Math.PI) / 180) // 꺽이는부분 윗쪽 길이
|
const topL = (length1 - length2) / 2 / Math.cos((angle * Math.PI) / 180) // 꺽이는부분 윗쪽 길이
|
||||||
|
|
||||||
points = [
|
points = [
|
||||||
{
|
|
||||||
x: pointer.x - length1 / 2,
|
|
||||||
y: pointer.y + length3 / 2,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + length1,
|
x: pointer.x - length1 / 2 + length1,
|
||||||
y: pointer.y + length3 / 2,
|
y: pointer.y + length3 / 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)) + length2 + topL * Math.cos(degreesToRadians(angle)),
|
x: pointer.x - length1 / 2,
|
||||||
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)) + topL * Math.sin(degreesToRadians(angle)),
|
y: pointer.y + length3 / 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)),
|
||||||
|
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)) + length2,
|
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)) + length2,
|
||||||
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
|
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)),
|
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)) + length2 + topL * Math.cos(degreesToRadians(angle)),
|
||||||
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
|
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)) + topL * Math.sin(degreesToRadians(angle)),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
@ -1084,10 +1077,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
* @param { } polygon
|
* @param { } polygon
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//폴리곤, 상하반전, 좌우반전
|
|
||||||
const changeSurfaceLineType = (polygon) => {
|
const changeSurfaceLineType = (polygon) => {
|
||||||
const { isXInversion, isYInversion } = polygon //상하반전, 좌우반전
|
|
||||||
|
|
||||||
polygon.lines.forEach((line) => {
|
polygon.lines.forEach((line) => {
|
||||||
line.attributes.type = LINE_TYPE.WALLLINE.GABLE
|
line.attributes.type = LINE_TYPE.WALLLINE.GABLE
|
||||||
})
|
})
|
||||||
@ -1105,8 +1095,10 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
if (line[coord1] === line[coord2]) {
|
if (line[coord1] === line[coord2]) {
|
||||||
if (line.direction === evaesDirection) {
|
if (line.direction === evaesDirection) {
|
||||||
line.attributes.type = LINE_TYPE.WALLLINE.EAVES
|
line.attributes.type = LINE_TYPE.WALLLINE.EAVES
|
||||||
|
line.stroke = 'rgb(47, 0, 255)'
|
||||||
} else if (line.direction === ridgeDirection) {
|
} else if (line.direction === ridgeDirection) {
|
||||||
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
|
line.stroke = 'rgb(44, 255, 2)'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -1126,18 +1118,19 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
: a
|
: a
|
||||||
})
|
})
|
||||||
|
|
||||||
//정렬된 폴리곤이 아니면(대각선이 존재하는 폴리곤일때)
|
if (
|
||||||
if (!polygon.isSortedPoints) {
|
(polygon.direction === 'south' && maxLineSorted.direction === 'left') ||
|
||||||
//좌우 반전을 했으면 반대로 정의함
|
(polygon.direction === 'north' && maxLineSorted.direction === 'right') ||
|
||||||
if (isYInversion) {
|
(polygon.direction === 'east' && maxLineSorted.direction === 'bottom') ||
|
||||||
polygon.lines.forEach((line) => {
|
(polygon.direction === 'west' && maxLineSorted.direction === 'top')
|
||||||
if (line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
|
) {
|
||||||
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
polygon.lines.forEach((line) => {
|
||||||
} else if (line.attributes.type === LINE_TYPE.SUBLINE.RIDGE) {
|
if (line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
|
||||||
line.attributes.type = LINE_TYPE.WALLLINE.EAVES
|
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
}
|
} else if (line.attributes.type === LINE_TYPE.SUBLINE.RIDGE) {
|
||||||
})
|
line.attributes.type = LINE_TYPE.WALLLINE.EAVES
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxLine.length === 1) {
|
if (maxLine.length === 1) {
|
||||||
@ -1148,224 +1141,31 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
: a
|
: a
|
||||||
})
|
})
|
||||||
|
|
||||||
const isRealEavesLine = polygon.lines.filter((line) => line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
|
const isRealEavesLine = polygon.lines.find((line) => line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
|
||||||
if (isRealEavesLine.length > 0) {
|
if (isRealEavesLine) {
|
||||||
isRealEavesLine.forEach((line) => {
|
if (polygon.direction === 'south' || polygon.direction === 'north') {
|
||||||
if (polygon.direction === 'south' || polygon.direction === 'north') {
|
const targetCoord =
|
||||||
const targetCoord =
|
polygon.direction === 'south' ? Math.max(maxLineCoord.y1, maxLineCoord.y2) : Math.min(maxLineCoord.y1, maxLineCoord.y2)
|
||||||
polygon.direction === 'south' ? Math.max(maxLineCoord.y1, maxLineCoord.y2) : Math.min(maxLineCoord.y1, maxLineCoord.y2)
|
const realLineCoord =
|
||||||
const realLineCoord = polygon.direction === 'south' ? Math.max(line.y1, line.y2) : Math.min(line.y1, line.y2)
|
polygon.direction === 'south' ? Math.max(isRealEavesLine.y1, isRealEavesLine.y2) : Math.min(isRealEavesLine.y1, isRealEavesLine.y2)
|
||||||
|
|
||||||
if (targetCoord !== realLineCoord) {
|
if (targetCoord !== realLineCoord) {
|
||||||
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
isRealEavesLine.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
}
|
|
||||||
} else if (polygon.direction === 'east' || polygon.direction === 'west') {
|
|
||||||
const targetCoord =
|
|
||||||
polygon.direction === 'east' ? Math.max(maxLineCoord.x1, maxLineCoord.x2) : Math.min(maxLineCoord.x1, maxLineCoord.x2)
|
|
||||||
const realLineCoord = polygon.direction === 'east' ? Math.max(line.x1, line.x2) : Math.min(line.x1, line.x2)
|
|
||||||
|
|
||||||
if (targetCoord !== realLineCoord) {
|
|
||||||
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
} else if (polygon.direction === 'east' || polygon.direction === 'west') {
|
||||||
|
const targetCoord = polygon.direction === 'east' ? Math.max(maxLineCoord.x1, maxLineCoord.x2) : Math.min(maxLineCoord.x1, maxLineCoord.x2)
|
||||||
|
const realLineCoord =
|
||||||
|
polygon.direction === 'east' ? Math.max(isRealEavesLine.x1, isRealEavesLine.x2) : Math.min(isRealEavesLine.x1, isRealEavesLine.x2)
|
||||||
|
|
||||||
|
if (targetCoord !== realLineCoord) {
|
||||||
|
isRealEavesLine.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function findCentroid(points) {
|
|
||||||
let sumX = 0,
|
|
||||||
sumY = 0
|
|
||||||
for (let i = 0; i < points.length; i++) {
|
|
||||||
sumX += points[i].x
|
|
||||||
sumY += points[i].y
|
|
||||||
}
|
|
||||||
return { x: sumX / points.length, y: sumY / points.length }
|
|
||||||
}
|
|
||||||
|
|
||||||
// 도형의 포인트를 왼쪽부터 반시계 방향으로 정렬하는 함수
|
|
||||||
/**
|
|
||||||
* 다각형의 점들을 시계 반대 방향으로 정렬하는 함수
|
|
||||||
* @param {Array} points - {x, y} 좌표 객체 배열
|
|
||||||
* @param {Object} startPoint - 시작점 (제공되지 않으면 가장 왼쪽 아래 점을 사용)
|
|
||||||
* @returns {Array} 시계 반대 방향으로 정렬된 점들의 배열
|
|
||||||
*/
|
|
||||||
function orderPointsCounterClockwise(points, startPoint = null) {
|
|
||||||
if (points.length <= 3) {
|
|
||||||
return points // 점이 3개 이하면 이미 다각형의 모든 점이므로 그대로 반환
|
|
||||||
}
|
|
||||||
|
|
||||||
// 시작점이 제공되지 않았다면 가장 왼쪽 아래 점을 찾음
|
|
||||||
let start = startPoint
|
|
||||||
if (!start) {
|
|
||||||
start = points[0]
|
|
||||||
for (let i = 1; i < points.length; i++) {
|
|
||||||
if (points[i].x < start.x || (points[i].x === start.x && points[i].y < start.y)) {
|
|
||||||
start = points[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 다각형의 중심점 계산
|
|
||||||
let centerX = 0,
|
|
||||||
centerY = 0
|
|
||||||
for (let i = 0; i < points.length; i++) {
|
|
||||||
centerX += points[i].x
|
|
||||||
centerY += points[i].y
|
|
||||||
}
|
|
||||||
centerX /= points.length
|
|
||||||
centerY /= points.length
|
|
||||||
|
|
||||||
// 시작점에서 시계 반대 방향으로 각도 계산
|
|
||||||
let angles = []
|
|
||||||
for (let i = 0; i < points.length; i++) {
|
|
||||||
// 시작점은 제외
|
|
||||||
if (points[i] === start) continue
|
|
||||||
|
|
||||||
// 시작점을 기준으로 각 점의 각도 계산
|
|
||||||
let angle = Math.atan2(points[i].y - start.y, points[i].x - start.x)
|
|
||||||
|
|
||||||
// 각도가 음수면 2π를 더해 0~2π 범위로 변환
|
|
||||||
if (angle < 0) angle += 2 * Math.PI
|
|
||||||
|
|
||||||
angles.push({
|
|
||||||
point: points[i],
|
|
||||||
angle: angle,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 각도에 따라 정렬 (시계 반대 방향)
|
|
||||||
angles.sort((a, b) => a.angle - b.angle)
|
|
||||||
|
|
||||||
// 정렬된 배열 생성 (시작점을 첫 번째로)
|
|
||||||
let orderedPoints = [start]
|
|
||||||
for (let i = 0; i < angles.length; i++) {
|
|
||||||
orderedPoints.push(angles[i].point)
|
|
||||||
}
|
|
||||||
|
|
||||||
return orderedPoints
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 특정 점에서 시작하여 시계 반대 방향으로 다음 점을 찾는 함수
|
|
||||||
* @param {Object} currentPoint - 현재 점 {x, y}
|
|
||||||
* @param {Array} points - 모든 점들의 배열
|
|
||||||
* @param {Array} visited - 방문한 점들의 인덱스 배열
|
|
||||||
* @param {Object} prevVector - 이전 벡터 방향 (첫 호출에서는 null)
|
|
||||||
* @returns {Object} 다음 점의 인덱스와 객체
|
|
||||||
*/
|
|
||||||
function findNextCounterClockwisePoint(currentPoint, points, visited, prevVector = null) {
|
|
||||||
let minAngle = Infinity
|
|
||||||
let nextIndex = -1
|
|
||||||
|
|
||||||
// 이전 벡터가 없으면 (첫 점인 경우) 아래쪽을 향하는 벡터 사용
|
|
||||||
if (!prevVector) {
|
|
||||||
prevVector = { x: 0, y: -1 }
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < points.length; i++) {
|
|
||||||
// 이미 방문했거나 현재 점이면 건너뜀
|
|
||||||
if (visited.includes(i) || (points[i].x === currentPoint.x && points[i].y === currentPoint.y)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 현재 점에서 다음 후보 점으로의 벡터
|
|
||||||
let vector = {
|
|
||||||
x: points[i].x - currentPoint.x,
|
|
||||||
y: points[i].y - currentPoint.y,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 벡터의 크기
|
|
||||||
let magnitude = Math.sqrt(vector.x * vector.x + vector.y * vector.y)
|
|
||||||
|
|
||||||
// 단위 벡터로 정규화
|
|
||||||
vector.x /= magnitude
|
|
||||||
vector.y /= magnitude
|
|
||||||
|
|
||||||
// 이전 벡터와 현재 벡터 사이의 각도 계산 (내적 사용)
|
|
||||||
let dotProduct = prevVector.x * vector.x + prevVector.y * vector.y
|
|
||||||
let crossProduct = prevVector.x * vector.y - prevVector.y * vector.x
|
|
||||||
|
|
||||||
// 각도 계산 (atan2 사용)
|
|
||||||
let angle = Math.atan2(crossProduct, dotProduct)
|
|
||||||
|
|
||||||
// 시계 반대 방향으로 가장 작은 각도를 가진 점 찾기
|
|
||||||
// 각도가 음수면 2π를 더해 0~2π 범위로 변환
|
|
||||||
if (angle < 0) angle += 2 * Math.PI
|
|
||||||
|
|
||||||
if (angle < minAngle) {
|
|
||||||
minAngle = angle
|
|
||||||
nextIndex = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nextIndex !== -1 ? { index: nextIndex, point: points[nextIndex] } : null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 다각형의 점들을 시계 반대 방향으로 추적하는 함수
|
|
||||||
* @param {Array} points - {x, y} 좌표 객체 배열
|
|
||||||
* @param {Object} startPoint - 시작점 (제공되지 않으면 가장 왼쪽 아래 점을 사용)
|
|
||||||
* @returns {Array} 시계 반대 방향으로 정렬된 점들의 배열
|
|
||||||
*/
|
|
||||||
function tracePolygonCounterClockwise(points, startPoint = null) {
|
|
||||||
if (points.length <= 3) {
|
|
||||||
return orderPointsCounterClockwise(points, startPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 시작점이 제공되지 않았다면 가장 왼쪽 아래 점을 찾음
|
|
||||||
let startIndex = 0
|
|
||||||
if (!startPoint) {
|
|
||||||
for (let i = 1; i < points.length; i++) {
|
|
||||||
if (points[i].x < points[startIndex].x || (points[i].x === points[startIndex].x && points[i].y < points[startIndex].y)) {
|
|
||||||
startIndex = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
startPoint = points[startIndex]
|
|
||||||
} else {
|
|
||||||
// 시작점이 제공된 경우 해당 점의 인덱스 찾기
|
|
||||||
for (let i = 0; i < points.length; i++) {
|
|
||||||
if (points[i].x === startPoint.x && points[i].y === startPoint.y) {
|
|
||||||
startIndex = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 결과 배열 초기화
|
|
||||||
let orderedPoints = [startPoint]
|
|
||||||
let visited = [startIndex]
|
|
||||||
|
|
||||||
let currentPoint = startPoint
|
|
||||||
let prevVector = null
|
|
||||||
|
|
||||||
// 모든 점을 방문할 때까지 반복
|
|
||||||
while (visited.length < points.length) {
|
|
||||||
let next = findNextCounterClockwisePoint(currentPoint, points, visited, prevVector)
|
|
||||||
|
|
||||||
if (!next) break // 더 이상 찾을 점이 없으면 종료
|
|
||||||
|
|
||||||
orderedPoints.push(next.point)
|
|
||||||
visited.push(next.index)
|
|
||||||
|
|
||||||
// 이전 벡터 업데이트 (현재 점에서 다음 점으로의 벡터)
|
|
||||||
prevVector = {
|
|
||||||
x: next.point.x - currentPoint.x,
|
|
||||||
y: next.point.y - currentPoint.y,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 벡터 정규화
|
|
||||||
let magnitude = Math.sqrt(prevVector.x * prevVector.x + prevVector.y * prevVector.y)
|
|
||||||
prevVector.x /= magnitude
|
|
||||||
prevVector.y /= magnitude
|
|
||||||
|
|
||||||
currentPoint = next.point
|
|
||||||
}
|
|
||||||
|
|
||||||
return orderedPoints
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
applySurfaceShape,
|
applySurfaceShape,
|
||||||
deleteAllSurfacesAndObjects,
|
deleteAllSurfacesAndObjects,
|
||||||
|
|||||||
@ -79,9 +79,6 @@ export function useEvent() {
|
|||||||
// 마우스 위치 기준으로 확대/축소
|
// 마우스 위치 기준으로 확대/축소
|
||||||
canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom)
|
canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom)
|
||||||
|
|
||||||
canvas.requestRenderAll()
|
|
||||||
canvas.calcOffset()
|
|
||||||
|
|
||||||
// 이벤트의 기본 동작 방지 (스크롤 방지)
|
// 이벤트의 기본 동작 방지 (스크롤 방지)
|
||||||
opt.e.preventDefault()
|
opt.e.preventDefault()
|
||||||
opt.e.stopPropagation()
|
opt.e.stopPropagation()
|
||||||
|
|||||||
@ -128,7 +128,7 @@
|
|||||||
"modal.module.basic.setting.pitch.module.row.margin": "上下間隔",
|
"modal.module.basic.setting.pitch.module.row.margin": "上下間隔",
|
||||||
"modal.module.basic.setting.pitch.module.column.amount": "列数",
|
"modal.module.basic.setting.pitch.module.column.amount": "列数",
|
||||||
"modal.module.basic.setting.pitch.module.column.margin": "左右間隔",
|
"modal.module.basic.setting.pitch.module.column.margin": "左右間隔",
|
||||||
"modal.module.basic.setting.prev": "前に戻る",
|
"modal.module.basic.setting.prev": "移転",
|
||||||
"modal.module.basic.setting.passivity.placement": "手動配置",
|
"modal.module.basic.setting.passivity.placement": "手動配置",
|
||||||
"modal.module.basic.setting.auto.placement": "設定値に自動配置",
|
"modal.module.basic.setting.auto.placement": "設定値に自動配置",
|
||||||
"plan.menu.module.circuit.setting.circuit.trestle.setting": "回路設定",
|
"plan.menu.module.circuit.setting.circuit.trestle.setting": "回路設定",
|
||||||
@ -1042,6 +1042,5 @@
|
|||||||
"wall.line.not.found": "外壁がありません",
|
"wall.line.not.found": "外壁がありません",
|
||||||
"roof.line.not.found": "屋根形状がありません",
|
"roof.line.not.found": "屋根形状がありません",
|
||||||
"roof.material.can.not.delete": "割り当てられた配置面があります。",
|
"roof.material.can.not.delete": "割り当てられた配置面があります。",
|
||||||
"module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다. (JA)",
|
"module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다. (JA)"
|
||||||
"chidory.can.not.install": "千鳥配置できない工法です。"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1042,6 +1042,5 @@
|
|||||||
"wall.line.not.found": "외벽선이 없습니다.",
|
"wall.line.not.found": "외벽선이 없습니다.",
|
||||||
"roof.line.not.found": "지붕형상이 없습니다.",
|
"roof.line.not.found": "지붕형상이 없습니다.",
|
||||||
"roof.material.can.not.delete": "할당된 배치면이 있습니다.",
|
"roof.material.can.not.delete": "할당된 배치면이 있습니다.",
|
||||||
"module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다.",
|
"module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다."
|
||||||
"chidory.can.not.install": "치조 불가 공법입니다."
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user