3

我怎样才能写 CATransform3D 等效于

CGPoint CGPointApplyAffineTransform(CGPoint point, CGAffineTransform t)
CGSize CGSizeApplyAffineTransform(CGSize size, CGAffineTransform t);
CGRect CGRectApplyAffineTransform(CGRect rect, CGAffineTransform t);

?

4

2 回答 2

3

这行得通,但是知道里面发生了什么当然会好得多-[CALayer convertPoint:toLayer:]

CGPoint CGPointApplyCATransform3D(CGPoint point, CATransform3D transform, CGPoint anchorPoint, CATransform3D parentSublayerTransform)
{

    static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
    static CALayer *sublayer, *layer;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sublayer = [CALayer layer];
        layer = [CALayer layer];
        [layer addSublayer:sublayer];
    });

    if(pthread_mutex_lock(&mtx))
    {
        [NSException raise:NSInternalInconsistencyException format:@"pthread_mutex_lock failed"];
    }

    layer.sublayerTransform = parentSublayerTransform;
    sublayer.transform = transform;
    sublayer.anchorPoint = anchorPoint;
    CGPoint retval = [sublayer convertPoint:point toLayer:layer];

    if(pthread_mutex_unlock(&mtx) != 0)
    {
        [NSException raise:NSInternalInconsistencyException format:@"pthread_mutex_unlock failed"];
    } 

    return retval;
}

简单的单元测试https://gist.github.com/hfossli/5130975

于 2013-03-10T23:13:11.270 回答
3

好的,类似于以下内容:

- (CGPoint)convertPoint:(CGPoint)p withTransform:(CATransform3D)t {

    NSArray *m1 = @[@(p.x), @(p.y), @(0), @(1)];
    NSMutableArray *m2 = [NSMutableArray array];
    [m2 addObject:@[@(t.m11), @(t.m12), @(t.m13), @(t.m14)]];
    [m2 addObject:@[@(t.m21), @(t.m22), @(t.m23), @(t.m24)]];
    [m2 addObject:@[@(t.m31), @(t.m32), @(t.m33), @(t.m34)]];
    [m2 addObject:@[@(t.m41), @(t.m42), @(t.m43), @(t.m44)]];
    NSMutableArray *result = [NSMutableArray array];
    for (int i = 0; i < 2; i++) {

        double k = 0;
        for (int j = 0; j < 4; j++) {

            k += [m1[j] doubleValue] * [m2[j][i] doubleValue];
        }
        [result addObject:@(k)];
    }
    return CGPointMake([result[0] doubleValue], [result[1] doubleValue]);
}

没有异常,没有互斥锁在多线程上阻塞当前线程,没有额外的层,也没有等待这些层被绘制。

适用于大多数变换,例如平移、旋转、缩放及其组合。用Objective C编写,在纯C中会更好(不转换为对象,反之亦然),但我只是想展示一个想法。

没有 Z 坐标,因为CGPoint仅由 x 和 y 组成,而您的“答案”根本不计算它们。

什么是“锚点”参数?锚点意味着一些额外的矩阵乘法 - 您移动图形以使您的锚点出现在 中(0, 0, 0),应用变换并将图形向后移动相同的距离。

父变换参数?同样,您只需要以正确的顺序将两个 4x4 矩阵相乘。

当然,你甚至不回答剩下的问题。

CGRect CGRectApplyAffineTransform(CGRect rect, CGAffineTransform t);

一个矩形意味着 4 个点。您只需要对这些点中的每一个应用变换。

CGSize CGSizeApplyAffineTransform(CGSize size, CGAffineTransform t);

变换为CGSize? CGSize在 3D 中转换,而CGSize有 2 个维度并且根本没有指定点?当您没有所有变量时,您只是尝试解决问题,因为例如旋转可能会影响大小并且您不知道执行此旋转的初始锚点。

于 2015-07-28T08:47:18.230 回答