bill 1 year ago
parent
commit
a1b7b23b71

+ 1 - 0
package.json

@@ -19,6 +19,7 @@
     "konva": "9.3.6",
     "mitt": "^3.0.1",
     "ol": "^9.1.0",
+    "piexifjs": "^1.0.6",
     "pinia": "^2.1.7",
     "proj4": "^2.11.0",
     "qrcode": "^1.5.3",

+ 6 - 0
pnpm-lock.yaml

@@ -13,6 +13,7 @@ specifiers:
   konva: 9.3.6
   mitt: ^3.0.1
   ol: ^9.1.0
+  piexifjs: ^1.0.6
   pinia: ^2.1.7
   proj4: ^2.11.0
   qrcode: ^1.5.3
@@ -35,6 +36,7 @@ dependencies:
   konva: 9.3.6
   mitt: 3.0.1
   ol: 9.2.4
+  piexifjs: 1.0.6
   pinia: 2.1.7_lku3umiefploqzvdryeqiyorrq
   proj4: 2.11.0
   qrcode: 1.5.3
@@ -1234,6 +1236,10 @@ packages:
     engines: {node: '>=8.6'}
     dev: true
 
+  /piexifjs/1.0.6:
+    resolution: {integrity: sha512-0wVyH0cKohzBQ5Gi2V1BuxYpxWfxF3cSqfFXfPIpl5tl9XLS5z4ogqhUCD20AbHi0h9aJkqXNJnkVev6gwh2ag==}
+    dev: false
+
   /pinia/2.1.7_lku3umiefploqzvdryeqiyorrq:
     resolution: {integrity: sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==}
     peerDependencies:

+ 9 - 6
src/components/point-input.vue

@@ -6,7 +6,7 @@
     width="500"
   >
     <el-form label-width="auto">
-      <el-form-item label="坐标" v-if="ivalue.pos">
+      <el-form-item label="坐标" v-if="coordInfo">
         <el-input :value="coordInfo" readonly type="textarea" rows="3" disabled />
       </el-form-item>
 
@@ -64,11 +64,14 @@ const typeOptions = [
   PointTypeEnum.other,
 ];
 
-const coordInfo = computed(
-  () => `经度:${toDegrees(ivalue.value.pos[1])}
-纬度:${toDegrees(ivalue.value.pos[0])}
-高程:${ivalue.value.pos[2]}`
-);
+const coordInfo = computed(() => {
+  const point = ivalue.value.pos;
+  if (!(!point || point.length === 0 || point.some((i) => !i))) {
+    return `经度:${toDegrees(ivalue.value.pos[0])}
+纬度:${toDegrees(ivalue.value.pos[1])}
+高程:${ivalue.value.pos[2]}`;
+  }
+});
 
 const emit = defineEmits<{
   (e: "update:visible", visible: boolean): void;

+ 2 - 2
src/lib/board/4dmap.js

@@ -13061,10 +13061,10 @@ class Cu {
   }
   update() {
     const { stage: t } = this.tree, e = this.bound[2] - this.bound[0], i = this.bound[3] - this.bound[1], n = t.width() / e, r = t.height() / i, a = -this.bound[0] * n, o = -this.bound[1] * r;
-    t.scale({ x: n, y: r }), t.position({ x: a, y: o }), this.tree.redraw(), this.tree.bus.emit("viewChange", {
+    t.scale({ x: n, y: r }), t.position({ x: a, y: o }), this.tree.bus.emit("viewChange", {
       mat: t.getTransform(),
       size: [t.width(), t.height()]
-    }), this.tree.shape.batchDraw();
+    }), this.tree.redraw(), this.tree.stage.draw();
   }
 }
 var _h = {};

File diff suppressed because it is too large
+ 1 - 1
src/lib/board/4dmap.umd.cjs


+ 74 - 0
src/util/image-exif.ts

