2010-04-16 25 views
10

我正在使用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); 
} 

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

登打士多边形必须在同一点开始和结束。所有国家的形状都是如此。现在我需要一个算法:

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

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

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

编辑: 我现在知道我正在寻找的是多边形的联盟。 David Lean explains how to do it使用SQL Server 2008中的空间函数可能是一种选择,但我的努力已停止,因为生成的多边形联合非常复杂,SQL将其截断为43,680个字符。我现在试图找到解决方法,或者找到一种在代码中进行联合的方法。

Regional Map

回答

5

在分组国家,我倒是希望有没有重叠的 - 你可能需要一个相当幼稚的算法,以查找共享顶点 - 一个简单的看法是通过点上的一个多边形迭代,看看它是否在你的任何其他多边形上,并共享相同的下一个或前一个点,以查看是否存在匹配。然后删除共享顶点来创建你的联盟

+0

确实。现在我只需要一个算法。 – grenade 2010-04-19 13:43:10

+0

只要阅读你的答案几次,我想我明白你在说什么。现在就放弃一下。 – grenade 2010-04-19 13:48:41

+0

我已经知道哪些顶点是共享的。只要按照正确的顺序通过将非共享顶点添加到联合多边形的算法... – grenade 2010-04-20 08:02:15

1

假设邻居国家共享共同的顶点和边缘(如果没有,问题变得更加困难)。

对于每个区域,通过与该区域中的国家对应的poylgons并创建一个顶点和边的列表。每个边都应该有指向其端点的两个顶点的指针,并且每个顶点都应该有指向其端点的边的指针。

当您将顶点添加到列表中时,请确保它们是唯一的顶点。换句话说,如果要添加坐标为(x,y)的顶点,如果列表中已经存在这样一个顶点,请不要添加新顶点。这意味着你可能必须检查列表中已有的每个新顶点。您可以通过将该区域的边界框分解为n x n可以存储顶点的区域来加快速度。当一个新的顶点进入时,查找它的箱子并且检查它与该箱子中的其他顶点。当您添加边缘到边缘列表中时,请执行同样的操作 - 如果添加边缘(v0,v1),请检查是否存在边缘(v0,v1)或(v1,v0) 。除了在这种情况下,从列表中消除现有的边缘,并且不要添加新的边缘。这是因为这两个边缘互相取消 - 他们来自邻国。不要忘记消除顶点列表中与删除的边相对应的边指针。

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

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

如果边界列表中还有任何边缘,请重新启动该过程以提取另一个边界循环,并继续前进,直到所有边界循环都已提取并且边界列表为空。

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