旋转多边形对象

时间:2015-05-01 00:36:03

标签: java rotation applet polygon trigonometry

旋转小行星(多边形)

我正在尝试旋转小行星(多边形)以使它们看起来很漂亮。我通过多个数学方程式做到这一点。首先,我给个体小行星一个旋转速度:

        rotVel = ((Math.random()-0.5)*Math.PI/16);

然后我创建了多边形形状

        this.shape = new Polygon();

然后生成积分,

    for (j = 0; j < s; j++) {
        theta = 2 * Math.PI / s * j;
        r = MIN_ROCK_SIZE + (int) (Math.random() * (MAX_ROCK_SIZE - MIN_ROCK_SIZE));
        x = (int) -Math.round(r * Math.sin(theta)) + asteroidData[0];
        y = (int)  Math.round(r * Math.cos(theta)) + asteroidData[1];
        shape.addPoint(x, y);
    } 

最后,在循环中调用一个方法,在该方法中,它尝试将多边形及其点向下移动以及旋转它们。 (我只是粘贴旋转部件,因为另一个正在工作)

    for (int i = 0; i < shape.npoints; i++) {

       // Subtract asteroid's x and y position
        double x = shape.xpoints[i] - asteroidData[0];
        double y = shape.ypoints[i] - asteroidData[1];

        double temp_x =  ((x * Math.cos(rotVel)) - (y * Math.sin(rotVel)));
        double temp_y =  ((x * Math.sin(rotVel)) + (y * Math.cos(rotVel)));

        shape.xpoints[i] = (int) Math.round(temp_x + asteroidData[0]);
        shape.ypoints[i] = (int) Math.round(temp_y + asteroidData[1]);  
    }

现在,问题在于当它打印到屏幕上时,小行星似乎会变形“翘曲”。或者更确切地说,某些多边形点上的x和y位置浮动&#39;当然。

我注意到当我制作'rotVel&#39;是一个整数问题解决但小行星将以马赫速度旋转。所以我得出结论,问题必须在四舍五入,但无论我做什么,我都无法找到一种方法让它工作,因为Polygon对象需要一个整数数组。

有谁知道如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

你的问题肯定是由四舍五入到int引起的!第一个改进是使所有形状坐标都为double类型。这将解决您的大部分不必要的影响&#39;。

但即使使用double,您也可能遇到令人讨厌的舍入错误,以防您进行大量非常小的坐标更新。解决方案很简单:只需避免小行星点的迭代更新。每次,您根据以前的坐标更新坐标,舍入误差将变得更糟。

相反,将旋转角度的字段添加到形状并增加它而不是点本身。在绘制形状之前,通过将旋转应用于点来计算最终位置。请注意,这永远不会改变点数。

您也可以将此概念扩展到其他转换(例如翻译)。你得到的是每种形状/物体的某种局部坐标系。形状的点在局部坐标系中定义。通过移动和旋转此系统,您可以将整个对象重新定位在空间的任何位置。

public class Shape {
    // rotation and position of the local coordinate system
    private double rot, x, y;

    // points of the shape in local coordinate system
    private double[] xp, yp;
    private int npoints;

    // points of the shape in world coordinates
    private int[][] wxp, wyp;
    private boolean valid;

    public void setRotation(double r) { this.rot = r; valid = false; }
    public void setPosition(double x, double y) { this.x = x; this.y = y; valid = false; }

    public void addPoint(double x, double y) {
        // TODO: add point to xp, yp
        valid = false;
    }

    public void draw(...) {
        if (!valid) {
            computeWorldCoordinates(wxp, wyp);
            valid = true;
        }

        // TODO: draw shape at world coordaintes wxp and wyp
    }

    protected void computeWorldCoordinates(int[] xcoord, int[] ycoord) {
        for (int i = 0; i < npoints; i++) {
            double temp_x = xp[i] * Math.cos(rot) - yp[i] * Math.sin(rot);
            double temp_y = xp[i] * Math.sin(rot) + yp[i] * Math.cos(rot);
            xcoord[i] = (int) Math.round(x + temp_x);
            ycoord[i] = (int) Math.round(y + temp_y);
        }
    }
}