Chaos Game fractal not rendering correctly

120 views Asked by At

I'm attempting to write code that will generate fractals according to the Chaos game

In particular, I'm trying to debug the faulty generation/rendering of this fractal:

enter image description here

I'm doing this with Javascript in a Canvas element. The relevant Javascript is below:

canvas = document.getElementById('myCanvas');
context = canvas.getContext('2d');

//constants
border = 10  //cardinal distance between vertices and nearest edge(s)

class Point{
  constructor(_x, _y){
    this.x = _x;
    this.y = _y;
  }
}

vertices = []
secondLastVertex = 0;
lastVertex = 0;

//vertices in clockwise order (for ease of checking adjacency)
vertices.push(new Point(canvas.width / 2, border));  //top
vertices.push(new Point(canvas.width - border, canvas.height * Math.tan(36 * Math.PI / 180) / 2));  //upper right
vertices.push(new Point(canvas.width * Math.cos(36 * Math.PI / 180), canvas.height - border));  //lower right
vertices.push(new Point(canvas.width * (1 - (Math.cos(36 * Math.PI / 180))), canvas.height - border));  //lower left
vertices.push(new Point(border, canvas.height * Math.tan(36 * Math.PI / 180) / 2));  //upper left

//move half distance towards random vertex but it can't neighbor the last one IF the last two were the same
function updatePoint(){
  //pick a random vertex
  v = Math.floor(Math.random() * vertices.length);

  if(lastVertex == secondLastVertex)
    //while randomly selected vertex is adjacent to the last approached vertex
    while((v == (lastVertex - 1) % 5) || (v == (lastVertex + 1) % 5))
      //pick another random vertex
      v = Math.floor(Math.random() * vertices.length);

  //cycle the last two vertices
  secondLastVertex = lastVertex;
  lastVertex = v;

  //move half way towards the chosen vertex
  point.x = (vertices[v].x + point.x) / 2;
  point.y = (vertices[v].y + point.y) / 2;
}

//starting point (doesn't matter where)
point = new Point(canvas.width / 2, canvas.height / 2);

for (var i = 0; i < 1000000; i++){
  //get point's next location
  updatePoint();
  
  //draw the point
  context.fillRect(Math.round(point.x), Math.round(point.y), 1, 1);
}

The rendering that is produced looks like this:

enter image description here

So far I haven't been able to determine what is causing the rendering to be so skewed and wrong. One possibility is that I've misunderstood the rules that generate this fractal (i.e. "move half the distance from the current position towards a random vertex that is not adjacent to the last vertex IF the last two vertices were the same")

Another is that I have some bug in how I'm drawing fractals. But the same code with rule/starting-vertex modifications is able to draw things like the Sierpinkski triangle/carpet and even other pentagonal fractals apparently perfectly. Though one other pentagonal fractal ended up with some weird skewing and "lower right fourth of each self-similar substructure" weirdness.

I tried making some slight modifications to how I interpreted the rules (e.g. "next vertex can't be adjacent OR EQUAL TO previous vertex if last two vertices were the same") but nothing like that helped. I also tried not rounding the coordinates of the target point before plotting it, but though this slightly changed the character/sharpness of the details, it didn't change any larger scale features of the plot.

1

There are 1 answers

0
David Bandel On BEST ANSWER

My issue as kindly pointed out by ggorlen, was that I wasn't comparing vertices for adjacency correctly. I mistakenly thought Javascript evaluated something like (-1 % 5) as 4, rather than -1.

To fix this, I add 4 to the index instead of subtracting 1, before modding it against 5 (the number of vertices)

This completely fixed the render. (in not just this case but other cases I'd been testing with different fractals)