分组地理形状

我正在使用Dundas Maps并尝试绘制世界地图,其中国家/地区被分组到特定于业务实现的区域。

我有世界上每个国家的形状数据(点和段)。 我可以通过将区域内的所有国家/地区的所有点和细分添加到新的区域形状来将国家/地区组合到一起。

foreach(var region in GetAllRegions()){ var regionShape = new Shape { Name = region.Name }; foreach(var country in GetCountriesInRegion(region.Id)){ var countryShape = GetCountryShape(country.Id); regionShape.AddSegments(countryShape.ShapeData.Points, countryShape.ShapeData.Segments); } map.Shapes.Add(regionShape); } 

问题是国家边界线仍然出现在一个区域内,我想删除它们,以便只显示区域边界。

Dundas多边形必须在同一点开始和结束。 所有国家形状都是如此。 现在我需要一个能够:

  • 确定国家边界在区域边界的交叉点,以便我可以加入区域边界段。
  • 确定哪些国家/地区边界不是区域边界,以便我可以丢弃它们。
  • 对生成的区域点进行排序,以便它们按顺序描述形状边界。

以下是我到目前为止使用地图的地方。 您可以看到仍需要删除国家/地区边界。 例如,蒙古和中国之间的边界应该被丢弃,而蒙古和俄罗斯之间的边界应该保留。

我需要保留区域边界的原因是区域颜色在传达信息方面很重要,但相邻区域可能是相同的颜色。 这些地区可以改变以包括或排除国家,这就是为什么区域塑造必须是动态的。

编辑:我现在知道我正在寻找的是一个多边形联盟。 David Lean 解释了如何使用SQL Server 2008中的空间函数来执行此操作,这可能是一个选项,但我的努力已经停止,因为生成的多边形联合非常复杂,以至于SQL将其截断为43,480个字符。 我现在正在尝试为此找到解决方法或找到在代码中进行联合的方法。

区域地图

在分组国家时,我希望没有重叠 – 您可以采用一种相当天真的算法来寻找共享顶点 – 一个简单的视图就是迭代一个多边形上的点,看看它是否在你的任何其他多边形上,并分享相同的下一个或上一个点,以查看是否匹配。 然后只需删除共享顶点即可创建联合

假设邻国共享共同的顶点和边缘(如果不是,则问题变得更加困难)。

对于每个区域,请浏览与该区域中的国家/地区对应的poylgons,并创建顶点和边的列表。 每个边都应该有指向作为其端点的两个顶点的指针,并且每个顶点应该具有指向其边缘的指针。

将顶点添加到列表时,请确保它们是唯一的顶点。 换句话说,如果要添加带坐标(x,y)的顶点,如果列表中已存在这样的顶点,则不添加新顶点。 这意味着您可能必须检查每个新顶点与列表中已有的顶点。 你可以通过将区域的边界框分解成n x n bin来加快速度,你可以在其中存储顶点。 当一个新顶点进入时,查找其bin并将其与该bin中的其他顶点进行对比。

在边缘列表中添加边时,请执行相同操作 – 如果要添加边(v0,v1),请检查是否存在现有边(v0,v1)或(v1,v0)。 除非在这种情况下,否则从列表中删除现有边,并且不添加新边。 那是因为这两个边缘相互“抵消” – 它们来自邻国。 并且不要忘记消除顶点列表中与删除边对应的边指针。

当你这样做时,你应该有一个两个国家不共享的边缘列表。 这些是形成该区域边界的边缘。 您还应该有一个顶点列表,一些指向两个边,另一些指向无边。 前顶点位于区域边界上。

现在从边列表中选取一条边,并从边列表中删除它(并从顶点作为其端点删除相应的边指针)。 转到其中一个顶点端点,它将指向另一个边缘。 通过这种方式,您将沿着区域边界从一条边走到另一条边。 在边缘列表中删除这些边时,将这些边添加到regionShape中。 最终你将回到第一个边缘的终点,你将有一个闭环。

如果edgelist中还有任何边缘,则再次启动该过程以提取另一个边界循环,并继续前进,直到所有边界循环都被提取并且edgelist为空。

我已经提到了一个优化,即将顶点空间组织到bin中,以便您可以更快地测试它们的相等性。 另一个优化是避免从列表中物理删除边缘,而只是将它们标记为“已删除”。