将矢量轮廓区域(边界)转换为栅格地图(像素网格)

发布于 2024-08-09 18:20:09 字数 875 浏览 12 评论 0原文

我有一张地图,它被边界(轮廓)分成多个区域,就像世界地图上的国家一样。每个区域都有特定的表面覆盖类别S(例如,水为0,草为0.03...)。边框由以下内容定义:

  • 其两侧的 S 值(一侧为 0.03,另一侧为 0.0,在下面的示例中)
  • 边框由多少个点组成(n=7(在下面的示例中),以及
  • n 个坐标对(xy)。

这是一个例子。

0.0300      0.0000           7
2660607.5   6332685.5   2660565.0   6332690.5   2660541.5   6332794.5 
2660621.7   6332860.5   2660673.8   6332770.5   2660669.0   6332709.5 
2660607.5   6332685.5

我想制作一个栅格地图,其中每个像素的值 S 对应于像素中心所在的区域。

请注意,边框代表 S 中的步骤变化。 S 的各种值代表离散类别(例如草或水),并且不是可以平均的值(即没有湿草!)。

另请注意,并非所有边框都是像上面的示例那样的闭环。这有点像国家边界:例如,美国-加拿大边界不是一个闭环,而是一条在两端与其他两个边界相连的线:加拿大-海洋和美国-海洋“边界”。 (尽管如此,闭环边界确实存在!)

任何人都可以向我指出一种可以做到这一点的算法吗?这?我不想重新发明轮子!

I have a map that is cut up into a number of regions by borders (contours) like countries on a world map. Each region has a certain surface-cover class S (e.g. 0 for water, 0.03 for grass...). The borders are defined by:

  • what value of S is on either side of it (0.03 on one side, 0.0 on the other, in the example below)
  • how many points the border is made of (n=7 in example below), and
  • n coordinate pairs (x, y).

This is one example.

0.0300      0.0000           7
2660607.5   6332685.5   2660565.0   6332690.5   2660541.5   6332794.5 
2660621.7   6332860.5   2660673.8   6332770.5   2660669.0   6332709.5 
2660607.5   6332685.5

I want to make a raster map in which each pixel has the value of S corresponding to the region in which the center of the pixel falls.

Note that the borders represent step changes in S. The various values of S represent discrete classes (e.g. grass or water), and are not values that can be averaged (i.e. no wet grass!).

Also note that not all borders are closed loops like the example above. This is a bit like country borders: e.g. the US-Canada border isn't a closed loop, but rather a line joining up at each end with two other borders: the Canada-ocean and the US-ocean "borders". (Closed-loop borders do exist nevertheless!)

Can anyone point me to an algorithm that can do this? I don't want to reinvent the wheel!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

神爱温柔 2024-08-16 18:20:09

以矢量形式处理此类几何图形的一般情况可能非常困难,特别是因为您描述的结构不需要几何图形保持一致。但是,由于您只想对其进行栅格化,因此将问题视为线段的 Voronoi 图可能会更加稳健。

通过将每条线段绘制为一对形成帐篷形状的四边形,可以在 OpenGL 中以图形方式完成 Voronoi 图的近似。 z 缓冲区用于使最接近的四边形优先,从而根据最接近的线对像素进行着色。这里的区别在于,您需要根据多边形所在线的哪一侧而不是它们代表的线来为多边形着色。讨论类似算法的一篇好论文是 Hoff 等人的 快速计算使用图形硬件的广义 Voronoi 图

3D 几何图形将类似于此草图,具有 3 个红色/黄色部分和 1 个蓝色/绿色部分:

3d 几何草图

此过程不需要您将任何内容转换为闭环,也不需要任何花哨的几何库。一切都由 z 缓冲区处理,并且应该足够快,可以在任何现代显卡上实时运行。一种改进是使用齐次坐标使基底投影到无穷大。

我在Python脚本中实现了这个算法 http://www.pasteall.org/9062/python。一个有趣的警告是,使用圆锥体来覆盖线的末端不会在不扭曲圆锥体形状的情况下起作用,因为代表线段端点的圆锥体是 Z 轴冲突的。对于您提供的示例几何体,输出如下所示:

The general case for processing this sort of geometry in vector form can be quite difficult, especially since nothing about the structure you describe requires the geometry to be consistent. However, since you just want to rasterize it, then treating the problem as a Voronoi diagram of line segments can be more robust.

Approximating the Voronoi diagram can be done graphically in OpenGL by drawing each line segment as a pair of quads making a tent shape. The z-buffer is used to make the closest quad take precedence, and thus color the pixel based on whichever line is closest. The difference here is that you will want to color the polygons based on which side of the line they are on, instead of which line they represent. A good paper discussing a similar algorithm is Hoff et al's Fast Computation of Generalized Voronoi Diagrams Using Graphics Hardware

The 3d geometry will look something like this sketch with 3 red/yellow segments and 1 blue/green segment:

sketch of 3d geometry

This procedure doesn't require you to convert anything into a closed loop, and doesn't require any fancy geometry libraries. Everything is handled by the z-buffer, and should be fast enough to run in real time on any modern graphics card. A refinement would be to use homogeneous coordinates to make the bases project to infinity.

I implemented this algorithm in a Python script at http://www.pasteall.org/9062/python. One interesting caveat is that using cones to cap the ends of the lines didn't work without distorting the shape of the cone, because the cones representing the end points of the segments were z-fighting. For the sample geometry you provided, the output looks like this:

voronoi rendering output

感受沵的脚步 2024-08-16 18:20:09

我建议您使用几何算法库,例如 CGAL。特别是“二维多边形”中的第二个示例参考手册的页面应该可以提供您所需要的内容。您可以将每个“边界”定义为多边形,并检查某些点是否在多边形内部。所以基本上这就像

for every y in raster grid
  for every x in raster grid
    for each defined polygon p
      if point(x,y) is inside polygon p
        pixel[X][Y] = inside_color[p]

我不太确定如何处理 Outside_color 因为外部区域会重叠,不是吗?无论如何,看看你的例子,每个外部区域都可能是水,所以你可以做一个最终的

    if pixel[X][Y] still undefined then pixel[X][Y] = water_value

(或者作为替代方案,在迭代多边形列表之前将像素[X][Y]设置为water_value)

I'd recommend you to use a geometry algorithm library like CGAL. Especially the second example in the "2D Polygons" page of the reference manual should provide you what you need. You can define each "border" as a polygon and check if certain points are inside the polygons. So basically it would be something like

for every y in raster grid
  for every x in raster grid
    for each defined polygon p
      if point(x,y) is inside polygon p
        pixel[X][Y] = inside_color[p]

I'm not so sure about what to do with the outside_color because the outside regions will overlap, won't they? Anyway, looking at your example, every outside region could be water, so you just could do a final

    if pixel[X][Y] still undefined then pixel[X][Y] = water_value

(or as an alternative, set pixel[X][Y] to water_value before iterating through the polygon list)

断念 2024-08-16 18:20:09
  • 首先,将所有边界转换为闭环(可能包括地图的边缘),并识别内部颜色。这必须是可能的,否则数据会不一致
  • 使用布雷森汉姆算法以单一未使用的颜色绘制地图上的所有边界线
    • 执行此操作时存储所有“边框像素”的列表
  • 为每个边框 执行此操作
    • 对其进行三角测量(delaunay)
    • 迭代三角形,直到找到一个其中心位于边界内的三角形(多边形内的点测试)
    • 用边界的内部颜色填充地图上的该点
  • 一旦填充了所有内部,就用 区域,迭代边界像素列表,查看每个像素应该是什么颜色
  • first, convert all your borders into closed loops (possibly including the edges of your map), and indentify the inside colour. this has to be possible, otherwise you have an inconsistency in your data
  • use bresenham's algorithm to draw all the border lines on your map, in a single unused colour
    • store a list of all the "border pixels" as you do this
  • then for each border
    • triangulate it (delaunay)
    • iterate through the triangles till you find one whose centre is inside your border (point-in-polygon test)
    • floodfill your map at that point in the border's interior colour
  • once you have filled in all the interior regions, iterate through the list of border pixels, seeing which colour each one should be
你是我的挚爱i 2024-08-16 18:20:09
  • 选择两种未使用的颜色作为标记“空”和“边框”
  • 用“空”颜色填充所有区域
  • 按“边框”颜色绘制所有区域边框
  • 迭代点以找到第一个具有“空”颜色的区域
  • 确定它属于哪个区域(谷歌) “多边形内的点”,可能您需要按照 Martin DeMello 的建议关闭边界)
  • 从该点执行洪水填充算法,并使用该区域的颜色
  • 转到下一个“空”点(无需重新启动搜索 - 只需继续)
  • 依此类推,直到没有“空”点为止
  • choose two unused colors as markers "empty" and "border"
  • fill all area with "empty" color
  • draw all region borders by "border" color
  • iterate through points to find first one with "empty" color
  • determine which region it belongs to (google "point inside polygon", probably you will need to make your borders closed as Martin DeMello suggested)
  • perform flood-fill algorithm from this point with color of the region
  • go to next "empty" point (no need to restart search - just continue)
  • and so on till no "empty" points will remain
