判断点与多边形关系

以前上学就学过,现在工作又遇到了,拿出来复习一下(看的很老的博客讲的都比较细了,不知道最近又有没有新方法)

  1. 引射线法:从被判断的点发射一条射线,与多边形有奇数个交点则在多边形内
  2. 面积和法:从多边形一顶点出发,计算被判断的点和相邻两点组成的三角形的面积和(可用1/2*向量叉乘求),面积和与多边形面积相等则在多边形内
  3. 夹角和法:从多边形一顶点出发,计算被判断的点和多边形相邻两顶点的夹角和(可用向量点积推出的夹角公式求),夹角和为360则在多边形内部
  4. 遮罩法:生成多边形的位图(多边形内部区域置为指定的颜色),找出将被判断点处位图的颜色,为指定的颜色则在内部

这几种方法除了遮罩法别的在判断凹多边形都得注意下细节,比如:

  • 夹角和法的射线正好卡在拐角处。
  • 面积和法、夹角和法顺时针为加,逆时针为减(要是都按加算的话肯定会算多了。。)

JS使用引射线法实现

已经有大神写出来了:substack/point-in-polygon: determine if a point is inside a polygon

/**
 * 判断点与多边形位置关系
 * @param  {Array<number>} point 待判断的点
 * @param  {Array<Array<number>>} vs    多边形点数组
 * @return {bool}       是否在内部
 */
function inside(point, vs){
    // ray-casting algorithm based on
    // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html

    var x = point[0], y = point[1];

    var inside = false;
    // 依次遍历多边形的每个边
    for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
        var xi = vs[i][0], yi = vs[i][1];
        var xj = vs[j][0], yj = vs[j][1];

        var intersect =
            ((yi > y) != (yj > y)) // 判断该点纵坐标是否在线段最高点和最低点之间[注1]
            && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); // 判断该点向x轴正方向发出的射线是否穿过线段[注2]

        if (intersect) inside = !inside;
    }

    return inside;
}

inside([0.5,2.5], [[1,1], [2,2], [1,3]])// false
inside([1.5,2], [[1,1], [2,2], [1,3]])// true

// 在边上的点又是什么情况?
inside([1.5,1.5], [[1,1], [2,2], [1,3]])// false
inside([1,2], [[1,1], [2,2], [1,3]])// true

注1:判断该点纵坐标是否在线段最高点和最低点之间

这里有5种情况:

      false (F!=F)

------false (F!=F)-------yi

      true  (T!=F)

------true  (T!=F)-------yj

      false (T!=T)

注2:判断该点向x轴正方向发出的射线是否穿过线段

  1. 计算改点平行于X轴的直线与该线段所在直线的交点的横坐标:(xj - xi) * (y - yi) / (yj - yi) + xi
  2. 判断该点横坐标是否小于交点的横坐标与孰大孰小:x < 交点的横坐标

C#实现

// 上面说的都没用到=_=,C#自带一个检测的方法

/* 说明:
 * 1. 虽然地球是圆的但中国坐标都是正的这么处理也没毛病
 *
 * 2. 经纬度一般小数点前3位后6位一共9位
 *
 *    PointF(float):32位,1位符号,8位指数,23位尾数。
 *    2^23 = 8,388,608 精度6-7位
 *    float不够用
 *
 *    Point(int):32位,1位符号,31位数
 *    2^31 = 2,147,483,648 精度9-10位
 *    int够用,但经测试只能乘100000,精确到小数点后5位(米级)
 *    乘1000000,精确到小数点后6位(分米级)时会全返回False,可能内部计算时越界了
 *
 *    计算时全是按双精度算的够用
*/

// 创建多边形区域
GraphicsPath gp = new GraphicsPath();
Region region = new Region();
gp.Reset();
gp.AddPolygon(new Point[]{
    new Point((int)(28.87243083439048 * 100000.0), (int)(106.83294296264648 * 100000.0)),
    new Point((int)(28.87243083439048 * 100000.0), (int)(106.84285640716554 * 100000.0)),
    new Point((int)(28.880735867389312 * 100000.0), (int)(106.84285640716554 * 100000.0)),
    new Point((int)(28.880735867389312 * 100000.0), (int)(106.83294296264648 * 100000.0)),
    new Point((int)(28.87243083439048 * 100000.0), (int)(106.83294296264648 * 100000.0))
});
region.MakeEmpty();
region.Union(gp);

//判断点是否在多边形区域里
bool result1 = region.IsVisible(new Point((int)(28.87243083439048 * 100000.0), (int)(106.83294296264648 * 100000.0)));
bool result2 = region.IsVisible(new Point((int)(39.904030 * 100000.0), (int)(116.407526 * 100000.0)));
Console.WriteLine(result1.ToString());
Console.WriteLine(result2.ToString());
Console.ReadLine();

原文地址:https://www.cnblogs.com/jffun-blog/p/10217693.html

时间: 2024-10-16 22:46:56

