Closed jmwright closed 3 years ago
@jmwright I just tested with Brave (i.e. Chrome) and everything works for me in the example notebook. Maybe you could give Chrome a try?
On the error, when you call disable_replay
, then the replay
command will not work any more. I admit, it should do so in a more understandable way and tell instead of raising an exception. I've opened a ticket for it https://github.com/bernhard-42/jupyter-cadquery/issues/24
So I didn't understand that you have to click the last line of code in the listing to see the result of the script. This was very counter-intuitive to me. Should it maybe default to showing you the end result, then allow you to click back through the lines that led up to that result?
Also, I'm not seeing the controls to adjust the parameters. Is there a line of code that has to be added?
@jmwright Just to avoid confusion (and I think it is already clear to you) if one only wants to see the result of the script, use show
or just return the cadquery Workplane as last result. replay
is for debugging. Try clicking on one line after the other in the box: You will follow a deconstruction of the fluent API step by step. If you want to understand how some steps fit together, then select more than one row. This feature really helped me to understand some more complex samples.
I agree, I will make the last row as the default in the next version.
Thank you for your feedback. If you‘ve programmed something yourself, everything seems very clear :-)
For the missing controls, do you mean the buttons in the viewer?
@bernhard-42 Thanks for the info, it helps me understand the intended workflow better.
There are sliders shown in this animated gif, and that's a really cool (and useful) feature. https://github.com/bernhard-42/jupyter-cadquery/blob/master/screenshots/clipping.gif
I can't figure out how to access those though.
Tagging @villares on this too as the information above will hopefully be helpful.
Do you see the whole cad view including buttons, part tree, ...? If so, the part tree is a tabbed view. If you click on "Clipping", you'll see the clipping dialog, if you click on "Tree" again, you'll see the Part tree again.
Btw. you can also double click on parts in the cad view and see some info in the box below "Tree/Clipping"
Sorry to be a very naïve user on this thread. I had trouble getting things to work due to my very limited knowledge of Jupyter notebooks AND cadquery, etc..
I think I saw something more that the clipping plane sliders (but now that you mention it, I think I was mistaken). Could we actually change values used to create the geometry using sliders?
@villares No worries and thanks for using jupyter-cadquery
The process to view a cadquery object is the following:
This means the cad view is completely decoupled from the cadquery object and as such I don't see an easy way to use sliders to change the underlying cadquery object (if this is what you would like to achieve)
I misunderstood what the sliders were for in that gif.
The way I had it in the FreeCAD module it would set the parameters and re-execute using CQGI. I think I had plain number fields, and it takes a bit for larger models to be refreshed after changing the parameters, but it worked pretty well.
Sorry, I accidentally hit the comment and close button. I've reopened the issue.
Hey @jmwright, what are we actually tracking with this ticket? Is it the auto select of the last element in the replay list and the removal of the exception? I currently working on a new version and maybe I can integrate it ...
@bernhard-42
Is it the auto select of the last element in the replay list and the removal of the exception?
I think so. I looks like you already created #24 to capture the exception update.
@jmwright I've published a new version of jupyter_cadquery (v2.0.0-beta1)
It fixes this issue in the following way:
1) when using replay and replay is not enabled it gives a little warning and falls back to standard show()
2) When you have replay enabled it show a little message how to use it and the last step is selected (so you see the final result)
Btw. the huge version step from v1 to v2 comes from the fact that I built my own MAssembly
class, which inherits from cadquery.Assembly
(and I renamed/deprecated Assembly
to PartGroup
- too many assemblies). MAssembly
is similar to cqparts
and FreeCad's Assembly4
and uses mates to assemble parts. It does this in the same way as cadquery.Assembly
by adapting the loc
property.
I have additionally converted the MAssembly
in a hierarchical way to threejs so that I can use the animation system of threejs to show moving CAD objects. You can see an animated gif in the global Readme.
As usual, you can look at it on binder or via docker, see the updated Readme. Just in case you're interested - feedback welcome ...
I'm tagging @adam-urbanczyk to be sure he sees the comment directly above about MAssembly and animation.
@bernhard-42 This is really impressive! I'll need some time to study what you've done, but I think it looks great. One thing I noticed from a UX perspective in Firefox is that there's no horizontal scroll bar when the 3D viewer appears on the right side, so I have to end up dragging the vertical divider over to see the viewer.
@jmwright This is unfortunately a limitation of sidecar. I didn't find a way to programmatically resize it or open it with the right size. I agree, dragging the divider is annoying, so I need to start to look at it ...
The whole massembly code is encapsulated in two files and it is completely independent of the viewing and animation code of jupyter-cadquery. There are two changes that could be interesting for CadQuery independent of MAssembly
:
back_left>lower
), because I use the leg
assembly (upper_leg
and lower_leg
) 6 times in the hexapod
assembly and to select the correct lower leg, the combined query was needed (at least I didn't see another way).("kind", "args")
instead of kind@args
- and from there I added ("wires", (x,y))
which selects the nearest wire to the given x,y
coords. To make life even easier, I allow to chain selectors: ("faces@>Z", ("wires", (x,y)))
:
lower = ">Z"
for hole in leg_holes: # list of 2 dim coords
obj = assy.find("left_back>lower", ("faces", lower), ("wires", hole))
...
where the first parameter selects the assembly and the other two are chained object selectors - happy to learn whether there are easier ways.
Why is there a relocation step in the middle? This has to do with how the animation system of threejs
works. For the animation a dedicated mate is the central point for for all rotations. So I had to ensure that the origin of each CadQuery object is relocated in a way that its origin coincides with the origin of the mate around which the rotation should happen.
If you do not use the animation system (e.g. using CQ-Editor), you should be able to omit this step (but I haven't tested this in the last version)
Maybe that little explanation helps if you look at the code.
Very interesting @bernhard-42 . The idea behind assemblies was to keep them lightweight, but I'm very open for suggestions. It is kind of uncharted territory.
You are probably interested in the latest addition of tag support in constrain
and _query
. I've started using PyParsing to handle the queries so extending the grammar should be easy. BTW using >
is not the best idea to separate IDs due to the fact that it is already used in the selectors. Maybe '/' or ':' would be better. Also note that (so far not enforced) assumption was that object IDs are unique. If it is too limiting we could always change it.
@adam-urbanczyk I think I also kept it lightweight. The flow in CadQuery is "assembly -> constraints -> solve" and solve will adapt the component's loc element according to the constraints. In MAssembly the flow is "assembly -> mates -> assemble" where the mates step adds connection coords to the assembly components and assemble then links them together by adapting the loc element again.
So it is just the difference between constraints + numeric solver and mates + static solver. From a result perspective, you shouldn't see a difference. all standard methods of Cadquery assemblies should apply.
I think there is a place for both of them. I personally find it easier to debug assemblies with static mates (one can look at the interim result rendering all mates) than to assume what the solver has done. But this clearly is only a personal preference.
Only if you want to use then animation system of jupyter-cadquery, you additionally have to tell which mate is the origin and relocate before you assemble. Therefor there is a origin property and a relocate method in my class.
My find extensions are just for convenience ... but the largest part of the code.
@adam-urbanczyk I think I also kept it lightweight. The flow in CadQuery is "assembly -> constraints -> solve" and solve will adapt the component's loc element according to the constraints. In MAssembly the flow is "assembly -> mates -> assemble" where the mates step adds connection coords to the assembly components and assemble then links them together by adapting the loc element again.
Clear, thanks @bernhard-42 . What I meant was: If you think there is functionality that needs to be added to CQ.Assembly
, I'm all ears as long as it does not complicate the code too much.
@jmwright I just released 2.0.0. It now automatically selects the last element for replays to ensure the full result is shown first. I guess we can close this ticket now?
Yes, thanks!
I'm on Firefox 81 on Ubuntu 18.04 64-bit.
Is the binder still up to date and maintained? I was trying to help a CadQuery user on Discord get started with jupyter-cadquery, but we can't get the binder to work. The user wants the widgets to dynamically adjust parameters.
https://mybinder.org/v2/gh/bernhard-42/jupyter-cadquery/v1.0.0?urlpath=lab&filepath=examples%2Fcadquery.ipynb
If I navigate to the examples directory and open cadquery-examples.ipynb, then execute the first two code cells, everything seems fine. But then if I try to execute cells further down, the 3D view doesn't update. Trying different combinations of things causes other problems. If I call disable_replay() in the first cell then I start getting errors like this: