gpt4 book ai didi

ios - 从两个 UIView 中的每一个中的三个点计算 CGAffineTransform 的值?

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

我有两个 UIView,每个都包含一个对象的可视化表示。我在每个 UIView 中都有三个已知的 CGPoint,它们对应于该对象上的相同位置。我需要对其中一个 View 应用转换,以便这三个点与另一个 View 中的对应点完美对齐。

我需要处理缩放、旋转和平移,即仿射变换,并且我知道计算此类平移参数的数学方法(参见 this question )。我不明白的是如何在 Obj-C 中实际执行这些计算并将正确的数字插入 CGAffineTrasnformMake。看起来应该是显而易见的,但出于某种原因,我认为我只是在这里遗漏了部分概念。

所以简而言之,在 UIView A 中给定 CGPoints (X1a,Y1a), (X2a,Y2a), (X3a,Y3a) 和 (X1b, Y1b), (X2b,Y2b), (X3b,Y3b) in UIView B,我该怎么做才能让我自己得到一个 CGAffineTransform 我可以应用到 UIView B?所以它与 UIView A 对齐?

顺便说一下,我的部署目标是 iOS 5;我不需要提前支持任何东西。

谢谢!

最佳答案

我在 iOS 中需要完全相同的东西。这是我最终想出的......我知道代数计算,但我不知道如何使用LAPACK。您需要添加 Accelerate 框架来计算矩阵逆。假设原始 UIView 中有点 p1、p2、p3,转换后的 UIView 中有 q1、q2、q3:

CGPoint p1, p2, p3, q1, q2, q3;

// TODO: initialize points

double A[36];

A[ 0] = p1.x; A[ 1] = p1.y; A[ 2] = 0; A[ 3] = 0; A[ 4] = 1; A[ 5] = 0;
A[ 6] = 0; A[ 7] = 0; A[ 8] = p1.x; A[ 9] = p1.y; A[10] = 0; A[11] = 1;
A[12] = p2.x; A[13] = p2.y; A[14] = 0; A[15] = 0; A[16] = 1; A[17] = 0;
A[18] = 0; A[19] = 0; A[20] = p2.x; A[21] = p2.y; A[22] = 0; A[23] = 1;
A[24] = p3.x; A[25] = p3.y; A[26] = 0; A[27] = 0; A[28] = 1; A[29] = 0;
A[30] = 0; A[31] = 0; A[32] = p3.x; A[33] = p3.y; A[34] = 0; A[35] = 1;

int err = matrix_invert(6, A);
assert(err == 0);

double B[6];

B[0] = q1.x; B[1] = q1.y; B[2] = q2.x; B[3] = q2.y; B[4] = q3.x; B[5] = q3.y;

double M[6];

M[0] = A[ 0] * B[0] + A[ 1] * B[1] + A[ 2] * B[2] + A[ 3] * B[3] + A[ 4] * B[4] + A[ 5] * B[5];
M[1] = A[ 6] * B[0] + A[ 7] * B[1] + A[ 8] * B[2] + A[ 9] * B[3] + A[10] * B[4] + A[11] * B[5];
M[2] = A[12] * B[0] + A[13] * B[1] + A[14] * B[2] + A[15] * B[3] + A[16] * B[4] + A[17] * B[5];
M[3] = A[18] * B[0] + A[19] * B[1] + A[20] * B[2] + A[21] * B[3] + A[22] * B[4] + A[23] * B[5];
M[4] = A[24] * B[0] + A[25] * B[1] + A[26] * B[2] + A[27] * B[3] + A[28] * B[4] + A[29] * B[5];
M[5] = A[30] * B[0] + A[31] * B[1] + A[32] * B[2] + A[33] * B[3] + A[34] * B[4] + A[35] * B[5];

NSLog(@"%f, %f, %f, %f, %f, %f", M[0], M[1], M[2], M[3], M[4], M[5]);

CGAffineTransform transform = CGAffineTransformMake(M[0], M[2], M[1], M[3], M[4], M[5]); // Order is correct...

这里是matrix_inverse的定义,它是一个C函数。它是从另一个 SO answer 修改而来的:

#import <Accelerate/Accelerate.h>
#include <stdlib.h>

int matrix_invert(long N, double *matrix) {

long error=0;
long *pivot = malloc(N*N*sizeof(long));
double *workspace = malloc(N*sizeof(double));

dgetrf_(&N, &N, matrix, &N, pivot, &error);

if (error != 0) {
// NSLog(@"Error 1");
return error;
}

dgetri_(&N, matrix, &N, pivot, workspace, &N, &error);

if (error != 0) {
// NSLog(@"Error 2");
return error;
}

free(pivot);
free(workspace);
return error;
}

Here is the source code on github ,我可能会在稍后将其重构为一个采用 CGPoints 的 NSArray 的函数。

如果超过3个点,需要用最小二乘法求解。 Matrix inverse 可以,但数值不稳定(结果可能会偏离很多),我以后可能还会将此解决方案添加到要点中。正确的方法是使用奇异值分解,我不知道如何使用 LAPACK。

关于ios - 从两个 UIView 中的每一个中的三个点计算 CGAffineTransform 的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13291796/

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