JavaScript 使用 Graham 扫描的凸包(Convex Hull using Graham Scan)

 先决条件:

如何检查两个给定的线段是否相交?

c++ https://blog.csdn.net/hefeng_aspnet/article/details/141713655
java https://blog.csdn.net/hefeng_aspnet/article/details/141713762
python https://blog.csdn.net/hefeng_aspnet/article/details/141714389
C# https://blog.csdn.net/hefeng_aspnet/article/details/141714420
Javascript https://blog.csdn.net/hefeng_aspnet/article/details/141714442 

贾维斯算法

 c++ https://blog.csdn.net/hefeng_aspnet/article/details/141716082
java https://blog.csdn.net/hefeng_aspnet/article/details/141716363
python https://blog.csdn.net/hefeng_aspnet/article/details/141716444
C# https://blog.csdn.net/hefeng_aspnet/article/details/141716403
Javascript https://blog.csdn.net/hefeng_aspnet/article/details/141716421 

        凸包是包含给定点集的最小凸多边形。它是计算几何学中一个有用的概念,在计算机图形学、图像处理和碰撞检测等各个领域都有应用。

凸多边形是所有内角都小于180度的多边形。可以为任意点集构造凸包,无论这些点如何排列。

格雷厄姆扫描算法:
        格雷厄姆扫描算法是一种简单而有效的算法,用于计算一组点的凸包。它的工作原理是迭代地将点添加到凸包中,直到所有点都添加完毕。

        该算法首先找到 y 坐标最小的点。该点始终位于凸包上。然后,该算法根据剩余点相对于起点的极角对它们进行排序。

        然后,算法会迭代地将点添加到凸包中。在每个步骤中,算法都会检查添加到凸包中的最后两个点是否形成右转。如果是,则将最后一个点从凸包中移除。否则,将排序列表中的下一个点添加到凸包中。

当所有点都被添加到凸包时,算法终止。

Graham Scan的实现:

第一阶段(排序点):
        实现格雷厄姆扫描算法的第一步是按照点相对于起点的极角对点进行排序。
        一旦点排序完毕,起点就会添加到凸包中。一旦点排序完毕,它们就会形成一条简单的闭合路径(见下图)。 

第二阶段(接受或拒绝点):

    一旦我们有了闭合路径,下一步就是遍历该路径并移除该路径上的凹点。如何决定移除哪个点以及保留哪个点?同样,方向在这里有帮助。排序数组中的前两个点始终是凸包的一部分。对于剩余的点,我们跟踪最近的三个点,并找到它们形成的角度。让这三个点分别为prev(p)、curr(c)和next(n)。如果这些点的方向(按相同顺序考虑它们)不是逆时针的,我们丢弃 c,否则我们保留它。下图显示了此阶段的分步过程。
 

下面是上述算法的实现:

// JavaScript program to find convex hull of a set of
// points. Refer

 //c++ C++ 3 个有序点的方向(Orientation of 3 ordered points)-CSDN博客
//java Java 3 个有序点的方向(Orientation of 3 ordered points)-CSDN博客
//python Python 3 个有序点的方向(Orientation of 3 ordered points)-CSDN博客
//C# C# 3 个有序点的方向(Orientation of 3 ordered points)-CSDN博客
//Javascript javascript 3 个有序点的方向(Orientation of 3 ordered points)-CSDN博客


// for explanation of orientation()

// A class used to store the x and y coordinates of points
class Point {
    constructor(x = null, y = null)
    {
        this.x = x;
        this.y = y;
    }
}

// A global point needed for sorting points with reference
// to the first point
let p0
    = new Point(0, 0);

// A utility function to find next to top in a stack
function nextToTop(S) { return S[S.length - 2]; }

// A utility function to return square of distance
// between p1 and p2
function distSq(p1, p2)
{
    return ((p1.x - p2.x) * (p1.x - p2.x)
            + (p1.y - p2.y) * (p1.y - p2.y));
}

