С Новым годом! Форум программистов, компьютерный форум, киберфорум
Геометрия
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/11: Рейтинг темы: голосов - 11, средняя оценка - 5.00
 Аватар для kzru_hunter
1124 / 795 / 101
Регистрация: 01.02.2011
Сообщений: 1,887
Записей в блоге: 1

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

20.02.2021, 08:47. Показов 2220. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, нашёл на другом форуме один из методов определения принадлежности точки многоугольнику:

Как я понял, нужно найти ближайшую к точке М среднюю точку P, пройдясь по всем отрезкам.
Но тогда такой алгоритм будет давать ошибочный результат, если точка M будет находиться в этом месте:

Не пойму, то ли я не так понял, то ли метод действительно ошибочен.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
20.02.2021, 08:47
Ответы с готовыми решениями:

Принадлежность точки неправильному многоугольнику
Определяется область путём задания координат точек (количество точек может быть произвольным). Как определить принадлежит ли точка этой...

Напишите алгоритм, определяющий принадлежность точки выпуклому многоугольнику из N точек
Напишите алгоритм, определяющий принадлежность точки выпуклому многоугольнику из N точек

Разработать программу, которая решает задачу принадлежности точки многоугольнику с помощью метода "Учет числа оборотов"
Здравствуйте, мне необходимо разработать программу которая решает задачу принадлежности точки многоугольнику с помощью метода "Учет...

14
 Аватар для palva
4277 / 2969 / 693
Регистрация: 08.06.2007
Сообщений: 9,924
Записей в блоге: 5
20.02.2021, 09:43
Ближайшая линия -- как я понял, выбирается тот отрезок расстояние которого от точки M наименьшее. Расстояние измеряется от точки М не до средней точки, а до ближайшей точки. Это надо либо перпендикуляр опускать, либо, если перпендикуляр не попадает на отрезок, сравнивать расстояния до концов отрезка.

Могу предложить другой алгоритм для плоского случая. Через M проводим горизонтальную прямую и ищем точки пересечения этой прямой с отрезками ломаной. Сначала проверяем, не лежит ли M на ломаной (тогда будет особый ответ). Если слева и справа четное число пересечений, то M -- вне, если нечетное, -- то внутри. Если чет-нечет, то ломаная незамкнута либо вообще не ломаная. Вместо горизонтальной прямой можно взять вертикальную или вообще произвольную. Для простоты вычислений берем прямую параллельно какой-либо оси координат.
1
Эксперт по математике/физике
11066 / 7367 / 3989
Регистрация: 14.01.2014
Сообщений: 16,799
20.02.2021, 09:48
Судя по малограмотной фразе: "средняя точка ограничивающей линии", можно сделать определённый вывод!
0
 Аватар для kzru_hunter
1124 / 795 / 101
Регистрация: 01.02.2011
Сообщений: 1,887
Записей в блоге: 1
20.02.2021, 10:05  [ТС]
palva Не, я правильно понял. У него оказывается ошибка в алгоритме, он потом поздно осознал это и расписал в другой теме исправленную версию:

Про алгоритм подсчёта пересечений я знаю, но он сложнее расписывается (там нужно ещё учитывать случаи, когда луч проходит через вершины или сразу через 2 вершины ребра). На algolist подробно расписано.
Вообще, я изучаю разные методы, чтобы понять, как обобщить это всё на 3-х мерный случай с замкнутой поверхностью.

Кстати, если не ошибаюсь, то его метод можно упростить:
1) Найти ближайшую к точке М вершину P. Эта вершина принадлежит двум ребрам.
2) Найти скалярное произведение PM*n1 и PM*n2 (где n1 и n2 - внешние нормали к рёбрам)
Если точка находится внутри многоугольника (или на ребре), то оба скалярных произведения не должны быть положительными.
0
фрилансер
 Аватар для Алексей1153
6446 / 5642 / 1128
Регистрация: 11.10.2019
Сообщений: 15,008
20.02.2021, 10:20
kzru_hunter, насколько я помню, метод определения следующий: для выпуклого многоугольника из точки проводятся отрезки ко всем вершинам. Получается много треугольников. Сумма площадей этих треугольников должна быть равна площади многоугольника.

Если многоугольник не выпуклый, то его нужно разбить на выпуклые

Может, это и долго, но там наверняка можно всякие сокращения в вычислениях совершить (в частности, можно не суммировать дальше, если сумма уже превзошла площадь многоугольника). Кроме того, этот способ интуитивно понятен и очевиден - достаточно нарисовать это на бумаге

