| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- // GeoTiff 地图文件处理
- // todo load: leaflet
- import JSZip from 'jszip'
- import { fileUtils } from '@/utils/util.js'
- import mapCanvas from '@/utils/mapCanvas.js'
- import * as wasmMap from '@/pkg/common_wasm.js'
- import {
- fromUrl,
- fromArrayBuffer,
- fromFile
- } from 'geotiff'
- // #ifdef APP-PLUS
- // import io from '@/utils/io.js'
- // #endif
- let that = null
- let dbHelper = null
- let imgMap = null
- export default {
- async handleMapInfo(context, mapInfo) {
- that = context
- dbHelper = that.$dbHelper
- imgMap = that.$refs.imgMap
- console.log("[handleMapInfo]", context, mapInfo)
- console.log("[handleMapInfo] imgMap", imgMap)
- try {
- await dbHelper.openDB()
-
- const res = await this.dbGetMapInfo(mapInfo.shopid)
- let download = false
- let action = null
- let mapData = null
- if (res == null || res.length == 0) {
- console.warn('[handleMapInfo] 本地无匹配记录,需要下载地图')
- download = true
- action = 'insert'
- } else {
- const localMd5 = (res.zipImage != undefined) ? res.zipImage.md5 : res.zipImageMd5
- if (localMd5 != mapInfo.zipimage.md5) {
- console.warn('[handleMapInfo] MD5不同,需再次下载地图')
- download = true
- action = 'update'
- } else {
- console.log('[handleMapInfo] MD5相同,无需再次下载地图')
- download = false
- mapData = this.getMapDataFromDBres(res)
- // download = true // debug, will del
- // action = 'update' // debug, will del
- }
- }
-
- if (download) {
- const zipData = await this.getZipFiles(mapInfo.zipimage.url)
- // const unzipFiles = await this.unzipMap(zipData)
- // console.log("[handleMapInfo] download", mapInfo, unzipFiles)
- const unzipFiles = ''
- await this.dbSaveMapInfo(mapInfo, zipData, unzipFiles, action)
- // mapData = unzipFiles[0].fileData
- mapData = zipData
- }
-
- await dbHelper.closeDB()
-
- // await this.parseMap(mapData)
- // await this.parseMap2(mapData)
- await this.loadMap(mapData)
- // return mapData
- } catch (err) {
- console.error('[handleMapInfo]', err)
- }
- },
-
- // 从指定的URL下载地图压缩包
- async getZipFiles(zipUrl) {
- console.log("[getZipFiles] zipUrl:", zipUrl)
- if (!(zipUrl.length > 0)) {
- console.log("[getZipFiles] err: zipUrl 为空")
- return
- }
- let [err, res] = await uni.request({
- url: zipUrl,
- timeout: 60000, // 超时时间,单位 ms
- responseType: 'arraybuffer', // 设置响应的数据类型。合法值:text、arraybuffer
- });
- console.log("[getZipFiles]", res)
- return res.data
- },
- // 解包并获取包内的各文件内容数据 (arraybuffer格式)
- async unzipMap(zipData) {
- // console.log("[unzipMap] zipData: ", zipData)
- if (zipData == undefined || (!(zipData.byteLength > 0))) {
- console.log("[unzipMap] err: zipData 为空")
- return
- }
- console.log("[unzipMap] 压缩包大小(字节) zipData.byteLength:", zipData.byteLength)
- try {
- let jsZip = new JSZip()
- let zip = await jsZip.loadAsync(zipData)
- // console.log('zip.files', zip.files)
- let unzipFiles = []
- let i = 0
- for (let fileName in zip.files) { // filename为压缩包中的文件名
- console.log('[unzipMap] fileName', fileName)
-
- let isImage = fileUtils.isTypeImage(fileName)
- let fileData = ''
- let dataType = ''
- // 获取文件内容,可以使用string、arraybuffer等格式
- if (isImage) {
- fileData = await zip.file(fileName).async('arraybuffer')
- dataType = 'arraybuffer'
- } else {
- fileData = await zip.file(fileName).async('string')
- dataType = 'string'
- }
-
- // console.log('[unzipMap] content', content)
-
- unzipFiles[i] = {
- fileName: fileName,
- fileData: fileData,
- dataType: dataType
- }
- i++
- }
- return unzipFiles
- } catch(err) {
- console.error('[unzipMap]', err)
- }
- },
-
- // 将地图信息保存到本地数据库中
- async dbSaveMapInfo(mapInfo, zipData, unzipFiles='', action='insert') {
- // #ifdef H5
- await this.dbSaveMapInfo_H5(mapInfo, zipData, unzipFiles, action)
- // #endif
-
- // #ifdef APP-PLUS
- await this.dbSaveMapInfo_APP(mapInfo, zipData, unzipFiles, action)
- // #endif
- },
-
- // [H5端] 将地图信息保存到本地浏览器 dbHelper 数据库中
- async dbSaveMapInfo_H5(mapInfo, zipData, unzipFiles, action) {
- // console.log("[dbSaveMapInfo_H5]", mapInfo, unzipFiles)
-
- let storeName = 'mapInfo'
- let data = {
- shopId: mapInfo.shopid,
- mapName: mapInfo.mapname,
- zipImage: {
- url: mapInfo.zipimage.url,
- md5: mapInfo.zipimage.md5,
- },
- zipData: zipData,
- unzipFiles: unzipFiles
- }
-
- try {
- if (action == 'insert') {
- await dbHelper.insertData(storeName, data)
- } else if (action == 'update') {
- await dbHelper.updateData(storeName, data)
- } else {
- console.warn('[dbSaveMapInfo_H5] 参数 action 非法: ' + action)
- }
- } catch(err) {
- console.error('[dbSaveMapInfo_H5]', err)
- }
- },
- // [APP端] 将地图信息保存到手机中的 SQLITE 数据库中
- async dbSaveMapInfo_APP(mapInfo, zipData, unzipFiles, action) {
- // console.log("[dbSaveMapInfo_APP]", mapInfo, unzipFiles)
-
- let tableName = 'mapInfo'
- let zipFileKey = 'map_' + mapInfo.shopid
- let zipFileName = ''
- if (unzipFiles.length > 0) {
- zipFileName = unzipFiles[0].fileName
- // let zipFilePath = mapInfo.shopid + '_' + unzipFiles[0].fileName
- let zipFileData = uni.arrayBufferToBase64(unzipFiles[0].fileData)
-
- // await io.write(zipFilePath, zipFileData)
- uni.setStorageSync(zipFileKey, zipFileData);
-
- console.log("[dbSaveMapInfo_APP] setStorageSync Key:", zipFileKey)
- console.log("[dbSaveMapInfo_APP] setStorageSync data.fileData length:", unzipFiles[0].fileData.byteLength)
-
- // let zipFile = uni.base64ToArrayBuffer(uni.getStorageSync(zipFileKey));
- // console.log("-----> getStorageSync Key", zipFileKey)
- // console.log("-----> getStorageSync data.fileData length", zipFile.byteLength)
- }
-
- let data = {
- shopId: mapInfo.shopid,
- mapName: mapInfo.mapname,
- zipImageUrl: mapInfo.zipimage.url,
- zipImageMd5: mapInfo.zipimage.md5,
- zipFileName: zipFileName,
- zipFileKey: zipFileKey,
- // zipFilePath: zipFilePath,
- }
-
- try {
- if (action == 'insert') {
- await dbHelper.insertData(tableName, data)
- } else if (action == 'update') {
- let wsql = 'shopId = ' + data.shopId
- await dbHelper.updateData(tableName, data, wsql)
- } else {
- console.warn('[dbSaveMapInfo_APP] 参数 action 非法: ' + action)
- }
- } catch(err) {
- console.error('[dbSaveMapInfo_APP]', err)
- }
- },
-
- async dbGetMapInfo(shopid) {
- let res = null
-
- // #ifdef H5
- res = await this.dbGetMapInfo_H5(shopid)
- // #endif
-
- // #ifdef APP-PLUS
- res = await this.dbGetMapInfo_APP(shopid)
- // #endif
-
- return res
- },
-
- // [H5端]
- async dbGetMapInfo_H5(shopid) {
- console.log("[dbGetMapInfo_H5]", shopid)
- let storeName = 'mapInfo'
- let key = shopid
-
- try {
- let data = await dbHelper.getDataByKey(storeName, key)
- return data
- } catch(err) {
- console.error('[dbGetMapInfo_H5]', err)
- }
- },
- // [APP端]
- async dbGetMapInfo_APP(shopid) {
- console.log("[dbGetMapInfo_APP] shopid", shopid)
- let tableName = 'mapInfo'
- let key = shopid
-
- try {
- let data = await dbHelper.getDataByKey(tableName, key)
-
- if (data != '' && data.zipFileKey.length > 0) {
- // let zipFileData = uni.base64ToArrayBuffer(await io.read(data.zipFilePath))
- let zipFileData = uni.base64ToArrayBuffer(uni.getStorageSync(data.zipFileKey))
- console.log("[dbGetMapInfo_APP] getStorageSync Key", data.zipFileKey)
- console.log("[dbGetMapInfo_APP] getStorageSync data length", zipFileData.byteLength)
-
- data.zipFileData = zipFileData
- }
- // console.log("[dbGetMapInfo_APP] data", data)
- return data
- } catch(err) {
- console.error('[dbGetMapInfo_APP]', err)
- }
- },
-
- getMapDataFromDBres(dbres) {
- let arrayBuffer = null
-
- // #ifdef H5
- // arrayBuffer = dbres.unzipFiles[0].fileData
- arrayBuffer = dbres.zipData
- // console.log('getMapDataFromDBres', dbres.unzipFiles[0].fileName, dbres.unzipFiles[0].fileData)
- // #endif
-
- // #ifdef APP-PLUS
- arrayBuffer = dbres.zipFileData
- // console.log('getMapDataFromDBres', dbres.zipFileName, dbres.zipFileData)
- // #endif
-
- return arrayBuffer
- },
- async parseMap(arrayBuffer) {
- // console.log("[parseMap]", arrayBuffer)
- // for(let i=0; i<30; i++) {
- // console.log(`[parseMap] arrayBuffer[${i}] ${arrayBuffer[i]}`)
- // }
-
- if (arrayBuffer == undefined || (!(arrayBuffer.byteLength > 0))) {
- console.log("[parseMap] err: arrayBuffer 为空")
- return
- }
- console.log("[parseMap] MAP文件大小(字节) arrayBuffer.byteLength: " + arrayBuffer.byteLength)
- try {
- // 加载 GeoTIFF 文件
- const tiff = await fromArrayBuffer(arrayBuffer)
- console.log("[parseMap] tiff", tiff)
- const image = await tiff.getImage()
- console.log("[parseMap] image", image)
- const width = image.getWidth();
- const height = image.getHeight();
- const tileWidth = image.getTileWidth();
- const tileHeight = image.getTileHeight();
- console.log(
- `[parseMap] width: ${width} height: ${height} tileWidth: ${tileWidth} tileHeight: ${tileHeight}`
- )
- // const samplesPerPixel = image.getSamplesPerPixel();
- // let canvas = this.$refs.canvasMap
- // canvas.width = width
- // canvas.height = height
- // let ctx = canvas.getContext('2d')
- // let ctx = uni.createCanvasContext('canvasMap', this)
- // 渲染图片
- // ctx.drawImage(image, 0, 0)
- // ctx.draw()
- // console.log('图片渲染完成')
- // return
- let imageData = new Uint8ClampedArray(width * height * 4)
- // console.log("imageData:", imageData)
- // let src = that
- image.readRasters().then(function(rasters) {
- // console.log("rasters:", rasters)
- // console.log("rasters:", JSON.stringify(rasters))
- for (let i = 0; i < width * height; i++) {
- let offset = i * 4
- // console.log("rasters[0]:", rasters[0][i])
- imageData[offset + 0] = rasters[0][i]
- imageData[offset + 1] = rasters[1][i]
- imageData[offset + 2] = rasters[2][i]
- imageData[offset + 3] = 255
- }
- uni.canvasPutImageData({
- canvasId: 'canvasMap',
- data: imageData,
- x: 0,
- y: 0,
- width: width,
- // height: 100,
- success(res) {
- console.log("[parseMap] canvasPutImageData res", res)
- },
- fail(err) {
- console.log("[parseMap] canvasPutImageData err", err)
- }
- })
- // ctx.draw()
- })
-
- // // when we are actually dealing with geo-data the following methods return
- // // meaningful results:
- // const origin = image.getOrigin();
- // const resolution = image.getResolution();
- // const bbox = image.getBoundingBox();
- } catch (err) {
- console.error("[parseMap] catch err:", err)
- }
- },
-
- async parseMap2(mapData) {
- let binaryData = [];
- binaryData.push(mapData);
- that.mapUrl = URL.createObjectURL(new Blob(binaryData));
-
- console.log("[parseMap2] imgMap", imgMap)
- // imgMap.src = URL.createObjectURL(new Blob(binaryData));
- },
-
- async loadMap(mapData) {
- try {
- let mapPackage = wasmMap.parse_map_package(new Uint8Array(mapData))
- console.log("[loadMap] mapPackage", mapPackage)
-
- let binaryData = [];
- binaryData.push(mapPackage.map_image_data);
- that.mapUrl = URL.createObjectURL(new Blob(binaryData));
-
- return
- await mapCanvas.initCanvas('canvasMap', that)
- mapCanvas.handleDrawMap(that.mapUrl)
-
- // let offset = new wasmMap.Offset()
- // offset.x = 100
- // offset.y = 200
- // let position = mapPackage.pic_to_position(offset)
- // console.log("[loadMap] pic_to_position", offset, position)
-
- // let position2 = new wasmMap.Position()
- // position2.latitude = 36.67352331171326
- // position2.longitude = 117.1257123815962
- // let offset2 = mapPackage.position_to_pic(position2)
- // console.log("[loadMap] position_to_pic", position2, offset2)
-
- // 使用完毕后一定要调用free方法释放内存
- // position.free()
- // offset2.free()
- // mapPackage.free()
-
- // console.log("[loadMap] imgMap", imgMap)
- } catch (err) {
- console.error('[loadMap]', err)
- }
- }
- }
|