Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 374

/ вопрос решён /

Здравствуйте ув. эксперты. Существует замкнутый полигон из N количества линий, соотвественно все вершины данны. Как опередить попадает ли данная точка в полигон или нет? (без использования регионов)

SMaks Вопрос решён, но можно продолжить его обсуждение в мини-форуме

Вопрос задал: SMaks (статус: 1-ый класс)
Вопрос отправлен: 4 марта 2007, 00:23
Состояние вопроса: решён, ответов: 2.

Ответ #1. Отвечает эксперт: Матвеев Игорь Владимирович

Здравствуйте, SMaks!

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

Я подготовил для Вас демонстрационную программу, использующую другой алгоритм:
1. Случайным образом выбирается точка A
2. Проверяется число пересечений отрезка, образованного точками A и исследуемой точки со всеми гранями многоугольника
3. Если число пересечений = 0 => переход к пункту 1
4. Если число пересечений четное - точка вне многоугольника, если нечетное - внутри.

(прикреплённый файл)

И еще замечания: Данный метод работает для любых многоугольников, но могут быть проблемы с перекрещеными многоугольниками. В таких случайх алгоритм выдает результат, будто при образовании многоугольника используется операция xor, т.е. если на площадь многоугольника еще раз накладывается площадь многоугольника - эта область не считается многоугольником.
Если это положение для Вас критично, Вы можете делать проверку несколько раз, а затем делать вывод.
К ответу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки ответа)

Ответ отправил: Матвеев Игорь Владимирович (статус: Студент)
Время отправки: 4 марта 2007, 06:58
Оценка за ответ: 5

Комментарий к оценке: Огромное спасибо, особенно за пример! Обратите внимание - можно увести точку за канву, нужно при перетаскивании ограничивать область курсора.

Ответ #2. Отвечает эксперт: Роман

Здравствуйте, SMaks!Привожу вам функцию которая определяет находится ли точка внутри многоугольника или нет.TestPolygon : array of TPoint - многоугольник;P : TPoint - точка положение которой нужно определить.Работает с любыми замкнутыми многоугольниками.

Приложение:
  1. function PtInRgn(TestPolygon : array of TPoint; const P : TPoint): boolean;
  2. var
  3. ToTheLeftofPoint, ToTheRightofPoint : byte;
  4. np : integer;
  5. OpenPolygon : boolean;
  6. XIntersection : real;
  7. begin
  8. ToTheLeftofPoint := 0;
  9. ToTheRightofPoint := 0;
  10. OpenPolygon := False;
  11.  
  12. {Prufen ob das Polygon geschlossen ist}
  13. {tests if the polygon is closed}
  14.  
  15. if not ((TestPolygon[0].X = TestPolygon[High(TestPolygon)].X) and
  16. (TestPolygon[0].Y = TestPolygon[High(TestPolygon)].Y)) then
  17. OpenPolygon := True;
  18.  
  19. {Tests fur jedes Paar der Punkte, um zu sehen wenn die Seite zwischen
  20. ihnen, die horizontale Linie schneidet, die TestPoint durchlauft}
  21. {tests for each couple of points to see if the side between them
  22. crosses the horizontal line going through TestPoint}
  23.  
  24. for np := 1 to High(TestPolygon) do
  25. if ((TestPolygon[np - 1].Y <= P.Y) and
  26. (TestPolygon[np].Y > P.Y)) or
  27. ((TestPolygon[np - 1].Y > P.Y) and
  28. (TestPolygon[np].Y <= P.Y))
  29. {Wenn es so ist} {if it does}
  30. then
  31. begin
  32. {berechnet die x Koordinate des Schnitts}
  33. {computes the x coordinate of the intersection}
  34.  
  35. XIntersection := TestPolygon[np - 1].X +
  36. ((TestPolygon[np].X - TestPolygon[np - 1].X) /
  37. (TestPolygon[np].Y - TestPolygon[np - 1].Y)) * (P.Y - TestPolygon[np - 1].Y);
  38.  
  39. {Zahler entsprechend verringern}
  40. {increments appropriate counter}
  41. if XIntersection < P.X then Inc(ToTheLeftofPoint);
  42. if XIntersection > P.X then Inc(ToTheRightofPoint);
  43. end;
  44.  
  45. {Falls das Polygon offen ist, die letzte Seite testen}
  46. {if the polygon is open, test for the last side}
  47.  
  48. if OpenPolygon then
  49. begin
  50. np := High(TestPolygon); {Thanks to William Boyd - 03/06/2001}
  51. if ((TestPolygon[np].Y <= P.Y) and
  52. (TestPolygon[0].Y > P.Y)) or
  53. ((TestPolygon[np].Y > P.Y) and
  54. (TestPolygon[0].Y <= P.Y)) then
  55. begin
  56. XIntersection := TestPolygon[np].X +
  57. ((TestPolygon[0].X - TestPolygon[np].X) /
  58. (TestPolygon[0].Y - TestPolygon[np].Y)) * (P.Y - TestPolygon[np].Y);
  59.  
  60. if XIntersection < P.X then Inc(ToTheLeftofPoint);
  61. if XIntersection > P.X then Inc(ToTheRightofPoint);
  62. end;
  63. end;
  64.  
  65. if (ToTheLeftofPoint mod 2 = 1) and (ToTheRightofPoint mod 2 = 1) then Result := True
  66. else
  67. Result := False;
  68. end;


Ответ отправил: Роман (статус: 5-ый класс)
Время отправки: 4 марта 2007, 12:07
Оценка за ответ: 5

Комментарий к оценке: То что нужно, Спасибо!

Мини-форум вопроса

Всего сообщений: 1; последнее сообщение — 5 марта 2007, 10:49; участников в обсуждении: 1.
Матвеев Игорь Владимирович

Матвеев Игорь Владимирович (статус: Студент), 5 марта 2007, 10:49 [#1]:

>Огромное спасибо, особенно за пример!
>Обратите внимание - можно увести точку за канву, нужно при перетаскивании ограничивать область курсора.
----
Это только пример. Я и не собирался учитывать в нем все. Обратите внимание, там выбирается вектор для проверки только с левой вертикальной грани, что потенциально неправильно и может привести к зацикливанию, если в треугольник, образованный исследуемой точкой и концами левого края поля не будет попадать отрезок(ки) многоугольника.
Нужно исправить, чтобы вибиралось со всех сторон.

31 января 2011, 19:26: Статус вопроса изменён на решённый (изменил модератор Ерёмин А.А.): Автоматическая обработка (2 и более ответов с оценкой 5)

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:27
Выполнено за 0.03 сек.