Merge branch 'feature/test'
This commit is contained in:
commit
fe9257044d
@ -4,7 +4,7 @@
|
|||||||
"useTabs": false,
|
"useTabs": false,
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"trailingComma": "all",
|
"trailingComma": "all",
|
||||||
"printWidth": 80,
|
"printWidth": 150,
|
||||||
"arrowParens": "always",
|
"arrowParens": "always",
|
||||||
"endOfLine": "auto"
|
"endOfLine": "auto"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
"@nextui-org/react": "^2.4.2",
|
"@nextui-org/react": "^2.4.2",
|
||||||
"fabric": "^5.3.0",
|
"fabric": "^5.3.0",
|
||||||
"framer-motion": "^11.2.13",
|
"framer-motion": "^11.2.13",
|
||||||
|
"mathjs": "^13.0.2",
|
||||||
"next": "14.2.3",
|
"next": "14.2.3",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import Hero from '@/components/Hero'
|
|
||||||
import Roof2 from '@/components/Roof2'
|
import Roof2 from '@/components/Roof2'
|
||||||
import { textState } from '@/store/canvasAtom'
|
import { textState } from '@/store/canvasAtom'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
|
|||||||
@ -7,21 +7,11 @@ import QPolygon from '@/components/fabric/QPolygon'
|
|||||||
|
|
||||||
import RangeSlider from './ui/RangeSlider'
|
import RangeSlider from './ui/RangeSlider'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import {
|
import { canvasSizeState, fontSizeState, sortedPolygonArray } from '@/store/canvasAtom'
|
||||||
canvasSizeState,
|
|
||||||
fontSizeState,
|
|
||||||
sortedPolygonArray,
|
|
||||||
} from '@/store/canvasAtom'
|
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
|
||||||
export default function Roof2() {
|
export default function Roof2() {
|
||||||
const {
|
const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage } = useCanvas('canvas')
|
||||||
canvas,
|
|
||||||
handleRedo,
|
|
||||||
handleUndo,
|
|
||||||
setCanvasBackgroundWithDots,
|
|
||||||
saveImage,
|
|
||||||
} = useCanvas('canvas')
|
|
||||||
|
|
||||||
//canvas 기본 사이즈
|
//canvas 기본 사이즈
|
||||||
const [canvasSize, setCanvasSize] = useRecoilState(canvasSizeState)
|
const [canvasSize, setCanvasSize] = useRecoilState(canvasSizeState)
|
||||||
@ -39,18 +29,8 @@ export default function Roof2() {
|
|||||||
|
|
||||||
const [showControl, setShowControl] = useState(false)
|
const [showControl, setShowControl] = useState(false)
|
||||||
|
|
||||||
const {
|
const { mode, changeMode, handleClear, fillCellInPolygon, zoomIn, zoomOut, zoom, togglePolygonLine, handleOuterlinesTest2, applyTemplateB } =
|
||||||
mode,
|
useMode()
|
||||||
changeMode,
|
|
||||||
handleClear,
|
|
||||||
fillCellInPolygon,
|
|
||||||
zoomIn,
|
|
||||||
zoomOut,
|
|
||||||
zoom,
|
|
||||||
togglePolygonLine,
|
|
||||||
handleOuterlinesTest2,
|
|
||||||
applyTemplateB,
|
|
||||||
} = useMode()
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!canvas) {
|
if (!canvas) {
|
||||||
@ -170,19 +150,33 @@ export default function Roof2() {
|
|||||||
{ x: 550, y: 300 },
|
{ x: 550, y: 300 },
|
||||||
{ x: 550, y: 450 },
|
{ x: 550, y: 450 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const type1A = [
|
||||||
|
{ x: 67, y: 81 },
|
||||||
|
{ x: 67, y: 660 },
|
||||||
|
{ x: 437, y: 660 },
|
||||||
|
{ x: 437, y: 1190 },
|
||||||
|
{ x: 858, y: 1190 },
|
||||||
|
{ x: 858, y: 81 },
|
||||||
|
]
|
||||||
|
|
||||||
|
const type1B = [
|
||||||
|
{ x: 137, y: 42 },
|
||||||
|
{ x: 137, y: 621 },
|
||||||
|
{ x: 667, y: 621 },
|
||||||
|
{ x: 667, y: 991 },
|
||||||
|
{ x: 1088, y: 991 },
|
||||||
|
{ x: 1088, y: 42 },
|
||||||
|
]
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
const polygon = new QPolygon(
|
const polygon = new QPolygon(type1, {
|
||||||
type4,
|
fill: 'transparent',
|
||||||
{
|
stroke: 'black',
|
||||||
fill: 'transparent',
|
strokeWidth: 1,
|
||||||
stroke: 'black',
|
selectable: true,
|
||||||
strokeWidth: 1,
|
fontSize: fontSize,
|
||||||
selectable: true,
|
name: 'QPolygon1',
|
||||||
fontSize: fontSize,
|
})
|
||||||
name: 'QPolygon1',
|
|
||||||
},
|
|
||||||
canvas, // 필수로 넣어줘야 함
|
|
||||||
)
|
|
||||||
|
|
||||||
canvas?.add(polygon)
|
canvas?.add(polygon)
|
||||||
|
|
||||||
@ -251,11 +245,7 @@ export default function Roof2() {
|
|||||||
{canvas && (
|
{canvas && (
|
||||||
<>
|
<>
|
||||||
<div className=" my-8 w-full text:pretty">
|
<div className=" my-8 w-full text:pretty">
|
||||||
<Button
|
<Button className="m-1 p-2" color={`${mode === Mode.DEFAULT ? 'primary' : 'default'}`} onClick={fillCellInPolygon}>
|
||||||
className="m-1 p-2"
|
|
||||||
color={`${mode === Mode.DEFAULT ? 'primary' : 'default'}`}
|
|
||||||
onClick={fillCellInPolygon}
|
|
||||||
>
|
|
||||||
모드 DEFAULT
|
모드 DEFAULT
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@ -265,39 +255,19 @@ export default function Roof2() {
|
|||||||
>
|
>
|
||||||
기준선 긋기 모드
|
기준선 긋기 모드
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button className="m-1 p-2" color={`${mode === Mode.EDIT ? 'primary' : 'default'}`} onClick={() => changeMode(canvas, Mode.EDIT)}>
|
||||||
className="m-1 p-2"
|
|
||||||
color={`${mode === Mode.EDIT ? 'primary' : 'default'}`}
|
|
||||||
onClick={() => changeMode(canvas, Mode.EDIT)}
|
|
||||||
>
|
|
||||||
에디팅모드
|
에디팅모드
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button className="m-1 p-2" color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`} onClick={() => changeMode(canvas, Mode.TEMPLATE)}>
|
||||||
className="m-1 p-2"
|
|
||||||
color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`}
|
|
||||||
onClick={() => changeMode(canvas, Mode.TEMPLATE)}
|
|
||||||
>
|
|
||||||
템플릿(기둥)
|
템플릿(기둥)
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button className="m-1 p-2" color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`} onClick={() => changeMode(canvas, Mode.PATTERNA)}>
|
||||||
className="m-1 p-2"
|
|
||||||
color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`}
|
|
||||||
onClick={() => changeMode(canvas, Mode.PATTERNA)}
|
|
||||||
>
|
|
||||||
템플릿(A 패턴)
|
템플릿(A 패턴)
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button className="m-1 p-2" color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`} onClick={() => changeMode(canvas, Mode.PATTERNB)}>
|
||||||
className="m-1 p-2"
|
|
||||||
color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`}
|
|
||||||
onClick={() => changeMode(canvas, Mode.PATTERNB)}
|
|
||||||
>
|
|
||||||
템플릿(B 패턴)
|
템플릿(B 패턴)
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button className="m-1 p-2" color={`${mode === Mode.TEXTBOX ? 'primary' : 'default'}`} onClick={() => changeMode(canvas, Mode.TEXTBOX)}>
|
||||||
className="m-1 p-2"
|
|
||||||
color={`${mode === Mode.TEXTBOX ? 'primary' : 'default'}`}
|
|
||||||
onClick={() => changeMode(canvas, Mode.TEXTBOX)}
|
|
||||||
>
|
|
||||||
텍스트박스 모드
|
텍스트박스 모드
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@ -363,30 +333,13 @@ export default function Roof2() {
|
|||||||
<Button className="m-1 p-2" onClick={PolygonToLine}>
|
<Button className="m-1 p-2" onClick={PolygonToLine}>
|
||||||
PolygonToLine
|
PolygonToLine
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}>
|
||||||
className="m-1 p-2"
|
|
||||||
color={`${showControl ? 'primary' : 'default'}`}
|
|
||||||
onClick={handleShowController}
|
|
||||||
>
|
|
||||||
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
|
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div className={showControl ? `flex justify-center flex-col items-center` : `hidden`}>
|
||||||
className={
|
|
||||||
showControl
|
|
||||||
? `flex justify-center flex-col items-center`
|
|
||||||
: `hidden`
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className="m-2 p-2 w-80">
|
<div className="m-2 p-2 w-80">
|
||||||
<RangeSlider
|
<RangeSlider title={`각도${angle}`} initValue={angle} min="0" step="1" max="360" onchange={setAngle} />
|
||||||
title={`각도${angle}`}
|
|
||||||
initValue={angle}
|
|
||||||
min="0"
|
|
||||||
step="1"
|
|
||||||
max="360"
|
|
||||||
onchange={setAngle}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="m-2 p-2 w-80">
|
<div className="m-2 p-2 w-80">
|
||||||
<RangeSlider
|
<RangeSlider
|
||||||
@ -409,11 +362,7 @@ export default function Roof2() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="m-2 p-2 w-80">
|
<div className="m-2 p-2 w-80">
|
||||||
<RangeSlider
|
<RangeSlider title={`글자 크기${fontSize}`} initValue={fontSize} onchange={setFontSize} />
|
||||||
title={`글자 크기${fontSize}`}
|
|
||||||
initValue={fontSize}
|
|
||||||
onchange={setFontSize}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
108
src/components/fabric/HelpLine.js
Normal file
108
src/components/fabric/HelpLine.js
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import { fabric } from 'fabric'
|
||||||
|
|
||||||
|
export class QLine extends fabric.Group {
|
||||||
|
line
|
||||||
|
text
|
||||||
|
fontSize
|
||||||
|
length = 0
|
||||||
|
x1
|
||||||
|
y1
|
||||||
|
x2
|
||||||
|
y2
|
||||||
|
direction
|
||||||
|
type = 'HelpLine'
|
||||||
|
parent
|
||||||
|
#lengthTxt = 0
|
||||||
|
|
||||||
|
constructor(points, option, lengthTxt) {
|
||||||
|
const [x1, y1, x2, y2] = points
|
||||||
|
|
||||||
|
if (!option.fontSize) {
|
||||||
|
throw new Error('Font size is required.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const line = new fabric.Line(points, { ...option, strokeWidth: 1 })
|
||||||
|
super([line], {})
|
||||||
|
|
||||||
|
this.x1 = x1
|
||||||
|
this.y1 = y1
|
||||||
|
this.x2 = x2
|
||||||
|
this.y2 = y2
|
||||||
|
this.line = line
|
||||||
|
this.fontSize = option.fontSize
|
||||||
|
this.direction = option.direction
|
||||||
|
this.parent = option.parent
|
||||||
|
|
||||||
|
if (lengthTxt > 0) {
|
||||||
|
this.#lengthTxt = Number(lengthTxt)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#init()
|
||||||
|
this.#addControl()
|
||||||
|
}
|
||||||
|
|
||||||
|
#init() {
|
||||||
|
this.#addLengthText(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
#addControl() {
|
||||||
|
this.on('moving', () => {
|
||||||
|
this.#addLengthText(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.on('modified', (e) => {
|
||||||
|
this.#addLengthText(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.on('selected', () => {
|
||||||
|
Object.keys(this.controls).forEach((controlKey) => {
|
||||||
|
if (controlKey !== 'ml' && controlKey !== 'mr') {
|
||||||
|
this.setControlVisible(controlKey, false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#addLengthText(isFirst) {
|
||||||
|
if (this.text) {
|
||||||
|
this.removeWithUpdate(this.text)
|
||||||
|
this.text = null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFirst && this.#lengthTxt > 0) {
|
||||||
|
const text = new fabric.Textbox(this.#lengthTxt.toFixed(0).toString(), {
|
||||||
|
left: (this.x1 + this.x2) / 2,
|
||||||
|
top: (this.y1 + this.y2) / 2,
|
||||||
|
fontSize: this.fontSize,
|
||||||
|
})
|
||||||
|
this.length = this.#lengthTxt
|
||||||
|
this.text = text
|
||||||
|
this.addWithUpdate(text)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const scaleX = this.scaleX
|
||||||
|
const scaleY = this.scaleY
|
||||||
|
const x1 = this.left
|
||||||
|
const y1 = this.top
|
||||||
|
const x2 = this.left + this.width * scaleX
|
||||||
|
const y2 = this.top + this.height * scaleY
|
||||||
|
const dx = x2 - x1
|
||||||
|
const dy = y2 - y1
|
||||||
|
this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0))
|
||||||
|
|
||||||
|
const text = new fabric.Textbox(this.length.toFixed(0).toString(), {
|
||||||
|
left: (x1 + x2) / 2,
|
||||||
|
top: (y1 + y2) / 2,
|
||||||
|
fontSize: this.fontSize,
|
||||||
|
})
|
||||||
|
this.text = text
|
||||||
|
this.addWithUpdate(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
setFontSize(fontSize) {
|
||||||
|
this.fontSize = fontSize
|
||||||
|
this.text.set({ fontSize })
|
||||||
|
this.addWithUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,11 +10,17 @@ export class QLine extends fabric.Group {
|
|||||||
x2
|
x2
|
||||||
y2
|
y2
|
||||||
direction
|
direction
|
||||||
|
idx
|
||||||
type = 'QLine'
|
type = 'QLine'
|
||||||
parent
|
parent
|
||||||
#lengthTxt = 0
|
#lengthTxt = 0
|
||||||
|
|
||||||
constructor(points, option, lengthTxt) {
|
constructor(points, option = { isActiveLengthText: true }, lengthTxt) {
|
||||||
|
// 소수점 전부 제거
|
||||||
|
points.forEach((point) => {
|
||||||
|
point = Math.round(point)
|
||||||
|
})
|
||||||
|
|
||||||
const [x1, y1, x2, y2] = points
|
const [x1, y1, x2, y2] = points
|
||||||
|
|
||||||
if (!option.fontSize) {
|
if (!option.fontSize) {
|
||||||
@ -32,12 +38,13 @@ export class QLine extends fabric.Group {
|
|||||||
this.fontSize = option.fontSize
|
this.fontSize = option.fontSize
|
||||||
this.direction = option.direction
|
this.direction = option.direction
|
||||||
this.parent = option.parent
|
this.parent = option.parent
|
||||||
|
this.idx = option.idx
|
||||||
|
|
||||||
if (lengthTxt > 0) {
|
if (lengthTxt > 0) {
|
||||||
this.#lengthTxt = Number(lengthTxt)
|
this.#lengthTxt = Number(lengthTxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#init()
|
option.isActiveLengthText ?? this.#init()
|
||||||
this.#addControl()
|
this.#addControl()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import {
|
import {
|
||||||
|
calculateIntersection,
|
||||||
distanceBetweenPoints,
|
distanceBetweenPoints,
|
||||||
|
findClosestLineToPoint,
|
||||||
findTopTwoIndexesByDistance,
|
findTopTwoIndexesByDistance,
|
||||||
getDegreeByChon,
|
getDegreeByChon,
|
||||||
getDirectionByPoint,
|
getDirectionByPoint,
|
||||||
@ -23,14 +25,22 @@ export default class QPolygon extends fabric.Group {
|
|||||||
shape = 0 // 점 6개일때의 shape 모양
|
shape = 0 // 점 6개일때의 shape 모양
|
||||||
helpPoints = []
|
helpPoints = []
|
||||||
helpLines = []
|
helpLines = []
|
||||||
|
|
||||||
|
wall
|
||||||
constructor(points, options, canvas) {
|
constructor(points, options, canvas) {
|
||||||
if (points.length !== 4 && points.length !== 6) {
|
/*if (points.length !== 4 && points.length !== 6) {
|
||||||
throw new Error('Points must be 4 or 6.')
|
throw new Error('Points must be 4 or 6.')
|
||||||
}
|
}*/
|
||||||
if (!options.fontSize) {
|
if (!options.fontSize) {
|
||||||
throw new Error('Font size is required.')
|
throw new Error('Font size is required.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 소수점 전부 제거
|
||||||
|
points.forEach((point) => {
|
||||||
|
point.x = Math.round(point.x)
|
||||||
|
point.y = Math.round(point.y)
|
||||||
|
})
|
||||||
|
|
||||||
const sortPoints = sortedPoints(points)
|
const sortPoints = sortedPoints(points)
|
||||||
const polygon = new fabric.Polygon(sortPoints, options)
|
const polygon = new fabric.Polygon(sortPoints, options)
|
||||||
|
|
||||||
@ -80,6 +90,10 @@ export default class QPolygon extends fabric.Group {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setWall(wall) {
|
||||||
|
this.wall = wall
|
||||||
|
}
|
||||||
|
|
||||||
setFontSize(fontSize) {
|
setFontSize(fontSize) {
|
||||||
this.fontSize = fontSize
|
this.fontSize = fontSize
|
||||||
this.texts.forEach((text) => {
|
this.texts.forEach((text) => {
|
||||||
@ -110,10 +124,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
const dy = end.y - start.y
|
const dy = end.y - start.y
|
||||||
const length = Math.sqrt(dx * dx + dy * dy)
|
const length = Math.sqrt(dx * dx + dy * dy)
|
||||||
|
|
||||||
const midPoint = new fabric.Point(
|
const midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2)
|
||||||
(start.x + end.x) / 2,
|
|
||||||
(start.y + end.y) / 2,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create new text object if it doesn't exist
|
// Create new text object if it doesn't exist
|
||||||
const text = new fabric.Text(length.toFixed(0), {
|
const text = new fabric.Text(length.toFixed(0), {
|
||||||
@ -157,16 +168,8 @@ export default class QPolygon extends fabric.Group {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for (
|
for (let x = bounds.left; x < bounds.left + bounds.width; x += cell.width + cell.padding) {
|
||||||
let x = bounds.left;
|
for (let y = bounds.top; y < bounds.top + bounds.height; y += cell.height + cell.padding) {
|
||||||
x < bounds.left + bounds.width;
|
|
||||||
x += cell.width + cell.padding
|
|
||||||
) {
|
|
||||||
for (
|
|
||||||
let y = bounds.top;
|
|
||||||
y < bounds.top + bounds.height;
|
|
||||||
y += cell.height + cell.padding
|
|
||||||
) {
|
|
||||||
const rect = new fabric.Rect({
|
const rect = new fabric.Rect({
|
||||||
left: x,
|
left: x,
|
||||||
top: y,
|
top: y,
|
||||||
@ -184,11 +187,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
new fabric.Point(rect.left + rect.width, rect.top + rect.height),
|
new fabric.Point(rect.left + rect.width, rect.top + rect.height),
|
||||||
]
|
]
|
||||||
|
|
||||||
const isInside = rectPoints.every(
|
const isInside = rectPoints.every((rectPoint) => this.inPolygon(rectPoint) && this.#distanceFromEdge(rectPoint) >= cell.padding)
|
||||||
(rectPoint) =>
|
|
||||||
this.inPolygon(rectPoint) &&
|
|
||||||
this.#distanceFromEdge(rectPoint) >= cell.padding,
|
|
||||||
)
|
|
||||||
|
|
||||||
if (isInside) {
|
if (isInside) {
|
||||||
this.addWithUpdate(rect)
|
this.addWithUpdate(rect)
|
||||||
@ -205,24 +204,13 @@ export default class QPolygon extends fabric.Group {
|
|||||||
* return {boolean}
|
* return {boolean}
|
||||||
*/
|
*/
|
||||||
isValid() {
|
isValid() {
|
||||||
const leftLinesLengthSum = this.lines
|
const leftLinesLengthSum = this.lines.filter((line) => line.direction === 'left').reduce((sum, line) => sum + line.length, 0)
|
||||||
.filter((line) => line.direction === 'left')
|
const rightLinesLengthSum = this.lines.filter((line) => line.direction === 'right').reduce((sum, line) => sum + line.length, 0)
|
||||||
.reduce((sum, line) => sum + line.length, 0)
|
|
||||||
const rightLinesLengthSum = this.lines
|
|
||||||
.filter((line) => line.direction === 'right')
|
|
||||||
.reduce((sum, line) => sum + line.length, 0)
|
|
||||||
|
|
||||||
const topLinesLengthSum = this.lines
|
const topLinesLengthSum = this.lines.filter((line) => line.direction === 'top').reduce((sum, line) => sum + line.length, 0)
|
||||||
.filter((line) => line.direction === 'top')
|
const bottomLinesLengthSum = this.lines.filter((line) => line.direction === 'bottom').reduce((sum, line) => sum + line.length, 0)
|
||||||
.reduce((sum, line) => sum + line.length, 0)
|
|
||||||
const bottomLinesLengthSum = this.lines
|
|
||||||
.filter((line) => line.direction === 'bottom')
|
|
||||||
.reduce((sum, line) => sum + line.length, 0)
|
|
||||||
|
|
||||||
return (
|
return leftLinesLengthSum === rightLinesLengthSum && topLinesLengthSum === bottomLinesLengthSum
|
||||||
leftLinesLengthSum === rightLinesLengthSum &&
|
|
||||||
topLinesLengthSum === bottomLinesLengthSum
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inPolygon(point) {
|
inPolygon(point) {
|
||||||
@ -247,10 +235,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let xInt =
|
let xInt = ((point.y - vertex1.y) * (vertex2.x - vertex1.x)) / (vertex2.y - vertex1.y) + vertex1.x
|
||||||
((point.y - vertex1.y) * (vertex2.x - vertex1.x)) /
|
|
||||||
(vertex2.y - vertex1.y) +
|
|
||||||
vertex1.x
|
|
||||||
if (xInt < point.x) {
|
if (xInt < point.x) {
|
||||||
intersects++
|
intersects++
|
||||||
}
|
}
|
||||||
@ -270,9 +255,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
const dx = vertex2.x - vertex1.x
|
const dx = vertex2.x - vertex1.x
|
||||||
const dy = vertex2.y - vertex1.y
|
const dy = vertex2.y - vertex1.y
|
||||||
|
|
||||||
const t =
|
const t = ((point.x - vertex1.x) * dx + (point.y - vertex1.y) * dy) / (dx * dx + dy * dy)
|
||||||
((point.x - vertex1.x) * dx + (point.y - vertex1.y) * dy) /
|
|
||||||
(dx * dx + dy * dy)
|
|
||||||
|
|
||||||
let closestPoint
|
let closestPoint
|
||||||
if (t < 0) {
|
if (t < 0) {
|
||||||
@ -352,9 +335,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
//외각선 기준
|
//외각선 기준
|
||||||
const topIndex = findTopTwoIndexesByDistance(this.lines).sort(
|
const topIndex = findTopTwoIndexesByDistance(this.lines).sort((a, b) => a - b) //배열중에 큰 2값을 가져옴 TODO: 나중에는 인자로 받아서 다각으로 수정 해야됨
|
||||||
(a, b) => a - b,
|
|
||||||
) //배열중에 큰 2값을 가져옴 TODO: 나중에는 인자로 받아서 다각으로 수정 해야됨
|
|
||||||
|
|
||||||
//일단 배열 6개 짜리 기준의 선 번호
|
//일단 배열 6개 짜리 기준의 선 번호
|
||||||
if (topIndex[0] === 4) {
|
if (topIndex[0] === 4) {
|
||||||
@ -425,23 +406,15 @@ export default class QPolygon extends fabric.Group {
|
|||||||
const direction = smallestLines[0].direction
|
const direction = smallestLines[0].direction
|
||||||
|
|
||||||
if (direction === 'top' || direction === 'bottom') {
|
if (direction === 'top' || direction === 'bottom') {
|
||||||
needPlusLine =
|
needPlusLine = smallestLines[0].x1 < smallestLines[1].x1 ? smallestLines[0] : smallestLines[1]
|
||||||
smallestLines[0].x1 < smallestLines[1].x1
|
needMinusLine = needPlusLine === smallestLines[0] ? smallestLines[1] : smallestLines[0]
|
||||||
? smallestLines[0]
|
|
||||||
: smallestLines[1]
|
|
||||||
needMinusLine =
|
|
||||||
needPlusLine === smallestLines[0] ? smallestLines[1] : smallestLines[0]
|
|
||||||
|
|
||||||
type = 1 // 가로가 긴 사각형
|
type = 1 // 가로가 긴 사각형
|
||||||
}
|
}
|
||||||
|
|
||||||
if (direction === 'left' || direction === 'right') {
|
if (direction === 'left' || direction === 'right') {
|
||||||
needPlusLine =
|
needPlusLine = smallestLines[0].y1 < smallestLines[1].y1 ? smallestLines[0] : smallestLines[1]
|
||||||
smallestLines[0].y1 < smallestLines[1].y1
|
needMinusLine = needPlusLine === smallestLines[0] ? smallestLines[1] : smallestLines[0]
|
||||||
? smallestLines[0]
|
|
||||||
: smallestLines[1]
|
|
||||||
needMinusLine =
|
|
||||||
needPlusLine === smallestLines[0] ? smallestLines[1] : smallestLines[0]
|
|
||||||
|
|
||||||
type = 2 // 세로가 긴 사각형
|
type = 2 // 세로가 긴 사각형
|
||||||
}
|
}
|
||||||
@ -452,33 +425,21 @@ export default class QPolygon extends fabric.Group {
|
|||||||
if (type === 1) {
|
if (type === 1) {
|
||||||
point1 = {
|
point1 = {
|
||||||
x: needPlusLine.x1 + smallestLength / 2,
|
x: needPlusLine.x1 + smallestLength / 2,
|
||||||
y:
|
y: needPlusLine.y1 > needPlusLine.y2 ? needPlusLine.y1 - smallestLength / 2 : needPlusLine.y2 - smallestLength / 2,
|
||||||
needPlusLine.y1 > needPlusLine.y2
|
|
||||||
? needPlusLine.y1 - smallestLength / 2
|
|
||||||
: needPlusLine.y2 - smallestLength / 2,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
point2 = {
|
point2 = {
|
||||||
x: needMinusLine.x1 - smallestLength / 2,
|
x: needMinusLine.x1 - smallestLength / 2,
|
||||||
y:
|
y: needMinusLine.y1 > needMinusLine.y2 ? needMinusLine.y1 - smallestLength / 2 : needMinusLine.y2 - smallestLength / 2,
|
||||||
needMinusLine.y1 > needMinusLine.y2
|
|
||||||
? needMinusLine.y1 - smallestLength / 2
|
|
||||||
: needMinusLine.y2 - smallestLength / 2,
|
|
||||||
}
|
}
|
||||||
} else if (type === 2) {
|
} else if (type === 2) {
|
||||||
point1 = {
|
point1 = {
|
||||||
x:
|
x: needPlusLine.x1 > needPlusLine.x2 ? needPlusLine.x1 - smallestLength / 2 : needPlusLine.x2 - smallestLength / 2,
|
||||||
needPlusLine.x1 > needPlusLine.x2
|
|
||||||
? needPlusLine.x1 - smallestLength / 2
|
|
||||||
: needPlusLine.x2 - smallestLength / 2,
|
|
||||||
y: needPlusLine.y1 + smallestLength / 2,
|
y: needPlusLine.y1 + smallestLength / 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
point2 = {
|
point2 = {
|
||||||
x:
|
x: needMinusLine.x1 > needMinusLine.x2 ? needMinusLine.x1 - smallestLength / 2 : needMinusLine.x2 - smallestLength / 2,
|
||||||
needMinusLine.x1 > needMinusLine.x2
|
|
||||||
? needMinusLine.x1 - smallestLength / 2
|
|
||||||
: needMinusLine.x2 - smallestLength / 2,
|
|
||||||
y: needMinusLine.y1 - smallestLength / 2,
|
y: needMinusLine.y1 - smallestLength / 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -566,357 +527,144 @@ export default class QPolygon extends fabric.Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#drawHelpLineInHexagon(chon) {
|
#drawHelpLineInHexagon(chon) {
|
||||||
let type = this.shape
|
const historyLines = []
|
||||||
|
const helpPoints = []
|
||||||
|
const notInterSectionLines = []
|
||||||
|
const ridge = []
|
||||||
|
const maxLength = this.lines.reduce((max, obj) => Math.min(max, obj.length), 999999)
|
||||||
|
this.points.forEach((point, index) => {
|
||||||
|
const wallPoint = this.wall.points[index]
|
||||||
|
// 두 점의 좌표
|
||||||
|
const x1 = point.x
|
||||||
|
const y1 = point.y
|
||||||
|
const x2 = wallPoint.x
|
||||||
|
const y2 = wallPoint.y
|
||||||
|
|
||||||
// 1 = 0, 3
|
let newX2, newY2
|
||||||
// 2 = 2, 5
|
|
||||||
// 3 = 1, 4
|
|
||||||
// 4 = 0, 3
|
|
||||||
|
|
||||||
// 라인 기준점 1,2
|
// x1, y1을 기준으로 x2, y2와의 거리를 유지한 새로운 직선 생성
|
||||||
let lines, lines2
|
const angle = Math.atan2(y2 - y1, x2 - x1)
|
||||||
// 용마루 시작점 2개
|
|
||||||
let vPoint1, vPoint2
|
|
||||||
// 용마루 시작점과 만나는 지붕의 중앙
|
|
||||||
let centerPoint1, centerPoint2
|
|
||||||
|
|
||||||
// 가장 긴 라인
|
newX2 = x1 + (maxLength + 50) * Math.cos(angle)
|
||||||
let longestLines
|
newY2 = y1 + (maxLength + 50) * Math.sin(angle)
|
||||||
|
|
||||||
// 용마루 길이
|
const line = new QLine([x1, y1, newX2, newY2], {
|
||||||
let ridgeLength = 0
|
fontSize: this.fontSize,
|
||||||
let ridgeStartPoint1, ridgeStartPoint2
|
stroke: 'blue',
|
||||||
|
idx: index,
|
||||||
|
})
|
||||||
|
historyLines.push(line)
|
||||||
|
this.addWithUpdate(line)
|
||||||
|
|
||||||
let ridgeEndPoint1, ridgeEndPoint2
|
this.canvas.renderAll()
|
||||||
|
})
|
||||||
|
|
||||||
let ridgeLength1, ridgeLength2
|
/**
|
||||||
|
* 삼각 지붕
|
||||||
|
*/
|
||||||
|
historyLines.forEach((line, index) => {
|
||||||
|
const prevLine = historyLines[(index - 1 + historyLines.length) % historyLines.length]
|
||||||
|
|
||||||
let ridgeHelpLinePoint1, ridgeHelpLinePoint2
|
let intersectionPoint = calculateIntersection(line, prevLine)
|
||||||
|
|
||||||
if (type === 1) {
|
if (!intersectionPoint) {
|
||||||
lines = [this.lines[0], this.lines[3]]
|
notInterSectionLines.push(line)
|
||||||
lines2 = [this.lines[1], this.lines[4]]
|
return
|
||||||
longestLines = [this.lines[4], this.lines[5]]
|
|
||||||
ridgeLength1 = lines2[0].length
|
|
||||||
ridgeLength2 = longestLines[0].length - lines[1].length
|
|
||||||
vPoint1 = {
|
|
||||||
x: lines[0].x1 + lines[0].length / 2,
|
|
||||||
y: lines[0].y1 + lines[0].length / 2,
|
|
||||||
}
|
|
||||||
vPoint2 = {
|
|
||||||
x: lines[1].x1 + lines[1].length / 2,
|
|
||||||
y: lines[1].y1 - lines[1].length / 2,
|
|
||||||
}
|
|
||||||
centerPoint1 = {
|
|
||||||
x: (lines[0].x1 + lines[0].x2) / 2,
|
|
||||||
y: (lines[0].y1 + lines[0].y2) / 2,
|
|
||||||
}
|
|
||||||
centerPoint2 = {
|
|
||||||
x: (lines[1].x1 + lines[1].x2) / 2,
|
|
||||||
y: (lines[1].y1 + lines[1].y2) / 2,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ridgeEndPoint1 = [
|
const helpLine1 = new QLine([prevLine.x1, prevLine.y1, intersectionPoint.x, intersectionPoint.y], {
|
||||||
vPoint1.x,
|
fontSize: this.fontSize,
|
||||||
vPoint1.y,
|
stroke: 'red',
|
||||||
vPoint1.x + ridgeLength1,
|
})
|
||||||
vPoint1.y,
|
|
||||||
]
|
|
||||||
ridgeEndPoint2 = [
|
|
||||||
vPoint2.x,
|
|
||||||
vPoint2.y,
|
|
||||||
vPoint2.x,
|
|
||||||
vPoint2.y - ridgeLength2,
|
|
||||||
]
|
|
||||||
|
|
||||||
ridgeHelpLinePoint1 = [
|
const helpLine2 = new QLine([line.x1, line.y1, intersectionPoint.x, intersectionPoint.y], {
|
||||||
lines2[0].x2,
|
fontSize: this.fontSize,
|
||||||
lines2[0].y2,
|
stroke: 'red',
|
||||||
ridgeEndPoint1[2],
|
})
|
||||||
ridgeEndPoint1[3],
|
notInterSectionLines.pop()
|
||||||
]
|
helpPoints.push(intersectionPoint)
|
||||||
ridgeHelpLinePoint2 = [
|
|
||||||
lines2[1].x2,
|
this.addWithUpdate(helpLine1)
|
||||||
lines2[1].y2,
|
this.addWithUpdate(helpLine2)
|
||||||
ridgeEndPoint2[2],
|
this.removeWithUpdate(prevLine)
|
||||||
ridgeEndPoint2[3],
|
this.removeWithUpdate(line)
|
||||||
]
|
this.canvas.renderAll()
|
||||||
} else if (type === 2) {
|
})
|
||||||
lines = [this.lines[2], this.lines[5]]
|
// 용마루
|
||||||
lines2 = [this.lines[0], this.lines[3]]
|
|
||||||
longestLines = [this.lines[0], this.lines[1]]
|
const ridgePoint = []
|
||||||
ridgeLength1 = lines2[1].length
|
|
||||||
ridgeLength2 = longestLines[0].length - lines[1].length
|
helpPoints.forEach((helpPoint, index) => {
|
||||||
vPoint1 = {
|
const closestLine = findClosestLineToPoint(helpPoint, notInterSectionLines)
|
||||||
x: lines[0].x1 - lines[0].length / 2,
|
|
||||||
y: lines[0].y1 - lines[0].length / 2,
|
// 가까운 선의 중심점
|
||||||
}
|
const centerClosestLinePoint = {
|
||||||
vPoint2 = {
|
x: (closestLine.x1 + closestLine.x2) / 2,
|
||||||
x: lines[1].x1 - lines[1].length / 2,
|
y: (closestLine.y1 + closestLine.y2) / 2,
|
||||||
y: lines[1].y1 + lines[1].length / 2,
|
|
||||||
}
|
|
||||||
centerPoint1 = {
|
|
||||||
x: (lines[0].x1 + lines[0].x2) / 2,
|
|
||||||
y: (lines[0].y1 + lines[0].y2) / 2,
|
|
||||||
}
|
|
||||||
centerPoint2 = {
|
|
||||||
x: (lines[1].x1 + lines[1].x2) / 2,
|
|
||||||
y: (lines[1].y1 + lines[1].y2) / 2,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ridgeEndPoint1 = [
|
const direction = getDirectionByPoint(helpPoint, centerClosestLinePoint)
|
||||||
vPoint1.x,
|
|
||||||
vPoint1.y,
|
|
||||||
vPoint1.x - ridgeLength1,
|
|
||||||
vPoint1.y,
|
|
||||||
]
|
|
||||||
|
|
||||||
ridgeEndPoint2 = [
|
let newX, newY
|
||||||
vPoint2.x,
|
|
||||||
vPoint2.y,
|
|
||||||
vPoint2.x,
|
|
||||||
vPoint2.y + ridgeLength2,
|
|
||||||
]
|
|
||||||
|
|
||||||
ridgeHelpLinePoint1 = [
|
switch (direction) {
|
||||||
lines2[1].x2,
|
case 'left': {
|
||||||
lines2[1].y2,
|
newX = ((closestLine.x2 - closestLine.x1) * (helpPoint.y - closestLine.y1)) / (closestLine.y2 - closestLine.y1) + closestLine.x1
|
||||||
ridgeEndPoint1[2],
|
newY = helpPoint.y
|
||||||
ridgeEndPoint1[3],
|
break
|
||||||
]
|
}
|
||||||
ridgeHelpLinePoint2 = [
|
case 'right': {
|
||||||
lines2[0].x2,
|
newX = ((closestLine.x2 - closestLine.x1) * (helpPoint.y - closestLine.y1)) / (closestLine.y2 - closestLine.y1) + closestLine.x1
|
||||||
lines2[0].y2,
|
newY = helpPoint.y
|
||||||
ridgeEndPoint2[2],
|
break
|
||||||
ridgeEndPoint2[3],
|
}
|
||||||
]
|
case 'top': {
|
||||||
} else if (type === 3) {
|
newX = helpPoint.x
|
||||||
lines = [this.lines[1], this.lines[4]]
|
newY = ((closestLine.y2 - closestLine.y1) * (helpPoint.x - closestLine.x1)) / (closestLine.x2 - closestLine.x1) + closestLine.y1
|
||||||
lines2 = [this.lines[2], this.lines[5]]
|
break
|
||||||
longestLines = [this.lines[0], this.lines[5]]
|
}
|
||||||
ridgeLength1 = this.lines[3].length
|
case 'bottom': {
|
||||||
ridgeLength2 = longestLines[0].length - lines[0].length
|
newX = helpPoint.x
|
||||||
vPoint1 = {
|
newY = ((closestLine.y2 - closestLine.y1) * (helpPoint.x - closestLine.x1)) / (closestLine.x2 - closestLine.x1) + closestLine.y1
|
||||||
x: lines[0].x1 + lines[0].length / 2,
|
break
|
||||||
y: lines[0].y1 - lines[0].length / 2,
|
}
|
||||||
}
|
|
||||||
vPoint2 = {
|
|
||||||
x: lines[1].x1 - lines[1].length / 2,
|
|
||||||
y: lines[1].y1 - lines[1].length / 2,
|
|
||||||
}
|
|
||||||
centerPoint1 = {
|
|
||||||
x: (lines[0].x1 + lines[0].x2) / 2,
|
|
||||||
y: (lines[0].y1 + lines[0].y2) / 2,
|
|
||||||
}
|
|
||||||
centerPoint2 = {
|
|
||||||
x: (lines[1].x1 + lines[1].x2) / 2,
|
|
||||||
y: (lines[1].y1 + lines[1].y2) / 2,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ridgeEndPoint1 = [
|
const ridgeHelpLine = new QLine([closestLine.x1, closestLine.y1, newX, newY], {
|
||||||
vPoint1.x,
|
fontSize: this.fontSize,
|
||||||
vPoint1.y,
|
stroke: 'purple',
|
||||||
vPoint1.x,
|
strokeWidth: 5,
|
||||||
vPoint1.y - ridgeLength2,
|
})
|
||||||
]
|
|
||||||
|
|
||||||
ridgeEndPoint2 = [
|
ridgePoint.push({ x: newX, y: newY })
|
||||||
vPoint2.x,
|
|
||||||
vPoint2.y,
|
|
||||||
vPoint2.x - ridgeLength1,
|
|
||||||
vPoint2.y,
|
|
||||||
]
|
|
||||||
|
|
||||||
ridgeHelpLinePoint1 = [
|
const ridge = new QLine([helpPoint.x, helpPoint.y, newX, newY], {
|
||||||
lines2[1].x2,
|
fontSize: this.fontSize,
|
||||||
lines2[1].y2,
|
stroke: 'skyblue',
|
||||||
ridgeEndPoint1[2],
|
strokeWidth: 5,
|
||||||
ridgeEndPoint1[3],
|
})
|
||||||
]
|
|
||||||
ridgeHelpLinePoint2 = [
|
|
||||||
lines2[0].x2,
|
|
||||||
lines2[0].y2,
|
|
||||||
ridgeEndPoint2[2],
|
|
||||||
ridgeEndPoint2[3],
|
|
||||||
]
|
|
||||||
} else if (type === 4) {
|
|
||||||
lines = [this.lines[0], this.lines[3]]
|
|
||||||
lines2 = [this.lines[1], this.lines[4]]
|
|
||||||
longestLines = [this.lines[1], this.lines[2]]
|
|
||||||
ridgeLength1 = longestLines[0].length - lines[0].length
|
|
||||||
ridgeLength2 = this.lines[4].length
|
|
||||||
vPoint1 = {
|
|
||||||
x: lines[0].x1 + lines[0].length / 2,
|
|
||||||
y: lines[0].y1 + lines[0].length / 2,
|
|
||||||
}
|
|
||||||
vPoint2 = {
|
|
||||||
x: lines[1].x1 - lines[1].length / 2,
|
|
||||||
y: lines[1].y1 + lines[1].length / 2,
|
|
||||||
}
|
|
||||||
centerPoint1 = {
|
|
||||||
x: (lines[0].x1 + lines[0].x2) / 2,
|
|
||||||
y: (lines[0].y1 + lines[0].y2) / 2,
|
|
||||||
}
|
|
||||||
centerPoint2 = {
|
|
||||||
x: (lines[1].x1 + lines[1].x2) / 2,
|
|
||||||
y: (lines[1].y1 + lines[1].y2) / 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
ridgeEndPoint1 = [
|
this.addWithUpdate(ridge)
|
||||||
vPoint1.x,
|
this.canvas.renderAll()
|
||||||
vPoint1.y,
|
|
||||||
vPoint1.x + ridgeLength1,
|
|
||||||
vPoint1.y,
|
|
||||||
]
|
|
||||||
|
|
||||||
ridgeEndPoint2 = [
|
this.addWithUpdate(ridgeHelpLine)
|
||||||
vPoint2.x,
|
this.removeWithUpdate(closestLine)
|
||||||
vPoint2.y,
|
this.canvas.renderAll()
|
||||||
vPoint2.x,
|
})
|
||||||
vPoint2.y + ridgeLength2,
|
|
||||||
]
|
|
||||||
|
|
||||||
ridgeHelpLinePoint1 = [
|
// 용마루 끼리 연결
|
||||||
lines2[0].x2,
|
for (let i = 0; i < ridgePoint.length; i = i + 2) {
|
||||||
lines2[0].y2,
|
const currentRidgeEndPoint = ridgePoint[i]
|
||||||
ridgeEndPoint1[2],
|
const nextRidgeEndPoint = ridgePoint[(i + 1) % ridgePoint.length]
|
||||||
ridgeEndPoint1[3],
|
const ridgeConnectLine = new QLine([currentRidgeEndPoint.x, currentRidgeEndPoint.y, nextRidgeEndPoint.x, nextRidgeEndPoint.y], {
|
||||||
]
|
fontSize: this.fontSize,
|
||||||
ridgeHelpLinePoint2 = [
|
stroke: 'green',
|
||||||
lines2[1].x2,
|
strokeWidth: 5,
|
||||||
lines2[1].y2,
|
})
|
||||||
ridgeEndPoint2[2],
|
this.addWithUpdate(ridgeConnectLine)
|
||||||
ridgeEndPoint2[3],
|
this.canvas.renderAll()
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const realLine1 = new QLine(
|
|
||||||
[lines[0].x1, lines[0].y1, vPoint1.x, vPoint1.y],
|
|
||||||
{ fontSize: this.fontSize, stroke: 'blue', strokeWidth: 1 },
|
|
||||||
getRoofHypotenuse(lines[0].length / 2),
|
|
||||||
)
|
|
||||||
|
|
||||||
const realLine2 = new QLine(
|
|
||||||
[lines[0].x2, lines[0].y2, vPoint1.x, vPoint1.y],
|
|
||||||
{ fontSize: this.fontSize, stroke: 'blue', strokeWidth: 1 },
|
|
||||||
getRoofHypotenuse(lines[0].length / 2),
|
|
||||||
)
|
|
||||||
|
|
||||||
const realLine3 = new QLine(
|
|
||||||
[lines[1].x1, lines[1].y1, vPoint2.x, vPoint2.y],
|
|
||||||
{ fontSize: this.fontSize, stroke: 'blue', strokeWidth: 1 },
|
|
||||||
getRoofHypotenuse(lines[1].length / 2),
|
|
||||||
)
|
|
||||||
|
|
||||||
const realLine4 = new QLine(
|
|
||||||
[lines[1].x2, lines[1].y2, vPoint2.x, vPoint2.y],
|
|
||||||
{ fontSize: this.fontSize, stroke: 'blue', strokeWidth: 1 },
|
|
||||||
getRoofHypotenuse(lines[1].length / 2),
|
|
||||||
)
|
|
||||||
|
|
||||||
// 옆으로 누워있는 지붕의 높이 점선
|
|
||||||
const realLine5 = new QLine(
|
|
||||||
[vPoint1.x, vPoint1.y, centerPoint1.x, centerPoint1.y],
|
|
||||||
{
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
stroke: 'blue',
|
|
||||||
strokeWidth: 1,
|
|
||||||
strokeDashArray: [5, 5],
|
|
||||||
},
|
|
||||||
getRoofHeight(lines[0].length / 2, getDegreeByChon(chon)),
|
|
||||||
)
|
|
||||||
|
|
||||||
// 옆으로 누워있는 지붕의 높이 점선
|
|
||||||
const realLine6 = new QLine(
|
|
||||||
[vPoint2.x, vPoint2.y, centerPoint2.x, centerPoint2.y],
|
|
||||||
{
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
stroke: 'blue',
|
|
||||||
strokeWidth: 1,
|
|
||||||
strokeDashArray: [5, 5],
|
|
||||||
},
|
|
||||||
getRoofHeight(lines[1].length / 2, getDegreeByChon(chon)),
|
|
||||||
)
|
|
||||||
|
|
||||||
// 용마루 보조선
|
|
||||||
const ridgeHelpLine1 = new QLine(
|
|
||||||
ridgeHelpLinePoint1,
|
|
||||||
{
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
stroke: 'blue',
|
|
||||||
strokeWidth: 1,
|
|
||||||
},
|
|
||||||
getRoofHypotenuse(lines[0].length / 2),
|
|
||||||
)
|
|
||||||
|
|
||||||
// 용마루 보조선
|
|
||||||
const ridgeHelpLine2 = new QLine(
|
|
||||||
ridgeHelpLinePoint2,
|
|
||||||
{
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
stroke: 'blue',
|
|
||||||
strokeWidth: 1,
|
|
||||||
},
|
|
||||||
getRoofHypotenuse(lines[1].length / 2),
|
|
||||||
)
|
|
||||||
|
|
||||||
// 용마루
|
|
||||||
const ridge1 = new QLine(
|
|
||||||
[vPoint1.x, vPoint1.y, ridgeEndPoint1[2], ridgeEndPoint1[3]],
|
|
||||||
{
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
stroke: 'blue',
|
|
||||||
strokeWidth: 1,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
// 용마루
|
|
||||||
const ridge2 = new QLine(
|
|
||||||
[vPoint2.x, vPoint2.y, ridgeEndPoint2[2], ridgeEndPoint2[3]],
|
|
||||||
{
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
stroke: 'blue',
|
|
||||||
strokeWidth: 1,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
const ridgeEndLine = new QLine(
|
|
||||||
[
|
|
||||||
ridgeEndPoint1[2],
|
|
||||||
ridgeEndPoint1[3],
|
|
||||||
ridgeEndPoint2[2],
|
|
||||||
ridgeEndPoint2[3],
|
|
||||||
],
|
|
||||||
{
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
stroke: 'blue',
|
|
||||||
strokeWidth: 1,
|
|
||||||
},
|
|
||||||
Math.abs(realLine1.length - realLine3.length),
|
|
||||||
)
|
|
||||||
this.helpLines = [
|
|
||||||
realLine1,
|
|
||||||
realLine2,
|
|
||||||
realLine3,
|
|
||||||
realLine4,
|
|
||||||
realLine5,
|
|
||||||
realLine6,
|
|
||||||
ridge1,
|
|
||||||
ridge2,
|
|
||||||
ridgeEndLine,
|
|
||||||
]
|
|
||||||
this.addWithUpdate(realLine1)
|
|
||||||
this.addWithUpdate(realLine2)
|
|
||||||
this.addWithUpdate(realLine3)
|
|
||||||
this.addWithUpdate(realLine4)
|
|
||||||
this.addWithUpdate(realLine5)
|
|
||||||
this.addWithUpdate(realLine6)
|
|
||||||
this.addWithUpdate(ridgeHelpLine1)
|
|
||||||
this.addWithUpdate(ridgeHelpLine2)
|
|
||||||
this.addWithUpdate(ridge1)
|
|
||||||
this.addWithUpdate(ridge2)
|
|
||||||
this.addWithUpdate(ridgeEndLine)
|
|
||||||
|
|
||||||
this.canvas.renderAll()
|
this.canvas.renderAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,9 @@
|
|||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import QRect from '@/components/fabric/QRect'
|
import QRect from '@/components/fabric/QRect'
|
||||||
import QPolygon from '@/components/fabric/QPolygon'
|
import QPolygon from '@/components/fabric/QPolygon'
|
||||||
import {
|
import { getStartIndex, rearrangeArray, findTopTwoIndexesByDistance, getDirection, getCenterPoint } from '@/util/canvas-util'
|
||||||
getStartIndex,
|
|
||||||
rearrangeArray,
|
|
||||||
findTopTwoIndexesByDistance,
|
|
||||||
getDirection,
|
|
||||||
getCenterPoint,
|
|
||||||
} from '@/util/canvas-util'
|
|
||||||
import { useRecoilState, useSetRecoilState } from 'recoil'
|
import { useRecoilState, useSetRecoilState } from 'recoil'
|
||||||
import {
|
import { fontSizeState, roofState, sortedPolygonArray, wallState } from '@/store/canvasAtom'
|
||||||
fontSizeState,
|
|
||||||
roofState,
|
|
||||||
sortedPolygonArray,
|
|
||||||
wallState,
|
|
||||||
} from '@/store/canvasAtom'
|
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
|
||||||
export const Mode = {
|
export const Mode = {
|
||||||
@ -101,8 +90,7 @@ export function useMode() {
|
|||||||
if (isNaN(length) || length === 0) {
|
if (isNaN(length) || length === 0) {
|
||||||
//마지막 추가 된 points 제거합니다.
|
//마지막 추가 된 points 제거합니다.
|
||||||
|
|
||||||
const lastPoint =
|
const lastPoint = historyPoints.current[historyPoints.current.length - 1]
|
||||||
historyPoints.current[historyPoints.current.length - 1]
|
|
||||||
|
|
||||||
canvas?.remove(lastPoint)
|
canvas?.remove(lastPoint)
|
||||||
|
|
||||||
@ -134,12 +122,7 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const line = new QLine(
|
const line = new QLine(
|
||||||
[
|
[points.current[0].left, points.current[0].top, points.current[0].left + scaledVector.x, points.current[0].top + scaledVector.y],
|
||||||
points.current[0].left,
|
|
||||||
points.current[0].top,
|
|
||||||
points.current[0].left + scaledVector.x,
|
|
||||||
points.current[0].top + scaledVector.y,
|
|
||||||
],
|
|
||||||
{
|
{
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
@ -180,27 +163,20 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const pushHistoryLine = (line) => {
|
const pushHistoryLine = (line) => {
|
||||||
if (
|
if (historyLines.current.length > 0 && historyLines.current[historyLines.current.length - 1].direction === line.direction) {
|
||||||
historyLines.current.length > 0 &&
|
|
||||||
historyLines.current[historyLines.current.length - 1].direction ===
|
|
||||||
line.direction
|
|
||||||
) {
|
|
||||||
// 같은 방향의 선이 두 번 연속으로 그려지면 이전 선을 제거하고, 새로운 선과 merge한다.
|
// 같은 방향의 선이 두 번 연속으로 그려지면 이전 선을 제거하고, 새로운 선과 merge한다.
|
||||||
|
|
||||||
const lastLine = historyLines.current.pop()
|
const lastLine = historyLines.current.pop()
|
||||||
canvas?.remove(lastLine)
|
canvas?.remove(lastLine)
|
||||||
|
|
||||||
const mergedLine = new QLine(
|
const mergedLine = new QLine([lastLine.x1, lastLine.y1, line.x2, line.y2], {
|
||||||
[lastLine.x1, lastLine.y1, line.x2, line.y2],
|
stroke: 'black',
|
||||||
{
|
strokeWidth: 2,
|
||||||
stroke: 'black',
|
selectable: false,
|
||||||
strokeWidth: 2,
|
viewLengthText: true,
|
||||||
selectable: false,
|
direction: lastLine.direction,
|
||||||
viewLengthText: true,
|
fontSize: fontSize,
|
||||||
direction: lastLine.direction,
|
})
|
||||||
fontSize: fontSize,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
historyLines.current.push(mergedLine)
|
historyLines.current.push(mergedLine)
|
||||||
canvas?.add(mergedLine)
|
canvas?.add(mergedLine)
|
||||||
} else {
|
} else {
|
||||||
@ -246,9 +222,12 @@ export function useMode() {
|
|||||||
points.current = []
|
points.current = []
|
||||||
historyPoints.current = []
|
historyPoints.current = []
|
||||||
|
|
||||||
handleOuterlinesTest()
|
const roof = handleOuterlinesTest()
|
||||||
const wall = makePolygon()
|
const wall = makePolygon()
|
||||||
|
|
||||||
|
roof.setWall(wall)
|
||||||
setWall(wall)
|
setWall(wall)
|
||||||
|
roof.drawHelpLine()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,9 +439,7 @@ export function useMode() {
|
|||||||
const newOuterlines = []
|
const newOuterlines = []
|
||||||
for (let i = 0; i < historyLines.current.length; i++) {
|
for (let i = 0; i < historyLines.current.length; i++) {
|
||||||
const next = historyLines.current[i + 1]
|
const next = historyLines.current[i + 1]
|
||||||
const prev =
|
const prev = historyLines.current[i - 1] ?? historyLines.current[historyLines.current.length - 1]
|
||||||
historyLines.current[i - 1] ??
|
|
||||||
historyLines.current[historyLines.current.length - 1]
|
|
||||||
if (next) {
|
if (next) {
|
||||||
if (next.direction === 'right') {
|
if (next.direction === 'right') {
|
||||||
// 다름 라인이 오른쪽으로 이동
|
// 다름 라인이 오른쪽으로 이동
|
||||||
@ -797,9 +774,7 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 평균 법선 벡터를 단위 벡터로 정규화
|
// 평균 법선 벡터를 단위 벡터로 정규화
|
||||||
var lengthNormal = Math.sqrt(
|
var lengthNormal = Math.sqrt(averageNormal.x * averageNormal.x + averageNormal.y * averageNormal.y)
|
||||||
averageNormal.x * averageNormal.x + averageNormal.y * averageNormal.y,
|
|
||||||
)
|
|
||||||
var unitNormal = {
|
var unitNormal = {
|
||||||
x: averageNormal.x / lengthNormal,
|
x: averageNormal.x / lengthNormal,
|
||||||
y: averageNormal.y / lengthNormal,
|
y: averageNormal.y / lengthNormal,
|
||||||
@ -816,7 +791,8 @@ export function useMode() {
|
|||||||
|
|
||||||
const roof = makePolygon(offsetPoints)
|
const roof = makePolygon(offsetPoints)
|
||||||
setRoof(roof)
|
setRoof(roof)
|
||||||
roof.drawHelpLine()
|
|
||||||
|
return roof
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -867,9 +843,7 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 평균 법선 벡터를 단위 벡터로 정규화
|
// 평균 법선 벡터를 단위 벡터로 정규화
|
||||||
const lengthNormal = Math.sqrt(
|
const lengthNormal = Math.sqrt(averageNormal.x * averageNormal.x + averageNormal.y * averageNormal.y)
|
||||||
averageNormal.x * averageNormal.x + averageNormal.y * averageNormal.y,
|
|
||||||
)
|
|
||||||
const unitNormal = {
|
const unitNormal = {
|
||||||
x: averageNormal.x / lengthNormal,
|
x: averageNormal.x / lengthNormal,
|
||||||
y: averageNormal.y / lengthNormal,
|
y: averageNormal.y / lengthNormal,
|
||||||
@ -885,6 +859,7 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const roof = makePolygon(offsetPoints)
|
const roof = makePolygon(offsetPoints)
|
||||||
|
roof.setWall(polygon)
|
||||||
setRoof(roof)
|
setRoof(roof)
|
||||||
roof.drawHelpLine()
|
roof.drawHelpLine()
|
||||||
}
|
}
|
||||||
@ -927,70 +902,532 @@ export function useMode() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 템플릿 B 적용
|
* 템플릿 B 적용
|
||||||
* 1. 모드 체인지
|
|
||||||
* 2. 외벽선 그리기 마무리
|
|
||||||
*/
|
*/
|
||||||
const applyTemplateB = () => {
|
const applyTemplateB = () => {
|
||||||
changeMode(canvas, Mode.EDIT)
|
changeMode(canvas, Mode.EDIT)
|
||||||
const polygon = drawWallPolygon()
|
const polygon = drawWallPolygon()
|
||||||
handleOuterLineTemplateB(polygon)
|
const params = {
|
||||||
|
eaves: 50,
|
||||||
|
edge: 20,
|
||||||
|
polygon,
|
||||||
|
}
|
||||||
|
handleInnerLineColor(polygon)
|
||||||
|
// handleOuterLineTemplateB(params)
|
||||||
|
console.log(polygon.lines.length)
|
||||||
|
if (polygon.lines.length === 4) {
|
||||||
|
handleTemplateBRect(params)
|
||||||
|
} else if (polygon.length === 6) {
|
||||||
|
handleTemplateB(params)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleOuterLineTemplateB = (polygon) => {
|
/**
|
||||||
|
* 4각형일때 계산 로직
|
||||||
|
* @param {obj} params
|
||||||
|
*/
|
||||||
|
const handleTemplateBRect = (params) => {
|
||||||
|
const { eaves, edge, polygon } = params
|
||||||
|
const centerLinePoint = {}
|
||||||
|
const centerDashLinePoint = {}
|
||||||
|
|
||||||
|
const qlineOpt = {
|
||||||
|
stroke: 'blue',
|
||||||
|
strokeWidth: 2,
|
||||||
|
selectable: false,
|
||||||
|
fontSize: fontSize,
|
||||||
|
}
|
||||||
|
const qlineOptDash = {
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 2,
|
||||||
|
strokeDashArray: [5, 5],
|
||||||
|
selectable: false,
|
||||||
|
fontSize: fontSize,
|
||||||
|
}
|
||||||
|
const qlineOptDashWithoutLength = {
|
||||||
|
...qlineOptDash,
|
||||||
|
isActiveLengthText: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
polygon.lines.forEach((line, index) => {
|
||||||
|
let outline
|
||||||
|
if (index === 0) {
|
||||||
|
outline = new QLine([line.x1 - edge, line.y1 - eaves, line.x2 - edge, line.y2 + eaves], qlineOpt)
|
||||||
|
const centeredPoint = getCenterPoint(line.y1, line.y2)
|
||||||
|
centerLinePoint.x1 = line.x1 - edge
|
||||||
|
centerLinePoint.y1 = centeredPoint
|
||||||
|
centerLinePoint.y2 = centeredPoint
|
||||||
|
centerDashLinePoint.y1 = line.y1 - eaves
|
||||||
|
centerDashLinePoint.y2 = line.y2 + eaves
|
||||||
|
} else if (index === 1) {
|
||||||
|
outline = new QLine([line.x1 - edge, line.y1 + eaves, line.x2 + edge, line.y2 + eaves], qlineOpt)
|
||||||
|
const centeredPoint = getCenterPoint(line.x1, line.x2)
|
||||||
|
centerLinePoint.x2 = line.x2 + edge
|
||||||
|
centerDashLinePoint.x1 = centeredPoint
|
||||||
|
centerDashLinePoint.x2 = centeredPoint
|
||||||
|
} else if (index === 2) {
|
||||||
|
outline = new QLine([line.x1 + edge, line.y1 + eaves, line.x2 + edge, line.y2 - eaves], qlineOpt)
|
||||||
|
} else if (index === 3) {
|
||||||
|
outline = new QLine([line.x1 + edge, line.y1 - eaves, line.x2 - edge, line.y2 - eaves], qlineOpt)
|
||||||
|
}
|
||||||
|
canvas.add(outline)
|
||||||
|
})
|
||||||
|
const centerLine = new QLine([centerLinePoint.x1, centerLinePoint.y1, centerLinePoint.x2, centerLinePoint.y2], qlineOpt)
|
||||||
|
canvas.add(centerLine)
|
||||||
|
const centerDashLine1 = new QLine(
|
||||||
|
[centerDashLinePoint.x1, centerDashLinePoint.y1, centerDashLinePoint.x2, getCenterPoint(centerDashLinePoint.y1, centerDashLinePoint.y2)],
|
||||||
|
qlineOptDashWithoutLength,
|
||||||
|
)
|
||||||
|
canvas.add(centerDashLine1)
|
||||||
|
const centerDashLine2 = new QLine(
|
||||||
|
[centerDashLinePoint.x1, getCenterPoint(centerDashLinePoint.y1, centerDashLinePoint.y2), centerDashLinePoint.x2, centerDashLinePoint.y2],
|
||||||
|
qlineOptDashWithoutLength,
|
||||||
|
)
|
||||||
|
canvas.add(centerDashLine2)
|
||||||
|
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 6각형일때 계산 로직
|
||||||
|
* @param {obj} params
|
||||||
|
*/
|
||||||
|
const handleTemplateB = (params) => {
|
||||||
|
const { eaves, edge, polygon } = params
|
||||||
|
// 가장 긴 라인이 첫번째일때
|
||||||
|
let shapeType = 0
|
||||||
|
console.log(polygon)
|
||||||
|
const odd = polygon.lines.filter((line, index) => index % 2 === 0)
|
||||||
|
const even = polygon.lines.filter((line, index) => index % 2 !== 0)
|
||||||
|
const rerangeOdd = chgLineDirectionVertical(odd)
|
||||||
|
const rerangeEven = chgLineDirectionHorizontal(even)
|
||||||
|
// 가장 긴 라인이 첫번째인지 판단
|
||||||
|
chkLengthIndex({ arr: odd, type: 'L' }) !== 0 ? (shapeType = 1) : null
|
||||||
|
// 가장 짧은 라인의 인덱스 반환
|
||||||
|
const shortIndex = chkLengthIndex({ arr: odd, type: 'S' })
|
||||||
|
|
||||||
|
const centralLinePoint = {
|
||||||
|
x1: 0,
|
||||||
|
y1: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 0,
|
||||||
|
}
|
||||||
|
const centralSubLinePoint = {
|
||||||
|
x1: 0,
|
||||||
|
y1: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 0,
|
||||||
|
}
|
||||||
|
const centralDashLinePoint = {
|
||||||
|
x1: 0,
|
||||||
|
y1: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 0,
|
||||||
|
}
|
||||||
|
const centralSubDashLinePoint = {
|
||||||
|
x1: 0,
|
||||||
|
y1: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 0,
|
||||||
|
}
|
||||||
|
const qlineOpt = {
|
||||||
|
stroke: 'blue',
|
||||||
|
strokeWidth: 2,
|
||||||
|
selectable: false,
|
||||||
|
fontSize: fontSize,
|
||||||
|
}
|
||||||
|
const qlineOptDash = {
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 2,
|
||||||
|
strokeDashArray: [5, 5],
|
||||||
|
selectable: false,
|
||||||
|
fontSize: fontSize,
|
||||||
|
}
|
||||||
|
|
||||||
|
rerangeOdd.forEach((line, index) => {
|
||||||
|
const centeredPoint = getCenterPoint(line.y1, line.y2)
|
||||||
|
let points1 = []
|
||||||
|
let points2 = []
|
||||||
|
if (polygon.shape === 2 || polygon.shape === 3) {
|
||||||
|
if (index === 0) {
|
||||||
|
points1 = [line.x1 - edge, line.y1 - eaves, line.x1 - edge, centeredPoint]
|
||||||
|
points2 = [line.x2 - edge, centeredPoint, line.x2 - edge, line.y2 + eaves]
|
||||||
|
centralLinePoint.x1 = line.x1 - edge
|
||||||
|
centralLinePoint.y1 = centeredPoint
|
||||||
|
centralLinePoint.y2 = centeredPoint
|
||||||
|
centralDashLinePoint.y1 = line.y1 - eaves
|
||||||
|
centralDashLinePoint.y2 = line.y2 + eaves
|
||||||
|
} else if (index === 1) {
|
||||||
|
if (polygon.shape === 2) {
|
||||||
|
points1 = [line.x1 + edge, line.y1 - eaves, line.x1 + edge, centeredPoint]
|
||||||
|
points2 = [line.x1 + edge, centeredPoint, line.x2 + edge, line.y2 + eaves]
|
||||||
|
centralSubLinePoint.x2 = line.x1 + edge
|
||||||
|
centralSubLinePoint.y2 = centeredPoint
|
||||||
|
} else {
|
||||||
|
points1 = [line.x1 + edge, getCenterPoint(rerangeOdd[2].y1, rerangeOdd[2].y2), line.x2 + edge, line.y2 + eaves]
|
||||||
|
points2 = [line.x1, getCenterPoint(rerangeOdd[2].y1, rerangeOdd[2].y2), line.x1, line.y1 + eaves]
|
||||||
|
centralLinePoint.x2 = line.x1 + edge
|
||||||
|
centralSubLinePoint.y1 = getCenterPoint(rerangeOdd[2].y1, rerangeOdd[2].y2)
|
||||||
|
centralSubLinePoint.y2 = getCenterPoint(rerangeOdd[2].y1, rerangeOdd[2].y2)
|
||||||
|
}
|
||||||
|
} else if (index === 2) {
|
||||||
|
if (polygon.shape === 2) {
|
||||||
|
points1 = [line.x1 + edge, line.y1 - eaves, line.x2 + edge, centralSubLinePoint.y2]
|
||||||
|
points2 = [line.x2, line.y2 - eaves, line.x2, centralSubLinePoint.y2]
|
||||||
|
} else {
|
||||||
|
points1 = [line.x1 + edge, line.y1 - eaves, line.x2 + edge, centeredPoint]
|
||||||
|
points2 = [line.x2 + edge, centeredPoint, line.x2 + edge, line.y2 + eaves]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (index === 0) {
|
||||||
|
points1 = [line.x1 - edge, line.y1 - eaves, line.x2 - edge, line.y2 + eaves]
|
||||||
|
centralSubLinePoint.x1 = line.x1 - edge
|
||||||
|
centralSubLinePoint.y1 = getCenterPoint(line.y1, line.y2)
|
||||||
|
centralSubLinePoint.y2 = getCenterPoint(line.y1, line.y2)
|
||||||
|
} else if (index === 1) {
|
||||||
|
if (polygon.shape === 1) {
|
||||||
|
points1 = [line.x1 - edge, centralSubLinePoint.y1, line.x2 - edge, line.y2 + eaves]
|
||||||
|
points2 = [line.x1, centralSubLinePoint.y1, line.x1, line.y1 + eaves]
|
||||||
|
centralLinePoint.x1 = line.x1 - edge
|
||||||
|
centralSubLinePoint.x2 = line.x2
|
||||||
|
} else {
|
||||||
|
points1 = [line.x1 + edge, line.y1 - eaves, line.x2 + edge, centeredPoint]
|
||||||
|
points2 = [line.x2 + edge, centeredPoint, line.x2 + edge, line.y2 + eaves]
|
||||||
|
centralLinePoint.x2 = line.x1 + edge
|
||||||
|
centralLinePoint.y1 = centeredPoint
|
||||||
|
centralLinePoint.y2 = centeredPoint
|
||||||
|
centralDashLinePoint.y1 = line.y1 - eaves
|
||||||
|
centralDashLinePoint.y2 = line.y2 + eaves
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (polygon.shape === 1) {
|
||||||
|
points1 = [line.x1 + edge, line.y1 - eaves, line.x1 + edge, centeredPoint]
|
||||||
|
points2 = [line.x2 + edge, centeredPoint, line.x2 + edge, line.y2 + eaves]
|
||||||
|
centralLinePoint.x2 = line.x1 + edge
|
||||||
|
centralLinePoint.y1 = centeredPoint
|
||||||
|
centralLinePoint.y2 = centeredPoint
|
||||||
|
centralDashLinePoint.y1 = line.y1 - eaves
|
||||||
|
centralDashLinePoint.y2 = line.y2 + eaves
|
||||||
|
} else {
|
||||||
|
points1 = [line.x1 - edge, line.y1 - eaves, line.x2 - edge, centralSubLinePoint.y1]
|
||||||
|
points2 = [line.x2, line.y2 - eaves, line.x2, centralSubLinePoint.y2]
|
||||||
|
centralLinePoint.x1 = line.x1 - edge
|
||||||
|
centralSubLinePoint.x2 = line.x2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (points1.length > 0) {
|
||||||
|
const subLine1 = new QLine(points1, qlineOpt)
|
||||||
|
canvas.add(subLine1)
|
||||||
|
}
|
||||||
|
if (points2.length > 0) {
|
||||||
|
const subLine2 = new QLine(points2, qlineOpt)
|
||||||
|
canvas.add(subLine2)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
rerangeEven.forEach((line, index) => {
|
||||||
|
let points = []
|
||||||
|
if (polygon.shape === 2 || polygon.shape === 3) {
|
||||||
|
if (index === 0) {
|
||||||
|
points = [line.x1 - edge, line.y1 + eaves, line.x2 + edge, line.y2 + eaves]
|
||||||
|
if (polygon.shape === 3) {
|
||||||
|
centralDashLinePoint.x1 = getCenterPoint(line.x1, line.x2)
|
||||||
|
centralDashLinePoint.x2 = getCenterPoint(line.x1, line.x2)
|
||||||
|
}
|
||||||
|
} else if (index === 2) {
|
||||||
|
points = [line.x1 - edge, line.y1 - eaves, line.x2 + edge, line.y2 - eaves]
|
||||||
|
if (polygon.shape === 2) {
|
||||||
|
centralDashLinePoint.x1 = getCenterPoint(line.x1, line.x2)
|
||||||
|
centralDashLinePoint.x2 = getCenterPoint(line.x1, line.x2)
|
||||||
|
centralLinePoint.x2 = line.x2 + edge
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (polygon.shape === 2) {
|
||||||
|
const subLines = [
|
||||||
|
[line.x1, line.y1 - eaves, line.x2 + edge, line.y2 - eaves],
|
||||||
|
[line.x1, centralSubLinePoint.y2, centralSubLinePoint.x2, centralSubLinePoint.y2],
|
||||||
|
]
|
||||||
|
subLines.forEach((sLine, index) => {
|
||||||
|
const subLine = new QLine(sLine, qlineOpt)
|
||||||
|
canvas.add(subLine)
|
||||||
|
})
|
||||||
|
centralSubDashLinePoint.x1 = getCenterPoint(line.x1, line.x2 + edge)
|
||||||
|
centralSubDashLinePoint.x2 = getCenterPoint(line.x1, line.x2 + edge)
|
||||||
|
centralSubDashLinePoint.y1 = line.y1 - eaves
|
||||||
|
centralSubDashLinePoint.y2 = centralSubLinePoint.y2
|
||||||
|
} else {
|
||||||
|
const subLines = [
|
||||||
|
[line.x1, line.y1 + eaves, line.x2 + edge, line.y2 + eaves],
|
||||||
|
[line.x1, centralSubLinePoint.y1, line.x2 + edge, centralSubLinePoint.y2],
|
||||||
|
]
|
||||||
|
subLines.forEach((sLine, index) => {
|
||||||
|
const subLine = new QLine(sLine, qlineOpt)
|
||||||
|
canvas.add(subLine)
|
||||||
|
})
|
||||||
|
centralSubDashLinePoint.x1 = getCenterPoint(line.x1, line.x2 + edge)
|
||||||
|
centralSubDashLinePoint.x2 = getCenterPoint(line.x1, line.x2 + edge)
|
||||||
|
centralSubDashLinePoint.y1 = centralSubLinePoint.y1
|
||||||
|
centralSubDashLinePoint.y2 = line.y2 + eaves
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (index === 0) {
|
||||||
|
if (polygon.shape === 1) {
|
||||||
|
const subLines = [
|
||||||
|
[centralSubLinePoint.x1, centralSubLinePoint.y1, centralSubLinePoint.x2, centralSubLinePoint.y2],
|
||||||
|
[line.x1 - edge, line.y1 + eaves, line.x2, line.y1 + eaves],
|
||||||
|
]
|
||||||
|
subLines.forEach((sLine, index) => {
|
||||||
|
const subLine = new QLine(sLine, qlineOpt)
|
||||||
|
canvas.add(subLine)
|
||||||
|
})
|
||||||
|
centralSubDashLinePoint.x1 = getCenterPoint(line.x1 - edge, line.x2)
|
||||||
|
centralSubDashLinePoint.x2 = getCenterPoint(line.x1 - edge, line.x2)
|
||||||
|
centralSubDashLinePoint.y1 = centralSubLinePoint.y1
|
||||||
|
centralSubDashLinePoint.y2 = line.y2 + eaves
|
||||||
|
} else {
|
||||||
|
points = [line.x1 - edge, line.y1 + eaves, line.x2 + edge, line.y2 + eaves]
|
||||||
|
}
|
||||||
|
} else if (index === 1) {
|
||||||
|
if (polygon.shape === 1) {
|
||||||
|
points = [line.x1 - edge, line.y1 + eaves, line.x2 + edge, line.y2 + eaves]
|
||||||
|
centralDashLinePoint.x1 = getCenterPoint(line.x1, line.x2)
|
||||||
|
centralDashLinePoint.x2 = getCenterPoint(line.x1, line.x2)
|
||||||
|
} else {
|
||||||
|
points = [line.x1 - edge, line.y1 - eaves, line.x2 + edge, line.y2 - eaves]
|
||||||
|
centralDashLinePoint.x1 = getCenterPoint(line.x1, line.x2)
|
||||||
|
centralDashLinePoint.x2 = getCenterPoint(line.x1, line.x2)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (polygon.shape === 1) {
|
||||||
|
points = [line.x1 - edge, line.y1 - eaves, line.x2 + edge, line.y2 - eaves]
|
||||||
|
} else {
|
||||||
|
const subLines = [
|
||||||
|
[centralSubLinePoint.x1, centralSubLinePoint.y1, centralSubLinePoint.x2, centralSubLinePoint.y2],
|
||||||
|
[line.x1 - edge, line.y1 - eaves, line.x2, line.y1 - eaves],
|
||||||
|
]
|
||||||
|
subLines.forEach((sLine, index) => {
|
||||||
|
const subLine = new QLine(sLine, qlineOpt)
|
||||||
|
canvas.add(subLine)
|
||||||
|
})
|
||||||
|
centralSubDashLinePoint.x1 = getCenterPoint(line.x1 - edge, line.x2)
|
||||||
|
centralSubDashLinePoint.x2 = getCenterPoint(line.x1 - edge, line.x2)
|
||||||
|
centralSubDashLinePoint.y1 = line.y1 - eaves
|
||||||
|
centralSubDashLinePoint.y2 = centralSubLinePoint.y2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (points.length > 0) {
|
||||||
|
const subLine = new QLine(points, qlineOpt)
|
||||||
|
canvas.add(subLine)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const centralLine = new QLine([centralLinePoint.x1, centralLinePoint.y1, centralLinePoint.x2, centralLinePoint.y2], qlineOpt)
|
||||||
|
canvas.add(centralLine)
|
||||||
|
const centralDashLine1 = new QLine([centralDashLinePoint.x1, centralDashLinePoint.y1, centralDashLinePoint.x1, centralLinePoint.y2], qlineOptDash)
|
||||||
|
canvas.add(centralDashLine1)
|
||||||
|
const centralDashLine2 = new QLine([centralDashLine1.x2, centralDashLine1.y2, centralDashLinePoint.x2, centralDashLinePoint.y2], qlineOptDash)
|
||||||
|
canvas.add(centralDashLine2)
|
||||||
|
const centralSubDashLine = new QLine(
|
||||||
|
[centralSubDashLinePoint.x1, centralSubDashLinePoint.y1, centralSubDashLinePoint.x2, centralSubDashLinePoint.y2],
|
||||||
|
qlineOptDash,
|
||||||
|
)
|
||||||
|
canvas.add(centralSubDashLine)
|
||||||
|
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 세로 방샹 라인의 좌표 순서를 위에서 아래로 변경
|
||||||
|
* @param {array} arr
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const chgLineDirectionVertical = (arr) => {
|
||||||
|
const newArr = arr.map((line, index) => {
|
||||||
|
if (line.direction !== 'bottom') {
|
||||||
|
const newPoint = { x1: line.x2, y1: line.y2, x2: line.x1, y2: line.y1 }
|
||||||
|
return newPoint
|
||||||
|
} else {
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return newArr
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 가로 방향 라인의 좌표 순서를 왼쪽에서 오른쪽으로 변경
|
||||||
|
* @param {array} arr
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const chgLineDirectionHorizontal = (arr) => {
|
||||||
|
const newArr = arr.map((line, index) => {
|
||||||
|
if (line.direction !== 'right') {
|
||||||
|
const newPoint = { x1: line.x2, y1: line.y2, x2: line.x1, y2: line.y1 }
|
||||||
|
return newPoint
|
||||||
|
} else {
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return newArr
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 라인 배열 중 가장 긴 라인의 인덱스를 반환합니다.
|
||||||
|
*/
|
||||||
|
const chkLengthIndex = (params) => {
|
||||||
|
const { arr, type } = params
|
||||||
|
let maxIndex = 0
|
||||||
|
for (let i = 1; i < arr.length; i++) {
|
||||||
|
if (type === 'L') {
|
||||||
|
if (arr[maxIndex].length < arr[i].length) {
|
||||||
|
maxIndex = i
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (arr[maxIndex].length > arr[i].length) {
|
||||||
|
maxIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 외벽선 색깔을 변경
|
||||||
|
* @param {array} polygon
|
||||||
|
*/
|
||||||
|
const handleInnerLineColor = (polygon) => {
|
||||||
|
polygon.lines.forEach((line, index) => {
|
||||||
|
if (index % 2 === 0) {
|
||||||
|
line.set('stroke', 'rgb(0, 220, 221)')
|
||||||
|
} else {
|
||||||
|
line.set('stroke', 'rgb(0, 224, 61)')
|
||||||
|
}
|
||||||
|
|
||||||
|
const overLine = new QLine([line.x1, line.y1, line.x2, line.y2], {
|
||||||
|
stroke: line.stroke,
|
||||||
|
strokeWidth: 2,
|
||||||
|
selectable: false,
|
||||||
|
fontSize: fontSize,
|
||||||
|
isActiveLengthText: false,
|
||||||
|
})
|
||||||
|
canvas.add(overLine)
|
||||||
|
})
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleOuterLineTemplateB = (params) => {
|
||||||
|
const { eaves, edge, polygon } = params
|
||||||
polygon.points.forEach((point, index) => {
|
polygon.points.forEach((point, index) => {
|
||||||
let x2 =
|
let x2 = index === polygon.points.length - 1 ? polygon.points[0].x : polygon.points[index + 1].x
|
||||||
index === polygon.points.length - 1
|
let y2 = index === polygon.points.length - 1 ? polygon.points[0].y : polygon.points[index + 1].y
|
||||||
? polygon.points[0].x
|
|
||||||
: polygon.points[index + 1].x
|
|
||||||
let y2 =
|
|
||||||
index === polygon.points.length - 1
|
|
||||||
? polygon.points[0].y
|
|
||||||
: polygon.points[index + 1].y
|
|
||||||
|
|
||||||
let x1 = point.x
|
let x1 = point.x
|
||||||
let y1 = point.y
|
let y1 = point.y
|
||||||
if (index % 2 === 0) {
|
if (index % 2 === 0) {
|
||||||
if (polygon.lines[index].direction === 'bottom') {
|
if (polygon.lines[index].direction === 'bottom') {
|
||||||
y1 = y1 - 50
|
y1 = y1 - eaves
|
||||||
y2 = y2 + 50
|
y2 = y2 + eaves
|
||||||
x1 = x1 - 20
|
x1 = x1 - edge
|
||||||
x2 = x2 - 20
|
x2 = x2 - edge
|
||||||
} else {
|
} else {
|
||||||
y1 = y1 + 50
|
y1 = y1 + eaves
|
||||||
y2 = y2 - 50
|
y2 = y2 - eaves
|
||||||
x1 = x1 + 20
|
x1 = x1 + edge
|
||||||
x2 = x2 + 20
|
x2 = x2 + edge
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (polygon.lines[index].direction === 'right') {
|
if (polygon.lines[index].direction === 'right') {
|
||||||
x1 = x1 - 20
|
x1 = x1 - edge
|
||||||
x2 = x2 + 20
|
x2 = x2 + edge
|
||||||
y1 = y1 + 50
|
y1 = y1 + eaves
|
||||||
y2 = y2 + 50
|
y2 = y2 + eaves
|
||||||
} else {
|
} else {
|
||||||
x1 = x1 + 20
|
x1 = x1 + edge
|
||||||
x2 = x2 - 20
|
x2 = x2 - edge
|
||||||
y1 = y1 - 50
|
y1 = y1 - eaves
|
||||||
y2 = y2 - 50
|
y2 = y2 - eaves
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (polygon.shape) {
|
switch (polygon.shape) {
|
||||||
case 1:
|
case 1:
|
||||||
break
|
|
||||||
case 2:
|
|
||||||
const centerPoint =
|
|
||||||
polygon.points[3].y +
|
|
||||||
(polygon.points[2].y - polygon.points[3].y) / 2
|
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
const subLine = new QLine(
|
const subLine = new QLine(
|
||||||
[
|
[
|
||||||
point.x - 20,
|
point.x - edge,
|
||||||
polygon.points[0].y +
|
polygon.points[0].y + (polygon.points[1].y - polygon.points[0].y) / 2,
|
||||||
(polygon.points[1].y - polygon.points[0].y) / 2,
|
polygon.points[2].x,
|
||||||
polygon.points[5].x + 20,
|
polygon.points[0].y + (polygon.points[1].y - polygon.points[0].y) / 2,
|
||||||
polygon.points[0].y +
|
],
|
||||||
(polygon.points[1].y - polygon.points[0].y) / 2,
|
{
|
||||||
|
stroke: 'blue',
|
||||||
|
strokeWidth: 2,
|
||||||
|
selectable: false,
|
||||||
|
fontSize: fontSize,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
canvas.add(subLine)
|
||||||
|
}
|
||||||
|
if (index === 1) {
|
||||||
|
x2 = x2 - edge
|
||||||
|
const subLine = new QLine([x2, y2, x2, polygon.points[0].y + (polygon.points[1].y - polygon.points[0].y) / 2], {
|
||||||
|
stroke: 'blue',
|
||||||
|
strokeWidth: 2,
|
||||||
|
selectable: false,
|
||||||
|
fontSize: fontSize,
|
||||||
|
})
|
||||||
|
canvas.add(subLine)
|
||||||
|
}
|
||||||
|
if (index === 2) {
|
||||||
|
y1 = point.y - (polygon.points[1].y - polygon.points[0].y) / 2
|
||||||
|
const centeredPoint = getCenterPoint(polygon.points[1].x, point.x)
|
||||||
|
const subLine = new QLine(
|
||||||
|
[centeredPoint, point.y + eaves, centeredPoint, polygon.points[0].y + (polygon.points[1].y - polygon.points[0].y) / 2],
|
||||||
|
{
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 2,
|
||||||
|
strokeDashArray: [5, 5],
|
||||||
|
selectable: false,
|
||||||
|
fontSize: fontSize,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
canvas.add(subLine)
|
||||||
|
}
|
||||||
|
if (index === 3) {
|
||||||
|
const centeredPoint = getCenterPoint(point.x, polygon.points[4].x)
|
||||||
|
const subLine = new QLine([centeredPoint, point.y + eaves, centeredPoint, polygon.points[5].y - eaves], {
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 2,
|
||||||
|
strokeDashArray: [5, 5],
|
||||||
|
selectable: false,
|
||||||
|
fontSize: fontSize,
|
||||||
|
})
|
||||||
|
canvas.add(subLine)
|
||||||
|
}
|
||||||
|
if (index === 5) {
|
||||||
|
const centeredPoint = getCenterPoint(point.y, polygon.points[4].y)
|
||||||
|
const subLine = new QLine([point.x + edge, centeredPoint, polygon.points[2].x - edge, centeredPoint], {
|
||||||
|
stroke: 'blue',
|
||||||
|
strokeWidth: 2,
|
||||||
|
selectable: false,
|
||||||
|
fontSize: fontSize,
|
||||||
|
})
|
||||||
|
canvas.add(subLine)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
const centerPoint = polygon.points[3].y + (polygon.points[2].y - polygon.points[3].y) / 2
|
||||||
|
if (index === 0) {
|
||||||
|
const subLine = new QLine(
|
||||||
|
[
|
||||||
|
point.x - egde,
|
||||||
|
polygon.points[0].y + (polygon.points[1].y - polygon.points[0].y) / 2,
|
||||||
|
polygon.points[5].x + egde,
|
||||||
|
polygon.points[0].y + (polygon.points[1].y - polygon.points[0].y) / 2,
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
stroke: 'blue',
|
stroke: 'blue',
|
||||||
@ -1002,7 +1439,7 @@ export function useMode() {
|
|||||||
canvas.add(subLine)
|
canvas.add(subLine)
|
||||||
}
|
}
|
||||||
if (index === 3) {
|
if (index === 3) {
|
||||||
x2 = x2 + 20
|
x2 = x2 + egde
|
||||||
|
|
||||||
const subLine = new QLine([x2, y2, x2, centerPoint], {
|
const subLine = new QLine([x2, y2, x2, centerPoint], {
|
||||||
stroke: 'blue',
|
stroke: 'blue',
|
||||||
@ -1013,26 +1450,20 @@ export function useMode() {
|
|||||||
canvas.add(subLine)
|
canvas.add(subLine)
|
||||||
}
|
}
|
||||||
if (index === 4) {
|
if (index === 4) {
|
||||||
y1 =
|
y1 = point.y + (polygon.points[index - 2].y - polygon.points[index - 1].y) / 2
|
||||||
point.y +
|
|
||||||
(polygon.points[index - 2].y - polygon.points[index - 1].y) / 2
|
|
||||||
|
|
||||||
const subLine = new QLine(
|
const subLine = new QLine([point.x, centerPoint, polygon.points[2].x + 20, centerPoint], {
|
||||||
[point.x, centerPoint, polygon.points[2].x + 20, centerPoint],
|
stroke: 'blue',
|
||||||
{
|
strokeWidth: 2,
|
||||||
stroke: 'blue',
|
selectable: false,
|
||||||
strokeWidth: 2,
|
fontSize: fontSize,
|
||||||
selectable: false,
|
})
|
||||||
fontSize: fontSize,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
canvas.add(subLine)
|
|
||||||
|
|
||||||
const subVerticalLine = new QLine(
|
const subVerticalLine = new QLine(
|
||||||
[
|
[
|
||||||
getCenterPoint(point.x, polygon.points[2].x + 20),
|
getCenterPoint(point.x, polygon.points[2].x + egde),
|
||||||
polygon.points[3].y - 50,
|
polygon.points[3].y - eaves,
|
||||||
getCenterPoint(point.x, polygon.points[2].x + 20),
|
getCenterPoint(point.x, polygon.points[2].x + egde),
|
||||||
centerPoint,
|
centerPoint,
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
@ -1047,25 +1478,14 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (index === 5) {
|
if (index === 5) {
|
||||||
const centeredPoint = getCenterPoint(
|
const centeredPoint = getCenterPoint(polygon.points[0].x, polygon.points[5].x)
|
||||||
polygon.points[0].x,
|
const verticalSubLine = new QLine([centeredPoint, polygon.points[0].y - eaves, centeredPoint, polygon.points[1].y + eaves], {
|
||||||
polygon.points[5].x,
|
stroke: 'black',
|
||||||
)
|
strokeWidth: 2,
|
||||||
const verticalSubLine = new QLine(
|
strokeDashArray: [5, 5],
|
||||||
[
|
selectable: false,
|
||||||
centeredPoint,
|
fontSize: fontSize,
|
||||||
polygon.points[0].y - 50,
|
})
|
||||||
centeredPoint,
|
|
||||||
polygon.points[1].y + 50,
|
|
||||||
],
|
|
||||||
{
|
|
||||||
stroke: 'black',
|
|
||||||
strokeWidth: 2,
|
|
||||||
strokeDashArray: [5, 5],
|
|
||||||
selectable: false,
|
|
||||||
fontSize: fontSize,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
canvas.add(verticalSubLine)
|
canvas.add(verticalSubLine)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -352,6 +352,18 @@ export function calculateIntersection(line1, line2) {
|
|||||||
return { x: intersectX, y: intersectY }
|
return { x: intersectX, y: intersectY }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findOrthogonalPoint(x1, y1, x2, y2, x3, y3, x4, y4) {
|
||||||
|
// Calculate the intersection point of two lines
|
||||||
|
const intersectionX =
|
||||||
|
((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) /
|
||||||
|
((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
|
||||||
|
const intersectionY =
|
||||||
|
((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) /
|
||||||
|
((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
|
||||||
|
|
||||||
|
return { x: intersectionX, y: intersectionY }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* points배열을 입력받아 반시계방향으로 정렬된 points를 반환합니다.
|
* points배열을 입력받아 반시계방향으로 정렬된 points를 반환합니다.
|
||||||
* @param points
|
* @param points
|
||||||
@ -417,3 +429,61 @@ export const sortedPoints = (points) => {
|
|||||||
|
|
||||||
return resultPoints
|
return resultPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* point가 선 위에 있는지 확인
|
||||||
|
* @param line
|
||||||
|
* @param point
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
// 직선의 방정식.
|
||||||
|
// 방정식은 ax + by + c = 0이며, 점의 좌표를 대입하여 계산된 값은 직선과 점 사이의 관계를 나타낸다.
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 점과 가까운 line 찾기
|
||||||
|
* @param point
|
||||||
|
* @param lines {Array}
|
||||||
|
* @returns {null}
|
||||||
|
*/
|
||||||
|
export function findClosestLineToPoint(point, lines) {
|
||||||
|
let closestLine = null
|
||||||
|
let closestDistance = Infinity
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
const distance = calculateDistance(point, line)
|
||||||
|
|
||||||
|
if (distance < closestDistance) {
|
||||||
|
closestDistance = distance
|
||||||
|
closestLine = line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closestLine
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 점과 직선사이의 최단 거리
|
||||||
|
* @param point
|
||||||
|
* @param line
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function calculateDistance(point, line) {
|
||||||
|
const x1 = line.x1
|
||||||
|
const y1 = line.y1
|
||||||
|
const x2 = line.x2
|
||||||
|
const y2 = line.y2
|
||||||
|
const x0 = point.x
|
||||||
|
const y0 = point.y
|
||||||
|
|
||||||
|
const numerator = Math.abs(
|
||||||
|
(y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1,
|
||||||
|
)
|
||||||
|
const denominator = Math.sqrt(Math.pow(y2 - y1, 2) + Math.pow(x2 - x1, 2))
|
||||||
|
return numerator / denominator
|
||||||
|
}
|
||||||
|
|||||||
2
startscript.js
Normal file
2
startscript.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var exec = require('child_process').exec
|
||||||
|
exec('yarn start', { windowsHide: true })
|
||||||
68
yarn.lock
68
yarn.lock
@ -14,6 +14,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.14.0"
|
regenerator-runtime "^0.14.0"
|
||||||
|
|
||||||
|
"@babel/runtime@^7.24.7":
|
||||||
|
version "7.24.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.8.tgz#5d958c3827b13cc6d05e038c07fb2e5e3420d82e"
|
||||||
|
integrity sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime "^0.14.0"
|
||||||
|
|
||||||
"@formatjs/ecma402-abstract@2.0.0":
|
"@formatjs/ecma402-abstract@2.0.0":
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.0.0.tgz#39197ab90b1c78b7342b129a56a7acdb8f512e17"
|
resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.0.0.tgz#39197ab90b1c78b7342b129a56a7acdb8f512e17"
|
||||||
@ -2262,6 +2269,11 @@ commander@^4.0.0:
|
|||||||
resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz"
|
resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz"
|
||||||
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
|
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
|
||||||
|
|
||||||
|
complex.js@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.1.1.tgz#0675dac8e464ec431fb2ab7d30f41d889fb25c31"
|
||||||
|
integrity sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==
|
||||||
|
|
||||||
compute-scroll-into-view@^3.0.2:
|
compute-scroll-into-view@^3.0.2:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz#753f11d972596558d8fe7c6bcbc8497690ab4c87"
|
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz#753f11d972596558d8fe7c6bcbc8497690ab4c87"
|
||||||
@ -2324,7 +2336,7 @@ debug@4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms "2.1.2"
|
ms "2.1.2"
|
||||||
|
|
||||||
decimal.js@^10.3.1:
|
decimal.js@^10.3.1, decimal.js@^10.4.3:
|
||||||
version "10.4.3"
|
version "10.4.3"
|
||||||
resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz"
|
resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz"
|
||||||
integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==
|
integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==
|
||||||
@ -2393,6 +2405,11 @@ emoji-regex@^9.2.2:
|
|||||||
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz"
|
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz"
|
||||||
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
||||||
|
|
||||||
|
escape-latex@^1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1"
|
||||||
|
integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==
|
||||||
|
|
||||||
escodegen@^2.0.0:
|
escodegen@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz"
|
resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz"
|
||||||
@ -2474,6 +2491,11 @@ form-data@^4.0.0:
|
|||||||
combined-stream "^1.0.8"
|
combined-stream "^1.0.8"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
|
fraction.js@^4.3.7:
|
||||||
|
version "4.3.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
|
||||||
|
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
|
||||||
|
|
||||||
framer-motion@^11.2.13:
|
framer-motion@^11.2.13:
|
||||||
version "11.2.13"
|
version "11.2.13"
|
||||||
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-11.2.13.tgz#ab23fbc386233b1a1548757d840190054e5e1f1d"
|
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-11.2.13.tgz#ab23fbc386233b1a1548757d840190054e5e1f1d"
|
||||||
@ -2703,6 +2725,11 @@ jackspeak@^3.1.2:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@pkgjs/parseargs" "^0.11.0"
|
"@pkgjs/parseargs" "^0.11.0"
|
||||||
|
|
||||||
|
javascript-natural-sort@^0.7.1:
|
||||||
|
version "0.7.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59"
|
||||||
|
integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==
|
||||||
|
|
||||||
jiti@^1.21.0:
|
jiti@^1.21.0:
|
||||||
version "1.21.6"
|
version "1.21.6"
|
||||||
resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz"
|
resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz"
|
||||||
@ -2810,6 +2837,21 @@ make-dir@^3.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
semver "^6.0.0"
|
semver "^6.0.0"
|
||||||
|
|
||||||
|
mathjs@^13.0.2:
|
||||||
|
version "13.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-13.0.2.tgz#eb87e31a21d9ffc57e26ce98ddb14a4a07b13d91"
|
||||||
|
integrity sha512-8vK/+InU4FTphRTWsrnvRsgSjbyNupRQYDDIXLuEGDZtJsGdbA9dVV4HZ0amBQb+RXplRjVJNGZZfB0WoHWFWA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.24.7"
|
||||||
|
complex.js "^2.1.1"
|
||||||
|
decimal.js "^10.4.3"
|
||||||
|
escape-latex "^1.2.0"
|
||||||
|
fraction.js "^4.3.7"
|
||||||
|
javascript-natural-sort "^0.7.1"
|
||||||
|
seedrandom "^3.0.5"
|
||||||
|
tiny-emitter "^2.1.0"
|
||||||
|
typed-function "^4.2.1"
|
||||||
|
|
||||||
merge2@^1.3.0:
|
merge2@^1.3.0:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz"
|
resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz"
|
||||||
@ -3263,6 +3305,11 @@ scroll-into-view-if-needed@3.0.10:
|
|||||||
dependencies:
|
dependencies:
|
||||||
compute-scroll-into-view "^3.0.2"
|
compute-scroll-into-view "^3.0.2"
|
||||||
|
|
||||||
|
seedrandom@^3.0.5:
|
||||||
|
version "3.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7"
|
||||||
|
integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==
|
||||||
|
|
||||||
semver@^6.0.0:
|
semver@^6.0.0:
|
||||||
version "6.3.1"
|
version "6.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||||
@ -3370,7 +3417,14 @@ string_decoder@^1.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "~5.2.0"
|
safe-buffer "~5.2.0"
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||||
|
version "6.0.1"
|
||||||
|
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||||
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
|
dependencies:
|
||||||
|
ansi-regex "^5.0.1"
|
||||||
|
|
||||||
|
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
@ -3480,6 +3534,11 @@ thenify-all@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
any-promise "^1.0.0"
|
any-promise "^1.0.0"
|
||||||
|
|
||||||
|
tiny-emitter@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
|
||||||
|
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
|
||||||
|
|
||||||
to-regex-range@^5.0.1:
|
to-regex-range@^5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
|
resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
|
||||||
@ -3519,6 +3578,11 @@ tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0:
|
|||||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz"
|
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz"
|
||||||
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
||||||
|
|
||||||
|
typed-function@^4.2.1:
|
||||||
|
version "4.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-4.2.1.tgz#19aa51847aa2dea9ef5e7fb7641c060179a74426"
|
||||||
|
integrity sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==
|
||||||
|
|
||||||
universalify@^0.2.0:
|
universalify@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz"
|
resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user