Entities and GetCorresponding in the SOLIDWORKS API (part 7)

In this blog post, you’ll find

  1. What are entities?
    1. All interfaces that implement IEntity
    2. What are loops?
    3. What are features?
    4. Casting to and from entities
  2. Entities and their Persistent Reference ID
  3. How to get an entity’s object
  4. How to select a vertex, face or edge: via its entity
  5. What are Safe Entities?
  6. How to assign an attribute to an entity
    1. What are attributes?
    2. Parameter types within attributes
    3. How to create an attribute
    4. How to retrieve an attribute from an entity
  7. Understanding the scope of an entity: does it belong to a part or a component?
    1. Models versus components
    2. Drawing components
    3. An entity is only valid in the current model
  8. How to use GetCorresponding to get a part entity in an assembly
    1. How to convert a part entity to a component entity
    2. How to convert a component entity to a part entity
    3. How to get an entity in a drawing view from a part entity
  9. All blog posts in this series

1. What are entities?

Every 3D model is built up from vertices (points), edges and faces. In the SOLIDWORKS API, we name these objects Entities. They all implement the IEntity interface because they share common properties and methods.

1.1. All interfaces that implement IEntity

This is the complete list of all interfaces that implement IEntity:

  1. IEdge
  2. IFace
  3. IFeature
  4. ILoop2
  5. IVertex

interfaces that implement IEntity

I think these five objects are the building blocks of geometry:

  1. Vertices/points are the smallest building blocks
  2. Two vertices create a straight edge
  3. One or more edges or vertices make up a loop
  4. One or more loops make up a face
  5. One or more faces create a feature

I don’t fully understand why loops and features are in the list of entities yet. And because the SOLIDWORKS API docs never explain what an object is, just what it does, we’ll have to figure that out ourselves. This is how I understand it now:

1.2. What are loops?

I haven’t used ILoop2 in my six years of SOLIDWORKS programming, so you probably won’t need them unless you are creating your own geometry. But from what I have read, SOLIDWORKS creates loops from a list of edges and/or vertices. Even one vertex can make up a loop.

So they create loops from edges and vertices, then create faces from these loops. Every face has at least one loop, but it can have more than one. A face with two holes in it has three loops, one being the outer loop.

1.3. What are features?

I have only looked at features as the items in the feature tree. But I think features are included in the list of entities because a feature might create a bunch of faces. An extruded circle creates three faces, for example. And when you call IFeature.GetFaces on a draft feature, SOLIDWORKS returns an empty array because a draft feature creates no new faces.

According to the SOLIDWORKS Object Model PDF, that you can download here, IFeature doesn’t even implement IEntity. But I think that is a mistake in the docs.

1.4. Casting to and from entities

Because all the interfaces above implement IEntity, you can cast (aka convert) the detailed object back to an entity to make use of IEntity properties and methods (aka members). In VBA:

You can also cast an Entity to a Face2 to use all the members in IFace2, but you have to make sure the entity is actually a face by calling IEntity.GetType first.

In C#, you have to make explicit casts when casting to and from entities:

Normally, when working in C#, you can cast implicitly when a type implements an interface. But the SOLIDWORKS API is different, and they talk about it here. I still don’t fully understand their explanation because they are talking about three programming languages in one post. My main takeaway is that SOLIDWORKS isn’t written in C# and inheritance works differently in C++ (I think it’s written in C++, at least). That is also why we have to use Interop (interoperability) DLLs to talk to SOLIDWORKS.

2. Entities and their Persistent Reference ID

All selectable objects in the SOLIDWORKS API have a Persistent Reference ID. I call them Persistent IDs for short. I explain them in detail in Persistent ID, sketch segment ID in the SOLIDWORKS API and I keep a list of all available ID types in All identifiers and IDs in the SOLIDWORKS API.

Names of features, faces and edges are great, but users can often change them. So we need an ID that stays the same, that is persistent. That’s when the Persistent ID comes into play. It consists of an array of bytes (so numbers of zero to 255) with a length of 16 (sometimes), 20 (often) or way more, like 491 bytes (occasionally). An example:

176-054-000-000-003-000-000-000-255-254-255-000-000-000-000-255

