From d12a4a2e348a63c589179e56867070c640caec21 Mon Sep 17 00:00:00 2001 From: ysCha Date: Thu, 2 Jul 2026 14:21:26 +0900 Subject: [PATCH] =?UTF-8?q?[2316]=20=EB=B0=A9=EC=9C=84=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=2016=EB=B0=A9=EC=9C=84=ED=99=94(22.5=C2=B0=20?= =?UTF-8?q?=EA=B7=A0=EB=93=B1)=20+=20=EB=B6=81=EB=A9=B4=20=ED=8C=90?= =?UTF-8?q?=EC=A0=95=20=C2=B1135=C2=B0=20=EA=B3=A0=EC=A0=95(=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=EC=99=80=20=EB=B6=84=EB=A6=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 12 +++-- src/hooks/module/useTrestle.js | 7 +-- src/hooks/usePolygon.js | 61 +++++------------------ src/util/canvas-util.js | 18 +++++++ 4 files changed, 42 insertions(+), 56 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 2b93bd69..19afa043 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -14,7 +14,7 @@ import { toggleManualSetupModeState, } from '@/store/canvasAtom' -import { calculateVisibleModuleHeight, getDegreeByChon, polygonToTurfPolygon, rectToPolygon, toFixedWithoutRounding } from '@/util/canvas-util' +import { calculateVisibleModuleHeight, getDegreeByChon, getRoofAzimuthDeg, polygonToTurfPolygon, rectToPolygon, toFixedWithoutRounding } from '@/util/canvas-util' import '@/util/fabric-extensions' // fabric 객체들에 getCurrentPoints 메서드 추가 import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom' import offsetPolygon, { calculateAngle, cleanSelfIntersectingPolygon, clipOffsetToOriginal, createLinesFromPolygon } from '@/util/qpolygon-utils' @@ -422,8 +422,9 @@ export function useModuleBasicSetting(tabNum) { if (canvasSetting.roofSizeSet != '3') { //북면이 있지만 if (roof.directionText && roof.directionText.indexOf('北') > -1) { - //북쪽일때 해당 서북서, 동북동은 제외한다고 한다 - if (!(roof.directionText.indexOf('西北西') > -1 || roof.directionText.indexOf('東北東') > -1)) { + // [方位16分割 2026-07-02] 표시는 16방위지만 북면 판정은 종전 ±135°로 고정(일본 요청). + // 라벨 문자열(西北西/東北東) 제외가 아니라 실제 방위각으로 판정 → 124~134°는 北西/北東로 표시돼도 비북면. + if (Math.abs(getRoofAzimuthDeg(roof)) >= 135) { isNorth = true } } @@ -478,8 +479,9 @@ export function useModuleBasicSetting(tabNum) { if (canvasSetting.roofSizeSet != '3') { //북면이 있지만 if (roof.directionText && roof.directionText.indexOf('北') > -1) { - //북쪽일때 해당 서북서, 동북동은 제외한다고 한다 - if (!(roof.directionText.indexOf('西北西') > -1 || roof.directionText.indexOf('東北東') > -1)) { + // [方位16分割 2026-07-02] 표시는 16방위지만 북면 판정은 종전 ±135°로 고정(일본 요청). + // 라벨 문자열(西北西/東北東) 제외가 아니라 실제 방위각으로 판정 → 124~134°는 北西/北東로 표시돼도 비북면. + if (Math.abs(getRoofAzimuthDeg(roof)) >= 135) { isNorth = true } } diff --git a/src/hooks/module/useTrestle.js b/src/hooks/module/useTrestle.js index c13dc67f..81a96a2f 100644 --- a/src/hooks/module/useTrestle.js +++ b/src/hooks/module/useTrestle.js @@ -2,7 +2,7 @@ import { useRecoilValue } from 'recoil' import { canvasState, currentAngleTypeSelector, currentCanvasPlanState } from '@/store/canvasAtom' import { POLYGON_TYPE, TRESTLE_MATERIAL } from '@/common/common' import { moduleSelectionDataState } from '@/store/selectedModuleOptions' -import { getDegreeByChon } from '@/util/canvas-util' +import { getDegreeByChon, getRoofAzimuthDeg } from '@/util/canvas-util' import { v4 as uuidv4 } from 'uuid' import { useMasterController } from '@/hooks/common/useMasterController' import { basicSettingState, trestleDisplaySelector } from '@/store/settingAtom' @@ -926,8 +926,9 @@ export const useTrestle = () => { surfaces.forEach((surface) => { const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId) const directionText = parent.directionText - // ['西北西','東北東'] 의 경우를 제외하고는 北이 들어간 경우 전부 북면으로 간주 - if (directionText.includes('北') && !directionText.includes('西北西') && !directionText.includes('東北東')) { + // [方位16分割 2026-07-02] 표시는 16방위지만 북면 판정은 종전 ±135°로 고정(일본 요청). + // 라벨 문자열(西北西/東北東) 제외가 아니라 실제 방위각으로 판정 → 124~134°는 北西/北東로 표시돼도 비북면. + if (directionText && directionText.includes('北') && Math.abs(getRoofAzimuthDeg(parent)) >= 135) { if (surface.modules.length > 0) { northArrangement = '1' } diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 87769390..98596529 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -407,56 +407,21 @@ export const usePolygon = () => { // 각도 -90: 동, 남, 서, 북 // 각도 -135: 북동, 남동, 남서, 북서 - let mapping - // 정확한 각도 먼저 체크 - if (normalizedAngle === 0) { - mapping = { south: '南', west: '西', north: '北', east: '東' } - } else if (normalizedAngle === 45) { - mapping = { south: '南西', west: '北西', north: '北東', east: '南東' } - } else if (normalizedAngle === 90) { - mapping = { south: '西', west: '北', north: '東', east: '南' } - } else if (normalizedAngle === 135) { - mapping = { south: '北西', west: '北東', north: '南東', east: '南西' } - } else if (normalizedAngle === 180 || normalizedAngle === -180) { - mapping = { south: '北', west: '東', north: '南', east: '西' } - } else if (normalizedAngle === -45) { - mapping = { south: '南東', west: '南西', north: '北西', east: '北東' } - } else if (normalizedAngle === -90) { - mapping = { south: '東', west: '南', north: '西', east: '北' } - } else if (normalizedAngle === -135) { - mapping = { south: '北東', west: '南東', north: '南西', east: '北西' } - } - // 범위 각도 체크 - else if (normalizedAngle >= 1 && normalizedAngle <= 44) { - // 1~44: 남남서, 서북서, 북북동, 동남동 - mapping = { south: '南南西', west: '西北西', north: '北北東', east: '東南東' } - } else if (normalizedAngle >= 46 && normalizedAngle <= 89) { - // 46~89: 서남서, 북북서, 동북동, 남남동 - mapping = { south: '西南西', west: '北北西', north: '東北東', east: '南南東' } - } else if (normalizedAngle >= 91 && normalizedAngle <= 134) { - // 91~134: 서북서, 북북동, 동남동, 남남서 - mapping = { south: '西北西', west: '北北東', north: '東南東', east: '南南西' } - } else if (normalizedAngle >= 136 && normalizedAngle <= 179) { - // 136~179: 북북서, 동북동, 남남동, 서남서 - mapping = { south: '北北西', west: '東北東', north: '南南東', east: '西南西' } - } else if (normalizedAngle >= -44 && normalizedAngle <= -1) { - // -1~-44: 남남동, 서남서, 북북서, 동북동 - mapping = { south: '南南東', west: '西南西', north: '北北西', east: '東北東' } - } else if (normalizedAngle >= -89 && normalizedAngle <= -46) { - // -46~-89: 동남동, 남남서, 서북서, 북북동 - mapping = { south: '東南東', west: '南南西', north: '西北西', east: '北北東' } - } else if (normalizedAngle >= -134 && normalizedAngle <= -91) { - // -91~-134: 동북동, 남남동, 서남서, 북북서 - mapping = { south: '東北東', west: '南南東', north: '西南西', east: '北北西' } - } else if (normalizedAngle >= -179 && normalizedAngle <= -136) { - // -136~-179: 북북동, 동남동, 남남서, 서북서 - mapping = { south: '北北東', west: '東南東', north: '南南西', east: '西北西' } - } else { - // 기본값: 0도 - mapping = { south: '南', west: '西', north: '北', east: '東' } + // [方位16分割 2026-07-02] 표준 16방위(22.5° 균등, 정수 각도 기준)로 표시. + // 양수 각도: 남→남남서→남서→…→북 / 음수 각도: 남→남남동→남동→…→북 + const positive = ['南', '南南西', '南西', '西南西', '西', '西北西', '北西', '北北西', '北'] + const negative = ['南', '南南東', '南東', '東南東', '東', '東北東', '北東', '北北東', '北'] + const to16 = (deg) => { + let a = Math.round(deg) // 티켓: 정수 각도 기준 (소수 입력은 반올림) + while (a > 180) a -= 360 + while (a < -180) a += 360 + const i = Math.round(a / 22.5) // -8 ~ 8 + return i >= 0 ? positive[i] : negative[-i] } - return mapping[dir] || '南' + // direction(지붕면 흐름): 남(0) 기준 90° 회전 — 서 +90, 북 +180, 동 -90 + const offset = { south: 0, west: 90, north: 180, east: -90 } + return to16(normalizedAngle + (offset[dir] ?? 0)) } text = getDirectionText(moduleCompass, direction) diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index c97d4017..49cb72a7 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -272,6 +272,24 @@ export const getChonByDegree = (degree) => { return Number((Math.tan((degree * Math.PI) / 180) * 10).toFixed(2)) } +// [方位16分割 2026-07-02] 지붕면의 실제 방위각(南=0, +=서쪽, -180~180)을 저장 데이터에서 계산. +// 북면 판정을 라벨(directionText) 대신 각도로 하기 위함 — 16방위 표시로 라벨이 바뀌어도 +// 북면 판정 경계는 종전 ±135°로 고정(일본 요청). moduleCompass/surfaceCompass 두 경로 모두 커버. +const AZIMUTH_DIR_OFFSET = { south: 0, west: 90, north: 180, east: -90 } +export const getRoofAzimuthDeg = (roof) => { + const normalize = (deg) => { + let a = Number(deg) + while (a > 180) a -= 360 + while (a < -180) a += 360 + return a + } + // surfaceCompass(면별 유수방향)가 있으면 그 값이 곧 면의 방위각 + if (roof?.surfaceCompass !== null && roof?.surfaceCompass !== undefined) { + return normalize(roof.surfaceCompass) + } + return normalize(Number(roof?.moduleCompass ?? 0) + (AZIMUTH_DIR_OFFSET[roof?.direction] ?? 0)) +} + /** * 두 점 사이의 방향을 반환합니다. * @param a {fabric.Object} -- 2.47.2