使用plotly dash 画3d圆柱(Python)

news2024/11/18 5:28:03

plotly3D (3d charts in Python)可以画3维图形

在做圆柱的3D装箱项目,需要装箱的可视化,但是Mesh (3d mesh plots in Python)只能画三角形,所以需要用多个三角形拼成一个圆柱(想做立方体的可视化,可以进入使用plotly dash 画3d立方体_python 3d绘图立方体-CSDN博客):

1 画上下底面的边线:因为只能画直线,所以只能用n边形代替圆(我感觉30-50就足够了)

# 找圆柱底边 num_points 个点 
def to_cylinder_point(cylinder:Cylinder):
    print(cylinder)
    # 设置圆形参数
    num_points = 30  # 圆形上的点的数量
    # 计算圆上的点的坐标
    theta = np.linspace(0, 2 * np.pi, num_points)
    x = cylinder.coordinate[0] + cylinder.radius * np.cos(theta)
    y = cylinder.coordinate[1] + cylinder.radius * np.sin(theta)
    z_underside = np.full(num_points, cylinder.coordinate[2])  
    z_top = np.full(num_points, cylinder.coordinate[2]+cylinder.height)
    return x,y,z_underside,z_top
# 画出下底边的轮廓
fig.add_scatter3d(x=x, y=y, z=z_bottom, mode="lines", line={'color': 'black', 'width': 2})

2 拼上下底面:以上下底面圆心为中心,上一步计算出来的“圆柱底边 num_points 个点”做边画三角形。

        # 将圆心插入首位
        b_x = np.insert(x,0,p.coordinate[0])
        b_y =np.insert(y,0,p.coordinate[1])
        b_z = np.insert(z_bottom,0,p.coordinate[2])
        t_z = np.insert(z_top, 0, p.coordinate[2] + p.height)
        i, j, k = to_planes(len(b_x))
        # 画底面
        fig.add_mesh3d(x=b_x,y=b_y,z=b_z,i=i,j=j,k=k,color='pink')

        # 画顶面
        fig.add_mesh3d(x=b_x,y=b_y,z=t_z,i=i,j=j,k=k,color='pink')

3 拼侧面:以上一步计算出来的 上下“圆柱底边 各num_points 个点”做边画三角形。

        s_x = np.concatenate((x,x))
        s_y = np.concatenate((y,y))
        s_z = np.concatenate((z_top,z_bottom))
        ii, jj, kk = to_side(len(s_z))

        # 画侧面
        fig.add_mesh3d(x=s_x,y=s_y,z=s_z,i=ii,j=jj,k=kk,color='pink')

所有代码:

import plotly.graph_objects as go
import numpy as np
import math

class Cylinder:
    def __init__(self, name, diameter,height,num = 0):
        self.name = name
        self.diameter = int(diameter)
        self.radius = int(diameter/2)
        self.height = int(height)
        self.num = num
        self.coordinate = None


def cylinder_copy(cylinder:Cylinder,height):
    new_cylinder = Cylinder(cylinder.name,cylinder.diameter,cylinder.height,cylinder.num)
    new_cylinder.coordinate = cylinder.coordinate+[height]
    return new_cylinder


class Box:
    def __init__(self, name, long,wide,height):
        self.name = name
        self.long = int(long)
        self.wide = int(wide)
        self.height = int(height)


def toline(cx,cy,cz):
    # 通过立方体的8个顶点,画出立方体的轮廓.cx(x轴8个坐标)
    x = [cx[0],cx[1],cx[2],cx[3],cx[0],cx[4],cx[5],cx[1],cx[5],cx[6],cx[2],cx[6],cx[7],cx[3],cx[7],cx[4]]
    y = [cy[0],cy[1],cy[2],cy[3],cy[0],cy[4],cy[5],cy[1],cy[5],cy[6],cy[2],cy[6],cy[7],cy[3],cy[7],cy[4]]
    z = [cz[0],cz[1],cz[2],cz[3],cz[0],cz[4],cz[5],cz[1],cz[5],cz[6],cz[2],cz[6],cz[7],cz[3],cz[7],cz[4]]
    return x,y,z

def toxyz(begin,end):
    # 通过开始结束位置确定立方体的8个顶点
    #        0       1                2         3               4         5         6         7
    x = [begin[0],begin[0],end[0],end[0],begin[0],begin[0],end[0],end[0]]
    y = [begin[1],end[1],end[1],begin[1],begin[1],end[1],end[1],begin[1]]
    z = [begin[2],begin[2],begin[2],begin[2],end[2],end[2],end[2],end[2]]
    return x,y,z

# 根据圆的边线,填满圆
def to_planes(n):
    ii=[]
    jj=[]
    kk=[]
    for v in range(1,n):
        ii.append(0)
        jj.append(v)
        if v+1>=n:
            kk.append(1)
        else:
            kk.append(v+1)
    return ii,jj,kk

# 根据圆上下底面的边线,填满侧边
def to_side(n):
    ii=[]
    jj=[]
    kk=[]
    half = int(n/2)
    for i in range(half):
        ii.append(i)
        if i+1>=half:
            jj.append(0)
        else:
            jj.append(i+1)
        kk.append(i+half)

        if i+1>=half:
            ii.append(0)
        else:
            ii.append(i+1)
        jj.append(i+half)
        if i+half+1>=n:
            kk.append(half)
        else:
            kk.append(i+half+1)

    return ii,jj,kk


def to_cylinder_point(cylinder:Cylinder):
    print(cylinder)
    # 设置圆形参数
    num_points = 30  # 圆形上的点的数量
    # 计算圆上的点的坐标
    theta = np.linspace(0, 2 * np.pi, num_points)
    x = cylinder.coordinate[0] + cylinder.radius * np.cos(theta)
    y = cylinder.coordinate[1] + cylinder.radius * np.sin(theta)
    z_underside = np.full(num_points, cylinder.coordinate[2])  # 在 z 轴上的坐标都为圆心的 z 坐标
    z_top = np.full(num_points, cylinder.coordinate[2]+cylinder.height)  # 在 z 轴上的坐标都为圆心的 z 坐标
    return x,y,z_underside,z_top



def getfig(box:Box,position):
    box_xyz = toxyz([0, 0, 0], [box.long, box.wide, box.height])

    box_line = toline(box_xyz[0], box_xyz[1], box_xyz[2])
    fig=go.Figure(data=[
        go.Scatter3d(
            x=box_line[0],
            y=box_line[1],
            z=box_line[2],
            mode='lines',
            line={'color': 'black', 'width': 2}
        )
    ])

    for p in position:
        x, y, z_bottom, z_top = to_cylinder_point(p)
        # 画下底面的线
        fig.add_scatter3d(x=x, y=y, z=z_bottom, mode="lines", line={'color': 'black', 'width': 2})
        # 画顶面的线
        fig.add_scatter3d(x=x, y=y, z=z_top, mode="lines", line={'color': 'black', 'width': 2})

        b_x = np.insert(x,0,p.coordinate[0])
        b_y =np.insert(y,0,p.coordinate[1])
        b_z = np.insert(z_bottom,0,p.coordinate[2])
        t_z = np.insert(z_top, 0, p.coordinate[2] + p.height)
        i, j, k = to_planes(len(b_x))
        # 画底面
        fig.add_mesh3d(x=b_x,y=b_y,z=b_z,i=i,j=j,k=k,color='pink')

        # 画顶面
        fig.add_mesh3d(x=b_x,y=b_y,z=t_z,i=i,j=j,k=k,color='pink')
        s_x = np.concatenate((x,x))
        s_y = np.concatenate((y,y))
        s_z = np.concatenate((z_top,z_bottom))
        ii, jj, kk = to_side(len(s_z))

        # 画侧面
        fig.add_mesh3d(x=s_x,y=s_y,z=s_z,i=ii,j=jj,k=kk,color='pink')

    fig.update_layout(
        clickmode='event+select',
        # 设置xyz轴比例原本比例:draw axes in proportion to the proportion of their ranges
        scene_aspectmode='data',
        scene=dict(xaxis_title='x-长'+str(box.long)+'mm',
                   yaxis_title='y-宽'+str(box.wide)+'mm',
                   zaxis_title='z-高'+str(box.height)+'mm',
                   xaxis=dict(
                       backgroundcolor="rgb(230, 230,200)",
                       gridcolor="white",
                       showbackground=True,
                       zerolinecolor="black", ),
                   yaxis=dict(
                       backgroundcolor="rgb(230, 230,200)",
                       gridcolor="white",
                       showbackground=True,
                       zerolinecolor="black"),
                   zaxis=dict(
                       backgroundcolor="rgb(230, 230,200)",
                       gridcolor="white",
                       showbackground=True,
                       zerolinecolor="black", ),
                   ),
        height=600,
        width=800,
    )

    return fig




cylinder = Cylinder('a',70,30)
cylinder.coordinate=[50+2*math.sqrt(3),70,10]

box = Box('b',100,200,70)
fig = getfig(box,[cylinder])
fig.show()

代码结果展示:

多个圆柱展示:

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

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

相关文章

vue实现跳转传参查询

vue实现跳转传参查询: 应用场景:外部链接携参跳转目标页时,避免多次输入查询信息查询 目标需求:登录及非登录状态均可跳转自动查询 避坑指南:token失效时需要重新缓存及路由导航缓存判断 简单实现:缓存信息&#xff0c…

PeakCAN连接到WSL2 Debian

操作步骤 按照以下步骤进行操作: 在Windows下安装PeakCAN驱动并安装,地址是https://www.peak-system.com/PCAN-USB.199.0.html?&L1 在Windows下安装usbipd,地址是https://github.com/dorssel/usbipd-win/releases,最新版是…

Elasticsearch:如何为 Elastic Stack 配置 AI Assistant

了解并安装 Elastic AI Assistant Elastic 推出了 Observability AI Assistant,这是一款利用生成式 AI 来增强你的 Observability 体验的强大工具。 该 AI 助手由 OpenAI 或 Azure OpenAI 服务的连接器提供支持,可带来上下文洞察和聊天功能,…

vue中的vuex

在Windows的应用程序开发中,我们习惯了变量(对象)声明和使用方式,就是有全局和局部之分,定义好了全局变量(对象)以后在其他窗体中就可以使用,但是窗体之间的变量(对象&am…

c++学习记录 多态—案例2—电脑组装

#include<iostream> using namespace std;//抽象不同的零件//抽象的cpu类 class Cpu { public://抽象的计算函数virtual void calculate() 0; };//抽象的显卡类 class VideoCard { public://抽象的显示函数virtual void display() 0; };//抽象的内存条类 class Memory …

【MySQL】聚合函数和内置函数

文章目录 1 :peach:聚合函数:peach:2 :peach:group by子句的使用:peach:3 :peach:内置函数:peach:3.1 :apple:日期函数:apple:3.2 :apple:字符串函数:apple:3.3 :apple:数学函数:apple: 4 :peach:其它函数:peach: 1 &#x1f351;聚合函数&#x1f351; 函数说明COUNT([DISTIN…

【大数据】Flink 架构(三):事件时间处理

《Flink 架构》系列&#xff08;已完结&#xff09;&#xff0c;共包含以下 6 篇文章&#xff1a; Flink 架构&#xff08;一&#xff09;&#xff1a;系统架构Flink 架构&#xff08;二&#xff09;&#xff1a;数据传输Flink 架构&#xff08;三&#xff09;&#xff1a;事件…

(十四)测频NE555应用

文章目录 NE555简介NE555原理图如何对NET_SIG&#xff08;P34&#xff09;引脚计脉冲测频应用部分代码现象 NE555简介 NE555是一种集成电路&#xff0c;其内部结构包括比较器、RS触发器、电压比较器和输出级三个主要功能模块。是由硬件直接产生的脉冲 NE555一些的常见应用&am…

Orion-14B-Chat-Plugin本地部署的解决方案

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

PGsql 解析json及json数组

创建测试数据 drop table if exists json_test; create table json_test as select 111 as id, {"nodes":{"1692328028076":{"nodeId":"1692328028076","nodeName":"测试表1","nodeType":"DATACO…

Golang 流媒体服务器lalserver使用指南

目录 安装 使用 1.推流 2.播放 官方地址 安装 1.下载源码 wget https://github.com/q191201771/lal/releases/download/v0.36.7/lal_v0.36.7_linux.zipunzip lal_v0.36.7_linux.zip cd lal_v0.36.7_linux 2.启动 ./bin/lalserver -c ./conf/lalserver.conf.json 使用 …

Linux部署lomp环境,安装typecho、WordPress博客

部署lomp环境&#xff0c;安装typecho、WordPress博客 一、环境要求1.1.版本信息1.2.准备阿里云服务器【新用户免费使用三个月】1.3.准备远程工具【FinalShell】 二、Linux下安装openresty三、Linux下安装Mysql四、安装Apache【此步骤可省略】4.1.安装Apache服务及其扩展包4.2.…

【React教程】(2) React之JSX入门与列表渲染、条件渲染详细代码示例

目录 JSX环境配置基本语法规则在 JSX 中嵌入 JavaScript 表达式在 JavaScript 表达式中嵌入 JSXJSX 中的节点属性声明子节点JSX 自动阻止注入攻击在 JSX 中使用注释JSX 原理列表循环DOM Elements 列表渲染语法高亮 条件渲染示例1&#xff1a;示例2&#xff1a;示例3&#xff08…

使用Docker安装Jenkins,并能够在该Jenkins中使用Docker

1. 构建Dockerfile 试错1 参考https://medium.com/manav503/how-to-build-docker-images-inside-a-jenkins-container-d59944102f30 按照文章里所介绍的&#xff0c;实现在Jenkins容器环境中依然能够调用Docker&#xff0c;需要做到以下几步 下载Jenkins镜像将环境中的docke…

解析PDF二维码:数字时代文件管理的创新之道

随着数字时代的来临&#xff0c;文件管理方式正经历着翻天覆地的变革。在这个变革的浪潮中&#xff0c;PDF二维码作为一种创新的技术手段&#xff0c;正逐渐引起人们的关注。本文将深入探讨PDF二维码的概念、应用领域以及在文件管理中的前景。 一、PDF二维码的概念 PDF二维码…

2024-01-29 ubuntu 用脚本设置安装交叉编译工具链路径方法,设置PATH环境变量

一、设置PATH环境变量的方法,建议用~/.bash_profile的方法&#xff0c;不然在ssh登录的时候可能没有设置PATH. 二、下面的完整的脚本&#xff0c;里面的echo "export PATH$build_toolchain_path:\$PATH" >> $HOME/.bashrc 就是把交叉编译路径写写到.bashrc设置…

笔记本从零安装ubuntu系统+多种方式远程控制

文章目录 前言ubuntu启动盘Windows远程Ubuntu安装XrdpXrdp卡顿问题解决Xrdp 二次登录会死机的问题Xrdp 卡顿问题 MobaXtermRustDesk 外网远程VNC 远程SSH远程其它设置 总结 前言 我有台老笔记本&#xff0c;上大学第一年的时候买的&#xff0c;现在已经不怎么好用了。打算刷个…

IS-IS:07 ISIS缺省路由

IS-IS 有两种缺省路由&#xff0c;第一种缺省路由是由 level-1 路由器在特定条件下自动产生的&#xff0c;它的下一跳是离它最近的 &#xff08;cost 最小&#xff09;level-1-2路由器。第二种缺省路由是 IS-IS 路由器上使用 default-route-advertise 命令产生并发布的。 本次实…

最后50个CC龙年红包封面,免费速领!还有更多......高中生也卷起Steam来了

微信视频号之前是送了我3张新年红包封面&#xff0c;一共是150个&#xff0c;但不太会操作浪费了100个&#xff0c;只能我自己用来送老铁了。 晓衡又做了一条 Cocos 小可爱 CC 封面红包&#xff0c;特别适合送女生或给小朋友们&#xff0c;点击视频领取&#xff01;还好微信又送…

Vue学习之使用开发工具创建项目、gitcode管理项目

Vue学习之使用开发工具创建项目、gitcode管理项目 翻阅与学习了vue的开发工具&#xff0c;通过对比最终采用HBuilderX作为开发工具&#xff0c;以下章节对HBuilder安装与基础使用介绍 1. HBuilder 下载 从HbuildX官网&#xff08;http://www.dcloud.io/hbuilderx.html&#…