You can store the persistent ID in a variable so that you can retrieve that object again at a later time. You can’t trust it 100%, though. To quote myself from my blog post about IDs:

Each ID value is unique within a model and it generally stays the same, even across SOLIDWORKS sessions. There is a remark in the docs, though, that it can change with rebuilds, but I don’t remember that actually becoming a problem in my software.

3. How to get an entity’s object

  • When a user has selected an item, you can get that object via  SelectionManager.GetSelectedObject6.
  • When you already know the persistent ID, you can get the object by calling  ModelDocExtension.GetObjectByPersistReference3.
    • Both of these methods will not return an Entity object directly but will return the more detailed object: a face, feature, vertex or edge.
  • If you work with a part and you know the name of the entity, you can use PartDoc.GetEntityByName.
    • I only use this method to get features, though, because it looks like a feature is the only entity type with a name.

For a complete list of ways to access an entity, check out the Accessors list on the IEntity page.

4. How to select a vertex, face or edge: via its entity

If you don’t understand entities, you’re going to have a hard time selecting them. Because IFeature is the only interface that has its own Select2 method.

For all other entity types, you need to cast the object to an entity, then call IEntity.Select4. You can pass null as an argument for the SelectData when you are doing simple selection work. If you want to set a mark, you need to pass a SelectData object.

5. What are Safe Entities?

An entity might not exist after a rebuild, as it is transient, short-lived. Just as a persistent ID may not always survive a rebuild.

Safe Entities do survive, though. So if you have an entity, need to call a rebuild and want to use that entity again, you need to get a safe entity via IEntity.GetSafeEntity. This returns a new entity object that will remain valid until you delete all pointers/references to the object. A safe entity does not persist between SOLIDWORKS sessions, though.

6. How to assign an attribute to an entity

6.1. What are attributes?

You can attach data to any entity, and we do that via attributes. Attributes are features, so they appear in the feature tree unless you explicitly hide them. They have a name and can even be suppressed.

Attributes can be added to:

  1. Bodies
  2. Components
  3. Entities
  4. Models

We add an attribute to the active model in our drawing automation add-in Drew to store two strings with extra data.

6.2. Parameter types within attributes

You can add multiple Parameters to an attribute, and a parameter can be any of the following parameter types:

  1. Double
  2. DVector (double vector, maybe?)
  3. Integer
  4. String

Only basic variable types, essentially. If you create a double, you can even set a default value. There are some weird quirks, though, like not being able to store a negative integer value.

6.3. How to create an attribute

Attributes are special objects, it seems. So, to create an attribute, you need to jump through some hoops:

  1. Call ISldWorks.DefineAttribute once in a session to create an Attribute Definition.
    • Every attribute name needs to be unique. So if you are planning to use an attribute in a product, you need to register your own prefix with the SOLIDWORKS team.
    • According to the docs, the prefix needs to be three letters long. The one we got assigned is four letters, though 😅
    • Store this definition somewhere in your running project because you’ll need it to create instances later.
  2. You call AddParameter on the attribute definition to add one or more parameters.
  3. You register the attribute definition by calling IAttributeDef.Register.
    • The definition is now final. You cannot add any parameters after the fact.
  4. Only now, you can start creating instances by calling IAttributeDef.CreateInstance5.
    • You pass the entity that the attribute definition should attach to as a parameter here.
    • If you want to hide or suppress the attribute, you can pass those settings as parameters as well.

6.4. How to retrieve an attribute from an entity

Because attributes are features, you can retrieve them in similar ways:

  1. By traversing the feature tree, checking the feature type, then calling IFeature.GetSpecificFeature2 to get the Attribute.
  2. By letting the user select the attribute feature, then using GetSelectedObject6 to get the feature object.
  3. By calling IPart.IFeatureByName, IAssembly.IFeatureByName or IDrawing.IFeatureByName.
    • I don’t know why they haven’t just added this method to IModelDoc.

If you already have an entity object, you can call IEntity.FindAttribute directly. A few caveats, though:

  • Apparently, an entity can have multiple attributes attached to it. That is why the FindAttribute method also has an argument for a number, to get the nth attribute.
  • I have not found a way to find out how many attributes are attached to an entity, though.

