CadQuery SVG & cq-editor screenshot: automated stencil/cell drawings

75 views
Skip to first unread message

neri-engineering

unread,
Feb 15, 2024, 10:49:54 PMFeb 15
to CadQuery
This may be a long email.  First, I want to praise CadQuery for performing a specific task very well.  That task is the ability to program a part and then save to STEP file (especially), all without the use of any GUI.  In other words parts can be generated in a very automated or batch-processed mode, without any human intervention.  In computer animation build scripts, for example, the rendering of individual frames is usually preceded by generation of all parts involved as individual STL files.

That being said, I rather like the default drawing style of the cq-editor, which employs a stencil outline and a nice phong shading for smooth color transitions, with a touch of spectral lighting.  No complaints there.

parts.png

And so, I am flirting with the idea of creating entire assembly video animations using this style of drawing, which has the outline drawing together with the shaded color drawing.  This style of drawing, you could say, is a cross between a patent-application-style outline drawing and a plain vanilla non-photo-realistic polygon-filled drawing.  At the very least, I would like to ability to create these sorts of image snapshots individually, for use in other ways (besides creation of 3D computer animation assembly videos).

Therefore the question I want to ask here is, which sort of rendering tool would be recommended to give this style of drawing, from an input STEP file (because the boundary representation is of course needed for generating the proper stencil outline as depicted above).

I flirted with the idea of using CadQuery and/or cq-editor to generate these sorts of drawings.  First I tried the SVG exporter from CadQuery:

cq.exporters.export(
    part,
    "./diff_tube.svg",
    opt = {
        "width": 960,
        "height": 540,
        "marginLeft": 50,
        "marginTop": 30,
        "projectionDir": (100, 100, 100),
        "showAxes": False,
        "showHidden": False,
        "focus": 40 # Unfortunately causes coarse polygonal approximations.
    }
)

outline.png

However while the SVG exporter would be great for patent application drawings, it does not fit my need; lacking, for example, is the ability to color the interior, and with perspective projection the circles are no longer ellipses (or at least the curve computations become much more involving) and so the strategy employed by CadQuery SVG exporter seems to be to approximate curves/arcs with a coarse number of straight line segments, as can be seen above.  No complaints there really, because I realize that CadQuery would do great at creating patent style engineering drawings which usually employ orthonormal projection.

Now if we "screen capture" something directly from cq-editor, the results are also quite interesting.

bleeding.png

