[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