7. Understanding the scope of an entity: does it belong to a part or a component?

You have to understand the scope of entities. Because you cannot just get an entity from a part, then try to use it again while the part is in an assembly. That entity does not exist there.

7.1. Models versus components

Models are basically documents, files. A model can be a part, assembly or drawing document and it is represented by IModelDoc2. These models can create geometry from scratch:

  1. A part contains features that create new faces and bodies
  2. An assembly can have holes at the assembly level, so it can create some new faces
  3. Drawings are secretly assemblies, and I think SOLIDWORKS creates cross-section views by just creating a cut-extrude, which is why cross-sections can give you zero-thickness errors. So even drawings create new geometry.

But once you add a part to an assembly, we call it a component and the API represents it as IComponent2. You can access the underlying model via IComponent2.GetModelDoc2. Be careful, though, because this returns null when the component is suppressed or when it is loaded as lightweight. So if you need access to all models in an assembly, you first need to call IAssemblyDoc.ResolveAllLightweightComponents.

The assembly itself is called the root component and the other components are its children. Each child can have its own children. This structure creates the tree of parts and (sub)assemblies that you see in the feature tree.

Since you can have multiple instances of the same part, each component has its own geometry and its own entities. Because an assembly-level hole should not appear in every part instance.

7.2. Drawing components

Since drawings are secretly assemblies, every view creates its own instance of the model you are showing. So that creates even more geometry. To bridge the gap between assemblies and drawings, the SOLIDWORKS API has the IDrawingComponent interface. You can get the visible drawing components in a view with IView.GetVisibleDrawingComponents and you can get the underlying Component2 object via IDrawingComponent.Component.

Unless you are doing fancy stuff with drawings, you will not need drawing components. Even in Drew, I hardly use them. I had been making add-ins for years before I discovered them 😄

7.3. An entity is only valid in the current model

This all leads up to an important conclusion: an entity is only valid in a certain context. A part entity only works within that part and an assembly entity only works within that assembly.

If you let a user select a part face in an assembly, you cannot use that entity directly to select a face when you have the part open. But you can convert them! I’ll explain that now.

8. How to use GetCorresponding to get a part entity in an assembly

8.1. How to convert a part entity to a component entity

Say you create a part and you want to use reference a face when this part is used in an assembly. You select a face and get the selected object, you don’t need to use the underlying entity. This all happens in the Model Context.

Now switch to an assembly that contains this part. We’re now working in the Assembly Context. To request the same face, you call IComponent2.GetCorresponding2 on the assembly component and pass the part’s face as an argument. This method returns a new face that belongs to the assembly context, or null if the input was incorrect. You can test it by calling the Select4 method because that method only selects the face if the context is correct.

This method works on any object with a persistent ID, by the way, so not just entities.

8.2. How to convert a component entity to a part entity

If you have a face that belongs to a component and you want to get the face that belongs to the underlying part, you need to call IModelDocExtension.GetCorresponding on the part’s model extension and pass the component face as an argument. You have now gone from the assembly context to the model context.

This method also lets you convert a face in a drawing view to a part face.

assembly and model context

How to go from part context to assembly context (right to left) and the other way around. Source: CodeStack.net

8.3. How to get an entity in a drawing view from a part entity

If you have a face that belongs to a part and you want to use it in a drawing view, you call IView.GetCorresponding and pass the part face as an argument.

To learn more about these contexts, CodeStack also has a blog post about assembly context with a few API examples.

9. All blog posts in this series

  1. The SOLIDWORKS Object Model + API explained
  2. SOLIDWORKS API: the basics – SldWorks, ModelDoc2
  3. How to work with Features 
  4. Persistent ID and sketch segment ID and more
  5. All identifiers in the SOLIDWORKS API
  6. About return values
  7. (this post) Entities and GetCorresponding
  8. Selections, math and custom properties
  9. How to create task panes and Property Manager Pages
  10. How to create your own SOLIDWORKS add-in
  11. Creating add-ins with SolidDna: the basics

Mis geen enkele post. Krijg een gratis add-in.

Schrijf je in voor onze nieuwsbrief en je krijgt onze TimeSavers add-in cadeau.