Есть очередной вопрос алгоритмического плана.
У меня используются алгоритмы Брезенхема для получения прямых, окружностей и эллипсов. Сейчас речь про окружности. Функция, которая генерит окружность, выдаёт массив (одномерный) с набором точек целевой окружности. Точки в массив набросаны как попало, потому как алгоритм генерит дугу для одного квадранта, и зеркалит их в оставшиеся три.
Что мне требуется - какой-то вариант, который бы позволил из выбранной точки, сделать несколько шагов по окружности (по часовой или против часовой стрелке). Т.е. я беру произвольную точку из массива и хочу обойти всю окружность из точки в точку.
Как это можно сделать? Как-то отсортировать массив? Но как? Как-то хитро его запонять? Опять же - как?
Для наглядности, есть окружность, координаты точек которой навалены в массив:
а в массив не проще запихать сгенеренную окружность
типа Circle:array[...] of Tpoint; ?
и потом хоть рандомом хоть чем - выбирай оттуда точку и вперед или назад двигай по индексу
либо извратно каждому элементу(точке окружности) в твоем одномерном массиве присвоить уникальный символ (только возникнет косяк сиволов то 256)
потом сканируешь свой получившийся бокс на наличие определенного символа и получаешь его координаты
ну э... брезенхем вроде для каждой 1/8 (или 1/4, смотря что за реализация) части окружности генерит точки подряд по обходу.
только обычно полученную точку сразу зеркалят в 8 (или 4), поэтому порядок получается хер знает какой.
если же эти 1/8-окружностей генерить последовательно (а не параллельно), то получим что надо.
только тут может чуток медленнее получиться (в константу раз).
еще можно оставить и параллельную генерацию, только для каждой новой точки вычислять ее позицию в массиве
и писать именно туда.
Мне кажется что зная координаты центра и имея 8 прилегающих клеток (две из которых являются частью окружности) можно вычислить какая будет соответствовать движению по часовой, а какая против.
Брезенхем генерит 4 или 8 упорядоченных последовательностей. Достаточно их разместить в правильном порядке и собрать в одну цепочку. Возможно последовательности отзеркалить надо будет (4 из для 8-кратного Брезенхема).
Короче. Если надо отсортировать массив - могу подсказать. Но можешь прислушаться к людям и сразу генерить упорядоченный массив. А если отсортировать, то вот:
1) берем квиксорт
2) на вход квиксорта, как известно, передается функция сравнения (мы ее сами пишем)
3) функция сравнения должна сравнить atan2(y,x) двух точек (то есть их углы относительно оси x)
4) профит!
одно но: первая точка будет не та, что ты задал, но тебя это не должно смущать, когда массив уже упорядочен против часовой :)
Я так понимаю что нужно написать некий итератор (http://ru.wikipedia.org/wiki/%D0%98%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80) который при каждом запросе выдает следующую точку.
- Запоминаешь в нем начальные условия: центр окружности, радиус, точку с которой двигаться;
- Определяешь квадрант точки, направление (по часовой или против);
- Запускаешь вхолостую брезенхемовский алготрим до тех пор пока не достигаешь нужной точки (или если хватит смекалки - выводишь параметры ошибки и всего такого для точки математически);
- При каждом вызове делаешь шаг а алгоритме Брезенхема чтоб получить следующую координату, если выходишь за границы квадранта - запускаешь его заново для следующего квадранта.
Мне кажется это проще всего, количество временных переменных минимально, работа относительно предсказуема.
Gambit_oz написал:
а в массив не проще запихать сгенеренную окружность
типа Circle:array[...] of Tpoint; ?
Shirson:
Функция, которая генерит окружность, выдаёт массив (одномерный) с набором точек целевой окружности.
и потом хоть рандомом хоть чем - выбирай оттуда точку и вперед или назад двигай по индексу
Проблема в том, что точки в массиве не по порядку идут. Брезенхем генерит часть окружности и остальное зеркалит 4 раза.
RichDad написал:
Короче. Если надо отсортировать массив - могу подсказать.
...
3) функция сравнения должна сравнить atan2(y,x)
Не имеет смысла сортировать Березенхем тригонометрической функцией :) Это как в ассемблер вставлять скриптовую часть.
0nni написал:
Мне кажется что зная координаты центра и имея 8 прилегающих клеток (две из которых являются частью окружности) можно вычислить какая будет соответствовать движению по часовой, а какая против.
Дело в том, что у меня не битмап, а одномерный массив с координатами точек.
rip написал:
ну э... брезенхем вроде для каждой 1/8 (или 1/4, смотря что за реализация) части окружности генерит точки подряд по обходу.
только обычно полученную точку сразу зеркалят в 8 (или 4), поэтому порядок получается хер знает какой.
если же эти 1/8-окружностей генерить последовательно (а не параллельно), то получим что надо.
только тут может чуток медленнее получиться (в константу раз).
еще можно оставить и параллельную генерацию, только для каждой новой точки вычислять ее позицию в массиве
и писать именно туда.
bsivko написал:
Брезенхем генерит 4 или 8 упорядоченных последовательностей. Достаточно их разместить в правильном порядке и собрать в одну цепочку. Возможно последовательности отзеркалить надо будет (4 из для 8-кратного Брезенхема).
Zer0 написал:
- Запоминаешь в нем начальные условия: центр окружности, радиус, точку с которой двигаться;
- Определяешь квадрант точки, направление (по часовой или против);
- Запускаешь вхолостую брезенхемовский алготрим до тех пор пока не достигаешь нужной точки (или если хватит смекалки - выводишь параметры ошибки и всего такого для точки математически);
- При каждом вызове делаешь шаг а алгоритме Брезенхема чтоб получить следующую координату, если выходишь за границы квадранта - запускаешь его заново для следующего квадранта.
Жуть какая. Но жуть правильная, как мне кажется. Это тоже попробую (это даже больше подходит к тому, что мне надо)