C# | 凸包算法之Jarvis,寻找一组点的边界/轮廓

C#实现凸包算法之Jarvis
文章目录
- C#实现凸包算法之Jarvis
- 前言
- 示例代码
- 实现思路
- 测试结果
- 结束语
前言
这篇关于凸包算法的文章,本文使用C#和Jarvis算法来实现凸包算法。
首先消除两个最基本的问题:
- 什么是凸包呢?
凸包是一个包围一组点的凸多边形。凸多边形是指多边形中的每个内角都小于180度的多边形。 - 凸包算法有什么用呢?
凸包算法的作用是找到这个凸多边形,并且使用最少的点来绘制出它的轮廓。凸包算法在计算机图形学、计算几何和机器学习等领域中有着广泛的应用。
示例代码
现在来看一下C#中的Jarvis算法是如何实现凸包算法的:
/// <summary>/// 通过Jarvis算法获取围绕所有点的凸多边形的轮廓点<br/>/// </summary>/// <param name="points">点数组</param>/// <returns>轮廓点数组</returns>public static PointD[] GetConvexHullByJarvis(PointD[] points){if (points.Length < 3){throw new ArgumentException("凸包算法需要至少3个点");}List<PointD> pointList = new List<PointD>(points);// 找到最左边的点PointD leftmostPoint = pointList[0];for (int i = 1; i < pointList.Count; i++){if (pointList[i].X < leftmostPoint.X){leftmostPoint = pointList[i];}}// 使用栈来存储凸包的点Stack<PointD> hull = new Stack<PointD>();PointD currentPoint = leftmostPoint;do{hull.Push(currentPoint);PointD endpoint = pointList[0];for (int i = 1; i < pointList.Count; i++){if (endpoint.Equals(currentPoint) || Cross(currentPoint, endpoint, pointList[i]) < 0){endpoint = pointList[i];}}currentPoint = endpoint;pointList.Remove(currentPoint);} while (!currentPoint.Equals(leftmostPoint));return hull.ToArray();}
上面代码中定义了一个名为GetConvexHullByJarvis的静态方法,该方法接受一个PointD类型的数组作为输入参数,并返回一个PointD类型的数组,表示围绕所有点的凸多边形的轮廓点。
补充一下,关于示例中使用到的Cross方法和PointD类型的源代码如下:
/// <summary>/// 计算从 a 到 b 再到 c 的叉积/// </summary>/// <returns>叉积值</returns>private static double Cross(PointD a, PointD b, PointD c){return (b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X);}
public struct PointD {public PointD(double x, double y) {X = x;Y = y;}public double X { get; set; }public double Y { get; set; }public override bool Equals(object obj){if (obj == null || GetType() != obj.GetType()){return false;}PointD other = (PointD)obj;return X.Equals(other.X) && Y.Equals(other.Y);}}
实现思路
- 找到最左边的点,将它放入凸包中;
- 找到在当前点的右侧且离当前点最远的点,将它放入凸包中;
- 重复这个过程,直到回到最左边的点,形成一个闭合的凸多边形。
这就是 Jarvis 算法的基本思路。
需要注意的是,当点集中存在大量共线的点时,Jarvis 算法的时间复杂度可能会退化到 O(n^2) 级别,因为需要不断地扫描点集中的点来找到下一个点。此外当点集中存在大量重复的点时,Jarvis 算法可能会陷入死循环,因此需要对点集进行去重操作。
测试结果
用于测试的数据点:
static PointD[] points = new PointD[]{ new PointD(0, 0),new PointD(0, 10),new PointD(10, 10),new PointD(10, 0),new PointD(1, 0),new PointD(4, 3),new PointD(5, 2),new PointD(6, 5),new PointD(4, 9),new PointD(4, 2),new PointD(5, 1),new PointD(6, 5),new PointD(1, 3),new PointD(7, 2),new PointD(8, 2),new PointD(6, 7),new PointD(8, 5),new PointD(9, 3),new PointD(7, 8),new PointD(8, 9),};
测试代码如下:
[TestMethod]public void GetConvexHullByJarvis(){Console.WriteLine("Jarvis 算法");PrintPoints(ConvexHull.GetConvexHullByJarvis(points));}private void PrintPoints(PointD[] points){Console.WriteLine(points.Select(p => $" ({p.X}, {p.Y})").Join("\r\n"));}
执行结果如下:

