217 lines
6.9 KiB
Python
217 lines
6.9 KiB
Python
|
|
#!/usr/bin/env python
|
|||
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
'''
|
|||
|
|
# @Time : 2026/1/7 10:41
|
|||
|
|
# @Author : reenrr
|
|||
|
|
# @File : 3D.py
|
|||
|
|
# @Desc : 界面上的线条3D显示
|
|||
|
|
'''
|
|||
|
|
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout
|
|||
|
|
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
|
|||
|
|
import matplotlib.pyplot as plt
|
|||
|
|
import sys
|
|||
|
|
|
|||
|
|
# 线条类型A
|
|||
|
|
class Target3DWidgetA(QWidget):
|
|||
|
|
def __init__(self, parent=None):
|
|||
|
|
super().__init__(parent)
|
|||
|
|
self.init_3d_plot()
|
|||
|
|
self.setLayout(QVBoxLayout())
|
|||
|
|
self.layout().addWidget(self.canvas)
|
|||
|
|
|
|||
|
|
def init_3d_plot(self):
|
|||
|
|
# 3D画布
|
|||
|
|
self.fig = plt.figure(figsize=(15, 6))
|
|||
|
|
self.canvas = FigureCanvas(self.fig)
|
|||
|
|
self.ax = self.fig.add_subplot(111, projection='3d')
|
|||
|
|
|
|||
|
|
# 绘制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. 轴范围(X轴设为0-60cm,Y/Z设为0-5cm)
|
|||
|
|
self.ax.set_xlim(0, 60)
|
|||
|
|
self.ax.set_ylim(0, 5)
|
|||
|
|
self.ax.set_zlim(0, 5)
|
|||
|
|
|
|||
|
|
# 2. 刻度间隔统一为1cm
|
|||
|
|
self.ax.set_xticks(range(0, 61, 5)) # X轴每5cm标一次刻度(避免太密集)
|
|||
|
|
self.ax.set_yticks(range(0, 6, 1)) # Y轴每1cm标一次刻度
|
|||
|
|
self.ax.set_zticks(range(0, 6, 1)) # Z轴每1cm标一次刻度
|
|||
|
|
|
|||
|
|
# 调整视角(适配X轴1cm刻度)
|
|||
|
|
self.ax.view_init(elev=20, azim=60)
|
|||
|
|
|
|||
|
|
def draw_target_shape(self):
|
|||
|
|
"""绘制3D结构"""
|
|||
|
|
vertices = [
|
|||
|
|
# 底部截面(Z=0平面)
|
|||
|
|
(0, 3, 0), (50, 3, 0),
|
|||
|
|
(50, 3, 0), (50, 0, 0),
|
|||
|
|
|
|||
|
|
# 中间截面(Z=0.5平面)
|
|||
|
|
(0, 0.5, 0.5), (0, 3, 0.5),
|
|||
|
|
(0, 3, 0.5), (50, 3, 0.5),
|
|||
|
|
(50, 3, 0.5), (50, 0.5, 0.5),
|
|||
|
|
(50, 0.5, 0.5), (0, 0.5, 0.5),
|
|||
|
|
|
|||
|
|
# 顶部界面(Z=2平面)
|
|||
|
|
(0, 0, 2), (0, 0.5, 2),
|
|||
|
|
(0, 0.5, 2), (50, 0.5, 2),
|
|||
|
|
(50, 0.5, 2), (50, 0, 2),
|
|||
|
|
(50, 0, 2), (0, 0, 2),
|
|||
|
|
|
|||
|
|
# z方向的连线
|
|||
|
|
(0, 3, 0.5), (0, 3, 0),
|
|||
|
|
(50, 3, 0.5), (50, 3, 0),
|
|||
|
|
(0, 0.5, 2), (0, 0.5, 0.5),
|
|||
|
|
(50, 0.5, 2), (50, 0.5, 0.5),
|
|||
|
|
(50, 0, 2), (50, 0, 0),
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# 绘制所有棱边
|
|||
|
|
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 = [
|
|||
|
|
("a", 50, 0, 1, 'red'),
|
|||
|
|
("b", 50, 1, 0, 'green'),
|
|||
|
|
("c", 50, 3, 0.25, 'blue'),
|
|||
|
|
("d", 25, 2, 0, 'magenta')
|
|||
|
|
]
|
|||
|
|
for text, x, y, z, color in annotations:
|
|||
|
|
self.ax.text(x, y, z, text, fontsize=14, color=color, weight='bold')
|
|||
|
|
|
|||
|
|
# 线条类型B
|
|||
|
|
class Target3DWidgetB(QWidget):
|
|||
|
|
def __init__(self, parent=None):
|
|||
|
|
super().__init__(parent)
|
|||
|
|
self.init_3d_plot()
|
|||
|
|
self.setLayout(QVBoxLayout())
|
|||
|
|
self.layout().addWidget(self.canvas)
|
|||
|
|
|
|||
|
|
def init_3d_plot(self):
|
|||
|
|
# 3D画布
|
|||
|
|
self.fig = plt.figure(figsize=(15, 6))
|
|||
|
|
self.canvas = FigureCanvas(self.fig)
|
|||
|
|
self.ax = self.fig.add_subplot(111, projection='3d')
|
|||
|
|
|
|||
|
|
# 绘制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. 轴范围(X轴设为0-60cm,Y/Z设为0-5cm)
|
|||
|
|
self.ax.set_xlim(0, 60)
|
|||
|
|
self.ax.set_ylim(0, 5)
|
|||
|
|
self.ax.set_zlim(0, 5)
|
|||
|
|
|
|||
|
|
# 2. 刻度间隔统一为1cm
|
|||
|
|
self.ax.set_xticks(range(0, 61, 5)) # X轴每5cm标一次刻度(避免太密集)
|
|||
|
|
self.ax.set_yticks(range(0, 6, 1)) # Y轴每1cm标一次刻度
|
|||
|
|
self.ax.set_zticks(range(0, 6, 1)) # Z轴每1cm标一次刻度
|
|||
|
|
|
|||
|
|
# 调整视角(适配X轴1cm刻度)
|
|||
|
|
self.ax.view_init(elev=20, azim=60)
|
|||
|
|
|
|||
|
|
def draw_target_shape(self):
|
|||
|
|
"""绘制3D结构"""
|
|||
|
|
vertices = [
|
|||
|
|
# 底部截面(Z=0平面)
|
|||
|
|
(0, 3, 0), (50, 3, 0),
|
|||
|
|
(50, 3, 0), (50, 0, 0),
|
|||
|
|
|
|||
|
|
# 中间截面(Z=0.5平面)
|
|||
|
|
(0, 0.5, 0.5), (0, 2.5, 0.5),
|
|||
|
|
(50, 2.5, 0.5), (50, 0.5, 0.5),
|
|||
|
|
(50, 0.5, 0.5), (0, 0.5, 0.5),
|
|||
|
|
|
|||
|
|
# 中间截面(Z=1平面)
|
|||
|
|
(0, 2.5, 1),(0, 3, 1),
|
|||
|
|
(0, 3, 1), (50, 3, 1),
|
|||
|
|
(50, 3, 1), (50, 2.5, 1),
|
|||
|
|
(50, 2.5, 1), (0, 2.5, 1),
|
|||
|
|
|
|||
|
|
# 顶部界面(Z=2平面)
|
|||
|
|
(0, 0, 2), (0, 0.5, 2),
|
|||
|
|
(0, 0.5, 2), (50, 0.5, 2),
|
|||
|
|
(50, 0.5, 2), (50, 0, 2),
|
|||
|
|
(50, 0, 2), (0, 0, 2),
|
|||
|
|
|
|||
|
|
# z方向的连线
|
|||
|
|
(0, 3, 1), (0, 3, 0),
|
|||
|
|
(50, 3, 1), (50, 3, 0),
|
|||
|
|
(0, 0.5, 2), (0, 0.5, 0.5),
|
|||
|
|
(50, 0.5, 2), (50, 0.5, 0.5),
|
|||
|
|
(50, 0, 2), (50, 0, 0),
|
|||
|
|
(0, 2.5, 1),(0, 2.5, 0.5),
|
|||
|
|
(50, 2.5, 1),(50, 2.5, 0.5)
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# 绘制所有棱边
|
|||
|
|
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 = [
|
|||
|
|
("a", 50, 0, 1, 'red'),
|
|||
|
|
("b", 50, 1, 0, 'green'),
|
|||
|
|
("c", 50, 3, 0.5, 'blue'),
|
|||
|
|
("d", 25, 2, 0, 'magenta')
|
|||
|
|
]
|
|||
|
|
for text, x, y, z, color in annotations:
|
|||
|
|
self.ax.text(x, y, z, text, fontsize=14, color=color, weight='bold')
|
|||
|
|
|
|||
|
|
|
|||
|
|
class MainWindowA(QMainWindow):
|
|||
|
|
def __init__(self):
|
|||
|
|
super().__init__()
|
|||
|
|
self.setWindowTitle("3D视图(X/Y/Z单位:1cm)")
|
|||
|
|
self.setGeometry(100, 100, 1200, 700) # 加宽窗口,适配X轴1cm刻度
|
|||
|
|
self.setCentralWidget(Target3DWidgetA())
|
|||
|
|
|
|||
|
|
class MainWindowB(QMainWindow):
|
|||
|
|
def __init__(self):
|
|||
|
|
super().__init__()
|
|||
|
|
self.setWindowTitle("3D视图(X/Y/Z单位:1cm)")
|
|||
|
|
self.setGeometry(100, 100, 1200, 700) # 加宽窗口,适配X轴1cm刻度
|
|||
|
|
self.setCentralWidget(Target3DWidgetB())
|
|||
|
|
|
|||
|
|
def ui_3d_a():
|
|||
|
|
app = QApplication(sys.argv)
|
|||
|
|
window = MainWindowA()
|
|||
|
|
window.show()
|
|||
|
|
sys.exit(app.exec())
|
|||
|
|
|
|||
|
|
def ui_3d_b():
|
|||
|
|
app = QApplication(sys.argv)
|
|||
|
|
window = MainWindowB()
|
|||
|
|
window.show()
|
|||
|
|
sys.exit(app.exec())
|
|||
|
|
|
|||
|
|
# ----------测试接口----------
|
|||
|
|
if __name__ == '__main__':
|
|||
|
|
ui_3d_a()
|
|||
|
|
# ui_3d_b()
|
|||
|
|
|