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
- 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:
// 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 identifyif (cadLink == null)
{
TaskDialog.TaskDialog.Show("Error", "CAD Link not found.");return Result.Failed;
}
- Access the CAD Geometry: The geometry of the CAD link is accessed through its
Geometry
property. This returns aGeometryElement
:
GeometryElement geomElem = cadLink.get_Geometry(new Options()); // Options for detail level
- Iterate SubSolids (Key Step): Now, iterate through the
GeometryElement
to find theSubSolid
instances. These represent the individual geometric pieces (lines, arcs, etc.) from the CAD file.
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);
}
}
}
}
- 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:
privatestringGetCadLayerName(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" firstif (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 inGetCadLayerName
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:
- Create a Revit add-in project.
- Add the necessary Revit API DLL references.
- Implement the code provided above.
- Run the add-in in Revit with a model that has a linked CAD file.
- 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.