判断点与多边形关系的相关文章

matlab练习程序(射线法判断点与多边形关系)

依然是计算几何. 射线法判断点与多边形关系原理如下: 从待判断点引出一条射线,射线与多边形相交,如果交点为偶数,则点不在多边形内,如果交点为奇数,则点在多边形内. 原理虽是这样,有些细节还是要注意一下,比如射线过多边形顶点或射线与多边形其中一边重合等情况还需特别判断. 这里就不特别判断了,因为我只是熟悉原理,并不是实际运用. 好吧,我实际是太懒了,不想判断了. 结果如下: 结果图和线性分类器的组合有几分相似. matlab代码如下: clear all;close all;clc; polyn=

Cupid&#39;s Arrow---hdu1756(判断点与多边形的位置关系 模板)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1756 题意:中文题,套模板即可: /* 射线法:判断一个点是在多边形内部,边上还是在外部,时间复杂度为O(n): 射线法可以正确用于凹多边形: 射线法是使用最广泛的算法,这是由于相比较其他算法而言,它不但可以正 确使用在凹多边形上,而且不需要考虑精度误差问题.该算法思想是从点出 发向右水平做一条射线,计算该射线与多边形的边的相交点个数,当点不在 多边形边上时,如果是奇数,那么点就一定在多边形内部,否

线段与多边形关系的算法

目录 介绍 解决思路 问题一:点与线段的关系 问题二:线段与线段的关系 问题三:点与多边形的关系 问题四:线段与多边形的关系 总结 源码 介绍 最近项目中要用到有关几何(Geometry)方面的知识,程序需要判断给定的一条线段(Segment)与指定多边形(Polygon)的位置关系.这种关系分为三种:多边形包含线段.多边形与线段相交以及多边形与线段无关联. 起初我以为.NET类库中已经包含此种判定功能的API,比如类似System.Drawing.Region这些类型,后来等到实际要用的时候才

判断点在多边形内部

项目的需要,需要判断点在多边形的内部,是整个算法必要的步骤,查了一些资料,中文很少,英文资料已经介绍的很清楚了,这里只是总结一下. 问题的完整描述是判断平面上一点在多边形的内部.外部或者边界上. 有两种解决方法:光线投射算法,环绕数法. 光线投射算法: 一个简单的判断方法是从该点想任意固定方向发送射线,求射线于多边形边的交点的个数.如果交点的个数是偶数个,则该点在多边形的外部,如果是交点的个数是奇数,则该点在多边形的外部.这种方法不能判断在多边形上的情况. 要注意两个问题: 第一个是当要判断的点

HDU 1756 Cupid&#39;s Arrow 判断点在多边形的内部

Cupid's Arrow Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1163    Accepted Submission(s): 425 Problem Description 传说世上有一支丘比特的箭,凡是被这支箭射到的人,就会深深的爱上射箭的人.世上无数人都曾经梦想得到这支箭.Lele当然也不例外.不过他想,在得到这支箭前,

ZOJ 1081 Points Within | 判断点在多边形内

题目: 给个n个点的多边形,n个点按顺序给出,给个点m,判断m在不在多边形内部 题解: 网上有两种方法,这里写一种:射线法 大体的思想是:以这个点为端点,做一条平行与x轴的射线(代码中射线指向x轴正方向) 如果交点个数为奇数的话就在内部,如果为偶数(包括0)就在外部 #include<cstdio> #include<algorithm> #include<cstring> #define N 105 using namespace std; int n,m; stru

LightOj1190 - Sleepwalking(判断点与多边形的位置关系--射线法模板)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1190 题意:给你一个多边形含有n个点:然后又m个查询,每次判断点(x, y)是否在多边形的内部; 射线法判断即可适用于任何(凸或凹)多边形;时间复杂度为O(n); 判断一个点是在多边形内部,边上还是在外部,时间复杂度为O(n):射线法可以正确用于凹多边形: 射线法是使用最广泛的算法,这是由于相比较其他算法而言,它不但可以正确使用在凹多边形上,而且不需要考虑精度误差问题.该算法思想是从

Unity3D 中判断点与多边形的关系

由点发出的射线与多边形边的交点个数,如果是偶数个说明在多边形的外面,交点个数为奇数个在多边形的内部,下面是代码: public bool IsPointInPolygon(Vector2 point, Vector2[] polygon) { int polygonLength = polygon.Length, i = 0; bool inside = false; float pointX = point.x, pointY = point.y; float startX, startY,

Hdu 4458 Shoot the Airplane(判断点在多边形内)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4458 思路:以飞机为参考系,则飞机相对静止,子弹加上水平方向速度-v.则只需枚举时间,判断该时间时点(子弹)是否在多边形(飞机)内.注意g可以为0,分匀变速和匀速.另外本题精度要求较高,判断点在线段上用坐标差值,避免使用Dot . #include<cstdio> #include<cstring> #include<iostream> #include<algori