Я работал над проектом визуализации для двумерных непрерывных данных. Это та вещь, которую вы можете использовать для изучения данных высот или температурных схем на 2D-карте. По сути, это действительно способ слияния 3-х измерений в 2-х мерный плюс цвет. В моей конкретной области исследований я не работаю с географическими данными о высоте, но это хорошая метафора, поэтому я буду придерживаться ее в этом посте.
Во всяком случае, на данный момент, у меня есть рендерер "с непрерывным цветом", которым я очень доволен:
Градиент - это стандартное цветовое колесо, где красные пиксели указывают координаты с высокими значениями, а фиолетовые пиксели указывают низкие значения.
Базовая структура данных использует некоторые очень умные (если я сам так говорю) алгоритмы интерполяции для обеспечения сколь угодно глубокого увеличения деталей карты.
Сейчас я хочу нарисовать некоторые топографические контурные линии (используя квадратные кривые Безье), но мне не удалось найти хорошую литературу, описывающую эффективные алгоритмы для нахождения этих кривых.
Чтобы дать вам представление о том, о чем я думаю, вот реализация бедного человека (где средство визуализации просто использует значение черного RGB всякий раз, когда сталкивается с пикселем, который пересекает линию контура):
Однако у этого подхода есть несколько проблем:
Области графика с более крутым наклоном приводят к более тонким (и часто ломаным) линиям топо. В идеале все линии топо должны быть непрерывными.
Области графика с более плоским наклоном приводят к более широким топографическим линиям (и часто целым областям черноты, особенно по внешнему периметру области рендеринга).
Итак, я смотрю на векторную графику для получения этих прекрасных, идеальных кривых толщиной 1 пиксель. Базовая структура алгоритма должна будет включать в себя следующие этапы:
На каждой дискретной высоте, где я хочу нарисовать линию топо, найдите набор координат, где высота по этой координате очень близка (учитывая произвольное значение эпсилона) к желаемой высоте.
Устранить лишние точки. Например, если три точки находятся на совершенно прямой линии, то центральная точка является избыточной, поскольку ее можно устранить, не меняя форму кривой. Аналогичным образом, с помощью кривых Безье часто можно устранить определенные точки привязки, отрегулировав положение соседних контрольных точек.
Соберите оставшиеся точки в последовательность так, чтобы каждый отрезок между двумя точками приближался к нейтральной по высоте траектории, и чтобы два отрезка никогда не пересекали пути. Каждая последовательность точек должна либо создавать замкнутый многоугольник, либо пересекать ограничивающую рамку области рендеринга.
Для каждой вершины найдите пару контрольных точек таким образом, чтобы результирующая кривая демонстрировала минимальную ошибку по отношению к избыточным точкам, исключенным на шаге № 2.
Убедитесь, что все элементы топографии, видимые в текущем масштабе рендеринга, представлены соответствующими линиями топо. Например, если данные содержат всплеск с большой высотой, но с очень маленьким диаметром, линии топо все равно должны быть нарисованы. Вертикальные элементы следует игнорировать, только если их диаметр меньше общей детализации рендеринга изображения.
Но даже при этих ограничениях я все еще могу думать о нескольких различных эвристиках для нахождения линий:
Найдите высшую точку в ограничительной рамке рендеринга. С этой высшей точки двигайтесь вниз по нескольким различным траекториям. Каждый раз, когда линия пересечения пересекает порог возвышения, добавьте эту точку в область, относящуюся к отметке. Когда путь прохождения достигает локального минимума, измените курс и двигайтесь в гору.
Выполните обход с высоким разрешением вдоль прямоугольной ограничительной рамки области рендеринга. На каждом пороговом уровне возвышения (и в точках перегиба, где наклон меняет направление), добавьте эти точки в определенную высоту. После завершения обхода границы начните трассировку внутрь от граничных точек в этих сегментах.
Сканирование всей области рендеринга с использованием измерения высоты с редким регулярным интервалом. Для каждого измерения используйте его близость к порогу превышения в качестве механизма, чтобы решить, следует ли проводить интерполированное измерение его соседей. Использование этого метода обеспечит лучшие гарантии покрытия всей области рендеринга, но будет трудно собрать результирующие точки в разумный порядок построения путей.
Итак, вот некоторые из моих мыслей ...
Прежде чем углубиться в реализацию, я хотел узнать, имеет ли кто-либо еще в StackOverflow опыт работы с такого рода проблемами и может ли предоставить указатели для точной и эффективной реализации.
Edit:
Меня особенно интересует предложение "Градиент", сделанное Эллисббеном. И моя основная структура данных (без учета некоторых оптимизирующих ярлыков интерполяции) может быть представлена в виде суммирования набора двумерных гауссовских функций, которые полностью дифференцируемы.
Полагаю, мне понадобится структура данных для представления трехмерного наклона и функция для вычисления этого вектора наклона в произвольной точке. Вдобавок ко всему, я не знаю, как это сделать (хотя кажется, что это должно быть легко), но если у вас есть ссылка, объясняющая математику, я был бы очень признателен!
UPDATE:
Благодаря превосходному вкладу Эллисббена и Азима, теперь я могу рассчитать угол контура для любой произвольной точки в поле. Рисование настоящих линий топо будет в ближайшее время!
Вот обновленные визуализации, с использованием и без использования топо-рендерера на основе гетто, который я использовал. Каждое изображение включает в себя тысячи случайных точек выборки, представленных красными точками. Угол контура в этой точке представлен белой линией. В некоторых случаях нельзя измерить наклон в данной точке (основываясь на гранулярности интерполяции), поэтому красная точка появляется без соответствующей линии угла контура.
Наслаждайтесь!
(ПРИМЕЧАНИЕ. В этих визуализациях используется топография поверхности, отличная от предыдущих визуализаций - поскольку я случайным образом генерирую структуры данных на каждой итерации, пока я создаю прототип, - но основной метод визуализации одинаков, поэтому Я уверен, что вы поняли.)
Вот забавный факт: на правой стороне этих визуализаций вы увидите кучу странных контурных линий под идеальными горизонтальными и вертикальными углами. Это артефакты процесса интерполяции, в котором используется сетка интерполяторов, чтобы уменьшить количество вычислений (примерно на 500%), необходимых для выполнения операций рендеринга ядра. Все эти странные контурные линии происходят на границе между двумя ячейками интерполяционной сетки.
К счастью, эти артефакты на самом деле не имеют значения. Хотя артефакты обнаруживаются во время вычисления наклона, конечный рендерер их не заметит, поскольку он работает с другой битовой глубиной.
ОБНОВЛЕНИЕ СНОВА:
А-а-а-а-а-а, в качестве еще одной снисходительности перед сном, вот еще одна пара визуализаций, одна в стиле "непрерывного цвета" старой школы и одна с 20 000 градиентных выборок. В этом наборе визуализаций я убрал красную точку для точечных образцов, так как она излишне загромождает изображение.
Здесь вы действительно можете увидеть те артефакты интерполяции, о которых я упоминал ранее, благодаря сеточной структуре коллекции интерполяторов. Я должен подчеркнуть, что эти артефакты будут полностью невидимы при окончательном рендеринге контура (поскольку разница в величине между любыми двумя соседними ячейками интерполятора меньше, чем битовая глубина визуализированного изображения).
Приятного аппетита !!