Search code examples
rggplot2alignmentvisualizationfibonacci

Correcting the Alignment of Fibonacci Squares for a Proper Spiral Formation in R


I'm working on creating a Fibonacci spiral with squares in R. I have successfully generated the Fibonacci sequence and plotted squares, but the alignment isn't correct. The first square is not centered properly, causing issues with the spiral formation.

Here’s the R code I’ve used so far:

# Install ggplot2 if not already installed
install.packages("ggplot2")

# Load ggplot2
library(ggplot2)

# Define a function to generate Fibonacci numbers
fibonacci <- function(n) {
  fib_seq <- numeric(n)
  fib_seq[1] <- 1
  fib_seq[2] <- 1
  for (i in 3:n) {
    fib_seq[i] <- fib_seq[i-1] + fib_seq[i-2]
  }
  return(fib_seq)
}

# Generate the first 10 Fibonacci numbers
fib_seq <- fibonacci(10)

# Initialize the data frame
squares <- data.frame(x = numeric(10), y = numeric(10), size = fib_seq)

# Set the initial position
squares[1,] <- c(0, 0, fib_seq[1])
squares[2,] <- c(fib_seq[1], 0, fib_seq[2])

# Compute the coordinates for the rest of the squares
for (i in 3:10) {
  if (i %% 2 == 1) {
    # Odd index: Square goes above or below
    squares[i, "x"] <- squares[i-2, "x"]
    squares[i, "y"] <- squares[i-1, "y"] + squares[i-1, "size"]
  } else {
    # Even index: Square goes left or right
    squares[i, "x"] <- squares[i-1, "x"] + squares[i-1, "size"]
    squares[i, "y"] <- squares[i-2, "y"]
  }
}

# Plot the squares using ggplot2
ggplot(data = squares, aes(xmin = x, ymin = y, xmax = x + size, ymax = y + size)) +
  geom_rect(fill = "white", color = "black") + # Square boundaries
  coord_fixed(ratio = 1) + # Maintain aspect ratio
  theme_void() # Remove axis labels and grid lines

The problem is that the placement of the first two squares is not centered, causing misalignment with the Fibonacci spiral. I need the squares to be positioned such that:

  • The first two squares are horizontally aligned.
  • The subsequent squares are placed below, to the right, above, and to the left in the Fibonacci sequence order.

How can I correct the positioning of these squares to ensure that they align properly with the spiral?

This image is my target!


Solution

  • I added two more directions to the code - and the arcs

    # Define a function to generate Fibonacci numbers
    fibonacci <- function(n) {
      fib_seq <- numeric(n)
      fib_seq[1] <- 1
      fib_seq[2] <- 1
      for (i in 3:n) {
        fib_seq[i] <- fib_seq[i-1] + fib_seq[i-2]
      }
      return(fib_seq)
    }
    
    # Generate the first 10 Fibonacci numbers
    fib_seq <- fibonacci(10)
    
    # Initialize the data frame
    squares <- data.frame(x = numeric(10), y = numeric(10), size = fib_seq)
    
    # Set the initial position and direction
    x <- 0
    y <- 0
    direction <- 1 
    
    for (i in 1:10) {
      if (direction == 1) {
        y <- y - ifelse(x == 0, 0, fib_seq[i])
        squares[i, "x"] <- x
        squares[i, "y"] <- y
      } else if (direction == 2) {
        x <- x + fib_seq[i-1]
        y <- y 
        squares[i, "x"] <- x
        squares[i, "y"] <- y
      } else if (direction == 3) {
        x <- x - fib_seq[i-2]
        y <- y + fib_seq[i-1]
        squares[i, "x"] <- x
        squares[i, "y"] <- y
      } else if (direction == 4) {
        x <- x - fib_seq[i]
        y <- y - fib_seq[i-2]
        squares[i, "x"] <- x
        squares[i, "y"] <- y
      }
    
      # Update the direction
      direction <- (direction %% 4) + 1
    }
    
    # Function to generate quarter circle arc data
    quarter_circle_arc <- function(x, y, size, direction) {
      theta <- seq(0, pi/2, length.out = 100)
      if (direction == 1) {
        # Bottom-left arc
        data.frame(
          x = x + size * (1 - cos(theta)),
          y = y + size * (1 - sin(theta))
        )
      } else if (direction == 2) {
        # Bottom-right arc
        data.frame(
          x = x + size * ( sin(theta)-1) + size,
          y = y + size * (1-cos(theta))
        )
      } else if (direction == 3) {
        # Top-right arc
        data.frame(
          x = x + size * (cos(theta) - 1) + size,
          y = y + size * (sin(theta) - 1) + size
        )
      } else if (direction == 0) {
        # Top-left arc
        data.frame(
          x = x + size * (1- sin(theta)),
          y = y + size * (cos(theta)-1) + size
        )
      }
    }
    
    # Plot the squares and quarter circle arcs
    ggplot() +
      # Plot squares
      geom_rect(data = squares, aes(xmin = x, ymin = y, xmax = x + size, ymax = y + size), 
            fill = "white", color = "black") +
      # Plot quarter circle arcs
      geom_path(data = do.call(rbind, lapply(1:10, function(i) {
        quarter_circle_arc(squares$x[i], squares$y[i], squares$size[i], direction = (i %% 4) )
      })), 
      aes(x = x, y = y), color = "black") +
      #coord_fixed(ratio = 1) +
      theme_void()