Random Circles in a Circle

Started by
13 comments, last by brucedjones 8 years, 3 months ago

So I basically want to create 5 sizes of circles randomly generated and placed in a circle around a point (the radius being 500 units) and I want to do this with javascript and jpgs.

Normally what I'd do is create a table and then just randomly fill it with imgs of say 5px, but the differing sizes are giving me a problem on how to solve this, because if I create a table of 5px imgs 200 cells wide & high and have the sizes represented in colors I know I would get overlap which I don't want.

Another solution that doesn't sound so good would be to instead of printing right to the web page put the 5px chunks in an array and then when I come across a size that takes up multiple cells add the chunks in the other rows, and then when I come to those columns in the array have it detect and jump over them, but that seems a bit of a mess.

Another possible idea that I just thought of is set a number of circles to be generated.

Generate the circle sizes.

Then for each size place the chunks in the cells.

check if cell and surrounding cells are filled

If a cell is filled with a circle chunk already, re-roll until the piece is placed...

Though thinking that through it comes to mind that that might generate the problem of never being able to find a place to fill and then going into an infinite loop

Is there a better solution than any of those?

Advertisement

It's not clear to me what you're trying to do, could you elaborate on what problem you're trying to solve?

I want to produce an image that is 1000x1000 px wide

Inside this image I want there to be a circular area with a 1000px diameter

Inside this area I want around 4000 (current working number) shapes with widths of 5px, 10px, 20px, 40px, and 80px and each of these circles being at least 10px away from any other shape, though I'm primarily thinking of circles, squares, and hexes...though the different shapes aren't that important.