Добавлено через 1 минуту
подправил )

Добавлено через 6 минут
хорошей оптимизацией может оказаться отсечение по охватывающему прямоугольнику и вписанной окружности
1
 Аватар для kzru_hunter
1124 / 795 / 101
Регистрация: 01.02.2011
Сообщений: 1,887
Записей в блоге: 1
20.02.2021, 10:29  [ТС]
Цитата Сообщение от Алексей1153 Посмотреть сообщение
насколько я помню, метод определения следующий: для выпуклого многоугольника из точки проводятся отрезки ко всем вершинам. Получается много треугольников. Сумма площадей этих треугольников должна быть равна площади многоугольника.
Если многоугольник не выпуклый, то его нужно разбить на выпуклые
Метод интересный, только вот непонятно, как его разбивать в программе.
Для выпуклого многоугольника думаю проще проверить, с какой стороны от каждого ребра (ребро - направленный отрезок) лежит точка с помощью векторного произведение. Если все векторные произведения >=0 или <= 0, то точка принадлежит многоугольника.

Добавлено через 3 минуты
Цитата Сообщение от kzru_hunter Посмотреть сообщение
Кстати, если не ошибаюсь, то его метод можно упростить:
1) Найти ближайшую к точке М вершину P. Эта вершина принадлежит двум ребрам.
2) Найти скалярное произведение PM*n1 и PM*n2 (где n1 и n2 - внешние нормали к рёбрам)
Если точка находится внутри многоугольника (или на ребре), то оба скалярных произведения не должны быть положительными.
Сейчас подумал и вроде как такой метод можно обобщить и для замкнутой поверхности. Только там нужно будет найти, как минимум три скалярных произведения PM*n1, PM*n2, PM*n3, ... (где n1,n2,n3 - внешние нормали к плоскостям граней, имеющих общую точку P)
0
фрилансер
 Аватар для Алексей1153
6446 / 5642 / 1128
Регистрация: 11.10.2019
Сообщений: 15,008
20.02.2021, 10:56
Цитата Сообщение от kzru_hunter Посмотреть сообщение
только вот непонятно, как его разбивать в программе.
можно разбить просто на треугольники, к примеру

Цитата Сообщение от kzru_hunter Посмотреть сообщение
Для выпуклого многоугольника думаю проще проверить
вычислений будет столько же и, не побоюсь этого слова, таких же - будут операции с теми же векторами
0
 Аватар для kzru_hunter
1124 / 795 / 101
Регистрация: 01.02.2011
Сообщений: 1,887
Записей в блоге: 1
20.02.2021, 11:25  [ТС]
Цитата Сообщение от Алексей1153 Посмотреть сообщение
можно разбить просто на треугольники, к примеру
Спасибо, не заметил
Цитата Сообщение от Алексей1153 Посмотреть сообщение
вычислений будет столько же и, не побоюсь этого слова, таких же - будут операции с теми же векторами
Вроде бы это делается через векторное произведение, т.к. оно равно площади параллелограмма, построенного на двух ребрах. Половина этой площади равна площади треугольника. Три площади - три векторных произведения.
И в том способе тоже три векторных произведений.
В одной статье была приведена производительность обоих способов и почему-то способ с площадями оказался медленней в 2 раза.
Добавлено через 1 минуту
Цитата Сообщение от kzru_hunter Посмотреть сообщение
Кстати, если не ошибаюсь, то его метод можно упростить:
1) Найти ближайшую к точке М вершину P. Эта вершина принадлежит двум ребрам.
2) Найти скалярное произведение PM*n1 и PM*n2 (где n1 и n2 - внешние нормали к рёбрам)
Если точка находится внутри многоугольника (или на ребре), то оба скалярных произведения не должны быть положительными.
Как можно доказать, что этот способ не даст ошибок?
Цитата Сообщение от kzru_hunter Посмотреть сообщение
Как можно доказать, что этот способ не даст ошибок?
Всё-таки даёт ошибку в следующем случае:

Исправленный алгоритм пользователя О. Федор тоже даёт ошибку для этого (см. пред. рис. ) многоугольника
Цитата Сообщение от palva Посмотреть сообщение
Ближайшая линия -- как я понял, выбирается тот отрезок расстояние которого от точки M наименьшее. Расстояние измеряется от точки М не до средней точки, а до ближайшей точки. Это надо либо перпендикуляр опускать, либо, если перпендикуляр не попадает на отрезок, сравнивать расстояния до концов отрезка.
Кстати, действительно, именно так и нужно было делать. Метод называется "Ближняя точка и ее нормаль". Для себя доказал, что этот метод действительно рабочий, но ещё самое важное - он должен работать и для замкнутой поверхности (по крайней мере я это для себя доказал).
0
Модератор
Эксперт по математике/физике
 Аватар для VSI
