ZOJ 1081 Points Within 判断点是否在多边形内

题目很简单,就是给出一个多边形和一些点,判断这些点是否在给出的多边形内。

方法:

在计算射线L和多边形的交点的时候,1。对于多边形的水平边不作考虑;2。对于多边形的顶点和L相交的情况,如果该顶点是其所属的边上纵坐标较大顶点,则计数,否则忽略;3。对于P在多边形边上的情形,直接可判断P属于多边行。若交点个数为奇数,则在多边形内,否则不在。由此得出算法的伪代码如下:
   count ← 0;
    以P为端点,作从右向左的射线L; 
    for 多边形的每条边s
     do if P在边s上 
          then return true;
        if s不是水平的
          then if s的一个端点在L上
                if 该端点是s两端点中纵坐标较大的端点
                  then count ← count+1
              else if s和L相交
                then count ← count+1;
    if count mod 2 = 1 
      then return true;
    else return false;
  其中做射线L的方法是:设P'的纵坐标和P相同,横坐标为正无穷大(很大的一个正数),则P和P'就确定了射线L。

var
  n,tot,m,i,p,q:longint;
  x,y:array[1..100] of longint;

function max(x,y:longint):longint;
begin
  if x>y then exit(x)
         else exit(y);
end;

function min(x,y:longint):longint;
begin
  if x<y then exit(x)
         else exit(y);
end;

function pd(p,q:longint):boolean;
var
  p1,q1,sum,s,i,s1:longint;
begin
  p1:=maxlongint div 200000;
  q1:=q;
  sum:=0;
  for i:=1 to n do
  begin
    s:=(x[i]-x[i+1])*(q-y[i+1])-(p-x[i+1])*(y[i]-y[i+1]);
    if (s=0)and(p<=max(x[i],x[i+1]))and(p>=min(x[i],x[i+1]))and(q<=max(y[i],y[i+1]))and(q>=min(y[i],y[i+1])) then exit(true);
    if y[i]=y[i+1] then continue;
    s:=(p1-p)*(y[i]-q)-(q1-q)*(x[i]-p);
    if (s=0)and(x[i]<=max(p,p1))and(x[i]>=min(p,p1))and(y[i]<=max(q,q1))and(y[i]>=min(q,q1)) then
    begin
      if y[i]>y[i+1] then inc(sum);
      continue;
    end;
    s:=(p1-p)*(y[i+1]-q)-(q1-q)*(x[i+1]-p);
    if (s=0)and(x[i+1]<=max(p,p1))and(x[i+1]>=min(p,p1))and(y[i+1]<=max(q,q1))and(y[i+1]>=min(q,q1)) then
    begin
      if y[i+1]>y[i] then inc(sum);
      continue;
    end;
    s:=(p1-p)*(y[i]-q)-(q1-q)*(x[i]-p);
    s1:=(p1-p)*(y[i+1]-q)-(q1-q)*(x[i+1]-p);
    if s*s1>0 then continue;
    s:=(x[i+1]-x[i])*(q-y[i])-(y[i+1]-y[i])*(p-x[i]);
    s1:=(x[i+1]-x[i])*(q1-y[i])-(y[i+1]-y[i])*(p1-x[i]);
    if s*s1>0 then continue;
    inc(sum);
  end;
  if sum mod 2=0
    then exit(false)
    else exit(true);
end;

begin
  read(n);
  while n>0 do
  begin
    if tot>0 then writeln;
    inc(tot);
    writeln('Problem ',tot,':');
    readln(m);
    for i:=1 to n do
      readln(x[i],y[i]);
    x[n+1]:=x[1];
    y[n+1]:=y[1];
    for i:=1 to m do
    begin
      readln(p,q);
      if pd(p,q)
        then writeln('Within')
        else writeln('Outside');
    end;
    read(n);
  end;
end.


你可能感兴趣的:(ZOJ 1081 Points Within 判断点是否在多边形内)