2013-08-21 192 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