지붕 라인별 offset 적용 추가

This commit is contained in:
Jaeyoung Lee 2024-09-20 09:44:36 +09:00
parent f185912c29
commit d6d295867e
3 changed files with 198 additions and 224 deletions

View File

@ -140,10 +140,10 @@ export default function Roof2(props) {
useEffect(() => { useEffect(() => {
get({ url: `/api/canvas-management/canvas-statuses/by-object/test123240822001` }).then((res) => { get({ url: `/api/canvas-management/canvas-statuses/by-object/test123240822001` }).then((res) => {
console.log(res) // console.log(res)
const arrangeData = res.map((item) => { const arrangeData = res.map((item) => {
console.log(item.canvasStatus.replace(/##/g, '"').replace(/\\/g, '')) // console.log(item.canvasStatus.replace(/##/g, '"').replace(/\\/g, ''))
const test = item.canvasStatus.replace(/##/g, '"').replace(/\\/g, '') const test = item.canvasStatus.replace(/##/g, '"').replace(/\\/g, '')
const test2 = test.substring(1, test.length - 1) const test2 = test.substring(1, test.length - 1)
return { return {

View File

@ -1472,11 +1472,203 @@ export function useMode() {
* 지붕 외곽선 생성 polygon을 입력받아 만들기 * 지붕 외곽선 생성 polygon을 입력받아 만들기
*/ */
const handleOuterlinesTest2 = (polygon, offset = 50) => { const handleOuterlinesTest2 = (polygon, offset = 50) => {
drawRoofPolygon(polygon, offset) const roof = drawRoofPolygon(polygon)
/*const offsetPoints = offsetPolygon(polygon.points, offset) roof.drawHelpLine()
roof.divideLine()
}
function inwardEdgeNormal(vertex1, vertex2) {
// Assuming that polygon vertices are in clockwise order
const dx = vertex2.x - vertex1.x
const dy = vertex2.y - vertex1.y
const edgeLength = Math.sqrt(dx * dx + dy * dy)
return {
x: -dy / edgeLength,
y: dx / edgeLength,
}
}
function outwardEdgeNormal(vertex1, vertex2) {
const n = inwardEdgeNormal(vertex1, vertex2)
return {
x: -n.x,
y: -n.y,
}
}
function createRoofPolygon(vertices) {
const edges = []
let minX = vertices.length > 0 ? vertices[0].x : undefined
let minY = vertices.length > 0 ? vertices[0].y : undefined
let maxX = minX
let maxY = minY
for (let i = 0; i < vertices.length; i++) {
const vertex1 = vertices[i]
const vertex2 = vertices[(i + 1) % vertices.length]
const outwardNormal = outwardEdgeNormal(vertex1, vertex2)
const inwardNormal = inwardEdgeNormal(vertex1, vertex2)
const edge = {
vertex1,
vertex2,
index: i,
outwardNormal,
inwardNormal,
}
edges.push(edge)
const x = vertices[i].x
const y = vertices[i].y
minX = Math.min(x, minX)
minY = Math.min(y, minY)
maxX = Math.max(x, maxX)
maxY = Math.max(y, maxY)
}
return {
vertices,
edges,
minX,
minY,
maxX,
maxY,
}
}
function createOffsetEdge(edge, dx, dy) {
return {
vertex1: {
x: edge.vertex1.x + dx,
y: edge.vertex1.y + dy,
},
vertex2: {
x: edge.vertex2.x + dx,
y: edge.vertex2.y + dy,
},
}
}
function edgesIntersection(edgeA, edgeB) {
const den =
(edgeB.vertex2.y - edgeB.vertex1.y) * (edgeA.vertex2.x - edgeA.vertex1.x) -
(edgeB.vertex2.x - edgeB.vertex1.x) * (edgeA.vertex2.y - edgeA.vertex1.y)
if (den === 0) {
return null // lines are parallel or coincident
}
const ua =
((edgeB.vertex2.x - edgeB.vertex1.x) * (edgeA.vertex1.y - edgeB.vertex1.y) -
(edgeB.vertex2.y - edgeB.vertex1.y) * (edgeA.vertex1.x - edgeB.vertex1.x)) /
den
const ub =
((edgeA.vertex2.x - edgeA.vertex1.x) * (edgeA.vertex1.y - edgeB.vertex1.y) -
(edgeA.vertex2.y - edgeA.vertex1.y) * (edgeA.vertex1.x - edgeB.vertex1.x)) /
den
// Edges are not intersecting but the lines defined by them are
const isIntersectionOutside = ua < 0 || ub < 0 || ua > 1 || ub > 1
return {
x: edgeA.vertex1.x + ua * (edgeA.vertex2.x - edgeA.vertex1.x),
y: edgeA.vertex1.y + ua * (edgeA.vertex2.y - edgeA.vertex1.y),
isIntersectionOutside,
}
}
function createMarginPolygon(polygon, lines, arcSegments = 0) {
const offsetEdges = []
polygon.edges.forEach((edge, i) => {
const offset = lines[i % lines.length].attributes.offset
const dx = edge.outwardNormal.x * offset
const dy = edge.outwardNormal.y * offset
offsetEdges.push(createOffsetEdge(edge, dx, dy))
})
const vertices = []
offsetEdges.forEach((thisEdge, i) => {
const prevEdge = offsetEdges[(i + offsetEdges.length - 1) % offsetEdges.length]
const vertex = edgesIntersection(prevEdge, thisEdge)
if (vertex && (!vertex.isIntersectionOutside || arcSegments < 1)) {
vertices.push({
x: vertex.x,
y: vertex.y,
})
}
})
const marginPolygon = createRoofPolygon(vertices)
marginPolygon.offsetEdges = offsetEdges
return marginPolygon
}
function createPaddingPolygon(polygon, lines, arcSegments = 0) {
const offsetEdges = []
polygon.edges.forEach((edge, i) => {
const offset = lines[i % lines.length].attributes.offset
const dx = edge.inwardNormal.x * offset
const dy = edge.inwardNormal.y * offset
offsetEdges.push(createOffsetEdge(edge, dx, dy))
})
const vertices = []
offsetEdges.forEach((thisEdge, i) => {
const prevEdge = offsetEdges[(i + offsetEdges.length - 1) % offsetEdges.length]
const vertex = edgesIntersection(prevEdge, thisEdge)
if (vertex && (!vertex.isIntersectionOutside || arcSegments < 1)) {
vertices.push({
x: vertex.x,
y: vertex.y,
})
}
})
const paddingPolygon = createRoofPolygon(vertices)
paddingPolygon.offsetEdges = offsetEdges
return paddingPolygon
}
const drawRoofPolygon = (wall) => {
let walls = wall.lines
walls.forEach((wall, index) => {
if (index === walls.length - 1 || index === 3) {
wall.attributes = {
type: 'gable',
offset: 30,
}
} else {
wall.attributes = {
type: 'hip',
offset: 50,
}
}
})
const polygon = createRoofPolygon(wall.points)
const originPolygon = new QPolygon(wall.points, { fontSize: 0 })
let offsetPolygon
let result = createMarginPolygon(polygon, wall.lines).vertices
const allPointsOutside = result.every((point) => !originPolygon.inPolygon(point))
if (allPointsOutside) {
offsetPolygon = createMarginPolygon(polygon, wall.lines).vertices
} else {
offsetPolygon = createPaddingPolygon(polygon, wall.lines).vertices
}
const roof = makePolygon( const roof = makePolygon(
offsetPoints.map((point) => { offsetPolygon.map((point) => {
return { x1: point.x, y1: point.y } return { x1: point.x, y1: point.y }
}), }),
) )
@ -1485,177 +1677,7 @@ export function useMode() {
setRoof(roof) setRoof(roof)
setWall(polygon) setWall(polygon)
roof.drawHelpLine() return roof
roof.divideLine()*/
}
const drawRoofPolygon = (wall, offset = 50) => {
let walls = wall.lines
walls.forEach((wall, index) => {
if (index === 0) {
wall.attributes = {
type: 'gable',
width: 30,
}
} else {
wall.attributes = {
type: 'hip',
width: 50,
}
}
})
console.log('walls', walls)
walls.forEach((currentWall, index) => {
let prevWall, nextWall
if (index === 0) {
prevWall = walls[walls.length - 1]
nextWall = walls[index + 1]
} else if (index === walls.length - 1) {
prevWall = walls[index - 1]
nextWall = walls[0]
} else {
prevWall = walls[index - 1]
nextWall = walls[index + 1]
}
let p1 = [
{ x: currentWall.x1, y: currentWall.y1 },
{ x: currentWall.x2, y: currentWall.y2 },
{ x: prevWall.x1, y: prevWall.y1 },
{ x: prevWall.x2, y: prevWall.y2 },
],
p2 = [
{ x: currentWall.x1, y: currentWall.y1 },
{ x: currentWall.x2, y: currentWall.y2 },
{ x: nextWall.x1, y: nextWall.y1 },
{ x: nextWall.x2, y: nextWall.y2 },
]
p1 = Array.from(new Set(p1.map((point) => JSON.stringify(point)))).map((point) => JSON.parse(point))
p2 = Array.from(new Set(p2.map((point) => JSON.stringify(point)))).map((point) => JSON.parse(point))
let p1Lengths = []
p1.forEach((point1, index) => {
let point2
if (p1.length - 1 === index) {
point2 = p1[0]
} else {
point2 = p1[index + 1]
}
const dx = Math.abs(point2.x - point1.x)
const dy = Math.abs(point2.y - point1.y)
p1Lengths.push({
length: Math.round(Math.sqrt(dx ** 2 + dy ** 2)),
coords: [
{ x: point1.x, y: point1.y },
{ x: point2.x, y: point2.y },
],
})
})
let p2Lengths = []
p2.forEach((point1, index) => {
let point2
if (p2.length - 1 === index) {
point2 = p2[0]
} else {
point2 = p2[index + 1]
}
const dx = Math.abs(point2.x - point1.x)
const dy = Math.abs(point2.y - point1.y)
p2Lengths.push({
length: Math.round(Math.sqrt(dx ** 2 + dy ** 2)),
coords: [
{ x: point1.x, y: point1.y },
{ x: point2.x, y: point2.y },
],
})
})
let x1 = 0,
y1 = 0,
x2 = 0,
y2 = 0,
offsetX1 = 0,
offsetY1 = 0,
offsetX2 = 0,
offsetY2 = 0
let alfa = Math.round(Math.sqrt(Math.abs(currentWall.x1 - currentWall.x2) ** 2 + Math.abs(currentWall.y1 - currentWall.y2) ** 2)),
bravo = Math.round(Math.sqrt(Math.abs(prevWall.x1 - prevWall.x2) ** 2 + Math.abs(prevWall.y1 - prevWall.y2) ** 2)),
charlie = p1Lengths.filter((length) => length.length !== alfa && length.length !== bravo)[0],
alpha = Math.round(Math.acos((alfa ** 2 + charlie.length ** 2 - bravo ** 2) / (2 * alfa * charlie.length)) * (180 / Math.PI) * 100) / 100,
beta = Math.round(Math.acos((bravo ** 2 + charlie.length ** 2 - alfa ** 2) / (2 * bravo * charlie.length)) * (180 / Math.PI) * 100) / 100,
gamma = Math.round(Math.acos((alfa ** 2 + bravo ** 2 - charlie.length ** 2) / (2 * alfa * bravo)) * (180 / Math.PI) * 100) / 100,
isValley = checkValley(wall, currentWall, prevWall)
console.log('현재 라인 : ', alfa)
gamma = isValley ? Math.round(((360 - gamma) / 2) * 100) / 100 : Math.round((gamma / 2) * 100) / 100
console.log('이전 라인과의 각도', gamma)
if (currentWall.x1 === currentWall.x2) {
offsetY1 = currentWall.attributes.width
offsetX1 = prevWall.attributes.width
x1 = Math.min(currentWall.x1, currentWall.x2) + offsetX1
y1 = currentWall.y1 + offsetY1
} else if (currentWall.y1 === currentWall.y2) {
offsetX1 = currentWall.attributes.width
offsetY1 = prevWall.attributes.width
x1 = currentWall.x1 + offsetX1
y1 = Math.min(currentWall.y1, currentWall.y2) + offsetY1
} else {
}
bravo = Math.round(Math.sqrt(Math.abs(nextWall.x1 - nextWall.x2) ** 2 + Math.abs(nextWall.y1 - nextWall.y2) ** 2))
charlie = p2Lengths.filter((length) => length.length !== alfa && length.length !== bravo)[0]
// alpha = Math.round(Math.acos((alfa ** 2 + charlie ** 2 - bravo ** 2) / (2 * alfa * charlie)) * (180 / Math.PI))
// betta = Math.round(Math.acos((bravo ** 2 + charlie ** 2 - alfa ** 2) / (2 * bravo * charlie)) * (180 / Math.PI))
gamma = Math.round(Math.acos((alfa ** 2 + bravo ** 2 - charlie.length ** 2) / (2 * alfa * bravo)) * (180 / Math.PI) * 100) / 100
isValley = checkValley(wall, currentWall, nextWall)
gamma = isValley ? Math.round(((360 - gamma) / 2) * 100) / 100 : Math.round((gamma / 2) * 100) / 100
console.log('다음 라인과의 각도', gamma)
/*let offsetX = 0,
offsetY = 0
let x1 = 0,
y1 = 0,
x2 = 0,
y2 = 0
if (prevWall.direction !== nextWall.direction) {
if (currentWall.x1 === currentWall.x2) {
offsetX = prevWall.x1 < currentWall.x1 ? currentWall.attributes.width : -currentWall.attributes.width
x1 = currentWall.x1
x2 = currentWall.x2
y1 = Math.min(currentWall.y1, currentWall.y2) - Math.min(prevWall.attributes.width, nextWall.attributes.width)
y2 = Math.max(currentWall.y1, currentWall.y2) + Math.max(prevWall.attributes.width, nextWall.attributes.width)
} else {
offsetY = prevWall.y1 < currentWall.y1 ? currentWall.attributes.width : -currentWall.attributes.width
x1 = Math.min(currentWall.x1, currentWall.x2) - Math.min(prevWall.attributes.width, nextWall.attributes.width)
x2 = Math.max(currentWall.x1, currentWall.x2) + Math.max(prevWall.attributes.width, nextWall.attributes.width)
y1 = currentWall.y1
y2 = currentWall.y2
}
} else {
}
x1 = x1 + offsetX
x2 = x2 + offsetX
y1 = y1 + offsetY
y2 = y2 + offsetY
const roof = new QLine([x1, y1, x2, y2], {
fontSize: fontSize,
stroke: 'black',
strokeWidth: 1,
name: 'roofLine',
})
canvas?.add(roof)
canvas?.renderAll()*/
})
} }
/** /**
@ -1693,50 +1715,6 @@ export function useMode() {
return isValley return isValley
} }
/**
* 구하려는 라인의 x1,y1좌표가 기준
* @param line1 이전 라인
* @param line2 현재 라인
* @param line3 다음 라인
* @param offset
* @returns {number}
*/
const getLineOffsetPoint = (line1, line2, line3, offset) => {
//밑변
let a = Math.abs(line1.x - line2.x)
//빗변
let c = Math.sqrt(Math.abs(line1.x - line2.x) ** 2 + Math.abs(line1.y - line2.y) ** 2)
console.log(a, c)
//밑변과 빗변사이의 각도
let alphaDegree = getDegreeBetweenTwoLines(line1, line2, line3)
alphaDegree = alphaDegree <= 90 ? alphaDegree : 180 - alphaDegree
alphaDegree = 90 - alphaDegree
console.log('alphaDegree : ', alphaDegree)
// console.log('Math.tan(alphaDegree * (Math.PI / 180)) : ', Math.tan(alphaDegree * (Math.PI / 180)))
console.log(Math.round(offset * Math.tan(alphaDegree * (Math.PI / 180))))
const angle = getDegreeBetweenTwoLines(line1, line2, line3)
const side1 = line1.length
const side2 = line2.length
const side3 = Math.sqrt(side1 ** 2 + side2 ** 2 - 2 * side1 * side2 * Math.cos(angle * (Math.PI / 180)))
const beta = Math.round(Math.asin((side2 * Math.sin(angle * (Math.PI / 180))) / side3) * (180 / Math.PI) * 10) / 10
const alpha = 180 - angle - beta
console.log('angle : ', angle, 'alpha : ', alpha, 'beta : ', beta)
const h = side2 * Math.sin(alpha * (Math.PI / 180))
const h_new = h + offset
console.log('빗변까지 길이 : ', h, 'offset 적용된 빗변까지 길이 : ', h_new)
const newAdjacent = h_new / Math.sin(angle * (Math.PI / 180))
console.log('offset 적용된 밑변 : ', newAdjacent)
// offset = Math.sqrt(diffAdjacent ** 2 + diffAdjacent ** 2) / 2
console.log('offset : ', offset)
return offset
}
/** /**
* 구하려는 라인의 x1,y1좌표가 기준 * 구하려는 라인의 x1,y1좌표가 기준
* @param line1 이전 라인 * @param line1 이전 라인

View File

@ -1206,10 +1206,6 @@ export const drawHippedRoof = (polygon, chon) => {
} }
const drawRoofRidge = (polygon, chon) => { const drawRoofRidge = (polygon, chon) => {
const points = []
polygon.wall.points.forEach((point) => points.push({ x: point.x, y: point.y }))
console.log('points : ', points)
const walls = polygon.wall.lines // 외벽의 라인 const walls = polygon.wall.lines // 외벽의 라인
const roofs = polygon.lines // 지붕의 라인 const roofs = polygon.lines // 지붕의 라인
let ridgeWall = [] let ridgeWall = []