TweetFollow Us on Twitter

GX Rigid Body Dragging
Volume Number:12
Issue Number:8
Column Tag:New Technologies

Dragging and Rigid-Body
Transformations

QD GX can make your Mac a swinging place

By Lawrence D’Oliveiro

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

QuickDraw GX offers some interesting new possibilities for interactive graphics. This article is a note on one of them: the idea of dragging an object about, and having it rotate to follow the drag, just like real objects tend to do when you pull or push them.

The code I’m presenting here is by no means finished; think of it as a rough sketch, a demonstration of the concept. It is written in Modula-2, and makes heavy use of my standard libraries, which you can find at ftp://ftphost.waikato.ac.nz/pub/ldo/MyModLib.hqx.

Feel free to use my code as a starting point for your own experiments.

Transformations in QuickDraw GX

QuickDraw GX supports 3-by-3 mappings, which are capable of applying any kind of linear transformation to the geometry of a GX shape. (A linear transformation is one that preserves the straightness of lines. Thus, a GX mapping cannot transform a straight line to a curve, or vice versa.)

Linear transformations can be broken down into various simple types: translations (changes of position), rotations, scaling, skewing and perspective. In fact, any arbitrary linear transformation can be considered to be built from components of these types.

There are various useful subsets of linear transformations: an affine transformation is one where any pair of parallel lines remains parallel after the transformation. GX’s perspective transformations clearly are not affine; thus, an affine transformation is one that has no perspective component.

An important subset of affine transformations is the set of rigid-body transformations: these are ones that preserve the distance between any two given points. Rigid-body transformations consist only of translations and rotations; this corresponds intuitively to our notions of real rigid bodies, which cannot be scaled or stretched in any way, though you can usually move them around and reorient them any way you like (unless they’re a lot bigger or heavier than you are).

Figure 1. As the cursor pulls the arrow to the right, the arrow swings into line with the direction of motion. These are successive screen shots from my program; the upper-left corner of each shot is the upper-left corner of the window.

Dragging a Rigid Body

Consider what happens when you try to move a real rigid body. The body has a center of mass; if you orient the direction of your force so that it passes exactly through this point, the object will change its position without rotating. But if you offset your force by any amount, you will produce a torque, and the object will change both its position and its orientation. (For example, place a book on a smooth surface such a desk, grasp it by just one corner, and pull in a straight line; the book, as it starts to move, also swings around to line up its center of mass with the direction of travel.)

Figure 1 shows this happening in my program.

In the following analysis, I’ll follow the rules of Aristotelian, rather than Newtonian, physics: objects have no inertia, but they are subject to friction, which acts through their center of mass. Thus, they stop moving as soon as you stop pushing them.

Consider a body with its center of mass at a point C. Say you apply a small force on it at a point F, sufficient to displace that point to a new position G close to F. The center of mass is in turn moved to a new position D (Figure 2).

Figure 2. Movements... Figure 3. ...and analysis

The force you apply can be split into two components: the component parallel to CF moves the object without rotating it (hence the new position of the center of mass, D, lies on this line), while the component perpendicular to this line exerts a pure rotational force on the object without moving the center of mass.

In Figure 2, q is the angle CFG and can have any value, while f is the angle of rotation FCG, and is assumed to be small (you’ll see why shortly).

Now draw a line P1P2 parallel to CF, and project the points C, D, F and G onto this line at the points Cp, Dp, Fp and Gp (Figure 3). Gt is the intersection between FFp and CG. In this case, q is greater than 90°, so the angle GFGt is q - 90° (I’ll leave the analysis of the case where q is less than 90° as an “exercise for the reader”, as they say). Since f is small, FGtG is close to 90°, so the ratio FGtFG is approximately cos q - 90°, which equals sin q. Now, since GFGt is a right angle, sin f equals FGtCF which becomes FG sin qCF when you apply the above approximation.

For larger movements, where the angle f might not be small, simply split the movement into lots of small steps with correspondingly small f. If you want a fancy-sounding term for this mathematical trick, it’s called differential calculus.

Translating This Into Code

The next step is to write some actual code based on this analysis. In the following, I’ll intermingle declarations and statements to suit the exposition, rather than the requirements of strict language syntax (in other words, I’ll be following the order in which code is usually written).

VAR
 LastMouse, ThisMouse : Point;
 ThisDelta : gxPoint;
 ShapeCenter : gxPoint;

LastMouse is the point F, while ThisMouse is the point G. ThisDelta is the displacement FG, computed as follows:

 ThisDelta.x := IntToFixed(ThisMouse.h - LastMouse.h);
 ThisDelta.y := IntToFixed(ThisMouse.v - LastMouse.v);

