2

私はこのコードを持っています。それは国のジオメトリとポイントのセットを取り、それらの国内のポイントのみを返します:

public static IEnumerable<Point> RemovePointsOutsideBorders(IEnumerable<Point> points, IEnumerable<Country> countries)
{
    var cc = new List<Point>();

    var SPAT_REF_ID = 4326;
    foreach (var p in points)
    {
            var validText = new SqlChars(new SqlString(string.Format("POINT({0} {1})", p.Longitude, p.Latitude)));
            var geoPoint = SqlGeometry.STPointFromText(validText, SPAT_REF_ID);

        foreach (var c in countries)
        {
            if(c.Polygon.STIntersects(geoPoint))
            {
                cc.Add(p);
                break;
            }
        }
    }

    return cc;
}

現在は非常に遅く、約 4000 のポイントがあり、緯度と経度の値が 2 倍で、そこから SqlGeometry への変換が遅くなります (約 25 秒かかります。これをおそらく 1 秒か 2 秒にする必要があります)。

var s = new SqlChars(new SqlString(string.Format("POINT({0} {1})", p.Longitude, p.Latitude)));
var pGeo = SqlGeometry.STPointFromText(s, SPAT_REF_ID);

これは、SqlGeometry.Point が緯度、経度の代わりに x、y を取るためにのみ行われます...どうすればこれをスピードアップできますか?

SqlGeometry (c.Polygon)速度を上げるために を減らすことができることは既に知っていますが、それを制御することはできません。私が求めているのは、緯度/経度から SqlGeometry ポイントへの変換を高速化する方法です。

4

1 に答える 1

2

これは私が最終的に思いついた解決策です.0.5秒ですべてを行います:

public static IEnumerable<Point> RemovePointsOutsideBorders(IEnumerable<Point> points, IEnumerable<Country> countries)
{
    // join all the country polygons into one (make a stamp)
    var allCountryPolygon = countries.Select(x => x.Polygon).UnionAll();

    // make a single geometry shape from our evenly spaced extent points (cookie dough)
    var pointsGeo = PointsToGeometry(points);

    // do an intersect (stamp country shape over extent based geometry)
    var cookieOfPoints = pointsGeo.STIntersection(allCountryPolygon);

    // how many points left inside? pick them all back out
    for (int n = 1; n <= cookieOfPoints.STNumPoints(); n++)
    {
        var insidePoint = cookieOfPoints.STPointN(n);
        yield return new Point
        {
            Longitude = insidePoint.STX.Value,
            Latitude = insidePoint.STY.Value
        };
    }
}

public static SqlGeometry PointsToGeometry(IEnumerable<Point> points)
{
    var bld = new SqlGeometryBuilder();
    bld.SetSrid(4326);
    bld.BeginGeometry(OpenGisGeometryType.MultiPoint);

    foreach (var p in points)
    {
        bld.BeginGeometry(OpenGisGeometryType.Point);
        bld.BeginFigure(p.Longitude, p.Latitude);
        bld.EndFigure();
        bld.EndGeometry();
    }

    bld.EndGeometry();
    return bld.ConstructedGeometry;
}

public static class ExtensionMethods
{
    /// <summary>
    /// Joins many geometries into one
    /// </summary>
    /// <param name="geometries">geometries to join</param>
    /// <returns>composite geometry</returns>
    public static SqlGeometry UnionAll(this IEnumerable<SqlGeometry> geometries)
    {
        var compositeGeometry = geometries.First();
        foreach (var g in geometries.Skip(1))
        {
            compositeGeometry = compositeGeometry.STUnion(g);
        }
        return compositeGeometry;
    }
}
于 2014-11-28T15:59:28.213 に答える