Man*_*ini 5 c# sql-server polygon point-in-polygon
我有一个问题,希望你们能帮助我解决.
我有一个DbGeometry点(或DbGeography,我可以使用两者),我想检查它是否在DbGeometry Polygon(或者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());
}
Run Code Online (Sandbox Code Playgroud)
所以我遍历区域(我的数据库的EF实体)并检查我的这一点是否在这个边界内.
问题是它没有返回任何结果,但我知道那个点在该边界内,因为我手动创建了边界,并且该点位于该边界内.
任何人都可以告诉我,如果有其他方法可以做到这一点或其他什么,我做错了什么?
非常感谢.
曼努埃尔
我想对Nick Strupat添加评论.
你应该小心戒指方向.SQL Server使用左手方向,这意味着如果沿着多边形的周边行走,左手应位于多边形的内侧,右手应位于外侧(逆时针或逆时针).我得到了"响铃方向"错误,因为我在相反方向(顺时针或右手)绘制了多边形,这意味着SQL Server正在处理地球的整个表面,除了我的多边形作为多边形的区域.
要检查点是否在多边形中,您应该始终使用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);
}
Run Code Online (Sandbox Code Playgroud)
实际上这很容易。
bool isInside(DbGeometry polygon, double longitude, double latitude) //or DbGeography in your case
{
DbGeometry point = DbGeometry.FromText(string.Format("POINT({0} {1})",longitude, latitude), 4326);
return polygon.Contains(point);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5402 次 |
| 最近记录: |