ShapeCenter is supposed to be the center of mass, or center of geometry, of the shape. GX provides a call, GXGetShapeCenter, that is supposed to return this in the coordinate system of the shape geometry itself. You could then put this through the shape mapping to get the center in “local coordinates”. Unfortunately, when I tried this, I got incorrect results for a complex picture shape (a QuickDraw GX bug?). So, to avoid this problem, my code takes ShapeCenter as the center of the shape’s bounding rectangle, rather than of its actual geometry:

GXGetShapeLocalBounds(TheShape, Bounds);
ShapeCenter.x := (Bounds.right + Bounds.left) DIV 2;
ShapeCenter.y := (Bounds.bottom + Bounds.top) DIV 2;

Next we perform the computation of the actual rotation angle, using good old floating-point numbers instead of fixed-point ones:

VAR
 DeltaX, DeltaY, Delta : LongReal;
 RadiusX, RadiusY, Radius : LongReal;
 DragAngle, RotationAngleSin : LongReal;
 RotationAngle : LongReal;

DeltaX and DeltaY are the x- and y-components of the displacement FG, while Delta is the magnitude of this displacement.

DeltaX := Fix2Double(ThisDelta.x);
DeltaY := Fix2Double(ThisDelta.y);
Delta := Sqrt(Squared(DeltaX) + Squared(DeltaY));

Similarly, RadiusX and RadiusY are the x- and y-components of thedistance CF, while Radius is the magnitude of this distance.

RadiusX := Fix2Double(IntToFixed(LastMouse.h) - ShapeCenter.x);
RadiusY := Fix2Double(IntToFixed(LastMouse.v) - ShapeCenter.y);
Radius := Sqrt(Squared(RadiusX) + Squared(RadiusY));

DragAngle is the angle q. I compute it here from the difference between the angles of the lines FG and CF (ArcTan2(x, y) returns the angle with tangent y/x in the appropriate quadrant, taking account of the signs of x and y):

DragAngle := ArcTan2(DeltaX, DeltaY) - ArcTan2(RadiusX, RadiusY);

RotationAngleSin is the sine of the angle f. DLimit is just a routine that constrains its first argument to within the specified limits (in this case, between -1 and 1). The need for this constraint will become apparent later.

RotationAngleSin := DLimit
 (
 Delta * Sin(DragAngle) / Radius,
 FLOATD(-1),
 FLOATD(1)
 );

And finally, we compute the angle f itself, converting from the floating-point radians that SANE operates in, to the fixed-point degrees that QuickDraw GX uses:

RotationAngle := 
 Double2Fix(ArcSin(RotationAngleSin) * FLOATD(180) / Pi())

Applying the transformation to the shape is pretty straightforward. Simply obtain the shape’s existing mapping:

VAR
 ShapeMapping : gxMapping;
...
GXGetShapeMapping(TheShape, ShapeMapping);

then apply the appropriate movement and rotation:

MoveMapping
  (
 (*@target :=*) ShapeMapping,
 (*hOffset :=*) ThisDelta.x,
 (*vOffset :=*) ThisDelta.y
  );
RotateMapping
  (
 (*@target :=*) ShapeMapping,
 (*angle :=*) RotationAngle,
 (*xCenter :=*) IntToFixed(ThisMouse.h),
 (*yCenter :=*) IntToFixed(ThisMouse.v)
  );
GXSetShapeMapping(TheShape, ShapeMapping)

Note that the center of rotation used in the RotateMapping call is the point G rather than C. This is all right, because the direction of rotation calculated by the code is actually the opposite of that in the analysis; thus the effect is the same.

Other Matters

There are several other aspects of the example code that I’ve glossed over so far.

To keep the size of the source code down, the program itself has absolutely the minimum user interface I felt I could get away with. It doesn’t even have any menus! When you start it up, it already has a shape loaded that you can try dragging about. You can bring in a different shape by dragging it into the window, from a Finder clipping file or another drag-aware application (I’ve provided a few sample clippings you can try). To quit the program, click the close box in the window.

An important issue is how to do off-screen rendering, so that your on-screen drawing doesn’t flicker. There is no direct equivalent to QuickDraw GWorlds in QuickDraw GX, but the GX SDK library code shows you how to create a much more powerful alternative: an offscreen graphics context that can optimize drawing simultaneously for multiple screens, rather than just the deepest one that your window happens to cross.

My actual program uses a routine I wrote called MoveSprite, which creates temporary offscreen structures every time you call it to move an object. It automatically sizes these structures to cover only the affected on-screen area (and doesn’t bother doing off-screen drawing if the old and new positions of the object don’t overlap). Thus, this routine is simpler to use than explicitly creating separate off-screen structures and reusing them for the duration of the drag, though it may be slower.

