From 4d95904cbf5c9819130cdf1112d589fe007c774c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?junh=5Feee=28=EC=9D=B4=EC=A4=80=ED=9D=AC=29?= Date: Fri, 27 Oct 2023 16:56:25 +0900 Subject: [PATCH 1/2] =?UTF-8?q?laanc=20=EB=B9=84=ED=96=89=EA=B5=AC?= =?UTF-8?q?=EC=97=AD=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95=20=EB=B0=8F?= =?UTF-8?q?=20=EB=B9=84=EA=B0=80=EC=8B=9C=EA=B6=8C=20=EB=AC=B8=EA=B5=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../map/mapbox/draw/LaancDrawControl.js | 426 ++++++++---------- src/utility/DrawUtil.js | 2 + 2 files changed, 188 insertions(+), 240 deletions(-) diff --git a/src/components/map/mapbox/draw/LaancDrawControl.js b/src/components/map/mapbox/draw/LaancDrawControl.js index 0df5082..827b9d3 100644 --- a/src/components/map/mapbox/draw/LaancDrawControl.js +++ b/src/components/map/mapbox/draw/LaancDrawControl.js @@ -50,7 +50,7 @@ export const LaancDrawControl = props => { const modeArr = [DrawLineStringMode, DrawPolygonMode, DrawCircleMode]; modeArr.forEach(m => { - m.onStop = state => handlerDblClickFinish(state); + m.onStop = state => handlerFinishDraw(state); // onClick 이벤트 오버라이드 const origin = m.onClick; @@ -77,19 +77,19 @@ export const LaancDrawControl = props => { const handlerCustomOnClick = (state, e) => { console.log('click'); - const type = handlerReturnMode(drawObj.getMode()); - const obj = state[type?.toLowerCase()]; + const mode = handlerReturnMode(drawObj.getMode()); + const obj = state[mode?.toLowerCase()]; - if (type && obj) { + if (mode && obj) { const feature = drawObj.get(obj.id); - const coordinates = feature.geometry.coordinates; - if (type !== 'CIRCLE') { + const initCoords = feature.geometry.coordinates; + if (mode !== 'CIRCLE') { if (state.currentVertexPosition > 1) { const coords = [ ...new Set( - type === 'LINE' - ? coordinates.map(JSON.stringify) - : coordinates[0].map(JSON.stringify) + mode === 'LINE' + ? initCoords.map(JSON.stringify) + : initCoords[0].map(JSON.stringify) ) ].map(JSON.parse); @@ -112,89 +112,74 @@ export const LaancDrawControl = props => { }; // 도형 그리기 완료 시 - // drawType을 바꾸면 종료처리가 돼서 이게 실행되는 듯 - const handlerDblClickFinish = state => { + const handlerFinishDraw = state => { + console.log('finish'); const mode = handlerReturnMode(drawObj.getMode()); - if (state.currentVertexPosition !== 0) { - console.log('dblclick'); - + const pointLength = state.currentVertexPosition; + if (pointLength > 0) { if (mode === 'CIRCLE') { - const obj = state.polygon; + const { properties, id } = state.polygon; const data = { - coord: obj.properties.center, - radius: obj.properties.radiusInKm * 1000, - id: obj.id + coords: properties.center, + mode: mode, + id: id, + radius: properties.radiusInKm * 1000 }; - drawObj.setFeatureProperty(data.id, 'id', mode); - handlerCreateOneMarker( - mapObject, - [0, -10], - data.coord, - data.radius, - data.id - ); - handlerAbnormalityCheck(data, mode); + drawObj.setFeatureProperty(id, 'id', mode); + handlerAbnormalityCheck(data).then(areaInfo => { + if (areaInfo) { + handlerCreateOneMarker( + mapObject, + [0, -10], + data.coords, + data.radius, + data.id + ); + handlerSaveData(areaInfo); + } + }); } else { const obj = state[mode.toLowerCase()]; - const length = state.currentVertexPosition; - if (obj.coordinates.length > 0) { - drawObj?.setFeatureProperty(obj.id, 'id', mode); - - // dbl클릭이 click 두번으로 인식돼서, 마지막 값을 없애버리기로 함 - if (mode === 'LINE') { - obj.coordinates.splice(-1); - // 여기서 버퍼 빈양식 만들어주자! - const buffer = drawObj.get(bufferId); - if (buffer) drawObj.delete(bufferId); - - const newBuffer = { - type: 'LineString', - coordinates: [] - }; - const newBufferId = drawObj.add(newBuffer); - drawObj.setFeatureProperty(newBufferId[0], 'id', 'BUFFER'); - drawObj.setFeatureProperty(newBufferId[0], 'lineId', obj.id); - setBufferId(newBufferId[0]); - - if (length < 2) { - // setAlertModal({ - // isOpen: true, - // title: '좌표 최소 개수', - // desc: '좌표를 두 개 점으로 이어주세요.' - // }); - props.setModal({ - title: '좌표 최소 개수', - desc: <>좌표를 두 개 점으로 이어주세요., - isOpen: true - }); - handlerRemoveError(obj.id); - return; - } - } else if (mode === 'POLYGON') { - obj.coordinates[0].splice(-1); - - if (length < 3) { - // setAlertModal({ - // isOpen: true, - // title: '좌표 최소 개수', - // desc: '좌표를 세 개 점으로 이어주세요.' - // }); - props.setModal({ - title: '좌표 최소 개수', - desc: <>좌표를 세 개 점으로 이어주세요., - isOpen: true - }); - handlerRemoveError(obj.id); - return; + const minPoint = mode === 'LINE' ? 2 : 3; + const desc = mode === 'LINE' ? '두' : '세'; + + // 좌표 최소 개수 체크 + if (pointLength < minPoint) { + props.setModal({ + title: '좌표 최소 개수', + desc: <>좌표를 {desc} 개 점으로 이어주세요., + isOpen: true + }); + handlerRemoveError(obj.id); + return; + } + + const coords = mode === 'LINE' ? obj.coordinates : obj.coordinates[0]; + coords.splice(-1); + + const data = { coords: coords, mode: mode, id: obj.id }; + handlerAbnormalityCheck(data).then(areaInfo => { + if (areaInfo) { + drawObj.setFeatureProperty(obj.id, 'id', mode); + + if (mode === 'LINE') { + const buffer = drawObj.get(bufferId); + if (buffer) drawObj.delete(bufferId); + + const newBuffer = { + type: 'LineString', + coordinates: [] + }; + const newBufferId = drawObj.add(newBuffer); + drawObj.setFeatureProperty(newBufferId[0], 'id', 'BUFFER'); + drawObj.setFeatureProperty(newBufferId[0], 'lineId', obj.id); + setBufferId(newBufferId[0]); } + + handlerSaveData(areaInfo); } - const data = { - coord: obj.coordinates, - id: obj.id - }; - handlerAbnormalityCheck(data, mode); - } + }); } } else { // 좌표가 찍히기도 전에 틀만 생성된 도형들 삭제 @@ -208,113 +193,94 @@ export const LaancDrawControl = props => { } }; - // 도형 수정 시 - const handlerUpdateSetting = e => { - console.log('update'); - - if (e.features[0]) { - const obj = e.features[0]; - const mode = obj.properties.id; - const initCoord = obj.geometry.coordinates; - - if (mode === 'CIRCLE') { - const data = { - coord: obj.properties.center, - radius: obj.properties.radiusInKm * 1000, - id: obj.id - }; - handlerRemoveGroupMarker(obj.id); - handlerCreateOneMarker( - mapObject, - [0, -10], - data.coord, - data.radius, - data.id - ); - handlerAbnormalityCheck(data, mode); - } else { - // 폴리곤은 중첩좌표 제거해서 서버에 넘겨야함 - if (mode === 'POLYGON') initCoord[0].splice(-1); - const data = { - coord: initCoord, - id: obj.id - }; - - // handlerRemoveGroupMarker(obj.id); - // handlerCreateGroupMarker(data, mode); - handlerAbnormalityCheck(data, mode); - } - } - }; - // 모든 비정상상황 체크 - const handlerAbnormalityCheck = async (data, mode) => { - console.log('비정상체크'); - - const initCoord = - mode === 'LINE' - ? data.coord - : mode === 'POLYGON' - ? data.coord[0] - : mode === 'CIRCLE' - ? data.coord - : null; - - const datas = { coord: initCoord, mode: mode }; - const areaInfo = handlerSettingAreaInfo(datas); + const handlerAbnormalityCheck = async data => { + // radius도 있음 + const { coords, mode, id } = data; + const areaInfo = handlerSettingAreaInfo(coords, mode); const areaList = props.handlerAreaInfoToAreaList(areaInfo); + let isBreak = false; - const isBreak1 = handlerIsSpecialFlight(data, mode); - const isBreak2 = handlerIsUnableArea(data, mode); - if (isBreak1 || isBreak2) return; - + // 비행금지 구역 체크 + console.log('unableElev'); try { - console.log('unableElev'); - const result = await axios.post(`api/bas/laanc/valid/elev`, areaList); - - if (result.data[0] === 0) { - props.setModal({ - title: '비행 불가 지역', - desc: ( - <> - 설정하신 비행구역 중 허용고도가 0m인 구역이 있습니다. -
- 비행구역 설정 시 허용고도를 다시 확인해주시기 바랍니다. - - ), - isOpen: true + const elev1 = await axios.post(`api/bas/laanc/valid/elev`, areaList); + const elev2 = []; + + if (mode === 'CIRCLE') { + const point = mapObject.project(coords); + const maine = mapObject.queryRenderedFeatures(point, { + layers: ['maine'] }); - handlerRemoveError(data.id); - return; + if (maine.length > 0) { + if (maine[0].properties.description.includes('김포공항 비행불가')) { + elev2.push(maine[0]); + isBreak = true; + } + } } else { - props.handlerSaveCheck(true); + for (let i = 0; i < coords.length; i++) { + const point = mapObject.project(coords[i]); + const maine = mapObject.queryRenderedFeatures(point, { + layers: ['maine'] + }); + + if (maine.length > 0) { + if (maine[0].properties.description.includes('김포공항 비행불가')) { + elev2.push(maine[0]); + isBreak = true; + break; + } + } + } } + + if (elev1.data[0] === 0 || elev2.length > 0) isBreak = true; } catch (error) { alert('에러 발생'); } - handlerSaveData(areaInfo); - }; + if (isBreak) { + props.setModal({ + title: '비행 불가 지역', + desc: ( + <> + 설정하신 비행구역 중 허용고도가 0m인 구역이 있습니다. +
+ 비행구역 설정 시 허용고도를 다시 확인해주시기 바랍니다. + + ), + isOpen: true + }); + handlerRemoveError(id); + return; + } else { + props.handlerSaveCheck(true); + } - // 비가시권 검사 - const handlerIsSpecialFlight = (data, mode) => { + // 비가시권 체크 console.log('specialFlight'); - let isBreak = false; + let text = ''; if (mode === 'CIRCLE') { if (data.radius > 1000) { + text = 'circle의 경우 반경'; isBreak = true; } } else { - const coords = mode === 'LINE' ? data.coord : data.coord[0]; - - for (let point = 0; point < coords.length - 1; point++) { - const distance = CalculateDistance(coords[point], coords[point + 1]); + if (mode === 'POLYGON') coords.push(coords[0]); + for (let j = 0; j < coords.length - 1; j++) { + const distance = CalculateDistance(coords[j], coords[j + 1]); if (distance > 1000) { + text = + mode === 'LINE' + ? 'waypoint의 경우 점과 점 사이가' + : 'polygon의 경우 변과 변 사이가'; isBreak = true; break; } } + if (mode === 'POLYGON') coords.splice(-1); } if (isBreak) { @@ -322,74 +288,65 @@ export const LaancDrawControl = props => { title: '특별 비행 신청', desc: ( <> - 육안으로 기체 확인이 불가능 합니다. -
가시권 밖 범위는 특별비행 신청을 진행하셔야 합니다.
- 드론원스톱을 통해서 신청해 주시기 바랍니다. + {text} 1km 초과 시 비 가시권에 해당됩니다. +
+ 비 가시권의 경우 특별비행 승인 신청이 필요하니, +
+ 아래 링크를 통해 드론원스톱으로 신청해 주시기 바랍니다. ), isOpen: true }); - handlerRemoveError(data.id); - return true; + handlerRemoveError(id); + return; } else { props.handlerSaveCheck(true); - return false; + return areaInfo; } }; - // 비행불가지역 검사 - const handlerIsUnableArea = (data, mode) => { - console.log('unableArea'); - let isBreak = false; - - if (mode === 'CIRCLE') { - const point = mapObject.project(data.coord); - const maine = mapObject.queryRenderedFeatures(point, { - layers: ['maine'] - }); + // 도형 수정 시 + const handlerUpdateSetting = e => { + console.log('update'); - if (maine.length > 0) { - if (maine[0].properties.description.includes('김포공항 비행불가')) { - isBreak = true; - // break; - } - } - } else { - const coord = mode === 'LINE' ? data.coord : data.coord[0]; + if (e.features[0]) { + const { geometry, properties, id } = e.features[0]; + const mode = properties.id; + const coords = + mode === 'LINE' ? geometry.coordinates : geometry.coordinates[0]; - for (let i = 0; i < coord.length; i++) { - const point = mapObject.project(coord[i]); - const maine = mapObject.queryRenderedFeatures(point, { - layers: ['maine'] + if (mode === 'CIRCLE') { + const data = { + coords: properties.center, + mode: mode, + id: id, + radius: properties.radiusInKm * 1000 + }; + handlerAbnormalityCheck(data).then(areaInfo => { + if (areaInfo) { + handlerRemoveGroupMarker(id); + handlerCreateOneMarker( + mapObject, + [0, -10], + data.coords, + data.radius, + data.id + ); + handlerSaveData(areaInfo); + } }); + } else { + // 폴리곤은 중첩좌표 제거해서 서버에 넘겨야함 + if (mode === 'POLYGON') coords.splice(-1); + const data = { coords: coords, mode: mode, id: id }; - if (maine.length > 0) { - if (maine[0].properties.description.includes('김포공항 비행불가')) { - isBreak = true; - break; - } - } + // handlerRemoveGroupMarker(obj.id); + // handlerCreateGroupMarker(data, mode); + handlerAbnormalityCheck(data).then(areaInfo => { + if (areaInfo) handlerSaveData(areaInfo); + }); } } - - if (isBreak) { - props.setModal({ - title: '비행 불가 지역', - desc: ( - <> - 설정하신 비행구역 중 허용고도가 0m인 구역이 있습니다. -
- 비행구역 설정 시 허용고도를 다시 확인해주시기 바랍니다. - - ), - isOpen: true - }); - handlerRemoveError(data.id); - return true; - } else { - props.handlerSaveCheck(true); - return false; - } }; // 비정상 감지 시 해당 도형, 마커 삭제 @@ -419,6 +376,7 @@ export const LaancDrawControl = props => { // 정상 좌표 처리 const handlerSaveData = areaInfo => { console.log('ok!!!'); + props.handlerCoordinates(areaInfo); setIsDrawDone(true); @@ -436,8 +394,8 @@ export const LaancDrawControl = props => { }; // areaInfo 셋팅 - const handlerSettingAreaInfo = data => { - if (!data.coord || !data.mode) { + const handlerSettingAreaInfo = (coord, mode) => { + if (!coord || !mode) { alert('에러 발생. 다시 시도해 주세요.'); return; } @@ -449,13 +407,13 @@ export const LaancDrawControl = props => { areaType: '' }; - const bufferZone = data.mode === 'POLYGON' ? 0 : 100; + const bufferZone = mode === 'POLYGON' ? 0 : 100; const prePath = []; - areaInfo.areaType = data.mode; + areaInfo.areaType = mode; if (areaInfo.areaType !== 'CIRCLE') { - data.coord.forEach(item => { + coord.forEach(item => { const p = { lat: item[1], lon: item[0] @@ -471,28 +429,14 @@ export const LaancDrawControl = props => { const feature = obj.filter(o => o.properties.id === 'CIRCLE'); const point = { - lat: data.coord[1], - lon: data.coord[0] + lat: coord[1], + lon: coord[0] }; areaInfo.coordinates = [point]; areaInfo.bufferZone = feature[0].properties.radiusInKm * 1000; } return areaInfo; - // props.handlerCoordinates(areaInfo); - // setIsDrawDone(true); - - // const viewCoordObj = drawObj - // .getAll() - // .features.filter(o => o.properties.id !== 'BUFFER'); - - // props.setViewCoordObj(viewCoordObj); - - // if (viewCoordObj.length > 19) { - // props.handlerAddChange('overAdd', true); - // } else { - // props.handlerAddChange('isViewAdd', true); - // } }; // 두 좌표배열이 완전히 일치하는지 판단 @@ -550,6 +494,8 @@ export const LaancDrawControl = props => { } } + if (lineId === '') return; + // features중에 위에서 찾은 lineId값을 properties로 갖고 있는 버퍼를 찾아서 지워줌 const oldBuffer = objs.find( obj => obj.properties?.lineId === lineId diff --git a/src/utility/DrawUtil.js b/src/utility/DrawUtil.js index dc95727..87553f1 100644 --- a/src/utility/DrawUtil.js +++ b/src/utility/DrawUtil.js @@ -136,6 +136,8 @@ export const handlerRemoveGroupMarker = id => { // 개별 마커 생성 export const handlerCreateOneMarker = (map, anchor, lngLat, text, id) => { + if (!id) return; + const popup = new mapboxgl.Popup({ offset: anchor, closeButton: false, From bb683071e73485b44fdcc2c0ce3a9bbba6385e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?junh=5Feee=28=EC=9D=B4=EC=A4=80=ED=9D=AC=29?= Date: Fri, 27 Oct 2023 17:04:01 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/laanc/map/LaancAreaMap.js | 4 ++-- .../{map/mapbox/draw => laanc/map}/LaancDrawControl.js | 8 ++++---- .../{map/mapbox/draw => laanc/map}/LaancMapSearch.js | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) rename src/components/{map/mapbox/draw => laanc/map}/LaancDrawControl.js (98%) rename src/components/{map/mapbox/draw => laanc/map}/LaancMapSearch.js (97%) diff --git a/src/components/laanc/map/LaancAreaMap.js b/src/components/laanc/map/LaancAreaMap.js index 2d814c6..b307301 100644 --- a/src/components/laanc/map/LaancAreaMap.js +++ b/src/components/laanc/map/LaancAreaMap.js @@ -30,8 +30,8 @@ import flatGimpo from '../../map/geojson/flatGimpoAirportAirArea.json'; import gimpo from '../../map/geojson/gimpoAirportAirArea.json'; import geoJson from '../../map/geojson/airArea.json'; import { FeatureAirZone } from '../../map/mapbox/feature/FeatureAirZone'; -import LaancMapSearch from '../../map/mapbox/draw/LaancMapSearch'; -import { LaancDrawControl } from '../../map/mapbox/draw/LaancDrawControl'; +import LaancMapSearch from './LaancMapSearch'; +import { LaancDrawControl } from './LaancDrawControl'; import LaancModal from '../../map/mapbox/draw/LaancModal'; export default function LaancAreaMap({ diff --git a/src/components/map/mapbox/draw/LaancDrawControl.js b/src/components/laanc/map/LaancDrawControl.js similarity index 98% rename from src/components/map/mapbox/draw/LaancDrawControl.js rename to src/components/laanc/map/LaancDrawControl.js index 827b9d3..503e706 100644 --- a/src/components/map/mapbox/draw/LaancDrawControl.js +++ b/src/components/laanc/map/LaancDrawControl.js @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { InfoModal } from '../../../modal/InfoModal'; +import { InfoModal } from '../../modal/InfoModal'; import { useDispatch, useSelector } from 'react-redux'; import { CalculateDistance, @@ -9,11 +9,11 @@ import { handlerRemoveAllMarker, handlerRemoveGroupMarker, handlerReturnMode -} from '../../../../utility/DrawUtil'; -import { drawTypeChangeAction } from '../../../../modules/control/map/actions/controlMapActions'; +} from '../../../utility/DrawUtil'; +import { drawTypeChangeAction } from '../../../modules/control/map/actions/controlMapActions'; import MapboxDraw from '@mapbox/mapbox-gl-draw'; import { CircleMode } from 'mapbox-gl-draw-circle'; -import axios from '../../../../modules/utils/customAxiosUtil'; +import axios from '../../../modules/utils/customAxiosUtil'; export const LaancDrawControl = props => { const dispatch = useDispatch(); diff --git a/src/components/map/mapbox/draw/LaancMapSearch.js b/src/components/laanc/map/LaancMapSearch.js similarity index 97% rename from src/components/map/mapbox/draw/LaancMapSearch.js rename to src/components/laanc/map/LaancMapSearch.js index f07331d..c2fe632 100644 --- a/src/components/map/mapbox/draw/LaancMapSearch.js +++ b/src/components/laanc/map/LaancMapSearch.js @@ -1,7 +1,7 @@ import { Input, InputGroup, InputGroupAddon, InputGroupText } from 'reactstrap'; import { Search } from 'react-feather'; import { useState } from 'react'; -import { flightPlanAPI } from '../../../../modules/basis/flight/apis/basisFlightApi'; +import { flightPlanAPI } from '../../../modules/basis/flight/apis/basisFlightApi'; export default function LaancMapSearch({ mapObject }) { const [query, setQuery] = useState('');