arcgis 切片分析录入mongodb

将arcgis的切片数据录入mongodb,这样可以支持自定义的server发步

以下是对3种arcgis切片规则的分析

松散型

也就是我们常见的文件式的切片管理方式,将 Arcgis Server 切出来的切片图片按照行列号的规范,存储在相应的文件夹中。

循环所有.png文件路径,存入mongodb数据库

javascript 复制代码
for (let i = 0; i < total; i++)
                    {
                        console.log("循环录入文件:" + i + "/" + total + "\t" + filesPaths[i]);
                        let filePath = filesPaths[i];

                        let data = fs.readFileSync(filePath);

                        filePath = filePath.replace(/\\/g, '/');
                        filePath = filePath.replace(rootFolder + '/', '');

                        //L08\R00000061\C000000D3.png

                        var infoString = filePath.replace(".png", "");
                        let level = parseInt(infoString.split('/')[0].replace("L", ""));
                        let row = parseInt(infoString.split('/')[1].replace("R", ""), 16);
                        let column = parseInt(infoString.split('/')[2].replace("C", ""), 16);

                        let b3dmData = { 'level': level, 'row': row, 'column': column, 'fullPath': filePath, 'data': data };
                        b3dmDataSet.push(b3dmData);
                        if (i != 0 && i % 10000 == 0)
                        {
                            await collection.insertMany(b3dmDataSet);
                            b3dmDataSet = [];
                            let proc = (i / total).toFixed(2) * 100;
                            console.log('已完成 ' + proc + '%');
                        } else if (i == filesPaths.length - 1)
                        {
                            await collection.insertMany(b3dmDataSet);
                            b3dmDataSet = [];
                            await client.close();
                            console.log('已完成 100%');
                        }
                    }

早期紧凑型

将切好的切片转化成.bundle.bundlex的两种文件格式存储。

  • 其中bundle文件用以存储切片数据,bundlx 是 bundle 文件中切片数据的索引文件

  • 一个 bundle 文件中最多可以存储128×128(16384)个切片;

  • 在 bundlx 文件中用固定的字节数量(5字节)标识一个切片在 bundle 文件中的状态(偏移量);每个 bundlx 文件都是一样的大小:81952字节,起始16字节和文件结束16字节与索引无关,剩余的81920字节数据以5个字节的频率重复,构成了一个对bundle文件的索引【注:16384 * 5 = 81920】;这5个字节标示了切片数据的偏移量。

  • 在 bundle 文件中,每2个切片数据之间相隔了4个字节;这4个字节正好是以低位到高位的方式标示了后续这个切片数据的长度。

  • 切片数据的长度(4字节)和数据偏移(5字节)是无符号的整数。

  • bundlx 文件的文件名,包含了切片的行列信息,而它所在的文件夹名称(目录名称),则包含切片的级别信息。

因此,我们如果知道了一个切片的级别、行号、列号,就可以找到相应的 bundlx 文件,并通过 bundlx 首先找到bundle中切片内容的偏移,然后从bundle文件中取出4个字节的长度数据,再随后根据这个长度读取真实的切片数据。

复制代码
假设已知切片的级别、行号和列号,求对应的 bundlx 文件:

目录名:L开头,并加上级别,级别不足2位的,高位补0,例如:L01,L19等。

文件名:R开头,加上4位16进制数(行号组最小行号),
	   再加上字母C,最后加上4位16进制数(列号组最小列号),
	   例如:R0080C0080.bundlx
	   
行号组最小行号、列号组最小列号 的计算:
(1)因为一个 bundle 文件中最多可以存储 128×128 个切片,所以,
	行号/128,向下取整,得到切片所在的"行号组的序数 r"(即第 r 组);
	列号/128,向下取整,得到切片所在的"列号组的序数 c"(即第 c 组);
	r * 128,得到所在行组的最小行号 rrrr;
	c * 128,得到所在列组的最小列号 cccc;
(2)将 rrrr 和 cccc 转成 16 进制数,并转化为长度为4的字符串(不足4位时,高位补0);

找到 bundlx 文件:
(3)拼接出文件名:R{rrrr}C{cccc}.bundlx
(4)拼接出路径:_alllayers\level\R{rrrr}C{cccc}.bundlx

--------------------------------

假设已知切片的级别、行号和列号,求对应的切片数据:

(1)求切片的序数:
行号 - 行号组最小行号(即:行号-rrrr),得到切片在当前行号组的序数 m;
列号 - 列号组最小列号(即:列号-cccc),得到切片在当前列号组的序数 n;
 m + 128 *n,得到切片在 bundle 文件中的序数 index(即:切片是 bundle 中总共的16384 张切片中的第 index 张切片);

(2)求切片的位置(偏移量):
因为在 bundlx 文件中,每张切片的位置信息用5字节表示,且头部有16个起始字节,所以,前(16 + 5 * index)个字节需要忽略;之后的5字节是切片的位置信息,如下解析切片的位置信息:
偏移量 offset = 第0字节 + 第1字节 * 256 + 第2字节 * 256 * 256 + 第3字节 * 256 * 256 * 256 + 第4字节 * 256 * 256 * 256 * 256。

(3)求切片的长度:
因为切片之前4个字节,是切片的长度信息,所以 用 offset 之后的四个字节来计算切片的长度,如下:
切片长度 length = 第0字节 + 第1字节 * 256 + 第2字节 * 65536 + 第3字节 * 16777216

(4)读取切片
offset 之后 length 个字节,就是切片的图片流。

以下是为了将arcgis切片数据存入mongodb中的核心代码