One feature of the code is that it doesn’t rotate the shape if you drag it at a point close to its center, or if you hold the command-key down. I figure this sort of feature could be useful in a “real” program, where the user might not always want the object to rotate.

One pitfall you always have to keep in mind when doing calculations on a computer is rounding error. In this case, repeated calls to RotateMapping can accumulate distortions in the shape geometry, since the mapping elements cannot be computed exactly. To get around this, you should keep separate track of the shape position and rotation angle, and recompute the shape mapping from these values each time, instead of applying an incremental rotation to the previous mapping. This will keep the distortion within fixed bounds, instead of letting it accumulate. My code doesn’t do this, though I must admit I have yet to notice any distortions in shapes after repeated drags.

Finally, I should own up to one important liberty I have taken with the mathematical analysis. Remember how I kept saying that the displacement and rotation angle were assumed to be small? In fact, the code will happily compute arbitrarily large values for the FG displacement, depending on how quickly you can move the mouse, and how long it takes your machine to redraw the shape in between checking the mouse position. This means that, for large mouse movements, the code is no longer strictly MC (Mathematically Correct). It’s also why I put in the DLimit call.

But then, I figure this is part of the fun of programming. For instance, I have found that I can drag a shape to a corner of the window, and leave the mouse absolutely stationary outside the window, while the shape continues to spin round and round in the corner. Is this a consequence of the code hitting a non-MC situation? I don’t know - you tell me!

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