@@ -0,0 +1,74 @@
+import * as piexif from "piexifjs";
+
+// 读取图片的EXIF信息
+export function readExif(file: Blob) {
+  return new Promise((resolve, reject) => {
+    const reader = new FileReader();
+    reader.onload = (e) => {
+      const exif = piexif.load(e.target.result);
+      console.log(exif);
+      resolve(exif);
+    };
+    reader.onerror = reject;
+    reader.readAsDataURL(file);
+  });
+}
+
+function convertToDMS(value: number) {
+  const degrees = Math.floor(value);
+  const minutes = Math.floor((value - degrees) * 60);
+  const seconds = (value - degrees - minutes / 60) * 3600;
+  return [degrees, minutes, seconds];
+}
+
+function createGPSIFD(lat: number, lon: number, alt: number) {
+  const latDMS = convertToDMS(Math.abs(lat));
+  const lonDMS = convertToDMS(Math.abs(lon));
+
+  const gpsIFD = {
+    [piexif.GPSIFD.GPSVersionID]: [2, 3, 0, 0],
+    [piexif.GPSIFD.GPSLatitudeRef]: lat >= 0 ? "N" : "S",
+    [piexif.GPSIFD.GPSLatitude]: [
+      [latDMS[0], 1],
+      [latDMS[1], 1],
+      [latDMS[2] * 100, 100],
+    ],
+    [piexif.GPSIFD.GPSLongitudeRef]: lon >= 0 ? "E" : "W",
+    [piexif.GPSIFD.GPSLongitude]: [
+      [lonDMS[0], 1],
+      [lonDMS[1], 1],
+      [lonDMS[2] * 100, 100],
+    ],
+    [piexif.GPSIFD.GPSAltitudeRef]: alt >= 0 ? 0 : 1,
+    [piexif.GPSIFD.GPSAltitude]: [Math.abs(alt), 1],
+  };
+  return gpsIFD;
+}
+
+export const attachImageCoord = (blob: Blob, latlngalt: number[]) => {
+  const reader = new FileReader();
+
+  const promise = new Promise<Blob>((resolve) => {
+    reader.onload = function (event) {
+      const exifObj = piexif.load(event.target.result);
+      const gpsIFD = createGPSIFD(latlngalt[0], latlngalt[1], latlngalt[2]);
+      exifObj["GPS"] = gpsIFD;
+
+      const exifBytes = piexif.dump(exifObj);
+      const newImageData = piexif.insert(exifBytes, event.target.result);
+
+      const base64Data = newImageData.split(",")[1];
+      const byteCharacters = atob(base64Data);
+      const byteNumbers = new Array(byteCharacters.length);
+      for (let i = 0; i < byteCharacters.length; i++) {
+        byteNumbers[i] = byteCharacters.charCodeAt(i);
+      }
+      const byteArray = new Uint8Array(byteNumbers);
+      const blob = new Blob([byteArray], { type: "image/jpeg" });
+      resolve(blob);
+    };
+  });
+  reader.readAsDataURL(blob);
+
+  return promise;
+};

+ 13 - 0
src/view/map/coord.vue

@@ -118,6 +118,7 @@
     </div>
 
     <template v-if="!queryMode && treeNode.length">
+      <input type="file" @change="changfile" />
       <el-button
         type="primary"
         :icon="Download"
@@ -197,6 +198,18 @@ import {
 } from "drawing-board";
 import { flyScene, gotoPointPage, mapManage } from "./install";
 import { board } from "./install";
+import { attachImageCoord, readExif } from "@/util/image-exif";
+import { saveAs } from "@/util/file-serve";
+
+const changfile = async (ev) => {
+  readExif(ev.target.files[0]);
+  const blob = await attachImageCoord(ev.target.files[0], [
+    127.101412416667,
+    37.338276944444,
+    5,
+  ]);
+  saveAs(blob);
+};
 
 const inputPoint = ref<ScenePoint | null>(null);
 const updatePointName = async (scenePoint: ScenePoint) => {

+ 14 - 7
src/view/map/layout.vue

@@ -93,13 +93,19 @@ import { PointTypeEnum, pointColorMap, PoPoint } from "drawing-board";
 import { boardData, scenePoints } from "@/store/scene";
 import saveAs from "@/util/file-serve";
 
-const typeOptions = [
-  PointTypeEnum.border,
-  PointTypeEnum.center,
-  PointTypeEnum.marker,
-  PointTypeEnum.other,
-  PointTypeEnum.mapSelect,
-];
+const typeOptions = computed(() => {
+  const options = [
+    PointTypeEnum.border,
+    PointTypeEnum.center,
+    PointTypeEnum.marker,
+    PointTypeEnum.other,
+  ];
+
+  if (!isCoordPage.value) {
+    options.push(PointTypeEnum.mapSelect);
+  }
+  return options;
+});
 
 const menus = [
   {
@@ -179,6 +185,7 @@ const capture = async () => {
   await new Promise((resolve) => setTimeout(resolve, 300));
   try {
     const dataURL = await board.toDataURL(2);
+
     await saveAs(dataURL, `${relics.value.name}-位置图.jpg`);
   } finally {
     captureing.value = false;