How to make overlap / collision over hundreds of canvas circles?

I draw 100 canvases of different sizes on a canvas, and they should not intersect. these circles will also animate from right to left (turning back to the right edge of the canvas when they leave the screen), and will also have a vertical “bob” for them, which also cannot cross other circles.

Below I am trying to attempt to block the browser. I scroll through a collection of circles and perform a function detectOverlap(), passing it a collection of circles.

Then the function detectOverlap()goes in circles, performing the following check:

detectOverlap: function (bubblesArr) {
    while (true) {
        var hit = 0;
        for (var i=0; i<bubblesArr.length; i++) {
            var circle = bubblesArr[i];
            var dx = this._x - circle._x;
            var dy = this._y - circle._y;
            var rr = this._radius + circle._radius;
            if (dx * dx + dy * dy < rr * rr) {
                hit++;
            }
        }
        if (hit == 0) {
            break; // didn't overlap, break out of while loop
        }
        // if we didn't break then there was an overlap somewhere. calc again.
        this._x = Math.round(Math.random() * this.stage.getWidth());
        this._y = Math.round(Math.random() * this.stage.getHeight());
    }
},

if hit == 0, the loop breaks, and we assume that there are no overlaps. Otherwise, we arbitrarily calculate the new X / Y position and restart the process.

. - ?

( ): "", , .

var $container;
var listData;
var bubbles = [];

function init(l, c) {
    $container = c;
    listData = l;

    // this just draws the canvas. full-width + 500px tall.
    var stage = new Konva.Stage({
      container: $container.selector,
      width: window.innerWidth,
      height: 500
    });

    // this creates the drawing layer where the bubbles will live
    layer = new Konva.Layer();

    // create an instance of the Bubble class for each element in the list.
    for (var i=0; i<listData.length; i++) {
        bubbles[i] = new celebApp.Bubble.Bubble(listData[i], stage);
    }

    /** TODO:::: FIGURE OUT COLLISION DETECTION */
    for (var i=0; i<bubbles.length; i++) {
        bubbles[i].detectOverlap(bubbles);
    }

    // create the Konva representation for our generated objects
    for (var i=0; i<bubbles.length; i++) {
        var b = bubbles[i];
        layer.add(new Konva.Circle({
            x: b._x,
            y: b._y,
            radius: b._radius,
            fill: b._fill,
            stroke: b._stroke,
            strokeWidth: b._strokeWidth,
        }));
    }

    // add the layer to the stage
    stage.add(layer);
}

Bubble: , , . , .

var Bubble = function (listData, stage) {
    this.stage = stage;
    this._x = Math.round(Math.random() * stage.getWidth()),
    this._y = Math.round(Math.random() * stage.getHeight()),
    this._radius = Math.round(Math.random() * 80);
    this._fill = 'red';
    this._stroke = 'black';
    this._strokeWidth = 4;
    this._speed = 3;
};
Bubble.prototype = {
    detectOverlap: function (bubblesArr) {
        while (true) {
            var hit = 0;
            for (var i=0; i<bubblesArr.length; i++) {
                var circle = bubblesArr[i];
                var dx = this._x - circle._x;
                var dy = this._y - circle._y;
                var rr = this._radius + circle._radius;
                if (dx * dx + dy * dy < rr * rr) {
                    hit++;
                }
            }
            if (hit == 0) {
                break; // didn't overlap
            }
            this._x = Math.round(Math.random() * this.stage.getWidth());
            this._y = Math.round(Math.random() * this.stage.getHeight());
        }
    },
};

EDIT: @MarcB - . , 100 while()?

for (var i=0; i<bubblesArr.length; i++) {
    var circle = bubblesArr[i];
    var combinedRadius = Math.abs(circle._radius + this._radius);
    var distance = Math.abs(this._x - circle._x);
    if (distance <= combinedRadius) {
        hit++;
    }
}
+4
2

. . , . , .

, . , . , .

, , , .

, . , , .

, , . x, , , , 5, , . , .

y, , , , , , , . , .

+1

( ), , ?

, , , , , . - :

Describe the space as a tuple consisting of a middle point and a top left point.

  (middle,top_left)

Choose a random point on the top border of the box:

-----x-----------

Choose one random point on the left border of the box and one on the right:

-----x-----------
|    |          |
|    |          |
x-----          |
|    |          |
|    |----------x
|    |          |
-----------------

You now have four new middle and top left points, easily calculated.

Add the four new tuples to the queue and remove the tuple 
representing the parent box. Customize the function to get appropriately 
sized results.

, . , , - ( , ) . ( , .)

- ( ):

var MIN_WIDTH = MIN_HEIGHT = 20;

function f(top_left,bottom_right){
  var w = bottom_right.x - top_left.x - 2 * MIN_WIDTH,
      h = bottom_right.y - top_left.y - 2 * MIN_HEIGHT,

      random_top = top_left.x + MIN_WIDTH 
                 + Math.ceil(Math.random() * w),

      random_left = top_left.y + MIN_HEIGHT
                  + Math.ceil(Math.random() * h),

      random_right = top_left.y + MIN_HEIGHT
                   + Math.ceil(Math.random() * h);

  var rectangle_1 = [top_left
                    ,{x: random_top, y: random_left}],

      rectangle_2 = [{x: top_left.x, y: random_left}
                    ,{x: random_top, y: bottom_right.y}],

      rectangle_3 = [{x: random_top, y: top_left.y}
                    ,{x: bottom_right.x, y: random_right}],

      rectangle_4 = [{x: random_top, y: random_right}
                    ,bottom_right];

  return [rectangle_1, rectangle_2, rectangle_3, rectangle_4];
}

console.log(JSON.stringify(f({x: 0, y: 0}, {x: 200, y: 200})))

f . f, . , ( ). . , - , "" .

0

All Articles