几何相关计算

news2024/9/24 13:24:47

目录

一、判断两个矩形是否相交

二、判断两条线段是否相交

三、判断点是否在多边形内

四、垂足计算

五、贝塞尔曲线

六、判断多边形顺时针还是逆时针

七、判断凹多边形


一、判断两个矩形是否相交

当矩形1的最大值比矩形2的最小值都小,那矩形1和矩形2一定不相交,其他同理。

struct Point {
	double x;
	double y;
};
struct Rec {
	Point min;
	Point max;
};
bool is_rec_overlap(const Rec& r1, const Rec& r2) {
	if(r1.max.x < r2.min.x
		|| r1.max.y < r2.min.y
		|| r2.max.x < r1.min.x
		|| r2.max.y < r1.min.y) {
		return false;
	} else {
		return true;
	}	
}

二、判断两条线段是否相交

排斥实验+跨立实验

#include<iostream>
#include<vector>

struct Point {
	double x;
	double y;
	Point(double _x, double _y) : x(_x),y(_y) {}
};

struct Edge {
    Point s;
    Point e;
    Edge(const Point& _s, const Point& _e) : s(_s),e(_e) {}
};

// 判断点在直线的左右侧:计算叉积(p_e_p_s) × (p-p_s)
// 若返回结果>0,则点p在线段ps_p_e的左侧;
// 若返回结果<0,则点p在线段ps_p_e的右侧;
// 若返回结果=0,则点p与ps、p_e共线;
double is_left(const Point& p, const Point& p_s, const Point& p_e) {
    return (p_e.x - p_s.x)*(p.y - p_s.y) - (p_e.y - p_s.y)*(p.x - p_s.x);
}

bool edges_intersect(const Edge& edge1, const Edge& edge2) {
    // 排斥实验:最小外包框不想交,edges不可能相交
    if(std::min(edge1.s.x, edge1.e.x) > std::max(edge2.s.x, edge2.e.x)
        || std::min(edge1.s.y, edge1.e.y) > std::max(edge2.s.y, edge2.e.y)
        || std::min(edge2.s.x, edge2.e.x) > std::max(edge1.s.x, edge1.e.x)
        || std::min(edge2.s.y, edge2.e.y) > std::max(edge1.s.y, edge1.e.y)) {
        return false;
    }

    // 跨立实验:edge1的两个端点在edge2的两侧,且edge2的两个端点在edge1的两侧,则edges相交。
    if(is_left(edge1.s, edge2.s, edge2.e) * is_left(edge1.e, edge2.s, edge2.e) <= 0
        && is_left(edge2.s, edge1.s, edge1.e) * is_left(edge2.e, edge1.s, edge1.e) <= 0) {
        return true;
    }

    return false;
}

参考:https://www.cnblogs.com/TangMoon/p/7611115.html

三、判断点是否在多边形内

简单版

// 判断点在多边形内部还是外部(射线法):
// 从待判断的点出发,向某一方向(这里假设水平向右)发射一条射线;
// 遍历多边形的每一条边,检查射线是否相交
// 统计交点数量,若为偶数,则点在外部,否则,点在内部。
// 这里交点的判断简化为:edge的两个端点y值一个大于pt.y,一个小于pt.y,同时统计pt所在水平直线与edge交点的x值小于pt.x的个数。
bool is_in_polygon(const Point& pt, const std::vector<Point>& polygon) {
	int count = polygon.size();
	if(count < 3) {
		return false;
	}

    int intersecting_count = 0;
	for(int i = 0; i < polygon.size(); i++) {
		Point edge_s = polygon.at(i);
		Point edge_e = polygon.at((i+1)%count);
        if((pt.y <= edge_s.y && pt.y > edge_e.y 
            || pt.y <= edge_e.y && pt.y > edge_s.y)) {
            // 外层的if保证了edge_e.y != edge_s.y
            double pt_on_edge_x = (pt.y - edge_s.y) * (edge_e.x - edge_s.x) / (edge_e.y - edge_s.y) + edge_s.x;
            if(pt_on_edge_x < pt.x) {
                intersecting_count++;
            }
        }
	}
    return intersecting_count % 2 == 1;
}

参考:https://www.cnblogs.com/tgycoder/p/4901600.html

四、垂足计算

double cal_distance_square(const Point& pt1, const Point& pt2) {
    return (pt2.x - pt1.x) * (pt2.x - pt1.x) + (pt2.y - pt1.y) * (pt2.y - pt1.y);
}

