点在多边形内算法,C#判断一个点是否在一个复杂多边形的内部
判断一点是否在不规则图像的内部算法,如下图是由一个个点组成的不规则图像,判断某一点是否在不规则矩形内部,先上效果图
算法实现如下,算法简单,亲试有效
public class PositionAlgorithmHelper{/// <summary>/// 判断当前位置是否在不规则形状里面/// </summary>/// <param name="nvert">不规则形状的定点数</param>/// <param name="vertx">当前x坐标</param>/// <param name="verty">当前y坐标</param>/// <param name="testx">不规则形状x坐标集合</param>/// <param name="testy">不规则形状y坐标集合</param>/// <returns></returns>public static bool PositionPnpoly(int nvert, List<double> vertx, List<double> verty, double testx, double testy){int i, j, c = 0;for (i = 0, j = nvert - 1; i < nvert; j = i++){if (((verty[i] > testy) != (verty[j] > testy)) && (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i])){c = 1 + c; ;}}if (c % 2 == 0){return false;}else{return true;}}}
用上图坐标进行测试:
class Program{static void Main(string[] args){test1();}/// <summary>/// test1/// </summary>public static void test1(){//不规则图像坐标List<Position> position = new List<Position>();position.Add(new Position() { x = 6, y = 0 });position.Add(new Position() { x = 10, y = 2 });position.Add(new Position() { x = 16, y = 2 });position.Add(new Position() { x = 20, y = 6 });position.Add(new Position() { x = 14, y = 10 });position.Add(new Position() { x = 16, y = 6 });position.Add(new Position() { x = 12, y = 6 });position.Add(new Position() { x = 14, y = 8 });position.Add(new Position() { x = 10, y = 8 });position.Add(new Position() { x = 8, y = 6 });position.Add(new Position() { x = 12, y = 4 });position.Add(new Position() { x = 6, y = 4 });position.Add(new Position() { x = 8, y = 2 });//用户当前位置坐标List<Position> userPositions = new List<Position>();userPositions.Add(new Position() { x = 14, y = 4 });userPositions.Add(new Position() { x = 15, y = 4 });userPositions.Add(new Position() { x = 10, y = 6 });userPositions.Add(new Position() { x = 8, y = 5 });//不规则图像x坐标集合List<double> xList = position.Select(x => x.x).ToList();//不规则图像y坐标集合List<double> yList = position.Select(x => x.y).ToList();foreach (var userPosition in userPositions){bool result = PositionAlgorithmHelper.PositionPnpoly(position.Count, xList, yList, userPosition.x, userPosition.y);if (result){Console.WriteLine(string.Format("{0},{1}【在】坐标内", userPosition.x, userPosition.y));}else{Console.WriteLine(string.Format("{0},{1}【不在】坐标内", userPosition.x, userPosition.y));}}}}
另外两种方式:
/// <summary> /// 判断点是否在多边形内. /// ----------原理---------- /// 注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数, /// 如果P在多边形外部,则交点个数必为偶数(0也在内)。 /// 所以,我们可以顺序考虑多边形的每条边,求出交点的总个数。还有一些特殊情况要考虑。假如考虑边(P1,P2), /// 1)如果射线正好穿过P1或者P2,那么这个交点会被算作2次,处理办法是如果P的从坐标与P1,P2中较小的纵坐标相同,则直接忽略这种情况 /// 2)如果射线水平,则射线要么与其无交点,要么有无数个,这种情况也直接忽略。 /// 3)如果射线竖直,而P0的横坐标小于P1,P2的横坐标,则必然相交。 /// 4)再判断相交之前,先判断P是否在边(P1,P2)的上面,如果在,则直接得出结论:P再多边形内部。 /// </summary> /// <param name="checkPoint">要判断的点</param> /// <param name="polygonPoints">多边形的顶点</param> /// <returns></returns> public static bool IsInPolygon2(Position checkPoint, List<Position> polygonPoints){int counter = 0;int i;double xinters;Position p1, p2;int pointCount = polygonPoints.Count;p1 = polygonPoints[0];for (i = 1; i <= pointCount; i++){p2 = polygonPoints[i % pointCount];if (checkPoint.y > Math.Min(p1.y, p2.y)//校验点的Y大于线段端点的最小Y && checkPoint.y <= Math.Max(p1.y, p2.y))//校验点的Y小于线段端点的最大Y {if (checkPoint.x <= Math.Max(p1.x, p2.x))//校验点的X小于等线段端点的最大X(使用校验点的左射线判断). {if (p1.y != p2.y)//线段不平行于X轴 {xinters = (checkPoint.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;if (p1.x == p2.x || checkPoint.x <= xinters){counter++;}}}}p1 = p2;}if (counter % 2 == 0){return false;}else{return true;}}/// <summary> /// 判断点是否在多边形内. /// ----------原理---------- /// 注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数, /// 如果P在多边形外部,则交点个数必为偶数(0也在内)。 /// </summary> /// <param name="checkPoint">要判断的点</param> /// <param name="polygonPoints">多边形的顶点</param> /// <returns></returns> public static bool IsInPolygon(Position checkPoint, List<Position> polygonPoints){bool inside = false;int pointCount = polygonPoints.Count;Position p1, p2;for (int i = 0, j = pointCount - 1; i < pointCount; j = i, i++)//第一个点和最后一个点作为第一条线,之后是第一个点和第二个点作为第二条线,之后是第二个点与第三个点,第三个点与第四个点... {p1 = polygonPoints[i];p2 = polygonPoints[j];if (checkPoint.y < p2.y){//p2在射线之上 if (p1.y <= checkPoint.y){//p1正好在射线中或者射线下方 if ((checkPoint.y - p1.y) * (p2.x - p1.x) > (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判断,在P1和P2之间且在P1P2右侧 {//射线与多边形交点为奇数时则在多边形之内,若为偶数个交点时则在多边形之外。 //由于inside初始值为false,即交点数为零。所以当有第一个交点时,则必为奇数,则在内部,此时为inside=(!inside) //所以当有第二个交点时,则必为偶数,则在外部,此时为inside=(!inside) inside = (!inside);}}}else if (checkPoint.y < p1.y){//p2正好在射线中或者在射线下方,p1在射线上 if ((checkPoint.y - p1.y) * (p2.x - p1.x) < (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判断,在P1和P2之间且在P1P2右侧 {inside = (!inside);}}}return inside;}
/// <summary> /// 判断点是否在多边形内. /// ----------原理---------- /// 注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数, /// 如果P在多边形外部,则交点个数必为偶数(0也在内)。 /// 所以,我们可以顺序考虑多边形的每条边,求出交点的总个数。还有一些特殊情况要考虑。假如考虑边(P1,P2), /// 1)如果射线正好穿过P1或者P2,那么这个交点会被算作2次,处理办法是如果P的从坐标与P1,P2中较小的纵坐标相同,则直接忽略这种情况 /// 2)如果射线水平,则射线要么与其无交点,要么有无数个,这种情况也直接忽略。 /// 3)如果射线竖直,而P0的横坐标小于P1,P2的横坐标,则必然相交。 /// 4)再判断相交之前,先判断P是否在边(P1,P2)的上面,如果在,则直接得出结论:P再多边形内部。 /// </summary> /// <param name="checkPoint">要判断的点</param> /// <param name="polygonPoints">多边形的顶点</param> /// <returns></returns> public static bool IsInPolygon2(Position checkPoint, List<Position> polygonPoints) { int counter = 0; int i; double xinters; Position p1, p2; int pointCount = polygonPoints.Count; p1 = polygonPoints[0]; for (i = 1; i <= pointCount; i++) { p2 = polygonPoints[i % pointCount]; if (checkPoint.y > Math.Min(p1.y, p2.y)//校验点的Y大于线段端点的最小Y && checkPoint.y <= Math.Max(p1.y, p2.y))//校验点的Y小于线段端点的最大Y { if (checkPoint.x <= Math.Max(p1.x, p2.x))//校验点的X小于等线段端点的最大X(使用校验点的左射线判断). { if (p1.y != p2.y)//线段不平行于X轴 { xinters = (checkPoint.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x; if (p1.x == p2.x || checkPoint.x <= xinters) { counter++; } } }
} p1 = p2; }
if (counter % 2 == 0) { return false; } else { return true; } }
/// <summary> /// 判断点是否在多边形内. /// ----------原理---------- /// 注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数, /// 如果P在多边形外部,则交点个数必为偶数(0也在内)。 /// </summary> /// <param name="checkPoint">要判断的点</param> /// <param name="polygonPoints">多边形的顶点</param> /// <returns></returns> public static bool IsInPolygon(Position checkPoint, List<Position> polygonPoints) { bool inside = false; int pointCount = polygonPoints.Count; Position p1, p2; for (int i = 0, j = pointCount - 1; i < pointCount; j = i, i++)//第一个点和最后一个点作为第一条线,之后是第一个点和第二个点作为第二条线,之后是第二个点与第三个点,第三个点与第四个点... { p1 = polygonPoints[i]; p2 = polygonPoints[j]; if (checkPoint.y < p2.y) {//p2在射线之上 if (p1.y <= checkPoint.y) {//p1正好在射线中或者射线下方 if ((checkPoint.y - p1.y) * (p2.x - p1.x) > (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判断,在P1和P2之间且在P1P2右侧 { //射线与多边形交点为奇数时则在多边形之内,若为偶数个交点时则在多边形之外。 //由于inside初始值为false,即交点数为零。所以当有第一个交点时,则必为奇数,则在内部,此时为inside=(!inside) //所以当有第二个交点时,则必为偶数,则在外部,此时为inside=(!inside) inside = (!inside); } } } else if (checkPoint.y < p1.y) { //p2正好在射线中或者在射线下方,p1在射线上 if ((checkPoint.y - p1.y) * (p2.x - p1.x) < (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判断,在P1和P2之间且在P1P2右侧 { inside = (!inside); } } } return inside; }
点在多边形内算法,C#判断一个点是否在一个复杂多边形的内部相关推荐
- 点在多边形内算法,JS判断一个点是否在一个复杂多边形的内部
点在多边形内算法,JS判断一个点是否在一个复杂多边形的内部: function isInPolygon(checkPoint, polygonPoints) {var counter = 0;var ...
- JAVA判断一个地理坐标是否在一个多边形区域内和是否在一个圆形区域内(经纬度)
怎么样判断一个坐标点在一个多边形区域内?包括规则多边形,不规则多边形,还有圆... 1 判断一个坐标是否在圆形区域内? 多边形和圆分开写,首先简单的就是判断是否在圆里面,如何判断一个坐标是否在圆形区域 ...
- [转]如何判断一个点是否在一个多边形内部
原文地址:http://hi.baidu.com/wayright/item/ad18e4c0c5446b2dee4665c9 在多边性的存储中,每一个多边形都是由一系列连续的点组成,例如保存为数组P ...
- Java 判断一个点是否在一个三角形内
题目描述: 如何判断一个点是否在一个三角形内. 测试样例: 自定义的POINT类: class POINT{int x;int y;public POINT(int x,int y){this.x ...
- Algorithm: 如何判断一个点是否在一个三角形内
昨日因为机缘巧合,做了一道阿里的实习生编程题.题目很有趣,其中涉及到了如何判断一个点是否在一个三角形内. 其中,判断这个问题最简单的方法是面积法.(图片来源:http://www.cnblogs.co ...
- 能否构成三角形的条件代码_Java 如何判断一个点是否在一个三角形内
题目描述: 如何判断一个点是否在一个三角形内. 测试样例: 自定义的POINT类: class POINT{ int x; int y; public POINT(int x,int y){ this ...
- 6-1 判断一个点是否在一个圆的内部 (20 分)
创建一个表示点的类Point,运用组合的方式创建圆形类. 圆形有个成员函数isPointIn用于判断一个点是否在该圆形的内部. 完成对应类代码,使得主函数可以正确运行. 注意类的数值型数据成员类型为浮 ...
- 判断一个点是否在某个多边形范围内(Java和python实现)
一.java实现 所用jar包: <dependency><groupId>nl.cloudfarming.client</groupId><artifact ...
- 微信小程序 - 判断一个经纬度是否在一个多边形区域内
功能描述: 最近公司做了一个定位打卡的小程序,需要判断用户的经纬度是否在一个闭合的多边形区域内,在区域内允许打卡,否则提示"不再打卡范围".由于腾讯地图小程序SDK没有提供相关功能 ...
最新文章
- 用python解“混合类型数据格式输入”题
- nsdata是java什么类型_Swift中基本数据类型与NSData转换
- 路由器命令大全手册教程 4
- Ajax调试servlet连接失败
- ##安装MySql数据库并解决如果安装出错卸载的注意事项
- 用Visual C++实现远程线程嵌入技术
- 数据库连接失败报错com.mysql.cj.jdbc.exceptions.CommunicationsException
- 《Android深度探索》第一章心得体会
- 贼好理解,这个项目教你如何用百行代码搞定各类NLP模型
- java 有限状态机_有限状态机( Finite State Machine )JAVA 版
- ajaxSubmit
- 数据库系统概念 第五章 习题答案
- 64位Win7 服务器运行失败
- AI大牛李沐装机视频来了!你也能练100亿的大模型
- 数据结构软件测试,资讯详情-java常见数据结构-柠檬班-自动化测试-软件测试培训-自学官网...
- 抖音书单号如何快速上热门
- 【Python图像处理】SciPy库
- matlab 伯德图 横坐标步长_【龙腾原创】教您使用matlab画伯德图(看了你就学会了,比mathcad好用多了。谁用谁知道!)...
- 快速入门Tableau系列 | Chapter13【雷达图和凹凸图】
- 【android】项目案例(三)之微信朋友圈上传,下载图片
热门文章
- 使用OpenCV创建视频
- OpenCV图像入门
- Qt Creator建立多个平台
- OpenGL纹理矩阵,alpha混合和丢弃
- C语言 内存管理之栈
- 经典C语言程序100例之三零
- 查找python矩阵中最大元素_找出矩阵中最大的元素
- Mycat关键特性,什么是MYCAT,MYCAT监控,版本架构,长期规划2.0,Mycat高可用方案
- SQLite Insert 语句(http://www.w3cschool.cc/sqlite/sqlite-insert.html)
- C语言二分查找法(指针和数组实现)