首先判断要检测的点是否在边上
然后再判断射线是否经过一个线段的端点,如果经过低端点不计数,经过高端点计数
#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; } } }