Adventures in Rotation

Alex Tweedly alex at tweedly.net
Sun Dec 4 20:04:55 EST 2005


Bill Marriott wrote:

>Ok, as our regular viewers know, I'm trying to mimic with Rev a pretty 
>little clock distributed with Konfabulator. The way K. does this clock is to 
>create little PNGs for each of the elements (second hand, minute hand, rim, 
>background), package them up in XML, and animate (rotate) them in 
>JavaScript.
>
>Attempt 4 (revised): revRotatePoly an irregular polygon
>
>So, I drew myself a pretty minute hand and then wrote a script.
>
>Code used:
>
>on mouseUp
>    repeat with i = 1 to 360
>        revRotatePoly the long ID of graphic "minuteHand",1
>        wait for 50 milliseconds
>    end repeat
>end mouseUp
>
>(I know the "wait for" method was not what I was going to use in my eventual 
>stack, for performance reasons, but I just wanted to test out spinning it.)
>
>Well, running this script was a shocker. It had the effect of crumpling my 
>pretty minute hand into a little ball. If you'd like to see what happens, go 
>to revOnline under my space, "MerryOtter" -- the stack is, "Fun with 
>revRotatePoly"
>
>  
>
I rather like that effect - though it certainly shouldn't be called 
"rotate" :-)

>My clock hand *is* pretty fancy, it's got 56 points. But the same thing 
>happens with graphics of only 3 points. Open the stack and try the simplest 
>kind of clock hand you could imagine with
><snip>
>  
>

>#13) General flakiness. I would definitely say revCrumplePoly is a better 
>name for the revRotatePoly command. Is there any situation where 
>revRotatePoly could be useful? Not if it does this. Totally bugged. (I 
>suspect the reason why is that Rev doesn't have fractional coordinates? 
>Could such a limitation really result in such dramatic distortion? If this 
>is the case, then Rev should store fractionals, but render to integers.)
>
>  
>
I think your suspicion is entirely correct. I think it would be 
generally very helpful if Rev would allow non-integer co-ords in the 
points list, and simply round to integers before drawing.

I change the code to

>     put the points of grc "minuteHand" into tPoints
>     repeat with i = 1 to 360
>         set the lockScreen to true
>         set the points of grc "minuteHand" to tPoints     
>         revRotatePoly the long ID of graphic "minuteHand", i    -- 
> note the change from "1" to "i" here
>         set the lockScreen to false
>         set the thumbposition of scrollbar "spinProgress" to i
>         wait for 50 milliseconds
>     end repeat

and it now does what it's intended to do. Though I really dislike what 
it's intended to do - rotate the object, then translate it so as to keep 
the top left of the bounding rectangle of the rotated shape the same.

We had a thread on rotating polygons back in March (to save you cracking 
out the trig books), here is the code modified to use the rotate handler 
I suggested then. Note this is written to emphasize readability rather 
than performance - could probably be made faster if needed.

> on mouseUp
>   put the points of grc "minuteHand" into tPoints
>   repeat with i = 1 to 360
>     set the lockScreen to true
>     set the points of grc "minuteHand" to tPoints     
>     myRotatePoly the name of grc "minuteHand", i, 0, 24
>     -- revRotatePoly the long ID of graphic "minuteHand", i
>     set the lockScreen to false
>     set the thumbposition of scrollbar "spinProgress" to i
>     wait for 50 milliseconds with messages
>   end repeat
>   set the points of grc "minuteHand" to tPoints     
> end mouseUp
>
> on myRotatePoly pGraphic, pAngle, basex, basey
>     put the topLeft of pGraphic into tTopLeft
>     put myPoints(pGraphic, basex, basey) into tPoints    -- returns 
> the list of points, relative to the base point
>     put the loc of pGraphic into tLoc
>     put sin(pAngle * (pi / 180)) into tSinAngle
>     put cos(pAngle * (pi / 180)) into tCosAngle
>     put (number of items of tPoints) div 2 into tNumItems
>     repeat with i = 1 to tNumItems
>         put (item (i + (i - 1)) of tPoints) into tCurrentH -- + item 1 
> of the center
>         put (item (i + i) of tPoints) into tCurrentV -- + item 2 of 
> the center
>         put trunc((tCosAngle * tCurrentH) - (tSinAngle * tCurrentV)) 
> into tTempH
>         put trunc((tSinAngle * tCurrentH) + (tCosAngle * tCurrentV)) 
> into tTempV
>         put tTempH + basex into tCurrentH     -- and add back the base 
> x and y
>         put tTempV + basey into tCurrentV
>         put tCurrentH,tCurrentV & comma after tFinalPoints
>     end repeat
>     delete last char of tFinalPoints
>     set the points of pGraphic to tFinalPoints
> end myRotatePoly
>
> function myPoints pGraphic, basex, basey
>     put the number of lines in the points of pGraphic into tNumPoints
>     put empty into tResult
>     put the points of pGraphic into tPoints
>     put basex into tStartlH
>     put basey into tStartV
>      
>     replace cr with comma in tPoints
>     if last char of tPoints is comma then delete last char of tPoints
>     repeat with i = 1 to tNumPoints
>         put (item (i + (i - 1)) of tPoints) - tStartlH into tCurrentH
>         put (item (i + i) of tPoints) - tStartV into tCurrentV
>         put tCurrentH,tCurrentV & comma after tResult
>     end repeat
>     delete last char of tResult
>     return tResult
> end myPoints


-- 
Alex Tweedly       http://www.tweedly.net



-- 
No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.1.362 / Virus Database: 267.13.11/191 - Release Date: 02/12/2005




More information about the use-livecode mailing list