实体框架DbGeography未正确计算面积

本文关键字:计算 框架 DbGeography 实体 | 更新日期: 2023-09-27 18:20:24

如果我将WKT格式的多边形定义为(经度/纬度):

string wkt = "POLYGON ((15.981800258159638 45.810693408924287, 15.983624160289764 45.810783148865241, 15.983688533306122 45.809844611497965, 15.981843173503876 45.8096838246252, 15.981800258159638 45.810693408924287))"

并且我创建DbGeography对象如下:

var polygon = System.Data.Entity.Spatial.DbGeography.FromText(wkt);

Area属性的值为510065621695499.69

如果我这样使用Postgres和PostGis做同样的事情:

select ST_Area(ST_GeographyFromText(wkt))

结果是15496.7483872527,这应该是正确的值。

如果我通过反转坐标(纬度/经度)创建多边形,则DbGeographyST_Area都返回相同的值(21247.6269483712)

有人能解释一下这里发生了什么吗?

附言:多边形位于克罗地亚的萨格勒布。

实体框架DbGeography未正确计算面积

这与多边形方向有关。引用文档的话,对于这些空间数据类型,"椭球系统中多边形的内部由左侧规则定义"。请参阅(例如)这个问题,以及毫无疑问的许多其他问题,以获得进一步的阅读和解决这个问题的方法。

如果反转WKT中点的顺序,您将得到一个区域15496.7447813973(使用对应于WGS84的4326 SRID),这与其他GIS系统提供的非常接近。我想这种差异可能是由于不同的SRID,但我远非专家。

请注意,您得到的错误结果非常接近510072000 km²,即整个地球的表面积-由于DbGeography使用了它所使用的定向协议,它已经构建了您想要的多边形的外部

要添加到AakashM的答案中,如果你总是想要更小的区域,你可以这样做:

    public double GetArea(string wellKnownText)
    {
        var sqlGeo = SqlGeography.Parse(wellKnownText);
        var normalArea = sqlGeo.STArea().Value;
        var reorientedArea = sqlGeo.ReorientObject().STArea().Value;
        // just trying to not return almost the whole area of our beloved planet...
        return Math.Min(normalArea, reorientedArea);
    }