*** GRAPHICS ROTATION (2D), by Alex Warren *********************************** Many people seem to want to know how to rotate 2D graphics, and in this article I'll show you how to do it using fairly simple trigonometry. An important rule for rotation is the following: In this rather bad ASCII-art circle of radius 1, point X is at (1,0) and O is the origin at (0,0): ***** ** | ** * | * *_____|O____X * | * * | * ** | ** ***** If we rotate X by A degrees/radians anticlockwise, trigonometry tells us that it will end up at point (COS(A),SIN(A)), which is how we rotate point X. This is fine if you just want to draw a circle without using the CIRCLE command perhaps, but it's a bit more complex if you want to use it for rotation. The following program will rotate any graphic or text that you put into it - the explanation of how it works comes after the program. Run it first though and see that it does indeed work. DEFINT A-Z CONST pi! = 3.141593 ' Define co-ordinates of box to rotate here, with (0,0) at the centre of the ' screen. BOXX1 = left co-or, BOXX2 = right co-or, BOXY1 = top co-or, ' BOXY2= bottom co-or, ie rectangle defined by (BOXX1, BOXY1)-(BOXX2, BOXY2) CONST BOXX1 = -12 CONST BOXX2 = 12 CONST BOXY1 = -12 CONST BOXY2 = 12 DIM r!(BOXX1 TO BOXX2, BOXY1 TO BOXY2) DIM a!(BOXX1 TO BOXX2, BOXY1 TO BOXY2) DIM p(BOXX1 TO BOXX2, BOXY1 TO BOXY2) FOR x = BOXX1 TO BOXX2 FOR y = BOXY1 TO BOXY2 r!(x, y) = SQR((x ^ 2) + (y ^ 2)) IF x < 0 THEN r!(x, y) = -r!(x, y) IF x = 0 THEN a!(x, y) = (pi / 4) ELSE a!(x, y) = ATN(y / x) NEXT y NEXT x SCREEN 7 WINDOW (-160, 100)-(160, -100) ' We set the co-ordinate system of the screen so ' that the point (0,0) is in the centre of the ' screen. ' *** INSERT DRAWING CODE HERE, ETC. *** LINE (-12, 12)-(12, -12), 15, B LINE (-11, 11)-(11, -11), 12, B LINE (-12, 12)-(12, -12), 13 LINE (-12, -12)-(12, 12), 14 ' *** END OF DRAWING CODE *** FOR x = BOXX1 TO BOXX2 FOR y = BOXY1 TO BOXY2 p(x, y) = POINT(x, y) NEXT y NEXT x a$ = INPUT$(1) ' Rotation code here. Note that angles are in RADIANS where 2ã rads=360ø ' (Characters in above comment may show incorrectly under Windows, it should ' read 2pi rads=360 degrees) curpage = 0 DO FOR angle! = 0 TO 2 * pi! STEP .1 SCREEN 7, , curpage, 1 - curpage CLS FOR x = BOXX1 TO BOXX2 FOR y = BOXY1 TO BOXY2 newx = COS(angle! + a!(x, y)) * r!(x, y) newy = SIN(angle! + a!(x, y)) * r!(x, y) PSET (newx, newy), p(x, y) NEXT y NEXT x curpage = 1 - curpage NEXT angle! LOOP UNTIL INKEY$ = CHR$(27) So how does this program use the above rule to rotate graphics? Well, it has to split up the entire graphic into circles and work out the angle of each point subtended at the centre of the circle. Sounds complicated? OK, here it is another way, using an example point P. The point (0,0) is O. | P | _______|O______ | | The co-ordinates of point P are (-4,2) in this example. We can work out which circle P is in by finding the distance between P and the point O (hence the radius of the circle). We can do this using Pythagoras' Theorem, which will tell us that the radius of the circle R is SQR((X^2)+(Y^2)). Next we need to work out P's angle in its circle, otherwise all points in the same circle would end up being plotted to the same point. We can work out P's angle using a!(x, y) = ATN(y / x). The function ATN in BASIC returns the inverse TAN, ie the same result as pressing ------- | -1| |tan | ------- on a calculator. This will tell us the angle "A" of the point "P", in radians: P \ \ \A ------ (1,0) So we work out the values R (radius) and A (angle) of each point BEFORE we rotate, and then we can use them during our rotation loop, like this: newx = COS(angle! + a!(x, y)) * r!(x, y) newy = SIN(angle! + a!(x, y)) * r!(x, y) This uses the (COS(A),SIN(A)) rule above, with A being the angle of rotation added to the angle of the point P. The co-ordinate obtained is then multiplied by the radius of P's circle. We then work out the values of newx and newy for each point in our rotation area, and plot newx and newy. We can use a FOR loop or similar to animate the rotation, as in the program above. -------------------------------------------------------- * EDITOR'S NOTE: * This article was originally printed in Peter Cooper's BASIX Fanzine, * Issue #9 from October 1997. This issue was edited by Alex Warren.