vtk三角化,将线段生成图形,删除线段之后,按下一次键盘撤回一次删除操作

请问有没有人能帮忙看一下这个函数有什么问题,下面这个使用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()的逻辑。具体步骤如下:

  1. deleteLine()函数中,在删除线段后的代码处添加以下代码:
if key == 's' or key == 'S':
    # 删除选中的线段
    extractEdges.GetOutput().DeleteCell(cellId)
    extractEdges.GetOutput().RemoveDeletedCells()

    # 更新渲染窗口
    renderWindow.Render()

    # 调用生成网格的函数
    generate_mesh_from_remaining_lines()
  1. 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.")