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,