我正在尝试使用一种方法来确定Lat,Long坐标是否在数据库中任何存储的多边形内,并返回它所属的那些(如果有的话)列表。
我有一个lat / long:
50.120578, -103.535156
我创建了地理围栏并将其存储在数据库中,
CREATE TABLE [dbo].[GeoFences] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[GeoPoints] [sys].[geography] NULL,
CONSTRAINT [PK_dbo.GeoFences] PRIMARY KEY CLUSTERED ([Id] ASC)
);
这些是GeoPoints的值。
POLYGON ((-129.63729858398437 57.279042764977774, -92.899017333984375 56.8970039212726, -93.865814208984375 48.922499263758255, -122.86972045898437 48.806863461085172, -129.37362670898437 57.088515327886505, -129.63729858398437 57.279042764977774))
使用这种方法,我希望它能在多边形环绕点时返回该行。
public IEnumerable<GeoFence> SearchGeoPoint(DbGeography geoPoint)
{
try
{
return _geoLocationRepository.Get.Where(obj => obj.GeoPoints.Intersects(geoPoint));
}
catch (Exception)
{
return null;
}
}
但是我一直没有返回任何行。我没有得到任何例外或错误,只有0行。
答案 0 :(得分:0)
您的坐标以错误的顺序定义,因此您的多边形实际上代表地球的小&#34;小&#34;孔。
SqlGeography应该&#34; walk&#34;坐标始终保持左侧的内部区域。这意味着你的多边形中定义的任何孔都应该走在&#34;对面&#34;方式(实际上仍然保持多边形的内部区域在左边)。从本质上讲,你是在地球中定义那个洞。
简而言之,您需要反转坐标顺序以获得正确的结果(以及您要查找的结果)。如果您使用的是SQL Server 2012,请尝试ReorientObject()
方法:
DECLARE @geog GEOGRAPHY = (SELECT [GeoPoints].ReorientObject() FROM [dbo].[GeoFences] WHERE [Id] = <an id>);
SELECT @geog;
但我会建议ReorientObject()
在这种情况下真的只是一个临时修复。你需要永久地重新定位&#39;所有存储的多边形 - 如果它们是使用正确的顺序定义的。
答案 1 :(得分:0)
发现这实际上是一些问题,希望遇到此问题的人会发现这有用。
第一个问题是我在LINQ查询中一起使用.Get.Where。当我删除.Get并直接使用数据库上下文(我使用的是通用存储库)时,它返回了我预期的行。
我替换了
return _geoLocationRepository.Get.Where(obj => obj.GeoPoints.Intersects(geoPoint));
使用
using(var context as DatabaseContext())
{
var results = new List<GeoFence>();
var query = context.GeoFences.Where(obj => obj.GeoPoints.Intersects(geoPoint));
//Have to iterate through the results (Only way I've found to access the data)
foreach(var fence in query)
{
results.Add(fence);
}
return results;
}
另外需要注意的是,你需要使用Long / Lat来创建你的POINT而不是Lat / Long(如果你做Lat / Long你会得到一个例外)。