【问题标题】:Possible Java/Eclipse compiler bug? (no, just more stupidity as usual)可能的 Java/Eclipse 编译器错误? (不,只是像往常一样愚蠢)
【发布时间】:2015-06-23 01:56:10
【问题描述】:

所以我正在制作一个简单的 3D 图形程序。但是我有一个与图形没有直接关系的错误。

我有一个 Triangle 类,可以平移、旋转等。我还有一个 Shape 类,可以从这些三角形中生成形状。所以当我想移动一个形状时,我可以使用一个形状对象来统一移动所有的形状。

当我尝试移动一个形状时会出现这个错误。发生的事情是翻译意味着传递给连续的所有三角形。但其中一些人的翻译翻了一番。

经过大量调试,我发现了一些奇怪的结果,因为似乎某些顶点承担了上一次迭代顶点的平移,但只有其中一些。 因此,将翻译翻倍。

我会附上屏幕截图,但我的声望不够高。

到目前为止,我唯一的解释是某些顶点共享数据。或者其中一些顶点的数据在运行时被存储并被使用,因为这些顶点是相似的。

形状类 -> 持有三角形对象

三角形类 -> 拥有 3 个顶点对象 -> 还有显示和翻译的方法

顶点类 -> 持有双 x、双 y、双 z

可能值得注意的是 shape 类中不同三角形的一些顶点具有相同的顶点。但这应该不是问题,因为它们会传递给不同的三角形。

Index: 0 // First Triangle
next check: 1.0 // The z value of the first vertex int the next triangle(index 1) 
1.0 // z val. before translation
1.010356248053852, dz: 0.009999833334166664 // z val. after translation
1.0 // z val. before translation
1.010356248053852, dz: 0.009999833334166664 // z val. after translation
1.0 // z val. before translation
1.010356248053852, dz: 0.009999833334166664 // z val. after translation

Index: 1 // Second triangle
next check: 1.5 // next check
1.010356248053852 // z val. before translation
1.0207124961077039, dz: 0.009999833334166664 // z val. after translation

最后两行是重要的。第一个应该说 1.0,正如索引 0 所说的那样(下一次检查:1.0)。 然而,当我们到达第二个三角形时,它已经平移了第一个三角形。因此,再次赋予效果。

这不会发生在所有人身上。

提前感谢您对文章的任何帮助或指导。

public Triangle(Point x, Point y, Point z, byte r, byte g, byte b, double fov)
{
    points = new Point[]{x, y, z};

    m_r = r;
    m_g = g;
    m_b = b;

    FOV = fov;
}
public void move(double x, double y, double z, double delta)
{
    for (int i = 0; i < 3; i++)
    {
        points[i].setDX(points[i].getDX() + (x * delta));
        points[i].setDY(points[i].getDY() + (y * delta));
        points[i].setDZ(points[i].getDZ() + (z * delta));
    }
}

/\重要的三角码

public void move(double x, double y, double z, double delta)
{
    for (int i = 0; i < index.length; i++)
    {
        rs.triMove(index[i], x, y, z, delta);
    }
}

/\形状移动代码 rs 是所有三角形的集合空间,但在添加此错误之前就开始了。索引是三角形在 rs 数组中的位置。

public void triMove(int index, double x, double y, double z, double delta)
{
    triangles.get(index).move(x, y, z, delta);
}

/\RS类动作代码。

一些可能有用的图片。 此刻很好/\当静止时

/\ 现在有点坏了。其中两个的 z 值翻了一番,另外两个没问题。

但是它们仍然是相同的点出错和相同的损坏量?

但有些东西非常奇怪的是,如果同一个记录是由四个三角形组成的。 但显然,这是一种破解方法,它不适用于更复杂的形状。

【问题讨论】:

  • 如果您认为自己发现了编译器错误,那么您可能还没有。
  • 这是Is Floating Point Math Broken的骗子吗?
  • 您应该包含一个MCVE 以允许其他人从外部测试您的代码和相关问题。
  • 没有源码很难说,但每次看到“不正确”的浮点值,很可能与对浮点数性质的理解泄露有关:epramono.blogspot.com.au/2005/01/double-vs-bigdecimal.html跨度>
  • 是的,我认为这是我的错,但我一直在寻找这个错误的日子,但一无所获。所以我有些幼稚的乐观。

标签: java eclipse


【解决方案1】:

这里有点摸不着头脑,因为您发布了这么少的代码,很难知道实际问题是什么,但这对我来说真的很突出:

可能值得注意的是 shape 类中不同三角形的一些顶点具有相同的顶点。但这应该不是问题,因为它们会传递给不同的三角形。

我会让每个Triangle 复制每个输入Point,以确保它们不会干扰另一个Triangle 的点。

即:

public Triangle(Point x, Point y, Point z, byte r, byte g, byte b, double fov)
{
    // This is just an example since I have no idea what your
    // Point class actually looks like
    points = new Point[]{
        new Point(x.getX(), x.getY(), x.getZ()),
        new Point(y.getX(), y.getY(), y.getZ()),
        new Point(z.getX(), z.getY(), z.getZ()),
    };

    m_r = r;
    m_g = g;
    m_b = b;

    FOV = fov;
}

