How can I write the CATransform3D equivalent to

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

?

有帮助吗?

解决方案

This works, but it would ofcourse be a lot better to know what happens inside -[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;
}

Simple unit tests https://gist.github.com/hfossli/5130975

其他提示

Okay, something like the following:

- (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]);
}

NO exceptions, NO mutexes blocking current thread on multithreading, NO extra layers and NO waiting until these layers will be drawn.

Works for most transforms such as translation, rotation, scaling and their combinations. Written in Objective C, it will be better in pure C (without converting to objects and vice versa) but I just wanted to show an idea.

No Z coordinate because CGPoint consists of x and y only and your "answer" doesn't count them at all.

What is the "anchor point" param? Anchor point means some additional matrix multiplications - you move the figure to make your anchor point appear in (0, 0, 0), apply transforms and move the figure back by the same distances.

Parent transform param? Again you just need to multiply two 4x4 matrices in correct order.

And of course you don't even answer to the rest of your question.

CGRect CGRectApplyAffineTransform(CGRect rect, CGAffineTransform t);

One rect means 4 points. you just need to apply the transform for each of these points.

CGSize CGSizeApplyAffineTransform(CGSize size, CGAffineTransform t);

Transform for CGSize? Transform for CGSize in 3D while CGSize has 2 dimensions and no points specified at all? You just try to solve a problem when you don't have all the variables because for example the rotation may have influence on size and you don't know the initial anchor point to perform this rotation.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top