当前位置: 首页 > news >正文

判断点在多边形内部

0. 介绍

网上资料很多,只简单介绍下,方便自己今后的理解。

1. 射线法

从该点引一条射线出来,如果和多边形有偶数个交点,则点在多边形外部。

因为有入必有出,所以从外部引进来的射线一定是交多边形偶数个点。

如图

在这里插入图片描述

这种方法唯一注意点是处理,引出的这条射线包括了多边形的边或者端点。

对此为了保证不重复,我们忽略在该射线上的边,和终点在该射线上的点。

实现

#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
#define INSIDE 0
#define OUTSIDE 1typedef struct {double x,y;
} Point;int InsidePolygon(Point *polygon,int N,Point p)
{int counter = 0;int i;double xinters;Point p1,p2;p1 = polygon[0];for (i=1;i<=N;i++) {p2 = polygon[i % N];if (p.y > MIN(p1.y,p2.y)) // 确保了点在多边形端点上,点的相邻边只被计算了一次。{if (p.y <= MAX(p1.y,p2.y)) {if (p.x <= MAX(p1.x,p2.x)) {// 为使得水平射线与边相交的条件 // y_0 < y <= y_1// min(x_0,x_1) < xif (p1.y != p2.y) {xinters = (p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;// 判断点是否在这条边的左侧if (p1.x == p2.x || p.x <= xinters)counter++;}}}}p1 = p2;}if (counter % 2 == 0)return(OUTSIDE);elsereturn(INSIDE);
}

判断点在边的左侧的示意图

在这里插入图片描述

2. 内角和

当点在多边形内时,内角和为 2 π 2 \pi 2π

实现参考

typedef struct {int h,v;
} Point;int InsidePolygon(Point *polygon,int n,Point p)
{int i;double angle=0;Point p1,p2;for (i=0;i<n;i++) {p1.h = polygon[i].h - p.h;p1.v = polygon[i].v - p.v;p2.h = polygon[(i+1)%n].h - p.h;p2.v = polygon[(i+1)%n].v - p.v;angle += Angle2D(p1.h,p1.v,p2.h,p2.v);}if (ABS(angle) < PI)return(FALSE);elsereturn(TRUE);
}/*Return the angle between two vectors on a planeThe angle is from vector 1 to vector 2, positive anticlockwiseThe result is between -pi -> pi
*/
double Angle2D(double x1, double y1, double x2, double y2)
{double dtheta,theta1,theta2;theta1 = atan2(y1,x1);theta2 = atan2(y2,x2);dtheta = theta2 - theta1;while (dtheta > PI)dtheta -= TWOPI;while (dtheta < -PI)dtheta += TWOPI;return(dtheta);
}

3. 同侧法

当多边形为凸多边形时,我们可以判断该点是否在各个边形成的直线的一侧;

来判断点是否在多边形的内部。实际上就是一个线性规划问题。

凹多边形的凹角附近不满足该条件。

只需要判断

( x − x 0 ) ( y 1 − y 0 ) + ( y − y 0 ) ( x 0 − x 1 ) (x-x_0)(y_1-y_0)+(y-y_0)(x_0-x_1) (xx0)(y1y0)+(yy0)(x0x1)

的值即可判断,点在多边形边的哪一侧。

给定两个点 P 0 ( x 0 , y 0 ) , P 1 ( x 1 , y 1 ) P_0(x_0,y_0),P_1(x_1,y_1) P0(x0,y0),P1(x1,y1),直线一般方程 A x + B y + c = 0 Ax+By+c=0 Ax+By+c=0推导。

  1. x 0 = x 1 x_0=x_1 x0=x1
    x − x 0 = 0 x-x_0=0 xx0=0
  2. x 0 ≠ x 1 x_0 \ne x_1 x0=x1
    直线点斜式方程 y = k x + b k = y 1 − y 0 x 1 − x 0 带入 P 0 , P 1 b = y 0 − k x 0 b = y 1 − k x 1 2 b = ( y 0 + y 1 ) − k ( x 0 + x 1 ) 带入 k ,化简得到 b = x 1 y 0 − x 0 y 1 x 1 − x 0 化为一般式子得到 ( y 1 − y 0 ) x + ( x 0 − x 1 ) y + x 1 y 0 − x 0 y 1 = 0 更加统一的形式 ( y 1 − y 0 ) ( x − x 0 ) + x 0 y 1 − x 0 y 0 + ( x 0 − x 1 ) ( y − y 0 ) + x 0 y 0 − x 1 y 0 + x 1 y 0 − x 0 y 1 = 0 合并化简得到 ( x − x 0 ) ( y 1 − y 0 ) − ( y − y 0 ) ( x 1 − x 0 ) = 0 直线点斜式方程y=kx+b\\ k=\frac{y_1- y_0}{x_1-x_0}\\ 带入P_0,P_1\\ b=y_0-kx_0\\ b=y_1-kx_1\\ 2b=(y_0+y_1)-k(x_0+x_1)\\ 带入k,化简得到\\ b=\frac{x_1y_0-x_0y_1}{x_1-x_0}\\ 化为一般式子得到\\ (y_1-y_0)x+(x_0-x_1)y+x_1y_0-x_0y_1=0\\ 更加统一的形式\\(y_1-y_0)(x-x_0)+x_0y_1-x_0y_0+\\(x_0-x_1)(y-y_0)+x_0y_0-x_1y_0+x_1y_0-x_0y_1=0\\ 合并化简得到\\ (x-x_0)(y_1-y_0)-(y-y_0)(x_1-x_0)=0 直线点斜式方程y=kx+bk=x1x0y1y0带入P0,P1b=y0kx0b=y1kx12b=(y0+y1)k(x0+x1)带入k,化简得到b=x1x0x1y0x0y1化为一般式子得到(y1y0)x+(x0x1)y+x1y0x0y1=0更加统一的形式(y1y0)(xx0)+x0y1x0y0+(x0x1)(yy0)+x0y0x1y0+x1y0x0y1=0合并化简得到(xx0)(y1y0)(yy0)(x1x0)=0
  3. x 0 = x 1 x_0=x_1 x0=x1代入 ( x − x 0 ) ( y 1 − y 0 ) − ( y − y 0 ) ( x 1 − x 0 ) = 0 (x-x_0)(y_1-y_0)-(y-y_0)(x_1-x_0)=0 (xx0)(y1y0)(yy0)(x1x0)=0;
    得到 x − x 0 = 0 x-x_0=0 xx0=0

归纳可得直线一般式方程
( y 1 − y 0 ) x + ( x 0 − x 1 ) y + x 1 y 0 − x 0 y 1 = 0 或 ( x − x 0 ) ( y 1 − y 0 ) − ( y − y 0 ) ( x 1 − x 0 ) = 0 (y_1-y_0)x+(x_0-x_1)y+x_1y_0-x_0y_1=0\\ 或\\ (x-x_0)(y_1-y_0)-(y-y_0)(x_1-x_0)=0 (y1y0)x+(x0x1)y+x1y0x0y1=0(xx0)(y1y0)(yy0)(x1x0)=0

4. 原文

eecs

http://www.lryc.cn/news/346249.html

相关文章:

  • livox雷达斜装修改
  • 【Spring】初识 Spring AOP(面向切面编程)
  • k8s各个组件的作用
  • Spring Cloud 整合Sentinel
  • Java入门基础学习笔记4——开发Helloworld入门程序
  • 了解WebSocket
  • 从开发角度理解漏洞成因(02)
  • Web实时通信的学习之旅:轮询、WebSocket、SSE的区别以及优缺点
  • TMS320F280049 CLB模块--LUT4 OUTLUT(4)
  • 功能测试_分类_用例_方法
  • [沫忘录]MySQL 锁
  • 噪声嵌入提升语言模型微调性能
  • XML文档基本语法
  • git开发工作流程
  • JDK生成https配置
  • 通过 Java 操作 redis -- set 集合基本命令
  • WebSocket前后端建立以及使用
  • C++数据结构之链表树图的存储
  • 又一位互联网大佬转行当网红,能写进简历么?
  • Codeforces Round 134 (Div. 1) A. Ice Skating (并查集)
  • 深入了解 Flask Request
  • 前端测试策略与实践:单元测试、E2E测试与可访问性审计
  • 修改el-checkbox样式
  • UE5缺少SDK,而无法在windows平台打包的解决方法
  • 4G,5G执法记录仪人脸识别、人脸比对使用说明
  • 掌握SEO优化的关键:提升网站排名的秘籍(如何提高网站seo排名)
  • 大模型微调之 在亚马逊AWS上实战LlaMA案例(九)
  • Php php7的特性
  • node pnpm修改默认包的存储路径
  • Adobe-Premiere-CEP 扩展 入门-视频剪辑-去气口插件-Silence Remover