更新:

为了解释发生了什么,这里有一个简短的例子:

Point.java

public class Point {
    int x;
    int y;

    public Point(final int x, final int y) {
        this.x = x;
        this.y = y;
        System.out.printf("Created point %s at (%s,%s)%n", this, x, y);
    }

    void move(int dx, int dy) {
        x += dx;
        y += dy;
        System.out.printf("Moved point %s (%s,%s) from (%s,%s) to (%s,%s)%n", this, dx, dy, x - dx, y - dy, x, y);
    }
}

Triangle.java:

public class Triangle {
    Point a;
    Point b;
    Point c;

    public Triangle(final Point a, final Point b, final Point c) {
        this.a = a;
        this.b = b;
        this.c = c;
        System.out.printf("Created triangle %s with points (%s, %s, %s)%n", this, this.a, this.b, this.c);
    }

    void move(int dx, int dy) {
        System.out.printf("Moving triangle %s (%s,%s)%n", this, dx, dy);
        a.move(dx, dy);
        b.move(dx, dy);
        c.move(dx, dy);
    }
}

Demo.java

public class Demo {

    public static void main(String[] args) {
        Point p1 = new Point(0, 0);
        Point p2 = new Point(1, 0);
        Point p3 = new Point(0, 1);
        Point p4 = new Point(1, 1);

        Triangle t1 = new Triangle(p1, p2, p3);
        Triangle t2 = new Triangle(p2, p3, p4);

        t1.move(1, 1);
        t2.move(1, 1);
    }
}

运行时,会产生以下输出:

Created point Point@448139f0 at (0,0)
Created point Point@7cca494b at (1,0)
Created point Point@7ba4f24f at (0,1)
Created point Point@3b9a45b3 at (1,1)
Created triangle Triangle@7699a589 with points (Point@448139f0, Point@7cca494b, Point@7ba4f24f)
Created triangle Triangle@58372a00 with points (Point@7cca494b, Point@7ba4f24f, Point@3b9a45b3)
Moving triangle Triangle@7699a589 (1,1)
Moved point Point@448139f0 (1,1) from (0,0) to (1,1)
Moved point Point@7cca494b (1,1) from (1,0) to (2,1)
Moved point Point@7ba4f24f (1,1) from (0,1) to (1,2)
Moving triangle Triangle@58372a00 (1,1)
Moved point Point@7cca494b (1,1) from (2,1) to (3,2)
Moved point Point@7ba4f24f (1,1) from (1,2) to (2,3)
Moved point Point@3b9a45b3 (1,1) from (1,1) to (2,2)

如您所见,因为两个三角形共享一些点对象,所以这些点被移动了两次。

如果我们将Triangle 中的构造函数改为如下所示:

public Triangle(final Point a, final Point b, final Point c) {
    this.a = new Point(a.x, a.y);
    this.b = new Point(b.x, b.y);
    this.c = new Point(c.x, c.y);
    System.out.printf("Created triangle %s with points (%s, %s, %s)%n", this, this.a, this.b, this.c);
}

我们得到以下输出:

Created point Point@448139f0 at (0,0)
Created point Point@7cca494b at (1,0)
Created point Point@7ba4f24f at (0,1)
Created point Point@3b9a45b3 at (1,1)
Created point Point@7699a589 at (0,0)
Created point Point@58372a00 at (1,0)
Created point Point@4dd8dc3 at (0,1)
Created triangle Triangle@6d03e736 with points (Point@7699a589, Point@58372a00, Point@4dd8dc3)
Created point Point@568db2f2 at (1,0)
Created point Point@378bf509 at (0,1)
Created point Point@5fd0d5ae at (1,1)
Created triangle Triangle@2d98a335 with points (Point@568db2f2, Point@378bf509, Point@5fd0d5ae)
Moving triangle Triangle@6d03e736 (1,1)
Moved point Point@7699a589 (1,1) from (0,0) to (1,1)
Moved point Point@58372a00 (1,1) from (1,0) to (2,1)
Moved point Point@4dd8dc3 (1,1) from (0,1) to (1,2)
Moving triangle Triangle@2d98a335 (1,1)
Moved point Point@568db2f2 (1,1) from (1,0) to (2,1)
Moved point Point@378bf509 (1,1) from (0,1) to (1,2)
Moved point Point@5fd0d5ae (1,1) from (1,1) to (2,2)

这可以正常工作,因为两个三角形不再共享任何点对象。

避免此类陷阱的一个好方法是始终复制构造函数参数 (defensive copying) 或使用 immutable objects

【讨论】:

  • 大概就是这样。下一个错误 - 一些形状共享三角形:D
  • 我更新了一个相当长的例子来说明正在发生的事情。
  • 非常感谢。从来不知道事情是这样发生的。好吧,我希望不要再发生了。
猜你喜欢
  • 2013-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-05
  • 1970-01-01
相关资源
最近更新 更多