分组地理形状

时间:2010-04-16 14:46:14

标签: c# algorithm geometry geography dundas

我正在使用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 explains how to do it使用SQL Server 2008中的空间函数,这可能是一个选项,但我的努力已经停止,因为生成的多边形联合非常复杂,以至于SQL将其截断为43,480个字符。我现在正试图找到一种解决方法,或者找到一种在代码中进行联合的方法。

Regional Map

2 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:1)

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

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

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

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

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

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

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

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