编辑:正如Patricia所指出的那样,我的当前方法不能得出完整的瓷砖集,因为仅被线条轻微碰触的瓷砖不会被包括在内。对于我来说,这是可以接受的,因为在我的情况下速度比准确性更重要,但仍应予以注意。
让它更清晰一些:我想要图像中的所有红色瓦片,但如果我为此获得速度,我可以跳过玫瑰色瓷砖等其他颜色的瓷砖。
你的问题基本上是在光栅图像上绘制线段。
如果你可以使用粉色瓷砖,可以使用Bresenham算法。否则,使用类似于绘制抗锯齿线条的技术:
从包含线段一端的瓷砖开始,并将其放入队列中。然后按照常规BFS算法进行,只将与线段相交的瓷砖放入队列中:
在一个迭代中,从队列的一端取出一个瓷砖,这是下一个发现的相交瓷砖。然后找到所有相邻的瓷砖,并将与线段相交的瓷砖(在这种情况下仅测试与直线的相交)放入队列的另一端。必须根据线的方向选择邻居。如果向下右移,则使用向下、向右和向下右侧的瓷砖作为邻居;如果向上移动,则仅使用上邻居,依此类推。
当到达包含线段另一端的瓷砖时结束。
测试线的梯度,与具有相同梯度符号的瓷砖对角线进行比较。如果比瓷砖对角线更陡峭,请在接下来的步骤中交换x和y坐标。
如果梯度比瓷砖对角线更浅,则该线会触及或穿过给定的瓷砖,并且该瓷砖不包含端点,至少其与瓷砖边缘的交点之一必须位于瓷砖的x边界上。
对于每个线端,请收集包含或接触端点的瓷砖。
对于两个端点x坐标之间的瓷砖边缘上的每个x坐标,请计算线的y坐标。收集接触该点的瓷砖。
我认为这可以通过最多几次除法来完成梯度检查。主要过程都是乘法、加法和比较。
根据线段的端点,您可以轻松计算出直线的方程:y = mx + b
。而且,根据线段的长度,您可以计算出参数形式:
x = x0 + ft
y = y0 + gt
给定这两个方程中的任意一个,您可以计算出该直线上任何给定 x
坐标的 y
坐标。因此...
从直线的第一个端点开始,您知道包含该点的单元格在集合中。您知道每个单元格的 x
坐标,因此您可以快速确定线段穿过单元格边界的 y
坐标。如果该 y
坐标在单元格的顶部 y
坐标之上,则线段与起始单元格上方相交。(如果线段的斜率为“向下”,则替换为“下方”)
如果您在 x
轴沿着每个单元格边界重复进行该测试,则会得到线段穿过的所有单元格的列表。