Circle Intersections w/ Raphael

I was discussing an interesting problem with a friend of mine awhile back – it relates to simulating the intersection of two or more 2d bubbles. This turns out to be trickier than you might expect. The first sketch I created regarding this problem was this:

I used circle intersection logic from Paule Bourke. (That really is one of my favorite websites).

The above is interesting, but taking it further will be tricky – it looks like some kind of Voronoi variation might be the way to go.

Here is the main source:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 var r = new Raphael(0, 0, 500, 500);
 
var CIRCLE_NUM = 4;
var circles = [];
var lines = [];
 
// make some randomly positioned circles
for (var i = 0; i < CIRCLE_NUM; i++){
  circles.push(r.circle(Math.random() * 150 + 150, 
                        Math.random() * 150 + 150, 
                        60)
               .attr({fill: "rgba(81, 121, 200, 0.3)"}));
}
 
var line = r.path();
var path = "";
 
render();
dragAndDrop();
 
function render() {
  path = "";
  redPath = "";
  lines = [];
  var leng = circles.length;
  for (var i = 0; i<leng; i++){
    for (var j = i + 1; j<leng; j++){
      circleIntersection(circles[i], circles[j]);
    }
  }
}
 
// easy to understand explanation here:
// http://paulbourke.net/geometry/2circle/
function circleIntersection(a, b) {
  var a, h, cx, cy, px, py;
  var ax = a.attr("cx");
  var ay = a.attr("cy");
  var bx = b.attr("cx");
  var by = b.attr("cy");
  var ra = a.attr("r");
  var rb = b.attr("r");
 
  var dx = Math.abs(ax - bx);
  var dy = Math.abs(ay - by);
 
  var d = Math.sqrt(dx * dx + dy * dy);
 
  if (d > (ra + rb)) {
    // no solutions
  } else if (d < Math.abs(ra - rb)) {
    // no collisions, one inside other
  } else if (d == 0 && ra == rb) {
    // circles are coincident   
  } else {
    // there is a collision
    a = (ra * ra - rb * rb + d * d) / (2 * d);
    h = Math.sqrt(ra * ra - a * a);
    cx = ax + a * (bx - ax) / d;
    cy = ay + a * (by - ay) / d;
 
    // point c (draw here)
 
    var tx = h * (by - ay) / d;
    var ty = h * (bx - ax) / d;
    px = cx + tx;
    py = cy - ty;
 
    var ln = {a:{x:px, y:py}};
 
    path += "M " + px + " " + py + " ";
 
    px = cx - tx;
    py = cy + ty;
 
    ln.b = {x:px, y:py};
 
    path += "L " + px + " " + py + " ";
 
    line.attr({path: path});
 
    lines.push(ln);
  }
}
 
function dragAndDrop(){
  var circs = r.set();
  for (var i = 0; i < circles.length; i++) {
    circs.push(circles[i]);
  }
  circs.drag(function(dx, dy) {
    this.attr({cx: this.ox + dx, cy: this.oy + dy});
    render();
  }, function() {
    this.ox = this.attr("cx");
    this.oy = this.attr("cy");
  });
}

On a side note, you can use this old-school gradient circle technique to create something similar:

Lately I’ve been speed coding actionscript, so no variable typing and no holding back on weird/bad tricks. Sometimes the result is unreadable – other times it looks like elegant pseudo-code (which one is this?):

This is the code for the above image.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[SWF(width=400, height=400, frameRate=1, backgroundColor=0xFFFFFF)]
 
var m = new Matrix();
var BUB_NUM = 30;
 
for (var i = 0; i < BUB_NUM; i++)
  bubble(Math.random() * stage.stageWidth, 
         Math.random() * stage.stageHeight);
 
function bubble(xp, yp) {
	var bub = addChild(new Sprite());
	var rad = Math.random() * 20 + 50;
	var diam = rad * 2;
	m.createGradientBox(diam, diam, 0, -rad, -rad);
	with(bub.graphics) {
		beginGradientFill("radial", 
				  [0, 0xFFFFFF], 
				  [1,1], 
				  [0,255], m);
		drawCircle(0, 0, rad);
	}
	with(bub){
	  x = xp;
	  y = yp;
	  blendMode = "darken";
	  cacheAsBitmap = true;
	}
}

Not sure what my final solution will be… should be interesting.



 
 
 

One Response to “Circle Intersections w/ Raphael”

  1. Nandeep Mali
    18. November 2012 um 04:53

    Very cool. I came upon this while trying to figure out how to intersection between a line and a circle.

Leave a Reply

Spam protection by WP Captcha-Free