[GIS算法] 点是否在多边形内 - C语言实现

版权声明:本文为博主原创文章,若有错误之处望大家批评指正!转载需附上原文链接,谢谢! https://blog.csdn.net/summer_dew/article/details/83956564

【原理】https://blog.csdn.net/summer_dew/article/details/83982367 射线法

/*
  @Time:20181111
  @Title:判断点是否在多边形内,不考虑点在边上
  @Desc:用Point循环链表表示Polygon
 */
#include<stdio.h>
#include<stdlib.h>

#define EXP 1e-8 //精度

typedef struct point{
	double x;
	double y;
	struct point *next;
}Point, *Polygon;

int CreatePolygon(Polygon *p);
int PointInPolygon(Point A, Polygon P);

/*测试数据
11
0 0 
1 2
2 1
3 2
4 2
5 3
6 0
3 1
2 0
1 1.5
0 0
1 1
5 1.5
*/
int main() {
	Point A;
	Polygon polygon;
	
	CreatePolygon(&polygon);
	while (1) {
		printf("输入点A:\n>>> ");
		scanf("%lf%lf", &A.x, &A.y);
		printf("%d\n", PointInPolygon(A, polygon) );
	}
	
	return 0;
}

// 返回1:创建成功
// 返回0:创建不成功,点没有闭合
int CreatePolygon(Polygon *pHead) {
	int n;
	int i;
	Point *p,*q;
	double a,b;
	double suba,subb;

	scanf("%d", &n);
	p = NULL;
	for (i=0; i<n; i++) {
		scanf("%lf%lf", &a, &b);
		if (p==NULL) { //第一个结点
			p = (Point *)malloc(sizeof(Point)); if (!p) exit(0);
			p->x = a; p->y = b;
			p->next = p; //循环链表
			*pHead = p;
		} else { 
			suba = (*pHead)->x - a;
			subb = (*pHead)->y - b;
			if ( suba>=-EXP && suba<=EXP && subb>=-EXP && subb<=EXP) { //闭合
				return 1;
			}
			q = (Point *)malloc(sizeof(Point)); if (!q) exit(0);
			q->x = a; q->y = b;
			// 连接
			p->next = q;
			q->next = *pHead;
			// 下一个
			p = q;
		}
	}
	return 0;
}

// 向右作射线
int PointInPolygon(Point A, Polygon head) {
	Point *p, *p1, *p2;
	int cnt;
	double ymax;
	double ymin;
	double x;

	cnt=0;
	p = head;
	do{
		p1 = p;
		p2 = p->next;
		if (p1->y > p2->y) {
			ymax = p1->y;
			ymin = p2->y;
		} else {
			ymax = p2->y;
			ymin = p1->y;
		}

		// 看交点
		if ( p1->y-p2->y >=-EXP && p1->y-p2->y <=EXP ) { // p1p2 与 y=A.y 平行
			p = p->next;
			continue;
		} else if ( A.y < ymin ) { //交点在p1p2延长线上
			p = p->next;
			continue;
		} else if ( A.y >= ymax ) { //交点在p1p2延长线上
			p = p->next;
			continue;
		}

		// 直线p1p2与y=A.y的求交点坐标
		x = (double)(A.y-p1->y) * (double)(p2->x-p1->x) / (double)(p2->y-p1->y) + p1->x;
		// 交点在A的右侧
		if ( x > A.x)
			cnt++;
		p = p->next;
	}while (p!=head);

	return cnt%2==1;
}

猜你喜欢

转载自blog.csdn.net/summer_dew/article/details/83956564