请问有没有人能帮忙看一下这个函数有什么问题,下面这个使用vtk,df是来自数据库里面的数据,tu_pict函数实现了按下'S'键删除线段的功能,但是为什么没有实现按下'G'键撤回上一次删除线段的功能,连generate_mesh_from_remaining_lines函数都没有调用。
class JkdWindow(QWidget):
def __init__(self):
super().__init__()
self.points = vtk.vtkPoints()
self.polydata = vtk.vtkPolyData()
self.extractEdges = vtk.vtkExtractEdges()
self.selectedLineId = -1
self.interactor = None
self.renderer = None
self.renderWindow = None
self.actor = None
self.sexComboBox1 = QComboBox() # 平台
self.df = None # 初始化 df 为 None
# 从数据库中读取'Bench'的数据并去重
bench_data = self.get_unique_bench_data_from_database() # 自定义函数,从数据库中获取'Bench'数据并去重
self.sexComboBox1.addItems(bench_data)
self.confirm_button = QPushButton("生成表格") # 确认按钮
self.confirm_button.clicked.connect(self.confirm_data) # 连接确认数据的槽函数
self.sct_button = QPushButton("显示点")
self.sct_button.clicked.connect(self.show_pict)
self.tu_button = QPushButton("生成图")
self.tu_button.clicked.connect(self.tu_pict)
# self.ti_button = QPushButton("生成体")
# self.ti_button.clicked.connect(self.ti_pict) #将线段生成体
# 创建布局
layout = QHBoxLayout()
input_layout = QVBoxLayout()
input_layout.addWidget(QLabel("选择平台:"))
input_layout.addWidget(self.sexComboBox1)
input_layout.addWidget(self.confirm_button)
input_layout.addWidget(self.sct_button)
input_layout.addWidget(self.tu_button)
# input_layout.addWidget(self.ti_button)
self.table_view = QTableView()
layout.addLayout(input_layout)
layout.addWidget(self.table_view)
self.setLayout(layout)
def get_unique_bench_data_from_database(self):
conn = pymssql.connect('DESKTOP-LLBGFK0', 'sa', '88108011', 'sjg')
cursor = conn.cursor()
sql_select = "SELECT DISTINCT Ct_ID FROM Table_1"
cursor.execute(sql_select)
bench_data = [str(row[0]) for row in cursor.fetchall()]
conn.close()
# bench_data.insert(0, "不选") # 将 "不选" 添加到平台数据列表的开头
return bench_data
def confirm_data(self): # 确认条件,得到符合条件的表格,不过如果是多个表格合并,当有表格与第一个表格中有相同列时,会将该列重命名添加后缀
#平台的内容
sebench = self.sexComboBox1.currentText()
connect = pymssql.connect('DESKTOP-LLBGFK0', 'sa', '88108011', 'sjg') # 服务器名,账户,密码,数据库名
if connect:
print("连接成功!")
cursor = connect.cursor()
sql_select = "select * from Table_1"
cursor.execute(sql_select) # 执行sql语句
results = cursor.fetchall() # 读取所有查询结果
#print(results)
connect.commit()
# 关闭数据库
connect.close()
# return connect
if not results:
QMessageBox.warning(self, '提示', '未导入数据或没有数据')
else:
k = []
for result in results: # 循环读取所有结果
if result[4] == sebench :
k.append(result)
if len(k) > 0:
data = {
'Hole_ID':[],
'E': [],
'N':[],
'Z':[],
'Ct_ID':[],
}
for result in k:
data['Hole_ID'].append(result[0])
data['E'].append(result[1])
data['N'].append(result[2])
data['Z'].append(result[3])
data['Ct_ID'].append(result[4])
self.df = pd.DataFrame(data)
# 有符合条件的数据
# print(k)
# df = pd.DataFrame(k, columns=['E'])
model = PandasModel(self.df)
self.table_view.setModel(model)
else:
# 没有符合条件的数据
QMessageBox.warning(self, "No Data", "No matching data found.")
def show_pict(self):
if hasattr(self, 'df'):
# 获取点的坐标
x = self.df['E']
y = self.df['N']
z = self.df['Z']
# 创建点集数据
points = vtk.vtkPoints()
for i in range(len(x)):
points.InsertNextPoint(x[i], y[i], z[i])
# 创建点的拓扑结构
vertices = vtk.vtkCellArray()
for i in range(len(x)):
vertices.InsertNextCell(1)
vertices.InsertCellPoint(i)
# 创建点集数据源
polydata = vtk.vtkPolyData()
polydata.SetPoints(points)
polydata.SetVerts(vertices)
# 创建点的图形表示
glyph = vtk.vtkGlyph3D()
glyph.SetInputData(polydata)
glyph.SetScaleFactor(2) # 设置点的大小
glyph.Update()
# 创建点的可视化
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(glyph.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
# 创建渲染器和窗口
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)
window = vtk.vtkRenderWindow()
window.AddRenderer(renderer)
# 创建交互器并显示窗口
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(window)
interactor.Initialize()
interactor.Start()
else:
QMessageBox.warning(self, "No Data", "No data to display.")
#主要看下面这段代码为什么出错。
def tu_pict(self):
if hasattr(self, 'df'):
# 从 DataFrame 中提取 x、y、z 轴坐标数据
x = self.df['E'].tolist()
y = self.df['N'].tolist()
z = self.df['Z'].tolist()
# 创建VTK点云数据
points = vtk.vtkPoints()
for i in range(len(x)):
points.InsertNextPoint(x[i], y[i], z[i])
polydata = vtk.vtkPolyData()
polydata.SetPoints(points)
# 使用vtkDelaunay3D进行三角化
delaunay = vtk.vtkDelaunay3D()
delaunay.SetInputData(polydata)
delaunay.Update()
# 获取三角化后的数据
triangulatedPolydata = delaunay.GetOutput()
# 提取边缘线段
extractEdges = vtk.vtkExtractEdges()
extractEdges.SetInputData(triangulatedPolydata)
extractEdges.Update()
# 创建点的可视化表示
vertexGlyphFilter = vtk.vtkVertexGlyphFilter()
vertexGlyphFilter.SetInputData(polydata)
vertexGlyphFilter.Update()
pointsMapper = vtk.vtkPolyDataMapper()
pointsMapper.SetInputConnection(vertexGlyphFilter.GetOutputPort())
pointsActor = vtk.vtkActor()
pointsActor.SetMapper(pointsMapper)
pointsActor.GetProperty().SetPointSize(3)
pointsActor.GetProperty().SetColor(1, 1, 1) # 设置点的颜色为白色
# 创建线段的可视化表示
edgesMapper = vtk.vtkPolyDataMapper()
edgesMapper.SetInputConnection(extractEdges.GetOutputPort())
edgesActor = vtk.vtkActor()
edgesActor.SetMapper(edgesMapper)
edgesActor.GetProperty().SetColor(1, 0, 0) # 设置线段的颜色为红色
# 创建渲染器和渲染窗口
renderer = vtk.vtkRenderer()
renderer.AddActor(pointsActor)
renderer.AddActor(edgesActor)
renderer.SetBackground(0, 0, 0)
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
renderWindow.SetSize(640, 480)
renderWindow.SetWindowName("2D Points and Edges Visualization")
# 创建交互器和交互器样式
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(renderWindow)
style = vtk.vtkInteractorStyleTrackballCamera()
interactor.SetInteractorStyle(style)
# 自定义回调函数,处理删除线段的逻辑
def deleteLine(obj, event):
# 获取按下的键值
key = interactor.GetKeySym()
if key == 's' or key == 'S':
# 获取点击坐标
clickPos = interactor.GetEventPosition()
# 创建Picker
picker = vtk.vtkCellPicker()
picker.SetTolerance(0.01)
picker.Pick(clickPos[0], clickPos[1], 0, renderer)
# 获取选中的单元格
cellId = picker.GetCellId()
# 检查是否选中了线段
if cellId >= 0:
# 删除选中的线段
extractEdges.GetOutput().DeleteCell(cellId)
extractEdges.GetOutput().RemoveDeletedCells()
# 更新渲染窗口
renderWindow.Render()
def generate_mesh_from_remaining_lines():
print('=======================================')
# 创建空的vtkPolyData用于存储剩余的线段
remainingLines = vtk.vtkPolyData()
# 创建线段的可视化表示
remainingEdgesMapper = vtk.vtkPolyDataMapper()
remainingEdgesMapper.SetInputData(remainingLines)
remainingEdgesActor = vtk.vtkActor()
remainingEdgesActor.SetMapper(remainingEdgesMapper)
remainingEdgesActor.GetProperty().SetColor(0, 1, 0) # 设置线段的颜色为绿色
# 创建渲染器和渲染窗口
remainingEdgesRenderer = vtk.vtkRenderer()
remainingEdgesRenderer.AddActor(remainingEdgesActor)
remainingEdgesRenderer.SetBackground(0, 0, 0)
remainingEdgesRenderWindow = vtk.vtkRenderWindow()
remainingEdgesRenderWindow.AddRenderer(remainingEdgesRenderer)
remainingEdgesRenderWindow.SetSize(640, 480)
remainingEdgesRenderWindow.SetWindowName("Generated Mesh Visualization")
# 创建交互器和交互器样式
remainingEdgesInteractor = vtk.vtkRenderWindowInteractor()
remainingEdgesInteractor.SetRenderWindow(remainingEdgesRenderWindow)
remainingEdgesStyle = vtk.vtkInteractorStyleTrackballCamera()
remainingEdgesInteractor.SetInteractorStyle(remainingEdgesStyle)
# 自定义回调函数,处理生成体的逻辑
def generateMesh(obj, event):
# 获取按下的键值
key = remainingEdgesInteractor.GetKeySym()
if key == 'g' or key == 'G':
# 使用vtkDelaunay3D进行三角化
delaunay = vtk.vtkDelaunay3D()
delaunay.SetInputData(remainingLines)
delaunay.Update()
# 获取三角化后的数据
triangulatedPolydata = delaunay.GetOutput()
# 创建体的可视化表示
meshMapper = vtk.vtkPolyDataMapper()
meshMapper.SetInputData(triangulatedPolydata)
meshActor = vtk.vtkActor()
meshActor.SetMapper(meshMapper)
meshActor.GetProperty().SetColor(0, 1, 0) # 设置体的颜色为绿色
# 添加体的Actor到渲染器中
renderer.AddActor(meshActor)
# 更新渲染窗口
renderWindow.Render()
# 将删除线段和生成体的回调函数与键盘事件关联
interactor.AddObserver("KeyPressEvent", deleteLine)
remainingEdgesInteractor.AddObserver("KeyPressEvent", generateMesh)
# 启动交互器
remainingEdgesInteractor.Initialize()
remainingEdgesInteractor.Start()
# 将删除线段的回调函数与键盘事件关联
interactor.AddObserver("KeyPressEvent", deleteLine)
# 启动交互器
interactor.Initialize()
interactor.Start()
else:
QMessageBox.warning(self, "No Data", "No data to display.")
参考gpt:
这段代码中没有实现按下'G'键撤回上一次删除线段的功能,也没有调用generate_mesh_from_remaining_lines函数的原因是因为在tu_pict函数中,定义了generate_mesh_from_remaining_lines函数,但并没有调用它。
要实现按下'G'键撤回删除操作的功能,可以在deleteLine函数中添加相应的逻辑来实现。在删除线段后,将被删除的线段存储起来,在按下'G'键时,将这些线段重新添加到remainingLines中,并更新渲染窗口。
另外,需要注意的是,在tu_pict函数中,generate_mesh_from_remaining_lines函数应该是类的方法,所以需要使用self.generate_mesh_from_remaining_lines来调用。同时,在tu_pict函数的最后,需要将交互器的样式更改为style,而不是remainingEdgesStyle。
以下是修改后的代码:
def tu_pict(self):
if hasattr(self, 'df'):
# 从 DataFrame 中提取 x、y、z 轴坐标数据
x = self.df['E'].tolist()
y = self.df['N'].tolist()
z = self.df['Z'].tolist()
# 创建VTK点云数据
points = vtk.vtkPoints()
for i in range(len(x)):
points.InsertNextPoint(x[i], y[i], z[i])
polydata = vtk.vtkPolyData()
polydata.SetPoints(points)
# 使用vtkDelaunay3D进行三角化
delaunay = vtk.vtkDelaunay3D()
delaunay.SetInputData(polydata)
delaunay.Update()
# 获取三角化后的数据
triangulatedPolydata = delaunay.GetOutput()
# 提取边缘线段
extractEdges = vtk.vtkExtractEdges()
extractEdges.SetInputData(triangulatedPolydata)
extractEdges.Update()
# 创建点的可视化表示
vertexGlyphFilter = vtk.vtkVertexGlyphFilter()
vertexGlyphFilter.SetInputData(polydata)
vertexGlyphFilter.Update()
pointsMapper = vtk.vtkPolyDataMapper()
pointsMapper.SetInputConnection(vertexGlyphFilter.GetOutputPort())
pointsActor = vtk.vtkActor()
pointsActor.SetMapper(pointsMapper)
pointsActor.GetProperty().SetPointSize(3)
pointsActor.GetProperty().SetColor(1, 1, 1) # 设置点的颜色为白色
# 创建线段的可视化表示
edgesMapper = vtk.vtkPolyDataMapper()
edgesMapper.SetInputConnection(extractEdges.GetOutputPort())
edgesActor = vtk.vtkActor()
edgesActor.SetMapper(edgesMapper)
edgesActor.GetProperty().SetColor(1, 0, 0) # 设置线段的颜色为红色
# 创建渲染器和渲染窗口
renderer = vtk.vtkRenderer()
renderer.AddActor(pointsActor)
renderer.AddActor(edgesActor)
renderer.SetBackground(0, 0, 0)
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
renderWindow.SetSize(640, 480)
renderWindow.SetWindowName("2D Points and Edges Visualization")
# 创建交互器和交互器样式
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(renderWindow)
style = vtk.vtkInteractorStyleTrackballCamera()
interactor.SetInteractorStyle(style)
# 存储被删除的线段
deletedLines = []
# 自定义回调函数,处理删除线段和撤回删除操作的逻辑
def deleteLine(obj, event):
# 获取按下的键值
key = interactor.GetKeySym()
if key == 's' or key == 'S':
# 获取点击坐标
clickPos = interactor.GetEventPosition()
# 创建Picker
picker = vtk.vtkCellPicker()
picker.SetTolerance(0.01)
picker.Pick(clickPos[0], clickPos[1], 0, renderer)
# 获取选中的单元格
cellId = picker.GetCellId()
# 检查是否选中了线段
if cellId >= 0:
# 删除选中的线段
deletedLines.append(extractEdges.GetOutput().GetCell(cellId))
extractEdges.GetOutput().DeleteCell(cellId)
extractEdges.GetOutput().RemoveDeletedCells()
# 更新渲染窗口
renderWindow.Render()
elif key == 'g' or key == 'G':
# 撤回删除操作
if len(deletedLines) > 0:
# 获取最后一个被删除的线段
lastDeletedLine = deletedLines.pop()
# 将线段添加回remainingLines
remainingLines.InsertNextCell(lastDeletedLine)
# 更新渲染窗口
renderWindow.Render()
# 将删除线段和撤回删除操作的回调函数与键盘事件关联
interactor.AddObserver("KeyPressEvent", deleteLine)
# 启动交互器
interactor.Initialize()
interactor.Start()
else:
QMessageBox.warning(self, "No Data", "No data to display.")
根据您提供的代码,我看到在 tu_pict
函数中实现了按下'S'键删除线段的功能,但是没有看到按下'G'键撤回上一次删除线段的相关代码。此外,generate_mesh_from_remaining_lines
函数也没有被调用。
要实现按下'G'键撤回上一次删除线段的功能,您可以在 keyPressEvent
方法中添加相应的逻辑。例如,您可以在 keyPressEvent
方法中检测按下的键是否为'G'键,并执行相应的操作来撤回上一次删除的线段。
以下是一个示例的代码片段,展示了如何在 keyPressEvent
方法中添加按下'G'键撤回上一次删除线段的逻辑:
def keyPressEvent(self, event):
if event.key() == Qt.Key_G:
self.undo_delete_line()
else:
super().keyPressEvent(event)
def undo_delete_line(self):
# 撤回上一次删除的线段逻辑
# 重新生成图形或从数据结构中恢复被删除的线段
# generate_mesh_from_remaining_lines() # 调用生成网格的函数
您需要根据具体的需求和数据结构来实现 undo_delete_line
方法中的逻辑,以便正确地撤回上一次删除的线段。
同时,请确保在相应的位置调用 generate_mesh_from_remaining_lines
函数,以便正确生成网格。
希望这些信息对您有所帮助!如果您还有其他问题,请随时提问。
回答部分参考、引用ChatGpt以便为您提供更准确的答案:
首先,根据您提供的代码,我注意到在函数tu_pict()
中确实没有调用generate_mesh_from_remaining_lines()
函数,因此按下'G'键时无法撤回上一次删除线段的操作并生成网格。
为了实现按下'G'键撤回删除线段的功能并生成网格,您可以在deleteLine()
函数中添加调用generate_mesh_from_remaining_lines()
的逻辑。具体步骤如下:
deleteLine()
函数中,在删除线段后的代码处添加以下代码:if key == 's' or key == 'S':
# 删除选中的线段
extractEdges.GetOutput().DeleteCell(cellId)
extractEdges.GetOutput().RemoveDeletedCells()
# 更新渲染窗口
renderWindow.Render()
# 调用生成网格的函数
generate_mesh_from_remaining_lines()
generate_mesh_from_remaining_lines()
函数的定义移动到JkdWindow
类的内部,与其他函数一起。确保generate_mesh_from_remaining_lines()
函数在tu_pict()
函数之前定义。通过以上步骤,按下'S'键删除线段后,再按下'G'键将会撤回上一次删除的线段并生成网格。
注意:由于无法查看图片内容,我只能根据代码逻辑进行推测和解释,请在实际运行中验证代码是否正确实现了您的需求。
generate_mesh_from_remaining_lines函数没有被正确调用,remainingEdgesInteractor没有启动
建议:在deleteLine回调函数里,同时调用generate_mesh_from_remaining_lines函数,在按'S'键删除线段后,启动remainingEdgesInteractor
结合AI总结如下参考意见:
从代码中看,你正确地实现了按下'S'键删除线段的功能,但没有实现按下'G'键撤回上一次删除线段的功能。问题可能出在generateMesh函数中。
在generateMesh函数中,你需要添加代码来撤销上一次的删除操作,并生成新的网格。根据你提供的代码,以下是一些可能的实现方法:
1、撤销上一次删除线段的操作用户数据(根据你的代码和设计)进行还原。这可能涉及到从数据结构中恢复被删除的线段,并将它们添加回remainingLines中。
2、完成撤销操作后,创建一个新的vtkDelaunay3D对象,将更新后的线段数据设置为输入数据,并调用Update方法进行三角化。
3、获取三角化后的数据,创建一个vtkPolyDataMapper对象,并将三角化后的数据设置为输入数据。
4、创建一个vtkActor对象,将vtkPolyDataMapper对象设置为其映射器。
5、将新的vtkActor对象添加到渲染器中。
6、更新渲染窗口。
问题已经自己解决了,使用的另外的方法,我也没法验证你们那个回答正确,不好意思了,下面是我解决的代码。
def tu_pict(self):
if hasattr(self, 'df'):
# 从 DataFrame 中提取 x 和 y 轴坐标数据
x = self.df['E'].tolist()
y = self.df['N'].tolist()
z = self.df['Z'].tolist()
# 创建VTK点云数据
points = vtk.vtkPoints()
for i in range(len(x)):
points.InsertNextPoint(x[i], y[i], z[i])
polydata = vtk.vtkPolyData()
polydata.SetPoints(points)
# 使用vtkDelaunay3D进行三角化
delaunay = vtk.vtkDelaunay3D()
delaunay.SetInputData(polydata)
delaunay.Update()
# 获取三角化后的数据
triangulatedPolydata = delaunay.GetOutput()
# 提取边缘线段
extractEdges = vtk.vtkExtractEdges()
extractEdges.SetInputData(triangulatedPolydata)
extractEdges.Update()
# 创建点的可视化表示
vertexGlyphFilter = vtk.vtkVertexGlyphFilter()
vertexGlyphFilter.SetInputData(polydata)
vertexGlyphFilter.Update()
pointsMapper = vtk.vtkPolyDataMapper()
pointsMapper.SetInputConnection(vertexGlyphFilter.GetOutputPort())
pointsActor = vtk.vtkActor()
pointsActor.SetMapper(pointsMapper)
pointsActor.GetProperty().SetPointSize(3)
pointsActor.GetProperty().SetColor(1, 1, 1) # 设置点的颜色为白色
# 创建线段的可视化表示
edgesMapper = vtk.vtkDataSetMapper()
edgesMapper.SetInputConnection(extractEdges.GetOutputPort())
edgesActor = vtk.vtkActor()
edgesActor.SetMapper(edgesMapper)
edgesActor.GetProperty().SetColor(1, 0, 0) # 设置线段的颜色为红色
# 创建渲染器和渲染窗口
renderer = vtk.vtkRenderer()
renderer.AddActor(pointsActor)
renderer.AddActor(edgesActor)
renderer.SetBackground(0, 0, 0)
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
renderWindow.SetSize(640, 480)
renderWindow.SetWindowName("2D Points and Edges Visualization")
# 创建交互器和交互器样式
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(renderWindow)
style = vtk.vtkInteractorStyleTrackballCamera()
interactor.SetInteractorStyle(style)
# 创建一个变量用于备份原始数据
originalData = vtk.vtkPolyData()
originalData.DeepCopy(extractEdges.GetOutput())
# 自定义回调函数,处理删除线段的逻辑
def deleteLine(obj, event):
# 获取按下的键值
key = interactor.GetKeySym()
if key == 'd' or key == 'D':
# 获取点击坐标
clickPos = interactor.GetEventPosition()
# 创建Picker
picker = vtk.vtkCellPicker()
picker.SetTolerance(0.01)
picker.Pick(clickPos[0], clickPos[1], 0, renderer)
# 获取选中的单元格
cellId = picker.GetCellId()
# 检查是否选中了线段
if cellId >= 0:
# 删除选中的线段
extractEdges.GetOutput().DeleteCell(cellId)
extractEdges.GetOutput().RemoveDeletedCells()
# 将被删除的线段的 ID 添加到 deletedCells 列表中
deletedCells.append(cellId)
# 更新渲染窗口
renderWindow.Render()
# 将删除线段的回调函数与键盘事件关联
interactor.AddObserver("KeyPressEvent", deleteLine)
# 添加撤回删除操作的回调函数
deletedCells = []
def undoDelete(obj, event):
# 获取按下的键值
key = interactor.GetKeySym()
if key == 'z' or key == 'Z':
if deletedCells:
# print(deletedCells)
# 从 deletedCells 列表中获取最后一个删除的线段的 ID
lastDeletedCellId = deletedCells.pop()
print(lastDeletedCellId)
# 获取原始数据中对应的单元格
originalCell = originalData.GetCell(lastDeletedCellId)
# 获取单元格的顶点列表
pointIds = originalCell.GetPointIds()
# 创建新的线段并插入顶点
newLine = vtk.vtkLine()
newLine.GetPointIds().SetId(0, pointIds.GetId(0))
newLine.GetPointIds().SetId(1, pointIds.GetId(1))
#print(newLine)
# 删除最后一个单元格
extractEdges.GetOutput().DeleteCell(lastDeletedCellId)
# 插入新线段
extractEdges.GetOutput().InsertNextCell(newLine.GetCellType(), newLine.GetPointIds())
# 更新单元格属性数组
extractEdges.GetOutput().GetCellData().Reset()
extractEdges.GetOutput().GetCellData().SetScalars(originalData.GetCellData().GetScalars())
print(extractEdges)
# 更新渲染窗口
renderWindow.Render()
else:
print("=====================")
interactor.AddObserver("KeyPressEvent", undoDelete)
# 启动交互器
interactor.Initialize()
interactor.Start()
else:
QMessageBox.warning(self, "No Data", "No data to display.")