[Drawkit] Transforms / ScaleBy

Graham Cox graham.cox at bigpond.com
Thu Apr 30 20:16:07 PDT 2009


On 01/05/2009, at 12:45 PM, Allan Daly wrote:

> Mike, Graham,
>
> Picking up on this thread ... for my DXF importer I need to be able  
> to scale DKShapeGroups by a scale factor that I read out of the DXF  
> INSERT entity data. Actually there can be separate X and Y scale  
> factors. How do I apply these to DKShapeGroups, or for that matter  
> any DKDrawableObject?

To a large extent, DK is designed to shield you from dealing with  
NSAffineTransform objects directly in most cases. If you are working  
with the built-in objects, there are very few places where the  
transforms are exposed. It's only when you get into low-level  
subclassing that they become necessary to deal with.

A drawable's -setLocation:, -setSize: and -setAngle: methods  
internally set up transforms for translation, scaling and rotation  
respectively.

To scale an object, pass the desired size to -setSize: and it will  
transform itself as necessary. This works with groups as well.

If you want to scale an object by a certain factor (x2, say) then you  
need to do a small calculation by taking the current size, multiplying  
it by the factors then setting the resulting size. There's no  
constraint on the scale factors being equal in X and Y.

The other thing DK shields you from is the transform origin. When  
dealing with transforms directly, you always have to allow for the  
origin of the coordinate system, which is where everything is measured  
from. For our purposes it's more useful to allow each object to  
effectively define its own local origin, so that sizing and rotation  
operations are performed relative to this point. By default DK's shape  
objects set this at their centre, so doubling a shape's size expands  
it about that centre point. Using -setOffset: allows you to move that  
point elsewhere relative to the shape's bounds, so if you wanted the  
top, left corner to remain where it is when doubling the size you  
could set the offset to {-0.5,-0.5} before calling -setSize: (The  
offset is always expressed as if the bounds were a 1 x 1 square).

The only slightly tricky possibility when using -setSize: is that if  
the object is already rotated, -setSize: operates as if the rotation  
weren't there - in other words the edge lengths of the rotated shape  
are always correctly set to the size you pass, and the unseen bounds  
will vary as needed. Mostly that's exactly what you want and is  
entirely intuitive, but if for example the DXF scale factors are  
expressed in terms of the scaled edges of the bounds rect, even with  
any rotation applied, you'll end up having to use a bit of  
trigonometry to work out how the bounds sizes are affected. If that  
turns out to be the case (probably unlikely) I can help you work out  
what to do.

> From reading through the message string below I can see that  
> NSAffineTransformation objects are involved, and from looking at the  
> API documentation on that I sort of get it, but frankly it eludes me  
> right now. Could either of you provide any help to get me pointed in  
> the right direction on this? And/or do you know any good links to  
> send me that would help me understand what the heck an  
> AffineTransformation is and how I should use it? Seem to me that I  
> fundamentally do not understand these Transformation objects and I  
> would like to.
>

A good starting point is probably the wikipedia article: http://en.wikipedia.org/wiki/Affine_transformation 
  though it suffers from the usual problem of wikipedia articles in  
that it dives into the maths without enough conceptual stuff.

A somewhat more Cocoa-oriented approach is here: http://cocoadevcentral.com/articles/000045.php

This is an excellent step-by-step guide, and was where I first got  
started with NSAffineTransform.

Hope that helps,

--Graham


More information about the Drawkit mailing list