将SVG矩阵转换为旋转角度。

我正在从一个带有矩阵的 SVG 文件中读取矩形的位置和旋转,格式如下:

<rect transform="matrix(1.02414 -0.133308 0.122628 0.942091 190.767 780.999)" width="122" height="20"/>

现在我正在尝试将这些值解析到 Lua 中,以便像这样绘制和使用 Corona 和物理效果,但它们部分为假,而且在我当前的猜测方法中也经常为 NAN。我需要做什么才能将上述矩阵转换为合适的 Lua 度数旋转?

我到目前为止拥有以下代码(值数组是 SVG 的矩阵值的顺序)。谢谢!

local x = values[5]; local y = values[6]
local rotation = math.acos(values[1])
if values[2] < 0 then rotation = -rotation end
rotation = math.floor( math.deg(rotation) )
rotation = rotation % 360

app.spritesHandler:createBar( math.floor(x), math.floor(y), rotation )

enter image description here

点赞
用户36537
用户36537

首先,我认为你需要从0到5进行索引,而不是从1到6。

根据 the spec,旋转矩阵是:

a  c  e
b  d  f
0  0  1

其中a-f是矩阵列表中的6个数字。

我们还发现,绕着 cx,cy 进行的 rotate(angle,cx,cy) 等同于:

  1. 平移(cx,cy)
  2. 旋转(angle)
  3. 平移(-cx,-cy)

这将是:

|1 0 cx|  |cos(t) -sin(t) 0|  |1 0 -cx|
|0 1 cy|  |sin(t)  cos(t) 0|  |0 1 -cy|
|0 0 1 |  |  0       0    1|  |0 0  1 |

  |cos(t)   -sin(t)  cx|  |1 0 -cx|
= |sin(t)    cos(t)  cy|  |0 1 -cy|
  |   0        0      1|  |0 0  1 |

  |cos(t)   -sin(t)  (-cx cos(t) + cy sin(t) + cx) |
= |sin(t)    cos(t)  (-cx sin(t) - cy cos(t) + cy) |
  |  0         0              1                    |

因此,这表明角度信息完全独立于系数a、b、c和d中。如果应用的唯一事物是这个矩阵,那么a和d应该匹配,而b和c应该只是相反的符号。

然而,看看你的数字列表,它们不是,所以我想知道是否还应用了其他的变换?正如评论者所指出的,数字是大于1的,因此不是角度上的简单三角函数操作的结果。

一个可能性是还进行了缩放。那个矩阵是:

| sx 0  0|
|  0 sy 0|
|  0  0 1|

因此,如果先应用缩放,然后进行旋转,我们将得到:

| sx 0  0| |cos(t)   -sin(t)  (-cx cos(t) + cy sin(t) + cx) |
|  0 sy 0| |sin(t)    cos(t)  (-cx sin(t) - cy cos(t) + cy) |
|  0  0 1| |  0         0              1                    |

  |sx cos(t)   -sx sin(t)   sx (-cx cos(t) + cy sin(t) + cx) |
= |sy sin(t)    sy cos(t)   sy (-cx sin(t) - cy cos(t) + cy) |
  |  0               0                  1                    |

从那个矩阵中:

a/c = sx cos(t) / (-sx sin(t))
    = - cos(t) / sin(t)
    = 1/tan(t)
tan(t) = c/a

tan(t) = 0.122628/1.02414
       = 0.119738
    t  = 6.82794 degrees.

从图像来看,我认为这看起来差不多。

所以,既然我们知道了t,我们可以计算出sx和sy:

a = sx cos(t)
sx = a/cos(t) = 1.0315

和sy:

d = sy cos(t)
sy = d/cos(t) = 0.94882

获取cxcy以查找旋转中心只是将已经获得的值带入上面的e和f方程进行进一步的替换。

2013-03-21 12:01:38
用户1847592
用户1847592

似乎是组合了旋转和拉伸,因为v[4]/v[1] == -v[3]/v[2]

因此,可以按照以下方式计算旋转:

local str = '<rect transform="matrix(1.02414 -0.133308 0.122628 0.942091 190.767 780.999)" width="122" height="20"/>'
local v = {}
str:match'matrix(%b())':gsub('[%d.-]+', function(d) v[#v+1] = tonumber(d) end)
local x, y = unpack(v, 5)
local rotation = math.floor(math.deg(math.atan2(v[3], v[4]))) % 360
2013-03-21 12:33:29