194 lines
7.4 KiB
JavaScript
194 lines
7.4 KiB
JavaScript
import { useMessage } from '@/hooks/useMessage'
|
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
|
import { usePopup } from '@/hooks/usePopup'
|
|
import { useRecoilValue } from 'recoil'
|
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
|
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
|
import { useEffect, useState } from 'react'
|
|
import Big from 'big.js'
|
|
import { calcLineActualSize, calcLinePlaneSize } from '@/util/qpolygon-utils'
|
|
import { normalizeDigits } from '@/util/input-utils'
|
|
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
|
|
|
export default function AuxiliarySize(props) {
|
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
|
const { id, pos = contextPopupPosition } = props
|
|
const [checkedRadio, setCheckedRadio] = useState(null)
|
|
const [value1, setValue1] = useState('')
|
|
const [value2, setValue2] = useState('')
|
|
const [size, setSize] = useState(0)
|
|
const { getMessage } = useMessage()
|
|
const { closePopup } = usePopup()
|
|
const currentObject = useRecoilValue(currentObjectState)
|
|
const canvas = useRecoilValue(canvasState)
|
|
|
|
|
|
useEffect(() => {
|
|
return () => {
|
|
canvas?.discardActiveObject()
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
setValue1('')
|
|
setValue2('')
|
|
}, [checkedRadio])
|
|
|
|
useEffect(() => {
|
|
if (currentObject === null) closePopup(id)
|
|
}, [currentObject])
|
|
|
|
const handleInput = (e) => {
|
|
let value = e.replace(/^0+/, '')
|
|
if (value === '') {
|
|
if (checkedRadio === 1) setValue1(value)
|
|
if (checkedRadio === 2) setValue2(value)
|
|
setSize(0)
|
|
} else {
|
|
//value = Big(value.replace(/[^0-9]/g, ''))
|
|
value = Big(normalizeDigits(value))
|
|
if (checkedRadio === 1) setValue1(value.toNumber())
|
|
if (checkedRadio === 2) setValue2(value.toNumber())
|
|
setSize(value.div(10).toNumber())
|
|
}
|
|
}
|
|
|
|
const handleSave = () => {
|
|
const { x1, y1, x2, y2 } = currentObject
|
|
|
|
// 선택한 선분의 planeSize와 actualSize의 사잇각을 구한다.
|
|
const angleBetweenLines = () => {
|
|
const planeSize = Big(currentObject?.attributes.planeSize)
|
|
const actualSize = Big(currentObject?.attributes.actualSize)
|
|
// actualSize가 planeSize보다 작거나 같을때는 각도가 0
|
|
if (actualSize.lte(planeSize)) {
|
|
return 0
|
|
}
|
|
// 삼각법을 사용하여 각도를 계산합니다
|
|
// cos(theta) = adjacent / hypotenuse
|
|
const cosTheta = planeSize.div(actualSize)
|
|
const thetaRadians = Big(Math.acos(cosTheta.toNumber())) // Angle in radians
|
|
return thetaRadians.times(180).div(Math.PI)
|
|
}
|
|
const degree = angleBetweenLines()
|
|
|
|
if (size > 0 && (checkedRadio === 1 || checkedRadio === 2)) {
|
|
// 두 지점 사이의 거리를 구한다.
|
|
const dx = Big(x2).minus(Big(x1))
|
|
const dy = Big(y2).minus(Big(y1))
|
|
const distance = Big(dx.pow(2).plus(dy.pow(2)).sqrt())
|
|
|
|
if (distance > 0) {
|
|
// 현재 선분의 길이와 입력된 길이의 차이를 구한다.
|
|
const scaleFactor = Big(size).div(distance)
|
|
|
|
//1지점 선택일때는 2지점의 좌표, 2지점 선택일때는 1지점의 좌표를 조정한다.
|
|
if (checkedRadio === 1) {
|
|
const newX2 = Big(x1).plus(dx.times(scaleFactor))
|
|
const newY2 = Big(y1).plus(dy.times(scaleFactor))
|
|
currentObject.set({ x2: newX2, y2: newY2 })
|
|
} else if (checkedRadio === 2) {
|
|
const newX1 = Big(x2).minus(dx.times(scaleFactor))
|
|
const newY1 = Big(y2).minus(dy.times(scaleFactor))
|
|
currentObject.set({ x1: newX1, y1: newY1 })
|
|
}
|
|
//planeSize와 actualSize를 재계산한다.
|
|
currentObject.attributes.planeSize = calcLinePlaneSize({
|
|
x1: currentObject.x1,
|
|
y1: currentObject.y1,
|
|
x2: currentObject.x2,
|
|
y2: currentObject.y2,
|
|
})
|
|
currentObject.attributes.actualSize = calcLineActualSize(
|
|
{
|
|
x1: currentObject.x1,
|
|
y1: currentObject.y1,
|
|
x2: currentObject.x2,
|
|
y2: currentObject.y2,
|
|
},
|
|
degree,
|
|
)
|
|
currentObject.addLengthText()
|
|
}
|
|
canvas.renderAll()
|
|
}
|
|
closePopup(id)
|
|
}
|
|
return (
|
|
<WithDraggable isShow={true} pos={pos} className="xm">
|
|
<WithDraggable.Header title={getMessage('modal.auxiliary.size.edit')} onClose={() => closePopup(id)} />
|
|
<WithDraggable.Body>
|
|
<div className="discrimination-box mb10">
|
|
<div className="d-check-radio pop mb10">
|
|
<input type="radio" name="radio01" id="ra01" onClick={(e) => setCheckedRadio(1)} />
|
|
<label htmlFor="ra01">1{getMessage('modal.auxiliary.size.edit.point')}</label>
|
|
</div>
|
|
<div className="outline-form mb15">
|
|
<div className="input-grid mr5" style={{ flex: '1 1 auto' }}>
|
|
<input type="text" className="input-origin block" defaultValue={currentObject?.attributes.planeSize} readOnly={true} />
|
|
</div>
|
|
<span className="thin">mm</span>
|
|
</div>
|
|
<div className="outline-form">
|
|
<span style={{ width: 'auto' }}>{getMessage('length')}</span>
|
|
<div className="input-grid mr5">
|
|
{/*<input type="text" className="input-origin block" value={value1} readOnly={checkedRadio !== 1} onChange={handleInput} />*/}
|
|
<CalculatorInput
|
|
id=""
|
|
name=""
|
|
label=""
|
|
className="input-origin block"
|
|
value={value1}
|
|
onChange={handleInput}
|
|
readOnly={checkedRadio !== 1}
|
|
options={{
|
|
allowNegative: false,
|
|
allowDecimal: false
|
|
}}
|
|
/>
|
|
</div>
|
|
<span className="thin">mm</span>
|
|
</div>
|
|
</div>
|
|
<div className="discrimination-box ">
|
|
<div className="d-check-radio pop mb10">
|
|
<input type="radio" name="radio01" id="ra02" onClick={(e) => setCheckedRadio(2)} />
|
|
<label htmlFor="ra02">2{getMessage('modal.auxiliary.size.edit.point')}</label>
|
|
</div>
|
|
<div className="outline-form mb15">
|
|
<div className="input-grid mr5" style={{ flex: '1 1 auto' }}>
|
|
<input type="text" className="input-origin block" defaultValue={currentObject?.attributes.planeSize} readOnly={true} />
|
|
</div>
|
|
<span className="thin">mm</span>
|
|
</div>
|
|
<div className="outline-form">
|
|
<span style={{ width: 'auto' }}>{getMessage('length')}</span>
|
|
<div className="input-grid mr5">
|
|
{/*<input type="text" className="input-origin block" value={value2} readOnly={checkedRadio !== 2} onChange={handleInput} />*/}
|
|
<CalculatorInput
|
|
id=""
|
|
name=""
|
|
label=""
|
|
className="input-origin block"
|
|
value={value2}
|
|
onChange={handleInput}
|
|
readOnly={checkedRadio !== 2}
|
|
options={{
|
|
allowNegative: false,
|
|
allowDecimal: false
|
|
}}
|
|
/>
|
|
</div>
|
|
<span className="thin">mm</span>
|
|
</div>
|
|
</div>
|
|
<div className="grid-btn-wrap">
|
|
<button className="btn-frame modal act" onClick={handleSave}>
|
|
{getMessage('modal.common.save')}
|
|
</button>
|
|
</div>
|
|
</WithDraggable.Body>
|
|
</WithDraggable>
|
|
)
|
|
}
|