判断一点是否在不规则图像的内部算法,如下图是由一个个点组成的不规则图像,判断某一点是否在不规则矩形内部,先上效果图

算法实现如下,算法简单,亲试有效

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#判断一个点是否在一个复杂多边形的内部的更多相关文章

  1. Mysql中判断一个点是否落在多边形内

    关于地理空间数据,经常需要处理两个空间数据的关联关系.有很多种方法可以处理,通过编写程序算法,或者是调用数据库中对应的function.在mysql数据库中,https://dev.mysql.com ...

  2. C#算法之判断一个字符串是否是对称字符串

    记得曾经一次面试时,面试官给我电脑,让我现场写个算法,判断一个字符串是不是对称字符串.我当时用了几分钟写了一个很简单的代码. 这里说的对称字符串是指字符串的左边和右边字符顺序相反,如"abb ...

  3. js 判断一个点是否在一个多边形之内

    出处: https://github.com/substack/point-in-polygon/blob/master/index.js github: https://github.com/sub ...

  4. 判断点在多边形内算法的C++实现

    目录 1. 算法思路 2. 具体实现 3. 改进空间 1. 算法思路 判断平面内点是否在多边形内有多种算法,其中射线法是其中比较好理解的一种,而且能够支持凹多边形的情况.该算法的思路很简单,就是从目标 ...

  5. [算法]Python判断一个点是否在多边形内部

    题目: 代码: # -*- coding:utf-8 -*- def rayCasting(p, poly): px = p['x'] py = p['y'] flag = False i = 0 l ...

  6. python中如何不区分大小写的判断一个元素是否在一个列表中

    python中判断某一个元素是否在一个列表中,可以使用关键字in 和 not in. 示例如下: 如果需要输出相应的信息,可以搭配使用if语句,这里不赘述. --------------------- ...

  7. php 判断一个点是否在一个多边形区域内

    <?php class pointMap{ private static $coordArray; private static $vertx = []; private static $ver ...

  8. js 算法,判断一个数组中的数字出现多少次

    let arr = [11, 11, 2, 2, 5, 5, 5, 5, 3]; //创建一个map,把每个数字和其个数相对应 let countObj = {}; for (i = 0; i < ...

  9. JavaScript 中 如何判断一个元素是否在一个数组中

    <script type="text/javascript"> var arrList=['12','qw','q','v','d','t']; console.log ...

随机推荐

  1. python 入门基础22 --复习 面向对象

    面向过程编程思想: 核心:过程 过程指的是解决问题的具体步骤,即先干什么再干什么. 基于该编程思想编写程序,相当于一条流水线,一种机械式的思维方式. 面向对象编程思想: 核心:对象 对象指的是数据与方 ...

  2. 非常有助于理解二极管PN结原理的资料

    https://www.zhihu.com/question/60053574/answer/174137061 我理解的半导体 pn 结的原理,哪里错了? https://blog.csdn.net ...

  3. mount过程分析之六——挂载关系(图解)【转】

    转自:https://blog.csdn.net/zr_lang/article/details/40343899 引言 写到这里我们已经从mount文件系统调用的入口开始,分析到内核的mount,通 ...

  4. linux中断申请之request_threaded_irq【转】

    转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=21977330&id=3755609 在linux里,中断处理分 ...

  5. Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7)【转】

    原文地址:Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://bl ...

  6. 让linux中 history显示每条命令的操作时间及操作用户【转】

    一.history 中显示日期时间用户名的办法 history 命令,用来显示命令行上的操作记录 不过默认是仅显示操作命令行本身,而没有记录操作时间等细节 例如 这样,我们查找记录时很麻烦,想回顾下某 ...

  7. [原创]Sql2008 使用TVP批量插入数据

    TVP(全称 :Table-Valued Parameter) 叫做表值参数(Table-Valued Parameter)是SQL2008的一个新特性.顾名思义,表值参数表示你可以把一个表类型作为参 ...

  8. 【LOJ】#2078. 「JSOI2016」无界单词

    题解 用所有的方案减去有界的方案 我们规定两个前缀后缀相同时长度最短的,设长度为l,因为长度最短所以他们也是无界单词,可以递推 \(f[i] = \sum_{j = 1}^{\lfloor \frac ...

  9. Codeforces Round #480 (Div. 2) E - The Number Games

    题目大意:给你n个点的一棵树, 每个点的权值为2^i ,让你删掉k个点使得剩下的权值和最大. 思路:这题还是比较好想的, 我们反过来考虑, 剩下一个的情况肯定是选第n个点,剩下两个 我们肯定优先考虑第 ...

  10. CSS------如何让div中的div处于右下角

    如图: 代码: <div style="width:300px;height:300px"> <div style="position:absolute ...