Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Equivalent Vscode Extension #40

Closed
noce2 opened this issue Mar 25, 2021 · 31 comments
Closed

Equivalent Vscode Extension #40

noce2 opened this issue Mar 25, 2021 · 31 comments
Labels
help wanted Extra attention is needed

Comments

@noce2
Copy link

noce2 commented Mar 25, 2021

Hi @bernhard-42 , thanks for this awesome extension. I was just thinking about the possibilities of something like this for VSCode. Please could you tell me if you'd already given it some thought/have ideas about how it could be done?

@bernhard-42
Copy link
Owner

Hi @noce2 in fact I am workinf on something similar. Since I don't want to maintain two different projects, I added a server mode to jupyer-cadquery. You open Jupyterlab, start the server and in VS Code you import a special show_object function that serializes your object and sends it to jupyterlab.
This allows full debugging in VS Code with viewing every interim object:

vscode-jupyter-cadquery

Would this be something you're interested in?

@bernhard-42
Copy link
Owner

@jmwright What do you think? Would this be interesting for the broader CadQuery community?
Currently for me it is more a nice challenge I work on, but should it be integrated into jupyter-cadquery?
It would work with any IDE that allows to debug python code. And it works with shift-enter, meaning running selections of the code on a persistent python interpreter started by the IDE.

@jmwright
Copy link

@bernhard-42 Integration with editors like VS Code (and Atom) has been asked about since way back when I was still working on cadquery-gui (Electron/web based). I think there is a segment of the community that would find this very useful. As to whether it should be integrated into jupyter-cadquery, I'm not sure. Can it live as a separate project, or does it need to be part of the jupyter-cadquery codebase?

I'll post a link to this on Discord to increase the visibility of this issue and try to get some more feedback for you.

@shimwell
Copy link

This all sounds great, just wondering were the repo might live.

@bernhard-42
Copy link
Owner

@jmwright Currently I have included it in jupyter-cadquery, since the viewer is in fact jupyter-cadquery plus a little http server in a separate thread that gets the serialized assembly via http, deserializes it and shows the model. So having a separate repo for the show_object sounded a little bit like overkill to me.

The plan would be to also have a docker container for the viewer (maybe the same with a different endpoint) and to have a command line tool named cq-viewer that would start the jupyter part. Still thinking about how to make it easier to use ...

@bernhard-42
Copy link
Owner

@shimwell Currently the whole piece lives in a dev branch of jupyter-cadquery on my local dev machine. I just disclosed it due this issue being openend to understand whether the process:

  • Start the viewer (running jupyter lab)
  • Open a browser and open the jupyter lab page
  • Open the notebook with the 2 lines and run the cell
  • Move to your editor of choice and import and use the modified show_object

would be acceptable or is simply too cumbersome.

Any feedback welcome

@wcraigtrader
Copy link

I'm a new user to CadQuery but an old hand with Python and OpenSCAD. Thanks for creating/maintaining jupyter-cadquery.

My use-case for CadQuery is to replace a lot of OpenSCAD modules with better-structured Python code. These modules are effectively a library for creating a set of models that share common characteristics, but are customized for different projects. The end result is a set of models that organize components for board games that are designed to fit in the original game box. The models may be boxes that are 3D-printed or laser-cut, or may be molds for thermoforming trays and lids. I need to be able to generate STL and STEP files, and would love to be able to create multi-part models in 3MF files.

I structure my code into multiple modules that abstract complex operations into classes and methods so that creating a new set of models is a simple matter of measuring the components and then quickly creating a script for that game that creates the models that are specific for that game. I prefer to code in VS Code, because it offers a superior environment for writing and testing Python code.

