Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是正六边形内的一点_Java_Algorithm_Geometry_Polygon - Fatal编程技术网

Java 是正六边形内的一点

Java 是正六边形内的一点,java,algorithm,geometry,polygon,Java,Algorithm,Geometry,Polygon,我正在寻求关于最佳方式的建议。我试图找出一个给定的点a:(a,b)是否在一个正六边形内,这个正六边形是由中心O:(x,y)和外接圆的直径定义的 对于这样一个简单的情况,使用光线投射或缠绕数来确定这一点似乎有些过分,我目前正在考虑寻找线OA的角度(从水平方向)和“归一化”(可能不是正确的词)将其转换为6个等边三角形中的一个,并查看该新点是否位于该三角形内 我觉得我错过了一些简单的东西,有一个简单的方法(或者如果我真的很幸运的话,一个JavaAPI)可以简单有效地做到这一点 谢谢你的帮助 编辑:六边

我正在寻求关于最佳方式的建议。我试图找出一个给定的点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;
}