diff --git a/src/components/header/Header.jsx b/src/components/header/Header.jsx index ef7dfa6c..2e9f297c 100644 --- a/src/components/header/Header.jsx +++ b/src/components/header/Header.jsx @@ -25,6 +25,7 @@ import { isObjectNotEmpty } from '@/util/common-utils' import { roofMaterialsAtom } from '@/store/settingAtom' import { useMasterController } from '@/hooks/common/useMasterController' import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting' +import { useSwal } from '@/hooks/useSwal' export const ToggleonMouse = (e, act, target) => { const listWrap = e.target.closest(target) @@ -75,6 +76,8 @@ export default function Header(props) { const [commonCode, setCommonCode] = useRecoilState(commonCodeState) const { promiseGet } = useAxios() + const { swalFire } = useSwal() + /** * 지붕재 목록 Header에서 조회 */ @@ -232,11 +235,32 @@ export default function Header(props) { key={`${menu.id}`} href={menu.url} replace={true} - onClick={() => { - // moveHome() - removeStuffRecoil(menu) - if (pathName === '/' && menu.id !== 8) { - window.location.reload() + onClick={(e) => { + + if(pathName === '/floor-plan') { + e.preventDefault() // 기본 네비게이션 방지 + e.stopPropagation() // 이벤트 전파 방지 + swalFire({ + text : getMessage(common.link.confirm), // 적절한 확인 메시지 + type : 'confirm', + confirmFn: () => { + // 확인 버튼 클릭 시 실행 + removeStuffRecoil(menu) + if (pathName === '/' && menu.id !== 8) { + window.location.reload() + } else { + router.push(menu.url) + } + router.push(menu.url) + } + }) + } else { + removeStuffRecoil(menu) + if (pathName === '/' && menu.id !== 8) { + window.location.reload() + } else { + router.push(menu.url) + } } }} > @@ -258,9 +282,24 @@ export default function Header(props) { scroll={false} href={m.url} replace={true} - onClick={() => { - removeStuffRecoil(m) - }} + onClick={(e) => { + if(pathName === '/floor-plan') { + e.preventDefault() // 기본 네비게이션 방지 + e.stopPropagation() // 이벤트 전파 방지 + swalFire({ + text: getMessage('common.link.confirm'), // 적절한 확인 메시지 + type: 'confirm', + confirmFn: () => { + // 확인 버튼 클릭 시 기존 로직 실행 + removeStuffRecoil(m) + router.push(m.url) + } + }) + } else { + removeStuffRecoil(m) + } + } + } > {getMessage(m.name)} diff --git a/src/hooks/common/useTurf.js b/src/hooks/common/useTurf.js new file mode 100644 index 00000000..6696cd0a --- /dev/null +++ b/src/hooks/common/useTurf.js @@ -0,0 +1,37 @@ +import * as turf from '@turf/turf' + +export const useTurf = () => { + /** + * 배치면 안에 있는지 확인 + * @param {*} squarePolygon + * @param {*} turfModuleSetupSurface + * @param spare + * @returns + */ + const checkModuleDisjointSurface = (squarePolygon, turfModuleSetupSurface, spare = 1) => { + // 표면 영역을 spare만큼 수동 확장 + const expandedSurface = { + type: 'Polygon', + coordinates: [ + turfModuleSetupSurface.geometry.coordinates[0].map(([x, y]) => { + // 각 점을 바깥쪽으로 2 단위씩 이동 + const coords = turfModuleSetupSurface.geometry.coordinates[0] + const centerX = coords.slice(0, -1).reduce((sum, [x, y]) => sum + x, 0) / (coords.length - 1) + const centerY = coords.slice(0, -1).reduce((sum, [x, y]) => sum + y, 0) / (coords.length - 1) + + return [x < centerX ? x - spare : x + spare, y < centerY ? y - spare : y + spare] + }), + ], + } + + const isWithin = turf.booleanContains(expandedSurface, squarePolygon) || turf.booleanWithin(squarePolygon, expandedSurface) + + const isContact = turf.booleanIntersects(squarePolygon, expandedSurface) && !turf.booleanOverlap(squarePolygon, expandedSurface) + + return isWithin || isContact + } + + return { + checkModuleDisjointSurface, + } +} diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 092c4e59..f4f8901b 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -34,6 +34,7 @@ import { isObjectNotEmpty } from '@/util/common-utils' import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle' import { useMode } from '@/hooks/useMode' import { usePolygon } from '@/hooks/usePolygon' +import { useTurf } from '@/hooks/common/useTurf' export function useModuleBasicSetting(tabNum) { const canvas = useRecoilValue(canvasState) @@ -62,6 +63,8 @@ export function useModuleBasicSetting(tabNum) { const setManualSetupMode = useSetRecoilState(toggleManualSetupModeState) const setModuleRowColArray = useSetRecoilState(moduleRowColArrayState) + const { checkModuleDisjointSurface } = useTurf() + useEffect(() => { return () => { //수동 설치시 초기화 @@ -517,6 +520,7 @@ export function useModuleBasicSetting(tabNum) { lockScalingX: true, // X 축 크기 조정 잠금 lockScalingY: true, // Y 축 크기 조정 잠금 name: POLYGON_TYPE.MODULE, + opacity: 0.85, } if (moduleSetupSurfaces.length !== 0) { @@ -758,21 +762,21 @@ export function useModuleBasicSetting(tabNum) { //여기서부턴 배치면 설치 외곽선 라인 // 위쪽 변에 스냅 if (Math.abs(smallTop - trestleTop) < trestleSnapDistance) { - tempModule.top = trestleTop + 1 + tempModule.top = trestleTop } // 아래쪽 변에 스냅 if (Math.abs(smallBottom - trestleBottom) < trestleSnapDistance) { - tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height - 1 + tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height } // 왼쪽변에 스냅 if (Math.abs(smallLeft - trestleLeft) < trestleSnapDistance) { - tempModule.left = trestleLeft + 1 + tempModule.left = trestleLeft } //오른쪽 변에 스냅 if (Math.abs(smallRight - trestleRight) < trestleSnapDistance) { - tempModule.left = trestleRight - tempModule.width - 1 + tempModule.left = trestleRight - tempModule.width } if (flowDirection === 'south' || flowDirection === 'north') { @@ -869,7 +873,7 @@ export function useModuleBasicSetting(tabNum) { if (!isIntersection) return tempModule.setCoords() //좌표 재정렬 - if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { + if (checkModuleDisjointSurface(tempTurfModule, turfPolygon)) { //마우스 클릭시 set으로 해당 위치에 셀을 넣음 const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module, true))) //겹치는지 확인 if (!isOverlap) { @@ -892,6 +896,7 @@ export function useModuleBasicSetting(tabNum) { }) canvas?.add(manualModule) + canvas.bringToFront(manualModule) manualDrawModules.push(manualModule) setModuleStatisticsData() @@ -990,6 +995,7 @@ export function useModuleBasicSetting(tabNum) { lockScalingX: true, // X 축 크기 조정 잠금 lockScalingY: true, // Y 축 크기 조정 잠금 name: POLYGON_TYPE.MODULE, + opacity: 0.85, } const objectsIncludeSurface = (turfModuleSetupSurface) => { @@ -1426,7 +1432,7 @@ export function useModuleBasicSetting(tabNum) { const tempTurfModule = polygonToTurfPolygon(tempModule) tempModule.setCoords() //좌표 재정렬 - if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { + if (checkModuleDisjointSurface(tempTurfModule, turfPolygon)) { //마우스 클릭시 set으로 해당 위치에 셀을 넣음 const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 if (!isOverlap) { @@ -1450,6 +1456,7 @@ export function useModuleBasicSetting(tabNum) { //오브젝트와 겹치지 않으면 넣는다 if (isDisjoint) { canvas?.add(manualModule) + canvas.bringToFront(manualModule) canvas?.renderAll() manualDrawModules.push(manualModule) setModuleStatisticsData() @@ -1874,6 +1881,8 @@ export function useModuleBasicSetting(tabNum) { lockScalingX: true, // X 축 크기 조정 잠금 lockScalingY: true, // Y 축 크기 조정 잠금 name: POLYGON_TYPE.MODULE, + //투명도 추가 + opacity: 0.85, } //선택된 지붕안에 오브젝트(도머, 개구등)이 있는지 확인하는 로직 포함되면 배열 반환 @@ -1892,15 +1901,20 @@ export function useModuleBasicSetting(tabNum) { return containsBatchObjects } + const addModule = (tempModule, moduleSetupArray, moduleArray) => { + canvas?.add(tempModule) + canvas.bringToFront(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + canvas.renderAll() + } + /** * 배치면 안에 있는지 확인 * @param {*} squarePolygon * @param {*} turfModuleSetupSurface * @returns */ - const checkModuleDisjointSurface = (squarePolygon, turfModuleSetupSurface) => { - return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface) - } /** * 자동 레이아웃 설치 일시 row col 초과 여부 확인 @@ -2091,10 +2105,10 @@ export function useModuleBasicSetting(tabNum) { const moduleArray = [] let calcAreaWidth = Math.abs(flowLines.right.x1 - flowLines.left.x1) //오른쪽 x에서 왼쪽 x를 뺀 가운데를 찾는 로직 - let calcModuleWidthCount = calcAreaWidth / (width + intvHor + 1) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1 - let calcModuleHeightCount = calcAreaHeight / (height + intvVer + 1) + let calcModuleHeightCount = calcAreaHeight / (height + intvVer) if (type === MODULE_SETUP_TYPE.LAYOUT) { calcModuleWidthCount = layoutCol > calcModuleWidthCount ? calcModuleWidthCount : layoutCol @@ -2124,7 +2138,7 @@ export function useModuleBasicSetting(tabNum) { for (let i = 0; i < calcModuleHeightCount; i++) { let isInstall = false - let moduleY = flowLines.bottom.y1 - height * i - 1 //살짝 여유를 준다 + let moduleY = flowLines.bottom.y1 - height * i //살짝 여유를 준다 //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 if (installedModuleHeightCount > 0) { @@ -2135,7 +2149,7 @@ export function useModuleBasicSetting(tabNum) { heightMargin = installedModuleHeightCount === 0 ? 0 : intvVer for (let j = 0; j < totalModuleWidthCount; j++) { - let moduleX = startPointX + width * j + 1 //5정도 마진을 준다 + let moduleX = startPointX + width * j //5정도 마진을 준다 widthMargin = j === 0 ? 0 : intvHor * j // 가로 마진값 chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 if (isChidori) { @@ -2170,10 +2184,7 @@ export function useModuleBasicSetting(tabNum) { if (disjointFromTrestle && isDisjoint) { //최초 한번은 그냥 그린다 //겹치는지 확인해서 포함된 모듈만 그린다 - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() + addModule(tempModule, moduleSetupArray, moduleArray) // ++installedModuleHeightCount @@ -2277,9 +2288,9 @@ export function useModuleBasicSetting(tabNum) { const moduleArray = [] let calcAreaWidth = flowLines.right.x1 - flowLines.left.x1 //오른쪽 x에서 왼쪽 x를 뺀 가운데를 찾는 로직 - let calcModuleWidthCount = calcAreaWidth / (width + intvHor + 1) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1 - let calcModuleHeightCount = calcAreaHeight / (height + intvVer + 1) + let calcModuleHeightCount = calcAreaHeight / (height + intvVer) //단수지정 자동이면 if (type === MODULE_SETUP_TYPE.LAYOUT) { @@ -2319,7 +2330,7 @@ export function useModuleBasicSetting(tabNum) { heightMargin = installedModuleHeightCount === 0 ? 0 : intvVer //모듈간에 마진이 있어 마진값도 넣음 for (let j = 0; j < totalModuleWidthCount; j++) { //모듈 열수 만큼 반복 - let moduleX = startPointX - width * j - 1 //시작점에서 우 -> 좌로 그려 내려간다 + let moduleX = startPointX - width * j //시작점에서 우 -> 좌로 그려 내려간다 widthMargin = j === 0 ? 0 : intvHor * j chidoriLength = 0 if (isChidori && !isMaxSetup) { @@ -2349,10 +2360,7 @@ export function useModuleBasicSetting(tabNum) { let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) if (disjointFromTrestle && isDisjoint) { - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() + addModule(tempModule, moduleSetupArray, moduleArray) isInstall = true @@ -2460,10 +2468,10 @@ export function useModuleBasicSetting(tabNum) { const moduleArray = [] - let calcAreaWidth = flowLines.bottom.y1 - flowLines.top.y1 //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직 - let calcModuleWidthCount = calcAreaWidth / (height + intvHor + 1) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 - let calcAreaHeight = flowLines.right.x1 - flowLines.left.x1 - let calcModuleHeightCount = calcAreaHeight / (width + intvVer + 1) + let calcAreaWidth = Math.abs(flowLines.bottom.y1 - flowLines.top.y1) //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직 + let calcModuleWidthCount = calcAreaWidth / (height + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcAreaHeight = Math.abs(flowLines.right.x1 - flowLines.left.x1) + let calcModuleHeightCount = calcAreaHeight / (width + intvVer) //단수지정 자동이면 if (type === MODULE_SETUP_TYPE.LAYOUT) { @@ -2490,12 +2498,12 @@ export function useModuleBasicSetting(tabNum) { //첫번재 모듈 설치 후 두번째 모듈을 몇개까지 설치 할 수 있는지 계산 if (moduleIndex > 0) { moduleMaxRows = totalModuleMaxRows - installedModuleHeightCount //두번째 모듈일때 - isChidoriLine = installedModuleHeightCount % 2 != 0 ? true : false //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 + isChidoriLine = installedModuleHeightCount % 2 !== 0 //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 } for (let i = 0; i < calcModuleHeightCount; i++) { let isInstall = false - let moduleY = flowLines.left.x1 + width * i + 1 //살짝 여유를 준다 + let moduleY = flowLines.left.x1 + width * i //살짝 여유를 준다 //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 if (installedModuleHeightCount > 0) { @@ -2506,11 +2514,11 @@ export function useModuleBasicSetting(tabNum) { heightMargin = installedModuleHeightCount === 0 ? 0 : intvHor for (let j = 0; j < totalModuleWidthCount; j++) { - let moduleX = startPointX + height * j + 1 //5정도 마진을 준다 + let moduleX = startPointX + height * j //5정도 마진을 준다 widthMargin = j === 0 ? 0 : intvVer * j // 가로 마진값 chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 if (isChidori && !isMaxSetup) { - chidoriLength = installedModuleHeightCount % 2 == 0 ? 0 : height / 2 - intvVer + chidoriLength = installedModuleHeightCount % 2 === 0 ? 0 : height / 2 - intvVer } let square = [ @@ -2527,17 +2535,14 @@ export function useModuleBasicSetting(tabNum) { moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) - - let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + let turfSurface = polygonToTurfPolygon(moduleSetupSurface, true) + let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, turfSurface) let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) if (disjointFromTrestle && isDisjoint) { //최초 한번은 그냥 그린다 //겹치는지 확인해서 포함된 모듈만 그린다 - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() + addModule(tempModule, moduleSetupArray, moduleArray) // ++installedModuleHeightCount @@ -2546,9 +2551,9 @@ export function useModuleBasicSetting(tabNum) { installedLastHeightCoord = moduleY + width + widthMargin } else { //디버깅용 - // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) - // canvas?.add(tempModule) - // canvas.renderAll() + /*tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + canvas?.add(tempModule) + canvas.renderAll()*/ } } @@ -2643,9 +2648,9 @@ export function useModuleBasicSetting(tabNum) { const moduleArray = [] let calcAreaWidth = flowLines.bottom.y1 - flowLines.top.y1 //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직 - let calcModuleWidthCount = calcAreaWidth / (height + intvHor + 1) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcModuleWidthCount = calcAreaWidth / (height + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 let calcAreaHeight = flowLines.right.x1 - flowLines.left.x1 - let calcModuleHeightCount = calcAreaHeight / (width + intvVer + 1) + let calcModuleHeightCount = calcAreaHeight / (width + intvVer) //단수지정 자동이면 if (type === MODULE_SETUP_TYPE.LAYOUT) { @@ -2677,7 +2682,7 @@ export function useModuleBasicSetting(tabNum) { for (let i = 0; i < calcModuleHeightCount; i++) { let isInstall = false - let moduleY = flowLines.right.x1 - width * i - 1 //살짝 여유를 준다 + let moduleY = flowLines.right.x1 - width * i //살짝 여유를 준다 //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 if (installedModuleHeightCount > 0) { @@ -2688,7 +2693,7 @@ export function useModuleBasicSetting(tabNum) { heightMargin = installedModuleHeightCount === 0 ? 0 : intvHor for (let j = 0; j < totalModuleWidthCount; j++) { - let moduleX = startPointX - height * j - 1 //5정도 마진을 준다 + let moduleX = startPointX - height * j //5정도 마진을 준다 widthMargin = j === 0 ? 0 : intvVer * j // 가로 마진값 chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 if (isChidori && !isMaxSetup) { @@ -2721,10 +2726,7 @@ export function useModuleBasicSetting(tabNum) { if (disjointFromTrestle && isDisjoint) { //최초 한번은 그냥 그린다 //겹치는지 확인해서 포함된 모듈만 그린다 - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() + addModule(tempModule, moduleSetupArray, moduleArray) isInstall = true //마지막에 설치된 모듈의 Y 좌표 @@ -3414,21 +3416,21 @@ export function useModuleBasicSetting(tabNum) { // 위쪽 변에 스냅 if (Math.abs(smallTop - trestleTop) < trestleSnapDistance) { - tempModule.top = trestleTop + 1 + tempModule.top = trestleTop } // 아래쪽 변에 스냅 if (Math.abs(smallBottom - trestleBottom) < trestleSnapDistance) { - tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height - 1 + tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height } // 왼쪽변에 스냅 if (Math.abs(smallLeft - trestleLeft) < trestleSnapDistance) { - tempModule.left = trestleLeft + 1 + tempModule.left = trestleLeft } //오른쪽 변에 스냅 if (Math.abs(smallRight - trestleRight) < trestleSnapDistance) { - tempModule.left = trestleRight - tempModule.width - 1 + tempModule.left = trestleRight - tempModule.width } if (flowDirection === 'south' || flowDirection === 'north') { @@ -3705,16 +3707,6 @@ export function useModuleBasicSetting(tabNum) { return containsBatchObjects } - /** - * 배치면 안에 있는지 확인 - * @param {*} squarePolygon - * @param {*} turfModuleSetupSurface - * @returns - */ - const checkModuleDisjointSurface = (squarePolygon, turfModuleSetupSurface) => { - return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface) - } - const flatRoofDownFlowSetupModule = ( surfaceMaxLines, maxLengthLine, diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index 31f88221..69defd9d 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -68,6 +68,8 @@ export function useRoofShapeSetting(id) { const globalLocaleState = useRecoilValue(globalLocaleStore) const { post } = useAxios(globalLocaleState) + const { addLine, removeLine } = useLine() + useEffect(() => { pitchRef.current = currentAngleType === ANGLE_TYPE.SLOPE ? pitch : getChonByDegree(pitch) }, [pitch]) @@ -182,6 +184,41 @@ export function useRoofShapeSetting(id) { return } + /** + * 외벽선이 시계방향인지 시계반대 방향인지 확인 + */ + const outerLinePoints = outerLines.map((line) => ({ x: line.x1, y: line.y1 })) + let counterClockwise = true + let signedArea = 0 + + outerLinePoints.forEach((point, index) => { + const nextPoint = outerLinePoints[(index + 1) % outerLinePoints.length] + signedArea += point.x * nextPoint.y - point.y * nextPoint.x + }) + + if (signedArea > 0) { + counterClockwise = false + } + /** 시계 방향일 경우 외벽선 reverse*/ + if (!counterClockwise) { + outerLines.reverse().forEach((line, index) => { + addLine([line.x2, line.y2, line.x1, line.y1], { + stroke: line.stroke, + strokeWidth: line.strokeWidth, + idx: index, + selectable: line.selectable, + name: 'outerLine', + x1: line.x2, + y1: line.y2, + x2: line.x1, + y2: line.y1, + visible: line.visible, + }) + canvas.remove(line) + }) + canvas.renderAll() + } + if ([1, 2, 3, 5, 6, 7, 8].includes(shapeNum)) { // 변별로 설정이 아닌 경우 경사를 지붕재에 적용해주어야함 setRoofPitch() diff --git a/src/locales/ja.json b/src/locales/ja.json index 8629e287..f27b8d7f 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -565,6 +565,7 @@ "commons.north": "北", "commons.none": "選択しない", "common.type": "分類", + "common.link.confirm": "移動しますか?", "font.style.normal": "通常", "font.style.italic": "イタリック体", "font.style.bold": "太字", diff --git a/src/locales/ko.json b/src/locales/ko.json index 62b60350..3dd00617 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -565,6 +565,7 @@ "commons.north": "북", "commons.none": "선택안함", "common.type": "분류", + "common.link.confirm": "이동 하시겠습니까?", "font.style.normal": "보통", "font.style.italic": "기울임꼴", "font.style.bold": "굵게", diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 2b5c21e4..231a511b 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -2555,7 +2555,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { { x: currentRoof.x2, y: currentRoof.y2 }, ] const prevHipLines = [] - const nextHipLine = [] + const nextHipLines = [] let prevLineRidge, nextLineRidge baseHipLines.forEach((current) => { @@ -2584,7 +2584,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { y: line.y1, })) ) { - nextHipLine.push(current) + nextHipLines.push(current) } }) prevHipLines.forEach((current) => { @@ -2633,7 +2633,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { }) } }) - nextHipLine.forEach((current) => { + nextHipLines.forEach((current) => { if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { let findPoint if (Math.abs(current.x1 - currentRoof.x2) <= 1 && Math.abs(current.y1 - currentRoof.y2) <= 1) { @@ -2740,235 +2740,236 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { /** 4각*/ if (prevLineRidge === nextLineRidge) { polygonPoints.push({ x: ridgeLine.x1, y: ridgeLine.y1 }, { x: ridgeLine.x2, y: ridgeLine.y2 }) - } - /** 6각이상*/ - let isOverLap = - currentVectorX === 0 - ? (prevLineRidge.y1 <= nextLineRidge.y1 && prevLineRidge.y2 >= nextLineRidge.y1) || - (prevLineRidge.y1 >= nextLineRidge.y1 && prevLineRidge.y2 <= nextLineRidge.y1) || - (prevLineRidge.y1 <= nextLineRidge.y2 && prevLineRidge.y2 >= nextLineRidge.y2) || - (prevLineRidge.y1 >= nextLineRidge.y2 && prevLineRidge.y2 <= nextLineRidge.y2) - : (prevLineRidge.x1 <= nextLineRidge.x1 && prevLineRidge.x2 >= nextLineRidge.x1) || - (prevLineRidge.x1 >= nextLineRidge.x1 && prevLineRidge.x2 <= nextLineRidge.x1) || - (prevLineRidge.x1 <= nextLineRidge.x2 && prevLineRidge.x2 >= nextLineRidge.x2) || - (prevLineRidge.x1 >= nextLineRidge.x2 && prevLineRidge.x2 <= nextLineRidge.x2) - if (isOverLap) { - const prevDistance = currentVectorX === 0 ? Math.abs(prevLineRidge.x1 - currentRoof.x1) : Math.abs(prevLineRidge.y1 - currentRoof.y1) - const nextDistance = currentVectorX === 0 ? Math.abs(nextLineRidge.x1 - currentRoof.x1) : Math.abs(nextLineRidge.y1 - currentRoof.y1) - - /** 현재 지붕 라인과 먼 라인의 포인트를 온전히 사용한다. */ - if (Math.abs(prevDistance - nextDistance) < 1) { - const minX = Math.min(currentRoof.x1, currentRoof.x2, currentLine.x1, currentLine.x2) - const maxX = Math.max(currentRoof.x1, currentRoof.x2, currentLine.x1, currentLine.x2) - const minY = Math.min(currentRoof.y1, currentRoof.y2, currentLine.y1, currentLine.y2) - const maxY = Math.max(currentRoof.y1, currentRoof.y2, currentLine.y1, currentLine.y2) - if (currentVectorX === 0) { - polygonPoints.push({ x: prevLineRidge.x1, y: minY }, { x: prevLineRidge.x1, y: maxY }) - } else { - polygonPoints.push({ x: minX, y: prevLineRidge.y1 }, { x: maxX, y: prevLineRidge.y1 }) - } - } else if (prevDistance < nextDistance) { - polygonPoints.push({ x: nextLineRidge.x1, y: nextLineRidge.y1 }, { x: nextLineRidge.x2, y: nextLineRidge.y2 }) - - /** 이전라인과 교차한 마루의 포인트*/ - let prevRidgePoint1 - if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - prevRidgePoint1 = polygonPoints.find( - (point) => - (point.x === prevLineRidge.x1 && point.y === prevLineRidge.y1) || (point.x === prevLineRidge.x2 && point.y === prevLineRidge.y2), - ) - } else { - prevRidgePoint1 = - currentVectorX === 0 - ? currentRoof.y1 === prevLineRidge.y1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - : currentRoof.x1 === prevLineRidge.x1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - - polygonPoints.push(prevRidgePoint1) - } - - /** 다음 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/ - let checkRidgePoint - if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - const ridgePoint1 = polygonPoints.filter((point) => point.x === nextLineRidge.x1 && point.y === nextLineRidge.y1) - checkRidgePoint = ridgePoint1.length > 0 ? { x: nextLineRidge.x2, y: nextLineRidge.y2 } : { x: nextLineRidge.x1, y: nextLineRidge.y1 } - } else { - checkRidgePoint = - currentVectorX === 0 - ? currentRoof.y2 !== nextLineRidge.y1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - : currentRoof.x2 !== nextLineRidge.x1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - } - - const prevRidgePoint2 = - currentVectorX === 0 ? { x: prevRidgePoint1.x, y: checkRidgePoint.y } : { x: checkRidgePoint.x, y: prevRidgePoint1.y } - polygonPoints.push(prevRidgePoint2) - } else { - polygonPoints.push({ x: prevLineRidge.x1, y: prevLineRidge.y1 }, { x: prevLineRidge.x2, y: prevLineRidge.y2 }) - - /** 다음라인과 교차한 마루의 포인트*/ - let nextRidgePoint1 - if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - nextRidgePoint1 = polygonPoints.find( - (point) => - (point.x === nextLineRidge.x1 && point.y === nextLineRidge.y1) || (point.x === nextLineRidge.x2 && point.y === nextLineRidge.y2), - ) - } else { - nextRidgePoint1 = - currentVectorX === 0 - ? currentRoof.y2 === nextLineRidge.y1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - : currentRoof.x2 === nextLineRidge.x1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - polygonPoints.push(nextRidgePoint1) - } - - /** 이전 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/ - let checkRidgePoint - if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - const ridgePoint1 = polygonPoints.filter((point) => point.x === prevLineRidge.x1 && point.y === prevLineRidge.y1) - checkRidgePoint = ridgePoint1.length > 0 ? { x: prevLineRidge.x2, y: prevLineRidge.y2 } : { x: prevLineRidge.x1, y: prevLineRidge.y1 } - } else { - checkRidgePoint = - currentVectorX === 0 - ? currentRoof.y1 !== prevLineRidge.y1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - : currentRoof.x1 !== prevLineRidge.x1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - } - - const nextRidgePoint2 = - currentVectorX === 0 ? { x: nextRidgePoint1.x, y: checkRidgePoint.y } : { x: checkRidgePoint.x, y: nextRidgePoint1.y } - polygonPoints.push(nextRidgePoint2) - } } else { - /** 마루가 겹치지 않을때 */ - const otherRidgeLines = [] + /** 6각이상*/ + let isOverLap = + currentVectorX === 0 + ? (prevLineRidge.y1 <= nextLineRidge.y1 && prevLineRidge.y2 >= nextLineRidge.y1) || + (prevLineRidge.y1 >= nextLineRidge.y1 && prevLineRidge.y2 <= nextLineRidge.y1) || + (prevLineRidge.y1 <= nextLineRidge.y2 && prevLineRidge.y2 >= nextLineRidge.y2) || + (prevLineRidge.y1 >= nextLineRidge.y2 && prevLineRidge.y2 <= nextLineRidge.y2) + : (prevLineRidge.x1 <= nextLineRidge.x1 && prevLineRidge.x2 >= nextLineRidge.x1) || + (prevLineRidge.x1 >= nextLineRidge.x1 && prevLineRidge.x2 <= nextLineRidge.x1) || + (prevLineRidge.x1 <= nextLineRidge.x2 && prevLineRidge.x2 >= nextLineRidge.x2) || + (prevLineRidge.x1 >= nextLineRidge.x2 && prevLineRidge.x2 <= nextLineRidge.x2) + if (isOverLap) { + const prevDistance = currentVectorX === 0 ? Math.abs(prevLineRidge.x1 - currentRoof.x1) : Math.abs(prevLineRidge.y1 - currentRoof.y1) + const nextDistance = currentVectorX === 0 ? Math.abs(nextLineRidge.x1 - currentRoof.x1) : Math.abs(nextLineRidge.y1 - currentRoof.y1) - baseGableRidgeLines - .filter((ridge) => ridge !== prevLineRidge && ridge !== nextLineRidge) - .filter((ridge) => (currentVectorX === 0 ? ridge.x1 === ridge.x2 : ridge.y1 === ridge.y2)) - .filter((ridge) => - currentVectorX === 0 ? nextVectorX === Math.sign(nextLine.x1 - ridge.x1) : nextVectorY === Math.sign(nextLine.y1 - ridge.y1), - ) - .forEach((ridge) => { - const size = currentVectorX === 0 ? Math.abs(nextLine.x1 - ridge.x1) : Math.abs(nextLine.y1 - ridge.y1) - otherRidgeLines.push({ ridge, size }) - }) - if (otherRidgeLines.length > 0) { - const otherRidge = otherRidgeLines.sort((a, b) => a.size - b.size)[0].ridge - /** - * otherRidge이 prevRidgeLine, nextRidgeLine 과 currentLine의 사이에 있는지 확인해서 분할하여 작업 - * 지붕의 덮힘이 다르기 때문 - */ - const isInside = - currentVectorX === 0 - ? Math.abs(currentLine.x1 - otherRidge.x1) < Math.abs(currentLine.x1 - prevLineRidge.x1) && - Math.abs(currentLine.x1 - otherRidge.x1) < Math.abs(currentLine.x1 - nextLineRidge.x1) - : Math.abs(currentLine.y1 - otherRidge.y1) < Math.abs(currentLine.y1 - prevLineRidge.y1) && - Math.abs(currentLine.y1 - otherRidge.y1) < Math.abs(currentLine.y1 - nextLineRidge.y1) - - if (isInside) { - polygonPoints.push( - { x: prevLineRidge.x1, y: prevLineRidge.y1 }, - { x: prevLineRidge.x2, y: prevLineRidge.y2 }, - { x: nextLineRidge.x1, y: nextLineRidge.y1 }, - { x: nextLineRidge.x2, y: nextLineRidge.y2 }, - ) - - let ridgeAllPoints = [ - { x: prevLineRidge.x1, y: prevLineRidge.y1 }, - { x: prevLineRidge.x2, y: prevLineRidge.y2 }, - { x: nextLineRidge.x1, y: nextLineRidge.y1 }, - { x: nextLineRidge.x2, y: nextLineRidge.y2 }, - ] - let ridgePoints = [] - ridgeAllPoints.forEach((point) => { - let isOnLine = false - roof.lines.forEach((line) => { - if (isPointOnLine({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }, point)) { - isOnLine = true - } - }) - if (!isOnLine) { - ridgePoints.push(point) - } - }) - if (ridgePoints.length === 2) { - if (Math.sign(otherRidge.x1 - otherRidge.x2) === 0) { - polygonPoints.push( - { x: otherRidge.x1, y: ridgePoints[0].y }, - { - x: otherRidge.x1, - y: ridgePoints[1].y, - }, - ) - } else { - polygonPoints.push( - { x: ridgePoints[0].x, y: otherRidge.y1 }, - { - x: ridgePoints[1].x, - y: otherRidge.y1, - }, - ) - } - } - } else { - polygonPoints.push({ x: otherRidge.x1, y: otherRidge.y1 }, { x: otherRidge.x2, y: otherRidge.y2 }) - - let ridgePoints = [ - { x: prevLineRidge.x1, y: prevLineRidge.y1 }, - { x: prevLineRidge.x2, y: prevLineRidge.y2 }, - { x: nextLineRidge.x1, y: nextLineRidge.y1 }, - { x: nextLineRidge.x2, y: nextLineRidge.y2 }, - ] - - ridgePoints.forEach((point) => { - let isOnLine = false - roof.lines.forEach((line) => { - if (isPointOnLine({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }, point)) { - isOnLine = true - } - }) - if (isOnLine) { - polygonPoints.push(point) - } - }) - - if (Math.sign(otherRidge.x1 - otherRidge.x2) === 0) { - const prevY = - (prevLineRidge.y1 <= otherRidge.y1 && otherRidge.y1 <= prevLineRidge.y2) || - (prevLineRidge.y1 >= otherRidge.y1 && otherRidge.y1 >= prevLineRidge.y2) - ? otherRidge.y1 - : otherRidge.y2 - const nextY = - (nextLineRidge.y1 <= otherRidge.y1 && otherRidge.y1 <= nextLineRidge.y2) || - (nextLineRidge.y1 >= otherRidge.y1 && otherRidge.y1 >= nextLineRidge.y2) - ? otherRidge.y1 - : otherRidge.y2 - polygonPoints.push({ x: prevLineRidge.x1, y: prevY }, { x: nextLineRidge.x1, y: nextY }) + /** 현재 지붕 라인과 먼 라인의 포인트를 온전히 사용한다. */ + if (Math.abs(prevDistance - nextDistance) < 1) { + const minX = Math.min(currentRoof.x1, currentRoof.x2, currentLine.x1, currentLine.x2) + const maxX = Math.max(currentRoof.x1, currentRoof.x2, currentLine.x1, currentLine.x2) + const minY = Math.min(currentRoof.y1, currentRoof.y2, currentLine.y1, currentLine.y2) + const maxY = Math.max(currentRoof.y1, currentRoof.y2, currentLine.y1, currentLine.y2) + if (currentVectorX === 0) { + polygonPoints.push({ x: prevLineRidge.x1, y: minY }, { x: prevLineRidge.x1, y: maxY }) } else { - const prevX = - (prevLineRidge.x1 <= otherRidge.x1 && otherRidge.x1 <= prevLineRidge.x2) || - (prevLineRidge.x1 >= otherRidge.x1 && otherRidge.x1 >= prevLineRidge.x2) - ? otherRidge.x1 - : otherRidge.x2 - const nextX = - (nextLineRidge.x1 <= otherRidge.x1 && otherRidge.x1 <= nextLineRidge.x2) || - (nextLineRidge.x1 >= otherRidge.x1 && otherRidge.x1 >= nextLineRidge.x2) - ? otherRidge.x1 - : otherRidge.x2 - polygonPoints.push({ x: prevX, y: prevLineRidge.y1 }, { x: nextX, y: nextLineRidge.y1 }) + polygonPoints.push({ x: minX, y: prevLineRidge.y1 }, { x: maxX, y: prevLineRidge.y1 }) + } + } else if (prevDistance < nextDistance) { + polygonPoints.push({ x: nextLineRidge.x1, y: nextLineRidge.y1 }, { x: nextLineRidge.x2, y: nextLineRidge.y2 }) + + /** 이전라인과 교차한 마루의 포인트*/ + let prevRidgePoint1 + if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { + prevRidgePoint1 = polygonPoints.find( + (point) => + (point.x === prevLineRidge.x1 && point.y === prevLineRidge.y1) || (point.x === prevLineRidge.x2 && point.y === prevLineRidge.y2), + ) + } else { + prevRidgePoint1 = + currentVectorX === 0 + ? currentRoof.y1 === prevLineRidge.y1 + ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } + : { x: prevLineRidge.x2, y: prevLineRidge.y2 } + : currentRoof.x1 === prevLineRidge.x1 + ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } + : { x: prevLineRidge.x2, y: prevLineRidge.y2 } + + polygonPoints.push(prevRidgePoint1) + } + + /** 다음 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/ + let checkRidgePoint + if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { + const ridgePoint1 = polygonPoints.filter((point) => point.x === nextLineRidge.x1 && point.y === nextLineRidge.y1) + checkRidgePoint = ridgePoint1.length > 0 ? { x: nextLineRidge.x2, y: nextLineRidge.y2 } : { x: nextLineRidge.x1, y: nextLineRidge.y1 } + } else { + checkRidgePoint = + currentVectorX === 0 + ? currentRoof.y2 !== nextLineRidge.y1 + ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } + : { x: nextLineRidge.x2, y: nextLineRidge.y2 } + : currentRoof.x2 !== nextLineRidge.x1 + ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } + : { x: nextLineRidge.x2, y: nextLineRidge.y2 } + } + + const prevRidgePoint2 = + currentVectorX === 0 ? { x: prevRidgePoint1.x, y: checkRidgePoint.y } : { x: checkRidgePoint.x, y: prevRidgePoint1.y } + polygonPoints.push(prevRidgePoint2) + } else { + polygonPoints.push({ x: prevLineRidge.x1, y: prevLineRidge.y1 }, { x: prevLineRidge.x2, y: prevLineRidge.y2 }) + + /** 다음라인과 교차한 마루의 포인트*/ + let nextRidgePoint1 + if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { + nextRidgePoint1 = polygonPoints.find( + (point) => + (point.x === nextLineRidge.x1 && point.y === nextLineRidge.y1) || (point.x === nextLineRidge.x2 && point.y === nextLineRidge.y2), + ) + } else { + nextRidgePoint1 = + currentVectorX === 0 + ? currentRoof.y2 === nextLineRidge.y1 + ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } + : { x: nextLineRidge.x2, y: nextLineRidge.y2 } + : currentRoof.x2 === nextLineRidge.x1 + ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } + : { x: nextLineRidge.x2, y: nextLineRidge.y2 } + polygonPoints.push(nextRidgePoint1) + } + + /** 이전 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/ + let checkRidgePoint + if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { + const ridgePoint1 = polygonPoints.filter((point) => point.x === prevLineRidge.x1 && point.y === prevLineRidge.y1) + checkRidgePoint = ridgePoint1.length > 0 ? { x: prevLineRidge.x2, y: prevLineRidge.y2 } : { x: prevLineRidge.x1, y: prevLineRidge.y1 } + } else { + checkRidgePoint = + currentVectorX === 0 + ? currentRoof.y1 !== prevLineRidge.y1 + ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } + : { x: prevLineRidge.x2, y: prevLineRidge.y2 } + : currentRoof.x1 !== prevLineRidge.x1 + ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } + : { x: prevLineRidge.x2, y: prevLineRidge.y2 } + } + + const nextRidgePoint2 = + currentVectorX === 0 ? { x: nextRidgePoint1.x, y: checkRidgePoint.y } : { x: checkRidgePoint.x, y: nextRidgePoint1.y } + polygonPoints.push(nextRidgePoint2) + } + } else { + /** 마루가 겹치지 않을때 */ + const otherRidgeLines = [] + + baseGableRidgeLines + .filter((ridge) => ridge !== prevLineRidge && ridge !== nextLineRidge) + .filter((ridge) => (currentVectorX === 0 ? ridge.x1 === ridge.x2 : ridge.y1 === ridge.y2)) + .filter((ridge) => + currentVectorX === 0 ? nextVectorX === Math.sign(nextLine.x1 - ridge.x1) : nextVectorY === Math.sign(nextLine.y1 - ridge.y1), + ) + .forEach((ridge) => { + const size = currentVectorX === 0 ? Math.abs(nextLine.x1 - ridge.x1) : Math.abs(nextLine.y1 - ridge.y1) + otherRidgeLines.push({ ridge, size }) + }) + if (otherRidgeLines.length > 0) { + const otherRidge = otherRidgeLines.sort((a, b) => a.size - b.size)[0].ridge + /** + * otherRidge이 prevRidgeLine, nextRidgeLine 과 currentLine의 사이에 있는지 확인해서 분할하여 작업 + * 지붕의 덮힘이 다르기 때문 + */ + const isInside = + currentVectorX === 0 + ? Math.abs(currentLine.x1 - otherRidge.x1) < Math.abs(currentLine.x1 - prevLineRidge.x1) && + Math.abs(currentLine.x1 - otherRidge.x1) < Math.abs(currentLine.x1 - nextLineRidge.x1) + : Math.abs(currentLine.y1 - otherRidge.y1) < Math.abs(currentLine.y1 - prevLineRidge.y1) && + Math.abs(currentLine.y1 - otherRidge.y1) < Math.abs(currentLine.y1 - nextLineRidge.y1) + + if (isInside) { + polygonPoints.push( + { x: prevLineRidge.x1, y: prevLineRidge.y1 }, + { x: prevLineRidge.x2, y: prevLineRidge.y2 }, + { x: nextLineRidge.x1, y: nextLineRidge.y1 }, + { x: nextLineRidge.x2, y: nextLineRidge.y2 }, + ) + + let ridgeAllPoints = [ + { x: prevLineRidge.x1, y: prevLineRidge.y1 }, + { x: prevLineRidge.x2, y: prevLineRidge.y2 }, + { x: nextLineRidge.x1, y: nextLineRidge.y1 }, + { x: nextLineRidge.x2, y: nextLineRidge.y2 }, + ] + let ridgePoints = [] + ridgeAllPoints.forEach((point) => { + let isOnLine = false + roof.lines.forEach((line) => { + if (isPointOnLine({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }, point)) { + isOnLine = true + } + }) + if (!isOnLine) { + ridgePoints.push(point) + } + }) + if (ridgePoints.length === 2) { + if (Math.sign(otherRidge.x1 - otherRidge.x2) === 0) { + polygonPoints.push( + { x: otherRidge.x1, y: ridgePoints[0].y }, + { + x: otherRidge.x1, + y: ridgePoints[1].y, + }, + ) + } else { + polygonPoints.push( + { x: ridgePoints[0].x, y: otherRidge.y1 }, + { + x: ridgePoints[1].x, + y: otherRidge.y1, + }, + ) + } + } + } else { + polygonPoints.push({ x: otherRidge.x1, y: otherRidge.y1 }, { x: otherRidge.x2, y: otherRidge.y2 }) + + let ridgePoints = [ + { x: prevLineRidge.x1, y: prevLineRidge.y1 }, + { x: prevLineRidge.x2, y: prevLineRidge.y2 }, + { x: nextLineRidge.x1, y: nextLineRidge.y1 }, + { x: nextLineRidge.x2, y: nextLineRidge.y2 }, + ] + + ridgePoints.forEach((point) => { + let isOnLine = false + roof.lines.forEach((line) => { + if (isPointOnLine({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }, point)) { + isOnLine = true + } + }) + if (isOnLine) { + polygonPoints.push(point) + } + }) + + if (Math.sign(otherRidge.x1 - otherRidge.x2) === 0) { + const prevY = + (prevLineRidge.y1 <= otherRidge.y1 && otherRidge.y1 <= prevLineRidge.y2) || + (prevLineRidge.y1 >= otherRidge.y1 && otherRidge.y1 >= prevLineRidge.y2) + ? otherRidge.y1 + : otherRidge.y2 + const nextY = + (nextLineRidge.y1 <= otherRidge.y1 && otherRidge.y1 <= nextLineRidge.y2) || + (nextLineRidge.y1 >= otherRidge.y1 && otherRidge.y1 >= nextLineRidge.y2) + ? otherRidge.y1 + : otherRidge.y2 + polygonPoints.push({ x: prevLineRidge.x1, y: prevY }, { x: nextLineRidge.x1, y: nextY }) + } else { + const prevX = + (prevLineRidge.x1 <= otherRidge.x1 && otherRidge.x1 <= prevLineRidge.x2) || + (prevLineRidge.x1 >= otherRidge.x1 && otherRidge.x1 >= prevLineRidge.x2) + ? otherRidge.x1 + : otherRidge.x2 + const nextX = + (nextLineRidge.x1 <= otherRidge.x1 && otherRidge.x1 <= nextLineRidge.x2) || + (nextLineRidge.x1 >= otherRidge.x1 && otherRidge.x1 >= nextLineRidge.x2) + ? otherRidge.x1 + : otherRidge.x2 + polygonPoints.push({ x: prevX, y: prevLineRidge.y1 }, { x: nextX, y: nextLineRidge.y1 }) + } } } } @@ -3043,13 +3044,11 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } const intersection = edgesIntersection(checkEdge, lineEdge) if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } + intersectionRoofs.push({ + line, + intersection, + size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), + }) } }) } else { @@ -3063,13 +3062,11 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } const intersection = edgesIntersection(checkEdge, lineEdge) if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } + intersectionRoofs.push({ + line, + intersection, + size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), + }) } }) }