// 计算(p_e-p_s)和(p-p_s)的点积
double dot_product(const Point& p, const Point& p_s, const Point& p_e) {
    return (p_e.x - p_s.x)*(p.x - p_s.x) + (p_e.y - p_s.y)*(p.y - p_s.y);
}

// 判断点pt到edge的投影点project_pt与edge的关系
/*  r = AP dot AB / ||AB||^2
    r=0 : project_pt = A
    r=1 : project_pt = B
    r<0 : project_pt is on backward extension of AB
    r>1 : project_pt is on forward extension of AB
   0<r<1: project_pt is on AB
*/
double relation(const Point& pt, const Edge& edge) {
    double len_square = cal_distance_square(edge.s, edge.e);
    // 特殊情况处理
    if(len_square < EP) {
        if(cal_distance_square(pt, edge.s) < EP) {
            return 0;
        } else {
            return -1; // 随便给个<0或>1的值
        }
    }
    return dot_product(pt, edge.s, edge.e) / len_square;
}

// 计算点pt到线段edge投影点.
// 若投影点在线段上,则project_pt赋值投影点,返回true
// 若投影点不在线段上,则project_pt赋值最近点,返回false。
bool calc_project_pt(const Point& pt, const Edge& edge, Point& project_pt) {
    double r = relation(pt, edge);
    if(r < 0) {
        project_pt = edge.s;
        return false;
    } else if (r > 1) {
        project_pt = edge.e;
        return false;
    }
    project_pt.x = edge.s.x + r * (edge.e.x - edge.s.x);
    project_pt.y = edge.s.y + r * (edge.e.y - edge.s.y);
    return true;
}

五、贝塞尔曲线

n阶贝塞尔曲线:B(t)=\sum_{i=0}^{n}\binom{n}{i}P_i(1-t)^{n-i}t^i

n阶贝塞尔曲线递归表达:P_0^n=(1-t)P_0^{n-1}+tP_1^{n-1},t\in [0,1]

二次贝塞尔曲线:B(t)=(1-t)^2P_0+2t(1-t)P_1+t^2P_2,t\in [0,1]

三次贝塞尔曲线:B(t)=(1-t)^3P_0+3t(1-t)^2P_1+3t^2(1-t)P_2+t^3P_3,t\in [0,1]

\binom{n}{i}表示从n个数中取i个数构成一个组合有多少种取法。

贝塞尔曲线(Bezier Curve)原理、公式推导及matlab代码实现-CSDN博客l

六、判断多边形顺时针还是逆时针

辛普森面积法

// 向量v1与向量v2的叉乘:
// 三维空间中为法向量,该向量垂直于向量v1与v2构成的平面。
// 二维空间中,有公式:v1×v2 = |v1||v2|sin(θ),该角度有正负,是指从v1到v2的角度
double cross_product(const Point& v1, const Point& v2) {
    return v1.x * v2.y - v1.y * v2.x;
}

// 辛普森面积法判断多边形坐标点是顺时针还是逆时针存储
// 面积<0,则为顺时针;面积>0,则为逆时针
bool is_clockwise_polygon(const std::vector<Point>& polygon) {
    int n = polygon.size();
    if(polygon.size() < 3) {
        return false;
    }
    double area = 0.0;
    for(int i = 1; i < n-1; i++) {
        Point v1 = Point(polygon.at(i).x - polygon.at((i-1+n)%n).x,
            polygon.at(i).y - polygon.at((i-1+n)%n).y);
        Point v2 = Point(polygon.at((i+1)%n).x - polygon.at(i).x,
            polygon.at((i+1)%n).y - polygon.at(i).y);
        area += cross_product(v1, v2) / 2;
        std::cout << "i: " << i << ",area: " << area << std::endl;
        
    }
    return area < 0;
}

七、判断凹多边形

(1)角度法:判断每个顶点的角度是否大于180度,若存在这样的顶点,则多边形为凹多边形。

(2)叉乘法:假设多边形形点为逆时针存储,依次判断P_{i-1}P_i,P_iP_{i+1}叉乘结果是否存在负值,若存在则为凹多边形。

// 向量v1与向量v2的叉乘:
// 三维空间中为法向量,该向量垂直于向量v1与v2构成的平面。
// 二维空间中,有公式:v1×v2 = |v1||v2|sin(θ),该角度有正负,是指从v1到v2的角度
double cross_product(const Point& v1, const Point& v2) {
    return v1.x * v2.y - v1.y * v2.x;
}

