正在查找瓣叶多边形的中心?

t1qtbnec  于 2022-10-30  发布在  PHP
关注(0)|答案(5)|浏览(139)

我在自己创建的Map上有一堆传单多边形。每个多边形代表不同的东西。根据用户所在的页面,特定的一组信息会显示在弹出窗口中。我需要找到一种方法,使“弹出窗口”气泡在它所代表的多边形的中心打开。
每个多边形都是使用以下代码绘制的:

var L20 = [
    [74.0995, -99.92615],
    [74.14008, -99.4043],
    [74.07691, -99.33838],
    [74.03617, -99.86023]
];

var L19 = [
    [74.02559, -99.84924],
    [74.06636, -99.32739],
    [74.0029, -99.26147],
    [73.96197, -99.77783]
];

var L18 = [
    [73.95142, -99.76684],
    [73.99235, -99.25048],
    [73.92889, -99.18456],
    [73.8878, -99.69543]
];

var set1 = L.polygon([L20, L19, L18], {
    color: "#fff",
    weight: 1,
    stroke: true,
    opacity: 0.05,
    fillColor: "#346B1F",

}).addTo(map);

该弹出窗口是使用以下代码绘制的:

var popup = L.popup({})
    .setLatLng([73.64017, -100.32715])
    .setContent(content).openOn(map);
    var popup = L.popup();

所以我需要为.setLatLang找到一种方法来确定或者被给定多边形的中心。
我想出了3个可能有效的解决方案,但不知道如何去做。
1.找到一种方法,使用多边形的坐标来确定弹出窗口将打开的多边形的中心。
1.调用多边形的一个点,然后偏移弹出窗口的位置。
1.为每个多边形使用一个id,这样每个弹出窗口都知道它可以在哪个框区域(多边形)中打开。
有人能帮帮我吗?

wlp8pajw

wlp8pajw1#

一段时间以来,Leaflet已经内置了getCenter()方法:

polygon.getBounds().getCenter();
fumotvh3

fumotvh32#

有几种方法可以近似多边形的形心。
最简单(但精度最低)的方法是使用polygon.getBounds().getCenter();获得包含多边形的边界框的中心,如yarl所建议的
我最初用求点的质心的公式来回答这个问题,它可以通过求顶点坐标的平均值来求出。

var getCentroid = function (arr) { 
    return arr.reduce(function (x,y) {
        return [x[0] + y[0]/arr.length, x[1] + y[1]/arr.length] 
    }, [0,0]) 
}

centerL20 = getCentroid(L20);

虽然点的质心是一个足够接近的近似值来欺骗我,但一位评论者指出,它不是多边形的质心 *。
基于非自交闭合多边形的质心公式的实现给出了正确的结果:

var getCentroid2 = function (arr) {
    var twoTimesSignedArea = 0;
    var cxTimes6SignedArea = 0;
    var cyTimes6SignedArea = 0;

    var length = arr.length

    var x = function (i) { return arr[i % length][0] };
    var y = function (i) { return arr[i % length][1] };

    for ( var i = 0; i < arr.length; i++) {
        var twoSA = x(i)*y(i+1) - x(i+1)*y(i);
        twoTimesSignedArea += twoSA;
        cxTimes6SignedArea += (x(i) + x(i+1)) * twoSA;
        cyTimes6SignedArea += (y(i) + y(i+1)) * twoSA;
    }
    var sixSignedArea = 3 * twoTimesSignedArea;
    return [ cxTimes6SignedArea / sixSignedArea, cyTimes6SignedArea / sixSignedArea];        
}
gudnpqoy

gudnpqoy3#

您 尝试 解决 的 问题 称为 " * * 极 难 接近 * * 问题 " 。 在 多边 形 中 找到 放置 标签 的 最 佳 位置 并 不能 通过 找到 边界 框 的 中心 来 完全 解决 。 考虑 一 个 形状 为 字母 U 的 多边 形 。 边界 框 的 中心 将 标签 放置 在 多边 形 的 外部 。 我 花 了 很 长 时间 才 找到 这个 出色 的 库 :https://github.com/mapbox/polylabel 的 最 大 值
摘自 * * 自述 文件 . MD : * *
一 种 快速 算法 , 用于 查找 多边 形 的 不可 访问 极点 , 即 距离 多边 形 轮廓 最 远 的 内部 点 ( 不要 与 质心 混淆 ) , 以 JavaScript 库 的 形式 实现 。 对于 在 多边 形 上 优化 放置 文本 标签 非常 有用 。
这 是 一 种 迭代 网格 算法 , 灵感 来自 Garcia-Castellanos 和 Lombardo 于 2007 年 发表 的 论文 。 与 论文 中 的 算法 不同 , 此 算法 :

  • 保证 在 给定 精度 内 找到 全局 最 优 解
  • 速度 快 许多 倍 ( 10 - 40 倍 )

用法 :
给定 类似 GeoJSON 格式 的 多边 形 坐标 和 精度 ( 默认 为 1.0 ) , Polylabel 将 返回 [ x , y ] 格式 的 不可 访问 坐标 的 极点 。
x1月 1 日

算法 的 工作 原理 :
这 是 一 种 基于 网格 的 迭代 算法 , 它 首先 用 大 的 正方 形 单元 覆盖 多边 形 , 然后 按照 最 有 希望 的 顺序 迭代 地 分割 它们 , 同时 积极 地 修剪 不 感 兴趣 的 单元 。
1.生成 完全 覆盖 多边 形 的 初始 正方 形 像 元 ( 像 元 大小 等于 宽度 或 高度 , 以 较小 者 为准 ) 。 计算 从 每个 像 元 中心 到 外部 多边 形 的 距离 , 如果 点 位于 多边 形 外部 ( 通过 光线 投射 检测 ) , 则 使用 负值 。
1.将 像 元 放入 优先 级 队列 中 , 按 与 像 元 内 某 点 的 最 大 潜在 距离 排序 , 该 距离 定义 为 与 中心 的 距离 和 像 元 半径 之 和 ( 等于 cell _ size * sqrt ( 2 )/2 ) 。
1.计算 与 多边 形 质心 的 距离 , 并 将 其 选 作 第 一 个 " 目前 最 佳 " 。
1.从 优先 级 队列 中 逐个 取出 单元 格 。 如果 单元 格 的 距离 比 当前 最 佳 值 更 好 , 则 将 其 保存 。 然后 , 如果 该 单元 格 可能 包含 比 当前 最 佳 值 更 好 的 解 ( cell _ max - best _ dist 〉 precision ) , 则 将 其 拆分 为 4 个子 单元 格 并 将 其 放入 队列 。
1.当 队列 耗尽 时 , 停止 算法 , 返回 最 优 单元 格 的 中心 作为 不可 达 极点 , 保证 在 给定 精度 内 是 全局 最 优 的 。


语言

yruzcnhs

yruzcnhs4#

假设每个多边形只有4条边

var L20 = [
[74.0995, -99.92615],
[74.14008, -99.4043],
[74.07691, -99.33838],
[74.03617, -99.86023]
];

使用此示例获取最大和最小LAT:分别为74.03617和74.14008,因此长时间相同:分别为-99.92615和99.33838
然后得到每个的中间值:(最大值-最小值)/ 2 = 0.051955和-0.293885,然后将它们加到最小量上
中心为74.088125, -99.632265

mznpcxlj

mznpcxlj5#

要将多边形移动到视图中并使其居中,请用途:

map.fitBounds(poly.getBounds())

这也将正确设置缩放级别。

相关问题