zoukankan      html  css  js  c++  java
  • inPolygonTest学习和C++实现

    大家好,我是小鸭酱,博客地址为:http://www.cnblogs.com/xiaoyajiang  
    此篇博客实现了判定平面一点是否在给定多边形内部的功能。精确,性能优良,因为只包含加法和乘法运算,效率极高。
    实现的C++源码如下,注意点在源码的相应注释中。
    有错误和不好的地方还望各位批评指正。
     
    #include<iostream>
    using namespace std;
     
    struct Point2f  // 用以进行简单测试的结构。opencv中也有同名的数据类型,注意其x和y与我们想的不一样。
    {
        double x;
        double y;
    };
     
    bool onPolygonTest(Point2f polygon[], int num, Point2f test_point);  // 用以测试在多边形边上的退化情况
    bool onLineTest(Point2f p, Point2f q, Point2f s);  // 用以测试在边上的退化情况
    bool inPolygonTest(Point2f polygon[], int num, Point2f test_point);  // 一般情况
    bool toLeftTest(Point2f p, Point2f q, Point2f s);  // 核心技术
    double Area2(Point2f p, Point2f q, Point2f s);  // 核心技术实现
    /*----------------------------------------------------------------------*/
    /*   函数bool isInner(Point2f [], int num, Point2f, bool)               */
    /*   输入                                                                                 */
    /*         参数1 多边形顶点: Point2f polygon[]                             */
    /*         参数2 多边形顶点个数                                                    */
    /*         参数3 测试点:Point2f test_point                                   */
    /*         参数4 是否包含边上的点:bool isIncludeLine                    */
    /*   输出                                                                                */
    /*         true:在多边形内;                                                      */
    /*         false:不在多边形内                                                     */
    /*  作者:小鸭酱的书签                                                            */ 
    /*  日期:2016年9月28日                                                        */ 
    /*--------------------------------------------------------------------*/
    bool isInner(Point2f polygon[], int num, Point2f test_point, bool isIncludeLine)  
    {
        if(num < 3)
            return false;
        if (isIncludeLine)  // 首先判断退化情况
            return (onPolygonTest(polygon, num, test_point) || inPolygonTest(polygon, num, test_point));
        else  // 一般情况
            return inPolygonTest(polygon, num, test_point);
    }
     
    bool onPolygonTest(Point2f polygon[], int num, Point2f test_point)  // 只要点在任意一条边上,都算作在内部
    {
        int sum = 0;
        int i = 0;
        for(; i < num - 1; ++i)
        {
            sum += onLineTest(polygon[i], polygon[i+1], test_point);
            if (sum > 0)
                return true;
        }
        sum += onLineTest(polygon[i], polygon[0], test_point);
        return sum > 0;
    }
    bool onLineTest(Point2f p, Point2f q, Point2f s)  // 处理退化情况,判断点是否在线上;这里只处理多边形是没有旋转的矩形的情况。后期更新任意线段
    {
        if(p.x == q.x && q.x == s.x && (s.y - p.y) * (s.y - q.y) <= 0 )
            return true;
        else if(q.y == p.y && p.y == s.y && (s.x - p.x) * (s.x - q.x) <= 0 )
            return true;
        else
            return false;
    }
     
    bool inPolygonTest(Point2f polygon[], int num, Point2f test_point)  // 根据点在每条边的left或者right的pattern来判断是否在内部
    {
        int sum = 0;  // 用以记录有多少个left的pattern
        int i = 0;
        for(; i < num - 1; ++i)
        {
            sum += toLeftTest(polygon[i], polygon[i+1], test_point);
        }
        sum += toLeftTest(polygon[i], polygon[0], test_point);
     
        return (sum == 0 || sum == num) ? true : false;  // 很显然,当点在多边形的每条有向边的right或者left,它才会在内部
    }
     
    bool toLeftTest(Point2f p, Point2f q, Point2f s)  // 主要技术。有向面积值大于0则在有向边的左边
    {
        return Area2(p, q, s) > 0;
    }
     
    double Area2(Point2f p, Point2f q, Point2f s)  // 可见其只包含加法和乘法运算,计算给定点和多边形的一条有向边所组成的三角形的2倍面积,我们是要使用其符号来判断在左边还是右边
    {
     
        return
        p.x * q.y - p.y * q.x
        + q.x * s.y - q.y * s.x
        + s.x * p.y - s.y * p.x;
     
    }
     
    int main()                  // test
    {
        Point2f polygon[4];
        polygon[0].x = 0;
        polygon[0].y = 0;
        polygon[1].x = 2;
        polygon[1].y = 0;
        polygon[2].x = 2;
        polygon[2].y = 1;
        polygon[3].x = 0;
        polygon[3].y = 1;
        Point2f test_point;
     
        test_point.x = 0;
        test_point.y = 2;
        int n = sizeof(polygon) / sizeof(Point2f);
        cout << "in = " << inPolygonTest(polygon, n, test_point) << endl;
        cout << "online = " << onPolygonTest(polygon, n, test_point) << endl;
        cout << "output = " << isInner(polygon, n, test_point, false) << endl;
        cout << n << endl << endl;
     
        return 0;
    }
  • 相关阅读:
    VB C# 语法对比图 (代码实例)
    改进了的一个邮件发送类
    什么时候应该使用 ==?什么时候应该使用 Equals?
    c#写的贪吃蛇小游戏
    七招制胜ASP.NET应用程序开发
    SQL Server开发人员应聘常被问的问题汇总
    DataTable中数据记录的统计
    ASP.NET中数据库数据导入Excel并打印
    在.NET中得到计算机硬件信息的一些功能
    C#.NET 中的类型转换
  • 原文地址:https://www.cnblogs.com/xiaoyajiang/p/5950091.html
Copyright © 2011-2022 走看看