查找落在填充画布弧线内的 x/y 坐标

3
这是fiddle示例。
我画了圆周上的弧线,想知道如何找到它们所覆盖的所有x/y坐标,这样就不必每次使用isPointInPath()重新绘制它们以确定鼠标光标是否在其上方。我考虑将所有的x/y坐标写入一个数组中,然后检查鼠标位置的x/y坐标是否匹配,如果找到匹配项,则更改光标。问题在于,我不知道推导所有x/y值的代码。

2
你知道吗,其实你不需要重新绘制弧形才能使用.isPointInPath()--省略任何对.fill().stroke()的调用,你就可以得到一个路径,可以用来测试是否包含一个点。 - ellisbben
@ellisbben 你应该把那个发表为答案! :) - Phrogz
嗯,我想知道为什么我没有考虑到那个。让我试一试。 - jamauss
@ellisben - 感谢您的建议。实际上,这个方法非常有效,因为我的瓶颈在于画布上几个项目的不断重新渲染。如果您想将您的评论作为答案添加,我很乐意接受它。 - jamauss
完成。当人们发现一个隐藏的好答案时,我感到很高兴。 :) - ellisbben
4个回答

3
这是您应该使用的方法:http://en.wikipedia.org/wiki/Point_in_polygon 这个方法的原理其实非常简单:如果以任意一点为终点的射线穿过多边形周长的次数是偶数,那么相应的点一定在多边形外部。如果是奇数,则在多边形内。
以下是Pimvdb找到的一个函数:
function isPointInPoly(poly, pt){
    for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
        ((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y))
        && (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x)
        && (c = !c);
    return c;
}

你推荐那一页上的哪个算法? - mwcz
好的,我明白我需要传递一个x/y坐标的数组和我想要测试是否在我的多边形中的x/y坐标。我仍然不清楚如何获得/计算传递给isPointInPoly的x/y坐标数组。获取鼠标的x/y位置很简单,但计算被我的弧线覆盖的x/y却让我感到困惑。 - jamauss
@jarnauss:我转念一想,我觉得我发的链接可能不太有用,因为它是关于直线而不是弧线的。如果你想使用它,你可以使用拐角点,但那只是对弧线的近似... - pimvdb
是的,我现在正在寻找一个“isPointInArc”的解决方案。到目前为止,通过谷歌搜索的结果看起来不太乐观。 - jamauss
无论哪种方式都可以,每个多边形都是由点和线构成的(甚至包括圆)。只要提供这些点,弧线就会被正确绘制。 - Korvin Szanto

3
您实际上不需要重新绘制弧形就可以使用.isPointInPath()——只需省略任何对.fill().stroke()的调用,您将拥有一个路径,您可以用它来测试它是否包含一个点。
我建议您有一个函数来概述弧形路径(.beginPath(),路径命令,.closePath()),然后再有两个调用它的函数——一个调用弧形路径函数,然后设置填充样式并填充路径以绘制它,另一个调用弧形路径函数,然后只是测试一个点是否在路径中。

这基本上就是我最终所做的。我将一个标志传递到函数中,以确定是否实际绘制任何内容。 - jamauss

0

我不会称呼你的图形为“弧线”(它们更像是弯曲的矩形),但这里有一个大致的草图,展示如何编写判断点是否位于该图形中的函数:

  1. 通过端点和半径计算圆心。
    1. 如果该点距离圆心比近处的弧线更近(距离平方大于近处半径的平方),则返回false。
    2. 如果该点距离圆心比远处的弧线更远,则返回false。
  2. 计算相对于圆心的矩形端点的起始角度和结束角度。(提示:Math.atan2
    1. 计算该点相对于圆心的角度。如果它不在端点的角度之间,则返回false。
      • 注意,端点可能会穿越Math.atan2的包装值。
  3. 如果其他测试都通过,则返回true。

在这个区域中,您无法计算“所有”点,因为它们有无限多。创建图像中所有整数像素坐标的查找表是可能的,但是浪费资源。

相比于您提出的方案,会使用保留模式图形系统(提示:SVG),让它使用更高效的代码跟踪鼠标事件。


0

这里有一个更简单的方法:

我已经修改了drawtabs函数,以便检查鼠标是否在选项卡内: http://jsfiddle.net/kkDqz/4/

警告

这种方法很简单,但需要在mousemove事件中重新绘制所有内容


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接