// To find orientation of ordered triplet (p, q, r).
// The function returns following values
// 0 --> p, q and r are collinear
// 1 --> Clockwise
// 2 --> Counterclockwise
function orientation(p, q, r)
{
    let val = ((q.y - p.y) * (r.x - q.x)
               - (q.x - p.x) * (r.y - q.y));
    if (val == 0)
        return 0; // collinear
    else if (val > 0)
        return 1; // clock wise
    else
        return 2; // counterclock wise
}

// A function used by cmp_to_key function to sort an array
// of points with respect to the first point
function compare(p1, p2)
{

    // Find orientation
    let o = orientation(p0, p1, p2);
    if (o == 0) {
        if (distSq(p0, p2) >= distSq(p0, p1))
            return -1;
        else
            return 1;
    }
    else {
        if (o == 2)
            return -1;
        else
            return 1;
    }
}

// Prints convex hull of a set of n points.
function convexHull(points, n)
{
    // Find the bottommost point
    let ymin = points[0].y;
    let min = 0;
    for (var i = 1; i < n; i++) {
        let y = points[i].y;

        // Pick the bottom-most or choose the left
        // most point in case of tie
        if ((y < ymin)
            || ((ymin == y)
                && (points[i].x < points[min].x))) {
            ymin = points[i].y;
            min = i;
        }
    }

    // Place the bottom-most point at first position
    points[0], points[min] = points[min], points[0];

    // Sort n-1 points with respect to the first point.
    // A point p1 comes before p2 in sorted output if p2
    // has larger polar angle (in counterclockwise
    // direction) than p1
    let p0 = points[0];
    points.sort(compare);
    

    // If two or more points make same angle with p0,
    // Remove all but the one that is farthest from p0
    // Remember that, in above sorting, our criteria was
    // to keep the farthest point at the end when more than
    // one points have same angle.
    let m = 1; // Initialize size of modified array
    for (var i = 1; i < n; i++) {
        // Keep removing i while angle of i and i+1 is same
        // with respect to p0
        while ((i < n - 1)
               && (orientation(p0, points[i], points[i + 1])
                   == 0))
            i += 1;

        points[m] = points[i];
        m += 1; // Update size of modified array
    }

    // If modified array of points has less than 3 points,
    // convex hull is not possible
    if (m < 3)
        return;

    // Create an empty stack and push first three points
    // to it.
    let S = [];
    S.push(points[0]);
    S.push(points[1]);
    S.push(points[2]);

    // Process remaining n-3 points
    for (var i = 3; i < m; i++) {
        // Keep removing top while the angle formed by
        // points next-to-top, top, and points[i] makes
        // a non-left turn
        while (true) {
            if (S.length < 2)
                break;
            if (orientation(nextToTop(S), S[S.length - 1],
                            points[i])
                >= 2)
                break;
            S.pop();
        }

        S.push(points[i]);
    }

    // Now stack has the output points,
    // print contents of stack
    while (S.length > 0) {
        let p = S[S.length - 1];
        console.log("(" + p.x + ", " + p.y + ")");
        S.pop();
    }
}

// Driver Code
let points = [
    new Point(0, 3), new Point(1, 1), new Point(2, 2),
    new Point(4, 4), new Point(0, 0), new Point(1, 2),
    new Point(3, 1), new Point(3, 3)
];

let n = points.length;
convexHull(points, n);

// This code is contributed by phasing17

输出: 

(0,3)
(4,4)
(3,1)
(0,0)

时间复杂度: O(nLogn),其中 n 为输入点的数量。

    第一步(找到最底部的点)需要 O(n) 时间。第二步(对点进行排序)需要 O(nLogn) 时间。第三步需要 O(n) 时间。在第三步中,每个元素最多被推送和弹出一次。因此,第六步逐个处理点需要 O(n) 时间,假设堆栈操作需要 O(1) 时间。总体复杂度为 O(n) + O(nLogn) + O(n) + O(n),即 O(nLogn)。