Also I want the center to be empty as well (i don't know how large the center is currently. I need to see how this looks before i decide and adjust it)

Also I need to be able adjust the frequency of those sizes and edit the color of the circles to indicate anothe attribute. (For example a 5px circle can be red, blue, green, orange, etc, based another attribute that i can change the frequency of)

This sounds completely wierd, but that's what I need.

I don't think what it is for is important so I'll leave that out, but it's just the first step in what I'm doing.

Sounds like you need something like a Poisson disc sample set: https://www.jasondavies.com/poisson-disc/

This can be used to distribute sample points with a minimal distance within a boundary.

Mitchell's Best Candidate algorithm might also work well: http://bl.ocks.org/mbostock/1893974

Ok I figured out a bunch of how to do this...

Create the first circle with x/y coordinate, and size. Throw it in an Array

With each new circle test it against the whole array

If the circle fails reroll, if it passes add it to the array

When the Array has x number of members draw all the circles

To create the circles i'll use canvas

And for the check, this tut seems perfect for what i need. http://gamedevelopment.tutsplus.com/tutorials/when-worlds-collide-simulating-circle-circle-collisions--gamedev-769

The only problem I think I now have (besides brain not working right right now problems which is why I'm not writing all that up right this second) is that I want all these circles to be within a certain radius of the center... I think I could use that tutorial and reverse the detection to see if the circle is inside another circle, but I'm not sure.

Sounds like you need something like a Poisson disc sample set: https://www.jasondavies.com/poisson-disc/

This can be used to distribute sample points with a minimal distance within a boundary.

Mitchell's Best Candidate algorithm might also work well: http://bl.ocks.org/mbostock/1893974

The first link I can't find the sample... but both the first and second aren't doing quite what I want and the code on the second one I don't feel like figuring out ^.^ for something that seems to be doing something different than what i want, but similar... but different enough to not quite useful.

Thanks though...those scripts look interesting.

The only problem I think I now have (besides brain not working right right now problems which is why I'm not writing all that up right this second) is that I want all these circles to be within a certain radius of the center... I think I could use that tutorial and reverse the detection to see if the circle is inside another circle, but I'm not sure.

Just generate by angle/radius instead of x/y:


angle = random(0, PI*2)
distanceFromCenter = random(minimalDistanceFromCenter + newCircleRadius, maximalDistanceFromCenter - newCircleRadius)
newCirclePositionX = centerX + cos(angle) * distanceFromCenter
newCirclePositionY = centerY + sin(angle) * distanceFromCenter

Here's what I got so far...

The multidimensional array after the do while loop seems to be messing up and I don't know why.

-----

edit: got some help in the chat... fixed it a little bit, now it gets to 4th itteration and then breaks at the same spot rather than not going through even once.

edit2: Figured out the array thing... now the overlapCheck function isn't working...


<html>
<body>
<canvas id="myCanvas" width="1000" height="1000" style="border:3px solid #c3c3c3;">
It appears that your browser does not support HTML5 and the canvas element.
</canvas>

<script type="text/javascript">
function drawCircle(x,y,r,color) {
    color.beginPath();
    color.arc(x,y,r,0,Math.PI*2,true);
    color.closePath();
    color.fill();
}

function getColor() {
var hexColor = "#000000";
return hexColor.toUpperCase();
}


function overlapCheck(x,y,radius) {
for(var i=1; i<4000; i++) {

if (x + radius + Circle[i][2] > Circle[i][0] 
&& x < Circle[i][0] + radius + Circle[i][2]
&& y + radius + Circle[i][2] > Circle[i][1] 
&& y < Circle[i][1] + radius + Circle[i][2])
{
//AABBs are overlapping

distance = Math.sqrt(
            ((x - Circle[i][0]) * (x – Circle[i][0]))
          + ((y - Circle[i][1]) * (y – Circle[i][1]))
);

if (distance < radius + Circle[i][2]) {
pass = false;
} else { 
pass = true;}
}

return pass;
}
}


//Construct Array and first entry
var Circle = [];
for (var i=0;i<4000;i++) {
     Circle[i] = [,,,];
}

Circle[0][0] = 500;
Circle[0][1] = 500;
Circle[0][2] = 50;
Circle[0][3] = "#000000";

// Fill Array
for(var i=1; i<10; i++) {
do {
var x = Math.floor((Math.random() * 1000));
var y = Math.floor((Math.random() * 1000));
var radsize = Math.floor((Math.random() * 5) + 1);
if(radsize == 1) {radius = 2.5;}
if(radsize == 2) {radius = 5;}
if(radsize == 3) {radius = 10;}
if(radsize == 4) {radius = 20;}
if(radsize == 5) {radius = 40;}

//var pass = overlapCheck(x,y,radius);
pass = true
}
while(pass == false)
/*
while loop check variable = !overlapCheck(x,y,radius)
Current variable is just to bypass
*/
Circle[i][0] = x;
Circle[i][1] = y;
Circle[i][2] = radius;
Circle[i][3] = "#000000";

}

var theCanvas=document.getElementById("myCanvas");
var canvasContext=theCanvas.getContext("2d");

circles = Circle.length;
for(var i=0; i<circles; i++) {
canvasContext.fillStyle=Circle[i][3];
drawCircle(Circle[i][0],Circle[i][1],Circle[i][2],canvasContext);
}
</script>
</body>
</html>
Rewritten. Though none of the circles move.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>


</head>
<body>


    <canvas id="myCanvas" width="1000" height="1000" style="border:3px solid #c3c3c3;">
    It appears that your browser does not support HTML5 and the canvas element.
    </canvas>

    <script type="text/javascript">
        function drawCircle(x, y, r, color) {
            color.beginPath();
            color.arc(x, y, r, 0, Math.PI * 2, true);
            color.closePath();
            color.fill();
        }

        function getColor() {
            var hexColor = "#000000";
            return hexColor.toUpperCase();
        }


        function overlapCheck(x, y, radius) {
            var pass = false; // not sure of the initial value
            for (var i = 1; i < 4000; i++) {

                if (
                    ((x + radius + Circle[i][2]) > Circle[i][0])
                    &&
                     (x < (Circle[i][0] + radius + Circle[i][2]))
                    &&
                     ((y + radius + Circle[i][2]) > Circle[i][1])
                    &&
                     (y < (Circle[i][1] + radius + Circle[i][2]))
                   ) {
                    //AABBs are overlapping

                    var x_circle = (x - Circle[i][0]);
                    var y_circle = (y - Circle[i][1]);
                    distance = Math.sqrt((x_circle * x_circle) + (y_circle * y_circle));

                    if (distance < radius + Circle[i][2]) {
                        pass = false;
                    } else {
                        pass = true;
                    }
                }

                return pass;
            }
        }


        //Construct Array and first entry
        var Circle = [];
        for (var i = 0; i < 4000; i++) {
            Circle[i] = [, , , ];
        }

        Circle[0][0] = 500;
        Circle[0][1] = 500;
        Circle[0][2] = 50;
        Circle[0][3] = "#000000";

        // Fill Array
        for (var i = 1; i < 10; i++) {
            do {
                var x = Math.floor((Math.random() * 1000));
                var y = Math.floor((Math.random() * 1000));
                var radsize = Math.floor((Math.random() * 5) + 1);
                if (radsize == 1) { radius = 2.5; }
                if (radsize == 2) { radius = 5; }
                if (radsize == 3) { radius = 10; }
                if (radsize == 4) { radius = 20; }
                if (radsize == 5) { radius = 40; }

                var pass = overlapCheck(x,y,radius);
                //pass = true
            }
            while (pass == false)
            /*
            while loop check variable = !overlapCheck(x,y,radius)
            Current variable is just to bypass
            */
            Circle[i][0] = x;
            Circle[i][1] = y;
            Circle[i][2] = radius;
            Circle[i][3] = "#000000";

        }

        var theCanvas = document.getElementById("myCanvas");
        var canvasContext = theCanvas.getContext("2d");

        circles = Circle.length;
        for (var i = 0; i < circles; i++) {
            canvasContext.fillStyle = Circle[i][3];
            drawCircle(Circle[i][0], Circle[i][1], Circle[i][2], canvasContext);
        }
    </script>     
</body>
</html>

Beginner in Game Development?  Read here. And read here.

 

the following seems to be working, i guess you can get rid off the AABB, I dont think it's any good for performance also you can avoid the sqrt there by squaring the sum radious'


<!DOCTYPE html>
<html xmlns="[url=http://www.w3.org/1999/xhtml]http://www.w3.org/1999/xhtml[/url]">
<head>
    <title></title>

</head>
<body>

    <canvas id="myCanvas" width="1000" height="1000" style="border:3px solid #c3c3c3;">
    It appears that your browser does not support HTML5 and the canvas element.
    </canvas>
    <script type="text/javascript">
        function drawCircle(x, y, r, color) {
            color.beginPath();
            color.arc(x, y, r, 0, Math.PI * 2, true);
            color.closePath();
            color.fill();
        }
        function getColor() {
            var hexColor = "#000000";
            return hexColor.toUpperCase();
        }

        function overlapCheck(x, y, radius, already_done) {
            var pass = false; // not sure of the initial value
            for (var i = 0; i < already_done; i++) {
                if (
                    (Math.abs(x  - Circle[i][0]) < radius + Circle[i][2])
                    &&
                    (Math.abs(y  - Circle[i][1]) < radius + Circle[i][2])
                   ){
                    //AABBs are overlapping
                    var x_circle = (x - Circle[i][0]);
                    var y_circle = (y - Circle[i][1]);
                    distance = Math.sqrt((x_circle * x_circle) + (y_circle * y_circle));
                    if (distance < radius + Circle[i][2])
                    {
                        pass = true;
                        break;
                    }
                    else
                    {
                        pass = false;
   
                    }
                }
            }
            return pass;
        }

        //Construct Array and first entry
        var Circle = [];
        for (var i = 0; i < 100; i++) {
            Circle[i] = [, , , ];
        }
        Circle[0][0] = 500;
        Circle[0][1] = 500;
        Circle[0][2] = 50;
        Circle[0][3] = "#000000";
        // Fill Array
        var pass;
        var x;
        var y;
        var radsize;
        for (var i = 0; i < Circle.length; i++) {
            do {
                x = Math.floor((Math.random() * 1000));
                y = Math.floor((Math.random() * 1000));
                radsize = Math.floor((Math.random() * 5) + 1);
                if (radsize == 1) { radius = 2.5; }
                if (radsize == 2) { radius = 5; }
                if (radsize == 3) { radius = 10; }
                if (radsize == 4) { radius = 20; }
                if (radsize == 5) { radius = 40; }
                pass = overlapCheck(x,y,radius,i);
            }
            while (pass)

            Circle[i][0] = x;
            Circle[i][1] = y;
            Circle[i][2] = radius;
            Circle[i][3] = "#000000";
        }
        var theCanvas = document.getElementById("myCanvas");
        var canvasContext = theCanvas.getContext("2d");
        for (var i = 0; i < Circle.length; i++)
        {
            canvasContext.fillStyle = Circle[i][3];
            drawCircle(Circle[i][0], Circle[i][1], Circle[i][2], canvasContext);
        }
    </script>    
</body>
</html>

This topic is closed to new replies.

Advertisement