VTK scene

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
heda
Veteran
Posts: 1348
Joined: Sat Dec 12, 2015 5:49 pm

Re: VTK scene

Post by heda »

a bit unclear what your intended endgame is, you write visualize, but since you mention paraview - it sounds more like you are looking for interaction.

anyway, out of curiosity just checked if one would crash fc by doing a vkt-interactor through fc - it did not crash - so in that sense you have hope if you're ok with an external vtk window, you will have to code all the interaction, but that is needed regardless if it is inside or outside of fc.

is vtk alive in the python world of fc?

Code: Select all

>>> import vtk
>>> vtk.vtkColor3f(.5, 5, 5)
(vtkCommonDataModelPython.vtkColor3f)[0.5, 5.0, 5.0]
>>>
that is promising :-)

let's read an image

Code: Select all

>>> img = vtk.vtkPNGReader('/home/abc/Pictures/alarm bell.png')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: could not extract hexadecimal address from argument string

>>> ## oops - forgot that getting anything done in vtk is really cumbersome...
>>> 
>>> img = vtk.vtkPNGReader()
>>> img.SetFileName('/home/abc/Pictures/alarm bell.png')
>>> img.Update()

>>> ## no errors, so seemingly it works
>>> img
(vtkIOImagePython.vtkPNGReader)0x7f0fc34b8160
>>> img.GetDataExtent()
(0, 140, 0, 143, 0, 0)
it works, looks like all data powers of vtk are reachable through python - that is a really good start

now, can we crash fc with a scene and interactor?

Code: Select all

>>> actor = vtk.vtkImageActor()
>>> actor.GetMapper().SetInputConnection(img.GetOutputPort())
>>> renderer = vtk.vtkRenderer()
>>> renderer.AddActor(actor)
>>> window = vtk.vtkRenderWindow()
>>> window.AddRenderer(renderer)
>>> interactor = vtk.vtkRenderWindowInteractor()
>>> interactor.SetRenderWindow(window)
>>> interactor.Initialize()
>>> interactor.Start()
gives an external non-modal window with the picture and one can interact with the window
of course it is blocking, close-icon on window does release the blocking, but it does not actually close the window - all that should be possible to make with proper clean-up code - this was just a test to see if there was any hope at all - and there was :-).

it all depends on you dedication to get something like this done, but embedding a vtk-app in fc is something that sounds like it would take a while to get it done.
first I would really evaluate if it is possible to live with only using the data crunching powers of vtk in fc, just guessing that it would make life a lot easier.
if not, I would make what I wanted (scene & interaction) in pure vtk, (i.e. not using fc at all to begin with, getting to know the vtk api is enough to cope with)
once that is done it is time to figure out how to get that into fc, can one live with a blocking process and an external window? how to write the clean-up code? etc?
or is the starting code of wmayer enough to get it embedded?

good luck.
Last edited by heda on Sun Oct 10, 2021 8:22 am, edited 1 time in total.
Zoltan
Posts: 62
Joined: Wed Jul 07, 2021 10:08 am

Re: VTK scene

Post by Zoltan »

Thank you @wmayer. I experienced some issues though:

1. The push button is embedded in a new FreeCAD tab, but the main window (type QMainWindow) is not.
2. Black stripes appeared along the borders of the FreeCAD scene, even on other tabs, after running the code.
3. When I quit FreeCAD and relaunch it again, the Macro, the View and the Workbench toolsets are not enabled in my toolbar. On the other hand, if I quit without running the code, the settings are kept when I restart FreeCAD.

The first two observations can be seen below.
FG0fmqYtkp-min.gif
FG0fmqYtkp-min.gif (743.29 KiB) Viewed 2791 times



If I set mdi as the parent of MainWindow, the application is not embedded but works as expected.
V1f6suh7cF.gif
V1f6suh7cF.gif (502.59 KiB) Viewed 2791 times
Zoltan
Posts: 62
Joined: Wed Jul 07, 2021 10:08 am

Re: VTK scene

Post by Zoltan »

@heda
a bit unclear what your intended endgame is, you write visualize, but since you mention paraview - it sounds more like you are looking for interaction.
The idea is to select three points in the FreeCAD scene, create a plane based on those three points, and cut a VTK 3D image (volume) with that plane. So yes, that needs interaction.
is vtk alive in the python world of fc?
Yes, I tried VTK from within FreeCAD, and it works nicely. That's why I had the idea to somehow connect VTK with FreeCAD in an interactive manner.
of course it is blocking, close-icon on window does release the blocking, but it does not actually close the window
Why do you say, "of course"? To me, it is not evident.
all that should be possible to make with proper clean-up code
If you look at my GIF in my previous post, the vedo framework makes non-blocking possible by rendering the scene in a Qt window.
first I would really evaluate if it is possible to live with only using the data crunching powers of vtk in fc, just guessing that it would make life a lot easier.
That was my first thought too: just use VTK for computations. However, the temptation is so great to create an application that can interact with FreeCAD. :)
once that is done it is time to figure out how to get that into fc, can one live with a blocking process and an external window? how to write the clean-up code? etc?
Maybe the solution is not to use the VTK scene, but follow the approach of vedo, and embed it into a Qt window. You could see that it solves the issue of blocking and the clean-up.
or is the starting code of wmayer enough to get it embedded?
The embedding works kind-of, as shown in my previous post. I could live an external window for now. What about the other way around: create a Qt application based on vedo to harness VTK in a Qt window, and then embed FreeCAD into this Qt application? This should be possible according to the wiki, although those examples did not work for me with Qt5. Another possibly relevant link.
heda
Veteran
Posts: 1348
Joined: Sat Dec 12, 2015 5:49 pm

Re: VTK scene

Post by heda »

cool that the vedo thing seems to work fairly well.

