Вращение NSImage с или без NSAffineTransform

У меня есть NSImage рисуется на подкласс NSView. В предыдущем вопросе мне помогли нарисовать его вертикально в верхнем левом углу. Теперь я хочу иметь возможность вращать изображение. У меня есть кнопка, которая увеличивает переменную вращения%4, а затем умножаю ее на -90, чтобы найти угол поворота. Затем я использую NSAffineTransform, чтобы повернуть изображение и перевести его обратно на экран. Однако, похоже, что это не работает так, как я ожидаю. У меня две проблемы.

1) Когда я поворачиваю, часть изображения, которая находится в области, которой не было в предыдущем кадре, рисуется правильно. Однако зелье, которое было там ранее, остается в качестве исходного изображения. Это означает, что после нескольких поворотов имеется квадрат исходного вертикального изображения, а затем прямоугольник ниже или слева от повернутого изображения.

2) Когда я изменяю размер окна, изображение перерисовывается (как и должно) в исходной вертикальной ориентации (как и не должно).

По сути, я прихожу к выводу, что NSAffineTransform работает не так, как я думаю. Есть ли другой способ повернуть (и перевести) изображение? Спасибо

большой кусок кода: (код между "РАБОТАМИ" и "окончанием работ" - это рабочий код, который просто рисует изображение. Это было из моего предыдущего вопроса).

[СТАРЫЙ КОД УДАЛЕН, заменен нижним новым кодом]

Спасибо

РЕДАКТИРОВАТЬ: немного больше исследований обнаруживает, что вместо выполнения NSAffineTtransform я могу вращать представление. Кажется, это работает лучше. Однако я не могу заставить перевод работать правильно. новый код ниже (оригинальный код удален для экономии места)

- (void)drawRect:(NSRect)rect
{

//WORKS
    NSRect frame;
    frame.origin = NSZeroPoint;
    frame.size = [image size];
// end works

    float deltaX, deltaY, height, width;

// if the rotate button was just clicked, we need to rotate by 90 deg, otherwise not
    double rotateDeg = justRot ? -90.0 : 0;

    justRot = NO;

// rotate

    deltaX = 0;
    deltaY = 0;

// translate to account for rotation

    height = [image size].height;
    width = [image size].width;

    switch (rotation)
    {
        case 0:
            NSLog(@"No rotation ");
            break;
        case 1: 
            deltaX += width;
            break;
        case 2:
            deltaX += width;
            deltaY +=  height;  
            break;
        case 3:
            deltaY += height;
            break;
    }


    NSPoint orig;
    if (rotation != 0)
    {
        orig.x = -100;
        orig.y = -100;
    }
    [self rotateByAngle: rotateDeg];
    NSLog(@"orig %f %f", orig.x, orig.y);
//  WORKS
    [self setFrame: frame];
    [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];
// end works
    [self translateOriginToPoint: orig];    
}

3 ответа

Решение

Хорошо, для истории, в случае, если у кого-то еще есть этот вопрос, вот ответ, который я придумал:

Вращение кадра остается в drawRect, все остальное перемещается в метод rotate:

-(void)rotate
{
    float deltaX, deltaY, height, width;

    rotation = (rotation +1) % 4 ;

    deltaX = 0;
    deltaY = 0;

// translate to account for rotation

    height = [image size].height;
    width = [image size].width;

    switch (rotation)
    {
        case 0:
            NSLog(@"No rotation ");
            deltaY -= width;
        break;
        case 1: 
            deltaY -= height;
            break;
        case 2:
            deltaX += height-width;
            deltaY -= height ;  
            break;
        case 3:
            deltaX += height-width;
            deltaY -= width;
            break;
    }

    NSPoint orig;
    orig.x = deltaX;
    orig.y = deltaY;

    [self rotateByAngle: 90.0];
    [self translateOriginToPoint: orig];

    [self setNeedsDisplay:YES];
}

Я предполагаю, что вы хотите повернуть изображение вокруг его центра. Если это так, вам нужно перевести начало аффинного преобразования в центр изображения, затем повернуть, а затем перевести обратно. Теперь, если у вас остались артефакты предыдущей позиции, это возможно потому, что вы не вызвали -[NSView setNeedsDisplayInRect:] с правильными прямоугольниками. Помните, что вам нужно сделать недействительными как изображения предыдущих, так и новые позиции.

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

Взгляните на мой старый пример кода Transformed Image по адресу: http://developer.apple.com/mac/library/samplecode/Transformed_Image/index.html

Другие вопросы по тегам