Unity 算法 之 点集中计算绘制 凸包 的简单整理

news2024/9/22 13:37:17

Unity 算法 之 点集中计算绘制 凸包 的简单整理

目录

Unity 算法 之 点集中计算绘制 凸包 的简单整理

一、简单介绍

二、Graham扫描法

第一种说明:

第二种说明:

三、代码(第二种说明)

 四、参考文献


一、简单介绍

算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。

凸包(Convex Hull)是一个计算几何(图形学)中的概念。

 

在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。

X的凸包可以用X内所有点(X1,...Xn)的线性组合来构造.

在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。

用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点。

凸包:在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集被称为X的凸包。

给定一组离散的点,求得包围整个离散点的边的集合。
例如,在墙上随机定了N个钉子,然后用一个足够大的橡皮筋包围这些钉子,那么松开橡皮筋之后,橡皮筋的范围就是凸包。

那么凸包的算法,就是输入一组离散点,返回能够组成凸包的点,将这些点连接起来就是凸包了。
常用的凸包算法是Graham扫描法,和Jarvis步进法 

二、Graham扫描法

时间复杂度:O(n㏒n) 
思路:Graham扫描的思想是先找到凸包上的一个点,然后从那个点开始按逆时针方向逐个找凸包上的点,实际上就是进行极角排序,然后对其查询使用。 

第一种说明:

1、把所有点放在二维坐标系中,则纵坐标最小的点一定是凸包上的点,如图中的P0。

2、把所有点的坐标平移一下,使 P0 作为原点,如上图。

3、计算各个点相对于 P0 的幅角 α ,按从小到大的顺序对各个点排序。当 α 相同时,距离 P0 比较近的排在前面。例如上图得到的结果为 P1,P2,P3,P4,P5,P6,P7,P8。我们由几何知识可以知道,结果中第一个点 P1 和最后一个点 P8 一定是凸包上的点。
(以上是准备步骤,以下开始求凸包)
以上,我们已经知道了凸包上的第一个点 P0 和第二个点 P1,我们把它们放在栈里面。现在从步骤3求得的那个结果里,把 P1 后面的那个点拿出来做当前点,即 P2 。接下来开始找第三个点:

4、连接P0和栈顶的那个点,得到直线 L 。看当前点是在直线 L 的右边还是左边。如果在直线的右边就执行步骤5;如果在直线上,或者在直线的左边就执行步骤6。

5、如果在右边,则栈顶的那个元素不是凸包上的点,把栈顶元素出栈。执行步骤4。

6、当前点是凸包上的点,把它压入栈,执行步骤7。

7、检查当前的点 P2 是不是步骤3那个结果的最后一个元素。是最后一个元素的话就结束。如果不是的话就把 P2 后面那个点做当前点,返回步骤4。

 

第二种说明:

1、从离散点集合S中获取一个y轴最小,x轴最小的点 P0。(如果最小y轴有多个点,就取x轴最小的点)

2、计算S中其他的点到P0点的极角,并按照从小到大的顺序进行排序的到集合S1(极角相同,取距离最段的排在前),通过排序后可以确定PO点和排序后集合S1 中的第一个点P1点是凸包点,加入凸包列表中。

3、从S1中取得下一个点(P2),计算P2点位于线段(P0,01)的左边还是右边。

4、如果是左边,将P2点加入凸包点队列,如果右边,移除上一次加入的点(P1),重新计算P1点与集合中线段的位置关系(这里移除P1后,列表里只有一个,那就直接加入)

5、重复3到4步骤,知道S1中没有点为止。

 

