Как повернуть изображение, нарисованное непосредственно в NSView с помощью DrawRect в приложении OSX?

Я пишу приложение OSX в Xcode, используя Objective-C. У меня есть окно с NSView внутри него, и предполагается, что NSView использует данные из NSMutableArray, содержащего NSNumbers, для рисования соответствующих изображений в сетке, чтобы изображения рисовались в 0,0; 32,0; 64,0 . . . 0,32; 32,32; и т.д. Соответственно счетчик массива - это W*H сетки, в данном случае 21*21 или 441.

Вы щелкаете левой кнопкой мыши, чтобы «поместить» изображение, что на самом деле означает просто обновление массива в зависимости от того, где вы щелкнули, а затем вызываете setNeedsDisplay:YES, чтобы он перерисовывался, чтобы отразить обновленный массив. Пока что я могу заставить его правильно рисовать изображения на основе массива.

Однако, когда вы щелкаете правой кнопкой мыши, предполагается, что изображение в определенном слоте сетки будет поворачиваться на определенную величину. Единственная проблема, с которой я столкнулся, это выяснить, как на самом деле рисовать повернутые изображения в их правильных местах. Они должны вращаться вокруг своих центральных точек, которые будут иметь относительные координаты 16,16 (все изображения имеют размер 32x32 пикселя). Как есть, мой код:

- (void)drawRect:(NSRect)dirtyRect
{
    [super drawRect:dirtyRect];

    //Black background
    [[NSColor blackColor] setFill];
    NSRectFill(dirtyRect);

    // Drawing code here.
    NSRect rectToDraw = CGRectMake(0,0,32,32);
    NSInteger imageIndex = 0;
    NSImage *imageToDraw = nil;
    for (int i = 0; i < [objDataArray count]; i++) {
        //Loop through data array and draw each image where it should be
        if ([objDataArray objectAtIndex:i]==[NSNull null]) continue; //Don't draw anything in this slot

        //Math to determine where to draw based on the current for loop index
        //0 = 0,0; 1 = 32,0 . . . 20 = 640,0; 21 = 0,32; etc. (grid is 21x21)
        rectToDraw.origin.x = (i % 21)*32;
        rectToDraw.origin.y = floor(i/21)*32;

        //Get the data at this index in the data array
        imageIndex = [((NSNumber*)[objDataArray objectAtIndex:i]) integerValue];

        //Use the retrieved number to get a corresponding image
        imageToDraw = (NSImage*)[objImagesArray objectAtIndex:imageIndex];

        //Draw that image at the proper location
        [imageToDraw drawInRect:rectToDraw];
    }
}

Итак, скажем, что величина поворота в градусах определяется переменной rotateAmount. Как изменить строку drawInRect (последняя строка перед закрывающими фигурными скобками) так, чтобы изображение отображалось в правильном месте, указанном rectToDraw, но повернуто на угол rotateAmount относительно своего центра?

Спасибо.


person Adam    schedule 29.05.2014    source источник


Ответы (1)


Вы не рисуете изображение повернутым как таковое. Вы преобразуете координатное пространство, а затем рисуете изображение.

[NSGraphicsContext saveGraphicsState];

NSAffineTransform* xform = [NSAffineTransform transform];

// Translate the image's center to the view origin so rotation occurs around it.
[xform translateXBy:-NSMidX(rectToDraw) yBy:-NSMidY(rectToDraw)];
[xform rotateByDegrees:rotationAmount];
[xform concat];

[imageToDraw drawInRect:NSOffsetRect(rectToDraw, -NSMidX(rectToDraw), -NSMidY(rectToDraw))];

[NSGraphicsContext restoreGraphicsState];

Есть некоторый шанс, что у меня есть обратное преобразование. Я всегда забываю, куда это идет (если это трансформирует представление или содержание). Если ваше изображение уходит в никогда-никогда, измените знаки перевода.

person Ken Thomases    schedule 30.05.2014
comment
Спасибо. Я думаю, что понимаю это достаточно хорошо, а если нет, я попытаюсь использовать документацию NSAffineTransform. - person Adam; 30.05.2014