2013-10-02 4 views
9

Итак, я программирую рекурсивную программу, которая должна нарисовать снежинки Коха с использованием OpenGL, и у меня есть программа, в основном работающая, за исключением одной крошечной проблемы. Чем глубже рекурсия, тем больше получаются две особые вершины. Картинки внизу.Небольшая ошибка в реализации снежинки Коха

EDIT: Меня не интересует аспект OpenGL, у меня есть эта часть. Если вы не знаете OpenGL, все, что делает glVertex, это провести линию между двумя вершинами, указанными в двух вызовах метода. Притворите его 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 (Все хорошо):

enter image description here

N = 1 (Может быть, немного Бенди, возможно)

enter image description here

N = 5 (WAT)

enter image description here

+0

Без знания алгоритма: Это может быть проблема с двойной ошибкой. –

ответ

1

Итак, оказывается, что я самый тупой человек в живых.

Спасибо всем за попытку, я ценю помощь.

Этот код предназначен для обработки равностороннего треугольника, его очень специфического для этого (вы можете сказать по углам).

Я положил треугольник с высотой, равной основанию (не равностороннему). Когда я фиксировал входной треугольник, все работает отлично.

4

Я не вижу никакой очевидной проблемы по коду. Однако у меня есть теория о том, что происходит.

Кажется, что все точки на графике основаны на местоположениях точек, которые были до него. Таким образом, любые ошибки округления, возникающие во время этого процесса, в конечном итоге начинают накапливаться, в конечном итоге заканчиваясь тем, что он собирается сбежать и уйти.

Что бы я сделал для стартеров, это вычисление начальной и конечной точек каждого сегмента перед рекурсией, чтобы ограничить влияние ошибок округления внутренних вызовов.

+0

Ну, конечные конечные точки начала всей кривой предоставляются пользователем, это V1, V2, V3 (начальный треугольник). Невозможно рассчитать внутренние точки перед рукой, что и вся рекурсия. –

+0

Чтобы немного изменить свое предложение и быть более конкретным: способ, которым я бы это сделал, - разделить это на то, что «штук» рисовать. Начальный уровень состоит из трех частей, представленных в виде строк, если n = 0. При n> 0 каждая часть будет делать следующее: Получить начальные точки A и конечную точку B (предположительно переданные как параметры). Вычислите точки AB 'и AB' 'для точек 1/3 и 2/3 пути в. Определите A-AB' и AB '' - B как две новые части, затем вычислите точку AB * «шипа», и определите AB'-AB * и AB * -AB '' как новые фигуры. Recurse. Это позволит предотвратить крупномасштабные ошибки округления. – Smallhacker

2

Одна вещь о снежинке Коха заключается в том, что алгоритм будет приводить к проблеме округления один раз (это рекурсивный и все округлые ошибки складываются). Трюк заключается в том, чтобы держать его как можно дольше. Есть три вещи, которые вы можете сделать:

  • Если вы хотите получить более подробную информацию, то можете расширить возможности Double. Вам нужно будет использовать свой собственный диапазон координат и преобразовывать их, каждый раз, когда вы на самом деле рисуете на экране, для отображения координат. Ваши собственные координаты должны масштабироваться и показывать последний шаг рекурсии (последний треугольник) в системе координации, например. 100x100. Затем вычислите три новых треугольника поверх этого, преобразуйте в координаты экрана и покрасьте.
  • Линия dir=Math.PI/3; делится на 3 вместо (double) 3.Добавить . после 3
  • Убедитесь, что вы используете Point2D.Double в любом месте. Ваш код должен сделать это, но я бы написал его везде.

Вы выиграли игру, когда у вас все еще есть хорошая снежинка, но получите Stackoverflow.

+0

Мне пришлось сделать эту маленькую шутку с помощью Stackoverflow. Я был вынужден к моим генам ;-) – jboi

+0

Компилятор преобразует 3 в 3.0; не требуется никаких действий. – duffymo

+0

Наверное, да. эти вещи всегда заставляют меня нервничать, когда я их вижу. Самый важный момент - первый. – jboi