hm, if the main use case is to select points for a plane - that could fairly easy be done in fc/coin
that should then be possible to use to make the work in vtk without any actual vtk driven window
once you have your image that can be put on the screen with the coin-scene (or image wb),
or am I thinking wrong?

with that said, it would be great if you manage to get an example of embedding vtk with interaction into fc working,
that will probably over time lead to additional functionality in fc
Zoltan
Posts: 62
Joined: Wed Jul 07, 2021 10:08 am

Re: VTK scene

Post by Zoltan »

Yes, selecting points in Coin3D is easy. The reason I would need VTK is that I want to superpose a 3D image (volume) with my FreeCAD geometry (you could see the geometry in the attached GIF). The Image workbench is fine for displaying a raster image, but that would not be a volume, only a slice of the volume.
If this VTK thing does not work, I could settle with displaying an image with the Image workbench, but the goal would be showing and slicing the volume.
heda
Veteran
Posts: 1348
Joined: Sat Dec 12, 2015 5:49 pm

Re: VTK scene

Post by heda »

looks like vedo has it's own .show(), might be that the code in there will not play well with fc.

found this more bare bones embedding (a vtk-interactor in a qt-frame).
https://github.com/diego0020/tutorial-vtk-pyqt
was able to make this run with pyqt5 on my box after fixing the errors, like 4 to 5 differences, vtk render window in vtk.qt and the os.path sections

maybe a more bare bones embedding is the way to go if you cannot get vedo to play along.
did not try to get it into fc, but if it runs in a qt-frame it has to be possible to make it work in fc.
wmayer
Founder
Posts: 20298
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: VTK scene

Post by wmayer »

Zoltan wrote: Sun Oct 10, 2021 7:36 am Thank you @wmayer. I experienced some issues though:
I don't know why you have these issues but for me it works as expected and there is no black border either. I guess the black border is a problem with your graphic driver.
Zoltan
Posts: 62
Joined: Wed Jul 07, 2021 10:08 am

Re: VTK scene

Post by Zoltan »

Could you please share the exact code you tried, just to make sure that the problem is with the graphics card (or the lack of: my laptop doesn't have a discrete GPU)?
User avatar
freecadlzh
Posts: 138
Joined: Fri Mar 06, 2020 12:52 pm

Re: VTK scene

Post by freecadlzh »

wmayer wrote: Sun Oct 10, 2021 6:19 am This way you can add a view to the mdi area:

Code: Select all

mw = Gui.getMainWindow()
mdi = mw.findChild(Qt.QMdiArea)
view = MainWindow()
sub = mdi.addSubWindow(view)
sub.show()
In the example you you've linked you have to make two changes:
  • Replace

    Code: Select all

    from PyQt5 import Qt
    with

    Code: Select all

    from PySide2 import QtWidgets as Qt
    from PySide2.QtCore import Slot
    
    because we use PySide2 as Python binding
  • Replace the decorator

    Code: Select all

    @Qt.pyqtSlot()
    with

    Code: Select all

    @Slot()
    But you can also omit it.

Code: Select all

from vedo import Plotter, Cone
import vtk.qt
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

from vedo import Plotter, Cone

from PySide2 import QtWidgets as Qt
from PySide2.QtCore import Slot

class MainWindow(Qt.QMainWindow):
    def __init__(self, parent=None):
        Qt.QMainWindow.__init__(self, parent)
        self.frame = Qt.QFrame()
        self.vl = Qt.QVBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
        self.vl.addWidget(self.vtkWidget)
        
        # create renderer and add the actors
        self.vp = Plotter(qtWidget=self.vtkWidget)
        
        self.vp += Cone().rotateX(20)
        self.vp.show(interactorStyle=0)
        
        # set-up the rest of the Qt window
        button = Qt.QPushButton("My Button makes the cone red")
        button.setToolTip('This is an example button')
        button.clicked.connect(self.onClick)
        self.vl.addWidget(button)
        self.frame.setLayout(self.vl)
        self.setCentralWidget(self.frame)
        self.show() # <--- show the Qt Window
        
    def onClose(self):
        #Disable the interactor before closing to prevent it
        #from trying to act on already deleted items
        self.vtkWidget.close()
        
    @Slot()
    def onClick(self):
        self.vp.actors[0].color('red').rotateZ(40)
        self.vp.interactor.Render()

mw = Gui.getMainWindow()
mdi = mw.findChild(Qt.QMdiArea)
view = MainWindow()
sub = mdi.addSubWindow(view)
sub.show()
Thanks for your help, But the code runs in my freecad macro got a errors:

Code: Select all

    view = MainWindow()
  File "C:/Users/Thinkpad P17 Gen1/AppData/Roaming/Electromagnetic and Acoustic Environment simulation system/Macro/lzhEmbed4.FCMacro", line 15, in __init__
    self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
  File "C:\MyProg\EmAEss_v19.1216.2\FreeCADBuild\bin\lib\site-packages\vtkmodules\qt\QVTKRenderWindowInteractor.py", line 260, in __init__
    QWidget.__init__(self, parent, wflags | Qt.MSWindowsOwnDC)
<class 'TypeError'>: QWidget(parent: QWidget = None, flags: Union[Qt.WindowFlags, Qt.WindowType] = Qt.WindowFlags()): argument 1 has unexpected type 'PySide2.QtWidgets.QFrame'
Image

I comfirm the PySide2 have setup ok, I did not know where is the problem, Need helps, Thanks a lot.
Attachments
errors.jpg
errors.jpg (785.06 KiB) Viewed 1590 times
wmayer
Founder
Posts: 20298
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: VTK scene

Post by wmayer »

The error is not in the macro but the vtk wrapper. You have to fix the file QVTKRenderWindowInteractor.py
Post Reply