Here are my experiences with CQ-editor 0.2.0, jupyter-cadquery 2.0.0 in a browser, and jupyter-cadquery 2.0.0 in VS Code:

  1. CQ-editor. CQ-editor is good for creating and testing small chunks of CadQuery script, and horrible for working with Python modules. If you make a change to a module, you have to stop and restart CQ-editor to pick up the change. CQ-editor is very sensitive to variations in the Qt5 libraries, and breaks in strange fashions, which can cause code loss because it doesn't have an auto-save function. Good integration with the Python logging framework. Very nice rendering of models. Doesn't understand if name == 'main' blocks, so I'm continually moving test code around.
  2. jupyter-cadquery in a browser. Quirky, powerful, slow. The replay feature is wonderful, but if I make a change in one of my modules, then I have to restart the jupyter kernel to pick up the change, and then I end up with multiple sidecar windows showing previous results. And you can't resize the sidecar windows. Lots of warning messages about jupyter_cadquery being enabled. Susceptible to browser out-of-memory crashes.
  3. jupyter-cadquery in VS Code Like its counterpart in a browser, but rendering the first sidecar is so slow its maddening.One sidecar per jupyter cell. No integration with the VS Code debugger.
  4. Pure CadQuery exporting STL for my slicer. This is the easiest (only?) way to interact with the VS Code debugger with the worst visuals. But it is fast, so lends itself well to iteration.

What I want:

  1. A visual debugger for CadQuery that interacts with VS Code and lets me debug modules.
  2. Using jupyter notebooks for testing and debugging is fine, but they need to respect Python package/import conventions, and can't sit at the top of the project hierarchy -- they need to go in a notebook directory, yet be able to interact with my other project code.
  3. Needs to be able to respond to changes in modules seamlessly.

@noce2
Copy link
Author

noce2 commented Mar 26, 2021

@bernhard-42 thank you so much for responding on this.

I think having the viewer open in a separate window outside VSCode is similar to the kind of workflow Frontend Devs use to debug Web Applications that need to run on say Chrome or Firefox so I don't think we're making a painful journey with the first step you suggest. 2 options I have in mind that we could use to streamline the workflow you outlined are:

  1. Have your special show_object function run the jupyter lab command, and open the browser at the jupyter link and port using python's webbrowser module.
  2. Have a vscode extension that allows a file to be "opened with cadquery viewer" on a split screen with a viewer that looks identical to how the viewer works now. (this one sounds like significantly more work 😂 so I'd be more than happy to help here).

@bernhard-42
Copy link
Owner

@wcraigtrader Thanks for your great detailed feedback. It contains a lot of pain points that I also have:

jupyter-cadquery in a browser. Quirky, powerful, slow.

Slow: Yes, especially when you have complex or many objects in an assembly. This mainly comes from tessellation and I tried a lot (you can show timings by adding timeit=True to the show command).

However multithreading and python are no friends and for multiprocessing the cadquery objects can't be pickled. So got stuck with this unfortunately


Lots of warning messages about jupyter_cadquery being enabled

You should only see warnings when you have replay enabled. The implementation of replay is pretty dangerous: It intercepts at every method call doing some analysis on the object. It seems to work well, however I still cannot exclude some side effects - hence the warning.

Do you see other warnings triggered by jupyter-cadquery?

Should I add a flag to enable_replay to not issue these warnings


And you can't resize the sidecar windows.

As much as I love sidecar, as much I hate that it is a too restricted feature of JupyterLab. You can't reuse a side car, you can't resize a sidecar or open it with another than the default size, ... I fear I need to fork it at some point of time to get the features into it that I need. I looked at its code and it doesn't seem to be easy (if possible at all with the JupyterLab api).


respect Python package/import conventions, and can't sit at the top of the project hierarchy

Not sure I fully understand, however, let me give an example:

Assume this project:

.
├── lib
│   └── __init__.py
└── notebooks
    └── Untitled.ipynb

with lib having one function square in __init__

I start Jupyter Lab in the folder above lib and notebook (which doesn't mean I need to store any notebook on this level).
I have this first cell of my notebook:

import pathlib
import sys
sys.path.insert(0, str(pathlib.Path().absolute().parent))

Then I can can import lib in the notebook

from lib import square
square(2)

But maybe I misunderstood your point ...


Needs to be able to respond to changes in modules seamlessly.

Have you tried %load_ext autoreload ?

image

This seems to be the approach for those use cases


A visual debugger for CadQuery that interacts with VS Code and lets me debug modules.

This is the idea of the proposal above:

  • Your code does not run in JupyterLab, it runs in the debugging environment of VS Code (or Pycharm, ...)
  • There is no sidecar :-)
  • If something goes wrong, just restart the kernel and re-run the first and only cell

Basically, Jupyterlab is simply reduced to being a viewer and not a coding environment:
All your code runs in VS Code with full debugging as VS Code allows. If you call the special show_object function, it will take the CadQuery object, make an assembly out of it (if it is not already one), serialise the assembly and send it via HTTP to the viewer. The viewer will deserialise and view it in the browser.

So actually a complete decoupling of IDE and viewer which could give you best of both worlds. If you look at the animated gif, this it how it currently looks like. Still trying to improve the user experience.

Downsides:

  • Of course, it will not be faster (see tessellation problem mentioned above)
  • no support for replay at the moment. I would need to move the list view to the cad view, which is possible, but I haven't planned for.

Would this be something that would help you, or still too quirky and slow for being part of your workflow?

@bernhard-42
Copy link
Owner

bernhard-42 commented Mar 26, 2021

@noce2 Thanks for the feedback and ideas. I will take them into account and think more about a simple user experience. Will keep you posted.

@Jojain
Copy link
Contributor

Jojain commented Mar 26, 2021

@wcraigtrader and others, while having a vscode extension for cadquery would definitely be nice there is another option that is to use vscode with cq-editor and the autoreload option of cq-editor.
Using it this way you can write your code in vscode and having the benefits of the file managements, autocompletion etc in vscode and running your code in cq-editor each time you save your main file (the one open in cq-editor).
It's honestly not so bad of an aproach to me at least.

@bernhard-42
Talking about the vscode extension, the thing that would the best suits my needs would be to have a vscode extension allowing me to render my code in a splitted view (having the posibility to have everything in one window is nice)

I don't really know how all of this works what you described in your last message seems the closest to what I would like.
Anyway thanks for what you are doing that looks great :) !

