是正六边形内的一个点

时间:2011-03-04 11:50:10

标签: java algorithm geometry polygon

我正在寻找有关最佳方法的建议。我试图找出给定点A:(a,b)是否在正六边形内,用中心O定义:( x,y)和外接圆的直径。

对于这样一个简单的情况,使用Ray-casting或Winding-number来确定这个似乎有点过分了,我现在正在寻找找到OA线的角度(从水平方向)的选项,以及将它标准化(可能不是正确的单词)到6个等边三角形中的一个,看看这个新点是否在这个三角形内。

我感觉我错过了一些简单的东西,并且有一种简单方法(或者如果我真的很幸运,一个Java API)来简单有效地完成这项工作。

感谢您的帮助。

编辑:六边形的方向使得其中一边与水平面平齐。

8 个答案:

答案 0 :(得分:8)

如果您将问题缩小到检查单个象限中的{x = 0, y = 0, d = 1},则可以非常简单。

public boolean IsInsideHexagon(float x0, float y0, float d, float x, float y) {
    float dx = Math.abs(x - x0)/d;
    float dy = Math.abs(y - y0)/d;
    float a = 0.25 * Math.sqrt(3.0);
    return (dy <= a) && (a*dx + 0.25*dy <= 0.5*a);
}
  • dy <= a检查该点是否低于水平边缘。
  • a*dx + 0.25*dy <= 0.5*a检查该点位于倾斜右边缘的左侧。

对于{x0 = 0, y0 = 0, d = 1},角点为(±0.25, ±0.43)(±0.5, 0.0)

答案 1 :(得分:6)

您可以使用六边形的每个边的方程式;通过它们,您可以了解给定点是否与六边形的中心位于同一半平面中。

例如,右上角有等式:

-sqrt(3)x - y + sqrt(3)/2 = 0

您可以插入点的坐标,然后插入中心的坐标。如果结果具有相同的符号,则该点位于左下半平面中(因此它可能位于六边形内)。

然后使用其他方面的方程式重复 请注意,此算法适用于任何凸多边形

答案 2 :(得分:6)

这就是我一直在使用的:

public bool InsideHexagon(float x, float y)
{
    // Check length (squared) against inner and outer radius
    float l2 = x * x + y * y;
    if (l2 > 1.0f) return false;
    if (l2 < 0.75f) return true; // (sqrt(3)/2)^2 = 3/4

    // Check against borders
    float px = x * 1.15470053838f; // 2/sqrt(3)
    if (px > 1.0f || px < -1.0f) return false;

    float py = 0.5f * px + y;
    if (py > 1.0f || py < -1.0f) return false;

    if (px - py > 1.0f || px - py < -1.0f) return false;

    return true;
}

pxpy是投射到坐标系上的xy的坐标,可以更容易地检查边界。

enter image description here

答案 3 :(得分:4)

看起来你知道一般解决方案:“使用......似乎有些过分了”。所以这是我的想法:

计算从点到中心的距离,我们称之为l

然后你可以将它与inradius(r)和circumradius(R)进行比较。如果l < r则点在六边形内,如果l > R则在外面。如果r < l < R那么你必须分别检查每一方,但由于R - r非常小(十六进制边长的13%),所以你必须进行复杂计算的可能性很小。

可在此处找到公式:http://mathworld.wolfram.com/Hexagon.html

答案 4 :(得分:1)

我首先检查点是否在内切圆内(您可以轻松计算内切圆半径)或外接圆(您已经拥有)之外。

第一个意味着该点在,后者意味着它已经出局。

据统计,大多数输入点应该允许您根据上述简单测试来决定。

对于最坏的情况(点位于内切圆和外接圆之间),我认为你可以找到最接近该点的两个顶点,然后看到该点V1V2的哪一侧(内部或外部,相对于O中心)。 特殊情况:点等于其中一个顶点=&gt;它在。

如果我有一个更聪明的想法(或者我将开始真正学习三角学),我会编辑答案让你知道:)

答案 5 :(得分:0)

从点P中减去六边形中心的位置,得到一个向量V.然后,用下面的向量取V的点积,这对应于三对相对的六边形边缘:

[0,1] ; the edges that are flat with the horizontal
[cos(30),sin(30)] ; the upper-right and lower-left edges
[cos(-30),sin(-30)] ; the lower-right and upper-left edges

如果任何点积的幅度大于从六边形中心到其中一个边缘的距离,则该点不在六边形内。

作为参考,矢量[a,b]和[c,d]的点积为a * c + b * d。

上面的角度“30”以度为单位;)

答案 6 :(得分:0)

你想要的是找出一个点是否在凸多边形内的代码,六边形是一个特殊情况。

这是一个很好的答案: https://stackoverflow.com/a/34689268/516188

我确实修改了该功能供我使用,我发现我的版本更清晰。这是打字稿(你只是斜视和它的javascript):

function vectorX(v: Vector): number {
    return v[1].x - v[0].x;
}

function vectorY(v: Vector): number {
    return v[1].y - v[0].y;
}

function crossProduct(v1: Vector, v2: Vector): number {
    return vectorX(v1)*vectorY(v2) - vectorY(v1)*vectorX(v2);
}

function isInConvexPolygon(testPoint: Point, polygon: Polygon): boolean {
    // https://stackoverflow.com/a/34689268/516188
    if (polygon.length < 3) {
        throw "Only supporting polygons of length at least 3";
    }
    // going through all the edges around the polygon. compute the
    // vector cross-product http://allenchou.net/2013/07/cross-product-of-2d-vectors/
    // to find out for each edge on which side of the edge is the point.
    // if the point is on the same side for all the edges, it's inside
    let initCrossIsPositive = undefined;
    for (var i=0;i<polygon.length;i++) {
        if (polygon[i].x === testPoint.x &&
            polygon[i].y === testPoint.y) {
            // testPoint is an edge of the polygon
            return true;
        }
        const curPointOnEdge = polygon[i];
        const nextPointOnEdge = polygon[(i+1)%polygon.length];
        const vector1 = <[Point,Point]>[curPointOnEdge, nextPointOnEdge];
        const vector2 = <[Point,Point]>[curPointOnEdge, testPoint];
        const cross = crossProduct(vector1, vector2);
        if (initCrossIsPositive === undefined) {
            initCrossIsPositive = cross > 0;
        } else {
            if (initCrossIsPositive !== (cross > 0)) {
                return false;
            }
        }
    }
    // all the cross-products have the same sign: we're inside
    return true;
}

答案 7 :(得分:0)

使用均质坐标对十六进制晶格有一个很好的概括,将晶格表示为与平面 x + y + z = 0相交的立方晶格,请参见https://www.redblobgames.com/grids/hexagons/#coordinates < / p>