荭秂 2024-08-16 18:20:09

我解决这个问题的方法如下:

  1. 沿着每个路段前进;定期停止L
  2. 在每个停靠点,将一个跟踪点直接放置在路段的左侧和右侧(距路段一定的小距离 d 处)。示踪点分别归属于左侧和右侧的 S 值。
  3. 进行最近邻插值。栅格网格上的每个点都归属于最近的追踪点的 S。

即使存在非闭合线(例如在地图边缘),此功能也有效。

这不是一个“完美”的分析算法。有两个参数:Ld。只要 d << ,该算法就可以完美地工作。 L。否则,您可能会在段连接处(尤其是那些具有锐角的连接处)附近出现不准确的情况(通常为单像素)。

The way I've solved this is as follows:

  1. March along each segment; stop at regular intervals L.
  2. At each stop, place a tracer point immediately to the left and to the right of the segment (at a certain small distance d from the segment). The tracer points are attributed the left and right S-value, respectively.
  3. Do a nearest-neighbour interpolation. Each point on the raster grid is attributed the S of the nearest tracer point.

This works even when there are non-closed lines, e.g. at the edge of the map.

This is not a "perfect" analytical algorithm. There are two parameters: L and d. The algorithm works beautifully as long as d << L. Otherwise you can get inaccuracies (usually single-pixel) near segment junctions, especially those with acute angles.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文