Python VTKPlotLib how to remove existing mesh

162 Views Asked by At

I am running into an issue with the code below. When the button is hit the code should grab the next model and display it, however, the old mesh is still present in the image and doesn't go away. In VTKPlotLib how do you erase the previous mesh, without destroying the qtfigure and messing up the flow of gui application?

Example of the problem

from PyQt5 import QtWidgets
import vtkplotlib as vpl
from PyQt5.QtWidgets import QLineEdit, QMessageBox
from stl.mesh import Mesh


class Tagger(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        # Go for a vertical stack layout.
        vbox = QtWidgets.QVBoxLayout()
        self.setLayout(vbox)
        self.setWindowTitle("Tagging Engine")

        # Create the figure
        self.figure = vpl.QtFigure2()
        self.figure.add_preset_views()

        # Create a button and attach a callback.
        self.button = QtWidgets.QPushButton("Load Next Model")
        self.button.released.connect(self.button_pressed_cb)

        # Create textbox
        self.textbox = QLineEdit(self)
        self.textbox.move(20, 20)
        self.textbox.resize(280, 40)

        # Create a button and attach a callback.
        self.button2 = QtWidgets.QPushButton("Save Current Data")
        self.button2.released.connect(self.button_pressed_save)

        # QtFigures are QWidgets and are added to layouts with `addWidget`
        vbox.addWidget(self.button)
        vbox.addWidget(self.textbox)
        vbox.addWidget(self.button2)
        vbox.addWidget(self.figure)

    def button_pressed_cb(self):
        self.mesh = Mesh.from_file(r"C:/examplefile.stl")

        vpl.mesh_plot(mesh_data=self.mesh, color="#94b1ff")

        # Reposition the camera to better fit to the model
        vpl.reset_camera(self.figure)


        self.figure.update()
2

There are 2 best solutions below

1
VonC On BEST ANSWER

bwoodsend/vtkplotlib issue 2 does mention:

There are several ways to clean the figure between calls to show() or to remove previous added meshes:

You generally need to retain references to everything you wish to alter.
So you may need to change your setup to something like the following if you’re not already doing this:

fig = vpl.figure() # To create a new figure.
# Or
fig = vpl.gcf() # To get the current one.

mesh = vpl.mesh_plot(...)

Once you have these references you can use any of:

# To hide it

mesh.visible = False 
# To make it fully transparent (effectively hiding it).
mesh.opacity = 0

Or if you’re unlikely to want to reshow that mesh again then you can remove it from the figure (and save some RAM).

fig.remove_plot(mesh) # also accepts iterables of plots.
# Or by the shorthand:
fig -= mesh

# Optionally, release the `mesh` reference so Python can have its RAM
# back. 
del mesh

The figure does keep its contents in fig.plots.
So if you’re feeling lazy you could just use:

fig -= fig.plots

which will remove everything. (You may need to call fig.reset_camera() after you’ve added the next mesh if it’s very different is size/position.)

Since mesh_plot returns a vtkplotlib.mesh_plot, you could memorize it in order to remove it at the next call:

class Tagger(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        # ...

        self.mesh_plot = None  # Add this to keep track of the mesh plot

    def button_pressed_cb(self):
        if self.mesh_plot is not None:
            self.figure.remove_plot(self.mesh_plot)  # Remove the previous mesh if it exists

        self.mesh = Mesh.from_file(r"C:/examplefile.stl")
        self.mesh_plot = vpl.mesh_plot(mesh_data=self.mesh, color="#94b1ff")

        vpl.reset_camera(self.figure)
        self.figure.update()

fig.remove_plot(mesh) can be used to remove a plot from the figure, provided you have references to both the figure and the plot you want to remove.
In your case, self.figure is the figure and self.mesh_plot is the plot you want to remove.

You could also use fig -= mesh as a shorthand for fig.remove_plot(mesh), if you prefer.

Additionally, if you want to remove all plots from the figure, you could use fig -= fig.plots. This would be equivalent to a clear_figure function, if one were available.

3
AudioBubble On

You could use the remove_all_meshes() method.

def button_pressed_cb(self):
    # Remove all existing meshes
    self.figure.remove_all_meshes() # Add this to your code.
    
    mesh = Mesh.from_file(self.modelid)
    vpl.mesh_plot(mesh_data=mesh, color="#94b1ff")
    
    # Reposition the camera to better fit the mesh.
    vpl.reset_camera(self.figure)
    
    # Without this, the figure will not redraw unless you click on it.
    self.figure.update()

Theoretically, using self.figure.remove_all_meshes() before plotting the new mesh, should make the previous mesh to be removed from the figure before adding the new one.