2013-08-21 194 views
0

我正在尋找等式來將圓轉換爲橢圓,以便我可以找到從點到橢圓邊界的最短距離。我找到了一個圓和一個點之間的距離的等式,但不知道如何將它轉換爲橢圓。將圓轉換爲橢圓,以便從橢圓邊框計算點的距離

像素和PY是點和x和y是圓原點和射線是半徑

closestCirclePoint: function(px, py, x, y, ray) { 
    var tg = (x += ray, y += ray, 0); 
    return function(x, y, x0, y0) { 
     return Math.sqrt((x -= x0) * x + (y -= y0) * y); 
    }(px, py, x, y) > ray 
     ? {x: Math.cos(tg = Math.atan2(py - y, px - x)) * ray + x, 
     y: Math.sin(tg) * ray + y} 
     : {x: px, y: py}; 
} 
+0

一個橢圓有兩個半徑和旋轉角度旁邊的原點,所以你是什麼意思「*射線意思是半徑的一半*「? – Bergi

+0

抱歉,ray是圓的半徑。我不知道這轉化爲一個橢圓。 – Zero

回答

1

[加法回答:如何近似橢圓上的最近點]

如果你願意犧牲完美的實用性...

這裏是一種方法來計算一個橢圓點是「接近ish」到你的目標點。

enter image description here

的方法:

  • 確定你的目標點在橢圓的象限
  • 計算開始和結束該象限的弧度角。
  • 沿橢圓象限計算點(「走橢圓」)。
  • 對於每個計算出的橢圓點,計算到目標點的距離。
  • 保存距目標最短距離的橢圓點。

缺點:

  • 結果爲近似值。
  • 它比數學上完美的計算更不雅 - 使用暴力方法。
  • (但一個有效的蠻力方法)。

優點:

  • 近似的結果是相當不錯的。
  • 表現很不錯。
  • 計算簡單得多。
  • 計算(可能)比數學上完美的計算更快。
  • (成本約20三角函數計算加上一些加法/減法)
  • 如果需要更高的精度,你只需要改變1可變
  • (更準確地花費更多的計算,當然)

性能注意:

  • 你可以預先計算所有「走點」橢圓上的甚至更好的性能。

下面是這個方法的代碼:

// calc a point on the ellipse that is "near-ish" the target point 
    // uses "brute force" 
    function getEllipsePt(targetPtX,targetPtY){ 

     // calculate which ellipse quadrant the targetPt is in 
     var q; 
     if(targetPtX>cx){ 
      q=(targetPtY>cy)?0:3; 
     }else{ 
      q=(targetPtY>cy)?1:2; 
     } 

     // calc beginning and ending radian angles to check 
     var r1=q*halfPI; 
     var r2=(q+1)*halfPI; 
     var dr=halfPI/steps; 
     var minLengthSquared=200000000; 
     var minX,minY; 

     // walk the ellipse quadrant and find a near-point 
     for(var r=r1;r<r2;r+=dr){ 

      // get a point on the ellipse at radian angle == r 
      var ellipseX=cx+radiusX*Math.cos(r); 
      var ellipseY=cy+radiusY*Math.sin(r); 

      // calc distance from ellipsePt to targetPt 
      var dx=targetPtX-ellipseX; 
      var dy=targetPtY-ellipseY; 
      var lengthSquared=dx*dx+dy*dy; 

      // if new length is shortest, save this ellipse point 
      if(lengthSquared<minLengthSquared){ 
       minX=ellipseX; 
       minY=ellipseY; 
       minLengthSquared=lengthSquared; 
      } 
     } 

     return({x:minX,y:minY}); 
    } 

這裏是代碼和一個小提琴:http://jsfiddle.net/m1erickson/UDBkV/

<!doctype html> 
<html> 
<head> 
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> 
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> 

<style> 
    body{ background-color: ivory; padding:20px; } 
    #wrapper{ 
     position:relative; 
     width:300px; 
     height:300px; 
    } 
    #canvas{ 
     position:absolute; top:0px; left:0px; 
     border:1px solid green; 
     width:100%; 
     height:100%; 
    } 
    #canvas2{ 
     position:absolute; top:0px; left:0px; 
     border:1px solid red; 
     width:100%; 
     height:100%; 
    } 
</style> 

<script> 
$(function(){ 

    // get canvas references 
    var canvas=document.getElementById("canvas"); 
    var ctx=canvas.getContext("2d"); 
    var canvas2=document.getElementById("canvas2"); 
    var ctx2=canvas2.getContext("2d"); 

    // calc canvas position on page 
    var canvasOffset=$("#canvas").offset(); 
    var offsetX=canvasOffset.left; 
    var offsetY=canvasOffset.top; 


    // define the ellipse 
    var cx=150; 
    var cy=150; 
    var radiusX=50; 
    var radiusY=25; 
    var halfPI=Math.PI/2; 
    var steps=8; // larger == greater accuracy 


    // get mouse position 
    // calc a point on the ellipse that is "near-ish" 
    // display a line between the mouse and that ellipse point 
    function handleMouseMove(e){ 
     mouseX=parseInt(e.clientX-offsetX); 
     mouseY=parseInt(e.clientY-offsetY); 

     // Put your mousemove stuff here 
     var pt=getEllipsePt(mouseX,mouseY); 

     // testing: draw results 
     drawResults(mouseX,mouseY,pt.x,pt.y); 
    } 


    // calc a point on the ellipse that is "near-ish" the target point 
    // uses "brute force" 
    function getEllipsePt(targetPtX,targetPtY){ 

     // calculate which ellipse quadrant the targetPt is in 
     var q; 
     if(targetPtX>cx){ 
      q=(targetPtY>cy)?0:3; 
     }else{ 
      q=(targetPtY>cy)?1:2; 
     } 

     // calc beginning and ending radian angles to check 
     var r1=q*halfPI; 
     var r2=(q+1)*halfPI; 
     var dr=halfPI/steps; 
     var minLengthSquared=200000000; 
     var minX,minY; 

     // walk the ellipse quadrant and find a near-point 
     for(var r=r1;r<r2;r+=dr){ 

      // get a point on the ellipse at radian angle == r 
      var ellipseX=cx+radiusX*Math.cos(r); 
      var ellipseY=cy+radiusY*Math.sin(r); 

      // calc distance from ellipsePt to targetPt 
      var dx=targetPtX-ellipseX; 
      var dy=targetPtY-ellipseY; 
      var lengthSquared=dx*dx+dy*dy; 

      // if new length is shortest, save this ellipse point 
      if(lengthSquared<minLengthSquared){ 
       minX=ellipseX; 
       minY=ellipseY; 
       minLengthSquared=lengthSquared; 
      } 
     } 

     return({x:minX,y:minY}); 
    } 

    // listen for mousemoves 
    $("#canvas").mousemove(function(e){handleMouseMove(e);}); 



    // testing: draw the ellipse on the background canvas 
    function drawEllipse(){ 
     ctx2.beginPath() 
     ctx2.moveTo(cx+radiusX,cy) 
     for(var r=0;r<2*Math.PI;r+=2*Math.PI/60){ 
      var ellipseX=cx+radiusX*Math.cos(r); 
      var ellipseY=cy+radiusY*Math.sin(r); 
      ctx2.lineTo(ellipseX,ellipseY) 
     } 
     ctx2.closePath(); 
     ctx2.lineWidth=5; 
     ctx2.stroke(); 
    } 

    // testing: draw line from mouse to ellipse 
    function drawResults(mouseX,mouseY,ellipseX,ellipseY){ 
     ctx.clearRect(0,0,canvas.width,canvas.height); 
     ctx.beginPath(); 
     ctx.moveTo(mouseX,mouseY); 
     ctx.lineTo(ellipseX,ellipseY); 
     ctx.lineWidth=1; 
     ctx.strokeStyle="red"; 
     ctx.stroke(); 
    } 


}); // end $(function(){}); 
</script> 

</head> 

<body> 
    <div id="wrapper"> 
     <canvas id="canvas2" width=300 height=300></canvas> 
     <canvas id="canvas" width=300 height=300></canvas> 
    </div> 
</body> 
</html> 

原來的答案

這裏的圓形和橢圓形如何相關的

對於水平對準橢圓:

enter image description here

(X X)/(一個一)+(Y Y)/(B B)== 1;

其中a是水平頂點的長度,其中b是垂直頂點的長度。

如何圓和橢圓涉及:

如果== B,橢圓是圓!

但是......!

計算從任意點到橢圓上某個點的最小距離涉及到多於的計算。

下面是計算一個鏈接(點擊DistancePointEllipseEllipsoid.cpp):

http://www.geometrictools.com/SampleMathematics/DistancePointEllipseEllipsoid/DistancePointEllipseEllipsoid.html

+0

謝謝,這正是我正在尋找的。 – Zero