三、代码(第二种说明)

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class GrahamScan : MonoBehaviour {
    //离散的点
    public Transform[] Points;
    //组成边的顶点集合
    public List<Transform> ePoint = new List<Transform>();

    private bool IsFinsh = false;
    void Start()
    {
        Aritmetic();
    }

    //算法
    void Aritmetic()
    {
        Transform bp = BasePoint();
        bp.name = "P0";
        ePoint.Add(bp);
        Transform[] polarSort = PolarSort(bp);
        for (int i = 0; i < polarSort.Length; i++)
        {
            if (polarSort[i] == bp) continue;
            polarSort[i].name = "P" + (i + 1);
        }
        //通过排序,而可以得知 第一个点肯定在凸边上
        ePoint.Add(polarSort[0]);
        StartCoroutine(Ia(polarSort));
    }

    IEnumerator Ia(Transform[] polarSort)
    {
        for (int i = 1; i < polarSort.Length; i++)
        {
            yield return new WaitForSeconds(1);
            ePoint.Add(polarSort[i]);
            float d = PointDir(ePoint[ePoint.Count-1].position, ePoint[ePoint.Count - 2].position, ePoint[ePoint.Count - 3].position);
            if (d <= 0)
                continue;
            while (true)
            {
                yield return new WaitForSeconds(1);
                ePoint.RemoveAt(ePoint.Count-2);
                d = PointDir(ePoint[ePoint.Count - 1].position, ePoint[ePoint.Count - 2].position, ePoint[ePoint.Count - 3].position);
                if (d < 0)
                    break;
            }
        }
        IsFinsh = true;
    }

    void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        if (!IsFinsh)
        {
            for (int i = 0; i < ePoint.Count - 1; i++)
                Gizmos.DrawLine(ePoint[i].position, ePoint[i + 1].position);
            return;
        }

        for (int i = 0; i < ePoint.Count; i++)
        {
            if (i == ePoint.Count - 1)
            {
                Gizmos.DrawLine(ePoint[i].position,ePoint[0].position);
                continue;
            }
            Gizmos.DrawLine(ePoint[i].position,ePoint[i+1].position);
        }

    }

    /// <summary>
    /// 获取基点P0
    /// </summary>
    /// <returns></returns>
    Transform BasePoint()
    {
        //取y值最小 如果多个y值相等,去x最小(这里y 我们取z)
        Transform minPoint = Points[0];
        for (int i = 1; i < Points.Length; i++)
        {
            if (Points[i].position.z < minPoint.position.z)
                minPoint = Points[i];
            else if (Points[i].position.z < minPoint.position.z)
                minPoint = Points[i].position.x < minPoint.position.x ? Points[i] : minPoint;
        }
        return minPoint;
    }
    /// <summary>
    /// 获取点的方向 =0 在线上 <0在左侧 >0在右侧
    /// </summary>
    /// <param name="p"></param>
    /// <param name="p1"></param>
    /// <param name="p2"></param>
    /// <returns></returns>
    float PointDir(Vector3 p, Vector3 p1, Vector3 p2)
    {
        Vector3 v1 = p1 - p;
        Vector3 v2 = p2 - p1;
        float f = v1.x * v2.z - v2.x * v1.z;
        return f;
    }

    /// <summary>
    /// 极角排序
    /// </summary>
    /// <param name="bp"></param>
    /// <returns></returns>
    Transform[] PolarSort(Transform bp)
    {
        List<Transform> p = new List<Transform>();
        for (int i = 0; i < Points.Length; i++)
        {
            //如果是自己,则跳过
            if (Points[i] == bp) continue;
            Vector3 v = Vector3.zero;
            float e = GetProlar(Points[i], bp,out v);
            int index = -1;
            for (int j = 0; j < p.Count; j++)
            {
                Vector3 v1 = Vector3.zero;
                float e1 = GetProlar(p[j],bp,out v1);
                if (e1 > e)
                {
                    index = j;
                    break;
                }
                if (e1 == e && v.magnitude < v1.magnitude)
                {
                    index = j;
                    break;
                }
            }
            if (index == -1)
            {
                p.Add(Points[i]);
                continue;
            }
            p.Insert(index,Points[i]);
        }
        return p.ToArray();
    }
    /// <summary>
    /// 获取极角
    /// </summary>
    /// <param name="pos1"></param>
    /// <param name="pos2"></param>
    /// <returns></returns>
    float GetProlar(Transform pos1, Transform pos2,out Vector3 v)
    {
        v = pos1.position - pos2.position;
        return Mathf.Atan2(v.z,v.x);
    }

}

 四、参考文献

