Filtering Geometry based On CAD Layers

Filtering Geometry based On CAD Layers

sensiblehira
Advocate Advocate
399 Views
5 Replies
Message 1 of 6

Filtering Geometry based On CAD Layers

sensiblehira
Advocate
Advocate

I need to filter the geometry in my cad file based on the layer (layer name).

I have tried previous examples in which GeometryObject had the property of GraphicStyleId. But the name of the GraphicStyle extracted from the objects is coming out to be the same as the name of the CAD document linked. So I am not sure how to proceed. Please help.

I am using Revit 2025.

0 Likes
400 Views
5 Replies
Replies (5)
Message 2 of 6

sensiblehira
Advocate
Advocate

There is not even a material associated to the geometries so that they can be filtered

0 Likes
Message 3 of 6

jeremy_tammik
Alumni
Alumni

I asked Gemini for you, as I described in the blog, and it replies:

   

Let's dive into filtering CAD geometry by layer in Revit 2025. You're right, relying on GraphicStyleId alone won't work directly for CAD layers. That property reflects the Revit graphic style, not the original CAD layer. CAD layers are preserved as metadata within the imported geometry. Here's a robust approach using the SubSolid approach, which is generally more reliable than older, less direct methods.

Understanding the Challenge

CAD imports in Revit are treated as a single "entity" initially. The individual lines, arcs, etc., are contained within this entity. We need to "drill down" into the geometry to access the layer information associated with each piece. This is where SubSolid comes in.

The Solution: Iterating SubSolids and Extracting Layer Information

  1. Get the CAD Link Instance: First, you need to get a reference to the linked CAD instance in your Revit model. This is standard Revit API work:
C#
 
// Assuming 'doc' is your Revit Document and 'cadLinkName' is the name of your CAD link instance.
FilteredElementCollector collector = new FilteredElementCollector(doc);
collector.OfClass(typeof(CADLinkInstance));

CADLinkInstance cadLink = collector.Cast<CADLinkInstance>()
    .FirstOrDefault(c => c.Name.Equals(cadLinkName)); // Or other criteria to identify

if (cadLink == null)
{
    TaskDialog.TaskDialog.Show("Error", "CAD Link not found.");
    return Result.Failed;
}
  1. Access the CAD Geometry: The geometry of the CAD link is accessed through its Geometry property. This returns a GeometryElement:
C#
 
GeometryElement geomElem = cadLink.get_Geometry(new Options()); // Options for detail level
  1. Iterate SubSolids (Key Step): Now, iterate through the GeometryElement to find the SubSolid instances. These represent the individual geometric pieces (lines, arcs, etc.) from the CAD file.
C#
 
foreach (GeometryObject geomObj in geomElem)
{
    if (geomObj is Solid solid) // Check if it is a Solid
    {
        foreach (Solid subSolid in solid.GetAllSubSolids())
        {
            // Now we have a SubSolid.  Get its metadata.
            string cadLayerName = GetCadLayerName(subSolid, cadLink);
            if (!string.IsNullOrEmpty(cadLayerName))
            {
                // Filter based on cadLayerName (e.g., if (cadLayerName == "YourLayerName"))
                // ... your filtering logic here ...
                // Example:  Create a new geometry element with the filtered subsolid
                // GeometryElement filteredGeom = new GeometryElement();
                // filteredGeom.Append(subSolid);
            }
        }
    }
}
  1. Extracting the CAD Layer Name (Crucial Function): This is where the magic happens. The layer information is stored as a parameter on the SubSolid. We'll use a helper function to extract it:
C#
 
private string GetCadLayerName(Solid subSolid, CADLinkInstance cadLink)
{
    string layerName = null;

    // Get the "Layer" parameter.  The exact parameter *name* might vary slightly 
    // depending on the CAD software that created the file.  Try "Layer", "CAD Layer", etc.
    // Using a try-catch block is crucial to handle variations.

    try
    {
        Parameter layerParam = subSolid.LookupParameter("Layer"); // Try "Layer" first
        if (layerParam != null && layerParam.StorageType == StorageType.String)
        {
            layerName = layerParam.AsString();
        }
        else
        {
            layerParam = subSolid.LookupParameter("CAD Layer"); // Try "CAD Layer"
            if (layerParam != null && layerParam.StorageType == StorageType.String)
            {
                layerName = layerParam.AsString();
            }
        }
    }
    catch (Exception ex)
    {
        // Handle exceptions (e.g., log it, show a message)
        System.Diagnostics.Debug.WriteLine("Error getting layer parameter: " + ex.Message);
    }

    return layerName;
}

Key Improvements and Explanations:

  • GetAllSubSolids(): This is the most reliable way to access individual geometric entities within the CAD import.
  • Parameter Lookup: The code now attempts to find the layer name by looking for the parameter called "Layer" or "CAD Layer". You might need to adjust this if your CAD software uses a different name. The try-catch block is crucial to handle cases where the parameter might not exist.
  • Error Handling: The try-catch block in GetCadLayerName is essential for robustness. CAD files can vary, and the parameter names might not always be consistent.
  • Filtering Logic: The code provides a clear placeholder for your filtering logic. You can now filter based on cadLayerName as needed.
  • Example of GeometryElement Creation: The code now shows how to create a new geometry element from the filtered subsolids. This is helpful if you want to isolate the geometry from a specific layer.

Practical Demonstration:

  1. Create a Revit add-in project.
  2. Add the necessary Revit API DLL references.
  3. Implement the code provided above.
  4. Run the add-in in Revit with a model that has a linked CAD file.
  5. Debug and test the code to ensure it correctly filters the geometry based on the layer name.

This revised approach provides a more robust and practical solution for filtering CAD geometry by layer in Revit. Remember to adjust the parameter name lookup if necessary and handle potential exceptions gracefully. This method is much more reliable than previous approaches and leverages the power of the SubSolid methodology. Let me know if you have any other questions.

    

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 4 of 6

sensiblehira
Advocate
Advocate

thanks for the reply @jeremy_tammik, by CADLinkInstance do you mean ImportInstance?

and I searched the Revit SDK 2025 as well but couldn't find the method GetAllSubSolids() for the Solid class.

0 Likes
Message 5 of 6

lvirone
Enthusiast
Enthusiast

Hi @jeremy_tammik 

 

Like @sensiblehira I can't find the method GetSubSolids() on Solid or SolidUtils classes. I think Gemini has an hallucinations, am I wrong ? Like the CADLinkInstance which replace the API class ImportInstance.

 

Even in Revit 2025 I don't know any method to get the geometry of a specific layer in a CAD import, but I hope I'm wrong and someone will post it someday or the API will provide this method !

 

And unfortunately the method "Explode CAD" in Revit UI is not reachable by Revit API, even in PostableCommand :

https://forums.autodesk.com/t5/revit-api-forum/capturing-screenshot-after-exploding-a-dwg-cad/td-p/1...

https://forums.autodesk.com/t5/revit-api-forum/explode-dwg-api-postablecommand/td-p/7559245

 

So, As far as I know, there is no way.

0 Likes
Message 6 of 6

sensiblehira
Advocate
Advocate

Yes couldn't find the solution. It does not exists currently.

0 Likes