master
冯冬卫 1 year ago
parent 1b8018496d
commit 419bd20092

@ -1 +1 @@
main_2.py
creat_3d.py

@ -0,0 +1,639 @@
# -*- 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=0) # 俯视图
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()

@ -0,0 +1,385 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>790</width>
<height>757</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="data_file_lineEdit">
<property name="placeholderText">
<string>请导入数据文件</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="chose_datafile_button">
<property name="text">
<string>选择文件</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="well_file_lineEdit">
<property name="placeholderText">
<string>请导入井文件</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="chose_wellfile_button">
<property name="text">
<string>选择文件</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>levels:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="level_chose">
<property name="decimals">
<number>4</number>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QComboBox" name="colorbar_chose">
<property name="placeholderText">
<string>colorbar选择</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>包围盒</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="all_axes">
<property name="text">
<string>轴</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_12">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>轴字体</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="axes_wordsize">
<property name="value">
<number>8</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="axes_length">
<property name="text">
<string>轴长</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="scatter_density">
<property name="text">
<string>密度图/散点图</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="len_axes">
<property name="text">
<string>长轴</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="len_color">
<property name="text">
<string>长轴颜色</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="short_axes">
<property name="text">
<string>短轴</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="short_color">
<property name="text">
<string>短轴颜色</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="over_axes">
<property name="text">
<string>纵轴</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="over_color">
<property name="text">
<string>纵轴颜色</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="chose_oilwell_color">
<property name="text">
<string>油井颜色选择</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="chose_waterwell_color">
<property name="text">
<string>水井颜色选择</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>显示水井</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="center_scale">
<property name="text">
<string>显示油井</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="len_view">
<property name="text">
<string>长轴视图</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="short_view">
<property name="text">
<string>短轴视图</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="over_view">
<property name="text">
<string>俯视图</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clear_data">
<property name="text">
<string>清除数据</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGraphicsView" name="graphicsView"/>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

@ -0,0 +1,105 @@
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
from scipy.spatial.distance import cdist
import copy
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from matplotlib.colors import Normalize
import numpy as np
from skimage import measure
import matplotlib.cm as cm
class create():
def __init__(self):
"""
data is the x and y coordinate of data.pos
contours is the edge points
f is the kernel density value
levels is the levels for contours
x_range is the range of x label
y_range is the range of y label
"""
self.data = []
self.vertices = []
self.faces = []
self.levels = []
self.x_range = []
self.y_range = []
def data_pre(self, data_name):
with open(data_name, 'r') as f:
lines = f.readlines()
L_en=len(lines)
lines= lines[1:L_en]
data = []
for line in lines:
x, y,z,t = line.strip().split("\t")
data.append(list(map(float, [x,y,z])))
data = np.array(data)
self.data = data
self.x_range = [min(data[:, 0]), max(data[:,0])]
self.y_range = [min(data[:, 1]), max(data[:,1])]
self.z_range = [min(data[:, 2]), max(data[:,2])]
def contours_pre(self, level):
x = self.data[:, 0]
y = self.data[:, 1]
z = self.data[:, 2]
# 使用scipy库中的gaussian_kde函数计算密度估计
k = gaussian_kde(self.data.T)
xi, yi, zi = np.mgrid[x.min()*1.5:x.max()*1.5:30j, y.min()*1.5:y.max()*1.5:30j, z.min()-50:z.max()+50:50j]
density = k(np.vstack([xi.flatten(), yi.flatten(), zi.flatten()]))
self.density =density
level = density.max()*level/100
# 使用 marching_cubes 生成等值面顶点和面
verts, faces, _, _ = measure.marching_cubes(density.reshape(xi.shape), level=level)
a_0 = (x.max() - x.min()) / (verts[:, 0].max() - verts[:, 0].min())
vertices_0 = (verts[:, 0] - verts[:, 0].min()) * a_0 + x.min()-5
a_1 = (y.max() - y.min()+10) / (verts[:, 1].max() - verts[:, 1].min())
vertices_1 = (verts[:, 1] - verts[:, 1].min()) * a_1 + y.min()-5
a_2 = (z.max() - z.min()+10) / (verts[:, 2].max() - verts[:, 2].min())
vertices_2 = (verts[:, 2] - verts[:, 2].min()) * a_2 + z.min()-5
vertices = np.array([vertices_0, vertices_1, vertices_2]).T
self.vertices = vertices
self.faces = faces
class well_to_edge():
def __init__(self):
"""
name is used to store the well names
type is the types of the wells
position is the coordinates of wells
min_distance is the minimum distances between wells and edge
welltoedge_points is the points responding to the min_distance
angle is the angles between the shortest distance direction vector from the well to the edge and the positive direction of the y-axis during clockwise rotation;
wells_num: the number of wells
"""
self.name = []
self.type = []
self.position = []
self.min_distance = []
self.welltoedge_points = []
self.angle = []
self.wells_num = 0
def wells_name_and_position(self, wells_name):
# 读取井位信息
with open(wells_name, 'r') as f_j:
j_ing = f_j.readlines()
points = []
typee = []
namee = []
for line in j_ing:
if ('0' or '1') in line:
name, x, y, z, type = line.strip().split("\t")
if name != 'name':
points.append(list(map(float, [x, y, z])))
typee.append(list(map(int, [type])))
namee.append(name.split('\n'))
self.position = points
self.name = namee
self.type = typee
self.wells_num = len(points)
Loading…
Cancel
Save