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);
}

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

Dundas 多边形必须在同一点开始和结束。这是所有国家形状的情况。现在我需要一个算法,它可以:

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

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

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

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

区域地图

4

2 回答 2

5

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

于 2010-04-19T13:40:48.547 回答
1

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

对于每个区域,遍历与该区域中的国家对应的多边形,并创建一个顶点和边列表。每条边都应该有指向作为其端点的两个顶点的指针,并且每个顶点应该有指向作为端点的边的指针。

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

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

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

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

如果边缘列表中剩余任何边缘,则重新开始该过程以提取另一个边界循环,并继续进行直到所有边界循环都被提取并且边缘列表为空。

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

于 2010-04-23T20:00:45.157 回答