Explorar el Código

坐标系转换

Hwf hace 4 meses
padre
commit
0fa9c62811

+ 64 - 7
src/hooks/AMap/useAMap.ts

@@ -1,6 +1,7 @@
 import AMapLoader from '@amap/amap-jsapi-loader';
 import { nanoid } from 'nanoid';
 import { deepClone } from '@/utils';
+import { wgs_gcj_encrypts } from '@/utils/gisUtils';
 
 export function useAMap(options) {
   let AMap, map, nowLayer, labelsLayer, scale, cluster;
@@ -266,12 +267,6 @@ export function useAMap(options) {
       });
     });
   };
-  const removeMask = () => {
-    if (!!maskPolygon) {
-      map.remove(maskPolygon);
-      maskPolygon = null;
-    }
-  };
   const creatMask2 = (data, option) => {
     // 外多边形坐标数组和内多边形坐标数组
     const outer = [
@@ -282,12 +277,13 @@ export function useAMap(options) {
     ];
     //outer
     const pathArray = [outer];
+    data = convertCoordinates(data);
     data.features.forEach((item, index) => {
       let arr = [];
       const geometry = item.geometry;
       geometry.coordinates.forEach((coordinate) => {
         if (geometry.type === 'MultiPolygon') {
-          coordinate[0].forEach(coordinate2 => {
+          coordinate[0].forEach((coordinate2) => {
             arr.push(coordinate2);
           });
           pathArray.push(arr);
@@ -309,6 +305,12 @@ export function useAMap(options) {
     });
     map.add(maskPolygon);
   };
+  const removeMask = () => {
+    if (!!maskPolygon) {
+      map.remove(maskPolygon);
+      maskPolygon = null;
+    }
+  };
   let moveMarker, movePolyline, movePassedPolyline, timerId;
   const trackPlayback = (lineArr) => {
     if (timerId) {
@@ -495,6 +497,61 @@ export function useAMap(options) {
     data.id = id;
     return { text, data };
   };
+  const convertCoordinates = (geoJson) => {
+    const features = geoJson.features.map((feature) => {
+      const geometry = feature.geometry;
+      let newGeometry;
+      if (geometry.type === 'Point') {
+        const [x, y] = geometry.coordinates;
+        const obj = wgs_gcj_encrypts([{ lng: x, lat: y }])[0];
+        newGeometry = { ...geometry, coordinates: [obj.lng, obj.lat] };
+      } else if (geometry.type === 'MultiPoint') {
+        const newCoordinates = geometry.coordinates.map((coords) => {
+          const [x, y] = coords;
+          const obj = wgs_gcj_encrypts([{ lng: x, lat: y }])[0];
+          return [obj.lng, obj.lat];
+        });
+        newGeometry = { ...geometry, coordinates: newCoordinates };
+      } else if (geometry.type === 'LineString') {
+        const newCoordinates = geometry.coordinates.map((coords) => {
+          const [x, y] = coords;
+          const obj = wgs_gcj_encrypts([{ lng: x, lat: y }])[0];
+          return [obj.lng, obj.lat];
+        });
+        newGeometry = { ...geometry, coordinates: newCoordinates };
+      } else if (geometry.type === 'MultiLineString') {
+        const newCoordinates = geometry.coordinates.map((line) =>
+          line.map((coords) => {
+            const [x, y] = coords;
+            const obj = wgs_gcj_encrypts([{ lng: x, lat: y }])[0];
+            return [obj.lng, obj.lat];
+          })
+        );
+        newGeometry = { ...geometry, coordinates: newCoordinates };
+      } else if (geometry.type === 'Polygon') {
+        const newCoordinates = geometry.coordinates.map((ring) => {
+          const obj = wgs_gcj_encrypts(ring);
+          return obj;
+        });
+        newGeometry = { ...geometry, coordinates: newCoordinates };
+      } else if (geometry.type === 'MultiPolygon') {
+        const newCoordinates = geometry.coordinates.map((polygon) =>
+          polygon.map((ring) =>
+            ring.map((coords) => {
+              const [x, y] = coords;
+              const obj = wgs_gcj_encrypts([{ lng: x, lat: y }])[0];
+              return [obj.lng, obj.lat];
+            })
+          )
+        );
+        newGeometry = { ...geometry, coordinates: newCoordinates };
+      }
+
+      return { ...feature, geometry: newGeometry };
+    });
+
+    return { ...geoJson, features };
+  };
   onMounted(() => {
     initMap(options);
   });

+ 163 - 0
src/utils/gisUtils.ts

@@ -0,0 +1,163 @@
+//转换常数
+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;
+};

+ 44 - 2
src/views/globalMap/RightMenu/MobilePlatform.vue

@@ -33,6 +33,7 @@
         </div>
       </div>
     </div>
+    <Contact v-if="shareState.showShare" v-model="shareState.showShare" @close="handleCloseShare" @confirm="handleShareConfirm" />
   </div>
 </template>
 
@@ -40,6 +41,8 @@
 import { Search } from '@element-plus/icons-vue';
 import { getMobileWorkstationList, getMobileWorkstationTrajectory } from '@/api/globalMap/MobilePlatform';
 import { onMounted, reactive } from 'vue';
+import { getStartMiniWithNoParam } from '@/api/emergencyCommandMap/communication';
+import { showSuccessMsg } from '@/utils/notification';
 const trackPlayback = inject('trackPlayback');
 // 数据列表,直接定义为数组
 const dataList = reactive([]);
@@ -69,8 +72,47 @@ const handleCancel = () => {
   queryParams.keywords = '';
   initData();
 };
-const handleConnect = () => {};
-const handleCollaborate = () => {};
+const handleConnect = () => {
+  const dev_list = [{ id: 'mmyj0010@mm.zw.yj', avtype: 'av' }];
+  const screenWidth = window.screen.width * window.devicePixelRatio;
+  const screenHeight = window.screen.height * window.devicePixelRatio;
+  const data = {
+    'userid': '', // 空表示后台获取当前用户对应融合通信dev_id
+    'password': '123',
+    roomid: '', // 空表示新会议室
+    windowpos: { 'x': 0, 'y': 0, 'width': screenWidth, 'height': screenHeight, 'top': true },
+    members: {
+      num: dev_list.length + 2, // 配置多少个座位,一般就是邀请人多少个就多少个
+      'dev-list': dev_list
+    }
+  };
+  getStartMiniWithNoParam(data).then((res) => {
+    // 创建一个a标签元素
+    const a = document.createElement('a');
+    // 设置a标签的href属性
+    a.href = res.data;
+    // 触发点击事件
+    a.click();
+  });
+};
+// 分享
+let shareState = reactive({
+  type: '',
+  showShare: false,
+  id: ''
+});
+const handleCollaborate = (type, id?: string) => {
+  shareState.type = type;
+  shareState.id = id;
+  shareState.showShare = true;
+};
+const handleCloseShare = () => {
+  shareState.type = '';
+  shareState.id = '';
+};
+const handleShareConfirm = (data) => {
+  showSuccessMsg('开启协同成功');
+};
 // 轨迹
 const handleTrack = (item) => {
   getMobileWorkstationTrajectory(item.id).then((res) => {

+ 6 - 6
src/views/globalMap/RightMenu/OnlinePlotting/index.vue

@@ -810,15 +810,15 @@ const handleSendForm = () => {
   if (!form.value.pattern_name) {
     return proxy?.$modal.msgWarning('请填写预案名称');
   }
-  webSock = createWebSocket('X_cBqh0q1GUVhTOmS5c8w', getWebSocketData);
-  patternId.value = 'X_cBqh0q1GUVhTOmS5c8w';
-  // createCollaboration(form.value).then(() => {
-  //   patternId.value = form.value.pattern_id;
-  //   webSock = createWebSocket(form.value.pattern_id, getWebSocketData);
+  // webSock = createWebSocket('X_cBqh0q1GUVhTOmS5c8w', getWebSocketData);
+  // patternId.value = 'X_cBqh0q1GUVhTOmS5c8w';
+  createCollaboration(form.value).then(() => {
+    patternId.value = form.value.pattern_id;
+    webSock = createWebSocket(form.value.pattern_id, getWebSocketData);
     showForm.value = false;
     collaboration.value = true;
     proxy?.$modal.msgSuccess('开启协同标绘成功');
-  // });
+  });
 };
 const handleShowDialog = () => {
   editData.value = {