function ptInPolygon(x,y : integer;
Points: array of TPoint) : boolean;
var
rgn:HRGN;
bmp : Tbitmap;
begin
bmp := Tbitmap.create;
begin
Path(bmp.canvas.handle);
//开始记录路径
bmp.Canvas.Polygon(points);
EndPath(bmp.canvas.handle);
// 闭合路径
rgn:= PathToRegion(bmp.canvas.handle);
// 简切视窗
result := PtInRegion(rgn,x,y);
// 判断
bmp.free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if ptinpolygon(1000,1000,[Point(10, 10), Point(30, 10),
Point(130, 30), Point(240, 120)]) then
showmessage('In!')
else
showmessage('out!');
end;
***********************************
下面是真正的实现的算法:
huizhang (1998-12-31 8:01:35)
实在对不起, 那个算法确实有问题, 缺少一点判断。
现在给你另外一个算法,叫做“跳栅栏算法”。其原理如下:
假设有一个栅栏,你从现在所站地点沿着一个方向跑过去,遇到栅栏时就跳过去,记住你跳了几次。如果次数是单数,则你在栅栏内;如果是双数,则你在栅栏外。以下算法是向东跑过去的实现方法。该算法虽然用了一点除法,但是由于排除了不相关的栅栏,故速度也很快。此外它的优点是与多边形的排列方向无关。
function TForm1.PointInFence(p: TPoint;
Fence: Array of TPoint): boolean;
var
p1: TPoint;
ar: integer;
i, j: integer;
begin
ar:=0;
for i:=0 to PtNos-1do
begin
if i=PtNos-1 then
j:=0 else
j:=i+1;
//如果在所站点的水平方向上有栅栏存在
if ((((p.y>=Fence.y) and (p.y<fence[j].y)) or
((p.y>=fence[j].y) and (p.y<fence.y))) and
//且栅栏在我的右方
(p.x<(fence[j].x-fence.x)*(p.y-fence.y)/(fence[j].y-fence.y)+fence.x)) then
ar := Ar+1;
end;
result:= (Ar and $1) > 0;
end;