BetterTouchTool 2.332 - Customize multi-...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
BetterTouchTool 2.332 - Customize multi-...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
Capture One 11.0.1.40 - RAW workflow sof...
Capture One is a professional RAW converter offering you ultimate image quality with accurate colors and incredible detail from more than 400 high-end cameras -- straight out of the box. It offers... Read more
Capture One 11.0.1.40 - RAW workflow sof...
Capture One is a professional RAW converter offering you ultimate image quality with accurate colors and incredible detail from more than 400 high-end cameras -- straight out of the box. It offers... Read more
GraphicConverter 10.5.4 - $39.95
GraphicConverter is an all-purpose image-editing program that can import 200 different graphic-based formats, edit the image, and export it to any of 80 available file formats. The high-end editing... Read more
Dash 4.1.3 - Instant search and offline...
Dash is an API documentation browser and code snippet manager. Dash helps you store snippets of code, as well as instantly search and browse documentation for almost any API you might use (for a full... Read more
Microsoft OneNote 16.9 - Free digital no...
OneNote is your very own digital notebook. With OneNote, you can capture that flash of genius, that moment of inspiration, or that list of errands that's too important to forget. Whether you're at... Read more
DEVONthink Pro 2.9.17 - Knowledge base,...
Save 10% with our exclusive coupon code: MACUPDATE10 DEVONthink Pro is your essential assistant for today's world, where almost everything is digital. From shopping receipts to important research... Read more
OmniGraffle 7.6 - Create diagrams, flow...
OmniGraffle helps you draw beautiful diagrams, family trees, flow charts, org charts, layouts, and (mathematically speaking) any other directed or non-directed graphs. We've had people use Graffle to... Read more
iFinance 4.3.7 - Comprehensively manage...
iFinance allows you to keep track of your income and spending -- from your lunchbreak coffee to your new car -- in the most convenient and fastest way. Clearly arranged transaction lists of all your... Read more

Latest Forum Discussions

See All

World of Warships Blitz: A guide to tact...
Ahoy mates! It's time to set out on the high seas for some PvP battles, and ... sorry, actually, World of Warships Blitz has nothing to do with pirates. Let's start over. [Read more] | Read more »
Around the Empire: What have you missed...
Around this time every week we're going to have a look at the comings and goings on the other sites in Steel Media's pocket-gaming empire. We'll round up the very best content you might have missed, so you're always going to be up to date with the... | Read more »
Everything about Hero Academy 2: Part 4...
In this part of our Hero Academy 2 guide, we're going to have a look at some of the tactics you're going to need to learn if you want to rise up the ranks. We're going to start off slow, then get more advanced in the next section. [Read more] | Read more »
All the best games on sale for iPhone an...
Another week has flown by. Sometimes it feels like the only truly unstoppable thing is time. Time will make dust of us all. But before it does, we should probably play as many awesome mobile videogames as we can. Am I right, or am I right? [Read... | Read more »
The 7 best games that came out for iPhon...
Well, it's that time of the week. You know what I mean. You know exactly what I mean. It's the time of the week when we take a look at the best games that have landed on the App Store over the past seven days. And there are some real doozies here... | Read more »
Popular MMO Strategy game Lords Mobile i...
Delve into the crowded halls of the Play Store and you’ll find mobile fantasy strategy MMOs-a-plenty. One that’s kicking off the new year in style however is IGG’s Lords Mobile, which has beaten out the fierce competition to receive Google Play’s... | Read more »
Blocky Racing is a funky and fresh new k...
Blocky Racing has zoomed onto the App Store and Google Play this week, bringing with it plenty of classic kart racing shenanigans that will take you straight back to your childhood. If you’ve found yourself hooked on games like Mario Kart or Crash... | Read more »
Cytus II (Games)
Cytus II 1.0.1 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0.1 (iTunes) Description: "Cytus II" is a music rhythm game created by Rayark Games. It's our fourth rhythm game title, following the footsteps of three... | Read more »
JYDGE (Games)
JYDGE 1.0.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.0 (iTunes) Description: Build your JYDGE. Enter Edenbyrg. Get out alive. JYDGE is a lawful but awful roguehate top-down shooter where you get to build your... | Read more »
Tako Bubble guide - Tips and Tricks to S...
Tako Bubble is a pretty simple and fun puzzler, but the game can get downright devious with its puzzle design. If you insist on not paying for the game and want to manage your lives appropriately, check out these tips so you can avoid getting... | Read more »

Price Scanner via MacPrices.net

Deals on clearance 15″ Apple MacBook Pros wit...
B&H Photo has clearance 2016 15″ MacBook Pros available for up to $800 off original MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: – 15″ 2.7GHz Touch Bar MacBook Pro... Read more
Apple restocked Certified Refurbished 13″ Mac...
Apple has restocked a full line of Certified Refurbished 2017 13″ MacBook Airs starting at $849. An Apple one-year warranty is included with each MacBook, and shipping is free: – 13″ 1.8GHz/8GB/128GB... Read more
How to find the lowest prices on 2017 Apple M...
Apple has Certified Refurbished 13″ and 15″ 2017 MacBook Pros available for $200 to $420 off the cost of new models. Apple’s refurbished prices are the lowest available for each model from any... Read more
The lowest prices anywhere on Apple 12″ MacBo...
Apple has Certified Refurbished 2017 12″ Retina MacBooks available for $200-$240 off the cost of new models. Apple will include a standard one-year warranty with each MacBook, and shipping is free.... Read more
Apple now offering a full line of Certified R...
Apple is now offering Certified Refurbished 2017 10″ and 12″ iPad Pros for $100-$190 off MSRP, depending on the model. An Apple one-year warranty is included with each model, and shipping is free: –... Read more
27″ iMacs on sale for $100-$130 off MSRP, pay...
B&H Photo has 27″ iMacs on sale for $100-$130 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 27″ 3.8GHz iMac (MNED2LL/A): $2199 $100 off MSRP – 27″ 3.... Read more
2.8GHz Mac mini on sale for $899, $100 off MS...
B&H Photo has the 2.8GHz Mac mini (model number MGEQ2LL/A) on sale for $899 including free shipping plus NY & NJ sales tax only. Their price is $100 off MSRP. Read more
Apple offers Certified Refurbished iPad minis...
Apple has Certified Refurbished 128GB iPad minis available today for $339 including free shipping. Apple’s standard one-year warranty is included. Their price is $60 off MSRP. Read more
Amazon offers 13″ 256GB MacBook Air for $1049...
Amazon has the 13″ 1.8GHz/256B #Apple #MacBook Air on sale today for $150 off MSRP including free shipping: – 13″ 1.8GHz/256GB MacBook Air (MQD42LL/A): $1049.99, $150 off MSRP Read more
9.7-inch 2017 WiFi iPads on sale starting at...
B&H Photo has 9.7″ 2017 WiFi #Apple #iPads on sale for $30 off MSRP for a limited time. Shipping is free, and pay sales tax in NY & NJ only: – 32GB iPad WiFi: $299, $30 off – 128GB iPad WiFi... Read more

Jobs Board

AppleCare Support Engineer for *Apple* Medi...
# AppleCare Support Engineer for Apple Media Products Job Number: 113222855 Santa Clara Valley, California, United States Posted: 14-Nov-2017 Weekly Hours: 40.00 Read more
QA Automation Engineer, *Apple* Pay - Apple...
# QA Automation Engineer, Apple Pay Job Number: 113202642 Santa Clara Valley, California, United States Posted: 11-Dec-2017 Weekly Hours: 40.00 **Job Summary** At Read more
*Apple* Video Partnerships - Apple (United S...
# Apple Video Partnerships Job Number: 113059126 Santa Clara Valley, California, United States Posted: 15-Nov-2017 Weekly Hours: 40.00 **Job Summary** Partnerships Read more
Sr. Engineering Manager- *Apple* Media Produ...
# Sr. Engineering Manager- Apple Media Products Job Number: 113335268 Santa Clara Valley, California, United States Posted: 17-Jan-2018 Weekly Hours: 40.00 **Job Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.