RTCNA Wish #1: Replace detail groups with detail components

Michael McCune sent a wish via Twitter to “replace detail group instances with a detail component”.

That’s a good wish, and one that can almost be completely granted via the API as shown in this video.

The limitation is that the API provides no way to identify the rotation angle of a group instance. For any element in a subclass of the Instance class (such as a family instance, import instance, or Revit link instance) the API provides GetTransform() which contains the data needed to determine the instance’s rotation angle. The AssemblyInstance class also implements GetTransform().

Unfortunately, the Group class has no such method. As a result, while we could rotate the newly created detail components, there is no way to query the detail group instance to determine how much each detail component should be rotated.

public void detailGroupToComponent()
{
    Document doc = this.ActiveUIDocument.Document;
    
    // create a dictionary to store the mapping between detail groups and detail component
    // the NewLine character is used to delimit the family name and family type name
    Dictionary<string, string> groupComponentDict = new Dictionary<string, string>();
    groupComponentDict.Add("DG1","DetailComponent1" + Environment.NewLine + "Type 1");
    groupComponentDict.Add("filled regions","DetailComponent2" + Environment.NewLine + "Type 2");
    
    using (Transaction t = new Transaction(doc,"Detail Groups -> Detail Components"))
    {
        t.Start();    
        
        // find all group instances in the document with the Detail Groups category
        IEnumerable<ElementId> groups =  new FilteredElementCollector(doc)
            .OfClass(typeof(Group))
            .OfCategory(BuiltInCategory.OST_IOSDetailGroups).ToElementIds();
        
        foreach (ElementId id in groups)
        {
            Group g = doc.GetElement(id) as Group;
            
            // get the XYZ location of the group instance
            Location location = g.Location;
            LocationPoint lp = location as LocationPoint;
            XYZ xyz = lp.Point;
            
            // get the view that owns the group instance
            ElementId ownerviewId = g.OwnerViewId;
            View ownerview = doc.GetElement(ownerviewId) as View;
            
            // lookup the name of the family that will replace this group instance
            string familyNameType = groupComponentDict[g.Name];
            
            // split the family name / family type string
            string[] split = familyNameType.Split(new string[] {Environment.NewLine}, StringSplitOptions.None);
            string famName = split[0];
            string typeName = split[1];
            
            // find the FamilySymbol (which is the API name for the Family Type)
            FamilySymbol fs = new FilteredElementCollector(doc)
                .OfClass(typeof(FamilySymbol))
                .Cast<FamilySymbol>()
                .FirstOrDefault(q => q.Family.Name == famName && q.Name == typeName);

            // delete the group instance
            doc.Delete(g.Id);
            
            // create an instance of the detail component
            doc.Create.NewFamilyInstance(xyz, fs, ownerview);
        }
        t.Commit();
    }
}
Advertisements

2 thoughts on “RTCNA Wish #1: Replace detail groups with detail components

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s