Java 多边形相交失败,碰撞“;“尺寸”;太大

Java 多边形相交失败,碰撞“;“尺寸”;太大,java,collision-detection,polygon,Java,Collision Detection,Polygon,好的,我想做一个简单的小行星克隆。除了碰撞检测之外,一切正常 我有两个不同的版本,第一个使用java.awt.geom.Area: // polygon is a java.awt.Polygon and p is the other one final Area intersect = new Area(); intersect.add(new Area(polygon)); intersect.intersect(new Area(p.polygon)); return !intersect

好的,我想做一个简单的小行星克隆。除了碰撞检测之外,一切正常

我有两个不同的版本,第一个使用java.awt.geom.Area:

// polygon is a java.awt.Polygon and p is the other one
final Area intersect = new Area();
intersect.add(new Area(polygon));
intersect.intersect(new Area(p.polygon));
return !intersect.isEmpty();
这就像一个符咒。。。如果您不关心只有120颗小行星的40%CPU:(

因此,我在网上搜索著名的分离轴定理,因为我不擅长数学,我从中获取了实现,并将其转换为适合我的Java需求:

public double dotProduct(double x, double y, double dx, double dy) {
        return x * dx + y * dy;
    }

    public double IntervalDistance(double minA, double maxA, double minB,
            double maxB) {
        if (minA < minB) {
            return minB - maxA;
        } else {
            return minA - maxB;
        }
    }

    public double[] ProjectPolygon(double ax, double ay, int p, int[] x, int[] y) {
        double dotProduct = dotProduct(ax, ay, x[0], y[0]);
        double min = dotProduct;
        double max = dotProduct;
        for (int i = 0; i < p; i++) {
            dotProduct = dotProduct(x[i], y[i], ax, ay);
            if (dotProduct < min) {
                min = dotProduct;
            } else if (dotProduct > max) {
                max = dotProduct;
            }
        }
        return new double[] { min, max };
    }

    public boolean PolygonCollision(Asteroid ast) {
        int edgeCountA = points;
        int edgeCountB = ast.points;
        double edgeX;
        double edgeY;

        for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++) {
            if (edgeIndex < edgeCountA) {
                edgeX = xp[edgeIndex] * 0.9;
                edgeY = yp[edgeIndex] * 0.9;
            } else {
                edgeX = ast.xp[edgeIndex - edgeCountA] * 0.9;
                edgeY = ast.yp[edgeIndex - edgeCountA] * 0.9;
            }

            final double x = -edgeY;
            final double y = edgeX;
            final double len = Math.sqrt(x * x + y * y);
            final double axisX = x / len;
            final double axisY = y / len;

            final double[] minMaxA = ProjectPolygon(axisX, axisY, points, xp,
                    yp);
            final double[] minMaxB = ProjectPolygon(axisX, axisY, ast.points,
                    ast.xp, ast.yp);

            if (IntervalDistance(minMaxA[0], minMaxA[1], minMaxB[0], minMaxB[1]) > 0) {
                return false;
            }
        }
        return true;
    }
公共双点积(双x、双y、双dx、双dy){
返回x*dx+y*dy;
}
公共双间隔距离(双minA、双maxA、双minB、,
双最大值){
如果(最小值<最小值){
返回minB-maxA;
}否则{
返回minA-maxB;
}
}
公共双[]项目多边形(双ax、双ay、int p、int[]x、int[]y){
双点积=点积(ax,ay,x[0],y[0]);
双最小=点积;
double max=点积;
对于(int i=0;i最大值){
max=dotProduct;
}
}
返回新的双精度[]{min,max};
}
公共布尔多边形碰撞(小行星ast){
int edgeCountA=点;
int edgeCountB=ast.points;
双边缘;
双边缘;
对于(int edgeIndex=0;edgeIndex0){
返回false;
}
}
返回true;
}
它是有效的…有点。实际上,当使用这个代码时,小行星的“碰撞外壳”似乎太大了,它的大小是小行星的1.2倍。我不知道为什么

这里有两张图片供比较:

正如你所希望看到的,图片一中的小行星比图片2中使用SAT代码的小行星密度要大得多


有什么想法吗?或者有人知道我可以使用的Java多边形实现的交叉点测试吗?

看起来你的第二个结果是进行碰撞检测,就好像多边形是圆,其半径设置为多边形中心最远的点。我见过的大多数碰撞检测内容都会创建多边形可以放入的简单边界框(圆形或矩形)。只有当两个边界框相交时(一个简单得多的计算),才能继续进行更详细的检测。也许适当的算法仅用于边界框计算器

编辑: 还有,来自维基百科

如果其中一个物体不是凸的,则该定理不适用

图像中的许多小行星都有凹面