|
|||||
![]() последовательностях. Компиляторы и интерпретаторы. Хранение информации. Софт: просмотр PS и PDF файлов. ![]() Написать веб-мастеру Почитать историю сайта. |
Математика: Вычислительная геометрия.Проверка принадлежности точки многоугольнику.Случай треугольника.Для треугольника существует стандартный алгоритм, который надо знать, хотя и более общий тоже годится. Это - 'классика' аналитической геометрии, и в ручных расчетах используется именно он.
char BelongToPoly (point a, point b, point c, point p)
// Определение принадлежности точки треугольнику
{
float tmp1, tmp2;
char f1, f2, f3; // Флажки
/*
Для определения принадлежности точки
треугольнику используется следующий алгоритм:
вся плоскость делится прямой, содержащей
сторону треугольника, на две полуплоскости.
Далее смотрим, если наша точка и
противоположная этой стороне вершина треугольника
лежат в разных полуплоскостях, то точка не
принадлежит треугольнику.
Такую проверку надо провести для всех 3-х сторон !!!!!
*/
// Проверяем сторону AB
// Hаходим её уравнение y(x) по двум точкам
// Если точка P и точка C лежат в разных полуплоскостях,
// то произведение
// (y(p.x)-p.y)*(y(c.x)-c.y) будет отрицательным
// Уравнение прямой имеет вид:
// y(x)=((x-a.x)*(b.y-a.y))/(b.x-a.x)+a.y
tmp1=((p.x-a.x)*(b.y-a.y))/(b.x-a.x)+a.y-p.y;
tmp2=((c.x-a.x)*(b.y-a.y))/(b.x-a.x)+a.y-c.y;
if (tmp1*tmp2>=0) f1=1;
// То же проделываем для стороны BC
tmp1=((p.x-b.x)*(c.y-b.y))/(c.x-b.x)+b.y-p.y;
tmp2=((a.x-b.x)*(c.y-b.y))/(c.x-b.x)+b.y-a.y;
if (tmp1*tmp2>=0) f2=1;
// Аналогично для стороны CA
tmp1=((p.x-c.x)*(a.y-c.y))/(a.x-c.x)+c.y-p.y;
tmp2=((b.x-c.x)*(a.y-c.y))/(a.x-c.x)+c.y-b.y;
if (tmp1*tmp2>=0) f3=1;
// Точка принадлежит
if ((f1 == 1)&&(f2 == 1)&&(f3 == 1)) return (1);
// Точка не принадлежит
else return (0);
}
Выпуклый многоугольник.Теперь дадим общий алгоритм, пока только для выпуклых многоугольников. Alexandr Ivanov Пусть (x1,y1), (x2,y2), ... ,(xn,yn) - координаты точек полигона на плоскости. Сразу поясню, что координаты точек заданы в порядке обхода полигона в какую либо (любую) сторону, и стороны полигона не пересекаются (в последнем случае алгоритм тоже может работать корректно, но при дополнительных условиях) Xo,Yo - координаты точки,далее в цикле находим знак для каждого из векторных произведений Vn=(Xn+1-Xn)*(Yo-Yn)-(Xo-Xn)*(Yn+1-Yn)Zn=Sign(Vn) где Vn - значение в.п. для n-ной пары векторов, а Sign - функция возвращающая знак величины. Надо отметить, что в этом цикле при n = количеству вершин, n+1 = 1 (я думаю почему - и так понятно). Что мы делаем в геометрическом смысле ?
Таким образом, если точка внутри, то знаки всегда будут одинаковы - проверьте сами, Если же заранее известен обход вершин (например по часовой стрелке), то можно последнее условие упростить: если среди знаков есть '-' (для данного примера), то точка лежит вне, иначе внутри. Произвольный многоугольник.С произвольным многоугольником можно поступить гораздо проще, причем алгоритм будет включать и все предыдущие случаи. Проводим горизонтальную прямую через точку и сортируем координаты пересечений со сторонами по x. Если точка на четном месте - она внутри, на нечетном - снаружи. Отдельно рассматриваем случай нуля и лежит ли точка на пересечении линии со сторонами - иначе могут быть глюки. Алгоритм гораздо компактнее, но кода придется писать гораздо больше. Не забудьте разобрать случаи, когда точка лежит на сторонах. Вверх по странице, к оглавлению и навигации. | ||||