Guest User

Circle Packing

a guest
Jun 24th, 2020
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Like https://generativeartistry.com/tutorials/circle-packing/
  2. // but without the sillyness of iteratively growing by one unit
  3. // then checking for collision, as the maximum radius
  4. // allowed by borders or each other circles is already known.
  5.  
  6. var canvas = document.querySelector('canvas');
  7. var context = canvas.getContext('2d');
  8.  
  9. var size = window.innerWidth;
  10. var dpr = window.devicePixelRatio;
  11. canvas.width = size * dpr;
  12. canvas.height = size * dpr;
  13. context.scale(dpr, dpr);
  14.  
  15. context.lineWidth = 2;
  16.  
  17. var circles = [];
  18. var minRadius = 2;
  19. var maxRadius = size/2;
  20. var totalCircleAttempts = 500;
  21.  
  22. for( var i = 0; i < totalCircleAttempts; i++ ) {
  23.  
  24.   var newCircle;
  25.   var circleSafeToDraw;
  26.  
  27.   newCircle = {
  28.     x: Math.floor(Math.random() * size),
  29.     y: Math.floor(Math.random() * size),
  30.     radius: maxRadius
  31.   }
  32.  
  33.   // Check if new circle center spawned inside another
  34.   var isInside = false;
  35.   for(var i = 0; i < circles.length; i++) {
  36.     var otherCircle = circles[i];
  37.     var d = otherCircle.radius;
  38.     var x = newCircle.x - otherCircle.x;
  39.      var y = newCircle.y - otherCircle.y;
  40.      if (d*d >= (x*x) + (y*y)) {
  41.       isInside = true;
  42.       break;
  43.     }
  44.   }
  45.  
  46.   if(isInside) {
  47.     continue;
  48.   }
  49.  
  50.   // Reduce the radius if too close to an edge
  51.   if(newCircle.x - newCircle.radius <= 0)
  52.     newCircle.radius = newCircle.x;
  53.   if(newCircle.x + newCircle.radius >= size)
  54.     newCircle.radius = size - newCircle.x;
  55.   if(newCircle.y - newCircle.radius <= 0)
  56.     newCircle.radius = newCircle.y;
  57.   if(newCircle.y + newCircle.radius >= size)
  58.     newCircle.radius = size - newCircle.y;
  59.  
  60.   // Reduce the radius if too close to another circle
  61.   for(var i = 0; i < circles.length; i++) {
  62.     var otherCircle = circles[i];
  63.     var d = newCircle.radius + otherCircle.radius;
  64.     var x = newCircle.x - otherCircle.x;
  65.     var y = newCircle.y - otherCircle.y;
  66.     if (d*d >= (x*x) + (y*y)) {
  67.       newCircle.radius = Math.sqrt((x*x) + (y*y)) - otherCircle.radius;
  68.     }
  69.   }
  70.  
  71.   // Don't draw too small circles
  72.   if(newCircle.radius<minRadius) {
  73.     continue;
  74.   }
  75.  
  76.   // Draw the new circle
  77.   circles.push(newCircle);
  78.   context.beginPath();
  79.   context.arc(newCircle.x, newCircle.y, newCircle.radius, 0, 2*Math.PI);
  80.   context.stroke();
  81. }
Advertisement
Add Comment
Please, Sign In to add comment