DbGeography - 选择多边形

时间:2016-07-05 19:23:10

标签: sql-server entity-framework linq polygon spatial

我有一个案例,我想加载位于用户视口内的地图对象。

这是我创建用户视口矩形的方法:

DbGeography viewport_rectangle = DbGeography.FromText(string.Format("POLYGON(({0} {1}, {0} {2}, {3} {2}, {3} {1}, {0} {1}))", lon_min, lat_min, lat_max, lon_max));

然后我想选择所有对象(点,PolyLines,多边形,位于该矩形内):

var objects = db.mapobjects.Where(x => !x.LocationGeographic.Intersects(viewport_rectangle));

直到这里的一切都很好。如果PolyLine / Polygon未完全包含在视口多边形内,则会出现此问题。在这种情况下,它被忽略,我得到“没有对象”而不是对象,其中一些点/边缘在视口之外。

“相交”有什么替代方案吗?我想选择视口矩形中包含的对象,无论它们是否在内部,或者只有一小部分位于视口矩形内。

  

viewport_rectangle = {SRID = 4326; POLYGON((15.693584159016611)   46.532346466357438,15.693584159016611 46.532770863495614,15.695530101656916 46.532770863495614,15.695530101656916 46.532346466357438,15.693584159016611 46.532346466357438))}

仅部分位于viewport_rectangle内的对象,应该作为结果返回:

  

LINESTRING(15.694189164787527 46.532622094224166,15.694309193640944   46.532614944062828,15.694392677396532 46.5326121762582,15.694401059299702 46.532662919320614,15.694536175578829 46.532621632923423,15.694564338773485 46.532659690218026,15.694584455341097 46.532614944062828,15.694570373743769 46.532578039989573,15.694489236921068 46.53258611275777,15.694502312690016 46.532539290685662,15.694723930209872 46.53252614359414,15.69474438205361 46.532575041532539,15.694786962121723 46.532516225610692,15.694763492792843 46.532481858630774,15.694699790328738 46.532507922181281,15.694884862750767 46.532493852478581,15.694849658757446 46.53254505695287)

LINQ生成的查询的一部分:

  

选择           [Filter1]。[ObjectId] AS [ObjectId],           [Filter1]。[LocationGeographic] AS [LocationGeographic],           FROM(SELECT [Extent1]。[ObjectId] AS [ObjectId],[Extent1]。[LocationGeographic] AS [LocationGeographic]               FROM [dbo]。[mapobjects] AS [Extent1]           WHERE(([Filter1]。[LocationGeographic] .STIntersects(@ p__linq__0))<> cast(1   作为位))       )AS [Project1]

编辑: viewport_rectangle的正确顺序应为:

DbGeography viewport_rectangle = DbGeography.FromText(string.Format("POLYGON(({0} {1}, {2} {1}, {2} {3}, {0} {3}, {0} {1}))", lon_min, lat_min, lon_max, lat_max));

1 个答案:

答案 0 :(得分:1)

您的多边形似乎存在环形方向问题。您指定要点的顺序很重要。正如您所定义的那样,多边形是整个地球减去一个非常小的正方形(可能是您想要的视口)。我是如何确定的?

declare @line geography = geography::STGeomFromText('LINESTRING (15.694189164787527 46.532622094224166, 15.694309193640944 46.532614944062828, 15.694392677396532 46.5326121762582, 15.694401059299702 46.532662919320614, 15.694536175578829 46.532621632923423, 15.694564338773485 46.532659690218026, 15.694584455341097 46.532614944062828, 15.694570373743769 46.532578039989573, 15.694489236921068 46.53258611275777, 15.694502312690016 46.532539290685662, 15.694723930209872 46.53252614359414, 15.69474438205361 46.532575041532539, 15.694786962121723 46.532516225610692, 15.694763492792843 46.532481858630774, 15.694699790328738 46.532507922181281, 15.694884862750767 46.532493852478581, 15.694849658757446 46.53254505695287)', 4236),
    @poly geography = geography::STGeomFromText('POLYGON ((15.693584159016611 46.532346466357438, 15.693584159016611 46.532770863495614, 15.695530101656916 46.532770863495614, 15.695530101656916 46.532346466357438, 15.693584159016611 46.532346466357438))', 4236);

select @poly.EnvelopeAngle(); --returns 180
select @poly.ReorientObject().STIntersects(@line); --returns 1

最好您自己阅读EnvelopeAngle()方法。但我会说这个 - 我用它作为快速启发法来检测你在这里遇到的环定向问题。总是如果多边形有这个问题,包络角将是180(这几乎不是你想要的)。

我还在上面的代码中给出了如何修复它的妙语;在多边形上调用ReorientObject()顺时针更改为逆时针(反之亦然)。

最后,看起来你的线条完全包含在你的视口中;我用STContains()进行了测试。这解释了为什么在你认为你的视口是但是视口的所有内容之前你会变得虚假!