C-10 凸包

凸包

数学定义

  • 平面的一个子集S被称为是凸的,当且仅当对于任意两点A,B属于S,线段PS都完全属于S
  • 过于基础就不详细介绍了
    在这里插入图片描述

凸包的计算

  • github上找到了别人的代码,用4种方式实现了凸包的计算,把他放在这里
  • 链接地址https://github.com/MiguelVieira/ConvexHull2D
  • 先放这个代码的用法吧
int main() {
	vector<point> v = getPoints();
//1
	vector<point> h = quickHull(v);
	cout << "quickHull point count: " << h.size() << endl;
	print(h);
    
//2
	h = giftWrapping(v);
	cout << endl << "giftWrapping point count: " << h.size() << endl;
	print(h);
    
//3
	h = monotoneChain(v);
	cout << endl << "monotoneChain point count: " << h.size() << endl;
	print(h);
    
//4
	h = GrahamScan(v);
	cout << endl << "GrahamScan point count: " << h.size() << endl;
	print(h);
  • 这是具体的代码,直接写在一个头文件里,包含一下就能在程序里实现上面的诸多用法了


#include <algorithm>
#include <iostream>
#include <vector>
#include<random>
	using namespace std;
namespace ch{
	struct point {
		float x;
		float y;

		point(float xIn, float yIn) : x(xIn), y(yIn) { }
	};

	// The z-value of the cross product of segments 
	// (a, b) and (a, c). Positive means c is ccw
	// from (a, b), negative cw. Zero means its collinear.
	float ccw(const point& a, const point& b, const point& c) {
		return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
	}

	// Returns true if a is lexicographically before b.
	bool isLeftOf(const point& a, const point& b) {
		return (a.x < b.x || (a.x == b.x && a.y < b.y));
	}

	// Used to sort points in ccw order about a pivot.
	struct ccwSorter {
		const point& pivot;

		ccwSorter(const point& inPivot) : pivot(inPivot) { }

		bool operator()(const point& a, const point& b) {
			return ccw(pivot, a, b) < 0;
		}
	};

	// The length of segment (a, b).
	float len(const point& a, const point& b) {
		return sqrt((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y));
	}

	// The unsigned distance of p from segment (a, b).
	float dist(const point& a, const point& b, const point& p) {
		return fabs((b.x - a.x) * (a.y - p.y) - (b.y - a.y) * (a.x - p.x)) / len(a, b);
	}

	// Returns the index of the farthest point from segment (a, b).
	size_t getFarthest(const point& a, const point& b, const vector<point>& v) {
		size_t idxMax = 0;
		float distMax = dist(a, b, v[idxMax]);

		for (size_t i = 1; i < v.size(); ++i) {
			float distCurr = dist(a, b, v[i]);
			if (distCurr > distMax) {
				idxMax = i;
				distMax = distCurr;
			}
		}

		return idxMax;
	}


	// The gift-wrapping algorithm for convex hull.
	// https://en.wikipedia.org/wiki/Gift_wrapping_algorithm
	vector<point> giftWrapping(vector<point> v) {
		// Move the leftmost point to the beginning of our vector.
		// It will be the first point in our convext hull.
		swap(v[0], *min_element(v.begin(), v.end(), isLeftOf));

		vector<point> hull;
		// Repeatedly find the first ccw point from our last hull point
		// and put it at the front of our array. 
		// Stop when we see our first point again.
		do {
			hull.push_back(v[0]);
			swap(v[0], *min_element(v.begin() + 1, v.end(), ccwSorter(v[0])));
		} while (v[0].x != hull[0].x && v[0].y != hull[0].y);

		return hull;
	}


	// The Graham scan algorithm for convex hull.
	// https://en.wikipedia.org/wiki/Graham_scan
	vector<point> GrahamScan(vector<point> v) {
		// Put our leftmost point at index 0
		swap(v[0], *min_element(v.begin(), v.end(), isLeftOf));

		// Sort the rest of the points in counter-clockwise order
		// from our leftmost point.
		sort(v.begin() + 1, v.end(), ccwSorter(v[0]));

		// Add our first three points to the hull.
		vector<point> hull;
		auto it = v.begin();
		hull.push_back(*it++);
		hull.push_back(*it++);
		hull.push_back(*it++);

		while (it != v.end()) {
			// Pop off any points that make a convex angle with *it
			while (ccw(*(hull.rbegin() + 1), *(hull.rbegin()), *it) >= 0) {
				hull.pop_back();
			}
			hull.push_back(*it++);
		}

		return hull;
	}


	// The monotone chain algorithm for convex hull.
	vector<point> monotoneChain(vector<point> v) {
		// Sort our points in lexicographic order.
		sort(v.begin(), v.end(), isLeftOf);

		// Find the lower half of the convex hull.
		vector<point> lower;
		for (auto it = v.begin(); it != v.end(); ++it) {
			// Pop off any points that make a convex angle with *it
			while (lower.size() >= 2 && ccw(*(lower.rbegin() + 1), *(lower.rbegin()), *it) >= 0) {
				lower.pop_back();
			}
			lower.push_back(*it);
		}

		// Find the upper half of the convex hull.
		vector<point> upper;
		for (auto it = v.rbegin(); it != v.rend(); ++it) {
			// Pop off any points that make a convex angle with *it
			while (upper.size() >= 2 && ccw(*(upper.rbegin() + 1), *(upper.rbegin()), *it) >= 0) {
				upper.pop_back();
			}
			upper.push_back(*it);
		}

		vector<point> hull;
		hull.insert(hull.end(), lower.begin(), lower.end());
		// Both hulls include both endpoints, so leave them out when we 
		// append the upper hull.
		hull.insert(hull.end(), upper.begin() + 1, upper.end() - 1);
		return hull;
	}


	// Recursive call of the quickhull algorithm.
	void quickHull(const vector<point>& v, const point& a, const point& b,
		vector<point>& hull) {
		if (v.empty()) {
			return;
		}

		point f = v[getFarthest(a, b, v)];

		// Collect points to the left of segment (a, f)
		vector<point> left;
		for (auto p : v) {
			if (ccw(a, f, p) > 0) {
				left.push_back(p);
			}
		}
		quickHull(left, a, f, hull);

		// Add f to the hull
		hull.push_back(f);

		// Collect points to the left of segment (f, b)
		vector<point> right;
		for (auto p : v) {
			if (ccw(f, b, p) > 0) {
				right.push_back(p);
			}
		}
		quickHull(right, f, b, hull);
	}

	// QuickHull algorithm. 
	// https://en.wikipedia.org/wiki/QuickHull
	vector<point> quickHull(const vector<point>& v) {
		vector<point> hull;

		// Start with the leftmost and rightmost points.
		point a = *min_element(v.begin(), v.end(), isLeftOf);
		point b = *max_element(v.begin(), v.end(), isLeftOf);

		// Split the points on either side of segment (a, b)
		vector<point> left, right;
		for (auto p : v) {
			ccw(a, b, p) > 0 ? left.push_back(p) : right.push_back(p);
		}

		// Be careful to add points to the hull
		// in the correct order. Add our leftmost point.
		hull.push_back(a);

		// Add hull points from the left (top)
		quickHull(left, a, b, hull);

		// Add our rightmost point
		hull.push_back(b);

		// Add hull points from the right (bottom)
		quickHull(right, b, a, hull);

		return hull;
	}

	vector<point> getPoints() {
		vector<point> v;
		std::default_random_engine e(std::random_device{}());
		std::uniform_real_distribution<double> dist_x(0.05, 0.95);
		std::uniform_real_distribution<double> dist_y(0.05, 0.95);


		for (int i = 0; i < 30; ++i) {
			v.push_back(point(dist_x(e), dist_y(e)));
		}

		return v;
	}
}

可视化实现

这个exe小程序我放在主页了,大家可以免费下载,之后会创建一个仓库把代码公开出来,大家就可以在我的基础上实现更多的几何算法。
请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LibreOffice的国内镜像安装地址和node.js国内快速下载网站

文章目录 1、LibreOffice1.1、LibreOffice在application-conf.yml中的配置2、node.js 1、LibreOffice 国内镜像包网址&#xff1a;https://mirrors.cloud.tencent.com/libreoffice/libreoffice/ 1.1、LibreOffice在application-conf.yml中的配置 jodconverter:local:enable…

平安消保在行动 | 守护每一个舒心笑容 不负每一场双向奔赴

“要时刻记得以消费者为中心&#xff0c;把他们当做自己的朋友&#xff0c;站在他们的角度去思考才能更好地解决问题。” 谈及如何成为一名合格的消费者权益维护工作人员&#xff0c;平安养老险深圳分公司负责咨诉工作的庞宏霄认为&#xff0c;除了要具备扎实的专业技能和沟通…

安全及应用(更新)

一、账号安全 1.1系统帐号清理 #查看/sbin/nologin结尾的文件并统计 [rootrootlocalhost ~]# grep /sbin/nologin$ /etc/passwd |wc -l 40#查看apache登录的shell [rootrootlocalhost ~]# grep apache /etc/passwd apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin#改变…

const 修饰不同内容区分

1.修饰局部变量 const int a 1;int const a 1; 这两种是一样的 注意&#xff1a; const int b; 该情况下编译器会报错&#xff1a;常量变量"b”需要初始值设定项 将一个变量没有赋初始值直接const修饰后&#xff0c;在以后时无法更改内容的。 2.修饰常量字符串 a.…

算法题:用JS实现删除链表的倒数第N个节点

学习目标&#xff1a; 删除链表的倒数第N个节点 leetcode原题链接 学习内容&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点 示例 1: 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例 2: 输入&a…

基于YOLOv9的线路绝缘子缺陷检测【python源码+UI界面+数据集+模型+语音报警+安装说明】

往期精品导航 基于YOLOv9的脑肿瘤区域检测智慧课堂基于YOLOv8的学生上课行为检测基于YOLOv9pyside的安检仪x光危险物物品检测&#xff08;有ui&#xff09;基于YOLOv9的PCB板缺陷检测 前言 高压输电线绝缘子是电力输送系统中关键的组成部分&#xff0c;负责防止电流泄露&…

Trinity:转录组从头组装

安装 #下载安装包 wget -c https://github.com/trinityrnaseq/trinityrnaseq/releases/download/Trinity-v2.15.1/trinityrnaseq-v2.15.1.FULL.tar.gztar -xzvf trinityrnaseq-v2.15.1.FULL.tar.gz cd trinityrnaseq-v2.15.1 make make plugins #安装依赖 mamba install -c bio…

收银系统源码-次卡功能

智慧新零售收银系统是一套线下线上一体化收银系统&#xff0c;给门店提供了含线下收银称重、线上商城、精细化会员管理、ERP进销存、营销活动、移动店务助手等一体化行业解决方案&#xff01; 详细功能见下文&#xff1a; 门店收银系统源码-CSDN博客文章浏览阅读2.6k次&#…

SDK环境的安装(测试使用)

1、安装 将文件解压至目录,我的目录为:D:\Program Files\Android 解压后如下: 下载链接如下: sdk下载 提取码见文章最后: 2、配置环境 1、在环境变量中,选择系统变量,点击新建。 变量名:ANDROID_HOME 变量值:“你自己的android-sdk安装路径” (例如我的:D:\Pro…

大语言模型的应用探索AI Agent初探!

前言 大语言模型的应用之一是与大语言模型进行聊天也就是一个ChatBot&#xff0c;这个应用已经很广泛了。 接下来的一个应用就是AI Agent。 AI Agent是人工智能代理&#xff08;Artificial Intelligence Agent&#xff09;的概念&#xff0c;它是一种能够感知环境、进行决策…

算法训练营day26--455.分发饼干+376. 摆动序列+53. 最大子序和

一、455.分发饼干 题目链接&#xff1a;https://leetcode.cn/problems/assign-cookies/ 文章讲解&#xff1a;https://www.programmercarl.com/0455.%E5%88%86%E5%8F%91%E9%A5%BC%E5%B9%B2.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1MM411b7cq 1.1 初见思…

如何优化 PostgreSQL 中对于自关联表的查询?

文章目录 一、理解自关联表查询二、分析性能问题的可能原因&#xff08;一&#xff09;缺少合适的索引&#xff08;二&#xff09;大量数据的笛卡尔积&#xff08;三&#xff09;复杂的查询逻辑 三、优化策略及解决方案&#xff08;一&#xff09;创建合适的索引&#xff08;二…

史上最经典大型主机

注&#xff1a;本文资料有点老&#xff0c;但用来快速了解 IBM 大型机演进还不错。 1、大型机不为人知的秘密 自从发明计算机以来&#xff0c;人类的信息化历史进程得以加速推进。如果将全球各地的 PC 比大树上的枝繁叶茂&#xff0c;点缀一方沃土摇曳一股清风&#xff1b;那…

Servlet与Servlet容器

什么是Servlet? Servlet是Java EE&#xff08;现称Jakarta EE&#xff09;中的一个组件&#xff0c;通常用于创建动态Web内容。Servlet是运行在Web服务器上的Java程序&#xff0c;它处理客户端的请求并生成响应。Servlet的核心功能是处理HTTP请求和响应。下面是一个servlet例…

AIGC时代程序员的跃迁——编程高手的密码武器

大家好&#xff0c;我是herosunly。985院校硕士毕业&#xff0c;现担任算法研究员一职&#xff0c;热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名&#xff0c;CCF比赛第二名&#xff0c;科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

《初级C++》(一)

初级C&#xff08;一&#xff09; 1: C参考⽂档2&#xff1a;C创建与实现创建C的第一套程序命名空间的理解空间命名的实现C输⼊&输出缺省参数 1: C参考⽂档 https://legacy.cplusplus.com/reference/ 《非官方》 https://zh.cppreference.com/w/cpp 《官方中文版》 https:/…

学java的第3天 后端商城小程序工作

1.数据库的大坑 特殊字段名 ’我的图片表中有一个字段是描述我写成desc了&#xff0c;正好是mysql中的关键字 就不能使用了 2.后端编写 2.1可以把请求分开 在商品浏览页中 只显示商品的大致信息 当用户再点击其他按钮时在发出请求 2.2把请求合并 把数据整合到一起 利用ass…

Git秘籍大公开:从基础概念到高级技巧的全面解析

文章目录 前言一、Git基础介绍1. 作用2. 为什么要进行源代码管理?3. Git的诞生4. Git管理源代码特点5. Git操作流程图解 二、工作区暂存区和仓库区介绍1. 工作区2. 暂存区3. 仓库区 三、Git单人本地仓库操作1. 安装git2. 查看git安装结果3. 创建项目4. 创建本地仓库5. 配置个人…

前端JS特效第24集:jquery css3实现瀑布流照片墙特效

jquery css3实现瀑布流照片墙特效&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下(全部代码在文章末尾)&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8" /> <title>jquerycss3实现瀑…

一文彻底带你搞懂什么是适配器模式!!

一文彻底带你搞懂什么是适配器模式&#xff01;&#xff01; 什么是适配器模式&#xff1f;适配器的两种实现方式适用情况代码示例背景类适配器对象适配器 IO流中的实际应用应用扩展 总结 什么是适配器模式&#xff1f; 适配器模式&#xff08;Adapter Pattern&#xff09;是作…