辅助空间: O(n),因为使用了显式堆栈,所以没有占用额外的空间。

凸包的应用:

    凸包的应用范围很广,包括:

    碰撞检测:凸包可用于快速确定两个物体是否发生碰撞。这在计算机图形学和物理模拟中很有用。

    图像处理:凸包可用于分割图像中的对象。这对于诸如对象识别和跟踪之类的任务很有用。

    计算几何:凸包用于各种计算几何算法,例如查找最近的点对和计算一组点的直径。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能监控,守护绿色能源:EasyCVR在电站视频监控中心的一站式解决方案

随着科技的飞速发展&#xff0c;视频监控技术在社会安全、企业管理及智慧城市建设等领域中扮演着越来越重要的角色。特别是在电力行业中&#xff0c;电站作为能源供应的关键设施&#xff0c;其安全性和稳定性至关重要。传统的人工监控方式已难以满足现代电站复杂多变的运行需求…

基于SpringBoot+Vue+MySQL的甜品店管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 在数字化浪潮的推动下&#xff0c;甜品店行业也面临着转型与升级的需求。传统的线下经营模式已难以满足现代消费者对于便捷、高效购物体验的追求。为了提升运营效率、优化顾客体验&#xff0c;我们设计了一款基于SpringBoot后端…

Ubuntu 16.04安装填坑记录

一. 问题描述&#xff1a; &#xff08;1&#xff09;Ubuntu 16.04使用USB启动盘安装时&#xff0c;出现"try ubuntu without installation"或“install ubuntu”选择&#xff0c;Enter选择安装后&#xff0c;显示器黑屏无任何显示。 原因分析&#xff1a; 显示黑…

遥感图像变换检测实践上手(TensorRT+UNet)

目录 简介 分析PyTorch示例 onnx模型转engine 编写TensorRT推理代码 main.cpp测试代码 小结 简介 这里通过TensorRTUNet&#xff0c;在Linux下实现对遥感图像的变化检测&#xff0c;示例如下&#xff1a; 可以先拉去代码&#xff1a;RemoteChangeDetection 分析PyTorch示…

网络攻击DDOoS的原理、攻击手段及防范措施详解

一、DDoS的原理 1. 原理 DDoS&#xff08;分布式拒绝服务攻击&#xff09;是利用大量的僵尸主机对受害者发起攻击&#xff0c;从而造成受害者的资源被耗尽无法为合法用户提供服务。DDoS一般采用三级结构&#xff0c;包括&#xff1a; 攻击者&#xff1a;攻击指令的发起方僵尸…

【鸿蒙HarmonyOS NEXT】数据存储之分布式键值数据库

【鸿蒙HarmonyOS NEXT】数据存储之分布式键值数据库 一、环境说明二、分布式键值数据库介绍三、示例代码加以说明四、小结 一、环境说明 DevEco Studio 版本&#xff1a; API版本&#xff1a;以12为主 二、分布式键值数据库介绍 KVStore简介&#xff1a; 分布式键值数据库…

OpenHarmony(鸿蒙南向)——平台驱动指南【DAC】

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 概述 功能简介 DAC&#xff08;Digital to Analog Converter&…

Python办公自动化之Word

在现代办公环境中&#xff0c;自动化无疑是提升工作效率的关键。特别是处理文档的工作&#xff0c;很多人可能花费大量时间在重复性任务上。那么&#xff0c;有没有一种方法可以让我们用 Python 来自动化 Word 文档的操作呢&#xff1f;今天&#xff0c;我们来聊聊如何用 Pytho…

AI Agent应用出路到底在哪?

1 Agent/Function Call 的定义 Overview of a LLM-powered autonomous agent system&#xff1a; Agent学会调用外部应用程序接口&#xff0c;以获取模型权重中缺失的额外信息&#xff08;预训练后通常难以更改&#xff09;&#xff0c;包括当前信息、代码执行能力、专有信息源…

Docker安装与应用

