도머 설치된 지붕면 이동시 이상 수정

This commit is contained in:
hyojun.choi 2026-04-24 16:14:58 +09:00
parent 78e4225069
commit cce18d47ad
2 changed files with 51 additions and 2 deletions

View File

@ -146,11 +146,13 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.setCoords() this.setCoords()
// 보조선 / 자식 객체들도 같이 이동시킨다 (ROOF 가 아닌 WALL 등에서도 동작하도록) // 보조선 / 자식 객체들도 같이 이동시킨다 (ROOF 가 아닌 WALL 등에서도 동작하도록)
// 단, fabric.Group(도머 등)은 절대 위치 유지해야 하므로 제외
if ((dxModified !== 0 || dyModified !== 0) && this.canvas) { if ((dxModified !== 0 || dyModified !== 0) && this.canvas) {
const directChildren = this.canvas.getObjects().filter((obj) => { const directChildren = this.canvas.getObjects().filter((obj) => {
if (obj === this) return false if (obj === this) return false
if (obj.parentId !== this.id) return false if (obj.parentId !== this.id) return false
if (obj.name === 'lengthText') return false if (obj.name === 'lengthText') return false
if (obj.type === 'group') return false // 도머 등 Group 은 이동 대상에서 제외
return true return true
}) })
const childIds = new Set(directChildren.map((c) => c.id).filter(Boolean)) const childIds = new Set(directChildren.map((c) => c.id).filter(Boolean))
@ -181,6 +183,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
movedTextCount++ movedTextCount++
} }
}) })
this.canvas.renderAll() this.canvas.renderAll()
// ROOF 의 경우 polygonMoved 가 같은 일을 다시 하므로, _preDragLeft 는 거기서 정리됨 // ROOF 의 경우 polygonMoved 가 같은 일을 다시 하므로, _preDragLeft 는 거기서 정리됨
@ -277,6 +280,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
if (obj === this) return false if (obj === this) return false
if (obj.parentId !== this.id) return false if (obj.parentId !== this.id) return false
if (obj.name === 'lengthText') return false // 이미 재생성됨 if (obj.name === 'lengthText') return false // 이미 재생성됨
if (obj.type === 'group') return false // 도머 등 Group 은 절대 위치 유지
return true return true
}) })
@ -318,6 +322,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
movedTextCount++ movedTextCount++
} }
}) })
this.canvas.renderAll() this.canvas.renderAll()
} }

View File

@ -197,7 +197,29 @@ export function useUndoRedo() {
}) })
// 부모가 없는 고아 lengthText, arrow, flowText 제거 // 부모가 없는 고아 lengthText, arrow, flowText 제거
const parentIds = new Set(objects.filter((obj) => obj.id).map((obj) => obj.id)) // fabric.Group 내부의 QPolygon/QLine 자식 id도 부모로 간주해야
// 도머(Group) 내부 삼각형들의 lengthText가 사라지지 않음
const parentIds = new Set()
objects.forEach((obj) => {
if (obj.id) parentIds.add(obj.id)
if (obj.type === 'group' && obj._objects) {
obj._objects.forEach((child) => {
if (child.id) parentIds.add(child.id)
// 그룹 내부 QPolygon의 lines(QLine) id도 포함
if (child.lines && Array.isArray(child.lines)) {
child.lines.forEach((line) => {
if (line.id) parentIds.add(line.id)
})
}
})
}
// 일반 QPolygon의 lines id도 포함 (내부 보조선/치수선의 parentId)
if (obj.lines && Array.isArray(obj.lines)) {
obj.lines.forEach((line) => {
if (line.id) parentIds.add(line.id)
})
}
})
const orphans = objects.filter( const orphans = objects.filter(
(obj) => (obj.name === 'lengthText' || obj.name === 'arrow' || obj.name === 'flowText') && obj.parentId && !parentIds.has(obj.parentId), (obj) => (obj.name === 'lengthText' || obj.name === 'arrow' || obj.name === 'flowText') && obj.parentId && !parentIds.has(obj.parentId),
) )
@ -275,7 +297,14 @@ export function useUndoRedo() {
// loadFromJSON 후 QPolygon/QLine 의 lengthText 가 orphan 제거되었을 수 있으므로 재생성 // loadFromJSON 후 QPolygon/QLine 의 lengthText 가 orphan 제거되었을 수 있으므로 재생성
// (initLines 로 새 QLine 이 만들어지면 기존 lengthText 의 parentId 가 안 맞음) // (initLines 로 새 QLine 이 만들어지면 기존 lengthText 의 parentId 가 안 맞음)
const qPolygons = objects.filter((obj) => obj.type === 'QPolygon' && obj.name !== 'arrow' && obj.name !== POLYGON_TYPE.MODULE && obj.name !== POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.name !== POLYGON_TYPE.OBJECT_SURFACE) const shouldRebuildText = (poly) =>
poly.type === 'QPolygon' &&
poly.name !== 'arrow' &&
poly.name !== POLYGON_TYPE.MODULE &&
poly.name !== POLYGON_TYPE.MODULE_SETUP_SURFACE &&
poly.name !== POLYGON_TYPE.OBJECT_SURFACE
const qPolygons = objects.filter(shouldRebuildText)
qPolygons.forEach((polygon) => { qPolygons.forEach((polygon) => {
try { try {
polygon.initLines() polygon.initLines()
@ -283,6 +312,21 @@ export function useUndoRedo() {
} catch (e) { /* skip */ } } catch (e) { /* skip */ }
}) })
// Group 내부 QPolygon(도머 등)의 lengthText 도 동일하게 재생성
objects
.filter((obj) => obj.type === 'group' && obj._objects)
.forEach((group) => {
group._objects.forEach((child) => {
if (shouldRebuildText(child)) {
try {
if (!child.canvas) child.canvas = canvas
child.initLines?.()
child.addLengthText?.()
} catch (e) { /* skip */ }
}
})
})
canvas.getObjects() canvas.getObjects()
.filter((obj) => obj.type === 'QLine') .filter((obj) => obj.type === 'QLine')
.forEach((line) => { .forEach((line) => {