距离画在画布上

问题描述:

距离画在画布上

<html> 
 
<body style="margin:10px;"> 
 
<canvas id="myCanvas" width="500" height="500" style="border:1px solid #d3d3d3;"> 
 
</canvas> 
 
    
 
</body> 
 
    
 
<script language="javascript" type="text/javascript"> 
 

 

 

 
     var canvas = document.getElementById('myCanvas'); 
 
     var context = canvas.getContext('2d'); 
 

 
     var centerX = 400; 
 
     var centerY = 400; 
 
     var radius = .5; 
 

 
     context.beginPath(400,400); 
 
     context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); 
 
     context.fillStyle = 'blue'; 
 
     context.fill(); 
 
     context.lineWidth = 1; 
 
     context.strokeStyle = '#003300'; 
 
     context.stroke(); 
 

 

 

 
     context.beginPath(); 
 
     context.moveTo(50, 250); 
 
     context.bezierCurveTo(50, 250, 50, 250, 50, 250); 
 
     context.bezierCurveTo(90, 210, 90, 210, 90, 210); 
 
     context.bezierCurveTo(130, 90, 130, 90, 130, 90); 
 
     context.bezierCurveTo(260, 240, 260, 240, 260, 240); 
 
     context.bezierCurveTo(255, 400, 255, 400, 255, 400); 
 

 
     context.closePath(); 
 
     context.lineWidth = 1; 
 
     context.strokeStyle = 'green'; 
 
     context.stroke(); 
 
    
 
</script> 
 
\t 
 
\t 
 
\t 
 
\t 
 
</html>

第一次张贴在这里,但这个网站已经帮助了我很多与其他灰色地带我有!

我想确定从画布上的点到形状边缘的距离。形状将是不规则的,例如,如果它的三角形我不认为如果距离公式超出三角形的边缘,它将不起作用。

我有点沮丧,因为这可能是我的项目的垮台。任何开放的想法,将不胜感激!

谢谢

编辑:这里就是我说的,在这个例子中,我想知道这是多少像素从共同ORD 400,400对象的最近点的例子。但对于我的项目,无论这个点在哪里,我都希望能够测量到物体的最近点。

我知道这是很多要问,但我想我会给它一个镜头!

感谢您提前回复!

+1