5289 / 4071 / 1392
Регистрация: 30.07.2012
Сообщений: 12,487
20.02.2021, 17:37
А так не проще?
1
 Аватар для kzru_hunter
1124 / 795 / 101
Регистрация: 01.02.2011
Сообщений: 1,887
Записей в блоге: 1
20.02.2021, 21:18  [ТС]
VSI Спасибо. Плюс за mathcad. Как я понял, это метод трассировки луча, не сразу понял
0
 Аватар для kzru_hunter
1124 / 795 / 101
Регистрация: 01.02.2011
Сообщений: 1,887
Записей в блоге: 1
20.02.2021, 22:43  [ТС]
VSI Очень круто, что у Вас алгоритм оптимизирован до предела. Не так просто это сделать обычному юзеру )
Как я понял, если неравенство строгое, то будут отбрасываться точки лежащие на границе n-угольника, а чтобы и они включались, нужно изменить неравенство на нестрогое (<=)
Кстати, цикл можно упростить:
Название: 111.png
Просмотров: 118

Размер: 2.5 Кб
0
 Аватар для kzru_hunter
1124 / 795 / 101
Регистрация: 01.02.2011
Сообщений: 1,887
Записей в блоге: 1
26.02.2021, 11:15  [ТС]
Просмотрел разные способы, но по моему мнению только трассировка луча является наиболее предпочтительным методом, т.к. он быстро отсеивает ребра, лежащие выше и ниже и остаются только максимум 4 ребра (2 слева и два справа и то, если луч проходит через вершину), которые нужно рассмотреть более внимательнее. Вдобавок, возможно за раз отсеивать группы ребер, если применять деревья. Также можно применить метод трассировки луча и для многогранника (но там он напорядок сложнее), и также быстро отсеивать грани, если как бы запаковывать их в параллелепипеды и сразу отбрасывать те грани, для которых луч не пересекает их параллелепипеды.

Цитата Сообщение от kzru_hunter Посмотреть сообщение
Как я понял, если неравенство строгое, то будут отбрасываться точки лежащие на границе n-угольника, а чтобы и они включались, нужно изменить неравенство на нестрогое (<=)
К сожалению, это не всех случаев достаточно (когда, например, есть горизонтальные ребра). Нужно проводить немало дополнительных проверок. Вдобавок, в некоторых задачах может понадобиться узнать не просто принадлежности точки многоугольнику, а принадлежит ли точка его границе. И чтобы всё это учесть, нужно достаточно сильно переделать алгоритм, предложенный VSI, а потом ещё и на разных тестах перепроверить. Попробовал над этим заморочиться, но алгоритм сильно разросся, при этом в полученном виде его неудобно переписывать на какие-нибудь языки программирования, и решил, что лучше предложенного на хабре алгоритма ничего нету: https://habr.com/ru/post/161237/ (см. check2; check3 практически также отсекает ребра, но менее читабелен).
P.S. надеюсь эта ссылка разрешена
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12930 / 6798 / 1820
Регистрация: 18.10.2014
Сообщений: 17,205
01.03.2021, 19:21
Цитата Сообщение от kzru_hunter Посмотреть сообщение
Не пойму, то ли я не так понял, то ли метод действительно ошибочен.
Это не метод, это чушь какая-то.

Цитата Сообщение от kzru_hunter Посмотреть сообщение
У него оказывается ошибка в алгоритме, он потом поздно осознал это и расписал в другой теме исправленную версию:
"Исправленная версия" ничуть не лучше исходной версии.

Цитата Сообщение от kzru_hunter Посмотреть сообщение
К сожалению, это не всех случаев достаточно (когда, например, есть горизонтальные ребра). Нужно проводить немало дополнительных проверок.
Никаких сложных проверок там нет. Все совершенно элементарно. Подсчитываем пересечения ребер с горизонтальным лучом, выпущенным из тестируемой точки M(x,y). Принадлежность точки горизонтальному ребру - элементарная проверка. После этого в подсчете пересечений нас интересуют только ребра, у которых есть точка строго ниже луча, т.е ребра, для которых min(y1, y2) < y. Все.

