Java 是正六边形内的一点
我正在寻求关于最佳方式的建议。我试图找出一个给定的点a:(a,b)是否在一个正六边形内,这个正六边形是由中心O:(x,y)和外接圆的直径定义的 对于这样一个简单的情况,使用光线投射或缠绕数来确定这一点似乎有些过分,我目前正在考虑寻找线OA的角度(从水平方向)和“归一化”(可能不是正确的词)将其转换为6个等边三角形中的一个,并查看该新点是否位于该三角形内 我觉得我错过了一些简单的东西,有一个简单的方法(或者如果我真的很幸运的话,一个JavaAPI)可以简单有效地做到这一点 谢谢你的帮助Java 是正六边形内的一点,java,algorithm,geometry,polygon,Java,Algorithm,Geometry,Polygon,我正在寻求关于最佳方式的建议。我试图找出一个给定的点a:(a,b)是否在一个正六边形内,这个正六边形是由中心O:(x,y)和外接圆的直径定义的 对于这样一个简单的情况,使用光线投射或缠绕数来确定这一点似乎有些过分,我目前正在考虑寻找线OA的角度(从水平方向)和“归一化”(可能不是正确的词)将其转换为6个等边三角形中的一个,并查看该新点是否位于该三角形内 我觉得我错过了一些简单的东西,有一个简单的方法(或者如果我真的很幸运的话,一个JavaAPI)可以简单有效地做到这一点 谢谢你的帮助 编辑:六边
编辑:六边形的方向应确保其中一侧与水平面平齐。您可以使用六边形每一侧的方程式;有了它们,你可以知道一个给定的点是否与六边形的中心在同一个半平面上 例如,右上侧具有以下等式:
-sqrt(3)x - y + sqrt(3)/2 = 0
插入点的坐标,然后插入中心的坐标。如果结果具有相同的符号,则该点位于左下半平面(因此可能位于六边形内)
然后使用其他各边的方程式进行重复。请注意,此算法适用于任何凸多边形,看起来您知道一般解决方案:“使用它似乎有点过分……”。我的想法是: 计算点到中心的距离,我们称之为
l
然后,您可以将其与inradius(r
)和外接圆(r
)进行比较。若l
则点在六边形内,若l>r
则点在六边形外。如果r
,则必须分别检查每一侧,但由于r-r
非常小(十六进制边长度的13%),因此必须进行复杂计算的可能性很小
可以在这里找到公式:我首先检查点是在内切圆内(您可以轻松计算内切圆半径)还是在外切圆外(您已经有) 第一个意思是重点在,后一个意思是重点在 从统计学上讲,大多数输入点应该允许您根据上述简单测试做出决定
对于最坏的情况(点位于内接圆和外切圆之间),我认为您可以找到最接近该点的两个顶点,然后查看该点位于段V1V2的哪一侧(相对于O中心,是内部还是外部)。 特殊情况:点等于它所在的一个顶点=>点
如果我有一个更聪明的想法(或者如果我真的开始学习三角学),我会编辑答案让你知道:)如果你把问题归结为在一个象限中检查
{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);
}
公共布尔值IsInsideHexagon(浮点x0、浮点y0、浮点d、浮点x、浮点y){
浮点数dx=数学绝对值(x-x0)/d;
float dy=数学绝对值(y-y0)/d;
浮点a=0.25*数学sqrt(3.0);
返回(dy从点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”以度为单位;)这是我一直在使用的:
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;
}
public bool-InsideHexagon(浮点x,浮点y)
{
//根据内外半径检查长度(平方)
浮动l2=x*x+y*y;
如果(l2>1.0f)返回false;
如果(l2<0.75f)返回true;//(sqrt(3)/2)^2=3/4
//边境检查
浮点px=x*1.15470053838f;//2/sqrt(3)
如果(px>1.0f | | px<-1.0f)返回false;
浮球py=0.5f*px+y;
如果(py>1.0f | | py<-1.0f)返回false;
如果(px-py>1.0f | | px-py<-1.0f)返回false;
返回true;
}
px
和py
是投影到坐标系上的x
和y
坐标,在坐标系中更容易检查边界
您需要的是代码,以确定一个点是否位于凸多边形内,六边形是这种情况的一种特殊情况
下面是一个很好的答案:
我确实修改了该函数以供使用,我发现我的版本更清晰。它是typescript(你只是眯着眼睛,它是javascript):
函数向量(v:Vector):编号{
返回v[1].x-v[0].x;
}
功能向量(v:向量):数字{
返回v[1].y-v[0].y;
}
函数叉积(v1:Vector,v2:Vector):数字{
返回向量(v1)*向量(v2)-向量(v1)*向量(v2);
}
函数isInConvexPolygon(测试点:点,多边形:多边形):布尔{
// https://stackoverflow.com/a/34689268/516188
如果(多边形长度<3){
抛出“仅支持长度至少为3的多边形”;
}
//穿过多边形周围的所有边。计算
//向量叉积http://allenchou.net/2013/07/cross-product-of-2d-vectors/
//找出每条边的边的哪一侧是点。
//如果所有边的点位于同一侧,则该点位于内侧
设initCrossIsPositive=未定义;
对于(VarI=0;I0;
}否则{
if(initCrossIsPositive!==(交叉>0)){
返回false;
}
}
}
//所有的交叉产品都有相同的标志:我们在里面
返回true;
}
通过将晶格表示为
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;
}