@wcraigtrader
Copy link

@wcraigtrader and others, while having a vscode extension for cadquery would definitely be nice there is another option that is to use vscode with cq-editor and the autoreload option of cq-editor.
Using it this way you can write your code in vscode and having the benefits of the file managements, autocompletion etc in vscode and running your code in cq-editor each time you save your main file (the one open in cq-editor).
It's honestly not so bad of an aproach to me at least.

That only works well if your entire model fits in a single file. Once you start breaking things out into modules for code-reuse, it falls down very quickly if you're making changes to the modules.

@bernhard-42
Copy link
Owner

@wcraigtrader You were right, the last release of jupyter-cadquery was slow, very slow indeed.
The mistake was that I switched over to the OCP version of CadQuery without doing performance tests.
OCP lacks a C++ version of the tessellation algorithm that was there in pythonocc-core. On top, the python version from CadQuery.Shape that I based my code on, is slower than necessary.

I now built a new Tessellator class and the latest version should be much faster: For a 15 MB STEP file (https:/tpaviot/pythonocc-demos/blob/master/jupyter_notebooks/load_step_ap203_one_shape.ipynb) version 2.0 took more than 3 min:

| | Object: Group
| | | Triangulation:   51.88 sec
| | | nodes, normals:   88.02 sec
| | tessellate:       149.43 sec
| | | (Caching 140105220841072)
| | | build mesh time:  149.49 sec
| | | discretize time:    1.07 sec
| | | edge list:        0.70 sec
| | shape render time:  151.68 sec
| overall render time:  151.73 sec
| create bounding box:   34.96 sec
| configure view:       0.06 sec
add shapes:           186.75 sec
configure display:      0.02 sec
CPU times: user 3min 4s, sys: 3 s, total: 3min 7s
Wall time: 3min 7s

The latest version now needs < 10 sec:

| | Object: Group
| | | (quality: 0.930250, angular_tolerance: 0.300000)
| | | | Incremental mesh:    1.45 sec
| | | | nodes, normals:    6.16 sec
| | | | edges:          1.21 sec
| | | (Caching 139696955547440)
| | | build mesh time:    9.21 sec
| | shape render time:    9.38 sec
| overall render time:    9.39 sec
| create bounding box:    0.03 sec
| configure view:       0.05 sec
add shapes:             9.47 sec
configure display:      0.01 sec
CPU times: user 22.2 s, sys: 772 ms, total: 23 s
Wall time: 9.73 s

