论如何获取 2 个多边形相交关系

栏目: 编程工具 · 发布时间: 7年前

内容简介:2 个多边形的关系无非:

2 个多边形的关系无非:

  • 相交(一处交集)

论如何获取 2 个多边形相交关系

  • 相交(多处交集)

论如何获取 2 个多边形相交关系

  • 相切(相交的一种,交集为线)

论如何获取 2 个多边形相交关系

  • 包含(相交的一种,交集为面积较小多边形)

论如何获取 2 个多边形相交关系

  • 相等(相交的一种,交集为 2 多边形本身)

论如何获取 2 个多边形相交关系

  • 相离(无交集)

论如何获取 2 个多边形相交关系

先向大家阐述我的应用场景:需求方欲通过在地图上绘制蜂窝以分配员工所负责区域。纯手工绘制易将道路、楼、园林、水系等切割引发划分纠纷,故我们接入一叫 block 的服务,根据绘制点返回周围的 N 个 block 即真正的地理分区(不切割道路、楼、园林、水系等),我们将这 N 个 block 合并形成一整个蜂窝。但绘制点跨度较大时将遗漏其间细小 block 产生缝隙,更糟糕的情况是产生零散块儿使合并结果不为一整体。此刻需获知每一零散块儿与蜂窝的关系,丢弃相离及被完全包含的,并入相交的。

论如何获取 2 个多边形相交关系

业务场景不再赘述,直接上代码:

import MD5 from 'md5'
import TURF from 'turf'

/**
 * 获取 N 个多边形面积
 * @param callback
 * @param opts
 *  polygons(List{ polygonOpts })(必传): 多边形对象 List
 *  order(String)(默认不排序): ascend(升序) 或 descend(降序)
 *  @param polygonOpts
 *   path(Path)(必传): 路径 [[lng(Number), lat(Number)], ...]
 */
export function getPolygonsArea (callback, opts = {}) {
    var polygons = opts.polygons
    var response = { polygons: [] }
    for (let i = 0; i < polygons.length; i++) {
        // 获取多边形面积
        let area = TURF.area(TURF.polygon([polygons[i].path]))
        response.polygons.push({ ...polygons[i], area: area })
    }
    switch (opts.order) {
    // 升序排列
    case 'ascend':
        response.polygons.sort((a, b) => a.area - b.area)
        break
    // 降序排列
    case 'descend':
        response.polygons.sort((a, b) => b.area - a.area)
        break
    default:
        break
    }
    callback && callback(response)
}

/**
 * 获取 2 个多边形相交关系
 * @param callback
 * @param opts
 *  polygonA(Polygon{ polygonOpts })(必传): 多边形对象 A
 *  polygonB(Polygon{ polygonOpts })(必传): 多边形对象 B
 *  @param polygonOpts
 *   path(Path)(必传): 路径 [[lng(Number), lat(Number)], ...]
 */
export function getPolygonsRelation (callback, opts = {}) {
    var polygonA = TURF.polygon([opts.polygonA.path])
    var polygonB = TURF.polygon([opts.polygonB.path])
    // 获取 polygonA 与 polygonB 交集
    var intersection = TURF.intersect(polygonA, polygonB)
    if (intersection) {
        let geometry = intersection.geometry
        switch (geometry.type) {
            // 交集为线
            case 'MultiLineString':
                callback && callback({
                    relation: 'tangent',
                    desc: '相切的',
                    intersection: intersection,
                    polygonA: opts.polygonA,
                    polygonB: opts.polygonB
                })
                return
            // 交集为多个多边形
            case 'MultiPolygon':
                callback && callback({
                    relation: 'multiIntersectant',
                    desc: '相交的(多处交集)',
                    intersection: intersection,
                    polygonA: opts.polygonA,
                    polygonB: opts.polygonB
                })
                return
            // 交集为单个多边形
            case 'Polygon':
                getPolygonsArea((res) => {
                    // 面积较小多边形
                    let minPolygon = res.polygons[0]
                    // 面积较大多边形
                    let maxPolygon = res.polygons[1]
                    // 判断 2 个多边形 path 是否一模一样
                    if (MD5(minPolygon.path) === MD5(maxPolygon.path)) {
                        callback && callback({
                            relation: 'equal',
                            desc: '相等的',
                            intersection: intersection,
                            polygonA: opts.polygonA,
                            polygonB: opts.polygonB
                        })
                        return
                    }
                    // 判断较小多边形 path 与交集多边形 path 是否一模一样
                    if (MD5(minPolygon.path) === MD5(geometry.coordinates[0])) {
                        callback && callback({
                            relation: 'included',
                            desc: '包含的',
                            intersection: intersection,
                            polygonA: opts.polygonA,
                            polygonB: opts.polygonB,
                            minPolygon: minPolygon,
                            maxPolygon: maxPolygon
                        })
                    } else {
                        callback && callback({
                            relation: 'intersectant',
                            desc: '相交(一处交集)',
                            intersection: intersection,
                            polygonA: opts.polygonA,
                            polygonB: opts.polygonB
                        })
                    }
                }, {
                    polygons: [opts.polygonA, opts.polygonB],
                    order: 'ascend'
                })
                return
        }
    } else {
        callback && callback({
            relation: 'separated',
            desc: '相离的',
            intersection: intersection,
            polygonA: opts.polygonA,
            polygonB: opts.polygonB
        })
    }
}

机智的你发现我利用了第三方库 turf ,未自行研究大量几何算法。此分享内容不多,代码量较小,望勿嫌弃。俗话说“君子善假于物也”,俗话又说“天下代码一大抄,看你会抄不会抄”…

作者:呆恋小喵

我的后花园: https://sunmengyuan.github.io/garden/

我的 github: https://github.com/sunmengyuan

原文链接: https://sunmengyuan.github.io/garden/2018/08/31/polygon-relation.html


以上所述就是小编给大家介绍的《论如何获取 2 个多边形相交关系》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Learning PHP, MySQL, JavaScript, and CSS

Learning PHP, MySQL, JavaScript, and CSS

Robin Nixon / O'Reilly Media / 2012-9-3 / USD 39.99

If you're familiar with HTML, you can quickly learn how to build interactive, data-driven websites with the powerful combination of PHP, MySQL, and JavaScript - the top technologies for creating moder......一起来看看 《Learning PHP, MySQL, JavaScript, and CSS》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具