Рисовать радиалы из центра эллипса в кварце - PullRequest
2 голосов
/ 30 июня 2011

Я пытаюсь нарисовать радиалы из центра эллипса в кварце.

CGContextSetRGBStrokeColor(ctx, 0.0, 1.0, 1.0, 1.0); //cyan stroke
CGContextSetLineWidth(ctx, 2.0);
CGContextFillEllipseInRect(ctx, oRect);

CGContextSaveGState(ctx);        

CGPoint center = CGPointMake(CGRectGetMidX(oRect), CGRectGetMidY(oRect));
CGFloat maxX = CGRectGetMaxX(oRect);

for(int i = 0; i < 5; i++) {
    CGContextBeginPath(ctx);        
    CGContextMoveToPoint(ctx, maxX, center.y);
    CGContextAddLineToPoint(ctx, center.x, center.y);
    CGContextClosePath(ctx);
    CGContextStrokePath(ctx);
    CGContextRotateCTM(ctx, degreesToRadians(5.0));
}


CGContextRestoreGState(ctx);

Результат: quartz result

Вместо рисования линий, исходящих из центра эллипса, оно сдвигается при каждом преобразовании матрицы. Почему центр поворачивается вместо вращения?

1 Ответ

1 голос
/ 30 июня 2011

Проще говоря, это потому, что вызов CGContextRotateCTM(ctx, degreesToRadians(5.0)); применяет матрицу вращения вокруг начала координат системы координат . В этом случае кажется, что источник находится в левом верхнем углу вашего представления. Все это вращается вокруг левого верхнего угла, а не вокруг середины вашего взгляда.

Если вы хотите вращаться вокруг центра вашего вида, вам сначала нужно сместить систему координат. Самый простой способ сделать это, вероятно, просто применить перевод, чтобы переместить его в центр, применить вращение, а затем применить другой перевод, чтобы переместить его обратно в угол. В конечном итоге это будет выглядеть так:

///...
CGPoint center = CGPointMake(CGRectGetMidX(oRect), CGRectGetMidY(oRect));
CGFloat maxX = CGRectGetMaxX(oRect);

for(int i = 0; i < 5; i++) {
    CGContextBeginPath(ctx);        
    CGContextMoveToPoint(ctx, maxX, center.y);
    CGContextAddLineToPoint(ctx, center.x, center.y);
    CGContextClosePath(ctx);
    CGContextStrokePath(ctx);
    CGContextTranslateCTM(ctx, center.x, center.y); // Note
    CGContextRotateCTM(ctx, degreesToRadians(5.0));
    CGContextTranslateCTM(ctx, -center.x, -center.y); // Note
}

Вы, конечно, можете объединить всю операцию перевода-вращения-перевода в одну CGAffineTransform, например:

// Outside the loop
CGAffineTransform transform = CGAffineTransformMakeTranslation(center.x, center.y);
transform = CGAffineTransformRotate(transform, degreesToRadians(5.0));
transform = CGAffineTransformTranslate(transform, -center.x, -center.y);

for(int i = 0; i < 5; i++) {
    // ...
    CGContextConcatCTM(ctx, transform);
}

Это избавит вас от снижения производительности при выполнении трех отдельных операций с матрицами при каждом прохождении цикла. Но выберите тот, который вам понятнее; если вы не видите ощутимого влияния на производительность, всегда предпочитайте ремонтопригодность.

...