Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Игры";
Текущий архив: 2003.04.14;
Скачать: [xml.tar.bz2];

Вниз

Точка внутри полигона   Найти похожие ветки 

 
serg_1   (2002-11-04 15:14) [0]

Доброго времени суток,

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

P.S. ф-ции аля PtInRegion не предлагать (нужен сам алгоритм, поскольку я пока "системонезависем", да и точки имеют другой тип).


 
MBo   (2002-11-04 15:18) [1]

проводим из точки прямую, считаем количество пересечений каждого луча со сторонами.
Если четное - внутри. При этом надо не попасть на вершину.


 
Lord Warlock   (2002-11-04 15:23) [2]

А если соединить отрезком проверяемую точку и гарантированно лежащую вне полигона и посчитать кол-во пересечений сторон полигона.


 
serg_1   (2002-11-04 15:38) [3]

2MBo
берем бублик, точка центр бублика. любая прямая дает 4 пересечения (естественно мы в двумерной с-ме координат). а вообще, насколько я помню, алгоритм "подсчета оборотов" реализуется и работает пошустрее.


 
MBo   (2002-11-04 15:45) [4]

я написал - каждого луча прямой. Но ошибся -для внутренней точки должно быть нечетным.

посмотри еще это - я не проверял

type XYPoint = record
x,y: double;
end;

function IsInsidePolygon(const Polygon: array of XYpoint; const p: XYPoint):
boolean;
// returns "true" if p is inside polygon
var
i: integer;
p1, p2: ^XYPoint;
begin
Result:= false;
p2:= @Polygon[High(Polygon)];
for i:=Low(Polygon) to High(Polygon) do begin
p1:= @Polygon[i];
if ( (((p1.y<=p.y) and (p.y<p2.y)) or ((p2.y<=p.y) and (p.y<p1.y)))
and
(p.x<(p2.x-p1.x)*(p.y-p1.y)/(p2.y-p1.y)+p1.x) )
then Result:= not Result;
p2:= p1;
end;
end;



 
serg_1   (2002-11-04 16:16) [5]

угу, это похоже есть подсчет числа пересечиний луча (x,y) - (x, +infinity) с полигоном. работает почти всегда:). в случае, если для какой-то стороны y=y1=y2 результат не определен.


 
Ketmar   (2002-11-06 12:57) [6]

2serg_1:
а такие стороны можно смело выкидывать, ибо толку от них - 0. в принципе - очень даже работоспособный алгоритм (у меня шуршит не первый год, и ничего %-)).

Satanas Nobiscum! 06-Nov-XXXVII A.S.


 
Sapersky_   (2002-11-10 11:44) [7]

А определение пересечения двух произвольных отрезков - не подскажете ли?


 
MBo   (2002-11-10 12:58) [8]

http://algolist.manual.ru/maths/geom/intersect/lineline2d.php


 
Miha-ha   (2002-11-10 14:05) [9]

Есть такой вариант, но только для выпуклых полигонов:
Нужно провести от точки ко всем вершинам полигона прямые и подсчитать сумму углов меж этими прямыми, если она меньше 360градусов тогда точка либо вне полигона либо на границе полигона, если равна 360 то точка внутри!


 
Sapersky_   (2002-11-10 22:17) [10]

Спасибо. Я вроде и сам уже придумал - у меня есть функция определения положения точки относительно отрезка (справа/слева), и если точки одного отрезка лежат по разные стороны другого и наоборот, то вроде они пересекаются.


 
serg_1   (2002-11-12 11:22) [11]

2Ketmar
там еще надо смотреть пересекает ли наш луч вершину и если да, то каким образом (возможны три типа, случай когда у=у1=у2 действительно можно просто игнорировать:))
\/ \
--, ---, ---
/\ /
в первом и втором случаях пересечение не считаем, в последнем считаем.
2Miha-ha
насколько я понял имеется ввиду алгоритм, который считает сумму углов между нашей точкой (t) и точками (t1,..,tn) полигона, т.е.
угол_между((t;t1),(t;t2))+угол_между((t;t2),(t;t3))+...+угол_между((t;tn),(t;t1)).
если да, то почему он применим только для выпуклых полигонов? может быть ограничение более слабое, - для несамопересекающихся?


 
Ketmar   (2002-11-12 17:22) [12]

2serg_1:
да, конечно. извиняюсь за краткость и неточность - ну уж очень давно было, мог и забыть %-)

Satanas Nobiscum! 12-Nov-XXXVII A.S.


 
SashaS   (2002-11-15 16:33) [13]

Работает алгоритм для произвольных многоугольников даже с самопересечениями.

Подсчитывает сумму углов при обходе.


function testInsideRegion(X, Y: Integer;points:TPoints):boolean;
var i,j,k:Integer;
gangl,ang,sm,ab,bc,ac,scal:real;
pa,pb,pcl,pav,pnm,pna:Tpoint;

function rr(r1,r2:TPoint):real;
begin
result:= sqrt(sqr(r1.x-r2.x)+sqr(r1.y-r2.y));
end;

begin

ang:=0;

for i:= 1 to length(points) do //
begin

pa:=points[i-1];

if i=length(points) then pb:=points[0]
else pb:=points[i];

pcl.x:=x;
pcl.y:=y;

pav.x:= ((pa.x+pb.x)div 2)-pcl.x;
pav.y:= ((pa.y+pb.y)div 2)-pcl.y;

pnm.x:= pav.y;
pnm.y:=-pav.x;

pna.x:= pb.x-pa.X;
pna.y:= pb.y-pa.y;
scal := pnm.x*pna.X +pnm.y*pna.y;

ab:= rr(pa,pb);
ac:= rr(pa,pcl);
bc:= rr(pcl,pb);

if (abs(ac)<0.01)or(abs(bc)<0.01) then
begin
ang:=2*pi;
break;
end;

gangl:= (-sqr(ab)+sqr(bc)+sqr(ac)) /(2*ac*bc);
if abs(gangl)>=1 then sm:=pi else sm:= arcCos(gangl);

if scal>0 then ang:= ang + sm else ang:= ang - sm;
end;

if abs(abs(ang)-2*pi)<0.01 then
result:=true else
result:=false;

end;




Страницы: 1 вся ветка

Форум: "Игры";
Текущий архив: 2003.04.14;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.47 MB
Время: 0.007 c
14-44357
Namo
2003-03-31 10:15
2003.04.14
Американцы не были на Луне.


3-43998
Шоломицкий
2003-03-23 18:27
2003.04.14
Из базы выбрать


1-44116
Shirson
2003-04-03 08:54
2003.04.14
Как определить размер блока, полученного в pByte?


7-44491
Serghei
2003-02-18 15:58
2003.04.14
Двунаправленная и построчная печать !!!!


6-44295
D
2003-02-20 16:14
2003.04.14
Сокеты через WinAPI





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский