# -*- coding: utf-8 -*- import sys from PySide6.QtWidgets import QApplication, QMainWindow, QGraphicsView, QFileDialog, QColorDialog from PySide6.QtUiTools import QUiLoader from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar from matplotlib.figure import Figure import matplotlib.pyplot as plt from PySide6.QtWidgets import QVBoxLayout import creat_3d import numpy as np import matplotlib as mpl from matplotlib.path import Path from matplotlib.patches import Patch from PySide6.QtGui import QPalette import random from scipy.spatial import ConvexHull # plt.legend(prop={'family': 'SimHei', 'size': 15}) from mpl_toolkits.mplot3d.art3d import Poly3DCollection class MainWindow(QMainWindow): def __init__(self): super().__init__() self.toolbar = None self.canvas = None self.file_paths = [] self.get_color = lambda n: list(map(lambda i: "#" + "%06x" % random.randint(0, 0xFFFFFF),range(n))) self.len_color = ['k','k'] # 图例颜色选择值 self.sho_color = ['k','k'] self.ove_color = ['b','b'] self.colorbar = 'jet' # self.num = len(self.color) # 记录选择颜色的次数 self.oilwell_color = 'k' self.waterwell_color = 'k' self.chose = 0 self.len_num, self.short_num, self.over_num = 0,0,0 self.box = 0 self.axes = 0 self.angle_axes = 0 self.length_axes = 0 self.datachange = 0 self.wellchange = 0 self.waterwell_chose=0 self.oilwell_chose=0 self.scatter = 0 self.all_axes = 0 self.len_axes_r, self.sho_axes_r,self.ver_axes_up=0,0,0 self.axes_size = 8 self.len_view=0 self.short_view=0 self.over_view=0 # 加载UI文件 self.ui = QUiLoader().load('QT/3d_plot_2.ui') self.color_bar() self.ui.colorbar_chose.currentTextChanged.connect(self.update_colorbar) # 更新colorbar self.ui.chose_oilwell_color.clicked.connect(lambda: self.oil_well_color()) # 选择油井颜色 self.ui.chose_oilwell_color.clicked.connect(lambda: self.plot_density()) # 更新油井颜色 self.ui.chose_waterwell_color.clicked.connect(lambda: self.water_well_color()) # 选择水井颜色 self.ui.chose_waterwell_color.clicked.connect(lambda: self.plot_density()) # 更新水井颜色 # 更新图窗 self.ui.graphicsView.repaint() self.ui.graphicsView.update() self.graphics_layout = QVBoxLayout(self.ui.graphicsView) self.ui.chose_datafile_button.clicked.connect(self.choose_datafile) self.ui.chose_wellfile_button.clicked.connect(self.choose_wellfile) self.ui.data_file_lineEdit.textChanged.connect(lambda: self.data_change()) self.ui.well_file_lineEdit.textChanged.connect(lambda: self.well_change()) # 绘制或清除数据和画布 self.ui.clear_data.clicked.connect(lambda: self.clear_data()) # 绘图设置中心比例 self.ui.center_scale.clicked.connect(lambda: self.center_scale()) self.ui.center_scale.clicked.connect(lambda: self.plot_density()) self.ui.level_chose.valueChanged.connect(lambda: self.plot_density()) # self.ui.gWeight_chose.valueChanged.connect(lambda: self.plot_density()) # 绘制bounding——box self.ui.pushButton.clicked.connect(lambda: self.bounding_box()) # self.ui.pushButton_2.clicked.connect(lambda: self.Axes()) self.ui.pushButton_3.clicked.connect(lambda: self.axes_angles()) self.ui.axes_length.clicked.connect(lambda: self.axes_length()) self.ui.scatter_density.clicked.connect(lambda: self.scatter_density()) self.ui.all_axes.clicked.connect(lambda: self.all_axes_plot()) self.ui.axes_wordsize.valueChanged.connect(lambda: self.plot_density()) self.ui.len_view.clicked.connect(lambda: self._len_view()) self.ui.short_view.clicked.connect(lambda: self._short_view()) self.ui.over_view.clicked.connect(lambda: self._over_view()) self.ui.len_axes.clicked.connect(lambda: self._len_axes()) self.ui.short_axes.clicked.connect(lambda: self._short_axes()) self.ui.over_axes.clicked.connect(lambda: self._over_axes()) self.ui.len_color.clicked.connect(self.len_color_chose) # 选择长轴颜色 self.ui.short_color.clicked.connect(self.sho_color_chose) # 选择长轴颜色 self.ui.over_color.clicked.connect(self.ove_color_chose) # 选择长轴颜色 def _len_axes(self): if self.len_axes_r==0: self.len_axes_r = 1 else: self.len_axes_r=0 self.plot_density() def _short_axes(self): if self.sho_axes_r==0: self.sho_axes_r=1 else: self.sho_axes_r=0 self.plot_density() def _over_axes(self): if self.ver_axes_up==0: self.ver_axes_up=1 else: self.ver_axes_up=0 self.plot_density() def _len_view(self): if self.len_view==0: self.len_view=1 self.over_view = 0 self.short_view = 0 else: self.len_view=0 self.plot_density() def _short_view(self): if self.short_view==0: self.short_view=1 self.over_view = 0 self.len_view = 0 else: self.short_view=0 self.plot_density() def _over_view(self): if self.over_view == 0: self.over_view = 1 self.len_view = 0 self.short_view = 0 else: self.over_view = 0 self.plot_density() def all_axes_plot(self): if self.all_axes==0: self.all_axes=1 else: self.all_axes=0 self.plot_density() def scatter_density(self): if self.scatter==0: self.scatter=1 else: self.scatter=0 self.plot_density() def data_change(self): if self.datachange == 1: self.plot_density() self.dat_c = 0 def well_change(self): if self.wellchange == 1: self.waterwell_chose=1 self.oilwell_chose=1 self.plot_density() self.well_c = 0 def bounding_box(self): if self.box == 0: self.box = 1 else: self.box = 0 self.plot_density() def Axes(self): if self.axes==0: self.axes=1 else: self.axes=0 self.plot_density() def axes_angles(self): if self.waterwell_chose==0: self.waterwell_chose=1 else: self.waterwell_chose=0 self.plot_density() def axes_length(self): if self.length_axes==0: self.length_axes=1 else: self.length_axes=0 self.plot_density() def self_levels(self): self.levels = self.ui.level_chose.value() # 选择层参数 self.plot_density() def self_gWeight(self): self.gWeight = self.self.ui.gWeight_chose.value() self.plot_density() def scene_fig(self): fig = Figure() # 在Figure对象中添加子图 ax = fig.add_subplot(111) return fig, ax def canvas_adjust(self, fig): if self.canvas is not None: # 从布局中删除旧的 canvas 和 toolbar item = self.graphics_layout.takeAt(0) while item: widget = item.widget() if widget: widget.setParent(None) item = self.graphics_layout.takeAt(0) self.graphics_layout.removeWidget(self.canvas) self.canvas = FigureCanvas(fig) self.toolbar = NavigationToolbar(self.canvas, self.ui.graphicsView) self.toolbar.setParent(self.canvas) self.graphics_layout.addWidget(self.canvas) self.adjustSize() def choose_datafile(self): self.datachange = 0 file_dialog = QFileDialog(self) file_dialog.setFileMode(QFileDialog.ExistingFiles) if file_dialog.exec(): self.file_paths += file_dialog.selectedFiles() self.ui.data_file_lineEdit.setText(','.join(self.file_paths)) self.plot_density() def choose_wellfile(self): self.wellchange=0 self.waterwell_chose=1 self.oilwell_chose=1 file_dialog = QFileDialog(self) file_dialog.setFileMode(QFileDialog.ExistingFiles) if file_dialog.exec(): file_paths = file_dialog.selectedFiles() self.ui.well_file_lineEdit.setText(','.join(file_paths)) self.plot_density() def len_color_chose(self): col = QColorDialog.getColor() self.len_color[self.len_num] = col.name() self.len_num += 1 self.plot_density() def sho_color_chose(self): col = QColorDialog.getColor() self.sho_color[self.short_num] = col.name() self.short_num += 1 self.plot_density() def ove_color_chose(self): col = QColorDialog.getColor() self.ove_color[self.over_num] = col.name() self.over_num += 1 self.plot_density() def oil_well_color(self): col = QColorDialog.getColor() self.oilwell_color = col.name() def water_well_color(self): col = QColorDialog.getColor() self.waterwell_color = col.name() def color_bar(self): self.ui.colorbar_chose.addItem("jet") self.ui.colorbar_chose.addItem("viridis") self.ui.colorbar_chose.addItem("coolwarm") self.ui.colorbar_chose.addItem('plasma') self.ui.colorbar_chose.addItem("magma") self.ui.colorbar_chose.addItem("inferno") def update_colorbar(self): colorbar_name = self.ui.colorbar_chose.currentText() self.colorbar = plt.get_cmap(colorbar_name) self.plot_density() def clear_data(self): self.file_paths = [] self.len_color = ['k', 'k'] self.sho_color = ['k', 'k'] self.ove_color = ['b', 'b'] self.len_num, self.short_num, self.over_num = 0, 0, 0 self.chose = 0 self.box = 0 self.axes = 0 self.waterwell_chose = 0 self.oilwell_chose = 0 self.length_axes = 0 self.datachange = 0 self.wellchange = 0 self.scatter = 0 self.all_axes = 0 self.len_axes_r, self.sho_axes_r, self.ver_axes_up = 0, 0, 0 self.axes_size = 8 self.len_view = 0 self.short_view = 0 self.over_view = 0 self.ui.data_file_lineEdit.clear() self.ui.well_file_lineEdit.clear() self.canvas.figure.clf() # 清除画布上的内容 self.canvas.draw() def center_scale(self): if self.oilwell_chose == 0: self.oilwell_chose = 1 else: self.oilwell_chose = 0 # self.num = 0 def plot_density(self): fig, ax = self.scene_fig() data_name = self.ui.data_file_lineEdit.text().split(',') # 文件输入 =================1 level = self.ui.level_chose.value() # 层参数 =================2 self.datachange=1 data = creat_3d.create() legend_elements = [] if self.len_num == 2: self.len_num = 0 if self.short_num ==2: self.short_num = 0 if self.over_num==2: self.over_num=0 for i in range(len(data_name)): data.data_pre(data_name[i]) data.contours_pre(level) vertices = data.vertices faces = data.faces """画出密度等高线""" # 绘制等值面 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') if self.scatter == 1: vertices = data.data x = data.data[:, 0] y = data.data[:, 1] z = data.data[:, 2] ax.scatter(x, y, z, s=5, alpha=0.5) else: ax.plot_trisurf(vertices[:, 0], vertices[:, 1], faces, vertices[:, 2], cmap=self.colorbar, alpha=0.4, edgecolor='none') # 添加三维网格对象填充曲面内部 mesh = Poly3DCollection(vertices[faces], alpha=0.2, cmap=self.colorbar) ax.add_collection3d(mesh) ax.set_xlim(vertices[:, 0].min()-100, vertices[:, 0].max()+100) ax.set_ylim(vertices[:, 1].min() - 100, vertices[:, 1].max() + 100) ax.set_zlim(vertices[:, 2].min() - 100, vertices[:, 2].max() + 100) # 设置坐标轴标签 ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.grid(None) # self.OBB_3dbox(vertices, ax) wells_name = self.ui.well_file_lineEdit.text() # 井文件输入 =================6 if wells_name == '': z_value = vertices[:, 2].min()/2+vertices[:, 2].max()/2 self.OBB_3dbox(vertices, ax, z_value) print('ax.azim {}'.format(ax.azim)) print('ax.elev {}'.format(ax.elev)) self.canvas_adjust(fig) else: wells = creat_3d.well_to_edge() wells.wells_name_and_position(wells_name) self.wellchange = 1 """画井位信息""" typee = wells.type points = wells.position namee = wells.name for i in range(len(points)): if typee[i][0] == 0 and self.oilwell_chose==1: # oil_color = 'black' # 输入油井颜色选择 =================8 ax.scatter(points[i][0], points[i][1], points[i][2], marker='o', edgecolors=self.oilwell_color, facecolors='none', s=70) ax.scatter(points[i][0], points[i][1], points[i][2], marker='o', edgecolors=self.oilwell_color, facecolors='none', s=40, linewidths=0.5) ax.scatter(points[i][0], points[i][1], points[i][2], marker='o', edgecolors=self.oilwell_color, facecolors='none', s=20) ax.plot([points[i][0], points[i][0]], [points[i][1], points[i][1]], [points[i][2], points[i][2] - 100], color='r') ax.text(points[i][0], points[i][1], points[i][2] - 100, f'{namee[i][0]}', fontdict={'size': '8', 'color': 'b'}, zorder=len(data_name) + 2) # 井名信息 elif typee[i][0]==1: if self.waterwell_chose == 1: ax.scatter(points[i][0], points[i][1], points[i][2], marker='o', edgecolors=self.waterwell_color, facecolors=self.waterwell_color, s=70, zorder=len(data_name)+1) ax.plot([points[i][0],points[i][0]],[points[i][1],points[i][1]],[points[i][2],points[i][2]-100], color='r') ax.text(points[i][0], points[i][1], points[i][2] -100, f'{namee[i][0]}', fontdict={'size': '8', 'color': 'b'}, zorder=len(data_name) + 2) # 井名信息 continue self.OBB_3dbox(vertices, ax, points[i][2]) self.canvas_adjust(fig) def OBB_3dbox(self, points, ax, z_value): """ 计算三维数据点的OBB最小包围盒 参数: points: 三维数据点数组,形状为(N, 3) 返回: obb_center: OBB包围盒中心点,形状为(3,) obb_axes: OBB包围盒坐标轴,形状为(3, 3) obb_extents: OBB包围盒各坐标轴的长度,形状为(3,) """ # 计算凸包 hull = ConvexHull(points) hull_points = points[hull.vertices, :] # 计算凸包的质心 hull_center = np.mean(hull_points, axis=0) # 计算凸包的协方差矩阵 hull_cov = np.cov(hull_points, rowvar=False) # 对协方差矩阵进行SVD分解 u, s, vt = np.linalg.svd(hull_cov) # 计算OBB包围盒的坐标轴和长度 axes = vt.T # 将点云变换到以重心为原点的坐标系下 transformed_points = np.dot(points, vt) # x,y,z = transformed_points[:,0],transformed_points[:,1],transformed_points[:,2] x, y, z = points[:, 0], points[:, 1], points[:, 2] # 计算变换后的点云的最小包围盒 min_point = np.min(transformed_points, axis=0) max_point = np.max(transformed_points, axis=0) x_max, y_max, z_max = max_point[0], max_point[1], max_point[2] x_min, y_min, z_min = min_point[0], min_point[1], min_point[2] x_length = x_max - x_min y_length = y_max - y_min z_length = z_max - z_min extents = [x_length, y_length, z_length] center_new = min_point/2+max_point/2 # 新坐标轴下中心点坐标 center = np.dot(center_new, axes) # 八个顶点坐标 vertices = np.array([ [x_min, y_min, z_min], [x_max, y_min, z_min], [x_max, y_max, z_min], [x_min, y_max, z_min], [x_min, y_min, z_max], [x_max, y_min, z_max], [x_max, y_max, z_max], [x_min, y_max, z_max] ]) vertices = np.dot(vertices, axes) # 计算所有棱的端点坐标 ed_1 = [0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3] ed_2 = [1, 2, 3, 0, 5, 6, 7, 4, 4, 5, 6, 7] if self.box==1: for i, j in zip(np.array(ed_1), np.array(ed_2)): ax.plot([vertices[i][0], vertices[j][0]], [vertices[i][1], vertices[j][1]], zs=[vertices[i][2], vertices[j][2]], color='grey') self.plot_axes(ax, axes, vertices, z_value) return center, axes, extents def plot_axes(self, ax, axes, vertices, z): # 标注轴向 direct1 = vertices[0] - vertices[1] direct2 = vertices[2] - vertices[1] direct3= vertices[4] - vertices[0] ang_1 = np.arccos(np.dot(direct1, np.array(([1, 0, 0]))) / np.linalg.norm(direct1)) / np.pi * 180 ang_2 = np.arccos(np.dot(direct2, np.array(([0, 1, 0]))) / np.linalg.norm(direct2)) / np.pi * 180 ang_3 = np.arccos(np.dot(direct3, np.array(([0, 0, 1]))) / np.linalg.norm(direct3)) / np.pi * 180 if self.over_view==1: ax.view_init(elev=90, azim=90) # 俯视图 print(np.dot(direct1,direct2), ang_1, ang_2, ang_3) # 标注长短轴 if np.linalg.norm(vertices[0] - vertices[1]) >= np.linalg.norm(vertices[1] - vertices[2]): label1 = '长轴' label2 = '短轴' # 垂直长轴方向 if self.len_view==1: if vertices[0][0] > 0: ax.view_init(elev=ang_3, azim=90 - ang_2) else: ax.view_init(elev=ang_3, azim=90 - ang_1) # # 垂直短轴方向 if self.short_view==1: if vertices[0][0] > 0: ax.view_init(elev=ang_3, azim=ang_1+180) else: ax.view_init(elev=ang_3, azim=ang_2+180) else: label1 = '短轴' label2 = '长轴' # 垂直长轴方向 if self.len_view==1: if vertices[0][0] > 0: ax.view_init(elev=ang_3, azim=360-ang_1) else: ax.view_init(elev=ang_3, azim=360-ang_2) # # 垂直短轴方向 if self.short_view==1: if vertices[0][0] > 0: ax.view_init(elev=ang_3, azim=270 - ang_1) else: ax.view_init(elev=ang_3, azim=270 - ang_2) # 画长短轴 center = [0, 0, z] if (self.all_axes == 1 or self.len_axes_r==1) and label1 == '长轴': ax.quiver(*center, *np.dot(axes[0],vertices[0]-center)*axes[0] ,color=self.len_color[0], length=1, arrow_length_ratio=0.01) ax.quiver(*center, *np.dot(axes[0], vertices[2]-center) * axes[0], color=self.len_color[1], length=1, arrow_length_ratio=0.01) elif (self.all_axes == 1 or self.len_axes_r==1) and label2 == '长轴': ax.quiver(*center, *np.dot(axes[1], vertices[1]-center) * axes[1], color=self.len_color[0], length=1, arrow_length_ratio=0.01) ax.quiver(*center, *np.dot(axes[1], vertices[3]-center) * axes[1], color=self.len_color[1], length=1, arrow_length_ratio=0.01) if (self.all_axes == 1 or self.sho_axes_r==1) and label1 == '短轴': ax.quiver(*center, *np.dot(axes[0], vertices[0] - center) * axes[0] , color=self.sho_color[0], length=1, arrow_length_ratio=0.01) ax.quiver(*center, *np.dot(axes[0], vertices[2] - center) * axes[0], color=self.sho_color[1], length=1, arrow_length_ratio=0.01) elif (self.all_axes == 1 or self.sho_axes_r==1) and label2 == '短轴': ax.quiver(*center, *np.dot(axes[1], vertices[1] - center) * axes[1], color=self.sho_color[0], length=1, arrow_length_ratio=0.01) ax.quiver(*center, *np.dot(axes[1], vertices[3] - center) * axes[1], color=self.sho_color[1], length=1, arrow_length_ratio=0.01) if self.all_axes == 1 or self.ver_axes_up == 1: ax.quiver(*center, *axes[2] * np.dot(axes[2], vertices[4] - center), color=self.ove_color[0], length=1, arrow_length_ratio=0.01) ax.quiver(*center, *axes[2] * np.dot(axes[2], vertices[0] - center), color=self.ove_color[1], length=1, arrow_length_ratio=0.01) if self.length_axes == 1: len_1 = np.abs(np.dot(axes[0], vertices[0]-center)) len_2 = np.abs(np.dot(axes[0], vertices[2]-center)) len_3 = np.abs(np.dot(axes[1], vertices[1]-center)) len_4 = np.abs(np.dot(axes[1], vertices[3]-center)) if vertices[0][0]-vertices[1][0] >= 0: lb1 = '右半轴长' lb2 = '左半轴长' l1 = 3/4 l2 = 6/5 else: lb1 = '左半轴长' lb2 = '右半轴长' l1 = 6 / 5 l2 = 3 / 4 if vertices[2][0]-vertices[1][0] >= 0: lb3 = '右半轴长' lb4 = '左半轴长' l3 = 3 / 4 l4 = 6 / 5 else: lb3 = '左半轴长' lb4 = '右半轴长' l3 = 6 / 5 l4 = 3 / 4 lz = 1 if ang_1<=90: rota1=-ang_1 else: rota1=180-ang_1 if ang_2<=90: rota2=ang_2 else: rota2=180-ang_2 word_size = self.ui.axes_wordsize.value() if (self.all_axes == 1 or self.len_axes_r == 1) and label1 == '长轴': ax.text(center[0] + l1 * (vertices[0][0] / 2 - vertices[1][0] / 2), center[1] + l1 * (vertices[0][1] / 2 - vertices[1][1] / 2), center[2] + lz * (vertices[0][2] / 2 - vertices[1][2] / 2), label1+lb1 + f'{round(len_1,2)}m', fontdict={'size': word_size, 'color': self.len_color[0], 'family': 'SimHei'}, rotation=rota1) # 标出距离 ax.text(center[0]+l2*(-vertices[0][0] / 2 + vertices[1][0] / 2), center[1] + l2*(-vertices[0][1] / 2 + vertices[1][1] / 2), center[2] + lz * (-vertices[0][2] / 2 + vertices[1][2] / 2), label1+ lb2 + f'{round(len_2, 2)}m', fontdict={'size': word_size, 'color': self.len_color[1], 'family': 'SimHei'}, rotation=rota1) # 标出距离 elif (self.all_axes == 1 or self.len_axes_r == 1) and label2 == '长轴': ax.text(center[0] + l3 * (vertices[2][0] / 2 - vertices[1][0] / 2), center[1] + l3 * (vertices[2][1] / 2 - vertices[1][1] / 2), center[2] + lz * (vertices[2][2] / 2 - vertices[1][2] / 2), label2+lb3 + f'{round(len_4, 2)}m', fontdict={'size': word_size, 'color': self.len_color[1], 'family': 'SimHei'}, rotation=rota2) # 标出距离 ax.text(center[0] + l4 * (-vertices[2][0] / 2 + vertices[1][0] / 2), center[1] + l4 * (-vertices[2][1] / 2 + vertices[1][1] / 2), center[2] + lz * (-vertices[2][2] / 2 + vertices[1][2] / 2), label2 + lb4 + f'{round(len_3, 2)}m', fontdict={'size': word_size, 'color': self.len_color[0], 'family': 'SimHei'}, rotation=rota2) # 标出距离 if (self.all_axes == 1 or self.sho_axes_r == 1) and label1 == '短轴': ax.text(center[0] + l1 * (vertices[0][0] / 2 - vertices[1][0] / 2), center[1] + l1 * (vertices[0][1] / 2 - vertices[1][1] / 2), center[2] + lz * (vertices[0][2] / 2 - vertices[1][2] / 2), label1 + lb1 + f'{round(len_1, 2)}m', fontdict={'size': word_size, 'color': self.sho_color[0], 'family': 'SimHei'}, rotation=rota1) # 标出距离 ax.text(center[0] + l2 * (-vertices[0][0] / 2 + vertices[1][0] / 2), center[1] + l2 * (-vertices[0][1] / 2 + vertices[1][1] / 2), center[2] + lz * (-vertices[0][2] / 2 + vertices[1][2] / 2), label1 + lb2 + f'{round(len_2, 2)}m', fontdict={'size': word_size, 'color': self.sho_color[1], 'family': 'SimHei'}, rotation=rota1) # 标出距离 elif (self.all_axes == 1 or self.sho_axes_r == 1) and label2 == '短轴': ax.text(center[0] + l3 * (vertices[2][0] / 2 - vertices[1][0] / 2), center[1] + l3 * (vertices[2][1] / 2 - vertices[1][1] / 2), center[2] + lz * (vertices[2][2] / 2 - vertices[1][2] / 2), label2 + lb3 + f'{round(len_3, 2)}m', fontdict={'size': word_size, 'color': self.sho_color[0], 'family': 'SimHei'}, rotation=rota2) # 标出距离 ax.text(center[0] + l4 * (-vertices[2][0] / 2 + vertices[1][0] / 2), center[1] + l4 * (-vertices[2][1] / 2 + vertices[1][1] / 2), center[2] + lz * (-vertices[2][2] / 2 + vertices[1][2] / 2), label2 + lb4 + f'{round(len_4, 2)}m', fontdict={'size': word_size, 'color': self.sho_color[1], 'family': 'SimHei'}, rotation=rota2) # 标出距离 len_5 = np.abs(np.dot(axes[2], vertices[4]-center)) len_6 = np.abs(np.dot(axes[2], vertices[0]-center)) if self.all_axes == 1 or self.ver_axes_up == 1: ax.text(center[0] + 6 / 5 * (vertices[4][0] / 2 - vertices[0][0] / 2), center[1] + 6 / 5 * (vertices[4][1] / 2 - vertices[0][1] / 2), center[2] + 6 / 5 * (vertices[4][2] / 2 - vertices[0][2] / 2), '纵轴' + '上半轴' + f'{round(len_5, 2)}m', fontdict={'size': word_size, 'color': self.ove_color[0], 'family': 'SimHei'}, rotation=rota2) # 标出距离 ax.text(center[0] + 6 / 5 * (-vertices[4][0] / 2 + vertices[0][0] / 2), center[1] + 6 / 5 * (-vertices[4][1] / 2 + vertices[0][1] / 2), center[2] + 6 / 5 * (-vertices[4][2] / 2 + vertices[0][2] / 2), '纵轴下半轴' + f'{round(len_6, 2)}m', fontdict={'size': word_size, 'color': self.ove_color[1], 'family': 'SimHei'}, rotation=rota2) # 标出距离 if __name__ == '__main__': app = QApplication([]) stats = MainWindow() stats.ui.show() app.exec()