1、凸包算法详解(convex hull)

2、计算机几何 - 凸包

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

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

相关文章

工作上的三个境界:能做,能做好,能持续做好

某天&#xff0c;技术岗A员工抬杠管理岗B员工的工作&#xff1a;你的工作啊&#xff0c;实习生都能做&#xff0c;你的价值太小了........一顿DISS。 这样的场景&#xff0c;似曾相识否&#xff1f;这是职场中常见的一类人“杠精”的表现。 做技术的&#xff0c;往往认为管理…

MySQL8.0 OCP最新版1Z0-908认证考试题库整理-006

原题 Choose the best answer.You are having performance issues with MySQL instances. Those servers are monitored withMySQL Enterprise Monitor.Using Query Analyzer, where do you begin to look for problem queries?A) Sort the "Exec" column and check…

什么是物联网?如何保护物联网iot安全性

物联网iot:物联网&#xff08;IoT&#xff09;将生活中事物以网络进行连接&#xff0c;彼此交换信息。整个世界借由设备连接成一体。 对于消费者而言&#xff0c;这意味着您可以在大洋彼岸远程调节家中的恒温器。但是对企业而言&#xff0c;物联网不仅创造了连接客户和合作伙伴…

BBR 公平收敛

BBR 的公平收敛来自于两点&#xff1a; ProbeBW 状态加速比收敛&#xff1a;带宽越大&#xff0c;加速比越小。ProbeRTT 状态 RTT 收敛&#xff1a;inflight 越大&#xff0c;越容易让 inflight 小的测到 minrtt 而避免进入 ProbeRTT&#xff0c;inflight 越小&#xff0c;测量…

用Python代码自己写Python代码,竟如此简单

用Python代码自己写Python代码&#xff0c;竟如此简单 Python作为一门功能强大且使用灵活的编程语言&#xff0c;可以应用于各种领域&#xff0c;具有“无所不能”的特质。 Python甚至可以代替人&#xff0c;自己写Python代码。而且很简单&#xff0c;只需学会Python的基础知…

RabbitMQ学习笔记

目录 尚硅谷mq视频学习笔记 1.1. MQ 的相关概念 1.1.1. 什么是MQ 1.1.2. 为什么要用MQ 1.1.3. MQ 的分类 1.ActiveMQ 2.Kafka 3.RocketMQ 4.RabbitMQ 1.1.4. MQ 的选择 1.Kafka 2.RocketMQ 3.RabbitMQ 1.2. RabbitMQ 1.2.1. RabbitMQ 的概念 1.2.2. 四大核心概念…

7.7网络(二)

接上篇&#xff1a;7.7 网络&#xff08;一&#xff09;_龙赤子的博客-CSDN博客 目录 三 操作系统涉及的网络内容 1 网络栈 2 协议 3 应用 三 操作系统涉及的网络内容 1 网络栈 这里我们重点讨论操作系统里面的网络。这部分在整个网络架构中&#xff0c;属于端的技术。对于端来…

分布式锁-全面详解(学习总结---从入门到深化)

目录 分布式锁概述 为什么需要分布式锁 什么是分布式锁 分布式锁的特点 分布式锁问题_业务介绍 案列介绍 技术选型 创建表 创建订单表 创建商品表 创建订单商品关联表 分布式锁问题_创建SpringBoot项目 引入依赖 修改配置文件 编写主启动类 代码生成 编写创建订单接…

(附源码)node.js电商管理系统 毕业设计 251001

node.js电商管理系统 摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;电商管理系统当然也不能排除在外。电商管理系统 是以实际运用为开发背景&#xff0c;运用软件工程开…

