JSFiddle - React, Tailwind, and code Playground

by cristiscu

HTML

<canvas id='canvas' width='400' height='500'></canvas>

CSS

canvas { background-color: #ddd; }

JavaScript

// ===========================
// ancillary geometric classes
// ===========================
var Point = function (x, y)
{
    this.x = x;
    this.y = y;
}

Point.prototype = {
    dist: function (p) { return this.vect(p).norm(); },
    vect: function (p) { return new Point (p.x-this.x, p.y-this.y); },
    norm: function () { return Math.sqrt (this.x*this.x+this.y*this.y);},
    add : function (v) { return new Point (this.x + v.x, this.y + v.y);},
    mult: function (a) { return new Point (this.x * a, this.y * a);}
};
var Circle = function (radius, center)
{
    this.r = radius;
    this.c = center;
};

Circle.prototype = {
    surface:  function () { return Math.PI * this.r * this.r; },
    distance: function (circle) { return this.c.dist(circle.c) - this.r - circle.r; }
};


// =========================
// circle packer lives here!
// =========================
var Packer = function (circles, ratio)
{
    this.circles = circles;
    this.ratio   = ratio;
    this.list = this.solve();
}

Packer.prototype = {
    // find the smallest rectangle to fit all circles
    solve: function ()
    {
        var res = [];

// compute total surface of the circles
        var surface = 0;
        for (var i = 0 ; i < this.circles.length ; i++)
            surface += Math.PI * Math.pow(this.circles[i],2);
        
        // set a suitable precision
        var limit = surface/1000;
        for (var i = surface/2; i > limit; i /= 2)
        {
            var placement = this.compute(surface);
						console.log(i
                + ": placed " + placement.length
            		+ " out of " + this.circles.length
            		+ " for surface " + surface);
                
            if (placement.length != this.circles.length)
                surface += i;
            else
            {
                res = placement;
                this.bounds = this.tmp_bounds;
                surface -= i;
            }
        }
        return res; 
    },

  // check if a circle is inside...