truf.js 创建只有两个点 polygon 写入 mongoDb 的 2dsphere 索引报错的问题

问题描述

我使用 truf.js 提取一个 lineString 的 bbox ,再根据 bbox 得到一个 bboxPolygon,最后将数据写入带 2dsphere 索引的文档,这时有些特定的 lineString 会出现入库失败,原因是 MongoDb 提示 polygon 至少需要3个点。

// 计算 lineString 对象的矩形边界
const turf = require("@turf/turf");
let lineString = {
        type : "LineString",
        coordinates : [ [10,25],
						[11,25],
						[12,25],
						[15,25],
						[20,25]]
}
const bbox = turf.bbox(lineString);
const bboxPolygon = turf.bboxPolygon(bbox);
// TODO: 写库

原因分析:

在检查 bbox 的数据时发现:

[[10,25],[20,25]]

这是一个直线,两个Y坐标是一致的,结果导致 bbox 生成的 bboxPolygon数据也不对:

[
	[10,25],
	[20,25],
	[20,25],
	[10,25],
	[10,25]
]

排重后只有两个点,这在 MongoDb 入库时的 2dsphere 索引判定就会报错。


解决方案:

对 bbox 的第二个点做微小位移,防止 bboxPolygon 的点少于3个


    /**
     * 计算 lineString 对象的矩形边界
     * 对 bbox 做检查,防止 bbox 成为直线
     * 如果 bboxPolygon 使用 bbox 生成,在入库到mongoDb 时会报错
     */
    calculateRectangleBounds(turfLineString) {
        // 计算 lineString 对象的矩形边界
        let bbox = turf.bbox(turfLineString);
        // 检查 bbox 点集合被压缩成直线的情况
        let [x1, y1, x2, y2] = bbox;
        // 如果被压缩成直线,对后一个点的坐标做微小的位移
        let isFixed = false;
        if (x1 === x2) {
            x2 = this.floatTinyOffset(x2);
            isFixed = true;
        }
        if (y1 === y2) {
            y2 = this.floatTinyOffset(y2);
            isFixed = true;
        }
        if (isFixed) {
            bbox = [x1, y1, x2, y2];
        }
        const bboxPolygon = turf.bboxPolygon(bbox);
        return bboxPolygon;
    }

    /**
     * 对浮点数做微小的加法
     * eg: 38.1280970893173 -> 38.1280970893174
     * @param {Number} floatNumber
     * @returns Number
     */
    floatTinyOffset(floatNumber) {
        floatNumber = _.toNumber(floatNumber);
        let [zs, xs] = floatNumber.toString().split(".");
        return _.toNumber(zs + "." + (_.toInteger(xs) + 1));
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值