Skip to content

Conversation

jmwright
Copy link
Member

@jmwright jmwright commented Feb 26, 2025

The goal is to make it possible to round-trip assemblies to and from STEP without loss of data. This data can include:

  • Part location
  • Part color
  • Shape colors
  • Shape colors
  • Shape names (advanced face)

Fixes #826 and #1427

Copy link

codecov bot commented Feb 26, 2025

Codecov Report

❌ Patch coverage is 96.56160% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.06%. Comparing base (8431073) to head (315cce7).
⚠️ Report is 4 commits behind head on master.

Files with missing lines Patch % Lines
cadquery/occ_impl/importers/assembly.py 96.29% 1 Missing and 5 partials ⚠️
cadquery/occ_impl/assembly.py 93.93% 0 Missing and 4 partials ⚠️
cadquery/assembly.py 97.59% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1779      +/-   ##
==========================================
+ Coverage   95.66%   96.06%   +0.39%     
==========================================
  Files          28       30       +2     
  Lines        7431     9444    +2013     
  Branches     1122     1562     +440     
==========================================
+ Hits         7109     9072    +1963     
- Misses        193      226      +33     
- Partials      129      146      +17     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jmwright
Copy link
Member Author

@adam-urbanczyk In 4045c58 you set the cadquery.Assembly.importStep method up to be a class method, and you construct assy before calling the lower-level method. However, since the Assembly.name property is private and can only be set during instantiation, this creates an issue for me. I need to be able to set the top-level assembly name based on the name set in the STEP file, which requires me to set the name property after instantiation.

We need to decide on the proper way to fix this.

@adam-urbanczyk
Copy link
Member

Hey, I do not understand the issue. You can always do this:

assy = Assembly()
assy.name = '123'

Do you mean that you need to modify AssemblyProtocol to satisify mypy? That also does not sound like an issue to me.

@jmwright
Copy link
Member Author

Correct, mypy complains. I can make that change to make name a public property if you don't see an issue with doing so.

@adam-urbanczyk
Copy link
Member

I found one more issue: import did not update the fist key in .objects properly. It is fixed and tested now.

@jon-proximafusion
Copy link

jon-proximafusion commented Sep 12, 2025

Just tinkering with this and noticed the file sizes appear to be different to the original step file, am I doing something wrong here.

I have installed this branch with pip

pip install git+https://github.com/CadQuery/cadquery.git@assembly-import
import cadquery as cq
sphere = cq.Workplane().sphere(5.0)

assembly = cq.Assembly()
assembly.add(sphere, name="sphere")
assembly.export("sphere.step")

assembly2 = cq.Assembly()
assembly2.importStep("sphere.step")
assembly2.save("sphere2.step")
assembly2.export("sphere3.step")

Filesize appears to be quite different, is some content being missed when importing and saving again

ll
-rw-rw-r--  1 jon jon 3254 Sep 12 13:43 sphere2.step
-rw-rw-r--  1 jon jon 3254 Sep 12 13:43 sphere3.step
-rw-rw-r--  1 jon jon 6703 Sep 12 13:43 sphere.step

@adam-urbanczyk
Copy link
Member

Weird, something is definitely off here

@adam-urbanczyk
Copy link
Member

adam-urbanczyk commented Sep 12, 2025

Note that load is a static class method and it creates a new assembly:

import cadquery as cq
sphere = cq.Workplane().sphere(5.0)

assembly = cq.Assembly()
assembly.add(sphere, name="sphere")
assembly.export("sphere.step")

assembly2 = Assembly.load("sphere.step")
assembly2.save("sphere2.step")
assembly2.export("sphere3.step")
!ls -l *sphere*.step
-rw-r--r-- 1  197609 6706 Sep 12 14:58 sphere.step
-rw-r--r-- 1  197609 6690 Sep 12 15:01 sphere2.step
-rw-r--r-- 1  197609 6690 Sep 12 15:01 sphere3.step

@lorenzncode
Copy link
Member

I captured timing for export/load and step file size. These are only observations and perhaps are expected behavior.

  • load can be slow with many objects.
  • There seems to be significant file size difference in the reexport.
# 10k boxes example from PR 1157

import cadquery as cq
import timeit
import os

box = cq.Workplane().box(1, 1, 1)

assy = cq.Assembly()
num = 100
for i in range(1, num + 1, 1):
    for j in range(1, num + 1, 1):
        assy.add(
            box,
            name=f"box{i}_{j}",
            color=cq.Color("red"),
            loc=cq.Location((1.1 * i, 1.1 * j, 0)),
        )

# export the assembly to step
tsave = timeit.timeit('assy.export("test1.step")', globals=globals(), number=1)

# load the step
result = []


def timed_load():
    result.append(assy.load("test1.step"))


tload = timeit.timeit("timed_load()", globals=globals(), number=1)

# reexport to check file size
result[0].export("test2.step")

print(f"time export: {tsave:.1f} s")
print(f"time load: {tload:.1f} s")

print(
    f"original test1.step size: {os.path.getsize('test1.step') / (1024 * 1024):.2f} MB"
)
print(
    f"reexport test2.step size: {os.path.getsize('test2.step') / (1024 * 1024):.2f} MB"
)

(I am on a faster machine which explains the <2s export vs previous result with ~5s export)

time export: 1.5 s
time load: 29.3 s
original test1.step size: 21.92 MB
reexport test2.step size: 38.22 MB

@adam-urbanczyk
Copy link
Member

FYI: I did quite some rework. Will explain later.

@adam-urbanczyk
Copy link
Member

adam-urbanczyk commented Sep 26, 2025

  • Added xbf and xml support
  • Got rid of extra nodes as much as possible
  • Round trips require different handling of colors; colors should only be used on leaf nodes
  • Fixed color handling for roundtrips (srgb vs linear rgb)
  • There are still some strange issues here and there, but typical use cases seem to work reliably:

@adam-urbanczyk
Copy link
Member

Additionally, I tweaked the docs a little bit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

STEP import as an assembly
5 participants