Compare commits

..

19 Commits

Author SHA1 Message Date
67ebf0b514 [1360] 일본어 2025-12-19 13:12:41 +09:00
8be85a3f9e skt 2025121901 2025-12-19 09:19:26 +09:00
e93ecf169d Merge branch 'dev' of https://git.hanasys.jp/qcast3/qcast-front into dev_ysCha 2025-12-19 08:55:58 +09:00
306c71ead2 동이동변경 2025-12-18 18:05:08 +09:00
50376446d0 Merge branch 'dev' of https://git.hanasys.jp/qcast3/qcast-front into dev 2025-12-18 17:59:25 +09:00
1a432913fc A,B타입 지붕재 할당 시 방향 오류 수정 2025-12-18 17:59:16 +09:00
7be6b60e12 동이동변경 2025-12-18 17:27:28 +09:00
abb498178d Merge branch 'dev' of https://git.hanasys.jp/qcast3/qcast-front into dev_ysCha 2025-12-18 17:19:21 +09:00
b6bfa8fd2e Merge pull request '오브젝트 저장: 계산기 추가' (#497) from dev_ysCha into dev
Reviewed-on: #497
2025-12-18 14:06:06 +09:00
Jaeyoung Lee
252782f275 Merge branch 'feature/design-remake' into dev 2025-12-18 11:28:16 +09:00
Jaeyoung Lee
013fd963b3 변별로 4각에서 마루선 그려지지 않는 경우 처리 2025-12-18 11:27:56 +09:00
f345b0dbbe 처마/케라바 변경 탭 변경시 버튼 값 초기화 2025-12-18 10:12:34 +09:00
Jaeyoung Lee
86d595ef52 주석처리 안된곳 처리. 2025-12-17 17:50:18 +09:00
Jaeyoung Lee
ce5192ba1a Merge branch 'dev' into feature/design-remake 2025-12-17 17:34:56 +09:00
Jaeyoung Lee
3a8769bd91 변별로 설정 1차 운영서버 반영 2025-12-17 17:33:16 +09:00
Jaeyoung Lee
f3cd10931d 변별로 처리 중간저장 2025-12-11 14:39:46 +09:00
Jaeyoung Lee
6c0cc73cb8 중간 저장(반박공지붕 추가) 2025-11-24 10:35:00 +09:00
Jaeyoung Lee
a201d65ebe 변별로 대응 중간 저장 2025-11-21 14:15:52 +09:00
Jaeyoung Lee
d148077e6b 변별로 설정 중간 저장 2025-11-12 10:40:57 +09:00
6 changed files with 5280 additions and 791 deletions

View File

@ -57,6 +57,7 @@ export default function Qna() {
endRow : endRow, endRow : endRow,
schMainYn : 'N', schMainYn : 'N',
siteTpCd : 'QC', siteTpCd : 'QC',
langCd : 'JA',
}) })
const apiUrl = `${url}?${params.toString()}` const apiUrl = `${url}?${params.toString()}`

View File

