【发布时间】:2013-07-03 21:06:31
【问题描述】:
关于应用程序的一些信息;
该应用程序允许用户在 bing 地图 WPF api 上绘制和保存多边形。
我们感兴趣的代码是查找某个点是否在多边形内的天气。以下函数简单地循环遍历 bing 地图上多边形的LocationCollection,并创建一个作为多边形实例的SqlGeography object (OpenGisGeographyType.Polygon)。
然后我们将鼠标点击按经纬度转换为SqlGeography object (OpenGisGeographyType.Point),并使用SqlGeography.STIntersection 来查找我们的点是否在多边形内。
如图所示,即使该点在多边形之外,SqlGeography.STIntersection 仍然返回一个交点。 (您可以在图片中看到这一点,因为我将标签设置为“在交付区域内”或“客户我们的区域”,具体取决于 polyalSearch() 函数返回的内容。
图片中的右侧示例具有在多边形内测试位置时的预期结果。
图片中左边的例子包含了意想不到的结果——这表明一个点在一个多边形内,而它显然不是!
注意事项:
- 我使用 SqlGeography (myShape) 将形状放在地图上,所以我知道 正在使用适当的顶点构造形状。
- 我使用 SqlGeography (myPoint) 将图钉放在地图上,所以我知道
pin 正在正确的顶点进行测试。
- 这仅在大型多边形上失败
下面我给出了在内存中创建多边形以及将鼠标单击事件转换为纬度、经度的代码片段。 (我已经在 cmets 中包含了多边形顶点,这样就可以在不需要 bing api 的情况下查看它,只需用上面的 cmets 替换 for 循环)虽然,您需要引用 Microsoft.SqlServer.Types.dll 来创建 SqlGeography对象。它在 SQL Express 2008 中免费,可以在 C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies
public bool polygonSearch2(LocationCollection points, double lat, double lon)
{
SqlGeography myShape = new SqlGeography();
SqlGeographyBuilder shapeBuilder = new SqlGeographyBuilder();
// here are the verticies for the location collection if you want to hard code and try
//shapeBuilder.BeginFigure(47.4275329011347, -86.8136038458706);
//shapeBuilder.AddLine(36.5102408627967, -86.9680936860962);
//shapeBuilder.AddLine(37.4928909385966, -80.2884061860962);
//shapeBuilder.AddLine(38.7375329179818, -75.7180936860962);
//shapeBuilder.AddLine(48.0932596736361, -83.7161405610962);
//shapeBuilder.AddLine(47.4275329011347, -86.8136038458706);
//shapeBuilder.EndFigure();
//shapeBuilder.EndGeography();
// Here I just loop through my points collection backwards to create the polygon in the SqlGeography object
for (int i = points.Count - 1; i >= 0; i--)
{
if (i == 0)
{
shapeBuilder.AddLine(points[i].Latitude, points[i].Longitude);
shapeBuilder.EndFigure();
shapeBuilder.EndGeography();
continue;
}
if (i == points.Count - 1)
{
shapeBuilder.SetSrid(4326);
shapeBuilder.BeginGeography(OpenGisGeographyType.Polygon);
shapeBuilder.BeginFigure(points[i].Latitude, points[i].Longitude);
continue;
}
else
{
shapeBuilder.AddLine(points[i].Latitude, points[i].Longitude);
}
}
myShape = shapeBuilder.ConstructedGeography;
// Here I am creating a SqlGeography object as a point (user mouse click)
SqlGeography myPoint = new SqlGeography();
SqlGeographyBuilder pointBuilder = new SqlGeographyBuilder();
pointBuilder.SetSrid(4326);
pointBuilder.BeginGeography(OpenGisGeographyType.Point);
// Should pass, which it does
// Lat: lat = 43.682110574649791 , Lon: -79.79005605528323
// Should fail, but it intersects??
// Lat: 43.682108149690094 , Lon: -79.790037277494889
pointBuilder.BeginFigure(lat, lon);
pointBuilder.EndFigure();
pointBuilder.EndGeography();
myPoint = pointBuilder.ConstructedGeography;
SqlGeography result = myShape.STIntersection(myPoint);
if (result.Lat.IsNull)
return false;
else
return true;
}
非常感谢任何帮助,我开始让我的老板为这个问题发疯>.
这与 SRID 有什么关系吗?
【问题讨论】:
-
它是始终返回 true 还是仅在接近但仍处于外部时才返回?
-
@ta.speot.is 仅在关闭但仍在外面时
-
This only fails after zooming。你是说缩放地图,然后添加标记,返回错误的结果?不是说一开始在多边形内的大头针标记在图片缩放时会渲染到多边形外,对吧? -
@Tim 缩放地图后,添加标记返回不正确的结果 - 这是正确的。几乎它似乎只在缩小时才有效,因为计算不一定需要如此精确。感谢您的宝贵时间
标签: c# wpf bing-maps sqlgeography