【问题标题】:Calculating if mouse position is within bounds of a diamond polygon计算鼠标位置是否在菱形多边形的范围内
【发布时间】:2014-11-20 12:51:56
【问题描述】:

我在面板上绘制了一个菱形,我正在尝试计算鼠标位置是否在其范围内。问题是尝试菱形,它需要四个坐标组成四条线来创建形状。

最简单的方法是在钻石的边界内创建/拟合一个正方形,但我想考虑外面的剩余三角形区域。我最初以为我试图计算两点之间的斜率,并通过将斜率添加到方程中来确定鼠标的 x 和 y 是否与线相交,但事实证明,当涉及到线时,这要困难得多鉴于菱形的中心不为零,构成 TOP->RIGHT、RIGHT->BOTTOM 和 BOTTOM->LEFT。

是否有更简单的实现来检查鼠标的 x,y 是否在菱形的范围内?

【问题讨论】:

  • 如果菱形的宽度和高度相等,这是微不足道的。只需从钻石中心和您的观点中获取差异即可。如果不是,请尝试将钻石视为 2 个三角形,然后进行三角形命中测试。

标签: java mouseover point-in-polygon


【解决方案1】:

伪代码(更易读):

Point org = new Point(64, 32); // Center.
Point radii = new Point(32, 16); // Half the size.

Point mousePos = ...

mousePos -= org; // Relative to the center.
boolean inside = Math.abs(mousePos.x) * radii.y + Math.abs(mousePos.y) * radii.x
                 <= radii.x * radii.y;

在数学中,我们知道 (0, radius.y) 和 (radii.x, 0) 确定正象限中的边界线。 这归结为上面的公式。

static boolean isInsideDiamond(int x, int y, int[] xs, int[] ys) {
    int minX = xs[0];
    int maxX = minX;
    int minY = ys[0];
    int maxY = minY;
    for (int i = 1; i < 4; ++i) {
        minX = Math.min(minX, xs[i]);
        maxX = Math.max(maxX, xs[i]);
        minY = Math.min(minY, ys[i]);
        maxY = Math.max(maxY, ys[i]);
    }

    int orgX = (minX + maxX) / 2;
    int orgY = (minY + maxY) / 2;
    int radX = (maxX - minX) / 2;
    int radY = (maxY - minY) / 2;

    return isInsideDiamond(x, y, orgX, orgY, radX, radY);
}

static boolean isInsideDiamond(int x, int y, int orgX, int orgY, int radX,
        int radY) {
    x -= orgX;
    x = Math.abs(x);
    y -= orgY;
    y = Math.abs(y);
    return x * radY + y * radX <= radX * radY;
}

顺便说一句:

Polygon diamond = new Polygon(xs, ys, 4);
boolean inside = diamond.contains(x, y);

【讨论】:

  • 我喜欢它避免除法和浮点数的方式,并且与“在圈内”测试的相似性也很好。
  • 我已经将刚刚找到钻石中心和尺寸的代码与真正的计算代码分开了。希望你不要介意。
  • 我很高兴你拿到了代码。这总是很好。
  • @JoopEggen 你的方法不是真的检查包围钻石的椭圆,而是只检查钻石吗?
  • @JoopEggen 是的,我是按照勾股定理的思路来思考的,多亏了你的解释,我才发现这里的不同之处在于它是缩放的,而不是平方的。感谢您向我展示这在几何上是如何工作的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-09
  • 2018-05-04
  • 2011-06-17
  • 2011-10-30
  • 1970-01-01
  • 2019-03-15
  • 1970-01-01
相关资源
最近更新 更多