2015-11-21 18 views
5

私は2 ellipsesを持っており、それらの重なりを検出する必要があります。ここで 2つの楕円の重なりを計算する

は二つの円の間の重複を検出する例である、と私は楕円のために似たような探しています:

楕円の場合
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>
:横軸の半径と小さいです

答えて

7

あなたの楕円は、非常に特殊であることに、彼らは単にY軸に沿って縮小した円であるため、あなたはちょうどあなたが2倍とY軸に沿って平面を伸ばすならば何が起こるかを想像することができます。重なり合う楕円が重なり合う円になり、重なり合わない楕円が重なっても重なり合わないことに同意するでしょう。あたかも楕円が伸縮性のある素材に描かれているかのように想像してもらい、素材を垂直方向に伸ばすだけです。もちろん、重なり合った状態は変わりません。

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

を...と、そのままそれが延伸後も、あるX方向の半径に基づいているため、条件を続行:

だから、あなたはこれを書くことができますY方向の半径。もちろん、私は変数の名前を違うので、その変数でテストする必要があります。だから、コードを完了するために、我々が得る:ストレッチングは、それが同等と4 * dy * dyを書く短い距離の式2でdyを乗じて考慮されていること

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

注意。

あなたが作成したいい対話型のfiddleは、ここで私の更新があります。

+0

私はそれが本当にうまくいかないと思うか、あなたを理解できません。あなたはここであなたの数式を試すことができます:https://jsfiddle.net/rodriguevb/c60aefwn/ – Rodrigue

+0

非常に素晴らしいフィドル!私は自分の答えを更新しました。私はあなたの半径がY方向の半径であると最初は考えていましたが、私は今あなたのフィドルでX方向にあり、Y座標は半分になっています。したがって、式には '4 * dy * dy'が必要です。私はあなたのフィドルを使用し、私の答えに更新版を入れました。 – trincot

+0

ありがとうございました!それは今、完璧に動作します。問題は解決しました! – Rodrigue

関連する問題