@ -2,7 +2,7 @@ import { fabric } from 'fabric'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { QLine } from '@/components/fabric/QLine' import { QLine } from '@/components/fabric/QLine'
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util' import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util'
import { calculateAngle, drawGableRoof, drawRidgeRoof, drawShedRoof, toGeoJSON } from '@/util/qpolygon-utils' import { calculateAngle, drawGableRoof, drawRoofByAttribute, drawShedRoof, toGeoJSON } from '@/util/qpolygon-utils'
import * as turf from '@turf/turf' import * as turf from '@turf/turf'
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common' import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
import Big from 'big.js' import Big from 'big.js'
@ -314,14 +314,18 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
} }
const getParallelEavesLines = function (shedLines, lines) { const getParallelEavesLines = function (shedLines, lines) {
const eavesLines = lines.filter((line) => line.attributes?.type === LINE_TYPE.WALLLINE.EAVES)
const referenceAngle = calculateAngle(shedLines[0].startPoint, shedLines[0].endPoint) const referenceAngle = calculateAngle(shedLines[0].startPoint, shedLines[0].endPoint)
const otherSideLines = lines.filter((line) => {
return eavesLines.filter((line) => { const lineAngle = calculateAngle(line.startPoint, line.endPoint)
const eavesAngle = calculateAngle(line.startPoint, line.endPoint) return Math.abs(referenceAngle - lineAngle) === 180
return Math.abs(referenceAngle - eavesAngle) === 180
}) })
const containNotEaves = otherSideLines.filter((line) => line.attributes?.type !== LINE_TYPE.WALLLINE.EAVES)
if (containNotEaves.length === 0) {
return otherSideLines
} else {
return []
}
} }
const parallelEaves = getParallelEavesLines(shedLines, lines) const parallelEaves = getParallelEavesLines(shedLines, lines)
@ -337,7 +341,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
// 용마루 -- straight-skeleton // 용마루 -- straight-skeleton
console.log('용마루 지붕') console.log('용마루 지붕')
///drawRidgeRoof(this.id, this.canvas, textMode) ///drawRidgeRoof(this.id, this.canvas, textMode)
drawSkeletonRidgeRoof(this.id, this.canvas, textMode); drawSkeletonRidgeRoof(this.id, this.canvas, textMode)
} else if (isGableRoof(types)) { } else if (isGableRoof(types)) {
// A형, B형 박공 지붕 // A형, B형 박공 지붕
console.log('패턴 지붕') console.log('패턴 지붕')
@ -347,7 +351,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
drawShedRoof(this.id, this.canvas, textMode) drawShedRoof(this.id, this.canvas, textMode)
} else { } else {
console.log('변별로 설정') console.log('변별로 설정')
drawRidgeRoof(this.id, this.canvas, textMode) drawRoofByAttribute(this.id, this.canvas, textMode)
} }
}, },

View File

