GSoC 2020: A better IPython and Jupyter Notebook Integration for FreeCAD
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
Re: GSoC 2020: A better IPython and Jupyter Notebook Integration for FreeCAD
Nice work!
One remark: You currently hard coded the scene structure of a object into your code, where exactly the individual nodes are. This does only work for Part objects, as only those use this exact structure. Any other visualisation could use any kind of structures. Hence it makes sense to change your implementation to be more generic.
Coin works by iterating the scene graph and storing the "last seen nodes" to use them when needed. E.g. it goes down the graph, and when it finds a Coordinate3 node it stores it as currently active Coordinate Node. When it afterwards encounters any node, that requires a Coordinate3 node (like IndexedFaceSet), it uses the last seen one it has stored. If it encounteres another Coordinate3 node it overrides the currently active Coordinate3 node.
Implementing a system like this in your code gives you the possibility to parse all possible scene graphs.
One remark: You currently hard coded the scene structure of a object into your code, where exactly the individual nodes are. This does only work for Part objects, as only those use this exact structure. Any other visualisation could use any kind of structures. Hence it makes sense to change your implementation to be more generic.
Coin works by iterating the scene graph and storing the "last seen nodes" to use them when needed. E.g. it goes down the graph, and when it finds a Coordinate3 node it stores it as currently active Coordinate Node. When it afterwards encounters any node, that requires a Coordinate3 node (like IndexedFaceSet), it uses the last seen one it has stored. If it encounteres another Coordinate3 node it overrides the currently active Coordinate3 node.
Implementing a system like this in your code gives you the possibility to parse all possible scene graphs.
Re: GSoC 2020: A better IPython and Jupyter Notebook Integration for FreeCAD
Great progresses @kryptokommunist ! It's great to see all the chain from FreeCAD to WebGL debunked step by step...
At some point, it would be cool if you could have a look at the current FreeCAD to WebGL exporter at https://github.com/FreeCAD/FreeCAD/blob ... rtWebGL.py
an maybe see how we could use your work there... I have the impression you'll get to a better result, plus yours is working without the GUI open, which is definitely more interesting
At some point, it would be cool if you could have a look at the current FreeCAD to WebGL exporter at https://github.com/FreeCAD/FreeCAD/blob ... rtWebGL.py
an maybe see how we could use your work there... I have the impression you'll get to a better result, plus yours is working without the GUI open, which is definitely more interesting
- kryptokommunist
- Posts: 70
- Joined: Fri Mar 27, 2020 6:29 pm
- Location: Berlin
- Contact:
Re: GSoC 2020: A better IPython and Jupyter Notebook Integration for FreeCAD
I thought extracting the camera from the scene graph would make sense, so we get the same defaults as in FreeCAD. But after searching through the code and looking at the scene graph I can't find where the camera view is defined. To me it looks like the camera view is set somewhere outside the scene graph since when I open FreeCAD and create a document with an object the following code inside the Python console doesn't find any node inside the scene graph that is camera related:
It should identify any Camera node since this part of the code works:
The same holds true for "Light". Are the lighting and camera settings hidden in some special node? Alternatively I could just create some default settings myself.
Code: Select all
>>> from pivy import coin
>>> def dfs_traversal(root_node):
... for node in root_node:
... if "Camera" in str(type(node)):
... print("Found camera node: {}".format(type(node)))
... if type(node) is coin.SoSeparator or type(node) is coin.SoSwitch:
... dfs_traversal(node)
...
>>> sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()
>>> dfs_traversal(sg)
>>>
Code: Select all
>>> "Separator" in str(type(sg))
True
>>> str(type(sg))
"<class 'pivy.coin.SoSeparator'>"
Last edited by kryptokommunist on Fri Jul 17, 2020 8:17 am, edited 1 time in total.
- kryptokommunist
- Posts: 70
- Joined: Fri Mar 27, 2020 6:29 pm
- Location: Berlin
- Contact:
Re: GSoC 2020: A better IPython and Jupyter Notebook Integration for FreeCAD
I'm on it!
That should be not that far away. With the current code we can extract an threejs scene graph in JSON right from the Coin3D graph and then package that with some Javascript and HTML. That way we could save not just objects but it should also be possible to e.g. save the visual output of a FEM analysis. But I haven't tested that yet.yorik wrote: ↑Thu Jul 16, 2020 12:19 pm At some point, it would be cool if you could have a look at the current FreeCAD to WebGL exporter at https://github.com/FreeCAD/FreeCAD/blob ... rtWebGL.py
an maybe see how we could use your work there...
Reading into the WebGL export code it seems to extract the faces from Mesh::Feature instead of the Coin3D graph. Is there any difference? Then it builds Javscript by creating Strings within Python. My approach looks a bit cleaner since I now use Pythreejs to do the dirty work of translating it.
Last edited by kryptokommunist on Fri Jul 17, 2020 2:26 pm, edited 2 times in total.
Re: GSoC 2020: A better IPython and Jupyter Notebook Integration for FreeCAD
Your approach is definitely cleanerkryptokommunist wrote: ↑Thu Jul 16, 2020 10:36 pm Reading into the WebGL export code it seems to extract the faces from Mesh::Feature instead of the mono]Coin3D[/mono] graph. Is there any difference? Then it builds Javscript by creating Strings within Python. My approach looks a bit cleaner since I now use Pythreejs to do the dirty work of translating it.
That code is pretty old and a bit hackish... Taking data directly from coin3D is of course better and has many more possibilities. Plus, color and material info are already defined, etc.FreeCADGui.ActiveDocument.ActiveView.getCamera()
Regarding the camera, you can get view camera info from FreeCADGui.ActiveDocument.ActiveView.getCamera() and FreeCADGui.ActiveDocument.ActiveView.getCameraNode() (also from FreeCADGui.ActiveDocument.ActiveView.getViewer() )
Re: GSoC 2020: A better IPython and Jupyter Notebook Integration for FreeCAD
May be totally offtopic. I recently discovered jupyther notebook as quite useful for my daily work as structural engineer even without the use of FreeCAD. But ... Is it possible to test your work somehow without reading throught all the topic. Ist there some overview post how the bits and pieces fit together?kryptokommunist wrote: ↑Thu Jul 16, 2020 10:36 pm but it should also be possible to e.g. save the visual output of a FEM analysis. That would surely be cool.
- kryptokommunist
- Posts: 70
- Joined: Fri Mar 27, 2020 6:29 pm
- Location: Berlin
- Contact:
Re: GSoC 2020: A better IPython and Jupyter Notebook Integration for FreeCAD
It is now implemented that way.
I still don't have a good solution for this.
- find out where in FreeCAD I can access the names of edges and surfaces
Not started yet.
- extending my current pythreejs scene graph function to attach labels to it's surfaces and edges
Last week I got bogged down with some issues with the pythreejs implementation. There were some bugs and even the example code for setting up lighting correctly for a geometry didn't work. After a while I realized that you need to compute vertex normals for lighting to work. Then I found out that the pythreejs way of doing that has a bug (just doesn't work, no error message though). These and some other small things with the other goals above added together were quite frustrating so I procrastinated a bit with my side project. Let's say I put in some more community bonding. But I apologize for not posting updates more recently and I hope to make up for this later. Anyways since I finally solved this my motivation is back again I think it's still realistic to finish this in the next month. (If not I will continue anyways)
- extract color, lines, camera, lighting correctly from the FreeCAD scene graph as there currently are still some issues
On this point I still don't know if I can extract a camera and lighting source at all when running FreeCAD headless. If there are no remarks on that I'd like to understand what the default settings for FreeCAD are and just hard-code copy them.
My goals for this week are (kanban link)
- find out where in FreeCAD I can access the names of edges and surfaces
- extending my current pythreejs scene graph function to attach labels to it's surfaces and edges
- hard copy default camera, lighting defaults from FreeCAD
Last edited by kryptokommunist on Wed Jul 29, 2020 7:02 pm, edited 1 time in total.
- kryptokommunist
- Posts: 70
- Joined: Fri Mar 27, 2020 6:29 pm
- Location: Berlin
- Contact:
Re: GSoC 2020: A better IPython and Jupyter Notebook Integration for FreeCAD
No that's perfectly on topic. I'd be happy for someone to test this to find issues currently not on my radar. The faster way to start would be just running this notebook from the repo. I added some text to summarize, if there is still something missing please let me know.
Re: GSoC 2020: A better IPython and Jupyter Notebook Integration for FreeCAD
Nice job @kryptokommunistkryptokommunist wrote: ↑Wed Jul 29, 2020 12:35 am normals.gif
lighting_demo.gif
My goals for this week are (kanban link)
- find out where in FreeCAD I can access the names of edges and surfaces
- extending my current pythreejs scene graph function to attach labels to it's surfaces and edges
- hard copy default camera, lighting defaults from FreeCAD
Re: GSoC 2020: A better IPython and Jupyter Notebook Integration for FreeCAD
Vertexes, edges and faces (sub-shapes) don't have explicit names. In FreeCAD we simply call them Vertex/Edge/Face and append a number. The number of a sub-shape is the key value associated to the sub-shape when storing it in a map (see e.g. TopoShapePy::getEdges). Like in most parts of OCCT the numbers start with 1, not 0.find out where in FreeCAD I can access the names of edges and surfaces
Then on display side the logic is implemented in PartGui::ViewProviderExt and our custom Inventor nodes SoBrepPointSet, SoBrepEdgeSet and SoBrepFaceSet.
The mapping between a sub-shape on shape and rendering is handled with the two methods ViewProviderPartExt::getElement and ViewProviderPartExt::getDetail
The naming is part of the application logic and is not saved into an Inventor or VRML file.
Yes, there is indeed a "hidden" part of the actual scene graph. When you use the method getSceneGraph() of the 3d view (View3DInventorViewer) you get only a sub-part of the actual graph. To get the complete scene you must use the method getSceneGraph() of the SoRenderManager.hard copy default camera, lighting defaults from FreeCAD
Code: Select all
from pivy import coin
view = Gui.ActiveDocument.ActiveView.getViewer()
scene = view.getSoRenderManager().getSceneGraph()
sa = coin.SoSearchAction()
sa.setType(coin.SoCamera.getClassTypeId())
sa.apply(scene)
sa.getPath().getTail()
Code: Select all
from pivy import coin
view = Gui.ActiveDocument.ActiveView.getViewer()
scene = view.getSceneGraph()
sa = coin.SoSearchAction()
sa.setType(coin.SoCamera.getClassTypeId())
sa.apply(scene)
sa.getPath() # is None