[2296] 수동배치 모듈 간 이격 미검증 수정 — 배치 게이트에 isTooCloseToOtherModules 추가 #941
@ -34,6 +34,7 @@ import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle'
|
||||
import { useMode } from '@/hooks/useMode'
|
||||
import { useTurf } from '@/hooks/common/useTurf'
|
||||
import { useUndoRedo } from '@/hooks/useUndoRedo'
|
||||
// import { debugCapture } from '@/util/debugCapture' // [MODULE-PLACE-DIAG 2026-07-01] 수동배치 경계 초과 조사용 (재활성 시 주석 해제)
|
||||
|
||||
export function useModuleBasicSetting(tabNum) {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
@ -296,6 +297,44 @@ export function useModuleBasicSetting(tabNum) {
|
||||
}
|
||||
}
|
||||
|
||||
// [PLACE-CLEARANCE 2026-07-01] 手動配置 시 モジュール間離隔(縦 moduleIntvlVer / 横 moduleIntvlHor) 미검증 보완.
|
||||
// 겹침(booleanOverlap)·外周離隔(setupSurface)만 검사해, 인접 모듈에 0간격 밀착 스냅해도 통과하던 버그.
|
||||
// [2296-2] dfa90812 의 移動 수정(useModule.js:isTooCloseToOtherModules)과 동일 로직 — 진입점만 배치.
|
||||
// ⚠ 간격은 stroke 를 뺀 실제 정점(getCurrentPoints)으로 잰다. getBoundingRect 는 strokeWidth 팽창 → 정상 격자도 위반 오판.
|
||||
const isTooCloseToOtherModules = (module, otherModules, surface) => {
|
||||
if (!otherModules || otherModules.length === 0) return false
|
||||
const gapVer = Number(surface?.trestleDetail?.moduleIntvlVer ?? 0) / 10 // mm → canvas unit
|
||||
const gapHor = Number(surface?.trestleDetail?.moduleIntvlHor ?? 0) / 10
|
||||
if (gapVer <= 0 && gapHor <= 0) return false
|
||||
const EPS = 0.05 // 0.5mm — 좌표 반올림 잔차(±0.02) 흡수
|
||||
const bboxOf = (o) => {
|
||||
const pts = o.getCurrentPoints ? o.getCurrentPoints() : null
|
||||
if (pts && pts.length) {
|
||||
const xs = pts.map((p) => p.x)
|
||||
const ys = pts.map((p) => p.y)
|
||||
return { l: Math.min(...xs), r: Math.max(...xs), t: Math.min(...ys), b: Math.max(...ys) }
|
||||
}
|
||||
const r = o.getBoundingRect(true, true)
|
||||
return { l: r.left, r: r.left + r.width, t: r.top, b: r.top + r.height }
|
||||
}
|
||||
const mb = bboxOf(module)
|
||||
return otherModules.some((o) => {
|
||||
if (o.id === module.id) return false
|
||||
const nb = bboxOf(o)
|
||||
const overlapX = mb.l < nb.r - EPS && nb.l < mb.r - EPS
|
||||
const overlapY = mb.t < nb.b - EPS && nb.t < mb.b - EPS
|
||||
if (overlapX) {
|
||||
const vGap = mb.t >= nb.b ? mb.t - nb.b : nb.t >= mb.b ? nb.t - mb.b : 0
|
||||
if (vGap < gapVer - EPS) return true
|
||||
}
|
||||
if (overlapY) {
|
||||
const hGap = mb.l >= nb.r ? mb.l - nb.r : nb.l >= mb.r ? nb.l - mb.r : 0
|
||||
if (hGap < gapHor - EPS) return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
//선택 배치면 배열`
|
||||
let selectedModuleInstSurfaceArray = []
|
||||
|
||||
@ -477,6 +516,25 @@ export function useModuleBasicSetting(tabNum) {
|
||||
})
|
||||
|
||||
setupSurface.setViewLengthText(false)
|
||||
// [MODULE-PLACE-DIAG 2026-07-01] setupSurface 인셋 확인 로그 (재활성 시 주석 해제 + import 복원)
|
||||
// {
|
||||
// const _bbox = (pts) => {
|
||||
// const xs = pts.map((p) => p.x)
|
||||
// const ys = pts.map((p) => p.y)
|
||||
// return { minX: Math.min(...xs), maxX: Math.max(...xs), minY: Math.min(...ys), maxY: Math.max(...ys) }
|
||||
// }
|
||||
// const _roofPts = roof.getCurrentPoints()
|
||||
// const _rb = _bbox(_roofPts)
|
||||
// const _sb = _bbox(offsetPoints)
|
||||
// debugCapture.log('[MODULE-PLACE-DIAG] setupSurface 생성', {
|
||||
// roofId: roof.id, roofSizeSet: canvasSetting.roofSizeSet, pitch: roof.roofMaterial?.pitch, direction: roof.direction,
|
||||
// roofBboxCanvas: { w: +(_rb.maxX - _rb.minX).toFixed(2), h: +(_rb.maxY - _rb.minY).toFixed(2) },
|
||||
// setupBboxCanvas: { w: +(_sb.maxX - _sb.minX).toFixed(2), h: +(_sb.maxY - _sb.minY).toFixed(2) },
|
||||
// insetTopCanvas: +(_sb.minY - _rb.minY).toFixed(2), insetBottomCanvas: +(_rb.maxY - _sb.maxY).toFixed(2),
|
||||
// insetLeftCanvas: +(_sb.minX - _rb.minX).toFixed(2), insetRightCanvas: +(_rb.maxX - _sb.maxX).toFixed(2),
|
||||
// lineOffsets: roof.lines.map((l) => ({ type: l.attributes?.type, offset: l.attributes?.offset })),
|
||||
// })
|
||||
// }
|
||||
canvas.add(setupSurface) //모듈설치면 만들기
|
||||
|
||||
//지붕면 선택 금지
|
||||
@ -998,13 +1056,35 @@ export function useModuleBasicSetting(tabNum) {
|
||||
if (!isIntersection) return
|
||||
|
||||
tempModule.setCoords() //좌표 재정렬
|
||||
// [MODULE-PLACE-DIAG 2026-07-01] 수동배치 게이트 진단 로그 (재활성 시 주석 해제 + import 복원)
|
||||
// {
|
||||
// const _sc = turfPolygon?.geometry?.coordinates?.[0] || []
|
||||
// const _mc = tempTurfModule?.geometry?.coordinates?.[0] || []
|
||||
// const _bb = (c) => c.length ? { minX: Math.min(...c.map((p) => p[0])), maxX: Math.max(...c.map((p) => p[0])), minY: Math.min(...c.map((p) => p[1])), maxY: Math.max(...c.map((p) => p[1])) } : null
|
||||
// const _sb = _bb(_sc), _mb = _bb(_mc)
|
||||
// debugCapture.log('[MODULE-PLACE-DIAG] 배치 게이트', {
|
||||
// surfaceId: trestlePolygon?.id,
|
||||
// moduleBbox: _mb && { minX: +_mb.minX.toFixed(2), maxX: +_mb.maxX.toFixed(2), minY: +_mb.minY.toFixed(2), maxY: +_mb.maxY.toFixed(2) },
|
||||
// surfaceBbox: _sb && { minX: +_sb.minX.toFixed(2), maxX: +_sb.maxX.toFixed(2), minY: +_sb.minY.toFixed(2), maxY: +_sb.maxY.toFixed(2) },
|
||||
// overTopCanvas: _mb && _sb ? +(_sb.minY - _mb.minY).toFixed(2) : null,
|
||||
// overBottomCanvas: _mb && _sb ? +(_mb.maxY - _sb.maxY).toFixed(2) : null,
|
||||
// gateSpare0: checkModuleDisjointSurface(tempTurfModule, turfPolygon, 0),
|
||||
// gateSpare05: checkModuleDisjointSurface(tempTurfModule, turfPolygon, 0.5),
|
||||
// isTooClose: isTooCloseToOtherModules(tempModule, manualDrawModules, trestlePolygon),
|
||||
// gapVerReq: Number(trestlePolygon?.trestleDetail?.moduleIntvlVer ?? 0) / 10,
|
||||
// gapHorReq: Number(trestlePolygon?.trestleDetail?.moduleIntvlHor ?? 0) / 10,
|
||||
// existingModuleCount: manualDrawModules?.length,
|
||||
// })
|
||||
// }
|
||||
// [EDGE-PLACE-TOLERANCE 2026-06-09] 手動 1枚 배치: 端部에 딱 붙인 모듈이 소수 절단 잔차(±0.02)로 屋根 경계를 살짝 넘으면
|
||||
// spare=0 판정이 屋根外로 오인 → 「取り付け面からモジュールを取り付けることはできません」 경고. 屋根 절대좌표에 따라 2번째/3번째가 들쭉날쭉.
|
||||
// 이동/삽입/정렬(isOutsideSurface)과 동일한 0.5 허용오차로 잔차 흡수.
|
||||
if (checkModuleDisjointSurface(tempTurfModule, turfPolygon, 0.5)) {
|
||||
//마우스 클릭시 set으로 해당 위치에 셀을 넣음
|
||||
const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module, true))) //겹치는지 확인
|
||||
if (!isOverlap) {
|
||||
// [PLACE-CLEARANCE 2026-07-01] 인접 모듈과 モジュール間離隔(縦30/横3 등) 미만이면 배치 거부
|
||||
const isTooClose = isTooCloseToOtherModules(tempModule, manualDrawModules, trestlePolygon)
|
||||
if (!isOverlap && !isTooClose) {
|
||||
canvas?.remove(tempModule)
|
||||
|
||||
//안겹치면 넣는다
|
||||
@ -1036,8 +1116,11 @@ export function useModuleBasicSetting(tabNum) {
|
||||
// }
|
||||
|
||||
// getModuleStatistics()
|
||||
} else {
|
||||
} else if (isOverlap) {
|
||||
swalFire({ text: getMessage('module.place.overlab'), icon: 'warning' })
|
||||
} else {
|
||||
// [PLACE-CLEARANCE 2026-07-01] 間離隔 미달 — 설치면 밖 배치와 동일하게 취급(取り付け不可)
|
||||
swalFire({ text: getMessage('module.place.out'), icon: 'warning' })
|
||||
}
|
||||
} else {
|
||||
swalFire({ text: getMessage('module.place.out'), icon: 'warning' })
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user