dev #202
@ -387,7 +387,15 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
this.canvas = canvas
|
this.canvas = canvas
|
||||||
},
|
},
|
||||||
fillCellABType(
|
fillCellABType(
|
||||||
cell = { width: 50, height: 100, padding: 5, wallDirection: 'left', referenceDirection: 'none', startIndex: -1, isCellCenter: false },
|
cell = {
|
||||||
|
width: 50,
|
||||||
|
height: 100,
|
||||||
|
padding: 5,
|
||||||
|
wallDirection: 'left',
|
||||||
|
referenceDirection: 'none',
|
||||||
|
startIndex: -1,
|
||||||
|
isCellCenter: false,
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
const points = this.points
|
const points = this.points
|
||||||
|
|
||||||
@ -689,6 +697,59 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
|
|
||||||
return intersects % 2 === 1
|
return intersects % 2 === 1
|
||||||
},
|
},
|
||||||
|
|
||||||
|
inPolygonImproved(point) {
|
||||||
|
const vertices = this.points
|
||||||
|
let inside = false
|
||||||
|
const testX = point.x
|
||||||
|
const testY = point.y
|
||||||
|
|
||||||
|
for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) {
|
||||||
|
const xi = vertices[i].x
|
||||||
|
const yi = vertices[i].y
|
||||||
|
const xj = vertices[j].x
|
||||||
|
const yj = vertices[j].y
|
||||||
|
|
||||||
|
// 점이 정점 위에 있는지 확인
|
||||||
|
if (Math.abs(xi - testX) < 0.01 && Math.abs(yi - testY) < 0.01) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 점이 선분 위에 있는지 확인
|
||||||
|
if (this.isPointOnSegment(point, { x: xi, y: yi }, { x: xj, y: yj })) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ray casting 알고리즘
|
||||||
|
if (((yi > testY) !== (yj > testY)) &&
|
||||||
|
(testX < (xj - xi) * (testY - yi) / (yj - yi) + xi)) {
|
||||||
|
inside = !inside
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return inside
|
||||||
|
},
|
||||||
|
|
||||||
|
isPointOnSegment(point, segStart, segEnd) {
|
||||||
|
const tolerance = 0.1
|
||||||
|
const dxSegment = segEnd.x - segStart.x
|
||||||
|
const dySegment = segEnd.y - segStart.y
|
||||||
|
const dxPoint = point.x - segStart.x
|
||||||
|
const dyPoint = point.y - segStart.y
|
||||||
|
|
||||||
|
// 벡터의 외적을 계산하여 점이 선분 위에 있는지 확인
|
||||||
|
const crossProduct = Math.abs(dxPoint * dySegment - dyPoint * dxSegment)
|
||||||
|
|
||||||
|
if (crossProduct > tolerance) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 점이 선분의 범위 내에 있는지 확인
|
||||||
|
const dotProduct = dxPoint * dxSegment + dyPoint * dySegment
|
||||||
|
const squaredLength = dxSegment * dxSegment + dySegment * dySegment
|
||||||
|
|
||||||
|
return dotProduct >= 0 && dotProduct <= squaredLength
|
||||||
|
},
|
||||||
setCoords: function () {
|
setCoords: function () {
|
||||||
// 부모 클래스의 setCoords 호출
|
// 부모 클래스의 setCoords 호출
|
||||||
this.callSuper('setCoords')
|
this.callSuper('setCoords')
|
||||||
@ -699,10 +760,10 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
delete this.oCoords
|
delete this.oCoords
|
||||||
delete this.aCoords
|
delete this.aCoords
|
||||||
delete this.__corner
|
delete this.__corner
|
||||||
|
|
||||||
// 다시 부모 setCoords 호출
|
// 다시 부모 setCoords 호출
|
||||||
this.callSuper('setCoords')
|
this.callSuper('setCoords')
|
||||||
|
|
||||||
// 한 번 더 강제로 bounding rect 재계산
|
// 한 번 더 강제로 bounding rect 재계산
|
||||||
this._clearCache && this._clearCache()
|
this._clearCache && this._clearCache()
|
||||||
}
|
}
|
||||||
@ -711,7 +772,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
containsPoint: function (point) {
|
containsPoint: function (point) {
|
||||||
// 먼저 좌표 업데이트
|
// 먼저 좌표 업데이트
|
||||||
this.setCoords()
|
this.setCoords()
|
||||||
|
|
||||||
// 캔버스 줌과 viewport transform 고려한 좌표 변환
|
// 캔버스 줌과 viewport transform 고려한 좌표 변환
|
||||||
let localPoint = point
|
let localPoint = point
|
||||||
if (this.canvas) {
|
if (this.canvas) {
|
||||||
@ -722,13 +783,25 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
localPoint = fabric.util.transformPoint(point, inverted)
|
localPoint = fabric.util.transformPoint(point, inverted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 오브젝트의 transform matrix를 고려한 좌표 변환
|
||||||
|
const matrix = this.calcTransformMatrix()
|
||||||
|
const invertedMatrix = fabric.util.invertTransform(matrix)
|
||||||
|
const transformedPoint = fabric.util.transformPoint(localPoint, invertedMatrix)
|
||||||
|
|
||||||
|
// pathOffset을 고려한 최종 좌표 계산
|
||||||
|
const pathOffset = this.get('pathOffset')
|
||||||
|
const finalPoint = {
|
||||||
|
x: transformedPoint.x + pathOffset.x,
|
||||||
|
y: transformedPoint.y + pathOffset.y,
|
||||||
|
}
|
||||||
|
|
||||||
if (this.name === POLYGON_TYPE.ROOF && this.isFixed) {
|
if (this.name === POLYGON_TYPE.ROOF && this.isFixed) {
|
||||||
const isInside = this.inPolygon(localPoint)
|
const isInside = this.inPolygonImproved(finalPoint)
|
||||||
this.set('selectable', isInside)
|
this.set('selectable', isInside)
|
||||||
return isInside
|
return isInside
|
||||||
} else {
|
} else {
|
||||||
return this.callSuper('containsPoint', localPoint)
|
return this.inPolygonImproved(finalPoint)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,12 @@ import { OUTER_LINE_TYPE } from '@/store/outerLineAtom'
|
|||||||
import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall'
|
import OuterLineWall from '@/components/floor-plan/modal/lineTypes/OuterLineWall'
|
||||||
import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing'
|
import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
|
|
||||||
export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) {
|
export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) {
|
||||||
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
@ -52,6 +56,15 @@ export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
cutAuxiliary,
|
cutAuxiliary,
|
||||||
} = useAuxiliaryDrawing(id)
|
} = useAuxiliaryDrawing(id)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
const auxiliaryLines = canvas.getObjects().filter((line) => line.name === 'auxiliaryLine' && !line.isAuxiliaryFixed) // 보조선이 그려져 있는 경우 물어본다.
|
||||||
|
if (auxiliaryLines.length > 0) {
|
||||||
|
handleFix()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
const outerLineProps = {
|
const outerLineProps = {
|
||||||
length1,
|
length1,
|
||||||
setLength1,
|
setLength1,
|
||||||
|
|||||||
@ -2121,6 +2121,7 @@ export function useModuleBasicSetting(tabNum) {
|
|||||||
let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직
|
let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직
|
||||||
|
|
||||||
let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1
|
let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1
|
||||||
|
calcAreaHeight = isNaN(calcAreaHeight) ? moduleSetupSurface.height : calcAreaHeight
|
||||||
let calcModuleHeightCount = calcAreaHeight / (height + intvVer)
|
let calcModuleHeightCount = calcAreaHeight / (height + intvVer)
|
||||||
|
|
||||||
if (type === MODULE_SETUP_TYPE.LAYOUT) {
|
if (type === MODULE_SETUP_TYPE.LAYOUT) {
|
||||||
|
|||||||
@ -680,7 +680,7 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
|
|||||||
const newLine = addLine([line1.x1, line1.y1, interSectionPointsWithRoofLines[0].x, interSectionPointsWithRoofLines[0].y], {
|
const newLine = addLine([line1.x1, line1.y1, interSectionPointsWithRoofLines[0].x, interSectionPointsWithRoofLines[0].y], {
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: false,
|
selectable: true,
|
||||||
name: 'auxiliaryLine',
|
name: 'auxiliaryLine',
|
||||||
isFixed: true,
|
isFixed: true,
|
||||||
attributes: { ...line1.attributes },
|
attributes: { ...line1.attributes },
|
||||||
@ -693,7 +693,7 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
|
|||||||
const newLine = addLine([line1.x2, line1.y2, interSectionPointsWithRoofLines[0].x, interSectionPointsWithRoofLines[0].y], {
|
const newLine = addLine([line1.x2, line1.y2, interSectionPointsWithRoofLines[0].x, interSectionPointsWithRoofLines[0].y], {
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: false,
|
selectable: true,
|
||||||
name: 'auxiliaryLine',
|
name: 'auxiliaryLine',
|
||||||
isFixed: true,
|
isFixed: true,
|
||||||
attributes: { ...line1.attributes },
|
attributes: { ...line1.attributes },
|
||||||
@ -737,7 +737,6 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
|
|||||||
// line2.set(originLine2)
|
// line2.set(originLine2)
|
||||||
// canvas.renderAll()
|
// canvas.renderAll()
|
||||||
|
|
||||||
|
|
||||||
const intersectionPoint = calculateIntersection(line1, line2)
|
const intersectionPoint = calculateIntersection(line1, line2)
|
||||||
if (!intersectionPoint) {
|
if (!intersectionPoint) {
|
||||||
return
|
return
|
||||||
@ -865,6 +864,8 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cutAuxiliary()
|
||||||
|
|
||||||
const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
|
|
||||||
//lineHistory.current에 있는 선들 중 startPoint와 endPoint가 겹치는 line은 제거
|
//lineHistory.current에 있는 선들 중 startPoint와 endPoint가 겹치는 line은 제거
|
||||||
|
|||||||
@ -744,21 +744,21 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|||||||
/** baseLine을 기준으로 확인용 polygon 작성 */
|
/** baseLine을 기준으로 확인용 polygon 작성 */
|
||||||
const checkWallPolygon = new QPolygon(baseLinePoints, {})
|
const checkWallPolygon = new QPolygon(baseLinePoints, {})
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 외벽선이 시계방향인지 시계반대 방향인지 확인
|
// * 외벽선이 시계방향인지 시계반대 방향인지 확인
|
||||||
* @type {boolean}
|
// * @type {boolean}
|
||||||
*/
|
// */
|
||||||
let counterClockwise = true
|
// let counterClockwise = true
|
||||||
let signedArea = 0
|
// let signedArea = 0
|
||||||
|
//
|
||||||
baseLinePoints.forEach((point, index) => {
|
// baseLinePoints.forEach((point, index) => {
|
||||||
const nextPoint = baseLinePoints[(index + 1) % baseLinePoints.length]
|
// const nextPoint = baseLinePoints[(index + 1) % baseLinePoints.length]
|
||||||
signedArea += point.x * nextPoint.y - point.y * nextPoint.x
|
// signedArea += point.x * nextPoint.y - point.y * nextPoint.x
|
||||||
})
|
// })
|
||||||
|
//
|
||||||
if (signedArea > 0) {
|
// if (signedArea > 0) {
|
||||||
counterClockwise = false
|
// counterClockwise = false
|
||||||
}
|
// }
|
||||||
|
|
||||||
const drawEavesFirstLines = []
|
const drawEavesFirstLines = []
|
||||||
const drawEavesSecondLines = []
|
const drawEavesSecondLines = []
|
||||||
@ -780,6 +780,15 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|||||||
const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
|
const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint)
|
||||||
const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
|
const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint)
|
||||||
|
|
||||||
|
// const checkLine = new fabric.Line([currentLine.x1, currentLine.y1, currentLine.x2, currentLine.y2], {
|
||||||
|
// stroke: 'red',
|
||||||
|
// strokeWidth: 4,
|
||||||
|
// parentId: roofId,
|
||||||
|
// name: 'checkLine',
|
||||||
|
// })
|
||||||
|
// canvas.add(checkLine)
|
||||||
|
// canvas.renderAll()
|
||||||
|
|
||||||
const checkScale = Big(10)
|
const checkScale = Big(10)
|
||||||
const xVector = Big(nextLine.x2).minus(Big(nextLine.x1))
|
const xVector = Big(nextLine.x2).minus(Big(nextLine.x1))
|
||||||
const yVector = Big(nextLine.y2).minus(Big(nextLine.y1))
|
const yVector = Big(nextLine.y2).minus(Big(nextLine.y1))
|
||||||
@ -3039,6 +3048,26 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|||||||
})
|
})
|
||||||
polygonPoints = getSortedPoint(uniquePoints, baseHipLines)
|
polygonPoints = getSortedPoint(uniquePoints, baseHipLines)
|
||||||
|
|
||||||
|
/*polygonPoints.forEach((point) => {
|
||||||
|
const checkCircle = new fabric.Circle({
|
||||||
|
left: point.x,
|
||||||
|
top: point.y,
|
||||||
|
radius: 4,
|
||||||
|
fill: 'red',
|
||||||
|
parentId: roofId,
|
||||||
|
name: 'checkCircle',
|
||||||
|
})
|
||||||
|
canvas.add(checkCircle)
|
||||||
|
canvas.renderAll()
|
||||||
|
|
||||||
|
/!** 확인용 라인 제거 *!/
|
||||||
|
canvas
|
||||||
|
.getObjects()
|
||||||
|
.filter((obj) => obj.name === 'checkCircle' || obj.name === 'checkLine')
|
||||||
|
.forEach((obj) => canvas.remove(obj))
|
||||||
|
canvas.renderAll()
|
||||||
|
})*/
|
||||||
|
|
||||||
polygonPoints.forEach((currentPoint, index) => {
|
polygonPoints.forEach((currentPoint, index) => {
|
||||||
const nextPoint = polygonPoints[(index + 1) % polygonPoints.length]
|
const nextPoint = polygonPoints[(index + 1) % polygonPoints.length]
|
||||||
const points = [currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y]
|
const points = [currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y]
|
||||||
@ -3077,6 +3106,15 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|||||||
const nextLine = nextBaseLine.line
|
const nextLine = nextBaseLine.line
|
||||||
let { x1, x2, y1, y2 } = currentBaseLine
|
let { x1, x2, y1, y2 } = currentBaseLine
|
||||||
|
|
||||||
|
/*const checkLine = new fabric.Line([x1, y1, x2, y2], {
|
||||||
|
stroke: 'red',
|
||||||
|
strokeWidth: 4,
|
||||||
|
parentId: roofId,
|
||||||
|
name: 'checkLine',
|
||||||
|
})
|
||||||
|
canvas.add(checkLine)
|
||||||
|
canvas.renderAll()*/
|
||||||
|
|
||||||
const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1)
|
const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1)
|
||||||
const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1)
|
const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1)
|
||||||
const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
|
const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
|
||||||
@ -3097,11 +3135,11 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|||||||
.forEach((line) => {
|
.forEach((line) => {
|
||||||
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
|
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
|
||||||
const intersection = edgesIntersection(checkEdge, lineEdge)
|
const intersection = edgesIntersection(checkEdge, lineEdge)
|
||||||
if (intersection) {
|
if (intersection && isPointOnLine(line, intersection)) {
|
||||||
intersectionRoofs.push({
|
intersectionRoofs.push({
|
||||||
line,
|
line,
|
||||||
intersection,
|
intersection,
|
||||||
size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
|
size: Math.sqrt(Math.pow(intersection.x - currentMidX.toNumber(), 2) + Math.pow(intersection.y - currentMidY.toNumber(), 2)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -3115,11 +3153,11 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|||||||
.forEach((line) => {
|
.forEach((line) => {
|
||||||
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
|
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
|
||||||
const intersection = edgesIntersection(checkEdge, lineEdge)
|
const intersection = edgesIntersection(checkEdge, lineEdge)
|
||||||
if (intersection) {
|
if (intersection && isPointOnLine(line, intersection)) {
|
||||||
intersectionRoofs.push({
|
intersectionRoofs.push({
|
||||||
line,
|
line,
|
||||||
intersection,
|
intersection,
|
||||||
size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(),
|
size: Math.sqrt(Math.pow(intersection.x - currentMidX.toNumber(), 2) + Math.pow(intersection.y - currentMidY.toNumber(), 2)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user