Proposal: Importing STEP assemblies as nested layers, not nested blocks

Moving the conversation from There is a block definition on layer X, delete it before deleting layer - #107 by brian

A solution that we’ve been working toward in that thread for bringing in nested assemblies from STEP files, and representing them in Rhino such that:

  • Individual parts can be edited in Rhino simply.
  • Unnecessary parts and subassemblies can be easily deleted
  • The model can be exported back to STEP without losing any of the assembly structure

The strategy is to:

  1. read in assemblies as layers, with subassemblies on nested layers.
  2. Each assembly has a corresponding Named CPlane to mark its insertion location.
  3. Parts come in as blocks.
  4. ALL geometry lives on the Block Objects layer.

Here’s a model that demonstrates my prowess as a mechanical engineer, product designer, and color coordinator all at the same time:

This is a cabinet assembly with subassemblies:

A description of this assembly:

  • The Cabinet assembly has a Case part and two Door assemblies.
  • Each Door assembly has a part named Door and two Hinge subassemblies.
  • Each Hinge assembly has three parts: Hinge Plate 1, Hinge Plate 2, and Hinge Pin.

Here are the block definitions, describing the parts. There are no nested blocks.

And, finally, the Named CPlanes, to describe the insertion location of each assembly (I’m not convinced this is the best way to define an assembly insertion point, but it’s workable for this discussion):

Here’s the 3dm file, too:
Cabinet (1.0 MB)

Does this assembly seem like it would work for you @eobet @gustojunk @ec2638 @Louis_Leblanc @gijs @DuncanW @Willem - and everyone else that does mechanical modeling?

@eej you posted about something similar here: SolidWorks import assembly-layer nesting bug


This can’t work - one door and two hinges are mirrored with respect to the others. This means that their insertion frame is a left-handed frame (compared to a CPlane, which is always right-handed). This means, essentially, that each assembly needs a transform associated with it - exactly what a block instance has. It might be possible to work around this with just an insertion point, and to somehow reverse engineer the assembly transform from the block insertion transforms. But yuck… I really don’t know how to make this round trip in a sane way.

I would argue that the 2 mirrored doors are NOT the same part. Physically they cannot be manufactured using the exact same procedure/tooling. (imagine if it was a molded plastic part, you can’t use the same mold to produce the door and it’s mirrored counterpart). therefore, they should be considered two separate parts - Door, left hand and Door, right hand. That will also remove the necessity of having a left handed coordinate system.

Same thing with the hinges. It might be that the same hinge plate could be turned 180° to be used right/left - so that can be the same part with a simple rotation, not a mirror transformation.


This is a thing I also requested a while ago. Ended up creating my own script for creating layer structure from the nested blocks.

I’m not on the PC now. Are the cplanes rotated or they are simply a translation of the world-top cplane?

If this model is coming from catia each part would have its own coordinate system that gets rotated and translated when the model is assembled.

As @ivelin.peychev said, the CPlane thing is really important (and that’s why I sent you a Catia exported tiller control that was mounted upside down at an angle).

I imported your cabinet into Solidworks, changed the angle of the door and exported it again:

Cabinet Assembly (999.0 KB)

No idea why it became 5mb large, but the point is that when I re-import that file into Solidworks, I am able to edit the angled door and still have all of its CPlanes still align with it. Currently, the basepoint system in Rhino destroys that angle information, unless I’m missing something?

(And yeah, as mentioned, the doors are probably mirrored components, so CPlanes can’t handle that, and both Catia and Solidworks have functionality to create left/right hand mirrored parts, so that’s probably outside of the scope of this proposal.)

1 Like

That’s convenient, except it ignores the fact that there are often very complex parts and assemblies that are exact mirrors of each other. Certainly we wouldn’t expect that the engineers should model them individually, rather than just using a mirror transform? It seems that, if a goal of this exploration is better round-tripping of engineering data with MCAD systems, Rhino should support the mirror transforms, too.

They’re rotated. I presume Catia and SolidWorks support translation, rotation, scaling, and mirror transforms with their parts and assemblies.

Really? You’d be satisfied if mirrored components became two separate components in Rhino, and their linking was lost if imported back into Catia?

I’m curious about this from another direction now…

If we’re choosing to have layers represent assemblies, we know already that layers lack transform information to show how the assembly instance was transformed.

What other information would we lose from the assembly by turning it into a layer?

Under my proposal, all the nested transform information that would exist in “mirror the door” and “open the door” and “move the cabinet” would be compressed into a single block instance transform; the individual transforms are lost. Maybe that’s fine?

Hi @brian

Before I can answer could you specify which STEP application protocol are you targeting?
What kind of data can be stored inside?

Another good question is are you trying to implement a seamless interface between CATIA / SW / Inventor and Rhino or simply exporter/importer.

It all depends on what you want Rhino to help the engineer with.
What will the data be used in Rhino for? Surface operations? Split, Trim, BooleanUnion, etc.

Currently, step files (coming from CATIA) and imported in Rhino create surfaces (or if you check the box to be joined in the importer gui), also polysurfaces.
There’s no solid object in Rhino. Bob also said we were never promised one.

If there was a solid object type all this might be much easier.

