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

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()

代码结果展示:

多个圆柱展示:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

四、ES集群安全策略设置 X-pack

本文主要是结合ES集群搭建时使用,并且适用于ES7.x以上版本 背景及安全策略方案对比 ES 7.x以下版本默认几乎没有任何安全策略,如果集群IP、端口被暴露,在可访问的情况下任何用户都可以对索引进行管理以及数据的增删改查等,基于此需…

国外非常好的渗透测试资源集合和十大渗透测试演练系统,系统被攻击渗透入侵后进行取证和溯源

国外非常好的渗透测试资源集合和十大渗透测试演练系统,系统被攻击渗透入侵后进行取证和溯源。 Awesome Penetration Testing A collection of awesome penetration testing resources Online Resources Penetration Testing Resources Exploit development Social Enginee…

成功解决AttributeError: ‘str‘ object has no attribute ‘get‘

成功解决AttributeError: ‘str’ object has no attribute ‘get’. 🌵文章目录🌵 🌳引言🌳🌳报错分析及解决方案🌳🌳字典对象的get方法🌳🌳结尾🌳 &#x1…

安全测试-pikachu靶场搭建

pikachu靶场搭建 文章目录 pikachu安装步骤 pikachu pikachu是一个自带web漏洞的应用系统,在这里包含了常见的web安全漏洞,也就是练习的靶场。 练习内容包括: 1.暴力破解 2.XSS 3.CSRF 4.SQL注入 5.RCE 6.文件包含 7.不安全的文件下载 8.不安…

免 费 小程序商城搭建之b2b2c o2o 多商家入驻商城 直播带货商城 电子商务b2b2c o2o 多商家入驻商城 直播带货商城 电子商务

1. 涉及平台 平台管理、商家端(PC端、手机端)、买家平台(H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务) 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

c语言学习笔记

逗号表达式 #include <stdio.h>int main(){int a 10;int b 5;int c 6;int d (a 23,b a-4,c b2);printf("%d",d); }打印结果为: 逗号表达式,从左往右依次进行,将最后一个表达式的值赋值给变量. c语言字符串相关库函数 求字符串长度strlen长度不受限制的…

web wifi配网和模式切换-esp8266和esp32

web wifi配网和模式切换-esp8266和esp32 支持模式:1:tcp client() 2:tcp server 3:http server(POST/GET) 4:http client 5:udp,6:factory,7:mqtt 配网进入方式&#xff1a; 开机&#xff0c;指示灯亮起后(需要灯闪烁3下后)&#xff0c;需在3s内&#xff08;超过3s则会正常启动…

WebGL技术开发框架

WebGL技术框架是一些提供了便捷API和工具的库&#xff0c;用于简化和加速在Web浏览器中使用WebGL进行3D图形开发。以下是一些常用的WebGL技术框架&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.Th…

vue+ElementPlus实现中国省市区三级级联动封装

安装插件获取中国省份的所有数据 npm install element-china-area-data -S 借助ElementPlus 级联选择器 Cascader实现 <template><div><el-cascadersize"large":options"options"v-model"selectedOptions"change"handleCh…

32OLED中断系统&对射式红外计数&旋转编码计数

一.程序调试方式 二.OLED简介 stm32引脚上电后&#xff0c;如果不初始化&#xff0c;默认是浮空输入的模式&#xff0c;在这个模式下引脚不会输出电平 三. 中断系统 EXTI外部中断&#xff0c;TIM定时器&#xff0c;ADC模数转换器&#xff0c;USART串口&#xff0c;SPI通信&…

【SpringBoot3】集成Knife4j、springdoc-openapi作为接口文档

一、什么是springdoc-openapi Springdoc-openapi 是一个用于生成 OpenAPI&#xff08;之前称为 Swagger&#xff09;文档的库&#xff0c;专为 Spring Boot 应用程序设计。它可以根据你的 Spring MVC 控制器、REST 控制器和其他 Spring Bean 自动生成 OpenAPI 文档&#xff0c…

Google Chrome 中出现 ERR_SSL_KEY_USAGE_INCOMPATIBLE 错误

证书的方式发生了变化&#xff0c;出现了这个新错误&#xff0c;导致我无法浏览该网站。 可以右键属性获取位置 关闭导航器chrome并转到文件夹&#xff0c;找到Local State文件并删除 执行指令结束进程&#xff0c;重新打开浏览器即可 taskkill /im "chrome.exe"…

Unity3d实现简单的战斗

使用u3d实现一个简单的战斗demo&#xff0c;记下学到的知识点&#xff0c;以备后查。 1.判断是否点中指定物体 if (Input.GetMouseButton(0)) {Ray ray Camera.main.ScreenPointToRay(Input.mousePosition);if (Physics.Raycast(ray, out RaycastHit hit)){//坐标转换Vector…

PeakCAN连接到WSL2 Debian

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

我们是如何测试人工智能的(六)推荐系统拆解

推荐系统简介 推荐系统的问题 根据之前学习到的内容&#xff0c;我们已经基本了解到了要如何构建一个二分类模型。我们都知道模型大体可以分成&#xff0c;回归&#xff0c;二分类和多分类。但推荐系统是属于哪一种场景呢&#xff0c;比如我们常见的广告推荐或者内容推荐&…

线性代数---------学习总结

线性代数之行列式 行列式的几条重要的性质 1.某两行某两列交换位置之后&#xff0c;值变号 2.行列式转置&#xff0c;值不变 3.范德蒙德行列式&#xff0c;用不同行的公比做一系列的累乘运算 4.把某一行的行列式加到另一行上&#xff0c;利用他们之间的倍数关系&#xff0…

最小二乘圆柱拟合(高斯牛顿法)

欢迎关注更多精彩 关注我&#xff0c;学习常用算法与数据结构&#xff0c;一题多解&#xff0c;降维打击。 本期话题&#xff1a;最小二乘圆柱拟合 相关背景资料 点击前往 圆柱拟合输入和输出要求 输入 8到50个点&#xff0c;全部采样自圆柱上。每个点3个坐标&#xff0c;坐…

云计算底层技术奥秘、磁盘技术揭秘、虚拟化管理、公有云概述

云计算基础 实验图例 虚拟化平台安装 创建虚拟机 1、创建虚拟机 2cpu&#xff0c;4G内存&#xff08;默认用户名: root 密码: a&#xff09; 2、验证 ecs 是否支持虚拟化 [rootecs ~]# grep -Po "vmx|svm" /proc/cpuinfovmx... ...[rootecs ~]# lsmod |grep kvm…

Android 13以上版本读写SD卡权限适配

如题&#xff0c;最近工作上处理的问题&#xff0c;把解决方案简单逻列出来&#xff0c;供有需要的朋友参考之 解决方案&#xff1a; 1、配置权限 <uses-permission android:name"android.permission.READ_MEDIA_IMAGES" /><uses-permission android:name&q…

Security ❀ HTTP/HTTPS逐包解析交互过程细节

文章目录 1. TCP三次握手机制2. HTTP Request 请求报文3. HTTP Response 响应报文4. SSL/TLS协议4.1. ClientHello 客户端Hello报文4.2 ServerHello 服务器Hello报文4.3. *ServerKeyExchange 服务公钥交换4.4. ClientKeyExchange 客户端公钥交换4.5. *CertificateVerify 证书验…