结束语
通过本章的代码可以轻松实现Jarvis算法并找到一组点最外侧的凸多边形。如果您觉得本文对您有所帮助,请不要吝啬您的点赞和评论,提供宝贵的反馈和建议,让更多的读者受益。
相关文章:
C# | 凸包算法之Jarvis,寻找一组点的边界/轮廓
C#实现凸包算法之Jarvis 文章目录 C#实现凸包算法之Jarvis前言示例代码实现思路测试结果结束语 前言 这篇关于凸包算法的文章,本文使用C#和Jarvis算法来实现凸包算法。 首先消除两个最基本的问题: 什么是凸包呢? 凸包是一个包围一组点的凸多…...
SpringBoot接收请求参数的方式
【方式一】原始方式 因为SpringBoot封装了Servlet,所以也允许使用HttpServletRequest类中的方法来获取 /*** 【方式一】原始方式*/RequestMapping("/demo01")public String demo01(HttpServletRequest request) {// 参数名要与页面提交的参数名一致Strin…...
MKS SERVO4257D 闭环步进电机_系列5 CAN指令说明
第1部分 产品介绍 MKS SERVO 28D/35D/42D/57D 系列闭环步进电机是创客基地为满足市场需求而自主研发的一款产品。具备脉冲接口和RS485/CAN串行接口,支持MODBUS-RTU通讯协议,内置高效FOC矢量算法,采用高精度编码器,通过位置反馈&am…...
安捷伦E4440A(Agilent) e4440a 3HZ-26.5G频谱分析仪
Agilent E4440A、Keysight E4440A、HP E4440A频谱分析仪,3 Hz - 26.5 GHz(PSA 系列) Agilent / Keysight PSA 系列 E4440A 高性能频谱分析仪提供强大的一键式测量、多功能功能集和前沿技术,可满足您的项目和需求。选项可供您选…...
华为OD机试真题 Java 实现【最长子字符串的长度】【2022Q4 100分】,附详细解题思路
一、题目描述 给你一个字符串s,字符串s首尾相连组成一个环形,请你在环形中找出‘o’字符出现了偶数次最长子字符串的长度。 二、输入描述 输入一串小写字母组成的字符串。 三、输出描述 输出一个整数。 四、解题思路 题目要求在给定的环形字符串中找出字符’o’出现了…...
【iOS】--对象的底层结构
源码 先转一下源码 //#import <Foundation/Foundation.h> #import <objc/runtime.h>interface LGPerson : NSObject property (nonatomic, strong) NSString *KCName; endimplementation LGPersonendint main(int argc, const char * argv[]) {autoreleasepool {…...
高并发内存池设计_内存池
高并发内存池设计 1. 常用的内存操作函数2. 高性能内存池设计_弊端解决之道弊端一弊端二弊端三弊端四3. 弊端解决之道内存管理维度分析内存管理组件选型4. 高并发内存管理最佳实践内存池技术内存池如何解决弊端?高并发时内存池如何实现?5. 高效内存池设计和实现实现思路 (分而…...
给编程初学者的一封信
提醒:以下内容仅做参考,具体请自行设计。 随着信息技术的快速发展,编程已经成为一个越来越重要的技能。那么,我们该如何入门编程呢?欢迎大家积极讨论 一、自学编程需要注意什么? 要有足够的时间、精力等…...
【无功优化】基于改进教与学算法的配电网无功优化【IEEE33节点】(Matlab代码时候)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
数据在内存中的存储(超详细讲解)
目录 浮点数家族 浮点数类型在内存中的存储 一.为什么说整型和浮点数在内存中存储方式不同(证明) 二.浮点数的存储规则 浮点数在计算机内部的表示方法 1.对于M的存储和取出规则 2.对于E的存储和取出时的规则 对前面代码结果进行解释: …...
log4cplus使用示例
1、l4jlog.h封装头文件 #pragma once#include <iostream> #include <log4cplus/logger.h> #include <log4cplus/loggingmacros.h> #include <log4cplus/fileappender.h> #include <log4cplus/layout.h> #include <log4cplus/configurator.h&…...
人工智能学习07--pytorch20--目标检测:COCO数据集介绍+pycocotools简单使用
如:天空 coco包含pascal voc 的所有类别,并且对每个类别的标注目标个数也比pascal voc的多。 一般使用coco数据集预训练好的权重来迁移学习。 如果仅仅针对目标检测object80类而言,有些图片并没有标注信息,或者有错误标注信息。…...
learnOpenGL-深度测试
深度测试:OpenGL将一个片段的深度值与深度缓冲的内容进行对比。执行一个深度测试,测试通过则深度缓冲将会更新为新的深度值。测试失败则片段被丢弃。 深度测试片段着色器及模版测试之后执行。 片段着色器中内置变量gl_FragCoord的z值即为深度值。 提前深…...
阿里云服务器数据盘是什么?系统盘和数据盘区别
阿里云服务器系统盘和数据盘有什么区别?系统盘类似Windows电脑的C盘,数据盘相当于其他盘符,数据盘可以有多个而系统盘只能有一个,数据盘可有可无而云服务器系统盘是必须要有的。阿里云服务器网来详细说下阿里云服务器数据盘和系统…...
linux常用命令精选
参考文章: Top 60 Linux Interview Questions and Answers - howtouselinux 在管理和维护Linux系统时,有一些常用的命令可以帮助您进行系统初始化和配置。这些命令涵盖了各种任务,包括系统设置、用户管理、软件安装和网络配置等。 本文将为…...
人体行为足力特征分析及其应用研究_kaic
第一章 绪论 随着社会现代化的发展和科技的不断进步,我国航天事业蓬勃发展,与此同时产生了很多亟待解决的难题,康复医疗成为航天医学和康复领域的重要课题之一。载人航天实践证明,失重对航天员生理功能有很大影响,这不…...
javascript基础二十七:说说 JavaScript 数字精度丢失的问题,解决方案?
一、场景复现 一个经典的面试题 0.1 0.2 0.3 // false 为什么是false呢? 先看下面这个比喻 比如一个数 130.33333333… 这是一个除不尽的运算,3会一直无限循环,数学可以表示,但是计算机要存储,方便下次再使用,但…...
重塑工作场所:后疫情时代组织韧性的8个策略
经济寒冬来临,倒挂的收益率曲线、持续上升的利率以及层出不穷的裁员公告等等,让经济学家们得出一个结论:全球经济正在衰退。然而,经济下行周期可能是卓越公司改变其命运的最佳时机。有研究表明,相对于非经济衰退时期&a…...
TCP协议为什么要三次握手而不是两次?
TCP(Transmission Control Protocol,传输控制协议)的历史可以追溯到1970年代初期,最初的版本是RFC 793,后来经过多次更新和改进,包括RFC 1122、RFC 1323、RFC 2018、RFC 2581、RFC 2873、RFC 3168和RFC 461…...
使用Vuex进行状态管理
在Vue.js应用程序中,状态管理是一个重要的主题。当应用程序变得复杂,组件之间的状态共享和通信变得困难,这时候使用Vuex就会变得十分有用。Vuex是一个专门为Vue.js设计的状态管理库,它提供了一个集中式的状态管理方案,…...
QQ空间说说备份终极指南:GetQzonehistory完整教程
QQ空间说说备份终极指南:GetQzonehistory完整教程 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾经想要永久保存QQ空间里那些珍贵的青春回忆?那些承载着…...
VMware虚拟机创建详细教程(新手小白友好)
本教程以 VMware Workstation Pro 16/17 版本为例,演示如何创建一台新的虚拟机。第一步:启动新建虚拟机向导打开VMware Workstation,点击主界面上的 “创建新的虚拟机”,或依次点击菜单栏“文件” → “新建虚拟机”。图1 VMware创…...
(十)工业数据采集与断点续传
一、 工业物联网的致命伤:不稳定的网络环境在实验室或 IT 监控中,网络往往是稳定可靠的。但在工业现场,车间大型电机的电磁干扰、行车移动对光纤的拉扯、以及跨地域厂区的无线网络波动,会导致设备频繁出现“微离线”甚至长达数小时…...
暗黑破坏神2存档编辑器完整指南:三步轻松修改D2/D2R角色与装备
暗黑破坏神2存档编辑器完整指南:三步轻松修改D2/D2R角色与装备 【免费下载链接】d2s-editor 项目地址: https://gitcode.com/gh_mirrors/d2/d2s-editor 你是否厌倦了在暗黑破坏神2中反复刷装备却一无所获?是否因为早期加点失误导致角色后期无法应…...
铜钟音乐:在信息洪流中找回纯粹听歌体验的现代Web应用
铜钟音乐:在信息洪流中找回纯粹听歌体验的现代Web应用 【免费下载链接】tonzhon-music 铜钟 Tonzhon (tonzhon.whamon.com): 干净纯粹的音乐平台 (铜钟已不再使用 tonzhon.com,现在的 tonzhon.com 不是正版的铜钟) 项目地址: https://gitcode.com/GitH…...
libigl 极小曲面(全局优化之二)
文章目录 一、简介 二、实现代码 三、实现效果 参考资料 一、简介 二、实现代码 #include <numeric>//igl #include <igl/readPLY.h>...
机器学习博士生存指南:问题定义、三维技术栈与认知带宽管理
1. 这不是“读博指南”,而是一份机器学习方向博士生的生存手记 我带过7届硕士、指导过4位博士,自己也从MIT CSAIL实验室的PhD candidate一路走到现在,在工业界和学术界都完整跑过ML方向的闭环——从ICML投稿被拒5次到最终以共同作者身份参与N…...
快速开发AI客服原型时如何利用Taotoken分钟级接入多模型
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 快速开发AI客服原型时如何利用Taotoken分钟级接入多模型 在探索和构建AI客服原型时,开发者常常面临一个核心矛盾&#…...
C++ 左右值引用 完全详解(从入门到精通)
左右值引用是 C11 引入的最核心、影响最深远的特性,它直接催生了移动语义、完美转发、智能指针优化等现代 C 的基石。本文从最基础的定义开始,逐层深入到所有高级特性和常见陷阱,看完就能解决 99% 的面试和开发问题。一、先彻底搞懂ÿ…...
如何用Autolabel在5分钟内完成数据标注:面向新手的终极实战指南
如何用Autolabel在5分钟内完成数据标注:面向新手的终极实战指南 【免费下载链接】autolabel Label, clean and enrich text datasets with LLMs. 项目地址: https://gitcode.com/gh_mirrors/au/autolabel 还在为数据标注发愁吗?🤔 传统…...
