Skip navigation.
 
mlRe: Is it a bug in NSAffineTransform?
FROM : Henry McGilton
DATE : Tue Jun 20 17:28:09 2006

On Jun 19, 2006, at 10:20 PM, Bill So wrote:

> I m not an expert in computer graphics.  I m trying to use
> NSAffineTransform as documented in Cocoa Drawing Guide -> Coordinate
> Systems and Transforms -> Using Transforms in Your Code -> Undoing a
> Transformation.
>
> http://developer.apple.com/documentation/Cocoa/Conceptual/
> CocoaDrawingGuide/Transforms/chapter_4_section_4.html#//apple_ref/
> doc/uid/TP40003290-CH204-BCIJGDAA
>
> I found a strange behaviour in NSAffineTransform which doesn't align
> with what's described in the documentation.


        <<<<  munch --- see below  >>>>

> As specified in the guide, the SECOND transform should be relative to
> the previous element.  My understanding is that the frist transform
> translated the origin to (10, 10).  And the second transform
> translated the origin to (15, 10).
>
> But I don't find it correct when I implement the example in my testing
> application.  I implemented a custom NSView class "TransformView" and
> draw this view in NSWindows.
>
> The "drawRect" method of my TransformView class is as follow:
>
> - (void)drawRect:(NSRect)rect
> {
>     NSPoint testPoint = { 0.0, 0.0 };
>     [[NSColor whiteColor] setFill];
>     NSRectFill(rect);
>     
>     NSColor *myColor = [NSColor grayColor];
>     NSAffineTransform* xform = [NSAffineTransform transform];
>     [xform translateXBy:10.0 yBy:10.0];


At this point, the transform has translated origin to (10, 10)
>     [xform concat];


At this point, you have concated the CTM so that the origin
has been translated by (10, 10)

>     [myColor setFill];
>     NSRect myRect = NSMakeRect(0.0, 0.0, 4.0, 4.0);
>
> // fill 1st square
>     NSRectFill(myRect);
>     
>     [xform translateXBy:5.0 yBy:0.0];


At this point, the transform has translated origin to (15, 10)
>     [xform concat];


At this point, you have concated the *already* transformed CTM by
a *further* (15, 10) so that the origin becomes transformed by (25, 20).

concat operations are cumulative.    You might want to also take a
look at NSGraphicsContext as well, and look at the saveGraphicsState
and restoreGraphicsState methods.

If you insert a line of code before the second translateXBy:

    xform = [NSAffineTransform transform];

to obtain a fresh identity transform, your example then works as
you expect.

>
> // fill 2nd square
>     NSRectFill(myRect);
> }
>
> I found that the 2nd square is not drawn at (15, 10 ).  Instead, it is
> drawing at (25, 20)
>
> i.e. let 1st transformation matrix be T1 and 2nd transformation 
> matrix be T2.
>
> The transformation matrix when drawing the 2nd square is T1 x (T1 x
> T2) instead of T1 x T2


Precisely --- that is the answer according to the code as originally
written.


> There's one strange behaviour.  For the sake of debugging, I put an
> NSPoint variable "testPoint" and initialize it to (0, 0).  The result
> of [xform transformPoint:testPoint] is correct, i.e. (15, 10), not
> (25, 20).

Yes.  In that case, you simply transformed the point by the affine
transform itself --- the CTM in the graphics state was not involved.
To see what happens, in your original code, put these lines at the
end of the  drawRect  method.:

    NSRect testRect = NSMakeRect(testPoint.x, testPoint.y, 4.0, 4.0);
    [[NSColor redColor] set];
    NSRectFill(testRect);


> Is there anything wrong in my code or analysis?


Yes . . .    See above . . .

> Is it a bug in NSAffineTransform?


Highly unlikely . . .

    Cheers,
        ........  Henry

===============================+============================
  Henry McGilton, Boulevardier |    Trilithon Software
    Objective-C/Java Composer  |    Seroia Research
-------------------------------+----------------------------
  mailto:<email_removed>  |  http://www.trilithon.com
                                |
===============================+============================

Related mailsAuthorDate
mlIs it a bug in NSAffineTransform? Bill So Jun 20, 07:20
mlRe: Is it a bug in NSAffineTransform? Henry McGilton Jun 20, 17:28