A post in the forum mentions that “I have a list of Walls and I want to create a new View3D with the same walls but containing only the ‘Structure’ function layers”. We can do this nicely with the Part functionality and the Revit API.
public void ShowWallStructureOnly()
{
var doc = this.ActiveUIDocument.Document;
View3D view;
using (Transaction t = new Transaction(doc, "create wall structure view"))
{
t.Start();
view = View3D.CreateIsometric(doc, new FilteredElementCollector(doc)
.OfClass(typeof(ViewFamilyType))
.Cast<ViewFamilyType>()
.First(q => q.ViewFamily == ViewFamily.ThreeDimensional).Id);
if (doc.ActiveView is View3D)
{
view.SetOrientation(((View3D)doc.ActiveView).GetOrientation());
}
view.PartsVisibility = PartsVisibility.ShowPartsOnly;
PartUtils.CreateParts(doc, new FilteredElementCollector(doc, view.Id).OfClass(typeof(Wall))
.Where(q => PartUtils.IsValidForCreateParts(doc, new LinkElementId(q.Id)) && !PartUtils.HasAssociatedParts(doc, q.Id))
.Select(q => q.Id).ToList());
doc.Regenerate();
var toHide = new List<ElementId>();
foreach (var part in new FilteredElementCollector(doc, view.Id).OfClass(typeof(Part)))
{
// I expected DPART_ORIGINAL_TYPE would store the element id of the wall type
// but it stores the wall type's name as a string
var typeName = part.get_Parameter(BuiltInParameter.DPART_ORIGINAL_TYPE).AsString();
var wallType = new FilteredElementCollector(doc)
.OfClass(typeof(WallType))
.Cast<WallType>()
.First(q => q.Name == typeName);
var layers = wallType.GetCompoundStructure().GetLayers();
var parameter = part.get_Parameter(BuiltInParameter.DPART_LAYER_INDEX);
if (parameter == null)
{
continue;
}
// I expected DPART_LAYER_INDEX would store the index as an integer
// but it stores it as as string
var layerInt = int.Parse(parameter.AsString());
var layer = layers[layerInt - 1];
if (layer.Function != MaterialFunctionAssignment.Structure)
{
toHide.Add(part.Id);
}
}
if (toHide.Any())
view.HideElements(toHide);
t.Commit();
}
this.ActiveUIDocument.ActiveView = view;
}
An enhancement to this code could be to check the function of each wall type layer once, not once per wall.
Thank you for this nice sample. I summarised the functionality and thought my list of steps might be of interest to other as well, so here goes:
– Create new 3D isometric view
– Set parts visibility PartsVisibility.ShowPartsOnly
– Create parts from all walls
– For each part, retrieve its built-in parameter DPART_LAYER_INDEX
– Convert from string to wall compound structure layer index
– Hide part if its compound structure layer function differs from MaterialFunctionAssignment.Structure
Cheers, Jeremy.
Thank you Henry, this is a very intersting approach. I have another question is it possible to split walls by levels ?
Unfortunately there is no API access to the Split command
You can vote for this enhancement here https://forums.autodesk.com/t5/revit-ideas/make-api-methods-for-split-split-with-gap/idc-p/6882521
More info https://forums.autodesk.com/t5/revit-api-forum/split-wall/td-p/8495407
This makes total sense now, will cast my vote anyway, hopefull this will be addressed in future iterations. Thank you