【问题标题】:Grouping geographical shapes对地理形状进行分组
【发布时间】:2011-02-08 21:00:49
【问题描述】:

我正在使用 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,680 个字符。我现在正在尝试找到解决方法或找到一种在代码中进行联合的方法。

【问题讨论】:

    标签: c# algorithm geometry geography dundas


    【解决方案1】:

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

    【讨论】:

    • 确实如此。现在我只需要一个算法。
    • 只需阅读您的答案几次,我想我明白您在说什么。现在就试一试吧。
    • 我已经了解了哪些顶点是共享的。只需完成以正确顺序将未共享顶点添加到联合多边形的算法...
    • 我会通过迭代点来做到这一点,如果您可以保证点始终按顺时针顺序排列(例如),这将特别有用,因为您可以随时构建多边形- 从多边形“a”开始,检查共享顶点,如果找到,沿相反方向沿该周边继续,直到到达另一个具有原始形状的共享顶点(最坏的情况是它会是你离开的那个)
    • 您要删除共享线段,而不是共享顶点。您只想在共享该顶点的两个线段都从多边形中删除后删除该顶点。否则,您将删除连接两个生成的半多边形的顶点。
    【解决方案2】:

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

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

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

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

    完成后,您应该有一个不被两个国家共享的边列表。这些是形成区域边界的边缘。您还应该有一个顶点列表,一些指向两条边,而另一些则指向无边。前面的顶点在区域边界上。

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      相关资源
      最近更新 更多