形状是否都是多边形 - 由线段组成?当你说“距离”时,你的意思是指形状还是别的什么?如果对两者都是肯定的,你可以测试多边形的每一条线段并[找到距离该点最小的距离](http:// stackoverflow。COM /问题/ 29021887 /拖拽点-沿着矢量与 - 小鼠/ 29023665#29023665)。 – markE

+0

边缘x,y坐标将根据所使用的多边形和画布方法而变化....您可以发布代码示例吗? – KpTheConstructor

+0

据我所知(在所有诚实中有点生锈),因为Canvas使用光栅(像素)绘图,所以一旦你画出一个形状就会被遗忘,当然,你可以比较每个像素的颜色,但这将是昂贵的。最好的方法是跟踪你画到画布上的每一个形状,并与这些形状进行比较,至于数学背后的真正取决于你的使用情况 –

这个问题的范围对于我来说写很多解决方案。我将概述如何添加一些限制。

形状是一组弧形,线条,曲线(立方体和二次方)以及矩形,它们可以连接也可以不连接。距离将是定义每个形状的线上最近的点,并且不包括线宽。形状都在相同的规模和方向。

最好的方法是使用MarkE指出的距离线功能(在他的评论“find the least distance from the point”中)并将所有路径对象转换为线。如何细分每条曲线将决定位置的准确度,直线不需要细分。但假设你只是在一个像素之后(鼠标分辨率),那么代码就不会做太多的处理。

您可以将行定义为点集。由于您可能有未加入的路径,所以这些点集将位于二维数组中。

var lines = []; 
var currentLine = null; 
function startLine(){ 
    if(currentLine.length > 0){ 
     currentLine = []; // new array 
     lines.push(cuurentLine); // push onto the line array 
    } 
} 
function moveToPoint(x,y){ 
    startLine(); 
    addPoint(x,y); 
} 
function addPoint(x,y){ 
    currentLine.push(x:x,y:y); 
} 
function closePath(){ 
    currentLine.push(currentLine[0]); 
} 

然后你就可以匹配调用上述功能

所有渲染调用一个最简单的一组线

ctx.beginPath(); 
ctx.moveTo(x,y); // to save me time x and y are points of some coordinate. 
ctx.lineTo(x,y); 
ctx.lineTo(x,y); 
ctx.lineTo(x,y); 
ctx.closePath(); 

应与

startLine(); // you really only need moveToPoint 
moveToPoint(x,y); 
addPoint(x,y); 
addPoint(x,y); 
addPoint(x,y); 
closePath(); 
匹配

您的阵列应该看起来像

// p represents a point {x :x,y: y} 
lines [[p,p,p,p,p]]; // An array inside lines with 5 points. The last point is 
        // back to the start 

如果添加另一个路径

ctx.moveTo(x,y); // to save me time x and y are points of some coordinate. 
ctx.lineTo(x,y); 
ctx.lineTo(x,y); 
ctx.lineTo(x,y); 
// note I did not close path 

你必须

moveToPoint(x,y); 
addPoint(x,y); 
addPoint(x,y); 
addPoint(x,y); 

与之相匹配的阵列现在看起来像

// p represents a point {x :x,y: y} 
lines [[p,p,p,p,p],[p,p,p,p]]; // not second path is not closed and has one less point 

,并包含两个路径。

然后,您可以检查使用线功能(在回答的顶部链接)找到最接近的形状,你有你只需要调用该函数,你必须形状

function findclosestPoint(px,py){ // the point px,py 
    var minDist = Infinity; 
    var pf = {x:0,y:0}; // the closest point 
    for(i = 0; i < lines.length; i+=1){ 
     for(j = 0; j < lines[i].length-1; j+=1){ 
      var p = lines[i][j]; 
      var p1 = lines[i][j+1]; 
      // get closet point 
      var cp = getClosestPointOnLine({x0 : p.x, y0 : p.y, x1 : p1.x, y1 : p1.y},px,py); 
      // then get the distance. 
      var x = cp.x - px; 
      var y = cp.y - py; 
      x *= x; 
      y *= y; 
      var dist = Math.sqrt(x + y); 

      // is it the closest? 
      if(dist < minDist){ 
       minDist = dist; // yes remember this distance 
       pf.x = cp.x; 
       pf.y = cp.y; 
      } 
     } 
    } 
    return {dist : minDist, point : pf}; 
}   

的点解决方案。

var closest = findclosestPoint(400,400); 
console.log(closest.point) ;// >> {x:?,y:?} 
console.log(closest.dist) ;// >> ? in pixels 

为了让它适用于弧线,创建一个将弧线分割成更小的线段的功能。贝塞尔曲线和三次曲线相同。相隔2至3个像素的间隔点应该足够多。在StackOverflow中有很多用于查找弧和贝塞尔点的示例。

对于矩形作为一个例子

ctx.rect(x,y,w,h); 

创建一个函数来添加定义矩形的线条。

function addRect(x,y,w,h) 
    addPoint(x,y) // rects start at top left 
    addPoint(x+w,y) 
    addPoint(x+w,y+h) 
    addPoint(x,y+h) 
    addPoint(x,y) 
} 

请记住,fillrect和strokeRect以moveTo开头,因此如果需要添加moveToPoint函数调用。

对弧和贝塞尔曲线做同样的操作。

这就是它的全部。

如果你打算有不同的比例和旋转,你将不得不添加这些转换时,你将点添加到线阵列。

如果您希望包含线宽,您将不得不为每条线的边缘创建线条。对贝塞尔来说,这可能会很棘手,但是对于每个在堆栈中的子问题都有解决方案。从基础开始,提炼直至达到目标。

+0

非常感谢! – Mick