All right, this is great information. I need to sit down and work through it with my SVG Matrix algebra examples in front of me. I do have a couple of questions: - Assuming I already have the center poitns, I could derive all the values I wanted right? The rotate(t, x, y) command is a shortcut for translation if I remember right. It's short for translate(x,y) rotate(t) translate(-x,-y) isn't it? Would I have to take that into account? - Does the order matter? In the app, you can scale, rotate, and translate in any order. Michael Bishop ________________________________ From: Andrew Plotkin [mailto:erkyrath@eblong.com] Sent: Thu 6/1/2006 12:27 PM To: batik-users@xmlgraphics.apache.org Subject: RE: Extracting information from a transformation matrix On Thu, 1 Jun 2006, Bishop, Michael W. CONTR J9C880 wrote: > Wow, this is going to make me take another close look at the transformation matrix for SVG. Let's start with an example: > > transform="translate(x, y) scale(sx, sy) rotate(t, cx, cy)" > > The above is the only kind of transform I maintain in my application. > > If the user drags an element around the screen, it directly affects > translate. > If the user scales the element, it affects scale which indirectly > affects translate. > If the user rotates the element, I believe it affects scale which also > affects translate. > > What I want to do is be able to break apart the above to find out the > values I wanted before. The first thing I need to go is get a > representation of the above into the matrix values (a, b, c, d, e, f). Ok, let's work through it. Here is a simple routine that gets the transform of an object relative to its parent: function dump(id) { var el = document.getElementById(id); var parent = el.parentNode; var matrix = el.getTransformToElement(parent); alert(matrix.a + " " + matrix.c + " " + matrix.e + "\n" + matrix.b + " " + matrix.d + " " + matrix.f); } Some samples, in the standard format: a c e b d f 1 0 0 0 1 0 1 0 4 0 1 4 3 0 0 0 3 0 0.5 -0.8660253882408142 0 0.8660253882408142 0.5 0 (Note that 0.8660253882408142 is sqrt(3)/2, or sin(60). 0.5 is cos(60). Now you know where those numbers come from.) So an object with a translate+scale+rotate: 1.5 -2.598076105117798 4 2.598076105117798 1.5 4 Now this is easy to undo. We're going to pull the transforms off in forwards order (the *same* order they're listed in the transform attribute.) Translate is the (e,f) values directly: translate = (4,4). Now remove this by setting e and f to zero: 1.5 -2.598076105117798 0 2.598076105117798 1.5 0 The scale is the magnitude of (a,b). Or (c,d) or (a,c) -- all the same. Pythagorean theorem: scale = sqrt(1.5*1.5 + -2.598076105117798*-2.598076105117798) = 3 Now remove this by dividing each element of the matrix by 3: 0.5 -0.8660253882408142 0 0.8660253882408142 0.5 0 What's left is the pure rotation -- you can see it's the same as the "rot" matrix above. To get the angle out, you'll want to use an atan2 function; in Javascript this is Math.atan2. The result of that is radians, so we also have to convert to degrees: rotate = atan2(b,a) * 180 / 3.1415926 = 60 Now, the rotation in this example is a rotation around the origin. You asked about the more complex rotation "rotate(t, cx, cy)". Unfortunately, there's no way to get that information! If we consider the object and apply the above procedure, you'll get the result: translate=(10.69615268,4.401909828) scale=3 rotate=60 Or, if you like, The problem is, this is the right answer! These two transforms produce the *same* matrix -- the same a,b,c,d,e,f values. And there are an infinite other number of "translate(x, y) scale(sx, sy) rotate(t, cx, cy)" transforms that produce that matrix. To get a single solution, you *have* to assume that cx and cy are zero. Otherwise you're trying to get seven unknowns out of six variables, which is impossible. (If you assume cx and cy are zero, you get five unknowns out of six variable. The sixth unknown is skew, or stretching on an axis; the procedure above assumes there's none of that either.) --Z -- "And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..." * If the Bush administration hasn't shipped you to Syria for interrogation, it's for one reason: they don't feel like it. Not because you're patriotic. --------------------------------------------------------------------- To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org