Context Free Art

Tutorials/Rotating by a random angle

From Context Free Art

Jump to: navigation, search

Rotating by a random angle

Suppose you want to draw a shape rotated by a random angle -- let's say specifically by a random integer from 0 to 359. One approach would be to define 360 rules, each of which rotates the shape by a different angle:

rule RandomRotate { MyShape { } }
rule RandomRotate { MyShape { r 1 } }
rule RandomRotate { MyShape { r 2 } }
rule RandomRotate { MyShape { r 3 } }
rule RandomRotate { MyShape { r 4 } }
              /*
               *
               */
rule RandomRotate { MyShape { r 359 } }

That's a lot of rules to enter for just one effect! Fortunately, there's a better approach, based on the concept of a Search tree. The idea is first to rotate either not at all or by half a circle (i.e., either 0 or 180 degrees), then to rotate the result either not at all or by a quarter of a circle (i.e., either 0 or 90 degrees), then to rotate the result either not at all or by an eighth of a circle (i.e., either 0 or 45 degrees). At this point, we've rotated by one of 0, 45, 90, 135, 180, 225, 270, or 315 degrees -- eight possible angles from only six rules. So far, so good.

If we divide by two again we're going to start seeing non-integer angles. However, nothing says we have to keep dividing by two. For the next rotation we can rotate by one of {0, 15, 30} degrees, giving us any of 24 possible angles as illustrated below:

Selecting one of 24 angles

The last steps are to rotate by one of {0, 5, 10} degrees and finally by one of {0, 1, 2, 3, 4} degrees. In the end, it takes only 18 rules to rotate a shape by any of 360 unique angles! The rotation is also very fast: only seven rules are actually executed no matter what angle is finally chosen.

Here's a sample picture that demonstrates the preceding technique:

startshape Begin
 
background { h 200 sat 1 b 1 }
 
rule DrawArrow {
  SQUARE { x 0.5 size 1 0.075 }
  TRIANGLE { x 1 r 30 size 0.2 }
}
 
rule RandomRotate1 { RandomRotate2 { } }
rule RandomRotate1 { RandomRotate2 { r 180 } }
rule RandomRotate2 { RandomRotate3 { } }
rule RandomRotate2 { RandomRotate3 { r 90 } }
rule RandomRotate3 { RandomRotate4 { } }
rule RandomRotate3 { RandomRotate4 { r 45 } }
rule RandomRotate4 { RandomRotate5 { } }
rule RandomRotate4 { RandomRotate5 { r 15 } }
rule RandomRotate4 { RandomRotate5 { r 30 } }
rule RandomRotate5 { RandomRotate6 { } }
rule RandomRotate5 { RandomRotate6 { r 5 } }
rule RandomRotate5 { RandomRotate6 { r 10 } }
rule RandomRotate6 { RandomRotate7 { } }
rule RandomRotate6 { RandomRotate7 { r 1 } }
rule RandomRotate6 { RandomRotate7 { r 2 } }
rule RandomRotate6 { RandomRotate7 { r 3 } }
rule RandomRotate6 { RandomRotate7 { r 4 } }
rule RandomRotate7 { DrawArrow { } }
 
rule DrawRandomArrows { 30*{ b -0.05 z 1 } RandomRotate1 { } }
 
rule Begin { DrawRandomArrows { h 240 sat 1 b 1 } }

Arrows drawn at random angles

Note that this technique applies just as well to selecting random colors, random distances, random tower heights, etc. as it does to random angles.

The advantages of the binary-search technique over something like

rule RandomMove 99 { RandomMove { x 1 } }
rule RandomMove  1 { MyShape { } }

are

The only real disadvantage is code length.

Views
Personal tools
Navigation
Toolbox
MediaWiki
Attribution-Share Alike 2.5
book coverSee our book:
Community of Variation