是正六边形内的一个点

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

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

我觉得我错过了一些简单的东西,并且有一种简单有效的方法(或者,如果我真的很幸运,Java API)。

谢谢你的帮助。

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

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

例如,右上角有等式:

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

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

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

如果将问题减少到在单个象限中检查{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)

这就是我一直在使用的:

 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的坐标,在这里可以更容易地检查边界。

在此处输入图像描述

看起来你知道一般的解决方案:“看起来有点矫枉过正……”。 所以这是我的想法:

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

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

公式可以在这里找到: http : //mathworld.wolfram.com/Hexagon.html

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

第一个意思是关键点,后者意味着它已经出局。

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

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

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

从点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”是度;)

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

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

我确实修改了该function供我使用,我发现我的版本更清晰。 这是打字稿(你只是斜视和它的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[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; }