@ -116,6 +116,7 @@ export function useEavesGableEdit(id) {
useEffect(() => { useEffect(() => {
typeRef.current = type typeRef.current = type
radioTypeRef.current = '1'
}, [type]) }, [type])
const mouseOverEvent = (e) => { const mouseOverEvent = (e) => {

View File

@ -851,12 +851,15 @@ export const usePolygon = () => {
// innerLines와 polygonLines의 겹침을 확인하고 type 변경 // innerLines와 polygonLines의 겹침을 확인하고 type 변경
innerLines.forEach((innerLine) => { innerLines.forEach((innerLine) => {
polygonLines.forEach((polygonLine) => { polygonLines.forEach((polygonLine) => {
if (polygonLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
return
}
if (checkLineOverlap(innerLine, polygonLine)) { if (checkLineOverlap(innerLine, polygonLine)) {
// innerLine의 type을 polygonLine의 type으로 변경 // innerLine의 type을 polygonLine의 type으로 변경
if (innerLine.attributes && polygonLine.attributes.type) { if (innerLine.attributes && polygonLine.attributes.type) {
// innerLine이 polygonLine보다 긴 경우 polygonLine.need를 false로 변경 // innerLine이 polygonLine보다 긴 경우 polygonLine.need를 false로 변경
if (polygonLine.length < innerLine.length) { if (polygonLine.length < innerLine.length) {
if (polygonLine.lineName !== 'eaveHelpLine') { if (polygonLine.lineName !== 'eaveHelpLine' || polygonLine.lineName !== 'eaveHelpLine') {
polygonLine.need = false polygonLine.need = false
} }
} }
@ -1014,6 +1017,7 @@ export const usePolygon = () => {
canvas.add(line) canvas.add(line)
}) })
canvas.renderAll()*/ canvas.renderAll()*/
polygonLines = polygonLines.filter((line) => line.need) polygonLines = polygonLines.filter((line) => line.need)
polygonLines.forEach((line) => { polygonLines.forEach((line) => {
@ -1377,7 +1381,6 @@ export const usePolygon = () => {
let newRoofs = getSplitRoofsPoints(allLines) let newRoofs = getSplitRoofsPoints(allLines)
newRoofs = newRoofs.filter((roof) => roof.length !== 0) newRoofs = newRoofs.filter((roof) => roof.length !== 0)
newRoofs.forEach((roofPoint, index) => { newRoofs.forEach((roofPoint, index) => {
let defense, pitch let defense, pitch
@ -1411,6 +1414,124 @@ export const usePolygon = () => {
} }
}) })
// representLines가 없다면 A,B타입중 하나임
if (representLines.length === 0) {
// 1. roofPoint로 폴리곤의 라인들을 생성
const roofPolygonLines = []
for (let i = 0; i < roofPoint.length; i++) {
const nextIndex = (i + 1) % roofPoint.length
const startPt = roofPoint[i]
const endPt = roofPoint[nextIndex]
roofPolygonLines.push({
x1: startPt.x,
y1: startPt.y,
x2: endPt.x,
y2: endPt.y,
startPoint: startPt,
endPoint: endPt,
})
}
// 3. 평행 여부 확인 함수
const checkParallel = (line1, line2) => {
const v1x = line1.x2 - line1.x1
const v1y = line1.y2 - line1.y1
const v2x = line2.x2 - line2.x1
const v2y = line2.y2 - line2.y1
const length1 = Math.sqrt(v1x ** 2 + v1y ** 2)
const length2 = Math.sqrt(v2x ** 2 + v2y ** 2)
if (length1 === 0 || length2 === 0) return false
const norm1x = v1x / length1
const norm1y = v1y / length1
const norm2x = v2x / length2
const norm2y = v2y / length2
const EPSILON = 0.01
const crossProduct = Math.abs(norm1x * norm2y - norm1y * norm2x)
const dotProduct = norm1x * norm2x + norm1y * norm2y
return crossProduct < EPSILON || Math.abs(Math.abs(dotProduct) - 1) < EPSILON
}
// 4. 점에서 라인까지의 거리 계산 함수
const getDistanceFromPointToLine = (point, lineP1, lineP2) => {
const A = point.x - lineP1.x
const B = point.y - lineP1.y
const C = lineP2.x - lineP1.x
const D = lineP2.y - lineP1.y
const dot = A * C + B * D
const lenSq = C * C + D * D
let param = -1
if (lenSq !== 0) {
param = dot / lenSq
}
let xx, yy
if (param < 0) {
xx = lineP1.x
yy = lineP1.y
} else if (param > 1) {
xx = lineP2.x
yy = lineP2.y
} else {
xx = lineP1.x + param * C
yy = lineP1.y + param * D
}
const dx = point.x - xx
const dy = point.y - yy
return Math.sqrt(dx * dx + dy * dy)
}
// 5. 두 평행한 라인 사이의 거리 계산 (한 라인의 중점에서 다른 라인까지의 거리)
const getDistanceBetweenParallelLines = (line1, line2) => {
const midPoint = {
x: (line1.x1 + line1.x2) / 2,
y: (line1.y1 + line1.y2) / 2,
}
return getDistanceFromPointToLine(midPoint, { x: line2.x1, y: line2.y1 }, { x: line2.x2, y: line2.y2 })
}
// 6. roofPolygonLines의 모든 라인에서 평행하면서 가장 가까운 EAVES 라인 찾기
let closestLine = null
let minDistance = Infinity
roofPolygonLines.forEach((roofLine) => {
;[...polygonLines, ...innerLines].forEach((line) => {
// EAVES 타입만 필터링
if (line.attributes?.type !== LINE_TYPE.WALLLINE.EAVES && line.attributes?.type !== LINE_TYPE.WALLLINE.EAVE_HELP_LINE) {
return
}
const lineObj = {
x1: line.startPoint.x,
y1: line.startPoint.y,
x2: line.endPoint.x,
y2: line.endPoint.y,
}
if (checkParallel(roofLine, lineObj)) {
const distance = getDistanceBetweenParallelLines(roofLine, lineObj)
if (distance < minDistance && distance > 0) {
minDistance = distance
closestLine = line
}
}
})
})
if (closestLine) {
representLines.push(closestLine)
}
}
// representLines중 가장 긴 line을 찾는다. // representLines중 가장 긴 line을 찾는다.
representLines.forEach((line) => { representLines.forEach((line) => {
if (!representLine) { if (!representLine) {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff