经典算法-分治法由散点得出凸包-python实现

news2024/10/5 14:11:34

import copy
import random
import matplotlib
import math


def distance_p2l(point, line_point1, line_point2):
    if (line_point2[0] - line_point1[0]) == 0:
        return abs(point[0] - line_point2[0])
    # 计算直线的斜率
    m = (line_point2[1] - line_point1[1]) / (line_point2[0] - line_point1[0])
    # 计算直线的截距
    b = line_point1[1] - m * line_point1[0]
    # 计算距离
    d = abs(m * point[0] - point[1] + b) / math.sqrt(m ** 2 + 1)
    return d


def node_above_line(node, line0, line1,upper_convex=True,left_convex=True):
    real_y = node[1]
    # y_on_line =(node[0]-line0[0])/(line1[0]-line0[0])*(line1[1]-line0[1])+line0[1]

    if (line1[0] - line0[0])!=0:
        print(node[1],
              node[0] - line0[0] / (line1[0] - line0[0]) * (line1[1] - line0[1]) + line0[
                  1])
        if node[1] > (node[0]-line0[0])/(line1[0]-line0[0])* (line1[1]-line0[1])+line0[1]:

            return True
        else:
            return False
    else:
        if node[0]<line0[0]:
            if upper_convex==True:
                if left_convex:
                    return True
                else:
                    return False
            if upper_convex==False:
                if left_convex:
                    return False
                else:
                    return True

        else:
            if upper_convex == True:
                if left_convex:
                    return False
                else:
                    return True
            if upper_convex==False:
                if left_convex:
                    return True
                else:
                    return False

def cal_convex_hull_point(min_x_node, max_x_node, upper_set,upper_convex=True):
    if len(upper_set) == 0:
        return [min_x_node, max_x_node]
    upper_set_distance2line = [distance_p2l(point, max_x_node, min_x_node) for point in upper_set]
    max_idx = upper_set_distance2line.index(max(upper_set_distance2line))
    farthest_p = upper_set[max_idx]
    upper_set_mins =  [node for node in upper_set if node != farthest_p]
    left_subset_of_upper, right_subset_of_upper = [], []
    for node in upper_set_mins:
        if node_above_line(node, farthest_p, min_x_node,upper_convex=upper_convex,left_convex=True)==upper_convex:
            left_subset_of_upper.append(node)
        if node_above_line(node, farthest_p, max_x_node,upper_convex=upper_convex,left_convex=False)==upper_convex:
            right_subset_of_upper.append(node)
    lu = cal_convex_hull_point(min_x_node,farthest_p,left_subset_of_upper,upper_convex)
    ru = cal_convex_hull_point(farthest_p,max_x_node,right_subset_of_upper,upper_convex)
    return lu+ru



def divide_conquer(nodes):
    sorted_nodes = sorted(nodes, key=lambda x: x[0])
    max_x_node = sorted_nodes[-1]
    min_x_node = sorted_nodes[0]
    upper_set = []
    lower_set = []
    lu,ru,ll,rl = [],[],[],[]
    for node in sorted_nodes[1:-1]:
        if node_above_line(node, max_x_node, min_x_node):
            upper_set.append(node)
        else:
            lower_set.append(node)
    if len(upper_set)!=0:
        upper_set_distance2line = [distance_p2l(point, max_x_node, min_x_node) for point in upper_set]
        max_idx = upper_set_distance2line.index(max(upper_set_distance2line))
        farthest_p = upper_set[max_idx]
        upper_set_mins = [node for node in upper_set if node != farthest_p]
        left_subset_of_upper, right_subset_of_upper = [], []
        for node in upper_set_mins:
            if node_above_line(node, farthest_p, min_x_node,left_convex=True):
                left_subset_of_upper.append(node)
            if node_above_line(node, farthest_p, max_x_node,left_convex=False):
                right_subset_of_upper.append(node)
        lu = cal_convex_hull_point(min_x_node, farthest_p, left_subset_of_upper)
        ru = cal_convex_hull_point(farthest_p, max_x_node, right_subset_of_upper)
    if len(lower_set) != 0:
        lower_set_distance2line = [distance_p2l(point, max_x_node, min_x_node) for point in lower_set]
        max_idx = lower_set_distance2line.index(max(lower_set_distance2line))
        farthest_p = lower_set[max_idx]
        lower_set_mins = [node for node in lower_set if node != farthest_p]
        left_subset_of_lower, right_subset_of_lower = [], []
        for node in lower_set_mins:
            if node_above_line(node, farthest_p, min_x_node,upper_convex=False,left_convex=True)==False:
                left_subset_of_lower.append(node)
            if node_above_line(node, farthest_p, max_x_node,upper_convex=False,left_convex=False)==False:
                right_subset_of_lower.append(node)
        ll = cal_convex_hull_point(min_x_node, farthest_p, left_subset_of_lower,upper_convex=False)
        rl = cal_convex_hull_point(farthest_p, max_x_node, right_subset_of_lower,upper_convex=False)

    point_set = list(set(ll + lu + rl + ru))
    print("set point",point_set)
    convex0 = lu + ru
    convex1 = ll + rl
    convex0 = [convex0[i] for i in range(len(convex0)) if i==0 or i>0 and convex0[i]!=convex0[(i-1)]]
    convex1 = [convex1[i] for i in range(len(convex1)) if i==0 or i>0 and convex1[i] != convex1[i - 1]]
    convex1 = [convex1[i] for i in range(len(convex1) - 1, -1, -1)]
    convex  = convex0 +convex1
    convex = convex + [convex[0]]
    print("lines are ", convex)
    return convex


def draw_points(points, convex_p=None):
    import matplotlib.pyplot as plt
    plt.ion()
    # 输入点的坐标
    # points = [(0, 55), (40, 93), (20, 70), (10, 60)]  # 示例坐标

    # 分离 x 和 y 坐标
    x_coords = [point[0] for point in points]
    y_coords = [point[1] for point in points]

    # 绘制点
    plt.scatter(x_coords, y_coords, color='blue')

    if convex_p != None:
        c_x = [p[0] for p in convex_p]
        c_y = [p[1] for p in convex_p]
        colors = ['red'] * len(c_y)
        plt.scatter(c_x, c_y, color=colors)
        plt.plot(c_x, c_y, color='red')
    # 添加标题和坐标轴标签
    plt.title('Scatter Plot of Points')
    plt.xlabel('X Coordinate')
    plt.ylabel('Y Coordinate')
    plt.pause(5)
    plt.ioff()
    plt.clf()

def pnpoly(vertices, testp):
    n = len(vertices)
    j = n - 1
    res = False
    for i in range(n):
        if (vertices[i][1] > testp[1]) != (vertices[j][1] > testp[1]) and \
                testp[0] < (vertices[j][0] - vertices[i][0]) * (testp[1] - vertices[i][1]) / (
                vertices[j][1] - vertices[i][1]) + vertices[i][0]:
            res = not res
        j = i
    return res


for i in range(38,100):
    print('seed',i)
    random.seed(i)
    nodes = [(random.randint(0, 100), random.randint(0, 100)) for i in range(10)]
    print(nodes)
    draw_points(nodes)
    convex_p = divide_conquer(nodes)

    draw_points(nodes, convex_p)

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

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

相关文章

电脑出现mfc140u.dll丢失怎么办?教你7个方法解决此问题

mfc140u.dll 是一个动态链接库 (Dynamic Link Library, DLL) 文件&#xff0c;它是 Microsoft Windows 操作系统环境下用于支持应用程序运行的重要组成部分。具体来说&#xff0c;mfc140u.dll 是 Microsoft Foundation Class (MFC) 库 14.0 版本的 Unicode 版本动态链接库文件。…

分享一下项目中遇到的排序失效问题

今天把原来的一个查询接口的业务代码进行了优化&#xff0c;减少了十几行冗余的代码。 原来的代码 ChongwuServiceImpl.java /*** author heyunlin* version 1.0*/ Slf4j Service public class ChongwuServiceImpl implements ChongwuService {Overridepublic JsonResult<…

TensorFlow-gpu安装教程(Linux系统)

一、TensorFlow-gpu环境的安装 使用这个代码安装的前提是你的深度学习已经环境存在 &#xff08;例如&#xff1a;conda、pytorch、cuda、cudnn等环境&#xff09; TensorFlow版本对应GPU版本&#xff0c;自己选择版本&#xff0c;也可以忽略版本直接安装TensorFlow-gpu cond…

百度松果菁英班——机器学习实践五:明星图片爬取

飞桨AI Studio星河社区-人工智能学习与实训社区 &#x1f96a;图片爬取 import requests import os import urllib ​ class GetImage():def __init__(self,keyword大雁,paginator1):# self.url: 链接头self.url http://image.baidu.com/search/acjson?self.headers {User…

IO_DAY7

1:实现2个终端之间的互相聊天 要求:千万不要做出来2个终端之间的消息发送是读一写的&#xff0c;一定要能够做到&#xff0c;一个终端发送n条消息&#xff0c;另一个终端一条消息都不回复都是没有问题的 终端A&#xff1a; #include<myhead.h> int main(int argc, char…

测开面经(pytest测试案例,接口断言,多并发断言)

pytest对用户登录接口进行自动化脚本设计 a. 创建一个名为"test_login.py"的测试文件&#xff0c;编写以下测试脚本 import pytest import requests# 测试用例1&#xff1a;验证登录成功的情况 # 第一个测试用例验证登录成功的情况&#xff0c;发送有效的用户名和密…

three.js零基础入门超全超细的教程整理(一)

事情是这样的&#xff1a; 有一天 我干完活 看技术文章 发现了three.js 诶&#xff01;这玩应挺有意思 盘盘 于是第一天找教程 上官网 初上手 第二天 找案例 渲模型 试VR 第三天 捋文档 然后来活了 没时间捋了 下面是集百家精华教程的整理总结 涉及到教程方面有加源作者和地址…

AI智能分析盒子在工地的应用,提高工地管理效率和安全性

工地ai智能分析盒子是一种基于人工智能视觉分析技术的人工智能盒子&#xff0c;旨在提升工地作业区域的管理效率和保障作业人员的安全。通过最前沿的AI视觉算法、大数据&#xff0c;能够实时监控工地现场视频流画面&#xff0c;对施工工地人员的工作着装及日常作业行为进行规范…

【多线程】进程(进程的概念+进程的管理+PCB(进程控制块)+进程的调度)

文章目录 进程一、计算机的组成&#xff1a;1.指令&#xff08;Instruction&#xff09; 二、浅谈操作系统1.日常的操作系统1.操作系统内核内核&#xff1a;进程的隔离性&#xff1a; 三、进程&#xff08;process&#xff09;1.进程的概念2.进程的管理1.管理的两个角度&#x…

短视频有效粉丝不够怎么涨?有效粉丝不满足500怎么解决?不够500有效粉丝怎么挂橱窗?

在这个流量主导的短视频时代&#xff0c;想要在短视频平台上增加粉丝数量并非易事。然而随着短视频平台规则更新4月16日开始&#xff0c;不能满足五百有效粉丝&#xff0c;就不能挂橱窗了&#xff0c;对一些有效粉丝不够的用户来说&#xff0c;这个的确是有点麻烦&#xff0c;而…

Mysql底层原理二:Buffer Pool

1.数据区 就是描述信息缓存页这块&#xff0c;用来存放从磁盘加载的数据页&#xff08;看上图 索引页和数据页是分开的&#xff09; 2. free链表 用来标识数据区哪些数据页是可用的 3. flush链表 update的时候&#xff0c;如果数据在数据区可以找到&#xff0c;那就直接内…

基于Vue3 中后台管理系统框架

基于Vue3 中后台管理系统框架 文章目录 基于Vue3 中后台管理系统框架一、特点二、源码下载地址 一款开箱即用的 Vue 中后台管理系统框架&#xff0c;支持多款 UI 组件库&#xff0c;兼容PC、移动端。vue-admin, vue-element-admin, vue后台, 后台系统, 后台框架, 管理后台, 管理…

GPU部署ChatGLM3

首先&#xff0c;检查一下自己的电脑有没有CUDA环境&#xff0c;没有的话&#xff0c;去安装一个。我的电脑是4060显卡&#xff0c;买回来就自带这些环境了。没有显卡的话&#xff0c;也不要紧&#xff0c;这个懒人安装包支持CPU运行&#xff0c;会自动识别没有GPU&#xff0c;…

力扣刷题Days33-274. H 指数(js)

目录 1&#xff0c;题目 2&#xff0c;代码 2.1排序 2.2计数排序 3&#xff0c;学习与总结 3.1排序实现的学习总结 3.2计数排序的学习总结 1&#xff0c;题目 给你一个整数数组 citations &#xff0c;其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返…

vs2017离线安装(配合QT5.9.2使用)

以vs2017_Professional版本为例&#xff1a; 一、下载安装包vs2017_Professional.exe&#xff08;在线安装包即可&#xff09; 二、创建在目录&#xff1a;C:\vs2017_Professional_Package&#xff0c;把vs2017_Professional.exe放在该目录下。 ID&#xff1a; Microsoft.Vis…

pytorch演示pipeline并行

pytorch演示pipeline并行 1.单卡内存不够时,可以将网络切分成几段(stage),每个GPU负责一个stage。比如GPU0计算完之后将数据发送给GPU1算后续的stage 2.以上的方式,会导致GPU的利用率不高,可以将输入的batch切分成多份更小的batch,陆续送给GPU0,这样GPU0处理完micro batch0之后…

计算机网络 实验指导 实验9

实验9 三层交换机综合实验 1.实验拓扑图 名称相连的接口IP地址网关PC1F0/3172.1.1.2/28172.1.1.1/28PC2F0/4172.1.1.18/28172.1.1.17/28PC3F0/5172.1.1.34/28172.1.1.33/28PC4F0/3172.1.1.3/28172.1.1.1/28PC5F0/4172.1.1.19/28172.1.1.17/28PC6F0/5172.1.1.35/28172.1.1.33/2…

基于单片机分舱式电开水炉位控制系统

**单片机设计介绍&#xff0c;基于单片机分舱式电开水炉位控制系统 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机分舱式电开水炉位控制系统概要主要涉及通过单片机对电开水炉的各个舱位进行精确控制&#xff0c;实现水位、温度…

mos管开关出现尖峰的原理? mos管开关的时候cs会出现尖峰,请问这是什么原因?

MOS管在开关过程中出现尖峰现象&#xff0c;通常是由于电路中的寄生参数和快速电压变化引起的。以下是一些导致尖峰出现的主要原因和原理&#xff1a; 寄生电容 在MOS管的源极&#xff08;S&#xff09;和漏极&#xff08;D&#xff09;之间存在寄生电容&#xff0c;这个电容在…

考研数据结构——栈和队列(最全!)

一、栈 1.1栈的定义和基本概念 要讨论一种数据结构&#xff0c;就要从三方面讨论&#xff1a;逻辑结构、数据的运算、存储结构&#xff08;物理结构&#xff09;。 1.1.1 定义 线性表&#xff1a;线性表是具有相同数据类型的n个数据元素的有限序列&#xff0c;其中n为表长&am…