繁体   English   中英

用指定半径的圆点填充经度/纬度图的最有效方法是什么?

[英]What's the most efficient way to fill a longitude / latitude map with circular points of specified radius?

因此,我试图绕过某些公司API的限制,这些API提供有关景点的数据。 API不允许我收集整个状态的结果。 相反,我必须指定纬度/经度坐标,并以1到50000m的圆形半径收集附近的位置。 该API一次一次仅返回60个结果,无论指定位置中有多少个结果。 我知道我会在指定位置遇到60多个地方,但是我打算递归地将这些情况一分为二并进行处理。

我想将纽约州作为我的第一个测试用例。

我正在使用来自https://www.arcgis.com/home/item.html?id=b07a9393ecbd430795a6f6218443dccc的shapefile获取NY的形状,并确定我的点是否在边界内。

import geopandas as gpd
from shapely.geometry import Point, Polygon

usa = gpd.read_file('states_21basic/states.shp')
polygon = usa[usa.STATE_ABBR == 'NY']['geometry'].values[0]
point = Point(-74.005974,40.712776) # create point
print(polygon.contains(point)) # check if polygon contains point

有人建议我尝试使用泛洪填充算法,但是我不确定如何从中获取间隔坐标列表(以最小化API调用),以及如何确保每个部分都被覆盖,即使是像NY这样的怪异形状。

我的主要目标是收集所有位置,同时尽量减少API调用。 我并不是真的希望有任何代码,只是关于如何解决这个问题的想法。

**很遗憾,我已经从公司除名,无法将答案标记为已接受

您的问题可能有一个好的解决方案,而不是一个完美的解决方案。 我在地图上工作了很长时间,而且大多数地图本身都很复杂。 您还有另一种复杂性,这是您无法控制的外部依赖性。 我必须在较低级别执行类似的操作,以查询Google Maps以获得较小区域(不超过20米)的站点,以尝试将最接近的地理位置与我所在的地理位置相匹配。 首先,您需要做一个假设并尝试一下。 假设可能仅使用100米半径,或多或少覆盖一个街区。 您遇到的第二个问题是密度。 您可以在一段时间内探索零兴趣点的地图(纽约有很多空旷的地方,周围可能几乎没有任何东西)。

假设您可以将解决方案围成一个形状。 建议您从密集区域(曼哈顿?)中的预定义点开始,以在开始时最大化算法发现。 它运行时间越长,越接近检测到它将得到的更少。

泛洪填充算法在您的情况下是好的,但可能不是最好的。 例如,我可能会沿着街道走一些更复杂的东西,但是使用洪水填充的第一种方法会起作用。

“洪水填充”就像使用油漆,您朝一个方向行走; 在您的情况下,我建议使用8(N,S,W,E,NW,NE,SW,SE),检测是否已“绘制”(您需要将其存放在该位置的某个位置)为了避免重复调用,如果不重复调用API,Walking将打开一棵不同的执行树,从A点开始,递归地遍历N,S,E,W,NW,NE,SW,SE。像纽约这样的区域,该区域各有100米,将导致数千级递归,您需要对其进行优化。

要考虑的第三件事是检查点是否在多边形之外。 使用PNPoly非常简单。 一旦您位于多边形外,就必须停止在该方向上行走。

我与您分享为项目编码的C#中的PNPoly实现:

public bool IsCoordinateWithinPolygon(double latitude, double longitude, Polygon polygon)
{
    if(polygon == null || polygon.Coordinates.Count() == 0)
    {
        return false;
    }

    List<double> coordinatesY = new List<double>();
    List<double> coordinatesX = new List<double>();

    var minLatitude = double.MaxValue;
    var maxLatitude = double.MinValue;
    var minLongitude = double.MaxValue;
    var maxLongitude = double.MinValue;
    // Quick-check, determine if the coordinate is outside of the bounding rectangle
    foreach(var linearRing in polygon.Coordinates)
    {
        foreach (var coordinate in linearRing.Coordinates)
        {
            coordinatesY.Add(coordinate.Latitude);
            coordinatesX.Add(coordinate.Longitude);
            if (coordinate.Latitude < minLatitude)
            {
                minLatitude = coordinate.Latitude;
            }
            if(coordinate.Latitude > maxLatitude)
            {
                maxLatitude = coordinate.Latitude;
            }
            if(coordinate.Longitude < minLongitude)
            {
                minLongitude = coordinate.Longitude;
            }
            if(coordinate.Longitude > maxLongitude)
            {
                maxLongitude = coordinate.Longitude;
            }
        }
    }

    // Determine if the coordinate is outside the bounding box
    if( (latitude < minLatitude || latitude > maxLatitude) &&
        (longitude < minLongitude || longitude < maxLongitude))
    {
        // Out of the box
        return false;
    }

    // PNPoly Algorithm - Point Inclusion in Polygon Test 
    bool inclusion = false;
    var verty = coordinatesY.ToArray();
    var vertx = coordinatesX.ToArray();
    var nvert = vertx.Length;
    var testy = latitude;
    var testx = longitude;

    for (int i = 0, j = nvert - 1; i < nvert; j = i++)
    {
        if (((verty[i] > testy) != (verty[j] > testy)) &&
         (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i]))
            inclusion = !inclusion;
    }

    return inclusion;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM