Files
wire_controlsystem/UI/ui_3d.py

178 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
# @Time : 2026/1/7 10:41
# @Author : reenrr
# @File : 3D.py
# @Desc : 界面上的线条3D显示
'''
import sys
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
from PySide6.QtCore import Qt
class Target3DWidget(QWidget):
"""
3D显示窗口支持类型A和类型B
"""
VERTICES_A = [
# 底部截面Z=0平面
(0, 3, 0), (100, 3, 0),
(100, 3, 0), (100, 0, 0),
# 中间截面Z=0.5平面)
(0, 0.5, 0.5), (0, 3, 0.5),
(0, 3, 0.5), (100, 3, 0.5),
(100, 3, 0.5), (100, 0.5, 0.5),
(100, 0.5, 0.5), (0, 0.5, 0.5),
# 顶部界面Z=2平面
(0, 0, 2), (0, 0.5, 2),
(0, 0.5, 2), (100, 0.5, 2),
(100, 0.5, 2), (100, 0, 2),
(100, 0, 2), (0, 0, 2),
# z方向的连线
(0, 3, 0.5), (0, 3, 0),
(100, 3, 0.5), (100, 3, 0),
(0, 0.5, 2), (0, 0.5, 0.5),
(100, 0.5, 2), (100, 0.5, 0.5),
(100, 0, 2), (100, 0, 0),
]
VERTICES_B = [
# 底部截面Z=0平面
(0, 3, 0), (100, 3, 0),
(100, 3, 0), (100, 0, 0),
# 中间截面Z=0.5平面)
(0, 0.5, 0.5), (0, 2.5, 0.5),
(100, 2.5, 0.5), (100, 0.5, 0.5),
(100, 0.5, 0.5), (0, 0.5, 0.5),
# 中间截面Z=1平面
(0, 2.5, 1), (0, 3, 1),
(0, 3, 1), (100, 3, 1),
(100, 3, 1), (100, 2.5, 1),
(100, 2.5, 1), (0, 2.5, 1),
# 顶部界面Z=2平面
(0, 0, 2), (0, 0.5, 2),
(0, 0.5, 2), (100, 0.5, 2),
(100, 0.5, 2), (100, 0, 2),
(100, 0, 2), (0, 0, 2),
# z方向的连线
(0, 3, 1), (0, 3, 0),
(100, 3, 1), (100, 3, 0),
(0, 0.5, 2), (0, 0.5, 0.5),
(100, 0.5, 2), (100, 0.5, 0.5),
(100, 0, 2), (100, 0, 0),
(0, 2.5, 1), (0, 2.5, 0.5),
(100, 2.5, 1), (100, 2.5, 0.5)
]
ANNOTATIONS_A = [
("a", 100, 0.25, 2, 'red'),
("b", 100, 0.5, 1.25, 'magenta'),
("c", 100, 1, 0, 'green'),
("d", 100, 3, 0.25, 'blue'),
]
ANNOTATIONS_B = [
("a", 100, 0.25, 2, 'red'),
("b", 100, 0.5, 1.25, 'magenta'),
("c", 100, 1, 0, 'green'),
("d", 100, 3, 0.5, 'blue'),
("e", 100, 2.5, 0.6, 'orange'),
("f", 100, 2.75, 1, 'purple')
]
def __init__(self, index: int = 0, parent=None):
super().__init__(parent)
self._index = index
self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint) # 无边框窗口
self.setAttribute(Qt.WA_TranslucentBackground) # 设置背景为透明
self.setStyleSheet("background: transparent;")
self.init_3d_plot()
self.setLayout(QVBoxLayout())
self.layout().setContentsMargins(0, 0, 0, 0) # 移除布局的内边距
self.layout().addWidget(self.canvas)
def init_3d_plot(self):
# 3D画布
self.fig = plt.figure()
self.fig.patch.set_facecolor('none') # 设置figure背景透明
self.canvas = FigureCanvas(self.fig)
self.ax = self.fig.add_subplot(111, projection='3d')
self.ax.set_facecolor('none') # 设置axes背景透明
# 绘制3D形状
self.draw_target_shape()
# 添加标注
self.add_annotations()
# ========== 核心修改X/Y/Z轴统一为1cm单位 ==========
self.ax.set_xlabel('X')
self.ax.set_ylabel('Y')
self.ax.set_zlabel('Z')
# 1. 清空刻度数值(隐藏刻度数字)
self.ax.set_xticklabels([])
self.ax.set_yticklabels([])
self.ax.set_zticklabels([])
# 2. 隐藏刻度线针对3D轴的特殊设置
self.ax.tick_params(axis='x', which='both', length=0) # X轴刻度线长度设为0
self.ax.tick_params(axis='y', which='both', length=0) # Y轴刻度线长度设为0
self.ax.tick_params(axis='z', which='both', length=0) # Z轴刻度线长度设为0
# 轴范围保留保证3D图形显示范围正确
self.ax.set_xlim(0, 120)
self.ax.set_ylim(0, 5)
self.ax.set_zlim(0, 5)
# 调整视角适配X轴1cm刻度
self.ax.view_init(elev=20, azim=60)
def draw_target_shape(self):
"""绘制3D结构"""
vertices = self.VERTICES_A if self._index == 0 else self.VERTICES_B
# 绘制所有棱边
for i in range(0, len(vertices), 2):
x = [vertices[i][0], vertices[i + 1][0]]
y = [vertices[i][1], vertices[i + 1][1]]
z = [vertices[i][2], vertices[i + 1][2]]
self.ax.plot(x, y, z, color='black', linewidth=2)
def add_annotations(self):
"""标注位置适配X轴1cm单位"""
annotations = self.ANNOTATIONS_A if self._index == 0 else self.ANNOTATIONS_B
for text, x, y, z, color in annotations:
self.ax.text(x, y, z, text, fontsize=14, color=color, weight='bold')
# ----------对外接口----------
def show(x: int, y: int, w: int, h: int, index: int):
"""
显示3D视图窗口
:param x: 窗口横坐标
:param y: 窗口纵坐标
:param w: 窗口宽度
:param h: 窗口高度
:param index: 窗口索引0为A视图1为B视图
"""
if index not in (0, 1):
raise ValueError("index must be 0 or 1")
app = QApplication(sys.argv)
window = Target3DWidget(index)
window.setGeometry(x, y, w, h)
window.show()
sys.exit(app.exec())
# ----------测试接口----------
if __name__ == '__main__':
show(100, 100, 700, 700, 0) # 显示A视图窗口
# show(100, 100, 700, 700, 1) # 显示B视图窗口