检查dbgeometry dbgeometry/dbgeography点是否在多边形内 [英] Check if dbgeometry dbgeometry/dbgeography point is within a polygon

查看:124
本文介绍了检查dbgeometry dbgeometry/dbgeography点是否在多边形内的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题,希望你们能帮助我解决.

我有一个DbGeometry点(或DbGeography,我可以同时使用),我想检查一下它是否在DbGeometry多边形(或者DbGeography)内.

我目前正在这样做:

var dbZones = new List<WasteManager.Database.Zone>();
foreach(var zone in zones)
        {
            var res = from z in DatabaseContext.Zones
                   let boundary =
                       !z.BoundaryGeometry.IsValid
                           ? SqlSpatialFunctions.MakeValid(z.BoundaryGeometry)
                           : z.BoundaryGeometry
                      where z.ID == zone.ID && point.Within(boundary)
                      select z;

            if(res.FirstOrDefault() != null) dbZones.Add(res.FirstOrDefault());

        }

所以我遍历区域(数据库的EF实体),并检查我所拥有的这一点是否在此边界之内.

问题在于它不会返回任何结果,但是我知道该点在该边界之内,因为我手动创建了该边界,并且该点位于该边界之内.

有人可以告诉我我在做什么是错误的,是否有另一种方式可以做到这一点?

非常感谢.

Manuel

解决方案

我想对Nick Strupat添加评论.

您应谨慎对待戒指方向. SQL Server使用左手方向,这意味着如果您沿着多边形的边界行走,则您的左手应在多边形的内部,而您的右手应在多边形的外部(逆时针或逆时针).我遇到环向"错误,因为我沿相反的方向(顺时针或右手)绘制了多边形,这意味着SQL Server将地球的整个表面(多边形除外)视为多边形的区域. /p>

要检查点是否在多边形中,应始终使用point.Intersects(polygon)而不是!point.Intersects(polygon).

有一种解决方案,可以通过检查区域"的大小来检查多边形是否正常, 有关更多信息,请访问:

https://blog.falafel.com/ring-orientation-sql-spatial /

这是基于博客说明的代码:

    private bool isInside(DbGeography polygon, double longitude, double latitude)
    {
        DbGeography point = DbGeography.FromText(string.Format("POINT({1} {0})", latitude.ToString().Replace(',', '.'), longitude.ToString().Replace(',','.')), DbGeography.DefaultCoordinateSystemId);

        // If the polygon area is larger than an earth hemisphere (510 Trillion m2 / 2), we know it needs to be fixed
        if (polygon.Area.HasValue && polygon.Area.Value > 255000000000000L)
        {
            // Convert our DbGeography polygon into a SqlGeography object for the ReorientObject() call
            SqlGeography sqlPolygon = SqlGeography.STGeomFromWKB(new System.Data.SqlTypes.SqlBytes(polygon.AsBinary()), DbGeography.DefaultCoordinateSystemId);

            // ReorientObject will flip the polygon so the outside becomes the inside
            sqlPolygon = sqlPolygon.ReorientObject();

            // Convert the SqlGeography object back into DbGeography
            polygon = DbGeography.FromBinary(sqlPolygon.STAsBinary().Value);

        }
        return point.Intersects(polygon);
    }

I have a problem I hope you guys can help me solve.

I have got a DbGeometry point (or DbGeography, I can use both) and I would like to check if this is within a DbGeometry Polygon (alternatively a DbGeography).

I am doing this at the moment:

var dbZones = new List<WasteManager.Database.Zone>();
foreach(var zone in zones)
        {
            var res = from z in DatabaseContext.Zones
                   let boundary =
                       !z.BoundaryGeometry.IsValid
                           ? SqlSpatialFunctions.MakeValid(z.BoundaryGeometry)
                           : z.BoundaryGeometry
                      where z.ID == zone.ID && point.Within(boundary)
                      select z;

            if(res.FirstOrDefault() != null) dbZones.Add(res.FirstOrDefault());

        }

So I iterate through zones (EF entity of my db) and check if this point I have is within this boundary.

Problem is that it does not return any result, but I know that that point is within that boundary because I created manually the boundary and the point to be inside that boundary.

Can anyone tell me if what I am doing is wrong, if there is another way to do this or whatever else?

Much appreciate.

Manuel

解决方案

I would like to add a comment to Nick Strupat.

You should be carefull with ring orientation. SQL Server uses left-handed orientation, which means that if you are walking along the perimeter of a polygon, your left hand should be on the inside of the polygon and your right hand on the outside (counter-clockwise or anti-clockwise). I got the "ring orientation" error because I drew my polygon in the opposite direction (clockwise, or right-handed) which meant that SQL Server was treating the whole surface of the earth EXCEPT FOR my polygon as the area of the polygon.

To check if a point is in the polygon you should always use point.Intersects(polygon) and not !point.Intersects(polygon).

There is a solution to check if your polygon is ok or not by checking the size of the Area, For more information go to :

https://blog.falafel.com/ring-orientation-sql-spatial/

Here is my code based on the blog explanation :

    private bool isInside(DbGeography polygon, double longitude, double latitude)
    {
        DbGeography point = DbGeography.FromText(string.Format("POINT({1} {0})", latitude.ToString().Replace(',', '.'), longitude.ToString().Replace(',','.')), DbGeography.DefaultCoordinateSystemId);

        // If the polygon area is larger than an earth hemisphere (510 Trillion m2 / 2), we know it needs to be fixed
        if (polygon.Area.HasValue && polygon.Area.Value > 255000000000000L)
        {
            // Convert our DbGeography polygon into a SqlGeography object for the ReorientObject() call
            SqlGeography sqlPolygon = SqlGeography.STGeomFromWKB(new System.Data.SqlTypes.SqlBytes(polygon.AsBinary()), DbGeography.DefaultCoordinateSystemId);

            // ReorientObject will flip the polygon so the outside becomes the inside
            sqlPolygon = sqlPolygon.ReorientObject();

            // Convert the SqlGeography object back into DbGeography
            polygon = DbGeography.FromBinary(sqlPolygon.STAsBinary().Value);

        }
        return point.Intersects(polygon);
    }

这篇关于检查dbgeometry dbgeometry/dbgeography点是否在多边形内的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