diff --git a/src/components/laanc/map/FlightArea.js b/src/components/laanc/map/FlightArea.js index c7bdfbf..bc079e1 100644 --- a/src/components/laanc/map/FlightArea.js +++ b/src/components/laanc/map/FlightArea.js @@ -21,8 +21,9 @@ import { layerBuffer, layerPolygon, layerPolyline, - layerWayPoint -} from '../../../utility/DrawUtil'; + layerWayPoint, + handlerCreateAirSpace +} from '../../../utility/MapUtils'; // actions import { AREA_COORDINATE_LIST_SAVE, @@ -42,7 +43,6 @@ import { WeatherContainer } from '../../../containers/basis/flight/plan/WeatherC import { initFlightBas } from '../../../modules/laanc/models/laancModels'; import LaancAreaMap from './LaancAreaMap'; import LaancDrawModal from './LaancDrawModal'; -import { handlerCreateAirSpace } from './LaancComn'; export default function FlightArea({ centeredModal, @@ -105,7 +105,7 @@ export default function FlightArea({ //날씨 위치 데이터 const [wheather, setWheather] = useState([]); - // 미니맵에 표출되는 비행구역 정보 + // 미니맵에 표출되는 비행구역 geoJson 정보 const previewGeo = { type: 'FeatureCollection', features: [] diff --git a/src/components/laanc/map/LaancAreaMap.js b/src/components/laanc/map/LaancAreaMap.js index 0901ba2..eb8de5b 100644 --- a/src/components/laanc/map/LaancAreaMap.js +++ b/src/components/laanc/map/LaancAreaMap.js @@ -16,13 +16,13 @@ import { mapInitAction } from '../../../modules/control/map/actions/controlMapAc import { FormattingCoord, handlerFitBounds, - handlerGetCircleCoord -} from '../../../utility/DrawUtil'; + handlerGetCircleCoord, + handlerCreateAirSpace +} from '../../../utility/MapUtils'; import gimpo from '../../map/geojson/gimpoAirportAirArea.json'; import { FeatureAirZone } from '../../map/mapbox/feature/FeatureAirZone'; import LaancMapSearch from './LaancMapSearch'; import { LaancDrawControl } from './LaancDrawControl'; -import { handlerCreateAirSpace } from './LaancComn'; export default function LaancAreaMap({ mapContainer, diff --git a/src/components/laanc/map/LaancComn.js b/src/components/laanc/map/LaancComn.js deleted file mode 100644 index d8e30a8..0000000 --- a/src/components/laanc/map/LaancComn.js +++ /dev/null @@ -1,73 +0,0 @@ -import { useSelector } from 'react-redux'; -import geoJson from '../../map/geojson/airArea.json'; -import flatGimpo from '../../map/geojson/flatGimpoAirportAirArea.json'; - -// 공역 생성 -export const handlerCreateAirSpace = ( - map, - mapControl, - useGeoJson = { - ...geoJson, - ...flatGimpo, - features: [...geoJson.features, ...flatGimpo.features] - } -) => { - if (map.getLayer('maine')) { - map.removeLayer('maine'); - map.removeSource('maine'); - } - let arrGeoJson = []; - useGeoJson.features.map(item => { - if (item.properties.type === '0001' && mapControl.area0001) { - arrGeoJson.push({ - ...item, - properties: { ...item.properties, color: '#FF3648' } - }); - } else if (item.properties.type === '0002' && mapControl.area0002) { - arrGeoJson.push({ - ...item, - properties: { ...item.properties, color: '#FFA1AA' } - }); - } else if (item.properties.type === '0003' && mapControl.area0003) { - arrGeoJson.push({ - ...item, - properties: { ...item.properties, color: '#FFA800' } - }); - } else if (item.properties.type === '0004' && mapControl.area0004) { - arrGeoJson.push({ - ...item, - properties: { ...item.properties, color: '#A16B00' } - }); - } else if (item.properties.type === '0005' && mapControl.area0005) { - arrGeoJson.push({ - ...item, - properties: { ...item.properties, color: '#AB40FF' } - }); - } else if (item.properties.type === '0006' && mapControl.area0006) { - arrGeoJson.push({ - ...item, - properties: { ...item.properties, color: '#009cad' } - }); - } - }); - useGeoJson.features = arrGeoJson.filter(i => i.geometry.type === 'Polygon'); - - // 공역 생성 start - map.addSource('maine', { - type: 'geojson', - data: { - ...useGeoJson - } - }); - map.addLayer({ - id: 'maine', - type: 'fill', - source: 'maine', - layout: {}, - paint: { - 'fill-color': ['get', 'color'], - // 'fill-extrusion-height': 3000, - 'fill-opacity': 0.5 - } - }); -}; diff --git a/src/components/laanc/map/LaancDrawControl.js b/src/components/laanc/map/LaancDrawControl.js index 58990f2..a649f63 100644 --- a/src/components/laanc/map/LaancDrawControl.js +++ b/src/components/laanc/map/LaancDrawControl.js @@ -9,7 +9,7 @@ import { handlerRemoveAllMarker, handlerRemoveGroupMarker, handlerReturnMode -} from '../../../utility/DrawUtil'; +} from '../../../utility/MapUtils'; import { drawTypeChangeAction } from '../../../modules/control/map/actions/controlMapActions'; import MapboxDraw from '@mapbox/mapbox-gl-draw'; import { diff --git a/src/components/map/mapbox/MapBoxMap.js b/src/components/map/mapbox/MapBoxMap.js index 66959b6..5233d58 100644 --- a/src/components/map/mapbox/MapBoxMap.js +++ b/src/components/map/mapbox/MapBoxMap.js @@ -1,225 +1,32 @@ +import { useEffect, useState, useRef, useLayoutEffect } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; +import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; +// mapbox import 'mapbox-gl/dist/mapbox-gl.css'; +import { MAPBOX_TOKEN } from '../../../configs/constants'; import mapboxgl from 'mapbox-gl'; -import threebox from 'threebox-plugin'; -import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; -import * as THREE from 'three'; import MapboxLanguage from '@mapbox/mapbox-gl-language'; -import { MAPBOX_TOKEN } from '../../../configs/constants'; -import { useEffect, useState, useRef, useLayoutEffect } from 'react'; -import { useSelector, useDispatch } from 'react-redux'; + +import { DronToast } from './dron/DronToast'; import { DronMarker } from './dron/DronMarker'; -// import { DronHistory } from './dron/DronHistory'; -// import MapBoxMapControl from './MapBoxMapControl'; -// import { NaverMapSearch } from './search/NaverMapSearch'; +import { DronPlan } from './dron/DronPlan'; import { FeatureAirZone } from './feature/FeatureAirZone'; + +import threebox from 'threebox-plugin'; + import geoJson from '../../map/geojson/airArea.json'; -// import gimPo from '../../map/geojson/gimpoAirportAirArea.json'; import gimPo from '../../map/geojson/gimpoAirportAirArea.json'; // 김포 격자 공역 import gimPoGrid from '../../../components/map/geojson/airportAirArea.json'; // 김포 선형 공역 import flatGimpo from '../../map/geojson/flatGimpoAirportAirArea.json'; -// import DronPlan from './dron/DronPlan'; -// import NewDronPlan from './dron/NewDronPlan'; -// import { NewDronHistory } from './dron/NewDronHistroy'; -// import DronToast from './dron/DronToast'; -// import SensorZone from './sensor/SensorZone'; import { mapInitAction } from '../../../modules/control/map/actions/controlMapActions'; -import DronPlan from './dron/DronPlan'; -import DronToast from './dron/DronToast'; +import * as THREE from 'three'; // example 3d gltf 파일 import UamGltf from './models/out.glb'; -const uamPosition = { - type: 'FeatureCollection', - features: [ - { - type: 'Feature', - properties: { - name: 'V1', - background: '#ffffff', - border: '#15298A', - spanColor: '#000000' - }, - geometry: { - type: 'Point', - coordinates: [126.540668, 37.4797865] - } - }, - { - type: 'Feature', - properties: { - name: 'V2', - background: '#ffffff', - border: '#15298A', - spanColor: '#000000' - }, - geometry: { - type: 'Point', - coordinates: [126.6107763, 37.521245] - } - }, - { - type: 'Feature', - properties: { - name: 'V3', - background: '#ffffff', - border: '#15298A', - spanColor: '#000000' - }, - geometry: { - type: 'Point', - coordinates: [126.6243464, 37.5642352] - } - }, - { - type: 'Feature', - properties: { - name: 'V4', - background: '#ffffff', - border: '#15298A', - spanColor: '#000000' - }, - geometry: { - type: 'Point', - coordinates: [126.6650669, 37.3658236] - } - }, - { - type: 'Feature', - properties: { - name: 'V5', - background: '#ffffff', - border: '#15298A', - spanColor: '#000000' - }, - geometry: { - type: 'Point', - coordinates: [126.7074861, 37.4520753] - } - }, - { - type: 'Feature', - properties: { - name: 'R1', - background: '#429629', - border: '#ffffff', - spanColor: '#ffffff' - }, - geometry: { - type: 'Point', - coordinates: [126.5801572, 37.492581] - } - }, - { - type: 'Feature', - properties: { - name: 'R2', - background: '#429629', - border: '#ffffff', - spanColor: '#ffffff' - }, - geometry: { - type: 'Point', - coordinates: [126.6036588, 37.542031] - } - }, - { - type: 'Feature', - properties: { - name: 'R3', - background: '#429629', - border: '#ffffff', - spanColor: '#ffffff' - }, - geometry: { - type: 'Point', - coordinates: [126.6005224, 37.5764269] - } - }, - { - type: 'Feature', - properties: { - name: 'R4', - background: '#429629', - border: '#ffffff', - spanColor: '#ffffff' - }, - geometry: { - type: 'Point', - coordinates: [126.6600404, 37.5790407] - } - }, - { - type: 'Feature', - properties: { - name: 'R5', - background: '#429629', - border: '#ffffff', - spanColor: '#ffffff' - }, - geometry: { - type: 'Point', - coordinates: [126.649562, 37.524016] - } - }, - { - type: 'Feature', - properties: { - name: 'R6', - background: '#429629', - border: '#ffffff', - spanColor: '#ffffff' - }, - geometry: { - type: 'Point', - coordinates: [126.693722, 37.5506488] - } - }, - { - type: 'Feature', - properties: { - name: 'R7', - background: '#429629', - border: '#ffffff', - spanColor: '#ffffff' - }, - geometry: { - type: 'Point', - coordinates: [126.6023981, 37.4712333] - } - }, - { - type: 'Feature', - properties: { - name: 'R8', - background: '#429629', - border: '#ffffff', - spanColor: '#ffffff' - }, - geometry: { - type: 'Point', - coordinates: [126.6202759, 37.4046495] - } - }, - { - type: 'Feature', - properties: { - name: 'R9', - background: '#429629', - border: '#ffffff', - spanColor: '#ffffff' - }, - geometry: { - type: 'Point', - coordinates: [126.6296542, 37.3450207] - } - } - ] -}; - let gridCoords = []; let altitudeMarker = []; let linerAltitude = [ @@ -263,51 +70,32 @@ let linerAltitude = [ let linerAltitudeMarker = []; export default function MapBoxMap() { - const naver = window.naver; + const dispatch = useDispatch(); + // 공역표출 타입 + const mapControl = useSelector(state => state.controlMapReducer); + // 지도 + const mapContainer = useRef(null); const [mapObject, setMapObject] = useState(null); + // 지도 로드 여부 const [isMapLoaded, setMapLoaded] = useState(false); - const [arrPolyline, setArrPolyline] = useState([]); + + // 노탐 정보 모달 const [centeredModal, setCenteredModal] = useState(false); - const mapContainer = useRef(null); - const dispatch = useDispatch(); - const mapControl = useSelector(state => state.controlMapReducer); + // 비행예상경로 geoJson 정보 const [planGeo, setPlanGeo] = useState({ type: 'FeatureCollection', features: [] }); + // 지도 초기 셋팅 useLayoutEffect(() => { mapBoxMapInit(); }, []); - // useEffect(() => { - // if (mapObject) { - // uamPosition.features.map(uam => { - // const el = document.createElement('div'); - // const elChild = document.createElement('span'); - // elChild.innerText = uam.properties.name; - // elChild.style.color = uam.properties.spanColor; - // el.className = 'marker'; - // el.style.background = uam.properties.background; - // el.style.borderRadius = '50%'; - // el.style.border = `4px solid ${uam.properties.border}`; - // el.style.padding = '5px'; - // el.style.width = '40px'; - // el.style.height = '40px'; - // el.style.textAlign = 'center'; - // el.appendChild(elChild); - - // new mapboxgl.Marker(el) - // .setLngLat(uam.geometry.coordinates) - // .addTo(mapObject); - // }); - // } - // }, [mapObject]); - + // 공역 표출 정보에 따른 공역 변경 useEffect(() => { - console.log(mapObject); if (mapObject) { handlerCreateAirSpace(mapObject); } @@ -321,6 +109,7 @@ export default function MapBoxMap() { mapControl.liner ]); + // 공역 생성 const handlerCreateAirSpace = ( map, useGeoJson = { @@ -500,6 +289,7 @@ export default function MapBoxMap() { stats.update(); }; + // 맵박스 지도 초기 셋팅 const mapBoxMapInit = () => { mapboxgl.accessToken = MAPBOX_TOKEN; @@ -806,13 +596,13 @@ export default function MapBoxMap() { 'fill-outline-color': '#000000' }, filter: ['in', '$type', 'Polygon'] - // filter: ['==', ['get', 'id'], ['polygon', 'circle']] }); setMapLoaded(true); }); setMapObject(map); dispatch(mapInitAction(map)); + // map.on('style.load', () => { // map.addLayer({ // id: 'custom-threebox-model', @@ -846,28 +636,6 @@ export default function MapBoxMap() { // }); }; - const createUamArea = uam => { - const title = uam.title; - const position = new naver.maps.LatLng(uam.lat, uam.lon); - - const circle = new naver.maps.Circle({ - strokeColor: '#283046', - strokeOpacity: 1, - fillColor: '#8a1c05', - fillOpacity: 0.1, - center: position, - // map: mapObject, - radius: 100, - clickable: true - }); - - // circle.setMap(mapObject); - }; - - const handleHistoryInit = line => { - setArrPolyline([...arrPolyline, line]); - }; - return ( <>
{isMapLoaded && mapObject ? ( <> + - - - {/* */} - - {/* */} - {/* */} - - {/* */} - {/* */} ) : null} diff --git a/src/components/map/mapbox/dron/DronMarker.js b/src/components/map/mapbox/dron/DronMarker.js index b4450e2..8ac756c 100644 --- a/src/components/map/mapbox/dron/DronMarker.js +++ b/src/components/map/mapbox/dron/DronMarker.js @@ -1,4 +1,3 @@ -import $ from 'jquery'; import { useEffect, useState } from 'react'; import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import '../../../../assets/css/custom.css'; @@ -7,7 +6,6 @@ import FlightDetailIcon from '../../../../assets/images/airplan_pp.svg'; import DronIcon from '../../../../assets/images/drone-marker-icon.png'; import DronDetailIcon from '../../../../assets/images/drone-marker-icon-pulple.png'; import DronUamIcon from '../../../../assets/images/uam_icon.png'; -import DronUamDetailIcon from '../../../../assets/images/uam_icon_purple.png'; import { controlGpDtlAction, controlGpFlightPlanAction, @@ -29,28 +27,27 @@ export const DronMarker = props => { state => state.controlMapReducer, shallowEqual ); - // const { controlGroupAuthInfo } = useSelector( - // state => state.controlGroupAuthState - // ); const { controlGpArcrftWarnList } = useSelector( state => state.controlGpLogState ); + // 유저 정보 const { user } = useSelector(state => state.authState); + + // 유저가 가입한 그룹 목록 const { joinList } = useSelector(state => state.groupState); + // 마커, 데이터 블록 배열 const [arrMarkers, setArrMarkers] = useState([]); const [arrInfos, setArrInfos] = useState([]); + // 비행 기체 개수 const [count, setCount] = useState({ drone: [], flight: [] }); - // useLayoutEffect(() => { - // dispatch(controlGroupAuthAction.request()); - // }, [controlGpList]); - + // 유저가 속한 그룹 리스트 알아냄 useEffect(() => { dispatch( JOIN_LIST.request({ @@ -59,6 +56,7 @@ export const DronMarker = props => { ); }, []); + // 비행 기체 개수 계산 useEffect(() => { if (count.drone.length > 0 || count.flight.length > 0) { dispatch( @@ -79,12 +77,14 @@ export const DronMarker = props => { } }, [count]); + // 마커 생성 시 데이터 블록 자동 생성 useEffect(() => { if (arrMarkers.length != 0) { markerInfo(arrMarkers); } }, [arrMarkers]); + // 마커 셋팅 useEffect(() => { markerInit(); }, [controlGpList]); @@ -158,7 +158,7 @@ export const DronMarker = props => { // }); // }, [objectId]); - //마커를 그린다. + //마커 생성 const addMarkers = (position, id, controlId, gps) => { const gpsCnt = { gps: gps, @@ -286,23 +286,23 @@ export const DronMarker = props => { } }; + // 마커 클릭 시 드론 상세 정보 표출 const handlerDronClick = marker => { dispatch(objectClickAction(marker.controlId)); dispatch(controlGpDtlAction.request(marker.controlId)); - // dispatch(controlGpFlightPlanAction.request(idntfNum)); }; - //마커를 삭제 한다. + //마커 삭제 const removeMarkers = marker => { marker.remove(); }; - // 마커 데이터 블록 삭제 + // 데이터 블록 삭제 const removeInfos = info => { info.remove(); }; - //마커에 위치를 이동한다. + //마커 위치 이동 const moveMarkers = (marker, position, gps) => { marker.setLngLat(position); const warnList = controlGpArcrftWarnList?.filter( @@ -324,6 +324,7 @@ export const DronMarker = props => { marker.setRotation(gps.heading); }; + // 데이터 블록 위치 이동 const moveInfos = (info, position, item, idx) => { if (info) { info.setLngLat([position.lng, position.lat]); @@ -353,7 +354,7 @@ export const DronMarker = props => { } }; - //데이터가 없는 마커를 모두 삭제 한다. + //데이터가 없는 마커 모두 삭제 const allRemoveMarkers = () => { let isUnClick = false; if (arrMarkers && controlGpList) { @@ -398,7 +399,7 @@ export const DronMarker = props => { return isUnClick; }; - //마커를 셋팅 한다. + //마커 셋팅 const markerInit = () => { if (controlGpList) { allRemoveMarkers(); @@ -422,14 +423,17 @@ export const DronMarker = props => { } }; + // 마커 목록 업데이트 const removeArrMarkers = arrData => { setArrMarkers(arrData); }; + // 데이터블록 목록 업데이트 const updateArrInfos = arrData => { setArrInfos(arrData); }; + // 데이터 블록 생성 const markerInfo = arrMarkers => { arrMarkers.forEach((marker, idx) => { // 중복 데이터블록 체크 @@ -476,7 +480,6 @@ export const DronMarker = props => { info._controlId = marker.controlId; setArrInfos(m => [...m, info]); - // } }); }; diff --git a/src/components/map/mapbox/dron/DronPlan.js b/src/components/map/mapbox/dron/DronPlan.js index e296b49..78129df 100644 --- a/src/components/map/mapbox/dron/DronPlan.js +++ b/src/components/map/mapbox/dron/DronPlan.js @@ -1,431 +1,24 @@ import { useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; -import { handlerGetCircleCoord } from '../../../../utility/DrawUtil'; +import { handlerGetCircleCoord } from '../../../../utility/MapUtils'; -export const dummyPolyline = [ - { - planSno: 242, - groupId: 'C807F9', - cstmrSno: 2, - memberName: '팔네트웍스', - email: 'dhji@palnet.co.kr', - hpno: '01082504456', - clncd: '+82', - schFltStDt: '2023-11-15 10:00:00', - schFltEndDt: '2023-11-15 16:31:18', - fltPurpose: 'EDUCATION_FLIGHT', - aprvlYn: 'Y', - delYn: 'N', - createUserId: 'palnet', - createDt: '2023-11-15 10:00:00', - updateUserId: 'palnet', - updateDt: '2023-11-15 10:00:00', - docState: 'R', - areaList: [ - { - planAreaSno: 242, - planSno: 242, - areaType: 'LINE', - fltAreaAddr: '인천광역시 계양구 봉오대로463번길 26', - bufferZone: 100, - fltElev: '100', - createUserId: 'palnet', - createDt: '2023-11-14 15:57:21', - updateUserId: 'palnet', - updateDt: '2023-11-14 15:57:21', - docState: 'R', - coordList: [ - { - planAreaCoordSno: 515, - planAreaSno: 242, - lat: 37.530121373976954, - lon: 126.69937537668989, - createUserId: 'palnet', - createDt: '2023-11-14 15:57:21', - docState: 'R' - }, - { - planAreaCoordSno: 516, - planAreaSno: 242, - lat: 37.53072487369214, - lon: 126.70586394488811, - createUserId: 'palnet', - createDt: '2023-11-14 15:57:21', - docState: 'R' - }, - { - planAreaCoordSno: 517, - planAreaSno: 242, - lat: 37.52748497586097, - lon: 126.70594405066777, - createUserId: 'palnet', - createDt: '2023-11-14 15:57:21', - docState: 'R' - } - ], - bufferCoordList: [ - { - lat: 37.5316197886034, - lon: 126.70573274477093, - docState: 'R' - }, - { - lat: 37.531625304714495, - lon: 126.70590392813509, - docState: 'R' - }, - { - lat: 37.53161017252108, - lon: 126.70607419460082, - docState: 'R' - }, - { - lat: 37.531574739035676, - lon: 126.70623963959872, - docState: 'R' - }, - { - lat: 37.53151981682155, - lon: 126.70639646913716, - docState: 'R' - }, - { - lat: 37.53144666535704, - lon: 126.70654108681464, - docState: 'R' - }, - { - lat: 37.531356962150426, - lon: 126.70667017629863, - docState: 'R' - }, - { - lat: 37.53125276426794, - lon: 126.70678077737894, - docState: 'R' - }, - { - lat: 37.53113646115761, - lon: 126.70687035385097, - docState: 'R' - }, - { - lat: 37.53101071985107, - lon: 126.7069368516722, - docState: 'R' - }, - { - lat: 37.53087842380056, - lon: 126.70697874605814, - docState: 'R' - }, - { - lat: 37.530742606753975, - lon: 126.70699507643907, - docState: 'R' - }, - { - lat: 37.527502707958675, - lon: 126.70707513332411, - docState: 'R' - }, - { - lat: 37.526601887803295, - lon: 126.70709739090397, - docState: 'R' - }, - { - lat: 37.526566413313844, - lon: 126.70483525338567, - docState: 'R' - }, - { - lat: 37.52971486141971, - lon: 126.70475736339164, - docState: 'R' - }, - { - lat: 37.529226466217224, - lon: 126.69950664996875, - docState: 'R' - }, - { - lat: 37.52912191557935, - lon: 126.69838296584224, - docState: 'R' - }, - { - lat: 37.53091172822204, - lon: 126.69812038962549, - docState: 'R' - }, - { - lat: 37.5316197886034, - lon: 126.70573274477093, - docState: 'R' - } - ] - } - ], - arcrftList: [ - { - arcrftSno: 1, - idntfNum: 'PA0001', - prdctNum: 'PAV_001_PPAL20230914', - arcrftTypeCd: '01', - arcrftModelNm: 'PAV_001', - prdctCmpnNm: 'PalNetworks', - arcrftLngth: 0, - arcrftWdth: 0, - arcrftHght: 0, - arcrftWght: 0, - wghtTypeCd: '250G+2KG-', - takeoffWght: 0, - useYn: 'Y', - cameraYn: 'N', - insrncYn: 'Y', - createUserId: 'palnet', - createDt: '2023-09-14 17:32:59', - updateUserId: 'palnet', - updateDt: '2023-09-14 17:32:59', - docState: 'R' - } - ], - corpRegYn: 'N', - serviceType: 'PAV-KAC' - } -]; -export const dummyPolygon = [ - { - planSno: 244, - groupId: 'C807F9', - cstmrSno: 2, - memberName: '팔네트웍스', - email: 'dhji@palnet.co.kr', - hpno: '01082504456', - clncd: '+82', - schFltStDt: '2023-11-15 16:26:13', - schFltEndDt: '2023-11-15 18:21:13', - fltPurpose: 'TRAFFIC_MANAGEMENT', - fltType: 'COMMERCIAL', - fltTypeNm: '상업용', - aprvlYn: 'Y', - createUserId: 'palnet', - createDt: '2023-11-15 16:22:46', - updateUserId: 'palnet', - updateDt: '2023-11-15 16:22:46', - serviceType: 'PAV-KAC', - corpRegYn: 'N', - pdfUrl: '/api/comn/file/download/387', - areaList: [ - { - planAreaSno: 244, - planSno: 244, - areaType: 'POLYGON', - fltAreaAddr: '인천광역시 계양구 26', - bufferZone: 0, - fltElev: '100', - createUserId: 'palnet', - createDt: '2023-11-15 16:22:46', - updateUserId: 'palnet', - updateDt: '2023-11-15 16:22:46', - docState: 'R', - coordList: [ - { - planAreaCoordSno: 522, - planAreaSno: 244, - lat: 37.575642815639966, - lon: 126.7053377657183, - createUserId: 'palnet', - createDt: '2023-11-15 16:22:46', - docState: 'R' - }, - { - planAreaCoordSno: 523, - planAreaSno: 244, - lat: 37.56753805633005, - lon: 126.7033921798162, - createUserId: 'palnet', - createDt: '2023-11-15 16:22:46', - docState: 'R' - }, - { - planAreaCoordSno: 524, - planAreaSno: 244, - lat: 37.56832705395003, - lon: 126.71429651010209, - createUserId: 'palnet', - createDt: '2023-11-15 16:22:46', - docState: 'R' - }, - { - planAreaCoordSno: 525, - planAreaSno: 244, - lat: 37.57553523611571, - lon: 126.71606111127, - createUserId: 'palnet', - createDt: '2023-11-15 16:22:46', - docState: 'R' - } - ] - } - ], - arcrftList: [ - { - planArcrftSno: 240, - planSno: 244, - arcrftSno: 0, - idntfNum: 'PA0001', - arcrftTypeCd: 'UNMANNED_AIRCRAFT', - arcrftLngth: 0, - arcrftWdth: 0, - arcrftHght: 0, - arcrftWght: 0, - takeoffWght: 0, - createUserId: 'palnet', - createDt: '2023-11-15 16:22:46', - updateUserId: 'palnet', - updateDt: '2023-11-15 16:22:46', - docState: 'R', - acrftInsuranceYn: 'N', - arcrftWghtCd: 'W250G_LOE' - } - ], - pilotList: [ - { - planPilotSno: 242, - planSno: 244, - cstmrSno: 2, - groupNm: 'KAC', - memberName: '팔네트웍스', - email: 'dhji@palnet.co.kr', - hpno: '01082504456', - clncd: '+82', - createUserId: 'palnet', - createDt: '2023-11-15 16:22:46', - updateUserId: 'palnet', - updateDt: '2023-11-15 16:22:46', - docState: 'R' - } - ], - arcrftWght: '최대이륙중량 250g 이하', - elev: '100' - } -]; -export const dummyCircle = [ - { - planSno: 239, - groupId: 'C807F9', - cstmrSno: 2, - memberName: '팔네트웍스', - email: 'dhji@palnet.co.kr', - hpno: '01082504456', - clncd: '+82', - schFltStDt: '2023-11-14 12:01:00', - schFltEndDt: '2023-11-14 13:56:00', - fltPurpose: 'TRAFFIC_MANAGEMENT', - fltType: 'COMMERCIAL', - fltTypeNm: '상업용', - aprvlYn: 'Y', - createUserId: 'palnet', - createDt: '2023-11-13 11:59:10', - updateUserId: 'palnet', - updateDt: '2023-11-13 11:59:13', - serviceType: 'PAV-KAC', - corpRegYn: 'N', - pdfUrl: '/api/comn/file/download/382', - areaList: [ - { - planAreaSno: 239, - planSno: 239, - areaType: 'CIRCLE', - fltMethod: 'CLOCK_FLIGHT', - fltAreaAddr: '인천광역시 부평구 401', - bufferZone: 100, - fltElev: '12', - createUserId: 'palnet', - createDt: '2023-11-13 11:59:10', - updateUserId: 'palnet', - updateDt: '2023-11-13 11:59:10', - docState: 'R', - coordList: [ - { - planAreaCoordSno: 507, - planAreaSno: 239, - lat: 37.52165750816398, - lon: 126.71042734097875, - createUserId: 'palnet', - createDt: '2023-11-13 11:59:10', - docState: 'R' - } - ] - } - ], - arcrftList: [ - { - planArcrftSno: 235, - planSno: 239, - arcrftSno: 0, - idntfNum: 'PA0001', - arcrftTypeCd: 'UNMANNED_AIRCRAFT', - arcrftLngth: 0, - arcrftWdth: 0, - arcrftHght: 0, - arcrftWght: 0, - takeoffWght: 0, - createUserId: 'palnet', - createDt: '2023-11-13 11:59:10', - updateUserId: 'palnet', - updateDt: '2023-11-13 11:59:10', - docState: 'R', - acrftInsuranceYn: 'N', - arcrftWghtCd: 'W250G_LOE' - } - ], - pilotList: [ - { - planPilotSno: 237, - planSno: 239, - cstmrSno: 2, - groupNm: 'KAC', - memberName: '팔네트웍스', - email: 'dhji@palnet.co.kr', - hpno: '01082504456', - clncd: '+82', - createUserId: 'palnet', - createDt: '2023-11-13 11:59:10', - updateUserId: 'palnet', - updateDt: '2023-11-13 11:59:10', - docState: 'R' - } - ], - elev: '12', - arcrftWght: '최대이륙중량 250g 이하' - } -]; - -export default function DronPlan({ map, planGeo, setPlanGeo }) { +export const DronPlan = ({ map, planGeo, setPlanGeo }) => { const { controlGpList } = useSelector(state => state.controlGpState); + + // 비행예상경로 목록 const { controlGpFltPlanList } = useSelector( state => state.controlGpFltPlanState ); - const [objArr, setObjArr] = useState([]); - const [areaArr, setAreaArr] = useState([]); - const [bufferArr, setBufferArr] = useState([]); + // 비행중인 기체의 controlId 목록 const [controlIdArr, setControlIdArr] = useState([]); useEffect(() => { if (controlGpFltPlanList) { - console.log(controlGpFltPlanList, 'planList'); planInit(); } }, [controlGpFltPlanList]); - // useEffect(() => { - // planInit(); - // }, []); - useEffect(() => { if (controlGpList) { const listArr = controlGpList.map(gpList => { @@ -439,6 +32,7 @@ export default function DronPlan({ map, planGeo, setPlanGeo }) { } }, [controlGpList]); + // 비행예상경로 geoJson 업데이트 const updatePlanGeo = feature => { setPlanGeo(prev => ({ ...prev, @@ -446,11 +40,8 @@ export default function DronPlan({ map, planGeo, setPlanGeo }) { })); }; + // 비행예상경로 생성 준비 셋팅 const planInit = () => { - // const planList = dummyPolyline; - // const planList = dummyPolygon; - // const planList = dummyCircle; - const planList = controlGpFltPlanList; planList.forEach(plan => { const areaList = plan.areaList; @@ -480,6 +71,7 @@ export default function DronPlan({ map, planGeo, setPlanGeo }) { map?.getSource('plan').setData(planGeo); }; + // circle 비행예상경로 생성 const createCircle = (paths, bufferZone, idntfNum) => { const center = [paths[0][0], paths[0][1]]; const circlePaths = handlerGetCircleCoord(center, bufferZone); @@ -494,10 +86,10 @@ export default function DronPlan({ map, planGeo, setPlanGeo }) { properties: { id: 'circle', idntfNum: idntfNum } }; updatePlanGeo(circle); - setObjArr(prev => [...prev, { idntfNum: idntfNum, obj: circle }]); } }; + // polygon 비행예상경로 생성 const createPolygon = (paths, idntfNum) => { if (paths && paths[0].length > 2) { const polygon = { @@ -509,10 +101,10 @@ export default function DronPlan({ map, planGeo, setPlanGeo }) { properties: { id: 'polygon', idntfNum: idntfNum } }; updatePlanGeo(polygon); - setObjArr(prev => [...prev, { idntfNum: idntfNum, obj: polygon }]); } }; + // wayPoint 비행예상경로 생성 const createWayPoint = (paths, bufferList, idntfNum) => { if (paths && paths.length > 1) { const line = { @@ -524,7 +116,6 @@ export default function DronPlan({ map, planGeo, setPlanGeo }) { properties: { id: 'line', idntfNum: idntfNum } }; updatePlanGeo(line); - setObjArr(prev => [...prev, { idntfNum: idntfNum, obj: line }]); } if (bufferList && bufferList.length > 1) { @@ -543,32 +134,23 @@ export default function DronPlan({ map, planGeo, setPlanGeo }) { properties: { id: 'buffer', idntfNum: idntfNum } }; updatePlanGeo(buffer); - setObjArr(prev => [...prev, { idntfNum: idntfNum, obj: buffer }]); } }; + // 표출된 비행예상경로 삭제 const clear = diffArr => { - if (objArr) { - const clearObj = objArr - .filter(obj => diffArr.includes(obj.idntfNum)) - .map(obj => obj.obj); - - clearObj.map(obj => { - const feature = planGeo.features.filter( - geo => geo.properties.idntfNum !== obj.properties.idntfNum - ); - setPlanGeo(prev => ({ - ...prev, - features: feature - })); - }); - - const saveObj = objArr.filter(obj => !diffArr.includes(obj.idntfNum)); - setObjArr(saveObj); + if (planGeo.features.length > 0) { + const existObj = planGeo.features.filter( + obj => !diffArr.includes(obj.properties.idntfNum) + ); + setPlanGeo(prev => ({ + ...prev, + features: existObj + })); } map?.getSource('plan').setData(planGeo); }; return null; -} +}; diff --git a/src/components/map/mapbox/dron/DronToast.js b/src/components/map/mapbox/dron/DronToast.js index 6f86c63..fa19edc 100644 --- a/src/components/map/mapbox/dron/DronToast.js +++ b/src/components/map/mapbox/dron/DronToast.js @@ -12,16 +12,20 @@ import { import Avatar from '../../../../@core/components/avatar'; import { Info } from 'react-feather'; -export default function DronToast() { +export const DronToast = () => { const dispatch = useDispatch(); const [playing, toggle] = useAudio(warning); + + // 비정상상황 목록 const { controlGpArcrftWarnList } = useSelector( state => state.controlGpLogState ); + const [toastId, setToastId] = useState(); let warningList = []; + // 비정상 toast표출 및 알림음 재생 useEffect(() => { if (controlGpArcrftWarnList) { if (!toastId) { @@ -64,6 +68,7 @@ export default function DronToast() { } }, [controlGpArcrftWarnList]); + // 기체 클릭 시 const handlerToastClick = (controlId, idntfNum) => { dispatch(objectClickAction(controlId)); dispatch(controlGpDtlAction.request(controlId)); @@ -93,4 +98,4 @@ export default function DronToast() { }; return null; -} +}; diff --git a/src/components/map/mapbox/feature/FeatureAirZone.js b/src/components/map/mapbox/feature/FeatureAirZone.js index a976a54..8093055 100644 --- a/src/components/map/mapbox/feature/FeatureAirZone.js +++ b/src/components/map/mapbox/feature/FeatureAirZone.js @@ -1,17 +1,10 @@ -import { useEffect, useState } from 'react'; -import { useSelector } from 'react-redux'; +import { useEffect } from 'react'; import * as turf from '@turf/turf'; import geoJson from '../../../../components/map/geojson/airArea.json'; import '../../../../assets/css/custom.css'; // 격자 공역 Source const airPort = [ - // { - // title: '김포공항', - // buffer: 9300, - // center: [126.793722, 37.558522], - // reduce: [54.4, 218.6, 500, 905.4, 1459.8, 2195, 3173.5, 4552.5, 6952.5] - // }, { title: '인천공항', buffer: 9300, @@ -33,14 +26,13 @@ const airPort = [ ]; export const FeatureAirZone = props => { - const mapControl = useSelector(state => state.controlMapReducer); let popup; - let infoWindow; useEffect(() => { featureAirZoneInit(); }, []); + // 공역 정보 표출 window 생성 const infowindowOpen = data => { const content = '
' + @@ -74,6 +66,7 @@ export const FeatureAirZone = props => { .addTo(props.map); }; + // 공역 정보 표출 이벤트 로직 const featureAirEvent = markers => { markers.forEach(marker => { marker.getElement().addEventListener('mouseover', e => { @@ -323,8 +316,6 @@ export const FeatureAirZone = props => { 'line-opacity': opacity } }); - - // Grid area }; return null; diff --git a/src/utility/DrawUtil.js b/src/utility/MapUtils.js similarity index 74% rename from src/utility/DrawUtil.js rename to src/utility/MapUtils.js index 19cb367..d5266fd 100644 --- a/src/utility/DrawUtil.js +++ b/src/utility/MapUtils.js @@ -2,6 +2,9 @@ import * as turf from '@turf/turf'; import mapboxgl from 'mapbox-gl'; import 'mapbox-gl/dist/mapbox-gl.css'; +import geoJson from '../components/map/geojson/airArea.json'; +import flatGimpo from '../components/map/geojson/flatGimpoAirportAirArea.json'; + // geojson Feature 형식으로 반환 export const InitFeature = (type, id) => { return { @@ -234,3 +237,73 @@ export const layerBuffer = source => { filter: ['==', ['get', 'id'], 'buffer'] }; }; + +// 공역 생성 +export const handlerCreateAirSpace = ( + map, + mapControl, + useGeoJson = { + ...geoJson, + ...flatGimpo, + features: [...geoJson.features, ...flatGimpo.features] + } +) => { + if (map.getLayer('maine')) { + map.removeLayer('maine'); + map.removeSource('maine'); + } + let arrGeoJson = []; + useGeoJson.features.map(item => { + if (item.properties.type === '0001' && mapControl.area0001) { + arrGeoJson.push({ + ...item, + properties: { ...item.properties, color: '#FF3648' } + }); + } else if (item.properties.type === '0002' && mapControl.area0002) { + arrGeoJson.push({ + ...item, + properties: { ...item.properties, color: '#FFA1AA' } + }); + } else if (item.properties.type === '0003' && mapControl.area0003) { + arrGeoJson.push({ + ...item, + properties: { ...item.properties, color: '#FFA800' } + }); + } else if (item.properties.type === '0004' && mapControl.area0004) { + arrGeoJson.push({ + ...item, + properties: { ...item.properties, color: '#A16B00' } + }); + } else if (item.properties.type === '0005' && mapControl.area0005) { + arrGeoJson.push({ + ...item, + properties: { ...item.properties, color: '#AB40FF' } + }); + } else if (item.properties.type === '0006' && mapControl.area0006) { + arrGeoJson.push({ + ...item, + properties: { ...item.properties, color: '#009cad' } + }); + } + }); + useGeoJson.features = arrGeoJson.filter(i => i.geometry.type === 'Polygon'); + + // 공역 생성 start + map.addSource('maine', { + type: 'geojson', + data: { + ...useGeoJson + } + }); + map.addLayer({ + id: 'maine', + type: 'fill', + source: 'maine', + layout: {}, + paint: { + 'fill-color': ['get', 'color'], + // 'fill-extrusion-height': 3000, + 'fill-opacity': 0.5 + } + }); +};