Placing detail group in legend view without access to UI (Design Automation)

Placing detail group in legend view without access to UI (Design Automation)

pieter4
Advisor Advisor
10,063 Views
12 Replies
Message 1 of 13

Placing detail group in legend view without access to UI (Design Automation)

pieter4
Advisor
Advisor

I am creating an application for Design Automation for Revit in which I want to place detail groups onto a legend view.

 

If I'm not mistaken, the approach would typically be

 

- change active view (https://www.revitapidocs.com/2017/b6adb74b-39af-9213-c37b-f54db76b75a3.htm)

- call PlaceGroup() (https://www.revitapidocs.com/2019/586d4f2e-0985-2d0b-dbb7-ea6d2f704336.htm)

 

However, because I am running on Design Automation, I don't have access to the UI and therefor I cannot set UIDocument.Activeview. 

 

Does anyone have any ideas for a workaround? Is there an alternative method for placing detail groups which takes in a View as an argument? Or are there ways to change the ActiveView in Design Automation?

0 Likes
Accepted solutions (2)
10,064 Views
12 Replies
Replies (12)
Message 2 of 13

jeremy_tammik
Alumni
Alumni

Good question. I asked the development team for you.

   

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

pieter4
Advisor
Advisor

Thanks Jeremy! The link doesn't work for me, but I assume this is an internal slack channel? 

0 Likes
Message 4 of 13

jeremy_tammik
Alumni
Alumni

Yes, it is just for me to navigate back and forth between the public thread and the internal one.

  

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

ricaun
Advisor
Advisor

Why do you need the UI to place a group? Do you have a sample code?

 

I created one but only require the Document.

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Linq;

namespace RevitAddin.Commands
{
    [Transaction(TransactionMode.Manual)]
    public class CommandPlaceGroup : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
        {
            UIApplication uiapp = commandData.Application;

            Document document = uiapp.ActiveUIDocument.Document;

            PlaceGroup(document);

            return Result.Succeeded;
        }

        public void PlaceGroup(Document document)
        {
            GroupType groupType = new FilteredElementCollector(document)
                .OfClass(typeof(GroupType))
                .OfType<GroupType>()
                .FirstOrDefault();

            if (groupType is null)
            {
                Console.WriteLine("No group type found.");
                return;
            }

            Console.WriteLine(groupType.Name);

            using (Transaction transaction = new Transaction(document))
            {
                transaction.Start("Place Group");
                XYZ mypoint = new XYZ(0, 0, 0);
                document.Create.PlaceGroup(mypoint, groupType);
                transaction.Commit();
            }

        }
    }
}

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 6 of 13

pieter4
Advisor
Advisor

I believe your code would work for model groups but not for detail groups. Unless I'm missing something.

Message 7 of 13

ricaun
Advisor
Advisor

Hmmm, the PlaceGroup place the group detail in the activated view.

 

Looks like you need to use the uidoc.RequestViewChange(view) to select where the group is added.

 

The method PlaceGroup works in DA?

 

I have an idea to place the group detail in the view you want. Gonna test!

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 8 of 13

ricaun
Advisor
Advisor

@pieter4 wrote:

I believe your code would work for model groups but not for detail groups. Unless I'm missing something.


The code works fine with Detail Group, the code below select only the category for DetailGroups.

GroupType groupType = new FilteredElementCollector(document)
    .OfClass(typeof(GroupType))
    .OfType<GroupType>()
    .Where(e=>e.Category.Id == new ElementId(BuiltInCategory.OST_IOSDetailGroups))
    .FirstOrDefault();

Does not see a way to put the detail group in a view you want, but you can copy between views.

Works fine in Revit just need to check if the method PlaceGroup works in DA, my guess is the group gonna be added in a random/valid view.

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 9 of 13

ricaun
Advisor
Advisor
Accepted solution

After some test and some promising result to change the View of the group using copy the detail to the new view and delete the old one.

 

Here is the code!

 

public static Group ChangeView(Group group, View newView)
{
    // Model Groups do not have an owner view
    if (group.OwnerViewId == ElementId.InvalidElementId)
        return group;

    // Group is already in the correct view
    if (group.OwnerViewId == newView.Id)
        return group;

    var document = group.Document;
    var view = document.GetElement(group.OwnerViewId) as View;

    var elementsToCopy = new [] { group.Id };

    var options = new CopyPasteOptions();

    var elements = ElementTransformUtils.CopyElements(view, elementsToCopy, newView, Transform.Identity, options);
    document.Delete(elementsToCopy);

    var newGroup = elements.Select(e => document.GetElement(e)).OfType<Group>().FirstOrDefault();
    return newGroup;
}

 

 

Unfortunately the PlaceGroup put the detail group in an invalid view (ElementId.InvalidElementId) when you open de file using Application.OpenDocumentFile, probably because that document don't have a ActiveView. The same problem happen in Design Automation for Revit.

 

Here is a video testing that in Revit for Desktop and Revit for Design Automation.

[video]

 

Looks like PlaceGroup does not work without UI when using Detail Group.

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 10 of 13

pieter4
Advisor
Advisor

Wow Ricaun, huge thanks for spending so much time looking into this!

 

Using the copy/paste approach is a great workaround! I am running my application on a custom template, so I can simply include a view that holds a 'placeholder' detail group in my template. From my application, I can then copy paste the placeholder detail group into my desired view (and then change the type). 

 

If someone would need to do this on a generic Revit file, you could search the project for a placed detail groups and copy that, but you'll be in trouble if the file does not have any placed detail groups. So it would still be nice to have an api call to place detail groups in a given view. I created a Revit idea for it here: https://forums.autodesk.com/t5/revit-ideas/api-place-detail-group-in-view/idi-p/12795311

 

 

Message 11 of 13

ricaun
Advisor
Advisor
Accepted solution

Yes, if you have a Detail Group inside your document and copy that would work.

 

I was testing exactly that.

 

public static Group CreateGroupDetail(GroupType groupType, View view, XYZ location)
{
    var document = groupType.Document;

    Group groupBase = new FilteredElementCollector(document)
        .WhereElementIsNotElementType()
        .OfCategory(BuiltInCategory.OST_IOSDetailGroups)
        .OfClass(typeof(Group))
        .OfType<Group>()
        .FirstOrDefault();

    if (groupBase is null)
    {
        throw new Exception("No group found.");
    }

    Console.WriteLine($"CreateGroupDetail using {groupBase.GroupType.Name} [{groupBase.GroupType.Id}] to {groupType.Name} [{groupType.Id}]");

    var groupView = document.GetElement(groupBase.OwnerViewId) as View;

    var elementsToCopy = new[] { groupBase.Id };
    var options = new CopyPasteOptions();
    var elements = ElementTransformUtils.CopyElements(groupView, elementsToCopy, view, Transform.Identity, options);

    var newGroup = elements.Select(e => document.GetElement(e)).OfType<Group>().FirstOrDefault();
    newGroup.ChangeTypeId(groupType.Id);

    var locationPoint = newGroup.Location as LocationPoint;
    var oldLocation = locationPoint.Point;
    locationPoint.Point = location;

    Console.WriteLine($"CreateGroupDetail location {oldLocation} to {locationPoint.Point}");

    return newGroup;
}

 

 

Work great but you need to have a Detail Group inside the document in some view, a placeholder like you mention.

 

Maybe would be possible to copy a view from another document with a detail inside if the main document does not have a Detail Group instance. Would be fun to experiment and useful to fix others Revit API limitations.

 

PS: Should be a good idea to edit the Revit idea and add the link about this post, so people could find a workaround solution and reference about the issue.

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 12 of 13

pieter4
Advisor
Advisor
It seems we cannot edit ideas after posting them (which kinda makes sense), so I added it as a comment. Again huge thanks for looking into this. Much appreciated.
Message 13 of 13

ricaun
Advisor
Advisor

@pieter4 wrote:
It seems we cannot edit ideas after posting them (which kinda makes sense), so I added it as a comment.

Now thinking makes sense, you could get many votes and than change the idea 😂

 


@pieter4 wrote:
Again huge thanks for looking into this. Much appreciated.

No worries, was fun to looking into that. 😀

 

I created another video with the unit test project for the PlaceGroup problem.

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes