CadQuery / cadquery

A python parametric CAD scripting framework based on OCCT
https://cadquery.readthedocs.io
Other
3.19k stars 289 forks source link

Some examples how `projectionDir` works in SVG export #1685

Open Jopie01 opened 1 week ago

Jopie01 commented 1 week ago

I'm really struggling to make any sense how the projectionDir option works in exporting a SVG. The documentation tells me: Direction the camera will view the shape from., but how is that direction defined?

Imagine the following example

import cadquery as cq

box = cq.Workplane('XY').box(10, 20, 10)
box = box.faces("<X").workplane().circle(2).cutThruAll()

cq.exporters.export(box,
    "box_custom_options.svg",
    opt={
        "width": 300,
        "height": 300,
        "marginLeft": 10,
        "marginTop": 10,
        "showAxes": False,
        "projectionDir": (1, 0, 0),  # <-- I'm lost how this works
        "strokeWidth": 0.25,
        "strokeColor": (255, 0, 0),
        "hiddenColor": (0, 0, 255),
        "showHidden": False,
    },
)

When you run this in cq-editor you will get the following SVG g6

But I want that image 90 degrees rotated like so g7

But I can't get my head around how to do that. Are there any examples how projectionDir works and how to use it? It would be really nice if it was possible to define the rotations about the XYZ like you can when assembling parts.

lorenzncode commented 1 week ago

Currently there is no control over orientation. You might find the "up" orientation changes automatically with changes to projectionDir.

projectionDir = (1, 0, 0): out0

projectionDir = (1, 1e-6, 0): out1

"up" option added in draft PR #1277.

Jopie01 commented 5 days ago

Thanks for looking into this.

I also looked at the sourcecode of the SVG export and at the class reference of the HLRAlgo_Projector (https://dev.opencascade.org/doc/refman/html/class_h_l_r_algo___projector.html). In that class I found that it's also possible to send a gp_Trsf which allows to add a quaternion.

This allows to send the three angles when exporting a SVG, build a quaternion and add that as the projectionDir.

To test this, I copied a bit of code from the Location class https://github.com/CadQuery/cadquery/blob/master/cadquery/occ_impl/geom.py#L1029-L1035 and replaced https://github.com/CadQuery/cadquery/blob/master/cadquery/occ_impl/exporters/svg.py#L192 with the code. Also changed https://github.com/CadQuery/cadquery/blob/master/cadquery/occ_impl/exporters/svg.py#L197 to with

angles = (-90, 90, 0)  # <-- this should be configurable, now just for testing
T = gp_Trsf()

q = gp_Quaternion()
q.SetEulerAngles(gp_Extrinsic_XYZ, *map(radians, angles))

T.SetRotation(q)

if focus is not None:
    projector = HLRAlgo_Projector(coordinate_system, focus)
else:
    projector = HLRAlgo_Projector(T, False, 0.0)

By changing the angles, I can basically create any view I want.