Bläddra i källkod

粤政图 标注点信息弹窗

Hwf 4 månader sedan
förälder
incheckning
8eb5ec4024
7 ändrade filer med 2092 tillägg och 4258 borttagningar
  1. 1 0
      package.json
  2. 1549 0
      pnpm-lock.yaml
  3. 246 55
      src/components/Map/YztMap/index.vue
  4. 106 0
      src/components/Map/data.ts
  5. 1 83
      src/components/Map/index.vue
  6. 0 4120
      src/components/Map/mapData.ts
  7. 189 0
      src/utils/gisUtils.ts

+ 1 - 0
package.json

@@ -20,6 +20,7 @@
   "dependencies": {
     "@amap/amap-jsapi-loader": "^1.0.1",
     "@element-plus/icons-vue": "^2.3.1",
+    "@turf/turf": "^7.2.0",
     "@types/file-saver": "^2.0.7",
     "@types/uuid": "^10.0.0",
     "@vueuse/core": "^11.0.3",

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1549 - 0
pnpm-lock.yaml


+ 246 - 55
src/components/Map/YztMap/index.vue

@@ -1,13 +1,26 @@
 <template>
   <div ref="containerRef" class="map-container">
-    <div ref="mapRef" id="YztMap" class="map-container" :style="{ width: width, height: height }"></div>
+    <div
+        ref="mapRef"
+        id="YztMap"
+        class="map-container"
+        :style="{
+        width: width,
+        height: height
+      }"
+    />
   </div>
 </template>
 
 <script setup lang="ts">
-import 'ol/ol.css';
+import mmJson from '@/assets/json/mm2.json';
 import { olMap } from '@/utils/olMap/olMap';
 import { PointType } from '@/api/globalMap/type';
+import { ScaleLine } from 'ol/control';
+import { getPointInfoList } from '@/api/globalMap';
+import { getDictLabel } from '@/utils/dict';
+import { methodList, titleList } from '../data';
+import { pointDetailTemplate } from '../mapData';
 
 interface Props {
   activeMap: string;
@@ -15,7 +28,9 @@ interface Props {
 }
 const containerScale = inject('containerScale');
 const props = withDefaults(defineProps<Props>(), {});
-const emits = defineEmits(['update:drawing', 'selectGraphics']);
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { point_type } = toRefs<any>(proxy?.useDict('point_type'));
+const emits = defineEmits(['update:drawing', 'selectGraphics', 'handleShowWarehouse', 'handleShowVideo', 'handleShowPeople']);
 
 const mapRef = ref(null);
 const mapState = reactive({
@@ -30,35 +45,38 @@ const mapState = reactive({
 const containerRef = ref();
 const width = ref('100%');
 const height = ref('100%');
-let yztMap, map;
+let map, mapUtils;
 
 // 监听是否开启绘制
 watch(
-  () => props.drawing,
-  (value) => {
-    if (value) {
-      map.drawGraphics(props.graphicsType);
-    } else {
-      map.closeDraw();
+    () => props.drawing,
+    (value) => {
+      if (value) {
+        mapUtils.drawGraphics(props.graphicsType);
+      } else {
+        mapUtils.closeDraw();
+      }
     }
-  }
 );
-
+const mapList = reactive({
+  satellite2: ['YZT1715739306532', 'YZT1695608158269'],
+  satellite3: ['YZT1708679726700', 'YZT1695608158269'],
+  imageMap: ['YZT1640925052482', 'YZT1695608158269'],
+  imageMap2: ['YZT1640925052482', 'YZT1695608158269']
+});
 // 监听地图类型变化
 watch(
-  () => props.activeMap,
-  () => {
-    if (!map) return;
-    const id = props.activeMap === 'satellite2' ? ['YZT1715739306532', 'YZT1695608158269'] : ['YZT1708679726700', 'YZT1695608158269'];
-    map.replaceLayers(id);
-  }
+    () => props.activeMap,
+    () => {
+      if (!mapUtils) return;
+      mapUtils.replaceLayers(mapList[props.activeMap]);
+    }
 );
-
+let scale;
 const init = () => {
-  const id = props.activeMap === 'satellite2' ? ['YZT1715739306532', 'YZT1695608158269'] : ['YZT1708679726700', 'YZT1695608158269'];
-  map = new olMap({
+  mapUtils = new olMap({
     dom: mapRef.value,
-    id: id,
+    id: mapList[props.activeMap],
     center: mapState.center,
     zoom: mapState.zoom,
     minZoom: mapState.minZoom,
@@ -81,54 +99,222 @@ const init = () => {
       }
     },
     // 加载完成事件
-    onLoadCompleted: (yMap) => {
-      yztMap = yMap;
-      // initMouseTool(map);
+    onLoadCompleted: (YztMap) => {
+      map = YztMap;
+      // initMouseTool(mapUtils);
+      scale = new ScaleLine();
+      map.addControl(scale);
+      map.getView().on('change:resolution', () => {
+        mapState.zoom = map.getView().getZoom().toFixed(2);
+      });
       handleResize();
+    },
+    onMarkerClick: (data) => {
+      // 多点位
+      if (data.type === '1') {
+        let path = [];
+        props.pointType.forEach((item) => {
+          path.push(item.component);
+        });
+        getPointInfoList({
+          option: path.toString(),
+          longitude: data.longitude.toString(),
+          latitude: data.latitude.toString()
+        }).then((res) => {
+          const data2 = res.data.list;
+          let content = document.createElement('div');
+          // content.style.cssText = 'transform: scale(' + containerScale().scaleX + ');';
+          content.className = 'point-info';
+          let content2 = '';
+          content2 += '<div class="title-box"><div class="gradient-text">多点位信息</div></div>';
+          content2 += '<div class="icon1"></div>';
+          content2 += '<div class="icon2"></div>';
+          content2 += '<div class="icon3"></div>';
+          content2 += '<div class="icon4"></div>';
+          content.innerHTML = content2;
+          let tableBox = document.createElement('div');
+          tableBox.className = 'table-box';
+          let table = document.createElement('div');
+          table.className = 'table';
+          table.innerHTML = '<div class="point-item"><div class="td3">主题</div><div class="td3">名称</div></div>';
+          data2.forEach((item) => {
+            item.longitude = data.longitude;
+            item.latitude = data.latitude;
+            const div = document.createElement('div');
+            div.className = 'point-item point-item-hover';
+            div.innerHTML =
+                '<div class="td4">' + getDictLabel(point_type.value, item.dataType.toString()) + '</div><div class="td4">' + item.name + '</div>';
+            div.addEventListener('click', () => {
+              handlePointDetails(item);
+            });
+            table.appendChild(div);
+          });
+          tableBox.appendChild(table);
+          content.appendChild(tableBox);
+          let closeBtn = document.createElement('div');
+          closeBtn.className = 'close';
+          closeBtn.onclick = () => mapUtils.hideInfo(true);
+          content.appendChild(closeBtn);
+          mapUtils.showInfo(content, [data.longitude, data.latitude], true);
+        });
+      } else {
+        handlePointDetails(data);
+      }
     }
   });
 };
-const addMarker = (points) => {
-  map.addMarker(points);
+const handlePointDetails = (data) => {
+  let method = methodList[data.dataType];
+  let title = !!titleList[data.dataType] ? titleList[data.dataType] : '信息';
+  if (!method) return;
+  method(data.id).then((res) => {
+    if (!!pointDetailTemplate[data.dataType]) {
+      let div = document.createElement('div');
+      // div.style.cssText = 'transform: scale(' + containerScale().scaleX + ');';
+      div.className = 'point-info';
+      let titleDom = document.createElement('div');
+      titleDom.className = 'title-box';
+      titleDom.innerHTML = '<div class="gradient-text">' + title + '</div></div>';
+      div.appendChild(titleDom);
+      if (data.dataType === 2) {
+        let btnBox = document.createElement('div');
+        let btn = document.createElement('div');
+        btnBox.className = 'flex';
+        btn.className = 'btn';
+        btn.innerHTML = '<div class="video-icon"></div><div>物资详情</div>';
+        btn.onclick = () => {
+          emits('handleShowWarehouse', data);
+        };
+        btnBox.appendChild(btn);
+        div.appendChild(btnBox);
+      } else if (data.dataType === 4) {
+        let btnBox = document.createElement('div');
+        let btn = document.createElement('div');
+        btnBox.className = 'flex';
+        btn.className = 'btn';
+        btn.innerHTML = '<div class="video-icon"></div><div>附近视频</div>';
+        btn.onclick = () => {
+          emits('handleShowVideo', data);
+        };
+        btnBox.appendChild(btn);
+        div.appendChild(btnBox);
+      } else if (data.dataType === 41) {
+        let btnBox = document.createElement('div');
+        let btn = document.createElement('div');
+        btnBox.className = 'flex';
+        btn.className = 'btn';
+        btn.innerHTML = '<div class="video-icon"></div><div>人员列表</div>';
+        btn.onclick = () => {
+          emits('handleShowPeople', data);
+        };
+        btnBox.appendChild(btn);
+        div.appendChild(btnBox);
+      }
+      let icon1 = document.createElement('div');
+      icon1.className = 'icon1';
+      let icon2 = document.createElement('div');
+      icon2.className = 'icon2';
+      let icon3 = document.createElement('div');
+      icon3.className = 'icon3';
+      let icon4 = document.createElement('div');
+      icon4.className = 'icon4';
+      div.appendChild(icon1);
+      div.appendChild(icon2);
+      div.appendChild(icon3);
+      div.appendChild(icon4);
+      let table = document.createElement('div');
+      table.className = 'table-box';
+      let content = '';
+      content += '<div class="table">';
+      const newData = filterTd(res.rows[0], data.dataType);
+      newData.forEach((item) => {
+        if (item.type === 'shortText') {
+          content += '<div class="tr">';
+          item.data.forEach((item2) => {
+            content += '<div class="point-item">';
+            content += '<div class="td1">' + item2.label + '</div><div class="td2">' + item2.value + '</div>';
+            content += '</div>';
+          });
+          content += '</div>';
+        } else {
+          content += '<div class="point-item2">';
+          content += '<div class="td1">' + item.data[0].label + '</div><div class="td2">' + item.data[0].value + '</div>';
+          content += '</div>';
+        }
+      });
+      content += '</div>';
+      table.innerHTML = content;
+      div.appendChild(table);
+      let closeBtn = document.createElement('div');
+      closeBtn.className = 'close';
+      closeBtn.onclick = () => mapUtils.hideInfo(true);
+      div.appendChild(closeBtn);
+      mapUtils.showInfo(div, [data.longitude, data.latitude], true);
+    }
+  });
 };
-// 设置地图层级
-const setMapZoom = (value) => {
-  if (!yztMap) return;
-  const view = yztMap.map.getView();
-  if (value === 1) {
-    view.setCenter([113.280637, 23.125178]);
-    view.setZoom(7);
-  } else if (value === 2) {
-    view.setCenter([110.925175, 21.678955]);
-    view.setZoom(11);
-  } else if (value === 3) {
-    view.setCenter([110.925175, 21.678955]);
-    view.setZoom(12);
-  } else if (value === 4) {
-    view.setCenter([110.925175, 21.678955]);
-    view.setZoom(15);
-  } else if (value === 5) {
-    view.setCenter([110.925175, 21.678955]);
-    view.setZoom(16);
+const filterTd = (obj, dataType) => {
+  let data = [];
+  let tempData = {};
+  let i = 0;
+  for (let key in obj) {
+    let keyLabel = pointDetailTemplate[dataType][key];
+    if (!!keyLabel) {
+      if (i === 2) {
+        i = 0;
+      }
+      const value = !!obj[key] ? obj[key] : '';
+      if (value && value.length > 8) {
+        if (i === 0) {
+          data.push({ type: 'longText', data: [{ label: keyLabel, value: value }] });
+          i = 0;
+        } else {
+          tempData = { type: 'longText', data: [{ label: keyLabel, value: value }] };
+        }
+      } else {
+        if (i === 0) {
+          data.push({ type: 'shortText', data: [{ label: keyLabel, value: value }] });
+        } else {
+          data[data.length - 1].data.push({ label: keyLabel, value: value });
+        }
+        i++;
+        if (!!tempData && JSON.stringify(tempData) !== '{}') {
+          data.push(tempData);
+          tempData = {};
+          i = 0;
+        }
+      }
+    }
   }
+  if (!!tempData && JSON.stringify(tempData) !== '{}') {
+    data.push(tempData);
+  }
+  if (data[data.length - 1].data && data[data.length - 1].data.length === 1 && data[data.length - 1].type === 'shortText') {
+    data[data.length - 1].data[1] = { label: '', value: '' };
+  }
+  return data;
 };
-// 切换2D、3D
-const switchThreeDimensional = () => {
-  const view = yztMap.map.getView();
-  mapState.isThreeDimensional = !mapState.isThreeDimensional;
-  const pitch = mapState.isThreeDimensional ? 45 : 0;
-  view.setPitch(pitch);
+const addMarker = (points) => {
+  mapUtils.addMarker(points);
 };
 const clearMarker = () => {
-  this.map.clearMarker();
+  mapUtils.clearMarker();
 };
-defineExpose({ addMarker, clearMarker });
 const handleResize = () => {
   const containerWidth = containerRef.value.clientWidth * containerScale().scaleX;
   const containerHeight = containerRef.value.clientHeight * containerScale().scaleY;
   width.value = containerWidth + 'px';
   height.value = containerHeight + 'px';
-  yztMap.updateSize();
+  map.updateSize();
+};
+const getMap = () => {
+  return map;
+};
+const getScale = () => {
+  return scale;
+};
+const getMapUtils = () => {
+  return mapUtils;
 };
 // 加载事件
 onMounted(() => {
@@ -139,9 +325,14 @@ onMounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', handleResize);
 });
+provide('getMapUtils', getMapUtils);
+provide('getMap', getMap);
+provide('getScale', getScale);
+defineExpose({ getMapUtils, addMarker, clearMarker });
 </script>
 
 <style scoped>
+@import '../map.scss';
 .map-container {
   width: 100%;
   height: 100%;

+ 106 - 0
src/components/Map/data.ts

@@ -0,0 +1,106 @@
+import {
+  getEmergencyExpertDetails,
+  getEmergencyShelterTypeDetails,
+  getGasolinestationDetails,
+  getHospitalDetails,
+  getMiningcompanyDetails,
+  getWarehouseDetails,
+  getChemicalcompanyDetails,
+  getSchoolDetails,
+  getWaterloggedRoadsDetails,
+  getShipRealtilmePositionDetails,
+  getUAVDetails,
+  getRainbowDetails,
+  getTouristAttractionDetails,
+  getConstructionSitesDetails,
+  getYardSitesDetails,
+  getStationInfoDetails,
+  getMajorHazardSourceDetails,
+  getBuildingProjectDetails,
+  getChemicalWarehouseDetails,
+  getMiningOperationsDetails,
+  getEmergencyTransportResourcesDetails,
+  getEmergencyDisasterInfoOfficerDetails,
+  getMidmapDzzhDetails,
+  getVehicleDetails,
+  getMDPUnitDetails,
+  getWaterList,
+  getVideoDrowning,
+  getVideoForestFire,
+  getVideoDisasterPrevention
+} from '@/api/globalMap/spatialAnalysis';
+import { getRescueTeamsInfo } from '@/api/globalMap/rescueTeam';
+
+export const methodList = {
+  '1': getEmergencyExpertDetails,
+  '2': getWarehouseDetails,
+  '3': getEmergencyShelterTypeDetails,
+  '4': getWaterloggedRoadsDetails,
+  '5': getSchoolDetails,
+  '6': getHospitalDetails,
+  '7': getGasolinestationDetails,
+  '8': getMiningcompanyDetails,
+  // '9': getChemicalcompanyDetails,
+  '10': getShipRealtilmePositionDetails,
+  '11': getChemicalcompanyDetails,
+  '12': getChemicalcompanyDetails,
+  '13': getChemicalcompanyDetails,
+  '14': getChemicalcompanyDetails,
+  '15': getUAVDetails,
+  '16': getRainbowDetails,
+  '17': getMidmapDzzhDetails,
+  '18': getMiningOperationsDetails,
+  '20': getMDPUnitDetails,
+  '21': getBuildingProjectDetails,
+  '22': getChemicalWarehouseDetails,
+  '23': getMajorHazardSourceDetails,
+  '24': getStationInfoDetails,
+  '25': getYardSitesDetails,
+  '26': getTouristAttractionDetails,
+  '27': getConstructionSitesDetails,
+  '28': getEmergencyTransportResourcesDetails,
+  '29': getEmergencyDisasterInfoOfficerDetails,
+  '30': getVehicleDetails,
+  '31': getWaterList,
+  '32': getVideoDrowning,
+  '33': getVideoForestFire,
+  '34': getVideoDisasterPrevention,
+  '41': getRescueTeamsInfo
+};
+export const titleList = {
+  '1': '专家信息',
+  '2': '物资与装备仓库信息',
+  '3': '避难所信息',
+  '4': '易涝点信息',
+  '5': '学校信息',
+  '6': '医院信息',
+  '7': '加油站信息',
+  '8': '非煤矿山企业信息',
+  '9': '危化企业信息',
+  '10': '船舶动态信息',
+  '11': '危险化学品经营企业信息',
+  '12': '危险化学品生产企业信息',
+  '13': '危险化学品使用企业(使用许可)信息',
+  '14': '化工企业(不发使用许可)信息',
+  '15': '无人机信息',
+  '16': '雨窝点',
+  '17': '地质灾害隐患点',
+  '18': '矿山施工',
+  '19': '工矿商贸',
+  '20': '气象灾害防御重点单位',
+  '21': '建筑工程',
+  '22': '储罐信息',
+  '23': '重大危险源',
+  '24': '客运站',
+  '25': '堆场',
+  '26': '旅游场所',
+  '27': '在建工地',
+  '28': '运输资源',
+  '29': '灾害信息员',
+  '30': '重点车辆信息',
+  '31': '江湖河库',
+  '32': '防溺水',
+  '33': '森林防火',
+  '34': '防灾救援',
+  '41': '救援队伍'
+};

+ 1 - 83
src/components/Map/index.vue

@@ -8,32 +8,9 @@
 import { useAMap } from '@/hooks/AMap/useAMap';
 import { useDrawTool } from '@/hooks/AMap/useDrawTool';
 import { getDictLabel } from '@/utils/dict';
-import {
-  getEmergencyExpertDetails,
-  getEmergencyShelterTypeDetails,
-  getGasolinestationDetails,
-  getHospitalDetails,
-  getMiningcompanyDetails,
-  getWarehouseDetails,
-  getChemicalcompanyDetails,
-  getSchoolDetails,
-  getWaterloggedRoadsDetails,
-  getShipRealtilmePositionDetails,
-  getUAVDetails,
-  getRainbowDetails,
-  getTouristAttractionDetails,
-  getConstructionSitesDetails,
-  getYardSitesDetails,
-  getStationInfoDetails,
-  getMajorHazardSourceDetails,
-  getBuildingProjectDetails,
-  getChemicalWarehouseDetails,
-  getMiningOperationsDetails,
-  getEmergencyTransportResourcesDetails, getEmergencyDisasterInfoOfficerDetails
-} from '@/api/globalMap/spatialAnalysis';
 import { pointDetailTemplate } from './mapData';
 import {getPointInfoList} from "@/api/globalMap";
-import {getCurrentInstance, inject, nextTick, onMounted, onUnmounted, reactive, ref, toRefs, watch} from "vue";
+import { methodList, titleList } from './data';
 interface EventDetails {
   'event_id': String;
   'event_title': String;
@@ -165,65 +142,6 @@ const {
   trackPlayback
 } = { ...mapUtils };
 const handlePointDetails = (data) => {
-  let methodList = {
-    '1': getEmergencyExpertDetails,
-    '2': getWarehouseDetails,
-    '3': getEmergencyShelterTypeDetails,
-    '4': getWaterloggedRoadsDetails,
-    '5': getSchoolDetails,
-    '6': getHospitalDetails,
-    '7': getGasolinestationDetails,
-    '8': getMiningcompanyDetails,
-    // '9': getChemicalcompanyDetails,
-    '10': getShipRealtilmePositionDetails,
-    '11': getChemicalcompanyDetails,
-    '12': getChemicalcompanyDetails,
-    '13': getChemicalcompanyDetails,
-    '14': getChemicalcompanyDetails,
-    '15': getUAVDetails,
-    '16': getRainbowDetails,
-    '18': getMiningOperationsDetails,
-    '21': getBuildingProjectDetails,
-    '22': getChemicalWarehouseDetails,
-    '23': getMajorHazardSourceDetails,
-    '24': getStationInfoDetails,
-    '25': getYardSitesDetails,
-    '26': getTouristAttractionDetails,
-    '27': getConstructionSitesDetails,
-    '28': getEmergencyTransportResourcesDetails,
-    '29': getEmergencyDisasterInfoOfficerDetails
-  };
-  let titleList = {
-    '1': '专家信息',
-    '2': '物资与装备仓库信息',
-    '3': '避难所信息',
-    '4': '易涝点信息',
-    '5': '学校信息',
-    '6': '医院信息',
-    '7': '加油站信息',
-    '8': '非煤矿山企业信息',
-    '9': '危化企业信息',
-    '10': '船舶动态信息',
-    '11': '危险化学品经营企业信息',
-    '12': '危险化学品生产企业信息',
-    '13': '危险化学品使用企业(使用许可)信息',
-    '14': '化工企业(不发使用许可)信息',
-    '15': '无人机信息',
-    '16': '雨窝点',
-    '17': '地质灾害隐患点',
-    '18': '矿山施工',
-    '19': '工矿商贸',
-    '20': '气象灾害防御重点单位',
-    '21': '建筑工程',
-    '22': '储罐',
-    '23': '重大危险源',
-    '24': '客运站',
-    '25': '堆场',
-    '26': '旅游场所',
-    '27': '在建工地',
-    '28': '运输资源',
-    '29': '灾害信息员'
-  };
   let method = methodList[data.dataType];
   let title = !!titleList[data.dataType] ? titleList[data.dataType] : '信息';
   if (!method) return;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 4120
src/components/Map/mapData.ts


+ 189 - 0
src/utils/gisUtils.ts

@@ -0,0 +1,189 @@
+import * as turf from '@turf/turf';
+//转换常数
+const x_pi = (3.14159265358979324 * 3000.0) / 180.0;
+const pi = 3.14159265358979324;
+const a = 6378245.0;
+const ee = 0.00669342162296594323;
+
+function transformLon(x, y) {
+  let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
+  ret += ((20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0) / 3.0;
+  ret += ((20.0 * Math.sin(x * pi) + 40.0 * Math.sin((x / 3.0) * pi)) * 2.0) / 3.0;
+  ret += ((150.0 * Math.sin((x / 12.0) * pi) + 300.0 * Math.sin((x / 30.0) * pi)) * 2.0) / 3.0;
+  return ret;
+}
+
+function transformLat(x, y) {
+  let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
+  ret += ((20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0) / 3.0;
+  ret += ((20.0 * Math.sin(y * pi) + 40.0 * Math.sin((y / 3.0) * pi)) * 2.0) / 3.0;
+  ret += ((160.0 * Math.sin((y / 12.0) * pi) + 320 * Math.sin((y * pi) / 30.0)) * 2.0) / 3.0;
+  return ret;
+}
+// 判断是否在国内
+function outOfChina(lat, lon) {
+  if (lon < 72.004 || lon > 137.8347) return true;
+  if (lat < 0.8293 || lat > 55.8271) return true;
+  return false;
+}
+
+/*
+ WGS-84转换GCJ-02
+(即 天地图转高德、腾讯地图)
+[{lat: 21, lng: 110}]
+ */
+export const wgs_gcj_encrypts = (latlngs) => {
+  const point = [];
+  for (const latlng of latlngs) {
+    if (outOfChina(latlng.lat, latlng.lng)) {
+      point.push({
+        lat: latlng.lat,
+        lng: latlng.lng
+      });
+      return point;
+    }
+    let dLat = transformLat(latlng.lng - 105.0, latlng.lat - 35.0);
+    let dLon = transformLon(latlng.lng - 105.0, latlng.lat - 35.0);
+    const radLat = (latlng.lat / 180.0) * pi;
+    let magic = Math.sin(radLat);
+    magic = 1 - ee * magic * magic;
+    const sqrtMagic = Math.sqrt(magic);
+    dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * pi);
+    dLon = (dLon * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * pi);
+    const lat = latlng.lat + dLat;
+    const lng = latlng.lng + dLon;
+    point.push({
+      lat: lat,
+      lng: lng
+    });
+  }
+  return point;
+};
+
+/*
+ WGS-84转换GCJ-02
+(即 天地图转高德、腾讯地图)
+[[21,110]]
+ */
+export const wgs_gcj_encrypts2 = (latlngs) => {
+  const point = [];
+  for (const latlng of latlngs) {
+    // if (outOfChina(latlng[0], latlng[1])) {
+    //   point.push({
+    //     lat: latlng[0],
+    //     lng: latlng[1]
+    //   });
+    //   return point;
+    // }
+    let dLat = transformLat(latlng[1] - 105.0, latlng[0] - 35.0);
+    let dLon = transformLon(latlng[1] - 105.0, latlng[0] - 35.0);
+    const radLat = (latlng[0] / 180.0) * pi;
+    let magic = Math.sin(radLat);
+    magic = 1 - ee * magic * magic;
+    const sqrtMagic = Math.sqrt(magic);
+    dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * pi);
+    dLon = (dLon * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * pi);
+    const lat = latlng[0] + dLat;
+    const lng = latlng[1] + dLon;
+    point.push([lat, lng]);
+  }
+  return point;
+};
+/*
+ BD-09转换GCJ-02
+ (即 百度转高德、腾讯地图)
+ */
+export const bd_google_encrypt = (latlngs) => {
+  const point = [];
+  for (const latlng of latlngs) {
+    const x = latlng.lng - 0.0065;
+    const y = latlng.lat - 0.006;
+    const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
+    const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
+    const gg_lon = z * Math.cos(theta);
+    const gg_lat = z * Math.sin(theta);
+    point.push({
+      lat: gg_lon,
+      lng: gg_lat
+    });
+  }
+  return point;
+};
+
+/*
+ GCJ-02转换BD-09
+ (即 高德、腾讯转百度地图)
+ */
+export const google_bd_encrypt = (latlngs) => {
+  const point = [];
+  for (const latlng of latlngs) {
+    const x = latlng.lng;
+    const y = latlng.lat;
+    const z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
+    const theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
+    const bd_lon = z * Math.cos(theta) + 0.0065;
+    const bd_lat = z * Math.sin(theta) + 0.006;
+    point.push({
+      lat: bd_lat,
+      lng: bd_lon
+    });
+  }
+  return point;
+};
+
+/*
+ GCJ-02 到 WGS-84 的转换
+ (即 高德、腾讯转天地图)
+ */
+export const gcj_wgs_encrypts = (latlngs) => {
+  const point = [];
+  for (const latlng of latlngs) {
+    if (outOfChina(latlng.lat, latlng.lng)) {
+      point.push({
+        lat: latlng.lat,
+        lng: latlng.lng
+      });
+      return point;
+    }
+    let dLat = transformLat(latlng.lng - 105.0, latlng.lat - 35.0);
+    let dLon = transformLon(latlng.lng - 105.0, latlng.lat - 35.0);
+    const radLat = (latlng.lat / 180.0) * pi;
+    let magic = Math.sin(radLat);
+    magic = 1 - ee * magic * magic;
+    const sqrtMagic = Math.sqrt(magic);
+    dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * pi);
+    dLon = (dLon * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * pi);
+    const lat = dLat;
+    const lng = dLon;
+    point.push({
+      lat: lat,
+      lng: lng
+    });
+  }
+  return point;
+};
+
+// 合并边界多边形 如茂名市区级边界合并为茂名市边界
+export const mergeGeoJsonPolygons = (geoJsonData) => {
+  const polygons = geoJsonData.features.map((feature) => {
+    if (feature.geometry.type === 'Polygon') {
+      return turf.polygon(feature.geometry.coordinates);
+    } else if (feature.geometry.type === 'MultiPolygon') {
+      return turf.multiPolygon(feature.geometry.coordinates);
+    }
+  });
+  if (polygons.length <= 1) {
+    return polygons[0] || null;
+  }
+  let merged = turf.union(turf.featureCollection([polygons[0], polygons[1]]));
+  for (let i = 2; i < polygons.length; i++) {
+    merged = turf.union(turf.featureCollection([merged, polygons[i]]));
+  }
+  return merged;
+};
+
+// 获取多个坐标点的中心
+export const getPointsCenter = (points) => {
+  const features = turf.points(points);
+  return turf.center(features);
+}

Vissa filer visades inte eftersom för många filer har ändrats