Maybe you could give this version a try whether it improved performance for your models too.

@bernhard-42
Copy link
Owner

@jmwright I saw your tessellator in one of the early issues in the OCP repo (unfortunately after I built mine, since the issue is closed). The Tessellator class I built is also based on pythonocc and on FreeCad, is optimized for performance and additionally retrieves the edges from the mesh. Now mesh and edges are perfectly aligned. And it determines the quality parameter in the same way as FreeCad does it, to find a good tradeoff of time+memory with visual quality.

From a performance perspective, this is the best I could achieve with pure Python. Without a C++ version of the tessallator I cannot get rid of the 6 sec for "nodes, normals" (which actually copies values from C++ world into Python world, value after value ...). I already opened an issue in OCP, see CadQuery/cadquery#705

@jmwright
Copy link

@bernhard-42 I have considered building a Python extension in C/C++ for tessellation. It would probably end up being a customized port of the PythonOCC tessallator. I've been researching ways to build wheels to make extensions installable via pip, so maybe I'll experiment with that a little bit. Can you post a link to your new tessellator so I can see what you did?

@bernhard-42
Copy link
Owner

@jmwright https:/bernhard-42/jupyter-cadquery/blob/master/jupyter_cadquery/tessellator.py
I use parallel meshing and found out that pybind iterators are much slower than traditional for loops.

I also tried to add Pythonocc tessellator to OCP as a separate repo (e.g. due to license of pythonocc), but failed to convert OCP Shapes back to OCCT. Had to admit that I don't understand enough of both C++ and pybind11.

@bernhard-42
Copy link
Owner

And I am currently examining the upcoming VTK export of OCP 7.5. However, due to the very special VTK format for lines (len1, x1, x2, ..., len2, x1, x2, ...) I again run into performance issues. Still slower than my python tessellator :(

@jmwright
Copy link

Is this where the 6 second processing time comes from that's not practical to get rid of within Python? https:/bernhard-42/jupyter-cadquery/blob/master/jupyter_cadquery/tessellator.py#L96

@jmwright
Copy link

Tangentially related - I'm also thinking of ways to leverage this newer CadQuery plugin that does caching. CadQuery/cadquery-plugins#17

@bernhard-42
Copy link
Owner

@jmwright

Is this where the 6 second processing time comes from that's not practical to get rid of within Python?

I added some more measurements

| | | | Incremental mesh:    1.58 sec
timer_nodes:   1.85
timer_triangles:   1.55
timer_normals:   2.53
| | | | nodes, normals:    6.21 sec
| | | | edges:          1.27 sec

In the method tessellate are three loops copying from C++ memory to python: nodes, triangles and normals. Each of these loops are expensive with normals being the most expensive.
Same holds for edges.

What a C++ version needs to achieve is that the results (nodes, triangles, normals and edges) are arranged in memory so that we can use e.g. np.from_buffer (see e.g. VKTs vtk_to_numpy method). This happens in few ms.
Every copy action from C++ to python comes with an overhead. If one compares (node.X(), node.Y(), node.Z()) with node.Coord(), the three copy actions are much slower. If you now multiply with 100.000s of nodes, this is where the time is lost (while copying a buffer of 100.000 floats to numpy is extremely fast).

That's why I think we can't get the current Tesellator faster. I don't think there is a buffer of floats in OCCT meshs to copy, but the values are spread in C++ memory. I guess that's why Thomas in pythonocc has JoinPrimitives which nicely lays out the values to copy in one batch.

@Jojain
Copy link
Contributor

Jojain commented Apr 24, 2021

@bernhard-42 Is the jupyter_cadquery.viewer thing you showed in the comment below avaible somewhere ? Thanks

Hi @noce2 in fact I am workinf on something similar. Since I don't want to maintain two different projects, I added a server mode to jupyer-cadquery. You open Jupyterlab, start the server and in VS Code you import a special show_object function that serializes your object and sends it to jupyterlab.
This allows full debugging in VS Code with viewing every interim object:

vscode-jupyter-cadquery

Would this be something you're interested in?

@bernhard-42
Copy link
Owner

@Jojain Still working on it. This was just a question whether the usability (split of editor and browser) would be ok.
To get the model from VS code to the browser I started using exportStep/importStep, found it very slow, additionally detected that my tessellator was way too slow, ended up working on performance for days (hence the latest release).
I will now restart this project and post here if there is anything to test.

@Jojain
Copy link
Contributor

Jojain commented Apr 26, 2021

@bernhard-42 Ok cool thanks for this.
However have you tried importBrep / exportBrep instead of step? It may be faster/better to use.

@bernhard-42
Copy link
Owner

The current idea is to tessellate on the "VS Code side" and pickle the numpy arrays. Larger result but we talk about <100ms for large objects and even faster read (with importBrep I had 16 sec).

So I will change my rendering pipeline to also allow passing a dict representing the assembly with tessellated objects and quaternions as Locations. Then I can send this dict to the "juypter_cadquery side" (via http, zmq, ... still to be determined) to only build display and view the scene - completely independent of cadquery. This also has the advantage that VS Code's python env and jupyter cadquery's python env do not need to have the the same cadquery version.

However, this now needs to be built :-)

