# Polar Rose in Julia

### Background

I’m doing exercise 4.9 of Think Julia, which asks for a function for a polar rose using Luxor’s turtle graphics.

### Difficulties

1. Work out the geometric structure of the family of polar roses. The key is to construct some auxiliary isoceles triangles and work out the angles between them. One sees that they are parametrized by two varaibles n and k.
• n: number of petals
• k: petal increment
• constraint: k ≠ n ÷ 2
2. Handle the case when gcd(n, k) > 1, i.e. more than one closed loop.
3. The positive x direction goes to the right; the positive y direction goes down.

### Attempt

1. Use ThinkJulia.Reposition(t::Turtle, x, y) to reposition the turtle.
2. Use turn(t::Turtle, θ) to turn t
3. Use ThinkJulia.Orientation(t::Turtle, θ) to restore the turtle’s orientation after the move.

### Code

I spend three days writing and testing this function.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54  if !(@isdefined polyline) || !(typeof(polyline) <: Function) include("polyline.jl") println("loaded polyline.jl") end """ polar_rose(t, n, k, r) Draws a polar rose with the given radius and step: t: turtle n: number of petals k: petal increment (k < n/2) r: radius """ function polar_rose(t, n, k, r) t0_x, t0_y, t0_θ = t.xpos, t.ypos, t.orientation # store orig pos & orient if k == n / 2 # input checking error("k == n ÷ 2 impossible !") return else reduced_k = k > n / 2 ? n - k : k end step_angle_radian, step_angle_deg = 2 * π * reduced_k / n, 360 * reduced_k / n arc_radius = r / (2 * cos(step_angle_radian / 2)) arc_angle = 360 - 2 * step_angle_deg # Handles the case when gcd(reduced_k,n) > 1 num_loop = gcd(reduced_k,n) num_arc = n ÷ num_loop angular_sep_radian, angular_sep_deg = 2 * π / n, 360 / n # At (0,0), circle(t, r) always draw circle centered at (0,r) with r < 0 center_x = t0_x + r * cos(-(π - step_angle_radian) / 2) center_y = t0_y + r * sin(-(π - step_angle_radian) / 2) for j in 1:num_loop t_x = t0_x+center_x+r*cos(angular_sep_radian*(j-1)+(π+step_angle_radian)/2) t_y = t0_y+center_y+r*sin(angular_sep_radian*(j-1)+(π+step_angle_radian)/2) ThinkJulia.Reposition(t, t_x, t_y) if j > 1 turn(t, angular_sep_deg * (j - 1)) end for i in 1:num_arc arc(t, arc_radius, arc_angle) turn(t, -step_angle_deg) end end ThinkJulia.Reposition(t, t0_x, t0_y) # restore orig pos ThinkJulia.Orientation(t, t0_θ) # restore orig orient end 

To test this function, one can issue a few lines.

include("polar_rose.jl"); 🐢 = Turtle();
@svg begin
polar_rose(🐢, 8, 3, 100)
end


### Solution

The book’s solution is much simpler than mine. I’ve overthought this problem by thinking about the “petal increment”, concentric petal curves and closed loops. The author simply draws one single petal with an auxiliary function petal (t::Turtle, r, angle), which is a simple for loop.

function petal(t, r, angle)
for i in 1:2
arc(t, r, angle)
turn(t, angle-180)
end
end


The logic behind this loop is that arc(t::Turtle, r, angle) turns t’s orientation by -angle degrees due to the line turn(t, -angle) in the function polyline(t::Turtle, n, len, angle) called by arc(t, r, angle).

function polyline(t, n, len, angle)
for i in 1:n
forward(t, len)
turn(t, -angle)
end
end


N.B.: Since the y-axis is inverted in Luxor, so as the sign of an angle.

### No comment

Your email address will not be published. Required fields are marked *.