首先判断要检测的点是否在边上
然后再判断射线是否经过一个线段的端点,如果经过低端点不计数,经过高端点计数
#include <vector>
#include <string>
#include <iostream>
#include <cmath>
#include <stdio.h>
using namespace std;
const double eps = 1e-10;
const int N = 103;
bool lessEqual(double a, double b) {//<=
return a < b + eps;
}
bool largerEqual(double a, double b) {// >=
return a + eps > b;
}
bool equal(double a, double b) {
return fabs(a-b) < eps;
}
struct point {
double x;
double y;
point(){}
point(double a, double b) :x(a),y(b) {}
};
point ps[N];
int num;
int m;
//(b-a)X(c-a)
//如果b在c的右手边,为正;
//b在c的左手边,为负
//a,b,c共线,0
double x_multi(point &a, point &b, point &c) {
return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}
//(b-a)X(c-a)
//夹角小于90,正
//大于90,负
//等于90,0
double dot_multi(point &a, point &b, point &c) {
return (b.x - a.x) * (c.x - a.x) + (b.y - a.y) * (c.y - a.y);
}
bool onSegment(point &a, point &b, point &c) {//c点是否在线段ab之间
double max_x = max(a.x, b.x);
double max_y = max(a.y, b.y);
double min_x = min(a.x, b.x);
double min_y = min(a.y, b.y);
if (equal(x_multi(a,b,c),0.0) && lessEqual(c.x,max_x) && largerEqual(c.x, min_x) && lessEqual(c.y, max_y) && largerEqual(c.y, min_y))
return true;
return false;
}
bool onLine(point &a, point &b, point &c) {//已知a,b,c共线
double max_x = max(a.x, b.x);
double max_y = max(a.y, b.y);
double min_x = min(a.x, b.x);
double min_y = min(a.y, b.y);
if (lessEqual(c.x,max_x) && largerEqual(c.x, min_x) && lessEqual(c.y, max_y) && largerEqual(c.y, min_y))
return true;
return false;
}
bool segmentIntersect(point &a, point &b, point &c, point &d) {//两条线段是否相交
double d1 = x_multi(a,b,d);
double d2 = x_multi(a,b,c);
double d3 = x_multi(c,d,a);
double d4 = x_multi(c,d,b);
if (d1*d2 < 0 && d3 * d4 <0)
return true;
if (equal(d1,0.0) && onLine(a,b,d))
return true;
if (equal(d2,0.0) && onLine(a,b,c))
return true;
if (equal(d3,0.0) && onLine(c,d,a))
return true;
if (equal(d4,0.0) && onLine(c,d,b))
return true;
return false;
}
bool isInside(point &pt) {
int count = 0;
point end(1e9,pt.y);
for (int i = 0; i < num; ++i) {
int j = (i+1)%num;
if (onSegment(ps[i], ps[j], pt))
return true;
if (!equal(ps[i].y, ps[j].y)) {
point low = ps[i];
if (low.y > ps[j].y)
low = ps[j];
if (onSegment(pt,end,low))//较低端点不计算
continue;
if (segmentIntersect(pt,end,ps[i],ps[j]))
++count;
/*int tmp = -1;
if (onSegment(pt,end,ps[i]))
tmp = i;
else if (onSegment(pt,end,ps[j]))
tmp = j;
if(tmp != -1 && equal(ps[tmp].y, max(ps[i].y,ps[j].y)))
++count;
else if (tmp == -1 && segmentIntersect(ps[i],ps[j],pt,end))
++count;*/
}
}
return count % 2==1;
}
int main() {
int ind = 1;
while (scanf("%d", &num) && num !=0) {
scanf("%d", &m);
for (int i = 0; i < num ; ++i){
scanf("%lf%lf",&ps[i].x, &ps[i].y);
}
if (ind !=1)
cout<<endl;
cout<<"Problem "<<ind<<":"<<endl;
++ind;
for (int i = 0; i < m; ++i) {
point pt;
scanf("%lf%lf", &pt.x, &pt.y);
if (isInside(pt))
cout<<"Within"<<endl;
else
cout<<"Outside"<<endl;
}
}
}