javascript - 计算两个椭圆之间的重叠

标签 javascript math

我有 2 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 !
}

对于椭圆,我有相同的变量,因为我在垂直轴上的半径比水平轴上的半径小 2 倍:

var oval1 = {radius: 20, x: 5, y: 5};
var oval2 = {radius: 12, x: 10, y: 5};

// what comes here?

if ( /* condition ? */ ) {
    // collision !
}

Image: collision between two oval

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>

最佳答案

由于你的椭圆非常具体,因为它们只是沿 Y 轴缩小的圆,你可以想象如果你将平面沿 Y 轴拉伸(stretch) 2 倍会发生什么。你会同意那些重叠的椭圆会变成重叠的圆,而那些不重叠的椭圆在拉伸(stretch)后也不会重叠。你可以把它想象成椭圆是画在弹性 Material 上的,你只是在垂直方向拉伸(stretch) Material :这当然不会改变任何重叠情况。

所以,你可以这样写:

var stretchedDistance = Math.sqrt(dx * dx + 2 * dy * 2 * dy);

... 并继续保持目前的条件,因为它基于 X 方向的半径,拉伸(stretch)后也是 Y 方向的半径。当然,我以不同的方式命名了变量,因此您应该使用该变量进行测试。所以为了完成代码,我们得到:

var stretchedDistance = Math.sqrt(dx * dx + 4 * dy * dy);
if (stretchedDistance < circle1.radius + circle2.radius) {
    // collision !
}

请注意,拉伸(stretch)是通过乘以 dy 来考虑的与 2. 在距离公式中,写成 4 * dy * dy 是等效且更短的.

这是很好的互动 fiddle你创建了,我更新了它。

关于javascript - 计算两个椭圆之间的重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33849519/

相关文章:

javascript - 如何将事件处理程序添加到单击按钮时呈现的元素?

javascript - 加速 Nivo-Slider

math - 整数存储为 float

c++ - 遍历任意形状的点

javascript - HTML5 无尽的背景动画

javascript - 仅在 Javascript 中使用 string.includes() 时搜索整个单词

javascript - 解压从 JavaScript FileReader API 发送到 Python 的 BinaryString

c++ - 获取只能除以 2,3 和/或 5,但不能除以任何其他质数的数字

java - 使用数学和流在 Java 8 中重新映射数组

php - 如何获取数字的整数部分和小数部分?