As a matter of fact if you try to implement an importer of an assembly from STEP (if the AP contains all the relations between the objects) into Grasshopper definition it will be much easier and with less loss of data because of the immutability of the components and the connections. Respectively, an exporter from Grasshopper with all dependencies and relations exported back to STEP.

I don’t know. Right now we only export AP214AutomotiveDesign, AP214AutomotiveDesignCC2, and AP203ConfigControlDesign. I have no idea what we import - probably a lot more than those.

Merely an importer/exporter. I suppose at some point a Rhino.Inside solution might exist, but we’re not there yet. There’s still the problem of effectively maintaining the data from MCAD in Rhino in a way that it can round trip.

That, and reference geometry for modeling something else. I’m NOT trying to turn Rhino into an MCAD modeler. I’m trying to find a way to make it so that designers can reference MCAD data, and optionally tweak it, in a reasonable way. Maybe this is a pipe dream :slight_smile:

Yeah, that’s way beyond the scope of what I’m trying to figure out here.

That’s an interesting idea… that’s sort of how we’re dealing with Rhino.Inside Revit lately. Revit is to architecture as MCAD is for engineering, and many of the same problems exist - defining certain types of objects with certain characteristics that interact with other types of objects in well-defined ways.

A post was split to a new topic: Rhino Inside CATIA?

That mirrored components become separate in Rhino is completely fine. If I want to import a modified set of surfaces from a mirrored component back into Catia/Solidworks/NX, they will end up in the “master side” anyway, and get mirrored automatically to the other.

Again, what’s important to me is the rotation, and I’m still unclear if the basepoint/transform you are talking about includes it (my testing so far seems to indicate that no, it currently doesn’t, but again, I might be missing something).

@chuck just told me that STEP doesn’t support mirror transforms (only translation and rotation) so I guess my we don’t have to worry about them after all.

Remember that we’re prototyping by hand right now, so anything we do in Rhino to invent a new way of structuring data isn’t going to translate into STEP in a meaningful way. At this point, I’m trying to figure out if there’s any agreement about how a STEP assembly could import into Rhino in a way that has hope of being flexible, editable, and round-trippable.

The steps to solving this problem are:

  1. Come to some agreement about a solution that could work
  2. Prototype the solution manually and test (this may be hard/impossible)
  3. Actually change the STEP import/export code and test it.

@chuck tells me this isn’t going to be easy or quick to implement, even if we get a sane idea of what makes sense.

I believe the quickest solution is to simply change the code of the importer to (as the title says) import nested layers instead of nested blocks. That is currently possible with Python. I see no reason why it could be difficult to implement in Cpp. Also if I’m not wrong the importer is a plugin so messing it up won’t affect Rhino directly. Try it out, we’ll test the WIP and provide feedback.

update: to clarify a bit, the python script that I use is:

  • scanning the nested block
  • creating layers for each block
  • assigning the blocks to the respective 3d object.
  • deleting the blocks

You could simply add this as another checkbox/radio button in the importer gui keep the nested block functionality and if the user prefers create nested layers.

In MCAD, assembly relationships are strictly enforced. In Rhino, assembly relationships would be implied by nested layer membership.

Consider this:

  1. You import a STEP file with several instances of an assembly, and Rhino creates several different layers: assembly:1, assembly:2, assembly:3
  2. You leave all objects in assembly:1 alone.
  3. You transform all of the objects in assembly:2 uniformly
  4. You move one part within assembly:3 but leave the rest where they were
  5. You export as STEP

In this case, the best Rhino can do is to export assembly:1 and assembly:2 as instances of the original assembly, and make up some new assembly for assembly:3.

There would be no warning when the assembly relationship was broken.

Is that adequate?

:thinking:, isn’t it easier to simply create a separate panel for the nested blocks?

A treeview like panel.

1 Like

Probably not; especially if you’re looking to hide/show specific stuff inside the nested blocks or delete parts of the assembly you don’t need. Maybe that’s a completely different set of tools that could solve this problem - more robust nested block pruning tools. I don’t know.


that’s simply amazing!
if would keep step instances as block would make many of my client really happy.

+1000 for me!

@skysurfer - Do you need to round trip back to STEP? Or is a one-way import to nested layers adequate for you?

normally for me is just importing step into rhino but would be a great improvement to be able to export an STEP file with assembly/layer structures.

Nice stuggestion Brian. A lot is quite specific for your use case, and I hope I’ll find the time to wrap my head around it so we can conceive a more general and open user case with good flexibility. That has been Rhino’s strength for years.

Just quickly, I agree that a mirrored geometry is from the CAD world only. The parts should be designed with respective symmetry so that they can be rotated over, and thus actually speed up production.

I like this because it replicates how importing SolidWorks files into Rhino works now, which we find works very well. Each assembly comes in as a layer, with nested layers for each part.

It seems impossible to maintain the rigorousness of an MCAD tree style part/assembly structure while round-tripping though. How do you deal with assemblies that share identical parts? Changing the definition of a part (or block) changes all instances. In the layer setup that would not be the case and on export you could have one part with several definitions.

So I wouldn’t worry about that aspect of it.

There is still the problem though of editing nested blocks in general which would benefit from a tree-type interface. If that was solved the STEP-layer thing wouldn’t be an issue.


1 Like