def Szen3_recurrence(draw: ImageDraw, R: float, q: float, a: float, N: int): # Safety checks assert (N > 2), "N must be superior to 2" assert (q > 0 and q < 1), "q must be between 0 and 1 excluded" # Since we don't flip the image, the direct rotation is with # a negative sign a = -a # Induction variables # w1 and R1 center = R + 500j radius = R e = 1 # Constant part pre-computed to simplify calculations in the loop constant_part = ((q**-1) - 1) / (N - 2) factor = exp(1j * a) # Draw the first outer circle draw_circle(draw, center, R) # Find the center and radius of the next circles, and draw them for n in range(1, N): # Update the induction variables e *= factor radius *= q # Find the next center affix center += radius * e * constant_part * (2 * n - N) draw_circle(draw, center, radius)
def Szen1_explicit(draw : ImageDraw, R : float, q : float, N : int): # Safety checks assert (N > 2), "N must be superior to 2" assert (q > 0 and q < 1), "q must be between 0 and 1 excluded" # Induction variables qn_1 = q radius = R # Constant parts pre-computed to simplify calculations in the loop left_operand = R * ((q ** -1) - 1) / (N - 2) right_inner_coef = 1 / (1 - q) left_inner_coef = 2 * q * right_inner_coef * right_inner_coef right_inner_coef *= N # Save the first circle's computation (simpler this way) draw_circle(draw, R + 500j, R) # The explicit formula used here is slightly different : a "q" factor was # taken out to compute left_inner_coef for n in range(2, N + 1): # Update the induction variables radius *= q qn = qn_1 * q # Find the next center affix wn = R + left_operand * (left_inner_coef * (1 - n * qn_1 + qn * (n - 1)) - right_inner_coef * (q - qn)) qn_1 = qn draw_circle(draw, wn + 500j, radius)
def Szen2_explicit(draw: ImageDraw, R: float, q: float, a: float, N: int, show_convergence: bool = False): # Safety checks assert (N > 2), "N must be superior to 2" assert (q > 0 and q < 1), "q must be between 0 and 1 excluded" # Since we don't flip the image, the direct rotation is with # a negative sign a = -a # Induction variables qeian = 1 radius = R # Constant parts pre-computed to simplify calculations in the loop w1 = R + 500j qeia = q * exp(1j * a) const_part = R * qeia * ((q**-1) - 1) / (1 - qeia) # Save the first circle's computation (simpler this way) draw_circle(draw, R + 500j, R) for n in range(2, N + 1): # Update the induction variable qeian *= qeia radius *= q wn = w1 - const_part * (1 - qeian) draw_circle(draw, wn, radius) if show_convergence: draw_cross(draw, wn, color="#0000FF") if show_convergence: factor = exp(1j * a) draw_cross(draw, w1 - (R * q * factor * ((q**-1) - 1)) / (1 - q * factor))
def Szen3_explicit(draw: ImageDraw, R: float, q: float, a: float, N: int): # Safety checks assert (N > 2), "N must be superior to 2" assert (q > 0 and q < 1), "q must be between 0 and 1 excluded" # Since we don't flip the image, the direct rotation is with # a negative sign a = -a # Constant parts pre-computed to simplify calculations in the loop w1 = R + 500j qeia = q * exp(1j * a) Nqeia_2 = qeia * qeia const_num = 2 - N left_coef = R * ((q**-1) - 1) / (-const_num * ((1 - qeia)**2)) qeia_const_num = qeia * const_num right_const = N + 2 # Induction variables qeia_n = qeia qeia_nx1 = Nqeia_2 radius = R Nqeia_2 *= N draw_circle(draw, w1, radius) for n in range(2, N + 1): # Update the induction variables nx2 = 2 * n qeia_n = qeia_nx1 qeia_nx1 = qeia_n * qeia radius *= q # Find the next center affix wn = w1 + left_coef * (qeia_const_num + Nqeia_2 + qeia_n * (N - nx2) + qeia_nx1 * (nx2 - right_const)) draw_circle(draw, wn, radius)
def Szen2_recurrence(draw : ImageDraw, R : float, q : float, a : float, N : int, show_convergence : bool = False): # Safety checks assert (N > 2), "N must be superior to 2" assert (q > 0 and q < 1), "q must be between 0 and 1 excluded" # Since we don't flip the image, the direct rotation is with # a negative sign a = -a # Induction variables # w1 and R1 center = R + 500j radius = R e = 1 # Constant part pre-computed to simplify calculations in the loop constant_part = ((q ** -1) - 1) factor = exp(1j * a) # Draw the first outer circle draw_circle(draw, center, R) # Find the center and radius of the next circles, and draw them for n in range(1, N): # Update the induction variables e *= factor radius *= q # Find the next center affix center -= radius * constant_part * e draw_circle(draw, center, radius) if show_convergence: draw_cross(draw, center, color="#0000FF") if show_convergence: draw_cross(draw, (R + 500j) - (R * q * factor * constant_part) / (1 - q * factor))
def Szen1_recurrence(draw: ImageDraw, R: float, q: float, N: int): # Safety checks assert (N > 2), "N must be superior to 2" assert (q > 0 and q < 1), "q must be between 0 and 1 excluded" # w1 and R1 center = radius = R # Constant part pre-computed to simplify calculations in the loop constant_part = ((q**-1) - 1) / (N - 2) # Draw the first outer circle draw_circle(draw, center + 500j, R) # Find the center and radius of the next circles, and draw them for n in range(1, N): # Update the induction variables radius *= q # Find the next center affix center += radius * constant_part * (2 * n - N) draw_circle(draw, center + 500j, radius)