filepath为各个索引文件路径

b3dmDataSet为要存入mongodb的数据集

javascript 复制代码
                        //读取索引文件
                        let indexData = fs.readFileSync(filePath);
                        //读取数据文件
                        let imgdata = fs.readFileSync(filePath.replace(".bundlx", ".bundle"));

                        filePath = filePath.replace(/\\/g, '/');
                        filePath = filePath.replace(rootFolder + '/', '');

                        let level = parseInt(filePath.split('/')[0].replace("L", ""));
                        let filename = filePath.split('/')[1].split('.')[0];
                        let minRow = parseInt(filename.split('C')[0].replace("R", ""), 16);
                        let minColumn = parseInt(filename.split('C')[1].replace("C", ""), 16);

                        for (var rowindx = minRow; rowindx < minRow + size; rowindx++)
                        {
                            for (var colindx = minColumn; colindx < minColumn + size; colindx++)
                            {
                                var currentImageData = [];
                                //读取数据
                                {
                                    //计算切片序号
                                    var indexQP = (rowindx - minRow) + (colindx - minColumn) * size;
                                    //计算切片偏移量
                                    var offset = 0;
                                    {
                                        //需要忽略的长度
                                        var hLength = 16 + (5 * indexQP);
                                        //计算切片偏移量
                                        offset = //indexData.readUInt16LE(hLength);
                                            indexData[hLength] +
                                            (indexData[hLength + 1] * 256) +
                                            (indexData[hLength + 2] * 256 * 256) +
                                            (indexData[hLength + 3] * 256 * 256 * 256) +
                                            (indexData[hLength + 4] * 256 * 256 * 256 * 256);
                                    }

                                    //计算切片长度
                                    var qpLenth = imgdata[offset] +
                                        (imgdata[offset + 1] * 256) +
                                        (imgdata[offset + 2] * 256 * 256) +
                                        (imgdata[offset + 3] * 256 * 256 * 256);

                                    currentImageData = imgdata.slice(offset + 4, offset + 4 + qpLenth);
                                }

                                if (currentImageData.length > 0)
                                {
                                    let b3dmData = { 'level': level, 'row': rowindx, 'column': colindx, 'fullPath': filePath, 'data': currentImageData };
                                    b3dmDataSet.push(b3dmData);
                                }
                            }
                        }

10.3以后的紧凑型(未验证)

将切好的切片转化成.bundle的格式来存储。

  • 切片的索引、切片的偏移和切片的图片流都必然包含在这一.bundle文件中;

  • 头信息:.bundle文件起始 64 字节 是 bundle 的文件头信息;

  • 位置信息:头信息之后,记录了 16384 张切片的位置;每个位置信息,用8个字节表示;仅前4字节有用,从低位到高位;后4字节可忽略;

  • 图片流信息:位置信息之后,是图片流信息;每个切片图,先以4字节记录切片的长度,而后紧跟图片的流信息。

  • .bundle文件的文件名以及所在文件夹的名称,包含切片的级别、行列信息。

    假设已知切片的级别、行号和列号,求对应的 bundle 文件:
    求取方式同 "假设已知切片的级别、行号和列号,求对应的 bundlx 文件"。


    假设已知切片的级别、行号和列号,求对应的切片数据:

    (1)求切片的序数:
    行号 - 行号组最小行号(即:行号-rrrr),得到切片在当前行号组的序数 m;
    列号 - 列号组最小列号(即:列号-cccc),得到切片在当前列号组的序数 n;
    128 * m + n,得到切片在 bundle 文件中的序数 index(即:切片是 bundle 中总共的16384 张切片中的第 index 张切片);

    (2)求切片的位置(偏移量):
    因为每张切片的位置用8字节表示,且头信息占64字节,所以,前(64 + 8 * index)个字节需要忽略;之后的8字节是切片的位置信息(仅前4字节有用),如下解析切片的位置信息:
    偏移量 offset = 第1字节 + 第2字节 * 256 + 第3字节 * 65536 + 第4字节 * 16777216。

    (3)求切片的长度:
    因为切片之前4个字节,是切片的长度信息,所以 用(offset-4)之后的四个字节来计算切片的长度,如下:
    切片长度 length = 第0字节 + 第1字节 * 256 + 第2字节 * 65536 + 第3字节 * 16777216

    (4)读取切片
    offset 之后 length 个字节,就是切片的图片流。

相关推荐
无心使然云中漫步13 小时前
Openlayers调用ArcGis地图服务之一 —— 地图切片(/tile)
前端·arcgis·vue·数据可视化
无心使然云中漫步21 小时前
Openlayers调用ArcGis地图服务之三 —— 要素查询(/query)
前端·arcgis·vue·数据可视化
无心使然云中漫步2 天前
Openlayers调用ArcGis地图服务之二 —— 动态地图(/export)
前端·arcgis·vue·数据可视化
IT菜鸟程2 天前
漏洞修复案例:ArcGIS Server REST 服务目录敏感信息泄露
网络·安全·arcgis
刘晨鑫12 天前
MongoDB数据库应用
数据库·mongodb
爬山算法3 天前
MongoDB(92)什么是变更流(Change Streams)?
数据库·mongodb
小冯不疯3 天前
旺店通与金蝶云星空入库单管理对接方案
mongodb
MongoDB 数据平台3 天前
为编码代理引入 MongoDB 代理技能和插件
数据库·mongodb
忍冬行者3 天前
MongoDB 三节点副本集离线部署运维手册
运维·数据库·mongodb
AI视觉网奇4 天前
latex公式渲染
arcgis