9

所以我正在编写一个递归程序,该程序应该使用 OpenGL 绘制科赫的雪花,除了一个小问题外,我的程序基本上可以工作。递归越深,得到的 2 个特定顶点就越奇怪。图片在底部。

编辑:我并不真正关心 OpenGL 方面,我已经把那部分记下来了。如果您不了解 OpenGL,glVertex 所做的只是在 2 个方法调用中指定的两个顶点之间画一条线。假装它的drawLine(v1,v2)。一样的区别。

我怀疑我的找点方法是罪魁祸首,但我找不到任何看起来不正确的东西。

我遵循基本标准的绘图方法,这里是相关的代码片段

(V 代表顶点 V1 是左下角,v2 是右下角,v3 是上角):

        double dir = Math.PI;
        recurse(V2,V1,n);

        dir=Math.PI/3;
        recurse(V1,V3,n);

        dir= (5./3.)* Math.PI ;
        recurse(V3,V2,n);

递归方法:

public void recurse(Point2D v1, Point2D v2, int n){
    double newLength = v1.distance(v2)/3.;
    if(n == 0){
        gl.glVertex2d(v1.getX(),v1.getY());
        gl.glVertex2d(v2.getX(),v2.getY());

    }else{

        Point2D p1 = getPointViaRotation(v1, dir, newLength);
        recurse(v1,p1,n-1);
        dir+=(Math.PI/3.);

        Point2D p2 = getPointViaRotation(p1,dir,newLength);
        recurse(p1,p2,n-1);
        dir-=(Math.PI*(2./3.));

        Point2D p3 = getPointViaRotation(p2, dir, newLength);
        recurse(p2,p3,n-1);
        dir+=(Math.PI/3.);

        recurse(p3,v2,n-1);
    }

}

我真的怀疑我的数学是问题所在,但这对我来说是正确的:

public static Point2D getPointViaRotation(Point2D p1, double rotation, double length){
    double xLength = length * Math.cos(rotation);
    double yLength = length * Math.sin(rotation);
    return new Point2D.Double(xLength + p1.getX(), yLength + p1.getY());
}

N = 0(一切正常):

在此处输入图像描述

N = 1(也许有点弯曲,也许)

在此处输入图像描述

N = 5 (WAT)

在此处输入图像描述

4

3 回答 3

4

我在代码方面看不到任何明显的问题。然而,我确实有一个关于会发生什么的理论。

图表中的所有点似乎都基于它之前的点的位置。因此,在此过程中发生的任何舍入错误最终都会开始累积,最终以失控和偏离而告终。

我将为初学者做的是在递归之前计算每个段的起点和终点,以限制内部调用的舍入误差的影响。

于 2013-10-02T07:28:38.417 回答
2

关于科赫的雪花的一件事是,该算法将导致一次舍入问题(它是递归的,并且所有舍入错误加起来)。诀窍是,尽可能长时间地保持它。你可以做三件事:

  • 如果您想获得更详细的信息,唯一的方法是扩展Double. 每次在屏幕上实际绘制时,您都需要使用自己的坐标范围并将它们转换为屏幕坐标。您自己的坐标应缩放并显示坐标系中的最后一个递归步骤(最后一个三角形),例如 100x100。然后在其上计算三个新三角形,转换为屏幕坐标并绘制。
  • 该行dir=Math.PI/3;除以 3 而不是(double) 3。在.后面加上3
  • 确保在Point2D.Double任何地方使用。你的代码应该这样做,但我会在任何地方明确地写它。

当你仍然有一个漂亮的雪花但得到一个Stackoverflow时,你赢了比赛。

于 2013-10-02T07:43:11.717 回答
1

所以,事实证明我是世上最愚蠢的人。

感谢大家的尝试,感谢您的帮助。

此代码旨在处理等边三角形,对此非常具体(您可以通过角度来判断)。

我放入一个高度等于底边的三角形(不是等边的)。当我修复输入三角形时,一切正常。

于 2013-10-02T18:55:47.580 回答