2012-04-04 3 views
1

Я делаю эллипсоид из вокселей, и у меня есть реализация, но он работает некорректно, поскольку последние несколько часов я пытался добиться успеха.Проблемы с эллипсоидом Bresenham 3d

Вот как это работает:

  • Он рисует 2D эллипсов вниз по оси Z с использованием алгоритма окружности Bresenham
  • Он вычисляет координаты окружности идти вперед и один собирается из стороны в сторону
  • Это использует эти координаты, радиусы для X и Y

Вот что работает:

  • Spheres являются совершенными
  • Эллипсоиды совершенны когда
    • г> х и г> у
    • х == у

Вот что нет:

  • Эллипсоиды, когда x! = Y

Я предполагаю, что его потому, что я рисую ломтики от центра к передней каждый раз , но я не знаю. Ниже моя реализация, это беспорядок. Я быстро очистил его, чтобы это было понятно в какой-то степени. Кроме того, я сохраняю оптимизацию для более позднего, я просто хочу, чтобы она работала сейчас.

Я не буду показывать свою реализацию алгоритма круга, потому что я ЗНАЮ, что он работает, и это просто заставило бы этот вопрос дольше. Поэтому я объясню им две функции.

private List<Integer> getSlice(int rx, int ry) получает исходный результат от запуска алгоритма круга Bresenham, без необходимости в симметрии. Он возвращает результат, поскольку список x, y приводит к этому порядку.

public void generateEllipse(int z, int cx, int cy, int cz, int rx, int ry) генерирует эллипс с данной информацией и отображает координаты с помощью симметрии, они будут отображаться на экране.

ArrayList<Integer> s = getSlice(rz, rx); 
ArrayList<Integer> s2 = getSlice(rz, ry); 

int cap = Math.max(s2.size(), s.size()); 

while (s.size() > 1) 
{ 
    int x = 0; 
    int z = 0; 
    int z2 = 0; 
    int y2 = 0; 

    int i = cap - 2; 

    if (s.size() > i) 
    { 
     z = s.get(i); 
     x = s.get(i + 1); 

     s.remove(i + 1); 
     s.remove(i); 
    } 

    if (s2.size() > i) 
    { 
     z2 = s2.get(i); 
     y2 = s2.get(i + 1); 

     s2.remove(i + 1); 
     s2.remove(i); 
    } 

    if (x != 0 && y2 != 0) 
     generateEllipse(z, cx, cy, cz, x, y2); 

    cap = Math.max(s2.size(), s.size()); 

Я задал подобный вопрос через неделю или две назад (да у меня были проблемы, которые долго :() и получил ответ, я реализовал его, и он работал, но я не был удовлетворен, Я хочу, чтобы номера чисел с плавающей запятой не совпадали. См. 3D Ellipsoid out of discrete units.

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

EDIT:

Я получил х> у работы путем добавления

else if (y2 < x && ry - y2 != 0) 
    generateEllipse(z, cx, cy, cz, x, ry - y2); 

и || r - y2 == 0 в первый тест на дне.

Я не слишком уверен, почему это сработало, теперь я это выясню. Но у меня все еще возникают проблемы с y> x. Кто угодно?

EDIT2:

Теперь, когда я смотрю на нее, она отличается от у = х эллипсоида, назад к чертежной доске.

EDIT3:

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

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

На снимке вы не можете видеть, но маленький эллипс на самом деле находится в нескольких кварталах от большого эллипса. Это вызвано тем, что из эллипсов не рисуется, что вызвано списками, не имеющими данных. Фактический маленький эллипс эллипса вызван тем, что алгоритм рисует два октанта, оба из которых хранятся в списке от getSlice(...).

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

I итерация для while(!s.isEmpty()) и определение двух новых значений вне цикла: incX = s.size и incY = s1.size Я проверяю, соответствуют ли их значения z, если нет, то я исправлю это. Я думаю, что я получу значения, испытаю самый большой список, и если они не совпадут, то уменьшите значение inc наименьшего списка на два и получите старые значения.

Я тестирую !s.isEmpty(), потому что два списка будут пустыми одновременно. Также, используя эллипсы, я буду использовать то, что значение z, потому что, опять же, оба они должны быть равны.

Если это неправильно, то, я думаю, у меня есть этот документ, который я нашел, чтобы пройти: http://www.cs.sunysb.edu/vislab/wordpress/pdf/398.pdf.

ответ

2

Спасибо за тех, кто смотрел этот (хотя я не получил никакого ответа :(), я устанавливаю этот ответ, потому что проблема решена, код выглядит следующим образом:

ArrayList<Integer> s = getSlice(rz, rx); 
    ArrayList<Integer> s2 = getSlice(rz, ry); 

    boolean yMax = Math.max(s2.size(), s.size()) == s2.size(); 

    int decX = s.size() - 1; 
    int decY = s2.size() - 1; 

    boolean done = false; 

    while (!done) 
    { 

     int x = 0; 
     int z = 0; 
     int z2 = 0; 
     int y = 0; 

     y = s2.get(decY--); 
     z2 = s2.get(decY--); 

     x = s.get(decX--); 
     z = s.get(decX--); 

     if (z != z2) 
     { 
      if (yMax) 
      { 
       decX += 2; 
       x = s.get(decX); 

       s2.remove(decY + 2); 
       s2.remove(decY + 1);  
      } 
      else 
      { 
       decY += 2; 
       y = s2.get(decY); 

       s.remove(decX + 2); 
       s.remove(decX + 1); 
      } 

      z = z < z2 ? z : z2; 
     } 
     else 
     { 
      s.remove(decX + 2); 
      s.remove(decX + 1);    

      s2.remove(decY + 2); 
      s2.remove(decY + 1);  
     } 

     if (y != 0 && x != 0) 
      generateEllipse(z, cx, cy, cz, x, y); 

     done = yMax ? s2.isEmpty() : s.isEmpty(); 
    } 

Все, что нужно сделать сейчас, это оптимизация. Я все еще буду читать эту статью, она охватывает другие темы, интересные и полезные для моей программы :).

Проблема заключалась в том, что я не учитывал разные размеры каждого списка, если кривая менее крутая, чем другая, у нее будет больше координат. Z всегда будет одинаковым при rx == ry. Это позволило мне нарисовать сферы и перебросить назад эллипсоиды.

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

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

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

+0

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

+0

@MichaelSlade Да, есть сетка. Это видно на моей фотографии. Также на стороне примечания, я хотел упомянуть тест для 'done' только существует, потому что неожиданно списки не равны, когда это делается. Я уверен, что это простое исправление, но я заметил, что это проблема, когда rz больше, чем rx или ry и rx! = Ry. Я буду больше играть, думаю, исправление прост. – SpaceFace

+0

Prupel - Я пытался найти способ связаться с вами. Кажется, вы сделали целую массу потрясающей работы над этим для minecraft, и я бы хотел использовать ваши алгоритмы в модуле с открытым исходным кодом. Свяжитесь со мной, если вы думаете, что не возражаете, если вы не захотите разум разделяет их со мной. Приветствую человека! espernet irc: mikee – Mikee

Смежные вопросы