jmwright / cq-annotate

An annotation extension designed to work with the CadQuery API
Apache License 2.0
2 stars 0 forks source link

Selective explosion of sub-assemblies #1

Open julianstirling opened 4 months ago

julianstirling commented 4 months ago

I am just starting to have a play with assemblies and cq-annotate.

One thing I am delighted about is that I can assemble assemblies. This way we can have a complex nested object.

I made this code by modifying your example:

import cadquery as cq
from cq_annotate.views import explode_assembly

# Create the first assembly component for first assembly
box1 = cq.Workplane().workplane(offset=0.0).box(10, 10, 10)

# Create a second assembly component to be assembled with the first
box2 = cq.Workplane().workplane(offset=0.0).box(10, 10, 10)

# The first assembly
assy1 = cq.Assembly()

assy1.add(
    box1,
    loc=cq.Location((0, 0, 5)),
    metadata={"explode_loc": cq.Location((0, 0, 10))},
    color=cq.Color(1, 0, 0, 1),
)
assy1.add(
    box2,
    loc=cq.Location((0, 0, -5)),
    metadata={"explode_loc": cq.Location((0, 0, -10))},
    color=cq.Color(0, 1, 0, 1),
)

# Create the first assembly component for second assembly
box3 = cq.Workplane().workplane(offset=0.0).box(10, 10, 10)

# Create a second assembly component to be assembled with the first
box4 = cq.Workplane().workplane(offset=0.0).box(10, 10, 10)

# The second assembly
assy2 = cq.Assembly()

assy2.add(
    box3,
    loc=cq.Location((0, 0, 5)),
    metadata={"explode_loc": cq.Location((0, 0, 10))},
    color=cq.Color(1, 0, 0, 1),
)
assy2.add(
    box4,
    loc=cq.Location((0, 0, -5)),
    metadata={"explode_loc": cq.Location((0, 0, -10))},
    color=cq.Color(0, 1, 0, 1),
)

# The main assembly
assy3 = cq.Assembly()

assy3.add(
    assy1,
    loc=cq.Location((0, 5, 0)),
    metadata={"explode_loc": cq.Location((0, 10, 0))},
    color=cq.Color(1, 0, 0, 1),
)
assy3.add(
    assy2,
    loc=cq.Location((0, -5, 0)),
    metadata={"explode_loc": cq.Location((0, -10, 0))},
    color=cq.Color(0, 1, 0, 1),
)

explode_assembly(assy3)

# This only exists so that users running the example in CQ-editor
# can see the result
if "show_object" in globals():
    show_object(assy3)

When I explode, it nests and explodes all of the sub-assemblies as well. I can see this being needed in some cases (making big explosions of the whole assembly), but I can also see times when it only one layer of explosion is needed. When explaining a specific assembly step.

Short term suggestion

I think a short term and easy fix is probably to do something like def explode_assembly(assy, recursive=True): and then if recursive is false it doesn't traverse children.

Longer term suggestion

Have some way to identify sub-assemblies and explode identified ones. Perhaps via name?

jmwright commented 4 months ago

Both the short and long term options should be possible. The explode_assembly method does not currently use CadQuery's traverse method for assemblies because that method did not yet exist when I established this project. explode_assembly needs to be refactored to use that, which will handle arbitrarily deeply nested assemblies and will allow filtering by name, assuming that an assembly name is set (it is not required and CadQuery will use a generated UUID if it is not set).

It should also be easy to accommodate the recursive argument, but I should probably refactor the code for traverse first since that will change how the recursive argument is handled.