【数据结构与算法】拓扑排序与关键路径

&#x1f525; 本文由 程序喵正在路上 原创&#xff0c;CSDN首发&#xff01; &#x1f496; 系列专栏&#xff1a;数据结构与算法 &#x1f320; 首发时间&#xff1a;2022年12月4日 &#x1f98b; 欢迎关注&#x1f5b1;点赞&#x1f44d;收藏&#x1f31f;留言&#x1f43e;…

【C++智能指针】智能指针的发展和循环引用的原理和解决

目录 1.RAIl&#xff08;智能指针的雏形&#xff09; 2.拷贝导致的问题以及智能指针发展历史 2.1拷贝的问题&#xff08;资源被析构两次&#xff09; 2.2auto_ptr(资源权转移&#xff0c;不建议使用) 2.3unique_ptr(防拷贝&#xff0c;在不需要拷贝的情况下使用) 2.4share…

【vue】vue-count-to(数字滚动)插件:

文章目录一、效果&#xff1a;二、使用&#xff1a;【1】安装插件【2】案例三、Options四、Functions一、效果&#xff1a; 二、使用&#xff1a; 官方文档&#xff1a; github地址——https://github.com/PanJiaChen/vue-countTo npm地址——https://www.npmjs.com/package/…

在本地PC运行 Stable Diffusion 2.0

Stable Diffusion 2.0在前几天已经发布了&#xff0c;新版本在上一个版本的基础上进行了许多改进。OpenCLIP中新的深度检测和更好的文本到图像模型是主要的改进之一。 有很多的文章介绍了Stable Diffusion 2.0的改进&#xff0c;所以我们就不多介绍了&#xff0c;这里我们将介…

30分钟部署一个kubernetes集群【1.17】

作者:李振良 kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。 这个工具能通过两条指令完成一个kubernetes集群的部署: # 创建一个 Master 节点 $ kubeadm init# 将一个 Node 节点加入到当前集群中 $ kubeadm join <Master节点的IP和端口 >1. 安装要求…

.m3u8.sqlite文件转mp4,m3u8.sqlite文件转视频工具(开源免费)

文章目录一、预先准备1. 前提2. 主要思路3. 准备工具二、视频转换实战2.1. 软件下载2.2. TS转MP4工具2.3. 操作流程一、预先准备 1. 前提 如果已经买了课程&#xff0c;是可以下载的&#xff0c;并且腾讯课堂APP里就有下载功能。 2. 主要思路 在APP上下载视频缓存到手机本地…

postgres源码解析41 btree索引文件的创建--1

上述小节讲解了索引文件的物理创建&#xff0c;本篇讲解btree索引元组填充至索引文件的操作。先从数据结构入手&#xff0c;后深入执行流程。 postgres源码解析37 表创建执行全流程梳理–1 postgres源码解析37 表创建执行全流程梳理–2 postgres源码解析37 表创建执行全流程梳理…

详解设计模式:责任链模式

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;也被称为职责链模式&#xff0c;是在 GoF 23 种设计模式中定义了的行为型模式。 责任链模式 是将链中的每一个节点看作是一个对象&#xff0c;每个节点处理的请求不同&#xff0c;且内部自动维护一个下一节点…

降温了好冷,总结下11月

1、这两天广东气温骤降&#xff0c;出门必须加外套了&#xff0c;emmm&#xff0c;不想出门&#xff0c;各位宝宝注意保暖吖&#xff0c;别感冒了。2、这边疫情开始放开了&#xff0c;备好感冒药&#xff0c;锻炼身体&#xff0c;做好预防&#xff0c;靠自己了。3、11月过的真快…

jsp人事考勤管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 人事考勤管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用serlvetdaobean mvc 模式&#xff0c;系统主要采用B/S模式 开发。开发环境为TOMCAT7.0,Myeclipse8.…

[附源码]计算机毕业设计基于Springboot的花店售卖系统的设计与实现

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…