@bernhard-42
Copy link
Owner

@noce2 @Jojain @shimwell @jmwright If you want to give the beta of the IDE CadQuery viewer a try, you could now, see #42

@bernhard-42
Copy link
Owner

@noce2 After having released RC1 of Jupyter-CadQuery with a standalone viewer for IDEs, maybe we could close this?

@bernhard-42
Copy link
Owner

btw., since I want to support not only VS Code, I will not spend time on integrating this into VS Code.
So no further work on the VS Code side planned.

@noce2
Copy link
Author

noce2 commented Jul 14, 2021

Apologies for the delayed response @bernhard-42 . Thank you for all the work on this. It turns out, as VS Code 1.58, using the show object renders the cadquery viewer window!! 🥳 🎆 . I think it's definitely good to close this now.

image

@roipoussiere
Copy link
Contributor

Apologies for the delayed response @bernhard-42 . Thank you for all the work on this. It turns out, as VS Code 1.58, using the show object renders the cadquery viewer window!! partying_face fireworks . I think it's definitely good to close this now.

Wow this is really good!

Any chance to get this as a VS Code extension?

@bernhard-42
Copy link
Owner

@roipoussiere Now, with Jupyter-CadQuery 3 it should be possible, since the actual CAD viewer is full written in Javascript three-cad-viewer.

One would use python code from this repo. For assemblies this would be

from jupyter_cadquery.utils import numpy_to_json
from jupyter_cadquery.cad_objects import to_assembly
from jupyter_cadquery.base import _tessellate_group

result = numpy_to_json(_tessellate_group(to_assembly(a)))

See

assembly = to_assembly(
*cad_objs,
render_mates=render_mates,
mate_scale=mate_scale,
default_color=default_color,
show_parent=show_parent,
)
and
shapes, states = _tessellate_group(part_group, tessellation_args(config), progress, timeit)

The output is the format of the three-cad-viewer component. So one needs to run the python code above from VS Code and then push the resulting json object into three-cad-viewer which runs in a web view of VS Code.

However, I don't have time to maintain another project. But I am happy to help if someone gives it a try ;-)

@bernhard-42 bernhard-42 added the help wanted Extra attention is needed label Mar 24, 2022
@roipoussiere
Copy link
Contributor

roipoussiere commented Mar 24, 2022

However, I don't have time to maintain another project. But I am happy to help if someone gives it a try ;-)

You already did a very good work with this and the three-cad-viewer, thank you so much!

I understand that you don't have time to work on a VSCode extension, but if you still think it's a relevant idea, could you reopen this issue (and eventually pin it)? This will improve visibility.

Edit: oh I just realized that you created #68, nevermind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

7 participants