The above screenshot was taken with the default orthonormal viewing projection.  As we can see there is a bit of a z-buffering issue with the outline.  However, if we instead choose perspective projection (which is something I'm always going to rely on for my intents and purposes) then we get something that looks more like this:

perspective-view.png

The outline z-buffering anomaly has disappeared and more surprisingly the approximation for the curve/arc which was a coarse polygon when generated in SVG form now seems to be perfectly "smooth".

So, instead of searching for a tool outside the scope of CadQuery tools which will give me exactly the type of drawing directly above, with that same level of excellent quality, why not render to PNG directly from cq-editor, I ask.

Well, with that idea there are still a few missing puzzle pieces.  First, I would need to remove the red/green/blue coordinate axes (unless I devise a trick such as shifting the object far away from origin).  Also I am looking for a programmatic way of "snapping" these screenshots to disc.  For example I need the ability to specify camera angle and camera distance, camera position, all from some sort of script.  By comparison, OpenSCAD has a nice command-line interface which can be studied on UNIX systems by issuing the "man openscad" command.

    openscad --imgsize=$RAW_IMAGE_WIDTH,$RAW_IMAGE_HEIGHT \
             --preview \
             --projection="perspective" \
             --colorscheme="Tomorrow Night" \
             --camera=$TRX,$TRY,$TRZ,$ROTX,$ROTY,$ROTZ,$DIST \
             -D't='$T \
             -D'rev_factor='$REV_FACTOR \
             -D'mode="'${DETAIL_MODE}'"' \
             -D'4wd_rear_diff_stl_base_dir="'${STL_BUILD_DIR}'"' \
             -o "${GENERATED_IMAGE}" \
             "${SCAD_INPUT_FILE}"

I have bold-faced the options that I consider to be extremely useful in the OpenSCAD command-line interface.  Is anything like this feasible in cq-editor?  My goal is to find some tool, not necessarily CadQuery or cq-editor, which will generate the types of outline hybrid drawings pictured above, but with the sort of fine-grained control that is offered via the OpenSCAD command-line options.  I am looking for free tools that don't cost money.  Thanks for your support and opinions.

I realize that CadQuery and friends are not intended to be the Swiss Army Knife for all these sorts of things, but since it already almost does something correctly, would it not make sense to have it complete it fully.  Yes I know, CadQuery is not intended as a rendering tool.


Sent with Proton Mail secure email.

Jeremy Wright

unread,
Feb 16, 2024, 9:44:36 AMFeb 16
to neri-engineering, CadQuery
I believe there is a way to dump a scene to png using VTK, which would allow us to export CadQuery shapes and assemblies to png. This is something I have on my todo list, but do not have an ETA for or any guarantee that I will be able to get it to work.

Shaded SVG export is something that I am interested in as well, but it is not a small/easy task to do that.

--
cadquery home: https://github.com/CadQuery/cadquery
post issues at https://github.com/CadQuery/cadquery/issues
run it at home at : https://github.com/CadQuery/CQ-editor
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cadquery/b_JnCxvTNJKxuWnyhTQu_sdQcn0-RgacY0f0IgDzWzx-0vQrJUBNYifZ9o70s839vcBSdF4sXx7fwBlpjQKkn_8ufj0uYMBLbvfm0xvDVaE%3D%40protonmail.com.

neri-engineering

unread,
Feb 16, 2024, 10:22:52 AMFeb 16
to Jeremy Wright, CadQuery
Thank you for the well-formulated and informative response.  The answer you gave is exactly what I expected, as I have run into a tracker issue pertaining to color shaded SVGs for CadQuery, on the web somewhere.  If any amount of extensive future work is going to be done in improving the SVG exporter then I would suggest ditching the auto-centering and left/top margin approach, and using a "3D view port approach" where the view port dimensions (width and height) are defined, and the camera x,y,z, distance, and three angles of rotation ("gimbal coordinates", or seven parameters) are defined for camera, which could default to reasonable values.  I have some experience with SVG and may be willing to look into this myself; in that case we may collaborate off-line.  A robust colored SVG generation capability with filled/shaded colors and precise camera angles would be a really neat addition, because it would facilitate in automation of generation of 3D drawings, which could even be used for generating computer animations easily.  Sticking with SVG and not going to a PNG would be a better approach because that format is lossless; you can zoom in without getting "blocky pixellated effects".  I have experience implementing full 3D rendering stacks (pixel by pixel) and I know what a large undertaking this SVG generator would be.

Speaking of VTK, I have been meaning to ask about the whereabouts of a simple tutorial that would allow me to embed my parts (w/ interactive user interface) on a webpage in the same way that the "Examples" section has these parts embedded, with the ability to rotate and zoom using mouse functions:  https://cadquery.readthedocs.io/en/latest/examples.html#simple-rectangular-plate

I was about to start reverse-engineering the <script/> and <html/> snippets for these VTK elements there but then realized that I don't have to do that, assuming that some tutorial exists on how to make those "VTK widges" there on the Examples page.  In other words there must exist some code somewhere that converts my STEP files into the HTML script needed to render that part on a webpage.  Thanks for your help on this excellent product.

Sent with Proton Mail secure email.

Jeremy Wright

unread,
Feb 16, 2024, 10:52:30 AMFeb 16
to neri-engineering, CadQuery
We have a sphinx plugin that is specific to CadQuery to generate the 3D renders.


I think that some members of the community have modified the setup in the repository for their own uses, but I don't really know how.

There are different ways you could display your models in HTML.


You can also use glTF for assemblies, VRML should work for shapes (although I never use that exporter), and GitBuilding even does web renders of STL files, so I know that is possible and I have seen web renderers for STEP files. In short, there are a bunch of ways to show your models on the web.


Adam Urbanczyk

unread,
Feb 16, 2024, 1:00:46 PMFeb 16
to CadQuery
So regarding svg being approximated with segments, it should be easy to add: https://github.com/CadQuery/cadquery/issues/1524

Regarding offscreen rendering, it should be possible with OCCT
You could give it a try via OCP and share the code on github. We can then think where/if it should be integrated.

Regarding VTK, you could export as e.g. VTKJS (cq.exporters.assembly.exportVTKJS) and embed that (https://kitware.github.io/vtk-js/docs/). Otherwise, take a look at the CQ directive in the repo.

Neri-Engineering

unread,
Feb 16, 2024, 5:41:46 PMFeb 16
to CadQuery
Okay this is a multi answer.  (First is that I installed 2.4.x CadQuery but didn't want to spam the other thread just to answer that.)

I left a comment on the CadQuery tracker issue #1524 opened by Mr. Urbanczyk with some insights.  I think a cell-shading, meaning a color fill in SVG, is a huge endeavor and cannot be expected.  As someone who has implemented 3D pipelines I already see all the little hard parts that would have to be tackled.  Yes, doable, and yes, very difficult.  More reasonable is to add smooth curves for perspective view, and call it a day.  I still think that better viewport handling and camera positioning could be done with the SVG exporter, instead of using a left/top margin paradigm and scaling to fit.

Regarding my original inquiry, I think that a more reasonable approach for capturing images (for purposes of creating computer animations for example) is to "screen scrape" what is output by cq-editor.

While looking through Mr. Wright's HOWTO page because I was interested in an update procedure 2.3.1 --> 2.4.0 (https://gist.github.com/jmwright/5f3f399faeeac1664ecaba0a01dc076f#2-conda-update) I came across this example:

import sys, os
from cq_editor.widgets import viewer as cqv
import cadquery as cq

app = cqv.QApplication(sys.argv)
viewer = cqv.OCCViewer()

dlg = cqv.QDialog()
dlg.setFixedHeight(400)
dlg.setFixedWidth(600)

cqv.layout(dlg,(viewer,),dlg)
dlg.show()

box = cq.Workplane("XY").box(20,20,30).val().wrapped
box_ais = cqv.AIS_ColoredShape(box)

viewer.display(box_ais)
sys.exit(app.exec_())

This example works well.  I am thinking about studying this code in further detail, and trying to remove the X/Y/Z axis arrows, changing the background, and finding a way to explicitly specify the camera (or object) orientation.  The object orientation and camera orientation are sort of inverses of each other, obviously.  So whether you move the object and call it camera movement is all the same, except that lighting won't be the same, but perhaps this is actually ideal.  The example above already has the axes lines not present, which is exactly what I wanted.  (But it still has the arrows in the corner.)

So what I will be trying to do is start from the small code snippet above and work upwards, I don't even need to show the window for example, as this can maybe be done off-screen (I saw the other link posted by Adam w.r.t. OpenGL rendering offscreen but that seems a bit overwhelming at the moment, and I just want to get this to work first).  I want to create a little code snippet that accepts viewport size (easy, already demonstrated above), camera position, bg color, and output PNG name, and saves that to disc.  Something like this.

Initially I was going to take a top-down approach, trying to tweak the cq-editor app itself, adding come command-line flags which would cause it to not launch the full desktop and only do a screen dump or image save, but now that I ran across this code snippet I think building up from that (lower up approach) is more suitable.

Any pointers on where I can study the various capabilities of viewer objects etc. used in example above?  I assume that I will be able to accomplish this in pure Python.  I assume that the objects used in code snippet above are documented somewhere, in the form of an API.

Jeremy Wright

unread,
Feb 16, 2024, 6:53:31 PMFeb 16
to Neri-Engineering, CadQuery

Adam Urbanczyk

unread,
Feb 17, 2024, 3:49:25 AMFeb 17
to CadQuery
Note that CQ-editor already has screenshot functionality:


ofc this is not off-screen rendering, but I guess you are note after off-screen as such. You could use the viewer widget programmatically to achieve what you want. You can remove the trihedron using this method https://dev.opencascade.org/doc/refman/html/class_v3d___view.html#a1ec80c748d19634616972e8c770ff9b5

VTK approach is also a possibility. Expect better docs, but worse rendering quality.

Adam Urbanczyk

unread,
Feb 17, 2024, 1:01:20 PMFeb 17
to CadQuery

Neri-Engineering

unread,
Feb 17, 2024, 1:25:53 PMFeb 17
to CadQuery
Yes I already git-grabbed all of CadQuery and all of CQ-editor.  Have been looking at the code.  Looking at various resources online for making offscreen images.  Considering the link you posted too.  Will have something soon, will share.  The goal is to make the code as simple as possible and work everywhere.  All I want it the ability to programmatically dump PNG w/o opening window (e.g. do it on headless server - wow that sounds almost esoteric or metaphysical).

Neri-Engineering

unread,
Feb 17, 2024, 5:50:13 PMFeb 17
to CadQuery
Okay I could use some help here from someone like Adam (a programmer familiar with these APIs and window toolkits).

I have this code which does not work.

from OCP.AIS      import AIS_InteractiveContext
from OCP.Aspect   import Aspect_DisplayConnection
from OCP.Aspect   import Aspect_NeutralWindow
from OCP.OpenGl   import OpenGl_GraphicDriver
from OCP.V3d      import V3d_Viewer

display_connection = Aspect_DisplayConnection()
graphics_driver = OpenGl_GraphicDriver(display_connection)
viewer = V3d_Viewer(graphics_driver)
viewer.SetDefaultLights()
viewer.SetLightOn()
context = AIS_InteractiveContext(viewer)
view = viewer.CreateView()  # Object type V3d_View.
window = Aspect_NeutralWindow()
window.SetSize(960, 540)
window.SetVirtual(True)
view.SetWindow(window)  # Fails here.

The error I get on Linux is this, using CadQuery 2.4.0:

X Error of failed request:  BadWindow (invalid Window parameter)
  Major opcode of failed request:  3 (X_GetWindowAttributes)
  Resource id in failed request:  0x0
  Serial number of failed request:  29
  Current serial number in output stream:  30

Having trouble interpreting the error code, but I assume '3' has some meaning.  It's not finding an important attribute.  Maybe it's position?  Tried that.  Maybe it's background color?  Tried that too.  Maybe it's the "peer" or "native handle"?  Did not try that yet.


I am following a post made by user 'natalie' in this link: http://analysissitus.org/forum/index.php?threads/how-to-dump-a-picture-png-or-jpg-without-vizualizing-the-situation-first.72/ .  Her post was made at the end of 2021, so there may have been some API changes.  I tried setting various attributes such as position and background color, with still the same problem.  I did not try Aspect_NeutralWindow.SetNativeHandle() because I would not know what argument to pass it.  Tried various other things and am hitting my head against the wall.  I wanted to try this method instead of switching #ifdef on the OS.  If anyone has any helpful insights it would save me some time.  I am about to ditch the idea of using Aspect_NeutralWindow unless someone has some insights into this.  This seemed like the most elegant way to do things, but I cannot get it to work.  End goal is just to screen dump to PNG a model in headless mode.

Neri-Engineering

unread,
Feb 18, 2024, 1:03:18 AMFeb 18
to CadQuery
Before going to bed, because there must be a huge time difference, I want to ask where the color, which is optionally set in Assembly objects, is passed onto the underlying OCCT code.  I have cadquery and CQ-editor downloaded from Git and understand most of it.

Made good progress on offscreen rendering, works on Linux only, and is not working in headless mode (still needs connection to display even though no window is ever opened).  If I recall correctly there exist some apps that are able to render stuff in headless mode (for example ImageMagick within PHP is able to do image manipulations w/o X Windows, IIRC).  Not a showstopper.  Probably related to OpenGL I am guessing.  I am about to be able to automate some really really awesome and radical computer animations using the default rendering strategy from cq-editor.  It will be sweet.

Matthias Urlichs

unread,
Feb 18, 2024, 2:40:22 AMFeb 18
to cadq...@googlegroups.com
On 18.02.24 07:03, 'Neri-Engineering' via CadQuery wrote:
> (still needs connection to display even though no window is ever opened)

Easy workaround: You can start a toy vncserver and set $DISPLAY to point
to it.

--
-- mit freundlichen Grüßen
--
-- Matthias Urlichs

OpenPGP_signature.asc

mat...@walter.gd

unread,
Feb 18, 2024, 8:54:13 AMFeb 18
to CadQuery
Or much simpler, use `xvfb-run -a <your command>`.

Adam Urbanczyk

unread,
Feb 18, 2024, 12:53:23 PMFeb 18
to CadQuery

Neri-Engineering

unread,
Feb 18, 2024, 9:48:25 PMFeb 18
to CadQuery
Making huge progress with offscreen snapshot.  Will offer two camera specification strategies, just like in OpenSCAD: (1) eye/center (6-arg) or (2) gimbal camera coordinates (7-arg).  The second can be implemented in terms of the first internally.  The first does not allow overriding of "up" vector; it's fixed at (0,0,1).  This is the way OpenSCAD does it and I think it'll be easier to understand.

However I need a quick sanity check on the AIS rendering stuff.
I am trying to verify that in viewer.py, the make_AIS() call can be removed.  The only places in viewer.py where make_AIS is referenced is in the import and in the implementation of _display().  I did a global search for invocations of _display() and did not find any.  Now unless _display() is overriding some kind of parent class method, it can be removed, along with the make_AIS import statement in viewer.py.  Is this correct?  Just doing a sanity check here.  Trying to get a grasp of where the entry into the rendering happens.  Thanks.

The intricate math stuff does not bother me, but the code structure sometimes does, when people start using all sorts of annotations and code magic.  I'm more of a meat and potatoes kind of programmer.  Pragmatic and without excessive fluff.

Neri-Engineering

unread,
Feb 19, 2024, 2:30:14 AMFeb 19
to CadQuery
Here is a little something to get your appetite going.  https://www.youtube.com/watch?v=HuXFYvAcx_g
Still working out many details.

A code snippet for generating those frames would look something like this:

for i in range(0, total_frames):
    rotated = rotateY(part, 360*revs*i/total_frames)
    ais = AIS_ColoredShape(rotated.toOCC())
    cam_rot_z = 45+360*i/total_frames
    image_snapshot_gimbal(parts= ais,
                          bg1_rgb= 0x070707,
                          bg2_rgb= 0x1f1f1f,
                          camera_trans_x=   0.0,
                          camera_trans_y=   6.5,
                          camera_trans_z=  -1.5,
                          camera_rot_x=    66.0,
                          camera_rot_y=     0.0,
                          camera_rot_z=      cam_rot_z,
                          camera_distance= 39.0,
                          camera_projection= 'p',
                          image_width= 1280,
                          image_height= 720,
                          image_filename= padded_sequential_filename(
                              file_basename= "./cq_parts-",
                              file_inx= i,
                              pad_digits= 5,
                              file_suffix= ".png"))

Neri-Engineering

unread,
Feb 21, 2024, 12:17:54 PMFeb 21
to CadQuery
More eye candy from the prototype animator module.  Will support RAYTRACING and translucency.

Adam Urbanczyk

unread,
Feb 22, 2024, 2:04:18 AMFeb 22
to CadQuery
Looks nice, don't forget to share the code.

Neri-Engineering

unread,
Feb 22, 2024, 9:14:55 PMFeb 22
to CadQuery
Will do.  I need at least another two weeks, as this is very involving to take care of all the little details.

I will have my own SVG exporter at the same time, and the "paradigm" for camera specification etc. will be very similar for both the static image capture AND the SVG generator.  I envision an animation which has camera revolving around a rotating part (as the ones I've shown) changing to outline SVG mode mid-animation.  Basically I am imagining an animation starting in transparent-part mode with gradient background, going to raytracing/shadow mode, and then ending in black/white outline mode.  These all should be frames generated from same perspective, so that the outlines align perfectly.  This is why I need to work on the SVG at the same time, because the SVG generator & static image generator need to "align" in their paradigm.  I need to decide on an API/strategy for both, at the same time, more or less (modulo options for SVG).  The API itself need to have some degree of alignment.  It would not make sense to share any code at this time for that reason.
Reply all
Reply to author
Forward
0 new messages