在矩形上镶嵌六边形
Tessellating hexagons over a rectangle
我有一个无限的六边形网格,由立方 (x y z) 坐标系定义,如下所示:
我还有一个 视口 -- 一个矩形 canvas 我将在其中绘制六边形。
我的问题是这样的。因为六边形网格在所有方向上都是无限的,所以我不可能一次画出所有的六边形。因此,我需要绘制视口中的所有六边形,并且只绘制这些六边形。
这张图片总结了我想做的事情:
在此图像中,purple-colored 个六边形是我要渲染的,而 white-colored 个六边形是我不想渲染的。黑色矩形是 hte 视口——所有与它相交的六边形都将被绘制。 我如何找到要渲染的六边形(即它们的 xyz 坐标)?
一些其他信息:
- 我有一个函数可以调用一个六边形图块,并在给定立方 xyz 坐标的情况下以视口中的位置 (x,y) 为中心绘制它。因此,我只需要绘制每个矩形的 xyz 坐标,我就可以绘制它们。这可能会简化问题。
我有公式可以将立方六边形坐标转换为 x/y 坐标,然后再转换回来。鉴于上图,r/g/b 是上图的立方坐标轴,x 和 y 是笛卡尔坐标,s 是六边形边的长度...
y = 3/2 * s * b
b = 2/3 * y / s
x = sqrt(3) * s * ( b/2 + r)
x = - sqrt(3) * s * ( b/2 + g )
r = (sqrt(3)/3 * x - y/3 ) / s
g = -(sqrt(3)/3 * x + y/3 ) / s
r + b + g = 0
设X0、Y0为左上角坐标,RectWidth为矩形宽度,HexWidth = s * Sqrt(3/2)为六边形宽度。
找到最近的六边形r0、g0、b0、HX0、HY0的中心。 (直角在这个六边形内,因为六边形是Voronoy图的单元格)。记住水平和垂直移位DX = X0 - HX0, DY = Y0 - HY0
绘制横排Ceil(RectWidth/HexWidth)个六边形,r坐标递增,f递减,b保持不变,ROWINC=(1,-1,0)
。
注意如果DY > HexWidth/2
,您需要额外的顶行并将初始坐标向上移动(r0, g0-1, b0+1)
如果 DX < 0
,则将起点移动 L=(0, 1, -1)
,否则移动 R=(1, 0, -1)
。使用相同的 ROWINC
绘制另一个水平行
以替代方式移动行起点(L在R之后,R在L之后)。绘制水平行直到到达底部边缘。
检查底部是否需要额外的行。
你可以把矩形框想象成轴上的约束。
在图表中,水平线对应于 b
,您的约束将采用 somenumber ≤ b 和 b ≤ somenumber 的形式。例如,矩形可能在 3 ≤ b ≤ 7 范围内。
垂直线有点棘手,但它们是对应于 r-g
的“对角线”。您的约束将采用 somenumber ≤ r-g 和 r-g ≤ somenumber 的形式。例如,它的范围可能是 -4 ≤ r-g ≤ 5。
现在你有两个带约束的轴,你可以形成一个循环。最简单的方法是让外循环使用 b
:
for (b = 3; b ≤ 7; b++) {
…
}
内部循环有点棘手,因为那是对角线约束。由于我们知道 r+g+b=0,并且我们从外循环中知道 b 的值,我们可以重写对 r-g 的双变量约束。将 r+g+b=0 表示为 g=0-r-b。现在代入 r-g 得到 r-(0-r-b)。将 r-(0-r-b) 简化为 2*r-b。我们可以说 -4 ≤ r-g 或 -4 ≤ 2*r-b 或 -4+b ≤ 2*r 或 (-4+b)/2 ≤ r 而不是 -4 ≤ r-g。同样,我们可以将 r-g ≤ 5 重新排列为 2*r-b ≤ 5 到 r ≤ (5+b)/2。这给了我们我们的内部循环:
for (b = 3; b ≤ 7; b++) {
for (r = (-4+b)/2; r ≤ (5+b)/2; r++) {
g = 0-b-r;
…
}
}
最后一点是概括,将常量 3,7,-4,5 替换为矩形的实际边界。
我有一个无限的六边形网格,由立方 (x y z) 坐标系定义,如下所示:
我还有一个 视口 -- 一个矩形 canvas 我将在其中绘制六边形。
我的问题是这样的。因为六边形网格在所有方向上都是无限的,所以我不可能一次画出所有的六边形。因此,我需要绘制视口中的所有六边形,并且只绘制这些六边形。
这张图片总结了我想做的事情:
在此图像中,purple-colored 个六边形是我要渲染的,而 white-colored 个六边形是我不想渲染的。黑色矩形是 hte 视口——所有与它相交的六边形都将被绘制。 我如何找到要渲染的六边形(即它们的 xyz 坐标)?
一些其他信息:
- 我有一个函数可以调用一个六边形图块,并在给定立方 xyz 坐标的情况下以视口中的位置 (x,y) 为中心绘制它。因此,我只需要绘制每个矩形的 xyz 坐标,我就可以绘制它们。这可能会简化问题。
我有公式可以将立方六边形坐标转换为 x/y 坐标,然后再转换回来。鉴于上图,r/g/b 是上图的立方坐标轴,x 和 y 是笛卡尔坐标,s 是六边形边的长度...
y = 3/2 * s * b b = 2/3 * y / s x = sqrt(3) * s * ( b/2 + r) x = - sqrt(3) * s * ( b/2 + g ) r = (sqrt(3)/3 * x - y/3 ) / s g = -(sqrt(3)/3 * x + y/3 ) / s r + b + g = 0
设X0、Y0为左上角坐标,RectWidth为矩形宽度,HexWidth = s * Sqrt(3/2)为六边形宽度。
找到最近的六边形r0、g0、b0、HX0、HY0的中心。 (直角在这个六边形内,因为六边形是Voronoy图的单元格)。记住水平和垂直移位DX = X0 - HX0, DY = Y0 - HY0
绘制横排Ceil(RectWidth/HexWidth)个六边形,r坐标递增,f递减,b保持不变,ROWINC=(1,-1,0)
。
注意如果DY > HexWidth/2
,您需要额外的顶行并将初始坐标向上移动(r0, g0-1, b0+1)
如果 DX < 0
,则将起点移动 L=(0, 1, -1)
,否则移动 R=(1, 0, -1)
。使用相同的 ROWINC
以替代方式移动行起点(L在R之后,R在L之后)。绘制水平行直到到达底部边缘。
检查底部是否需要额外的行。
你可以把矩形框想象成轴上的约束。
在图表中,水平线对应于 b
,您的约束将采用 somenumber ≤ b 和 b ≤ somenumber 的形式。例如,矩形可能在 3 ≤ b ≤ 7 范围内。
垂直线有点棘手,但它们是对应于 r-g
的“对角线”。您的约束将采用 somenumber ≤ r-g 和 r-g ≤ somenumber 的形式。例如,它的范围可能是 -4 ≤ r-g ≤ 5。
现在你有两个带约束的轴,你可以形成一个循环。最简单的方法是让外循环使用 b
:
for (b = 3; b ≤ 7; b++) {
…
}
内部循环有点棘手,因为那是对角线约束。由于我们知道 r+g+b=0,并且我们从外循环中知道 b 的值,我们可以重写对 r-g 的双变量约束。将 r+g+b=0 表示为 g=0-r-b。现在代入 r-g 得到 r-(0-r-b)。将 r-(0-r-b) 简化为 2*r-b。我们可以说 -4 ≤ r-g 或 -4 ≤ 2*r-b 或 -4+b ≤ 2*r 或 (-4+b)/2 ≤ r 而不是 -4 ≤ r-g。同样,我们可以将 r-g ≤ 5 重新排列为 2*r-b ≤ 5 到 r ≤ (5+b)/2。这给了我们我们的内部循环:
for (b = 3; b ≤ 7; b++) {
for (r = (-4+b)/2; r ≤ (5+b)/2; r++) {
g = 0-b-r;
…
}
}
最后一点是概括,将常量 3,7,-4,5 替换为矩形的实际边界。