I have 2 ellipses and I need to detect any overlap between them.
Here is an example of detecting overlap between two circles, and I am looking for something similar for ellipses:
var circle1 = {radius: 20, x: 5, y: 5};
var circle2 = {radius: 12, x: 10, y: 5};
var dx = circle1.x - circle2.x;
var dy = circle1.y - circle2.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < circle1.radius + circle2.radius) {
// collision !
}
For ellipses, I have the same variable because my radius on the vertical axis is 2 times smaller as the radius on the horizontal axis:
var oval1 = {radius: 20, x: 5, y: 5};
var oval2 = {radius: 12, x: 10, y: 5};
// what comes here?
if ( /* condition ? */ ) {
// collision !
}
var result = document.getElementById("result");
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
// First eclipse
var eclipse1 = { radius: 20,
x: 100,
y: 40 };
// Second eclipse
var eclipse2 = { radius: 20,
x: 120,
y: 65 };
function have_collision( element1, element2 )
{
var dx = element1.x - element2.x;
var dy = element1.y - element2.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= element1.radius + element2.radius) {
return true;
}
else {
return false;
}
}
function draw( element ) {
// http://scienceprimer.com/draw-oval-html5-canvas
context.beginPath();
for (var i = 0 * Math.PI; i < 2 * Math.PI; i += 0.01 ) {
xPos = element.x - (element.radius/2 * Math.sin(i)) * Math.sin(0 * Math.PI) + (element.radius * Math.cos(i)) * Math.cos(0 * Math.PI);
yPos = element.y + (element.radius * Math.cos(i)) * Math.sin(0 * Math.PI) + (element.radius/2 * Math.sin(i)) * Math.cos(0 * Math.PI);
if (i == 0) {
context.moveTo(xPos, yPos);
} else {
context.lineTo(xPos, yPos);
}
}
context.fillStyle = "#C4C4C4";
context.fill();
context.lineWidth = 2;
context.strokeStyle = "#FF0000";
context.stroke();
context.closePath();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function(e) {
var mousePos = getMousePos(canvas, e);
eclipse2.x = mousePos.x;
eclipse2.y = mousePos.y;
result.innerHTML = 'Collision ? ' + have_collision( eclipse1, eclipse2 );
context.clearRect(0, 0, canvas.width, canvas.height);
draw( eclipse1 );
draw( eclipse2 );
}, false);
draw( eclipse1 );
draw( eclipse2 );
result.innerHTML = 'Collision ? ' + have_collision( eclipse1, eclipse2 );
#canvas {
border: solid 1px rgba(0,0,0,0.5);
}
<canvas id="canvas"></canvas>
<p id="result"></p>
<code>distance = Math.sqrt(dx * dx + dy * dy);</code>
As your ellipses are very specific, in that they are just circles shrunk along the Y axis, you can just imagine what would happen if you would stretch the plane along the Y-axis with a factor 2. You would agree that those overlapping ellipses would become overlapping circles, and those that did not overlap will also not overlap once stretched. You could imagine it as if the ellipses were drawn on a elastic material, and you just stretch the material in vertical direction: this will of course not change any overlapping condition.
So, you could write this:
var stretchedDistance = Math.sqrt(dx * dx + 2 * dy * 2 * dy);
... and continue with the condition as it stands, because it is based on the radius in the X-direction, which, after stretching, also is the radius in the Y-direction. Of course, I named the variable differently, so you should test with that variable. So to complete the code, we get:
var stretchedDistance = Math.sqrt(dx * dx + 4 * dy * dy);
if (stretchedDistance < circle1.radius + circle2.radius) {
// collision !
}
Note that the stretching is taken into account by multiplying dy
with 2. In the distance formula it is equivalent and shorter to write 4 * dy * dy
.
Here is the nice interactive fiddle you created, with my update to it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With