У меня есть некоторые геоданные (на изображении ниже путь реки показан красными точками), которые я хочу аппроксимировать, используя многосегментную кубическую кривую Безье. По другим вопросам о stackoverflow здесь и здесь Я нашел алгоритм Филиппа Шнайдера из "Graphics Gems" . Я успешно реализовал его и могу сообщить, что даже с тысячами баллов это очень быстро. К сожалению, такая скорость имеет ряд недостатков, а именно то, что установка выполняется довольно небрежно. Рассмотрим следующий рисунок:
Красные точки - это мои исходные данные, а синяя линия - многосегментный график Безье, созданный алгоритмом Шнайдера. Как видите, входными данными для алгоритма был допуск, который, по крайней мере, равен значению, указанному зеленой линией. Тем не менее алгоритм создает кривую Безье, имеющую слишком много крутых поворотов. Вы также видите эти ненужные резкие повороты на изображении. Легко представить кривую Безье с менее резкими поворотами для показанных данных, при этом сохраняя условие максимального допуска (просто сдвиньте кривую Безье немного в направлении пурпурных стрелок). Проблема, похоже, в том, что алгоритм выбирает точки данных из моих исходных данных в качестве конечных точек отдельных кривых Безье (точки пурпурных стрелок указывают на некоторых подозреваемых). Поскольку конечные точки кривых Безье ограничены таким образом, ясно, что алгоритм иногда дает довольно резкие искривления.
Я ищу алгоритм, который аппроксимирует мои данные многосегментной кривой Безье с двумя ограничениями:
- многосегментная кривая Безье никогда не должна находиться на расстоянии более определенного расстояния от точек данных (это обеспечивается алгоритмом Шнайдера)
- многосегментная кривая Безье никогда не должна создавать слишком резкие кривизны. Один из способов проверить соответствие этим критериям - прокрутить круг с минимальным радиусом кривизны вдоль многосегментной кривой Безье и проверить, касается ли он всех частей кривой на своем пути. Хотя кажется, что есть лучший метод с использованием произведение первой и второй производной
К сожалению, решения, которые я нашел, которые лучше подходят, либо работают только для одиночных кривых Безье (и опускают вопрос о том, как найти хорошие начальные и конечные точки для каждой кривой Безье на многосегментной кривой Безье), либо не допускают минимального ограничения кривизны. Я считаю, что ограничение минимальной кривизны здесь - сложное условие.
Вот еще один пример (он нарисован от руки и не на 100% точен):
Предположим, что на рисунке 1 показаны как ограничение кривизны (круг должен соответствовать всей кривой), так и максимальное расстояние любой точки данных от кривой (которое оказывается радиусом круга зеленого цвета). Успешное приближение красного пути на рисунке 2 показано синим цветом. Это приближение учитывает условие кривизны (круг может катиться внутри всей кривой и касаться ее повсюду), а также условие расстояния (показано зеленым). На рисунке 3 показан путь в другом приближении. Хотя здесь соблюдается условие расстояния, ясно, что круг больше не вписывается в кривизну. На рисунке 4 показан путь, который невозможно приблизить с данными ограничениями, потому что он слишком острый. Этот пример должен проиллюстрировать, что для правильной аппроксимации некоторых острых поворотов на пути необходимо, чтобы алгоритм выбирал контрольные точки, которые не являются частью пути. На рисунке 3 показано, что если были выбраны контрольные точки вдоль пути, ограничение кривизны больше не может выполняться. Этот пример также показывает, что алгоритм должен завершиться на некоторых входах, поскольку его невозможно аппроксимировать с заданными ограничениями.
Есть ли решение этой проблемы? Решение не должно быть быстрым. Если на обработку 1000 точек уходит день, ничего страшного. Решение также не должно быть оптимальным в том смысле, что оно должно приводить к аппроксимации методом наименьших квадратов.
В конце концов, я реализую это на C и Python, но я могу читать и на большинстве других языков.