如何将像素坐标转换为等轴测网格坐标

How do I convert pixel coordinates to isometric grid coordinates?

本文关键字:坐标 网格 转换 像素      更新时间:2023-09-26

我在弄清楚在哪里放置我的瓷砖或找到瓷砖角落时并没有太多麻烦,但我无法弄清楚用于确定我悬停的像素属于哪个网格单位的数学/公式。我的网格是这样运行的:

        y0,x0|y0,x1|y0,x2
     y1,x0|y1,x1|y1,x2
  y2,x0|y2,x1|y2,x2

y0,x0 是顶部/背面,并以画布的顶部边缘为中心。瓷砖的宽度是平时的两倍。我已经让偏移代码工作,因此我的鼠标像素坐标偏移量与我的磁贴相同,但我被难住了。

编辑:很抱歉这个令人困惑的问题。通宵代码会话疲劳。

我有这个功能(在这里简化):

getTilePixelCoord(x,y)
{
    p.x = S-yH+xH;
    p.y = yM+xM;
    return p;
}

我用来放置我的瓷砖。S 是原点,其中始终放置 0y,0x,H 是平铺像素高度,M 是 H/2。我需要的是与此相反的,一个getPixelTileCoord(pixelx,pixely);用于获取我悬停在哪个磁贴上。

初始观察

等距切片网格只是一个常规矩形网格,x 坐标会移动,具体取决于行数。

Rectangular Grid (y,x)
             v length (L)
          +_____+xxxxx+xxxxx+
          x     x     x     x
No offset>+xxxxx+xxxxx+xxxxx+
          x     x     x     x
          +xx|xx+xxxxx+xxxxx+
          x  |  x     x     x
          +xx|xx+xxxxx+xxxxx+
             ^ height (H)
+: corners

每个图块的长度边缘为 L px,垂直于该边缘的高度为 H px。每行的等轴测像素偏移量将为 O 像素。

Isometric Grid (y,x)
                  V length (L) is the same as above
height     ......+_____+xxxxx+xxxxx+
dependent >_____x 0,0 x     x     x
offset     ....+xxxxx+xxxxx+xxxxx+
(O)        ...x     x     x 1,2 x
           ..+x|xxx+xxxxx+xxxxx+
           .x  |  x     x     x
           +xxx|x+xxxxx+xxxxx+
               ^ height (H) is the same as above
+: corners

表示法

  • t(ty,tx)是指垂直位于ty处和水平位于tx
  • p(i,j)是指像素位置(以像素为单位)
  • MAX_Y是指磁贴行数

(所有位置始终以垂直组件优先列出。

例子

例 1

如果计数,您会注意到t(0,0)的角位于以下像素位置:

  • p(0, 3O) : 左上角
  • p(H, 2O) : 左下角
  • p(0, 3O+L) : 右上角
  • p(H, 2O+L) : 右下角

这四个点中的每一个也是其他瓷砖的角。

例 2

我们可以t(1,2)视为另一个例子。它们的角位于以下像素位置:

  • p(H, 2O+2L) : 左上角
  • p(2H, O+2L) : 左下角
  • p(H, 2O+3L) : 右上角
  • p(2H, O+3L) : 右下角

一般案例

对于tx的单位增加(从t(ty,tx)t(ty,tx+1)),角的水平像素位置变化L px

对于ty的每个单位增加(从 t(ty,tx)t(ty+1,tx)),角的水平像素位置变化-O px,角的垂直像素位置变化H px

概括地说,平铺t(ty,tx)的角(其中行数Y_MAX ,因此对于我们的示例,Y_MAX = 3 )位于以下像素位置:

p(    ty*H,   (Y_MAX-ty)*O +     tx*L) - top left
p((ty+1)*H, (Y_MAX-ty-1)*O +     tx*L) - bottom left
p(    ty*H,   (Y_MAX-ty)*O + (tx+1)*L) - top right
p((ty+1)*H, (Y_MAX-ty-1)*O + (tx+1)*L) - bottom right

您可以插入上面的示例以显示这些是正确的位置。

像素到磁贴

垂直位置

对于瓷砖t(ty,tx)p(i,j)ty*H <= i < (ty+1)*H

ty*H <= i   < (ty+1)*H
ty   <= i/H < ty+1
ty = floor(i/H)

因此,ty = floor(i/H).

水平位置

水平位置

稍微复杂一些,因为偏移以及水平位置取决于像素的垂直位置。我们可以看到偏移量从顶部的 O*Y_MAX px 开始,并在底部线性减小到 0 px。

在磁贴t(ty,tx)和像素p(i,j)的顶部,(Y_MAX-ty)*O + tx*L <= j < (Y_MAX-ty)*O + (tx+1)*L

在磁贴t(ty,tx)和像素p(i,j)的底部,(Y_MAX-ty-1)*O + tx*L <= j < (Y_MAX-ty-1)*O + (tx+1)*L

两者之间的差异是线性的,总计O px .

要找出我们在瓷砖上,我们可以使用 frac(i/H)i/H的小数部分。例如,在 p(80,0) ,如果每个图块都有一个高度H=30,我们将相对于图块的顶部frac(80/30) = 20 px;换句话说,三分之二的路程。我们从上面看到tyfloor(i/H)实际上是i/H的整数部分。因此,ty+frac(i/H) = i/H.

<小时 />

因此,对于切片t(ty,tx)和像素p(i,j)(Y_MAX-i/H)*O + tx*L < j < (Y_MAX-i/H)*O + (tx+1)*L

(Y_MAX-i/H)*O + tx*L <= j                     < (Y_MAX-i/H)*O + (tx+1)*L
tx*L                 <= j-((Y_MAX-i/H)*O)     < (tx+1)*L
tx                   <= (j-((Y_MAX-i/H)*O))/L < tx+1
tx = floor((j-((Y_MAX-i/H)*O))/L)

因此,tx = floor((j-((Y_MAX-i/H)*O))/L).

溶液

对于任何点p(i,j),磁贴t(ty,tx)都在t(floor(i/H),floor((j-((Y_MAX-i/H)*O))/L))

您的具体情况

就您的目的而言,L = 2HO = H可能是参数;采用上述解决方案并替换OL会将结果减少到一个依赖项H