Странно слышать рассуждения об этих проверках в рамках рассмотрения какого-то странного, но очевидно на порядки существенно более вычислительно тяжелого алгоритма.

---

Весь алгоритм для точки M(mx, my) выглядит так

Code
1
2
3
4
5
6
7
8
9
10
11
1. Перебираем ребра многоугольника (x1, y1)-(x2, y2):
 
  2. Отлавливаем попадание M на горизонтальное ребро - ответ готов
  3. Отлавливаем попадание M в начальную точку ребра - ответ готов
  4. Далее рассматриваем только те ребра, для которых max(y1, y2) >= my и min(y1, y2) < my
 
    5. Находим точку P(px, py) пересечения ребра с горизонталью my
    6. Отлавливаем равенство px == mx - ответ готов
    7. Засчитываем пересечение только если px > mx
 
8. Если финальное количество пересечений нечетно - точка внутри
0
 Аватар для kzru_hunter
1124 / 795 / 101
Регистрация: 01.02.2011
Сообщений: 1,887
Записей в блоге: 1
01.03.2021, 20:19  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Никаких сложных проверок там нет.
Я не говорил, что там сложные проверки. Я говорил, что их немало, вследствие чего код в 2 раза увеличится по размеру и вдобавок некрасиво будет смотреть при переносе на разные языки программирования.
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Весь алгоритм для точки M(mx, my) выглядит так
Попробуйте теперь это упаковать в реальный код. Да и как бы уже подробно про алгоритм трассировки луча давно всё расписано (выше писал). Ну и как бы это опять велосипед, когда уже всё за нас сделали и на сто рядов перепроверили. Ну и тема не совсем про алгоритм трассировки луча был. Потом VSI предложил реальный минимальный код, но нечитабельный. Мне он понравился, но переделка его под другие нужды оказалась не совсем неудачной из-за разрошенности, поэтому весь минимализм кода просто исчез и вдобавок осталась нечитабельность.
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Отлавливаем попадание M на горизонтальное ребро - ответ готов
Лучше сначала отсеить ребра, лежашие выше и ниже, чем отлавливать это попадание.

Вот весь оптимизированный перепроверенный на сто рядов код проверки пересечения луча с ребром (возвращает 0, если принадлежит ребру; -1, если пересекает; 1, если не пересекает):
Вложение 1231052
Тут можно ещё даже оптимизировать, если лишние проверки опустить ниже, а именно ax и bx поставить после первого if'a
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12930 / 6798 / 1820
Регистрация: 18.10.2014
Сообщений: 17,205
01.03.2021, 20:46
Цитата Сообщение от kzru_hunter Посмотреть сообщение
Я говорил, что их немало, вследствие чего код в 2 раза увеличится по размеру и вдобавок некрасиво будет смотреть при переносе на разные языки программирования.
Ну тогда вам нужен язык программирования, в котором в готовом виде есть примитив определения принадлежности точки многоугольнику. Вот там все будет красиво.

Цитата Сообщение от kzru_hunter Посмотреть сообщение
Попробуйте теперь это упаковать в реальный код.
Да уж десятки раз упаковывал. В каждой программе - по новой.

Цитата Сообщение от kzru_hunter Посмотреть сообщение
Лучше сначала отсеить ребра, лежашие выше и ниже, чем отлавливать это попадание.
Я описал алгоритм. А "сначала отсеить" (sic) - это посторонняя оптимизационно-реализационная деталь, к алгоритму как таковому не имеющая никакого отношения.

Цитата Сообщение от kzru_hunter Посмотреть сообщение
Вложение 1231052
"Вложение не существует или не указан идентификатор (номер)."
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
01.03.2021, 20:46
Помогаю со студенческими работами здесь

Принадлежность точки плоскости (ХУ).
Ответить на вопрос на скрине! Зарание спаспибо!

Принадлежность точки эллипсу
Есть эллипс. С помощью матрицы аффинного преобразования я его повернул и растянул как мне хочется. Теперь как узнать лежит ли внутри него...

Принадлежность точки прямоугольнику
Есть прямоугольник, повернутый на угол \gamma, следует определить находится ли произвольная точка A внутри него. Правильно ли я понимаю,...

Принадлежность точки отрезку
Есть точка в пространстве с известными координатами, есть отрезок или вектор в пространстве с известными координатами начала и конца. ...

Принадлежность точки отрезку в пространстве
Добрый день,нужна подфункция для проверки принадлежности точки отрезку на прямой отрезок задан 2 точками,значения хранятся в структуре vec...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru