Пусть на плоскости дано множество из n точек pi = ( xi, yi ) и нужно аппроксимировать его дугой окружности. Рассмотрим несколько подходов к решению этой задачи. В первом подходе координаты центра o = ( x, y ) и радиус r будем искать, как аргументы при которых функция
принимает минимальное значение. Сведём эту задачу к задаче наименьших квадратов. Для этого продифференцируем (1) по r и приравняем производную нулю. Отсюда получим выражение r 2 через x и y:
Подставим это выражение в (1) и приведём подобные члены. Получится задача наименьших квадратов:
Следующая программа решает эту задачу: Def<Circle2d> getCirclePnt22 ( CArrRef<Vector2d> p ); Основное преимущество рассмотренной задачи - это простота решения, но более интересной для практики является минимизация другой функции отклонений:
1) Получаем начальное приближение для x, y и r при помощи функции getCirclePnt22. 2) Вычисляем значения ci и si. 3) Решая задачу (5) получаем новые значения для x, y и r. Будем повторять шаги 2 и 3 пока алгоритм не сойдётся. В результате получаем программу: Def<Circle2d> getCirclePnt2 ( CArrRef<Vector2d> p ); В третьем подходе будем искать минимум суммы абсолютных разностей между радиусом окружности r и расстоянием от точки pi до центра окружности о:
Def<Circle2d> getCirclePnt1 ( CArrRef<Vector2d> p, nat & ix1, nat & ix2, nat & ix3 ); Def<Circle2d> getCirclePnt1 ( CArrRef<Vector2d> p );Временная сложность такого алгоритма равна O ( n4 ). Замечу, что окружности построенными этими тремя алгоритмами могут очень сильно отличаться. Описание шаблона классов CArrRef находится здесь.
Исходники находятся в approx2d.cpp Наверх |