diff --git a/package-lock.json b/package-lock.json index c6bd5e1..441bf64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "maptalks": "^1.1.3", "markdown-it": "^14.1.0", "mitt": "^3.0.1", + "ol": "^10.6.1", "serialport": "^12.0.0", "vue": "^3.3.4", "vue-drag-resize": "^2.0.3", @@ -687,6 +688,12 @@ "node": ">= 8" } }, + "node_modules/@petamoriken/float16": { + "version": "3.9.2", + "resolved": "https://r.cnpmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz", + "integrity": "sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==", + "license": "MIT" + }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -1412,6 +1419,12 @@ "@types/lodash": "*" } }, + "node_modules/@types/rbush": { + "version": "4.0.0", + "resolved": "https://r.cnpmjs.org/@types/rbush/-/rbush-4.0.0.tgz", + "integrity": "sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==", + "license": "MIT" + }, "node_modules/@types/web-bluetooth": { "version": "0.0.20", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", @@ -1983,6 +1996,12 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/earcut": { + "version": "3.0.2", + "resolved": "https://r.cnpmjs.org/earcut/-/earcut-3.0.2.tgz", + "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==", + "license": "ISC" + }, "node_modules/echart": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/echart/-/echart-0.1.3.tgz", @@ -2289,6 +2308,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/geotiff": { + "version": "2.1.3", + "resolved": "https://r.cnpmjs.org/geotiff/-/geotiff-2.1.3.tgz", + "integrity": "sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==", + "license": "MIT", + "dependencies": { + "@petamoriken/float16": "^3.4.7", + "lerc": "^3.0.0", + "pako": "^2.0.4", + "parse-headers": "^2.0.2", + "quick-lru": "^6.1.1", + "web-worker": "^1.2.0", + "xml-utils": "^1.0.2", + "zstddec": "^0.1.0" + }, + "engines": { + "node": ">=10.19" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -2651,6 +2689,12 @@ "any-promise": "^1.1.0" } }, + "node_modules/lerc": { + "version": "3.0.0", + "resolved": "https://r2.cnpmjs.org/lerc/-/lerc-3.0.0.tgz", + "integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==", + "license": "Apache-2.0" + }, "node_modules/less": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", @@ -2985,6 +3029,38 @@ "integrity": "sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==", "dev": true }, + "node_modules/ol": { + "version": "10.6.1", + "resolved": "https://r.cnpmjs.org/ol/-/ol-10.6.1.tgz", + "integrity": "sha512-xp174YOwPeLj7c7/8TCIEHQ4d41tgTDDhdv6SqNdySsql5/MaFJEJkjlsYcvOPt7xA6vrum/QG4UdJ0iCGT1cg==", + "license": "BSD-2-Clause", + "dependencies": { + "@types/rbush": "4.0.0", + "earcut": "^3.0.0", + "geotiff": "^2.1.3", + "pbf": "4.0.1", + "rbush": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/openlayers" + } + }, + "node_modules/ol/node_modules/quickselect": { + "version": "3.0.0", + "resolved": "https://r.cnpmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", + "license": "ISC" + }, + "node_modules/ol/node_modules/rbush": { + "version": "4.0.1", + "resolved": "https://r.cnpmjs.org/rbush/-/rbush-4.0.1.tgz", + "integrity": "sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==", + "license": "MIT", + "dependencies": { + "quickselect": "^3.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -3001,6 +3077,18 @@ "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==" }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://r.cnpmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, + "node_modules/parse-headers": { + "version": "2.0.6", + "resolved": "https://r.cnpmjs.org/parse-headers/-/parse-headers-2.0.6.tgz", + "integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==", + "license": "MIT" + }, "node_modules/parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", @@ -3038,6 +3126,18 @@ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "dev": true }, + "node_modules/pbf": { + "version": "4.0.1", + "resolved": "https://r.cnpmjs.org/pbf/-/pbf-4.0.1.tgz", + "integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==", + "license": "BSD-3-Clause", + "dependencies": { + "resolve-protobuf-schema": "^2.1.0" + }, + "bin": { + "pbf": "bin/pbf" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -3109,6 +3209,12 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://r2.cnpmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==", + "license": "MIT" + }, "node_modules/prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -3152,6 +3258,18 @@ } ] }, + "node_modules/quick-lru": { + "version": "6.1.2", + "resolved": "https://r.cnpmjs.org/quick-lru/-/quick-lru-6.1.2.tgz", + "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/quickselect": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz", @@ -3202,6 +3320,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://r2.cnpmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "license": "MIT", + "dependencies": { + "protocol-buffers-schema": "^3.3.1" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3817,6 +3944,12 @@ "resolved": "https://registry.npmjs.org/vue3-konami-code/-/vue3-konami-code-1.0.0.tgz", "integrity": "sha512-fhHAPFZA1jsgDHlYz5dnG52RmY9+vtfMthBaY1S5VBxNLdU4EWTbnJO0nfL8Uybw5uHsDqCGtTbGaX7nIvQ9Qw==" }, + "node_modules/web-worker": { + "version": "1.5.0", + "resolved": "https://r.cnpmjs.org/web-worker/-/web-worker-1.5.0.tgz", + "integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==", + "license": "Apache-2.0" + }, "node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", @@ -3832,6 +3965,12 @@ "integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==", "dev": true }, + "node_modules/xml-utils": { + "version": "1.10.2", + "resolved": "https://r.cnpmjs.org/xml-utils/-/xml-utils-1.10.2.tgz", + "integrity": "sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==", + "license": "CC0-1.0" + }, "node_modules/ylru": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.4.0.tgz", @@ -3847,6 +3986,12 @@ "dependencies": { "tslib": "2.3.0" } + }, + "node_modules/zstddec": { + "version": "0.1.0", + "resolved": "https://r.cnpmjs.org/zstddec/-/zstddec-0.1.0.tgz", + "integrity": "sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==", + "license": "MIT AND BSD-3-Clause" } }, "dependencies": { @@ -4181,6 +4326,11 @@ "fastq": "^1.6.0" } }, + "@petamoriken/float16": { + "version": "3.9.2", + "resolved": "https://r.cnpmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz", + "integrity": "sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==" + }, "@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -4555,6 +4705,11 @@ "@types/lodash": "*" } }, + "@types/rbush": { + "version": "4.0.0", + "resolved": "https://r.cnpmjs.org/@types/rbush/-/rbush-4.0.0.tgz", + "integrity": "sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==" + }, "@types/web-bluetooth": { "version": "0.0.20", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", @@ -4977,6 +5132,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "earcut": { + "version": "3.0.2", + "resolved": "https://r.cnpmjs.org/earcut/-/earcut-3.0.2.tgz", + "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==" + }, "echart": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/echart/-/echart-0.1.3.tgz", @@ -5195,6 +5355,21 @@ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true }, + "geotiff": { + "version": "2.1.3", + "resolved": "https://r.cnpmjs.org/geotiff/-/geotiff-2.1.3.tgz", + "integrity": "sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==", + "requires": { + "@petamoriken/float16": "^3.4.7", + "lerc": "^3.0.0", + "pako": "^2.0.4", + "parse-headers": "^2.0.2", + "quick-lru": "^6.1.1", + "web-worker": "^1.2.0", + "xml-utils": "^1.0.2", + "zstddec": "^0.1.0" + } + }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -5483,6 +5658,11 @@ } } }, + "lerc": { + "version": "3.0.0", + "resolved": "https://r2.cnpmjs.org/lerc/-/lerc-3.0.0.tgz", + "integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==" + }, "less": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", @@ -5724,6 +5904,33 @@ "integrity": "sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==", "dev": true }, + "ol": { + "version": "10.6.1", + "resolved": "https://r.cnpmjs.org/ol/-/ol-10.6.1.tgz", + "integrity": "sha512-xp174YOwPeLj7c7/8TCIEHQ4d41tgTDDhdv6SqNdySsql5/MaFJEJkjlsYcvOPt7xA6vrum/QG4UdJ0iCGT1cg==", + "requires": { + "@types/rbush": "4.0.0", + "earcut": "^3.0.0", + "geotiff": "^2.1.3", + "pbf": "4.0.1", + "rbush": "^4.0.0" + }, + "dependencies": { + "quickselect": { + "version": "3.0.0", + "resolved": "https://r.cnpmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==" + }, + "rbush": { + "version": "4.0.1", + "resolved": "https://r.cnpmjs.org/rbush/-/rbush-4.0.1.tgz", + "integrity": "sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==", + "requires": { + "quickselect": "^3.0.0" + } + } + } + }, "on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -5737,6 +5944,16 @@ "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==" }, + "pako": { + "version": "2.1.0", + "resolved": "https://r.cnpmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, + "parse-headers": { + "version": "2.0.6", + "resolved": "https://r.cnpmjs.org/parse-headers/-/parse-headers-2.0.6.tgz", + "integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==" + }, "parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", @@ -5767,6 +5984,14 @@ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "dev": true }, + "pbf": { + "version": "4.0.1", + "resolved": "https://r.cnpmjs.org/pbf/-/pbf-4.0.1.tgz", + "integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==", + "requires": { + "resolve-protobuf-schema": "^2.1.0" + } + }, "picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -5810,6 +6035,11 @@ "source-map-js": "^1.2.1" } }, + "protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://r2.cnpmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -5832,6 +6062,11 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "quick-lru": { + "version": "6.1.2", + "resolved": "https://r.cnpmjs.org/quick-lru/-/quick-lru-6.1.2.tgz", + "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==" + }, "quickselect": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz", @@ -5871,6 +6106,14 @@ "supports-preserve-symlinks-flag": "^1.0.0" } }, + "resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://r2.cnpmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "requires": { + "protocol-buffers-schema": "^3.3.1" + } + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -6259,6 +6502,11 @@ "resolved": "https://registry.npmjs.org/vue3-konami-code/-/vue3-konami-code-1.0.0.tgz", "integrity": "sha512-fhHAPFZA1jsgDHlYz5dnG52RmY9+vtfMthBaY1S5VBxNLdU4EWTbnJO0nfL8Uybw5uHsDqCGtTbGaX7nIvQ9Qw==" }, + "web-worker": { + "version": "1.5.0", + "resolved": "https://r.cnpmjs.org/web-worker/-/web-worker-1.5.0.tgz", + "integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==" + }, "webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", @@ -6271,6 +6519,11 @@ "integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==", "dev": true }, + "xml-utils": { + "version": "1.10.2", + "resolved": "https://r.cnpmjs.org/xml-utils/-/xml-utils-1.10.2.tgz", + "integrity": "sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==" + }, "ylru": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.4.0.tgz", @@ -6283,6 +6536,11 @@ "requires": { "tslib": "2.3.0" } + }, + "zstddec": { + "version": "0.1.0", + "resolved": "https://r.cnpmjs.org/zstddec/-/zstddec-0.1.0.tgz", + "integrity": "sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==" } } } diff --git a/package.json b/package.json index 622f16d..a84ff2e 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "maptalks": "^1.1.3", "markdown-it": "^14.1.0", "mitt": "^3.0.1", + "ol": "^10.6.1", "serialport": "^12.0.0", "vue": "^3.3.4", "vue-drag-resize": "^2.0.3", diff --git a/src-tauri/config.json b/src-tauri/config.json index 46fbff2..d0a3e2b 100644 --- a/src-tauri/config.json +++ b/src-tauri/config.json @@ -1 +1 @@ -{"pathofsave":"C:\\Program Files\\lucamtool","Filename":"testaa","caijiavgNumber":"1","useSG":false,"usehighpass":false,"Dispatcher":{"isenable":true,"begin":"06:25","end":"23:59"},"sensor_typeforset":"IS3"} \ No newline at end of file +{"pathofsave":null,"Filename":"testaa","caijiavgNumber":"1","useSG":false,"usehighpass":false,"Dispatcher":{"isenable":true,"begin":"06:25","end":"23:59"},"sensor_typeforset":"IRIS-IS11"} \ No newline at end of file diff --git a/src-tauri/data46.iris b/src-tauri/data46.iris new file mode 100644 index 0000000..9d1a9f5 Binary files /dev/null and b/src-tauri/data46.iris differ diff --git a/src/App.vue b/src/App.vue index efab979..90283c2 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,6 +1,4 @@ \ No newline at end of file diff --git a/src/DataView/assets/保存曲线-未点击.png b/src/DataView/assets/保存曲线-未点击.png new file mode 100644 index 0000000..ea92feb Binary files /dev/null and b/src/DataView/assets/保存曲线-未点击.png differ diff --git a/src/DataView/assets/保存曲线-点击.png b/src/DataView/assets/保存曲线-点击.png new file mode 100644 index 0000000..b073d75 Binary files /dev/null and b/src/DataView/assets/保存曲线-点击.png differ diff --git a/src/DataView/assets/图例设置-未点击.png b/src/DataView/assets/图例设置-未点击.png new file mode 100644 index 0000000..05cb039 Binary files /dev/null and b/src/DataView/assets/图例设置-未点击.png differ diff --git a/src/DataView/assets/图例设置-点击.png b/src/DataView/assets/图例设置-点击.png new file mode 100644 index 0000000..d5c875b Binary files /dev/null and b/src/DataView/assets/图例设置-点击.png differ diff --git a/src/DataView/assets/图钉.png b/src/DataView/assets/图钉.png new file mode 100644 index 0000000..9ece5d7 Binary files /dev/null and b/src/DataView/assets/图钉.png differ diff --git a/src/DataView/assets/文件图标-线.png b/src/DataView/assets/文件图标-线.png new file mode 100644 index 0000000..bb672b7 Binary files /dev/null and b/src/DataView/assets/文件图标-线.png differ diff --git a/src/DataView/assets/文件图标-面.png b/src/DataView/assets/文件图标-面.png new file mode 100644 index 0000000..88d623d Binary files /dev/null and b/src/DataView/assets/文件图标-面.png differ diff --git a/src/DataView/assets/文件夹图标.png b/src/DataView/assets/文件夹图标.png new file mode 100644 index 0000000..525bbf8 Binary files /dev/null and b/src/DataView/assets/文件夹图标.png differ diff --git a/src/DataView/assets/重置视图-未点击.png b/src/DataView/assets/重置视图-未点击.png new file mode 100644 index 0000000..c11e505 Binary files /dev/null and b/src/DataView/assets/重置视图-未点击.png differ diff --git a/src/DataView/assets/重置视图-点击.png b/src/DataView/assets/重置视图-点击.png new file mode 100644 index 0000000..dbcf60d Binary files /dev/null and b/src/DataView/assets/重置视图-点击.png differ diff --git a/src/DataView/menuvue/menubar.vue b/src/DataView/menuvue/menubar.vue index fc3a162..013b16a 100644 --- a/src/DataView/menuvue/menubar.vue +++ b/src/DataView/menuvue/menubar.vue @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/src/DataView/vuecomponents/GuiForDivesInfo.vue b/src/DataView/vuecomponents/GuiForDivesInfo.vue index a2f5010..17b97b2 100644 --- a/src/DataView/vuecomponents/GuiForDivesInfo.vue +++ b/src/DataView/vuecomponents/GuiForDivesInfo.vue @@ -1,74 +1,264 @@ - - + \ No newline at end of file diff --git a/src/DataView/vuecomponents/GuiForPlotShow.vue b/src/DataView/vuecomponents/GuiForPlotShow.vue index 5f86627..4b40f26 100644 --- a/src/DataView/vuecomponents/GuiForPlotShow.vue +++ b/src/DataView/vuecomponents/GuiForPlotShow.vue @@ -1,425 +1,1082 @@ - - + + \ No newline at end of file diff --git a/src/DataView/vuecomponents/GuiLeftSider.vue b/src/DataView/vuecomponents/GuiLeftSider.vue index 6306cf1..1a5f0d8 100644 --- a/src/DataView/vuecomponents/GuiLeftSider.vue +++ b/src/DataView/vuecomponents/GuiLeftSider.vue @@ -1,78 +1,447 @@ - + +.fileitem1 { + width: 100%; + height: 20px; + display: flex; + align-items: center; + + &>img { + width: 18px; + height: 18px; + margin-right: 5px; + } +} + +.fileitem2 { + width: 100%; + height: 18px; + display: flex; + align-items: center; + + &>img { + margin-right: 5px; + + width: 13px; + height: 13px; + } +} + +.fileitem:nth-child(2) { + width: 13px; + height: 13px; +} + +.GuiLeftSider { + padding: 17px 24px; +} + +.GuiLeftSider p { + font-size: 18px; + color: #434959; + text-align: left; + font-weight: 600; +} + +.defaultList button { + width: 100%; + height: 40px; + border-radius: 4px; + border: 1.4px solid #4271EE; + box-shadow: none; + font-size: 16px; + color: #4271EE; +} + \ No newline at end of file diff --git a/src/DataView/vuecomponents/MapContainer.vue b/src/DataView/vuecomponents/MapContainer.vue index 472b043..0902666 100644 --- a/src/DataView/vuecomponents/MapContainer.vue +++ b/src/DataView/vuecomponents/MapContainer.vue @@ -1,78 +1,236 @@ - - diff --git a/src/DataView/vuecomponents/PictureDisplayInterface.vue b/src/DataView/vuecomponents/PictureDisplayInterface.vue new file mode 100644 index 0000000..f1128bc --- /dev/null +++ b/src/DataView/vuecomponents/PictureDisplayInterface.vue @@ -0,0 +1,240 @@ + + + + + \ No newline at end of file diff --git a/src/DataView/vuecomponents/SaveFileDialog.vue b/src/DataView/vuecomponents/SaveFileDialog.vue new file mode 100644 index 0000000..462a273 --- /dev/null +++ b/src/DataView/vuecomponents/SaveFileDialog.vue @@ -0,0 +1,301 @@ + + + + + + + \ No newline at end of file diff --git a/src/main.js b/src/main.js index 086a3be..c0bf67c 100644 --- a/src/main.js +++ b/src/main.js @@ -2,54 +2,64 @@ import { createApp } from "vue"; import "./styles.css"; //import App from "./AppHyperSpectral.vue"; import App from "./App.vue"; -import { appWindow } from '@tauri-apps/api/window'; -import { LogicalSize } from '@tauri-apps/api/window'; -import ElementPlus from 'element-plus'; -import 'element-plus/dist/index.css' -import {createBootstrap} from 'bootstrap-vue-next' +import { appWindow } from "@tauri-apps/api/window"; +import { LogicalSize } from "@tauri-apps/api/window"; +import ElementPlus from "element-plus"; +import "element-plus/dist/index.css"; +import zhCn from 'element-plus/dist/locale/zh-cn.mjs' +import { createBootstrap } from "bootstrap-vue-next"; // // // Add the necessary CSS -import 'bootstrap/dist/css/bootstrap.css' -import 'bootstrap-vue-next/dist/bootstrap-vue-next.css' -import ArcoVue from '@arco-design/web-vue'; +import "bootstrap/dist/css/bootstrap.css"; +import "bootstrap-vue-next/dist/bootstrap-vue-next.css"; +import ArcoVue from "@arco-design/web-vue"; -import '@arco-design/web-vue/dist/arco.css'; -import { Draggable,DraggablePlugin, DraggableDirective } from '@braks/revue-draggable'; -import KonamiCode from 'vue3-konami-code'; +import "@arco-design/web-vue/dist/arco.css"; +import { + Draggable, + DraggablePlugin, + DraggableDirective, +} from "@braks/revue-draggable"; +import KonamiCode from "vue3-konami-code"; import EventBus from "./eventBus.js"; +import tauriApi from "./utils/tauriApi.js"; async function setWindowSize() { - // const primaryMonitor = await screen.primaryMonitor(); - // const screenSize = primaryMonitor.size; + // const primaryMonitor = await screen.primaryMonitor(); + // const screenSize = primaryMonitor.size; - const newSize = new LogicalSize(800, 600); - await appWindow.setSize(newSize); - // appWindow.setSize(new Size(1000, 1000)); + const newSize = new LogicalSize(800, 600); + await appWindow.setSize(newSize); + // appWindow.setSize(new Size(1000, 1000)); } var app = createApp(App); -app.use(ElementPlus); -app.use(createBootstrap( {components: true, directives: true,plugins:true,icons: true,})); +app.use(ElementPlus, { + locale: zhCn, +}); +app.use( + createBootstrap({ + components: true, + directives: true, + plugins: true, + icons: true, + }) +); app.use(ArcoVue); app.use(DraggablePlugin); app.use(KonamiCode, { - onKonamiCodeEntered: () => { - // 用户输入Konami Code后执行的代码 - console.log('Konami Code 已输入!'); - EventBus.emit('konamiactive'); - } + onKonamiCodeEntered: () => { + // 用户输入Konami Code后执行的代码 + console.log("Konami Code 已输入!"); + EventBus.emit("konamiactive"); + }, }); // or -app.directive('draggable', DraggableDirective) -app.component('Draggable', Draggable); - - - +app.directive("draggable", DraggableDirective); +app.component("Draggable", Draggable); +// 注册全局 API +app.config.globalProperties.$tauriApi = tauriApi; // app.use(BootstrapVueIcons); app.mount("#app"); - - - - diff --git a/src/utils/hyperspectralParser.js b/src/utils/hyperspectralParser.js new file mode 100644 index 0000000..683b2dc --- /dev/null +++ b/src/utils/hyperspectralParser.js @@ -0,0 +1,112 @@ +import { ref } from 'vue'; + +export function useHyperspectralDataParser() { + const parsedData = ref(null); + const error = ref(null); + + // 解析时间结构 + const parseTimeStruct = (timeData) => { + if (!timeData) return null; + return { + timezone: timeData.time_zone || 0, + year: timeData.year || 0, + month: timeData.month || 0, + day: timeData.day || 0, + hour: timeData.hour || 0, + minute: timeData.minute || 0, + second: timeData.second || 0, + millisecond: timeData.millisecond || 0 + }; + }; + + // 解析设备元数据 + const parseDeviceInfo = (metaData) => { + if (!metaData || metaData.info_type !== "devinfo") { + return null; + } + return { + infoType: metaData.info_type, + sensorId: metaData.sensor_id || '', + bandNum: metaData.bandnum || 0, + waveCoeff: { + a1: metaData.wave_coeff?.a1 || 0, + a2: metaData.wave_coeff?.a2 || 0, + a3: metaData.wave_coeff?.a3 || 0, + a4: metaData.wave_coeff?.a4 || 0 + } + }; + }; + + // 解析光谱数据 + const parseSpectralData = (uint8Array, bands, dataType) => { + try { + switch (dataType) { + case 0x20: // float32 + return new Float32Array(uint8Array.buffer, 0, bands); + case 0x21: // float64 + return new Float64Array(uint8Array.buffer, 0, bands); + case 0x10: // uint8 + return new Uint8Array(uint8Array.buffer, 0, bands); + case 0x11: // int16 + return new Int16Array(uint8Array.buffer, 0, bands); + case 0x12: // uint16 + return new Uint16Array(uint8Array.buffer, 0, bands); + case 0x13: // int32 + return new Int32Array(uint8Array.buffer, 0, bands); + case 0x14: // uint32 + return new Uint32Array(uint8Array.buffer, 0, bands); + default: + throw new Error(`Unsupported data type: 0x${dataType.toString(16)}`); + } + } catch (e) { + error.value = `Failed to parse spectral data: ${e.message}`; + return null; + } + }; + + // 主解析函数 + const parseHyperspectralData = (rawData, metaData) => { + try { + if (!rawData || !rawData.spectral_data || !rawData.bands) { + throw new Error('Invalid data format: missing required fields'); + } + const uint8Array = new Uint8Array(rawData.spectral_data); + const deviceInfo = metaData ? parseDeviceInfo(metaData) : null; + const result = { + deviceInfo, + dataInfo: { + name: rawData.name || '', + sensorId: rawData.sensor_id || '', + fiberId: rawData.fiber_id || 0, + collectionTime: rawData.collection_time ? parseTimeStruct(rawData.collection_time) : null, + exposure: rawData.exposure || 0, + gain: rawData.gain || 0, + dataType: rawData.data_type || 0, + pixelSize: rawData.pixel_size || 0, + groundType: rawData.ground_type || 0, + validFlag: rawData.valid_flag || 0, + bands: rawData.bands || 0 + }, + spectralData: parseSpectralData(uint8Array, rawData.bands, rawData.data_type) + }; + parsedData.value = result; + return result; + } catch (e) { + error.value = `Data parsing error: ${e.message}`; + return null; + } + }; + + // 重置状态 + const reset = () => { + parsedData.value = null; + error.value = null; + }; + + return { + parsedData, + error, + parseHyperspectralData, + reset + }; +} \ No newline at end of file diff --git a/src/utils/irisDataDispose.js b/src/utils/irisDataDispose.js new file mode 100644 index 0000000..0a47ece --- /dev/null +++ b/src/utils/irisDataDispose.js @@ -0,0 +1,455 @@ +class getIrisDataDispose { + spectralName; + irisData; + spectralInfoData; + spectral_data; + image_info; + devinfoData; + environmentData; + + constructor(irisData, spectralName) { + this.irisData = irisData; + this.spectralName = spectralName; + this.spectral_data = irisData.spectral_data_section; + this.image_info = irisData.image_info_section; + + for (const element of irisData.spectral_info_section) { + if (element.info_type == "devinfo") { + this.devinfoData = element; + } else if (element.info_type == "environment") { + this.environmentData = element; + } + } + } + + initData() { + const basicTypes = ["ground_dn", "flat_dn", "dark_dn", "gain"]; + const specialTypes = [ + "flat_ref", + "radiance_ground", + "radiance_flat", + "refrad", + ]; + + if (basicTypes.includes(this.spectralName)) { + return this.getFileSpectralData(); + } else if (specialTypes.includes(this.spectralName)) { + return this.getSpecialFileSpectralData(); + } + } + + //获取一般后端直接返回的类型 + getFileSpectralData() { + for (const element of this.spectral_data) { + const typedArray = manageSpectralData(element, this.devinfoData); + const normalArray = Array.from(typedArray); + if (element.name.toLowerCase().includes(this.spectralName)) { + return { ...element, normalArray }; + } + } + } + + //获取需要计算的类型 + getSpecialFileSpectralData() { + let spectralDataMap = new Map([ + ["ground_dn", null], + ["flat_dn", null], + ["dark_dn", null], + ["flat_ref", null], + ["gain", null], + ["radiance_ground", null], + ["radiance_flat", null], + ["refrad", null], + ]); + for (const element of this.spectral_data) { + const typedArray = manageSpectralData(element, this.devinfoData); + const normalArray = Array.from(typedArray); + if (element.name.toLowerCase().includes("ground_dn")) { + spectralDataMap.set("ground_dn", { ...element, normalArray }); + } else if (element.name.toLowerCase().includes("flat_dn")) { + spectralDataMap.set("flat_dn", { ...element, normalArray }); + } else if (element.name.toLowerCase().includes("dark_dn")) { + spectralDataMap.set("dark_dn", { ...element, normalArray }); + } else if (element.name.toLowerCase().includes("gain")) { + spectralDataMap.set("gain", { ...element, normalArray }); + } + } + + if ( + spectralDataMap.get("ground_dn") && + spectralDataMap.get("flat_dn") && + spectralDataMap.get("dark_dn") && + spectralDataMap.get("gain") + ) { + const obj1 = { + ground_dn: spectralDataMap.get("ground_dn").normalArray, + flat_dn: spectralDataMap.get("flat_dn").normalArray, + dark_dn: spectralDataMap.get("dark_dn").normalArray, + gain: spectralDataMap.get("gain").normalArray, + }; + + const arrAll = mergeObjectArrays(obj1); + const name = spectralDataMap.get("ground_dn").name.split("_")[0]; + + // 通用的数值验证函数 + const validateAndPush = (array, value, type, invalidCount) => { + if (isFinite(value) && !isNaN(value)) { + array.push(value); + return true; + } else { + invalidCount.invalidResult++; + return false; + } + }; + + // 通用的除零检查函数 + const checkDivision = (numerator, denominator, type, invalidCount) => { + if (Math.abs(denominator) < 1e-10) { + invalidCount.zeroDiv++; + return null; + } + return numerator / denominator; + }; + + // 通用的结果验证和返回函数 + const validateResult = (array, name, type) => { + if (array.length === 0) { + console.error(`${type}计算错误: 没有有效的数据点,无法生成图表`); + return { normalArray: [], name: name }; + } + return { normalArray: array, name: name }; + }; + + if (this.spectralName == "radiance_ground") { + const radiance_ground = []; + const invalidCount = { zeroDiv: 0, invalidResult: 0 }; + + for (const element of arrAll) { + const gainExposure = spectralDataMap.get("gain").exposure; + const groundExposure = spectralDataMap.get("ground_dn").exposure; + + // 检查曝光时间除零 - 改为补充0值 + if (Math.abs(groundExposure) < 1e-10) { + invalidCount.zeroDiv++; + radiance_ground.push(0); + continue; + } + + const exposureRatio = gainExposure / groundExposure; + const dnDiff = element.ground_dn - element.dark_dn; + const a = exposureRatio * (element.gain * dnDiff); + + // 验证结果,无效时补充0值 + if (isFinite(a) && !isNaN(a)) { + radiance_ground.push(a); + } else { + invalidCount.invalidResult++; + radiance_ground.push(0); + } + } + // 记录统计信息 + if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) { + console.warn(`radiance_ground计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${radiance_ground.length} 个`); + } + + return validateResult(radiance_ground, name + "_radiance_ground", 'radiance_ground'); + + } else if (this.spectralName == "radiance_flat") { + const radiance_flat = []; + const invalidCount = { zeroDiv: 0, invalidResult: 0 }; + + for (const element of arrAll) { + const gainExposure = spectralDataMap.get("gain").exposure; + const flatExposure = spectralDataMap.get("flat_dn").exposure; + + // 检查曝光时间除零 - 改为补充0值 + if (Math.abs(flatExposure) < 1e-10) { + invalidCount.zeroDiv++; + radiance_flat.push(0); + continue; + } + + const exposureRatio = gainExposure / flatExposure; + const dnDiff = element.flat_dn - element.dark_dn; + const b = exposureRatio * (element.gain * dnDiff); + + // 验证结果,无效时补充0值 + if (isFinite(b) && !isNaN(b)) { + radiance_flat.push(b); + } else { + invalidCount.invalidResult++; + radiance_flat.push(0); + } + } + // 记录统计信息 + if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) { + console.warn(`radiance_flat计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${radiance_flat.length} 个`); + } + + return validateResult(radiance_flat, name + "_radiance_flat", 'radiance_flat'); + + } else if (this.spectralName == "refrad") { + const refrad = []; + const invalidCount = { zeroDiv: 0, invalidResult: 0 }; + + for (const element of arrAll) { + const gainExposure = spectralDataMap.get("gain").exposure; + const groundExposure = spectralDataMap.get("ground_dn").exposure; + const flatExposure = spectralDataMap.get("flat_dn").exposure; + + // 检查曝光时间除零 - 改为补充0值 + if (Math.abs(groundExposure) < 1e-10 || Math.abs(flatExposure) < 1e-10) { + invalidCount.zeroDiv++; + refrad.push(0); + continue; + } + + const groundRatio = gainExposure / groundExposure; + const flatRatio = gainExposure / flatExposure; + + const groundDnDiff = element.ground_dn - element.dark_dn; + const flatDnDiff = element.flat_dn - element.dark_dn; + + const a = groundRatio * (element.gain * groundDnDiff); + const b = flatRatio * (element.gain * flatDnDiff); + + // 检查分母b是否为零 - 改为补充0值 + if (Math.abs(b) < 1e-10) { + invalidCount.zeroDiv++; + refrad.push(0); + } else { + const c = a / b; + if (isFinite(c) && !isNaN(c)) { + refrad.push(c); + } else { + invalidCount.invalidResult++; + refrad.push(0); + } + } + } + + // 记录统计信息 + if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) { + console.warn(`refrad计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${refrad.length} 个`); + } + + return validateResult(refrad, name + "_refrad", 'refrad'); + + } else if (this.spectralName == "flat_ref") { + const validData = []; + const invalidCount = { zeroDiv: 0, invalidResult: 0 }; + + for (const element of arrAll) { + const denominator = element.flat_dn - element.dark_dn; + const numerator = element.ground_dn - element.dark_dn; + + // 检查分母是否为零或接近零 - 改为补充0值 + if (Math.abs(denominator) < 1e-10) { + invalidCount.zeroDiv++; + validData.push(0); + } else { + const b = numerator / denominator; + if (isFinite(b) && !isNaN(b)) { + validData.push(b); + } else { + invalidCount.invalidResult++; + validData.push(0); + } + } + } + + // 记录统计信息 + if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) { + console.warn(`flat_ref计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${validData.length} 个`); + } + return validateResult(validData, name + "_flat_ref", 'flat_ref'); + } + } + } + + getSpectralInfoData() { + let spectralInfoData = []; + for (let i = 0; i < this.devinfoData.bandnum; i++) { + const a = + this.devinfoData.wave_coeff.a1 * i ** 3 + + this.devinfoData.wave_coeff.a2 * i * i + + this.devinfoData.wave_coeff.a3 * i + + this.devinfoData.wave_coeff.a4; + spectralInfoData.push(a); + } + return spectralInfoData; + } + + parseImageData(image_info) { + if (!image_info || image_info.length === 0) { + console.log("No image data found"); + return []; + } + const imageInfos = image_info; + const images = []; + for (const imageInfo of imageInfos) { + // 获取图像类型 + const imageType = imageInfo.info_type; + let mimeType; + switch (imageType) { + case 0: + mimeType = "image/jpeg"; + break; + case 1: + mimeType = "image/png"; + break; + case 2: + mimeType = "image/tiff"; + break; + case 3: + mimeType = "application/octet-stream"; // 原始数据 + break; + default: + mimeType = "application/octet-stream"; + } + // 创建Blob对象 + const imageBlob = new Blob([new Uint8Array(imageInfo.image_data)], { + type: mimeType, + }); + // 创建URL + const imageUrl = URL.createObjectURL(imageBlob); + images.push({ + name: imageInfo.name, + type: imageType, + url: imageUrl, + time: imageInfo.collection_time, + }); + } + + return images; + } +} + +function mergeObjectArrays(obj) { + const keys = Object.keys(obj); + const length = obj[keys[0]].length; + + const result = []; + + for (let i = 0; i < length; i++) { + const item = {}; + for (const key of keys) { + item[key] = obj[key][i]; + } + result.push(item); + } + + return result; +} + +const manageSpectralData = (rawData, devinfoData) => { + const bands = devinfoData.bandnum; + const uint8Array = new Uint8Array(rawData.spectral_data); + try { + switch (rawData.data_type) { + case 0x20: // float32 + return new Float32Array(uint8Array.buffer, 0, bands); + case 0x21: // float64 + return new Float64Array(uint8Array.buffer, 0, bands); + case 0x10: // uint8 + return new Uint8Array(uint8Array.buffer, 0, bands); + case 0x11: // int16 + return new Int16Array(uint8Array.buffer, 0, bands); + case 0x12: // uint16 + return new Uint16Array(uint8Array.buffer, 0, bands); + case 0x13: // int32 + return new Int32Array(uint8Array.buffer, 0, bands); + case 0x14: // uint32 + return new Uint32Array(uint8Array.buffer, 0, bands); + default: + throw new Error(`Unsupported data type: 0x${dataType.toString(16)}`); + } + } catch (e) { + error.value = `Failed to parse spectral data: ${e.message}`; + return null; + } +}; + +const spectralTypeList = [ + { + value: "ground_dn", + label: "地物DN", + }, + { + value: "flat_dn", + label: "参考DN", + }, + { + value: "dark_dn", + label: "暗噪DN", + }, + { + value: "flat_ref", + label: "反射率", + }, + { + value: "gain", + label: "能量校准文件", + }, + { + value: "radiance_ground", + label: "地物辐射亮度", + }, + { + value: "radiance_flat", + label: "参考辐射亮度", + }, + { + value: "refrad", + label: "反射率能量", + }, + { + value: "jdfs", + label: "绝对反射率", + }, + { + value: "ckbzwj", + label: "参考校准文件", + }, + { + value: "fszd", + label: "辐射照度", + }, +]; + +const spectralProcessTypeList = [ + { + value: "D1", + label: "一阶导数", + }, + { + value: "D2", + label: "二阶导数", + }, + { + value: "MA", + label: "移动平均平滑", + }, +]; + +function D1(arr) { + const result = []; + for (let i = 1; i < arr.length; i++) { + result.push(arr[i] - arr[i - 1]); + } + result.push(arr[arr.length - 1]); + return result; +} + +function D2(arr) { + const arr2 = D1(arr); + return D1(arr2); +} + +export { + spectralTypeList, + getIrisDataDispose, + spectralProcessTypeList, + D1, + D2, +}; diff --git a/src/utils/spectralDataService.js b/src/utils/spectralDataService.js new file mode 100644 index 0000000..a0c2b92 --- /dev/null +++ b/src/utils/spectralDataService.js @@ -0,0 +1,106 @@ +import { getIrisDataDispose, D1, D2 } from '../utils/irisDataDispose'; +import { invoke } from "@tauri-apps/api/tauri"; + +/** + * 光谱数据处理服务 + */ +export class SpectralDataService { + /** + * 提取文件名 + */ + static extractFileName(filePath) { + const match = filePath.match(/[^\\\/]+$/); + return match ? match[0] : ''; + } + + /** + * 加载文件数据 + */ + static async loadFileData(filePaths) { + const fileData = []; + for (const path of filePaths) { + try { + const src = await invoke("getoneirisfile", { path }); + const fileName = this.extractFileName(path); + fileData.push({ data: src, name: fileName }); + } catch (error) { + console.error(`加载文件失败: ${path}`, error); + } + } + return fileData; + } + + /** + * 处理光谱数据 + */ + static processSpectralData(fileData, spectralType, processType = '') { + const spectralDataList = []; + const imageList = []; + + for (const element of fileData) { + if (!element.data) continue; + + try { + const dispose = new getIrisDataDispose(element.data, spectralType); + const datay = dispose.initData(); + const datax = dispose.getSpectralInfoData(); + const environmentData = dispose.environmentData; + const img = dispose.parseImageData(element.data.image_info_section); + + if (datay?.normalArray && datax) { + spectralDataList.push({ + name: datay?.name || '', + datax: datax, + datay: datay.normalArray, + environmentData: { ...environmentData, fileName: element.name } + }); + imageList.push(img); + } + } catch (error) { + console.error(`处理光谱数据失败: ${element.name}`, error); + } + } + + return { + spectralDataList, + imageList, + processedData: this.applyProcessing(spectralDataList, processType) + }; + } + + /** + * 应用数据处理(D1/D2等) + */ + static applyProcessing(spectralDataList, processType) { + if (!processType) return spectralDataList; + + switch (processType) { + case 'D1': + return spectralDataList.map(item => ({ + name: item.name + '_D1', + datax: item.datax, + datay: D1(item.datay), + environmentData: item.environmentData + })); + case 'D2': + return spectralDataList.map(item => ({ + name: item.name + '_D2', + datax: item.datax, + datay: D2(item.datay), + environmentData: item.environmentData + })); + default: + return spectralDataList; + } + } + + /** + * 批量处理选定文件的光谱数据 + */ + static processSelectedFiles(fileData, selectedFileNames, spectralType, processType = '') { + const filteredData = fileData.filter(file => + selectedFileNames.includes(file.name) + ); + return this.processSpectralData(filteredData, spectralType, processType); + } +} \ No newline at end of file diff --git a/src/utils/tauriApi.js b/src/utils/tauriApi.js new file mode 100644 index 0000000..d14dea1 --- /dev/null +++ b/src/utils/tauriApi.js @@ -0,0 +1,118 @@ +import { invoke } from "@tauri-apps/api/tauri"; +import { dialog, fs } from "@tauri-apps/api"; + +export default { + /** + * 打开文件夹选择对话框并获取文件夹内容 + * @param {string} defaultPath 默认路径 + * @returns {Promise} 文件夹树形结构 + */ + async getFolderList(defaultPath = "") { + try { + // 打开文件夹选择对话框 + const options = { + defaultPath: defaultPath || "../", + directory: true, + title: "请选择文件夹", + }; + + const selectedPath = await dialog.open(options); + + if (!selectedPath) { + return { + label: '请选择', + children: [], + }; + } + + // 读取文件夹内容并构建树形结构 + const tree = await this.buildFolderTree(selectedPath); + return tree; + } catch (error) { + console.error("获取文件夹列表失败:", error); + return { + label: '请选择', + children: [], + }; + } + }, + + /** + * 构建文件夹树形结构 + * @param {string} folderPath 文件夹路径 + * @returns {Promise} 树形结构对象 + */ + async buildFolderTree(folderPath) { + try { + const entries = await fs.readDir(folderPath, { recursive: true }); + + // 获取文件夹名称 + const pathParts = folderPath.split(/[\\\/]/); + const folderName = pathParts[pathParts.length - 1] || folderPath; + const obj = { + name: folderName, + path: folderPath, + children: entries, + isFolder: true, + isLeaf: false + } + const data = this.getTreeData(obj); + return data + } catch (error) { + console.error("构建文件夹树失败:", error); + return { + label: folderPath, + children: [], + path: folderPath, + isFolder: true, + isLeaf: false + }; + } + }, + + + getTreeData(entries) { + if (!entries) { + return null; + } + const obj = { + label: entries.name, + path: entries.path, + } + if (entries?.children && Array.isArray(entries.children)) { + // 处理数组 + obj.children = entries.children.map((item) => { + return this.getTreeData(item); + }); + obj.isFolder = true; + obj.isLeaf = false; + + } else { + obj.isLeaf = true; + obj.isFolder = false; + } + return obj; + } + + +}; + + +function deepTraverse(data) { + if (Array.isArray(data)) { + // 处理数组 + data.forEach((item, index) => { + console.log(`数组项 ${index}:`, item); + deepTraverse(item); // 递归处理数组元素 + }); + } else if (typeof data === 'object' && data !== null) { + // 处理对象 + Object.entries(data).forEach(([key, value]) => { + console.log(`属性 ${key}:`, value); + deepTraverse(value); // 递归处理对象属性 + }); + } else { + // 基本类型值 + console.log('值:', data); + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index d500cde..a30b23d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -124,6 +124,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@petamoriken/float16@^3.4.7": + version "3.9.2" + resolved "https://r.cnpmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz" + integrity sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog== + "@popperjs/core@^2.11.8", "@popperjs/core@npm:@sxzz/popperjs-es@^2.11.7": version "2.11.8" resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz" @@ -287,6 +292,11 @@ resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.4.tgz" integrity sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ== +"@types/rbush@4.0.0": + version "4.0.0" + resolved "https://r.cnpmjs.org/@types/rbush/-/rbush-4.0.0.tgz" + integrity sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ== + "@types/web-bluetooth@^0.0.16": version "0.0.16" resolved "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz" @@ -694,6 +704,11 @@ destroy@^1.0.4: resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== +earcut@^3.0.0: + version "3.0.2" + resolved "https://r.cnpmjs.org/earcut/-/earcut-3.0.2.tgz" + integrity sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ== + echart@^0.1.3: version "0.1.3" resolved "https://registry.npmjs.org/echart/-/echart-0.1.3.tgz" @@ -854,6 +869,20 @@ function-bind@^1.1.2: resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== +geotiff@^2.1.3: + version "2.1.3" + resolved "https://r.cnpmjs.org/geotiff/-/geotiff-2.1.3.tgz" + integrity sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA== + dependencies: + "@petamoriken/float16" "^3.4.7" + lerc "^3.0.0" + pako "^2.0.4" + parse-headers "^2.0.2" + quick-lru "^6.1.1" + web-worker "^1.2.0" + xml-utils "^1.0.2" + zstddec "^0.1.0" + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" @@ -1096,6 +1125,11 @@ koa@^2.2.0: type-is "^1.6.16" vary "^1.1.2" +lerc@^3.0.0: + version "3.0.0" + resolved "https://r2.cnpmjs.org/lerc/-/lerc-3.0.0.tgz" + integrity sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww== + less@*, less@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/less/-/less-4.2.0.tgz" @@ -1339,6 +1373,17 @@ number-precision@^1.6.0: resolved "https://registry.npmjs.org/number-precision/-/number-precision-1.6.0.tgz" integrity sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ== +ol@^10.6.1: + version "10.6.1" + resolved "https://r.cnpmjs.org/ol/-/ol-10.6.1.tgz" + integrity sha512-xp174YOwPeLj7c7/8TCIEHQ4d41tgTDDhdv6SqNdySsql5/MaFJEJkjlsYcvOPt7xA6vrum/QG4UdJ0iCGT1cg== + dependencies: + "@types/rbush" "4.0.0" + earcut "^3.0.0" + geotiff "^2.1.3" + pbf "4.0.1" + rbush "^4.0.0" + on-finished@^2.3.0: version "2.4.1" resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" @@ -1351,6 +1396,16 @@ only@~0.0.2: resolved "https://registry.npmjs.org/only/-/only-0.0.2.tgz" integrity sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ== +pako@^2.0.4: + version "2.1.0" + resolved "https://r.cnpmjs.org/pako/-/pako-2.1.0.tgz" + integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== + +parse-headers@^2.0.2: + version "2.0.6" + resolved "https://r.cnpmjs.org/parse-headers/-/parse-headers-2.0.6.tgz" + integrity sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A== + parse-node-version@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz" @@ -1378,6 +1433,13 @@ pathe@^1.1.2: resolved "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz" integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== +pbf@4.0.1: + version "4.0.1" + resolved "https://r.cnpmjs.org/pbf/-/pbf-4.0.1.tgz" + integrity sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA== + dependencies: + resolve-protobuf-schema "^2.1.0" + picocolors@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" @@ -1421,6 +1483,11 @@ postcss@^8.4.35, postcss@^8.5.3: picocolors "^1.1.1" source-map-js "^1.2.1" +protocol-buffers-schema@^3.3.1: + version "3.6.0" + resolved "https://r2.cnpmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz" + integrity sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw== + prr@~1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" @@ -1441,11 +1508,21 @@ queue-microtask@^1.2.2: resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-lru@^6.1.1: + version "6.1.2" + resolved "https://r.cnpmjs.org/quick-lru/-/quick-lru-6.1.2.tgz" + integrity sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ== + quickselect@^1.0.1: version "1.1.1" resolved "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz" integrity sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ== +quickselect@^3.0.0: + version "3.0.0" + resolved "https://r.cnpmjs.org/quickselect/-/quickselect-3.0.0.tgz" + integrity sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g== + rbush@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/rbush/-/rbush-2.0.2.tgz" @@ -1453,6 +1530,13 @@ rbush@^2.0.2: dependencies: quickselect "^1.0.1" +rbush@^4.0.0: + version "4.0.1" + resolved "https://r.cnpmjs.org/rbush/-/rbush-4.0.1.tgz" + integrity sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ== + dependencies: + quickselect "^3.0.0" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" @@ -1465,6 +1549,13 @@ resize-observer-polyfill@^1.5.1: resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz" integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== +resolve-protobuf-schema@^2.1.0: + version "2.1.0" + resolved "https://r2.cnpmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz" + integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ== + dependencies: + protocol-buffers-schema "^3.3.1" + resolve@^1.22.8: version "1.22.8" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" @@ -1789,6 +1880,11 @@ vue3-konami-code@^1.0.0: resolved "https://registry.npmjs.org/vue3-konami-code/-/vue3-konami-code-1.0.0.tgz" integrity sha512-fhHAPFZA1jsgDHlYz5dnG52RmY9+vtfMthBaY1S5VBxNLdU4EWTbnJO0nfL8Uybw5uHsDqCGtTbGaX7nIvQ9Qw== +web-worker@^1.2.0: + version "1.5.0" + resolved "https://r.cnpmjs.org/web-worker/-/web-worker-1.5.0.tgz" + integrity sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw== + webpack-sources@^3.2.3: version "3.2.3" resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" @@ -1799,6 +1895,11 @@ webpack-virtual-modules@^0.6.1: resolved "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz" integrity sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg== +xml-utils@^1.0.2: + version "1.10.2" + resolved "https://r.cnpmjs.org/xml-utils/-/xml-utils-1.10.2.tgz" + integrity sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA== + ylru@^1.2.0: version "1.4.0" resolved "https://registry.npmjs.org/ylru/-/ylru-1.4.0.tgz" @@ -1810,3 +1911,8 @@ zrender@5.5.0: integrity sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w== dependencies: tslib "2.3.0" + +zstddec@^0.1.0: + version "0.1.0" + resolved "https://r.cnpmjs.org/zstddec/-/zstddec-0.1.0.tgz" + integrity sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==