<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=83.149.3.173&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=83.149.3.173&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/83.149.3.173"/>
		<updated>2026-08-05T10:51:11Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D0%BF%D1%80%D0%BE%D1%89%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE%D0%BB%D0%B8%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%86%D0%B5%D0%BF%D0%B8&amp;diff=18631</id>
		<title>Упрощение полигональной цепи</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D0%BF%D1%80%D0%BE%D1%89%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE%D0%BB%D0%B8%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%86%D0%B5%D0%BF%D0%B8&amp;diff=18631"/>
				<updated>2012-03-01T05:37:24Z</updated>
		
		<summary type="html">&lt;p&gt;83.149.3.173: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Упрощение полигональной цепи {{---}} процесс, позволяющий уменьшить число точек кривой, аппроксимированной серией точек.&lt;br /&gt;
==Задача==&lt;br /&gt;
Дана некоторая аппроксимированная кривая, заданная последовательностью точек, и некоторое &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;. Требуется ответить, какие точки мы можем оставить, так чтобы расхождение между исходной и получившейся кривыми не превышало &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;, при этом количество точек в получившейся кривой должно стремиться к минимуму.&lt;br /&gt;
==Мотивация==&lt;br /&gt;
Такая задача встречается при обработки векторной графики и построении карт. Расмотрим пример для построения карт. Дан путь из Москвы в Санкт-Петербург, заданный точками через каждый километр пути. В масштабах всей России такая точность явно ни к чему, стоит оставить лишь точки, отражающие ключевые участки пути. В этом случае и пригодится упрощение, одним из вариантов реализации которого является алгоритм Дугласа-Пекера.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм Дугласа-Пекера==&lt;br /&gt;
Алгоритму задается исходная ломаная и максимальное расстояние, которое может быть между исходной и упрощённой ломаными (то есть максимальное расстояние от точек исходной ломаной к ближайшему участку полученной ломаной). Упрощенная ломаная состоит из подмножества точек, которые определяются из исходной ломаная.&lt;br /&gt;
===Описание===&lt;br /&gt;
Начальная ломаная представляет собой упорядоченный набор точек.&lt;br /&gt;
&lt;br /&gt;
Алгоритм рекурсивно делит ломаную. Входом алгоритма служат координаты всех точек между первой и последней включая их, а так же &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;. Первая и последняя точка сохраняются неизменными. После чего алгоритм находит точку, наиболее удалённую от отрезка, состоящего из первой и последней (оптимальный способ поиска расстояния от точки до отрезка рассмотрен ниже). Если точка находится на расстоянии, меньше чем &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;, то все точки, которые ещё не были отмечены к сохранению, могут быть выброшены из набора и получившаяся прямая сглаживает кривую с точностью не ниже &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Если же расстояние больше &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;, то алгоритм рекурсивно вызывает себя на наборе от начальной до данной и от данной до конечной точек (что означает, что данная точка будет отмечена к сохранению).&lt;br /&gt;
&lt;br /&gt;
По окончанию всех рекурсивных вызовов выходная ломаная строится только из тех точек, что были отмечены к сохранению.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
&amp;lt;code&amp;gt;DouglasPeucker(int first, int last, double eps)&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;max = -infinity&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;index = -1&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;for (int i = first + 1; i &amp;lt; last; i++)&amp;lt;/code&amp;gt;&lt;br /&gt;
::&amp;lt;code&amp;gt;distance = dist(points[i], segment(points[first],points[last]))&amp;lt;/code&amp;gt;&lt;br /&gt;
::&amp;lt;code&amp;gt;if (distance &amp;gt; max &amp;amp;&amp;amp; distance &amp;gt; eps)&amp;lt;/code&amp;gt;&lt;br /&gt;
:::&amp;lt;code&amp;gt;max = distance, index = i&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;if(index == -1)&amp;lt;/code&amp;gt;&lt;br /&gt;
::&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt;&lt;br /&gt;
::&amp;lt;code&amp;gt;answer[index] = true&amp;lt;/code&amp;gt;&lt;br /&gt;
::&amp;lt;code&amp;gt;DouglasPeucker(first, index, eps)&amp;lt;/code&amp;gt;&lt;br /&gt;
::&amp;lt;code&amp;gt;DouglasPeucker(index, last, eps)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
[[Файл:Example_DP.png‎|300px|right]]&lt;br /&gt;
Рассмотрим пример для точек, заданных на рисунке, где сплошная линия отражает исходную линию, и &amp;lt;tex&amp;gt;\varepsilon = \sqrt 2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Шаг || Действие&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; || Найдем наиболее удаленную точку от отрезка &amp;lt;tex&amp;gt;1-5&amp;lt;/tex&amp;gt;, это точка &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || Расстояние до точки &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; больше &amp;lt;tex&amp;gt;\sqrt 2&amp;lt;/tex&amp;gt;, добавляем ее в ответ&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; || Запустим алгоритм для точек &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; || Найдем наиболее удаленную точку от отрезка &amp;lt;tex&amp;gt;1-3&amp;lt;/tex&amp;gt;, это точка &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; || Расстояние до точки &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; меньше &amp;lt;tex&amp;gt;\sqrt 2&amp;lt;/tex&amp;gt;, возвращаемся&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt; || Запустим алгоритм для точек &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; || Найдем наиболее удаленную точку от отрезка &amp;lt;tex&amp;gt;3-5&amp;lt;/tex&amp;gt;, это точка &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; || Расстояние до точки &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; меньше &amp;lt;tex&amp;gt;\sqrt 2&amp;lt;/tex&amp;gt;, возвращаемся&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;9&amp;lt;/tex&amp;gt; || Алгоритм завершен&lt;br /&gt;
|}&lt;br /&gt;
Линия, полученная в результате работы алгоритма, отражается пунктирной линией.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Ожидаемая сложность алгоритма может быть оценена выражением &amp;lt;tex&amp;gt;\Theta(n\log n)&amp;lt;/tex&amp;gt; в лучшем случае, когда номер наиболее удаленной точки всегда оказывается лексикографически центральным. Однако в худшем случае сложность алгоритма &amp;lt;tex&amp;gt;O\left(n^2\right)&amp;lt;/tex&amp;gt;, когда номер наиболее удаленной точки всегда соседний к номеру граничащей точки.&lt;br /&gt;
&lt;br /&gt;
===Замечания к алгоритму===&lt;br /&gt;
====Топология====&lt;br /&gt;
К сожалению, алгоритм Дугласа-Пекера в ходе своей работы не сохраняет топологию, что означает в ответе мы можем получить линию с самопересечениями.&lt;br /&gt;
&lt;br /&gt;
====Оптимальность====&lt;br /&gt;
[[Файл:DP(1).png‎|100px|thumb|right|Оптимальный по количеству точек ответ]]&lt;br /&gt;
[[Файл:DP(2).png‎|100px|thumb|left|Ответ алгоритма Дугласа-Пекера]]&lt;br /&gt;
Алгоритм может находить не минимальный по количеству точек ответ. Рассмотрим пример, где исходная линия с некоторым приближением будет представлять полуокружность. Мы можем подобрать такое &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt;, что алгоритм добавит три точки помимо стартовой и конечной (точки через каждую четверть исходной линии), в то же время мы можем взять две точки через&lt;br /&gt;
каждую треть исходной линии, для которых упрощение также верно.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Поиск расстояния от точки до отрезка==&lt;br /&gt;
===Идея===&lt;br /&gt;
При определении расстояния от точки до отрезка нужно сначала проанализировать взаимное расположение точки и отрезка прямой, то есть, проверить, куда опустится перпендикуляр из точки: непосредственно на отрезок или на прямую, являющуюся продолжением рассматриваемого отрезка. &lt;br /&gt;
&lt;br /&gt;
Если на отрезок, то ответ это расстояние от исходной точки до точки пересечения отрезка с перпендикуляром, если нет, то расстояние от исходной точки до одного из концов отрезка. &lt;br /&gt;
&lt;br /&gt;
Самое очевидное {{---}} это найти точку пересечения перпендикуляра и прямой, и в зависимости от ее положения вычислить ответ. На самом деле, этот анализ может быть произведен путем построения треугольника, вершинами которого являются концы отрезка и точка, и сопоставления соотношения длин его сторон.&lt;br /&gt;
&lt;br /&gt;
===Реализация===&lt;br /&gt;
[[Файл:DistancePointToSegment.gif‎|300px|right]]&lt;br /&gt;
Даны точка &amp;lt;tex&amp;gt;(x_0, y_0)&amp;lt;/tex&amp;gt; и отрезок, заданный точками &amp;lt;tex&amp;gt;(x_1, y_1)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;(x_2, y_2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Введём обозначения:&lt;br /&gt;
*&amp;lt;tex&amp;gt;R_1&amp;lt;/tex&amp;gt; отрезок &amp;lt;tex&amp;gt;(x_0, y_0)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;(x_1, y_1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;R_2&amp;lt;/tex&amp;gt; отрезок &amp;lt;tex&amp;gt;(x_0, y_0)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;(x_2, y_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;R_{12}&amp;lt;/tex&amp;gt; отрезок &amp;lt;tex&amp;gt;(x_1, y_1)&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;(x_2, y_2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если: &lt;br /&gt;
*&amp;lt;tex&amp;gt;|R_1| \ge \sqrt{|R_2|^2+|R_{12}|^2}&amp;lt;/tex&amp;gt;, то ответ это &amp;lt;tex&amp;gt;|R_2|&amp;lt;/tex&amp;gt;, так как угол между &amp;lt;tex&amp;gt;R_2&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;R_{12}&amp;lt;/tex&amp;gt; при данном условии &amp;lt;tex&amp;gt; \ge 90^{\circ}&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;|R_2| \ge \sqrt{|R_1|^2+|R_{12}|^2}&amp;lt;/tex&amp;gt;, то ответ это &amp;lt;tex&amp;gt;|R_1|&amp;lt;/tex&amp;gt;, так как угол между &amp;lt;tex&amp;gt;R_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;R_{12}&amp;lt;/tex&amp;gt; при данном условии &amp;lt;tex&amp;gt; \ge 90^{\circ}&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Оба предыдущих условия ложны, то &amp;lt;tex&amp;gt;abs(| \overrightarrow{R_{12}} \times  \overrightarrow{R_1}|/|\overrightarrow{R_{12}}|)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; \overrightarrow{R_{12}} = (x_2 -x_1, y_2 - y_1)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \overrightarrow{R_1} = (x_1 - x_0, y_1 - y_0)&amp;lt;/tex&amp;gt;. Это следует из формул для площади параллелограмма через векторное произведение и через произведения основания на высоту&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/Алгоритм_Рамера_—_Дугласа_—_Пекера Алгоритм Дугласа-Пекера]&lt;br /&gt;
*[http://pers.narod.ru/algorithms/pas_dist_from_point_to_line.html Поиск расстояния от точки до отрезка]&lt;br /&gt;
*[http://algolist.manual.ru/maths/geom/distance/pointline.php Поиск расстояния от точки до прямой]&lt;/div&gt;</summary>
		<author><name>83.149.3.173</name></author>	</entry>

	</feed>