首页 > 编程语言 >c++实现射线法 点和闭合区域位置关系判断

c++实现射线法 点和闭合区域位置关系判断

时间:2023-06-05 13:22:56浏览次数:46  
标签:return Point int 闭合 poly vertices 射线 c++ true

c++实现射线法   点和闭合区域位置关系判断

#include <iostream>
#include <vector>

struct Point {
    double x;
    double y;
};

struct Polygon {
    std::vector<Point> vertices;
};


// 定义三个点的方向
// 0 --> 点 p, q, r 是共线的
// 1 --> 顺时针
// 2 --> 逆时针
int orientation(Point p, Point q, Point r) {
    double val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
  
    if (val == 0) return 0;  // 共线
    return (val > 0) ? 1: 2; // 顺时针或者逆时针
}

// 检查线段 'p1q1' 和 'p2q2' 是否相交
bool doIntersect(Point p1, Point q1, Point p2, Point q2) {
    // 判断线段 'p1q1' 和 'p2q2' 的四个点的方向
    int o1 = orientation(p1, q1, p2);
    int o2 = orientation(p1, q1, q2);
    int o3 = orientation(p2, q2, p1);
    int o4 = orientation(p2, q2, q1);

    // 普通情况,四个方向都互不相同
    if (o1 != o2 && o3 != o4)
        return true;

    // 特殊情况,线段 'p1q1' 和 'p2q2' 的四个点是共线的
    if (o1 == 0 && onSegment(p1, p2, q1)) return true;
    if (o2 == 0 && onSegment(p1, q2, q1)) return true;
    if (o3 == 0 && onSegment(p2, p1, q2)) return true;
    if (o4 == 0 && onSegment(p2, q1, q2)) return true;

    return false; // 线段 'p1q1' 和 'p2q2' 不相交
}


bool isInside(Point p, Polygon poly) {
    int n = poly.vertices.size();
    if (n < 3) return false;  // 如果多边形顶点数量小于3则无法形成封闭图形
    
    Point extreme = {INT_MAX, p.y};  // 极点,点到这个极点的直线将和所有的边进行比较
    
    int count = 0, i = 0;
    do {
        int next = (i+1)%n;
        
        // 检查线段(poly.vertices[i], poly.vertices[next])是否与线段(p, extreme)相交
        if (doIntersect(poly.vertices[i], poly.vertices[next], p, extreme)) {
            // 如果点在多边形的一个顶点上,返回 true
            if (orientation(poly.vertices[i], p, poly.vertices[next]) == 0)
                return onSegment(poly.vertices[i], p, poly.vertices[next]);
            count++;
        }
        i = next;
    } while (i != 0);
    
    // 如果 count 为奇数,返回 true
    return count & 1;
}

// 给定三个共线点 p, q, r,检查点 q 是否在线段 'pr' 上
bool onSegment(Point p, Point q, Point r) {
    if (q.x <= std::max(p.x, r.x) && q.x >= std::min(p.x, r.x) &&
        q.y <= std::max(p.y, r.y) && q.y >= std::min(p.y, r.y))
        return true;
    return false;
}


int main() {
    Polygon polygon = {{0, 0}, {10, 0}, {10, 10}, {0, 10}};
    Point p = {5, 5};
    if (isInside(p, polygon))
        std::cout << "Point is inside the polygon.";
    else
        std::cout << "Point is outside the polygon.";
    return 0;
}

 

 

 

 

#####################

标签:return,Point,int,闭合,poly,vertices,射线,c++,true
From: https://www.cnblogs.com/herd/p/17457532.html

相关文章

  • java 图形学 点和闭合区域位置关系判断
    判断一个点是否在一个特定的区域内或外,通常需要你具备区域的数学表达(例如,方程、不等式等)以及要判断的点的坐标。例如,如果你有一个圆的方程(x-h)²+(y-k)²=r²,其中(h,k)是圆心,r是半径,你要判断点(a,b)是否在此圆内或外。你可以将点(a,b)的坐标带入这个方程:如果(a......
  • C++之浅拷贝和深拷贝
    浅拷贝:简单的复制拷贝操作P1的生命周期结束后,判断m_PtrAge是否为空,很明显m_PtrAge的值是0x0100,不为空,释放m_PtrAge指向的内存;P2的生命周期结束后,同样判断m_PtrAge是否为空,很明显m_PtrAge的值也是0x0100,也不为空,再次释放m_PtrAge指向的内存空间;两次释放都指向同一块内存空间,造成......
  • C++智能指针:weak_ptr
    weak_ptr虽然是智能指针,但实际上是作为shared_ptr的辅助指针使用。weak_ptr通常不单独使用,一般用于查看对应的shared_ptr的信息。weak_ptr没有重载*,->等指针运算符。weak_ptr对象不会影响shared_ptr对象的引用计数。 #include<iostream>#include<string.h>#include<memory......
  • C++继承
      三类继承方式子类会将父类的所有非静态成员属性继承过来,只不过编译器隐藏了父类的私有属性,子类不可以访问。 1classBase{2public:3inta_;4protected:5intb_;6private:7intc_;8};910classSon:publicBase{11pu......
  • 一个基于C++11的异步安全日志库
    0源码获取gitee1概述这是一个基于c++11的异步日志库目前仅支持windows已通过VS2019+windows11测试。支持自动清理距今指定天数的日志支持设定日志文件输出路径2待实现支持linux3一个范例使用范例 std::unique_ptr<oct_tk::AsyncLogging>async_log=s......
  • C++ 多态原理
    多态就是多种形态,C++的多态分为静态多态与动态多态。动态多态就是通过继承重写基类的虚函数实现的多态,在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。多态的总结:(1)用virtual关键字声明的函数叫做虚函数,虚函数肯定是类的......
  • QT的特殊命名空间方式和C++对比
    Qt有以下的写法QT_BEGIN_NAMESPACEnamespaceUi{classWidget;}QT_END_NAMESPACE在开始和结束关键字中间进行命名空间的创建及其内部类的声明 而C++则是直接进行创建namespaceMyNamespace{//在MyNamespace命名空间内定义的类、函数、变量等classMyC......
  • C++ 多态 虚函数virtual
    先解释虚函数,对于基类,子类继承基类后可能会调用其某个函数FA,而不同的子类继承了同一个基类后需要基类内某个同样的函数FA但又不是同个作用,此时则会在对应的子类内对应重载派生出FA_B函数和FA_C函数,而这时要求FA为虚函数(virtual)那为什么不各自写成一个函数B和C呢?这就是多态的意......
  • C++程序开发技巧
    引言类(class)的使用分为两种——基于对象(objectBased)和面向对象(objectoriented)基于对象是指,程序设计中单一的类,和其他类没有任何关系单一的类又分为:不带指针的类(classwithoutpointermembers)和带指针的类(classwithpointermembers)面向对象则是类(class)中涉及了类之间的关......
  • Effective Modern C++(四)再探移动语义与完美转发
    移动语义移动语义是c++11最为重要的特性之一,但这不代表着我们可以在任何时候都无脑地使用它。在以下几个情况下,移动语义并没有什么用处。没有移动操作:要移动的对象没有提供移动操作,所以移动的写法也会变成复制操作。比如对于STL库中的array容器而言,他的元素都直接存储在了......