前言 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言开发。Docker 可以让开发者打包他们的应用以及依赖包到一个轻 量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互 之间…

大语言模型之LlaMA系列- LlaMA 2及LLaMA2_chat(上)

LlaMA 2是一个经过预训练与微调的基于自回归的transformer的LLMs&#xff0c;参数从7B至70B。同期推出的Llama 2-Chat是Llama 2专门为对话领域微调的模型。 在许多开放的基准测试中Llama 2-Chat优于其他开源的聊天模型&#xff0c;此外Llama 2-Chat还做了可用性与安全性评估。 …

物联网系统中基于IIC通信的数字温度传感器测温方案

01 物联网系统中为什么要使用数字式温度传感器芯片 物联网系统中使用数字式温度传感器芯片的原因主要有以下几点&#xff1a; 高精度与稳定性 高精度测量&#xff1a;数字式温度传感器芯片&#xff0c;如DS18B20&#xff0c;采用芯片集成技术&#xff0c;能够有效抑制外界不…

2024-9-28 QT登录框基础练习

1.头文件 #ifndef LOGINWINDOW_H #define LOGINWINDOW_H#include <QWidget> #include <QPushButton> #include <QLineEdit> #include <QVBoxLayout>class LoginWindow : public QWidget {Q_OBJECTpublic:// 构造函数LoginWindow(QWidget *parent nul…

打造备份一体机,群晖科技平台化战略再进阶

数字经济时代&#xff0c;海量数据不断涌现&#xff0c;并成为核心生产要素&#xff0c;驱动着企业生产方式和商业模式发生深刻变革。 与其他生产要素不同&#xff0c;数据要素具有非稀缺性、非竞争性等特征&#xff0c;且只有在具体业务场景中才能充分释放其价值。尤其是近年…

Element-Plus中上传文件upload取消提示按钮与文字

去除提示按钮与文字 添加样式&#xff0c;让这个div进行隐藏 .el-upload__input {display: none !important; }

物联网系统中高精度压力检测方案_压力变送器

01 物联网系统中为什么要使用压力变送器 在物联网系统中使用压力变送器的原因主要基于以下几个方面&#xff1a; 感知层的核心作用 物联网系统主要由感知层、传输层、平台层和应用层组成。感知层作为物联网的“排头兵”&#xff0c;负责收集物理世界中的各种信息。压力变送…

在二维平面中,利用时差定位(TDOA)技术,结合N个锚点,通过三边法进行精确定位,采用MATLAB实现

文章目录 主程序程序代码运行结果 主程序 主程序代码如下&#xff1a; % TDOA测距定位&#xff0c;二维平面&#xff0c; 4个锚节点的情况 % author:Evand&#xff08;VX&#xff1a;matlabfilter&#xff0c;除前期达成一致外&#xff0c;讲解需付费&#xff09; % 2024年9月…

node-rtsp-stream、jsmpeg.min.js实现rtsp视频在web端播放

1. 服务地址&#xff08;私有&#xff09;&#xff1a;https://gitee.com/nnlss/video-node-server 2.node-rtsp-stream 需要安装FFMPEG&#xff1b; 3.给推拉流做了开关&#xff0c;可借助http请求&#xff0c;有更好方式可联系&#xff1b; 4.存在问题&#xff1a; 1&…

单点登录(SSO)基础

单点登录&#xff08;SSO, Single Sign-On&#xff09; 是一种身份认证机制&#xff0c;允许用户在多个独立的应用系统中只进行一次登录操作&#xff0c;即可访问所有授权的应用或服务&#xff0c;而无需每次切换应用时都进行登录。SSO 提高了用户体验的便捷性&#xff0c;同时…

基于springboot的书店图书销售管理系统的设计与实现 (含源码+sql+视频导入教程)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于springboot的书店图书销售管理系统拥有三个角色 管理员&#xff1a;用户管理、角色管理、权限管理、店铺管理等商家&#xff1a;图书管理、上架图书、访问量统计、销售总额统计、订单…