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