// 向量法判断多边形凹凸性。
// 以下代码要求:polygon的坐标点须为逆时针存储。
// 若坐标点为顺时针存储,代码中判断条件需要改为:cp>0。
bool is_convex_polygon1(const std::vector<Point>& polygon) {
    int n = polygon.size();
    if(polygon.size() < 3) {
        return false;
    }
    for(int i = 0; i < n; i++) {
        Point v1 = Point(polygon.at(i).x - polygon.at((i-1+n)%n).x,
            polygon.at(i).y - polygon.at((i-1+n)%n).y);
        Point v2 = Point(polygon.at((i+1)%n).x - polygon.at(i).x,
            polygon.at((i+1)%n).y - polygon.at(i).y);
        double cp = cross_product(v1, v2);
        std::cout << "i: " << i << ",cp: " << cp << std::endl;
        if(cp < 0 ) {
            return false;
        }
    }
    return true;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1932115.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ollama + fastgpt 搭建免费本地知识库

目录 1、ollama ollama的一些操作命令: 使用的方式: 2、fastgpt 快速部署: 修改配置: config.json: docker-compose.yml: 运行fastgpt: 访问OneApi: 添加令牌和渠道: 登陆fastgpt,创建知识库和应用 3、总结: 附录: 1. 11434是ollama的端口: 2. m3e 测…

SCI成稿丨计算机结合,中三区

Web服务器在慢速DDoS攻xxx改进研究互联网技术下基于xxx智能化交互空间艺术研究智慧城市视角企业经济发展中节xxxxx无线网络遥感图像xxx设计和规划中的应用分析基于智能物联网的生态养老控制系统与xxx展基于心理行为大数据分类算法的心理xxxxxxxxxx终端技术对消费者行为分析及客…

使用llama.cpp量化模型

文章目录 概要整体实验流程技术细节小结 概要 大模型量化是指在保持模型性能尽可能不变的情况下&#xff0c;通过减少模型参数的位数来降低模型的计算和存储成本。本次实验环境为魔搭社区提供的免费GPU环境&#xff08;24G&#xff09;&#xff0c;使用Llama.cpp进行4bit量化可…

go 语言实现快速排序

快速排序 - go 一、思路二、步骤及图解三、代码实现四、复杂度分析 一、思路 快速排序是一种分治策略的排序算法&#xff0c;关键过程是对数组进行划分。选择一个基准值&#xff08;pivot element&#xff09;&#xff0c;围绕着这个基准值划分子数组&#xff0c;对子数组递归调…

CyberVadis认证流程

1. 评估现有安全实践&#xff1a;组织需要对其现有的安全实践进行全面评估&#xff0c;包括安全策略、技术架构、人员安全意识等。 2. 确定目标&#xff1a;根据组织的需求和目标&#xff0c;确定需要改进的领域和优先级。 3. 制定计划&#xff1a;制定详细的认证计划&#x…

在 Windows 上开发.NET MAUI 应用_2.生成你的第一个应用

先决条件 Visual Studio 2022 17.8 或更高版本&#xff0c;并安装了 .NET Multi-platform App UI 工作负载。 可参考上一篇文章&#xff1a;http://t.csdnimg.cn/n38Yy 创建应用 1.启动 Visual Studio 2022。 在开始窗口中&#xff0c;单击“创建新项目”以创建新项目&#…

美式键盘 QWERTY 布局的来历

注&#xff1a;机翻&#xff0c;未校对。 The QWERTY Keyboard Is Tech’s Biggest Unsolved Mystery QWERTY 键盘是科技界最大的未解之谜 It’s on your computer keyboard and your smartphone screen: QWERTY, the first six letters of the top row of the standard keybo…

黑马头条Day02-app端文章查看,静态化freemarker

学习内容&#xff1a; 一、app端文章列表 1. 需求分析 文章的布局展示 2. 导入文章数据库 可以使用IDEA的数据库连接工具执行SQL脚本 3. 表结构分析 ap_article文章基本信息表 ap_article_config文章配置表 ap_article_content文章内容表 把课前资料里提供的实体类复制到mod…

转移C盘中的conda环境(包括.condarc文件修改,environment.txt文件修改,conda报错)

conda环境一般是默认安装到C盘的&#xff0c;若建立多个虚拟环境&#xff0c;时间长了&#xff0c;容易让本不富裕的C盘更加雪上加霜&#xff0c;下面给出将conda环境从C盘转移到D盘的方法。 目录 电脑软硬件转移方法查看当前conda目录转移操作第一步&#xff1a;.condarc文件修…

vmware虚拟机中,Centos安装Docker,解决国内无法访问

背景 本文主要解决了centos 的yum源 无法更新 和 docker的 源 国内无法访问的问题。 本文环境&#xff1a;windows宿主机装了vmware虚拟机&#xff0c;虚拟机中安装了Centos&#xff0c;centos内装docker。其实可以直接在window装docker desktop for windows&#xff0c;但…

ns3-gym入门(三):在opengym基础上实现一个小小的demo

因为官方给的"opengym""opengym-2"这两个例子都很简单&#xff0c;所以自己改了一个demo&#xff0c;把reward-action-state相互影响的关系表现出来 一、准备工作 在ns3.35/scratch目录下创建一个文件夹&#xff1a; &#xff08;后续的运行指令后面都需要…

JVM---对象是否存活及被引用的状态

1.如何判断对象是否存活 1.1 引用计数算法 概念&#xff1a;在对象头部增加一个引用计数器,每当有一个地方引用它时&#xff0c;计数器值就加一&#xff1b;当引用失效时&#xff0c;计数器值就减一&#xff1b;任何时刻计数器为零的对象就是不可能再被使用的。 优点&#xff1…

喰星云·数字化餐饮服务系统 多处 SQL注入漏洞复现

0x01 产品简介 喰星云数字化餐饮服务系统是一款专为餐饮企业设计的综合性管理软件,旨在通过信息化手段提升餐饮企业的运营效率、降低运营成本,并实现数据驱动的决策管理。该系统包括供应链管理、财务管理、巡店管理、人力资源管理等多个模块,可全面覆盖餐饮企业的日常运营需…

【多线程综合】java何时考虑线程安全问题、怎么考虑、又怎么解决?

前言&#xff1a;在编程中&#xff0c;线程安全是一个非常重要的概念。它涉及到多个线程并发访问共享资源时的正确性和一致性。在Java中&#xff0c;为了确保线程安全&#xff0c;我们需要考虑一些关键因素。 1、什么是线程安全 线程安全是指当多个线程同时访问一个对象时&am…

十大排序 之 快速排序

&#xff01;&#xff01;&#xff01;排序仅针对于数组哦本次排序是按照升序来的哦代码后边有图解哦 介绍 快速排序英文名为Quick Sort 基本思路 快速排序采用的是分治思想&#xff0c;即在一个无序的序列中选取一个任意的基准元素base&#xff0c;利用base将待排序的序列分…

基于RK3588的8K视频解码显示案例分享!引领超高清工业视频时代

8K、4K、2K显示对比 2K分辨率&#xff1a;也称为全高清&#xff08;FULL HD&#xff09;&#xff0c;它具有1920 x 1080像素的分辨率。这是目前大多数消费者电视和电脑显示器的标准分辨率&#xff0c;可以提供良好的图像质量。 4K分辨率&#xff1a;也称为4K超高清&#xff0…

我无法给博客园出钱,那我就出点建议吧

相信这张图大家都已经看见过了&#xff0c;从去年就传出博客园经营困难的情况&#xff0c;其实很多平台&#xff0c;不止是博客园&#xff0c;包括现在国内的很多公司都一样&#xff0c;经营是一件大难题&#xff0c;但很多公司我们不知道&#xff0c;悄无声息的倒下了。而博客…

【雅思备考IELTS】写作第一部分Writing Part One

Tips for IELTS Writing (Part 1) By James Lee 2024/7/15 Part 1: 图表数据分析 Analysis of a Graph / Chart / Curve, etc. 这部分一般是让分析一张图表&#xff08;Graph或Chart&#xff09;&#xff0c;用时约20分钟&#xff0c;字数不用太多&#xff0c;150词以上即可。…

推荐一个可以体验正版ChatGPT的平台

在鱼龙混杂的API市场&#xff0c;智创聚合API以其卓越的性能和创新的服务理念&#xff0c;为用户带来了前所未有的体验。我们自豪地宣布&#xff0c;现在加入我们的限时官方API渠道&#xff0c;您将享受到更快速率提升&#xff0c;以及更高质量的回复服务&#xff0c;而这些仅需…

Python酷库之旅-第三方库Pandas(028)

目录 一、用法精讲 71、pandas.tseries.api.guess_datetime_format函数 71-1、语法 71-2、参数 71-3、功能 71-4、返回值 71-5、说明 71-6、用法 71-6-1、数据准备 71-6-2、代码示例 71-6-3、结果输出 72、pandas.util.hash_array函数 72-1、语法 72-2、参数 72…