БлогNot. MathCAD: попадание точки в многоугольник

MathCAD: попадание точки в многоугольник

Собственно, subj. В реализации всего один цикл с числом шагов, равным числу вершин многоугольника, так что назвать её быстрой, думаю, не будет преувеличением.

Многоугольник не должен передаваться функции point_in_polygon как замкнутый, то есть, координаты первой и последней точек не совпадают ("замыкание" делает сам алгоритм). Служебная функция close_p делает "замыкание" только для отображения на графике, заодно видно, как в MathCAD показать многоугольник и точку на графике:

Mathcad: как вывести многоугольник и точку на график
Mathcad: как вывести многоугольник и точку на график

Для отображения на графике "большой точки" понадобилось дополнительно зайти двойным щелчком в окно форматирования графика и на вкладке "Трассировка" для второго ряда данных убрать показ линий и включить показ символа.

Алгоритм основан на методе лучей (учёта пересечений) и может быть описан так:

p - многоугольник, n - число его вершин, a - точка, 
i,j - номера очередной и следующей вершина
eps - погрешность, с которой точка считается лежащей на стороне многоугольника
для i от 1 до n нц
 если p.x==a.x и p.y==a.y, то вернуть 0 {точка на вершине}
 если i<n, то j=i+1, иначе j=0
 если p[i].y==p[j].y, то continue {перейти к началу цикла; горизонтальная линия}
 если p[i].y>a.y и p[j].y>a.y, то continue {оба конца стороны выше точки}
 если p[i].y<a.y и p[j].y<a.y, то continue {оба конца стороны ниже точки}
 если max(p[i].y,p[j].y)==a.y, то нач
  с=с+1 {если верхняя  вершина лежит на одной горизонтали с точкой,}
  f=1   {считаем пересечение на стороне}
 кон
 иначе если min(p[i].y,p[j].y)==a.y, то continue {если нижняя, то нет}
 иначе нач
  считаем t - коэффициент пропорциональности деления стороны горизонтальным лучом из точки a
  считаем t2 = p[i].x+t*(p[j].x-p[i].x)
  если t>0 и t<1 и t2<=a.x, то нач
   c=c+1 {считаем пересечение}
   если |t2-a.x|<eps, то f=1 {если с точностью eps совпадает с точкой, точка считается на стороне}
  кон
 кон
кц
если c mod 2==0, вернуть -1 {точка не лежит в полигоне}
иначе если f==1, вернуть 0 {точка лежит на стороне полигона}
иначе вернуть 1 {точка принадлежит многоугольнику}

Выпуклым наш полигон быть не обязан, для выпуклых многоугольников полно тривиальных алгоритмов.

Тестовая точка a задана сначала как вектор-строка, но с ними MathCAD нормально не работает, так что в функции point_in_polygon объект a транспонируется, превращаясь в вектор-столбец из двух элементов.

Ниже реализация выведена на скриншот и прикреплена как файл MathCAD 15.

Принадлежность точки произвольному многоугольнику в MathCAD
Принадлежность точки произвольному многоугольнику в MathCAD

 Скачать пример "Принадлежность точки многоугольнику", документ MathCAD 15 в архиве .zip (33 Кб)

P.S. В окончательной версии я отказался от параметра eps из-за найденных несоответствий между возвращаемыми значениями -1 и 0, так что 0 возвращается только если точка совпадает с одной из вершин многоугольника.

А вот показанные на Хабре алгоритмы работать не захотели никак :( Ну или я крив был.

28.11.2014, 10:00 [12652 просмотра]


теги: графика алгоритм mathcad

К этой статье пока нет комментариев, Ваш будет первым