gpt4 book ai didi

android - Matrix.postScale( sx, sy, px, py) 是如何工作的?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:54:21 25 4
gpt4 key购买 nike

先读 Taig's question

泰格说:

When calling Matrix.postScale( sx, sy, px, py ); the matrix gets scaled and also translated (depending on the given point x, y). That predestines this method to be used for zooming into images because I can easily focus one specific point. The android doc describes the method like this:

Postconcats the matrix with the specified scale. M' = S(sx, sy, px, py) * M

At a first glance this seems ridiculous because M is supposed to be a 3x3-Matrix. Digging around I've found out that android uses a 4x4-Matrix for its computations (while only providing 3x3 on its API). Since this code is written in C I'm having a hard time trying to understand what is actually happening.

我在 Wolfram 处看到了视觉转换

我的问题和泰格一样

What I actually want to know: How can I apply this kind of scaling (with a focused point) to the 3x3 Matrix that I can access within my Java-code?

谁能给我一个 10 岁 child 能理解的示例和具有 4 个参数(sx、sy、px、py)的二维缩放公式?

最佳答案

仔细看看 Matrix 方法。您将看到 getValue()setValue()。文档说他们使用具有 9 个值的 float 数组。还有一堆常量:MSCALE_X, MSCALE_Y, MTRANS_X, MTRANS_Y 等。这些常量是索引到 float[9] 数组中。

因为我们只在二维空间工作,所以矩阵实际上是一个2x2 矩阵。但是因为这个矩阵支持仿射变换,所以矩阵被扩展成了一个3x3的矩阵。 3x3 = 9,对应于float[9]数组。也就是说,本质上,您的 3x3 矩阵。

Matrix 的实际内容是用 C++ 编写的,并通过 JNI 访问,因为操作必须快快快快快快快。他们甚至使用一种针对计算速度进行了优化的特殊非标准 float 格式(“16.16”)。

我不知道您从哪里获得有关 4x4 阵列的信息。下面是来自 C++ JNI 的代码 fragment :

SkScalar         fMat[9];
mutable uint32_t fTypeMask;

void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
fMat[kMScaleX] = sx;
fMat[kMSkewX] = 0;
fMat[kMTransX] = tx;

fMat[kMSkewY] = 0;
fMat[kMScaleY] = sy;
fMat[kMTransY] = ty;

fMat[kMPersp0] = 0;
fMat[kMPersp1] = 0;
fMat[kMPersp2] = 1;

unsigned mask = 0;
if (sx != 1 || sy != 1) {
mask |= kScale_Mask;
}
if (tx || ty) {
mask |= kTranslate_Mask;
}
this->setTypeMask(mask | kRectStaysRect_Mask);
}

这是一个用于仿射变换的 3x3 矩阵。

当您调用 matrix.postScale() 时,您正在修改 scaleX、scaleY、transX 和 transY。 (pre..()post...() 方法保留矩阵中开始的任何转换。)Matrix 像这样应用新的转换:

X' = X * scaleX + transXY' = Y * scaleY + transY

这是整个矩阵乘法的简化版本。如果我有一个带点 (2,2) 的图形并将其缩放 2 倍,则新点将是 (4,4)。要沿 X 或 Y 轴移动,我只需添加一个常数。

因为 Matrix.postScale() 实际上需要一个焦点,所以该方法会在内部调整 transX 和 transY,就好像您正在平移、缩放,然后平移回来。这使得缩放看起来好像扩展/收缩以点 px, py 为中心。

transX = (1 - scaleX) * pxtransY = (1 - scaleY) * py

所以对于焦点,我通过将 px 和 py 直接添加到原始 x,y 值来将图形移动到 (px,py)。然后我进行缩放。但是要撤消翻译,我必须考虑到我原来的焦点现在已自行缩放,因此我必须减去 scaleX * px 和 scaleY * py 而不是减去 px 和 py。

SkewShear 类似于缩放,但轴相反:

X' = Y * skewXY' = X * skewY

由于您在缩放和平移时没有扭曲,因此 skewX 和 skewY 设置为零。所以它们仍然用于矩阵乘法,只是不影响最终结果。

旋转是通过添加一个小触发器来完成的:

theta = angle of rotationscaleX = cos(theta)skewX = -sin(theta)skewY = sin(theta)scaleY = cos(theta)

然后是 android.graphics.Camera(相对于 android.hardware.Camera),它可以获取 2D 平面并在 3D 空间中旋转/平移它.这就是 MPERSP_0MPERSP_1MPERSP_2 发挥作用的地方。我不是在做那些方程式;我是程序员,不是数学家。

但我不需要成为一名数学家。我什至不需要知道 Matrix 是如何计算的。我一直在研究支持捏/缩放的 ImageView 子类。因此,我使用 ScaleGestureDetector 来告诉我用户何时进行缩放。它具有方法 getScaleFactor()getFocusX()getFocusY()。我将这些值插入到 matrix.postScale() 中,并将我的 ImageView 的比例类型设置为 MATRIX,我调用 ImageView .setImageMatrix() 与我的缩放矩阵。瞧,图像会根据用户的手势完全按照用户期望的方式缩放。

所以我不明白所有关于探索 Matrix 幕后工作原理的焦虑。不过,我希望我在这里写的东西能给你正在寻找的答案。

关于android - Matrix.postScale( sx, sy, px, py) 是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30414892/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com