Обработка элементов в группах

Автор Тема: Обработка элементов в группах  (Прочитано 1869 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1572
  • Карма: 341
  • Отец modplus.org
    • ModPlus
Всем привет. Пытаюсь обрабатывать элементы в группах по схеме:
- разгруппировать
- обработать
- создать группы
Но Ревит себя как-то странно ведет или я ничего не понимаю.
Вот так выглядит метод:
Код - C# [Выбрать]
  1. private void NumerateInGroups(List<ElInGroup> elementsInGroups, Document doc)
  2. {
  3.     var transactionName = Language.GetFunctionLocalName(LangItem, new ModPlusConnector().LName);
  4.     if (string.IsNullOrEmpty(transactionName))
  5.         transactionName = LangItem;
  6.     using (TransactionGroup transactionGroup = new TransactionGroup(doc))
  7.     {
  8.         transactionGroup.Start($"{transactionName}: Groups");
  9.  
  10.         foreach (IGrouping<string, ElInGroup> grouping in elementsInGroups.GroupBy(e => e.GroupName))
  11.         {
  12.             List<List<ElementId>> elements = new List<List<ElementId>>();
  13.  
  14.             // ungroup and delete
  15.             Transaction transaction = new Transaction(doc);
  16.             transaction.Start("Ungroup");
  17.  
  18.             foreach (ElInGroup elInGroup in grouping)
  19.             {
  20.                 var group = (Group)doc.GetElement(new ElementId(elInGroup.GroupId));
  21.                 var grpElements = group.UngroupMembers().ToList();
  22.                 elements.Add(grpElements);
  23.             }
  24.  
  25.             transaction.Commit();
  26.  
  27.             transaction.Start("Numerate");
  28.  
  29.             foreach (ElInGroup elInGroup in grouping)
  30.             {
  31.                 foreach (var pair in elInGroup.Elements)
  32.                 {
  33.                     if (pair.Key.LookupParameter(_parameterName) is Parameter parameter)
  34.                     {
  35.                         parameter.Set(pair.Value);
  36.                     }
  37.                 }
  38.             }
  39.  
  40.             transaction.Commit();
  41.  
  42.             transaction.Start("Create new group");
  43.  
  44.             foreach (List<ElementId> elementIds in elements)
  45.             {
  46.                 Group newGroup = doc.Create.NewGroup(elementIds);
  47.                 newGroup.GroupType.Name = grouping.Key;
  48.             }
  49.  
  50.             transaction.Commit();
  51.  
  52.             //foreach (List<ElementId> elementIds in elements)
  53.             //{
  54.             //    transaction.Start("Create new group");
  55.  
  56.             //    Group newGroup = doc.Create.NewGroup(elementIds);
  57.             //    var groupType = new FilteredElementCollector(doc)
  58.             //        .OfClass(typeof(GroupType))
  59.             //        .Cast<GroupType>()
  60.             //        .FirstOrDefault(g => g.Name == grouping.Key);
  61.             //    if (groupType != null)
  62.             //        newGroup.GroupType = groupType;
  63.             //    else newGroup.GroupType.Name = grouping.Key;
  64.  
  65.             //    transaction.Commit();
  66.             //}
  67.  
  68.             transaction.Dispose();
  69.         }
  70.  
  71.         transactionGroup.Assimilate();
  72.     }
  73. }
Вспомогательный класс:
Код - C# [Выбрать]
  1. internal class ElInGroup
  2. {
  3.     public ElInGroup(Group group)
  4.     {
  5.         GroupId = group.Id.IntegerValue;
  6.         GroupName = group.Name;
  7.     }
  8.  
  9.     public int GroupId { get; }
  10.  
  11.     public string GroupName { get; set; }
  12.  
  13.     public Dictionary<Element, string> Elements { get; } = new Dictionary<Element, string>();
  14. }
Сначала список своих объектов я группирую по имени группы. Это я делаю для того, чтобы в рамках одной транзакции обрабатывать все экземпляры групп одного типа.
Потом разгруппировываю. Затем меняю нужный мне параметр, а затем создаю новые группы.
Так вот если я использую первый вариант:
Код - C# [Выбрать]
  1. transaction.Start("Create new group");
  2.  
  3. foreach (List<ElementId> elementIds in elements)
  4. {
  5.     Group newGroup = doc.Create.NewGroup(elementIds);
  6.     newGroup.GroupType.Name = grouping.Key;
  7. }
  8.  
  9. transaction.Commit();
то все хорошо за исключением одного но: Ревит создает несколько типов групп с одинаковым именем



Если я использую второй вариант:
Код - C# [Выбрать]
  1. foreach (List<ElementId> elementIds in elements)
  2. {
  3.     transaction.Start("Create new group");
  4.  
  5.     Group newGroup = doc.Create.NewGroup(elementIds);
  6.     var groupType = new FilteredElementCollector(doc)
  7.         .OfClass(typeof(GroupType))
  8.         .Cast<GroupType>()
  9.         .FirstOrDefault(g => g.Name == grouping.Key);
  10.     if (groupType != null)
  11.         newGroup.GroupType = groupType;
  12.     else newGroup.GroupType.Name = grouping.Key;
  13.  
  14.     transaction.Commit();
  15. }
то во-первых я начинаю ловить непонятные warning'ы, а во-вторых Ревит создает группы с другим именем:



При этом вишенка на торте - эти типы групп не имеют экземпляров групп! Т.е. свойство GroupSet пустое. А нужный мне тип группы (Группа массива 1) имеет все нужные мне 5 экземпляров.
Конечно можно попробовать перед вызовом метода запомнить какие были группы, а после работы метода получить новые группы и удалить пустые, но хотелось бы разобраться что не так.
Что я упускаю?

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 986
  • Карма: 296
  • Skype: alexandr.ignatovich.itc
Re: Обработка элементов в группах
« Ответ #1 : 22-07-2019, 12:25:02 »
Второй вариант выглядит правильнее. doc.Create.NewGroup создает GroupType, когда назначаете новосозданной группе GroupType, получаете сиротливый GroupType от новосозданной группы. А warning-и надо смотреть конкретнее, пока инфы не достаточно

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1572
  • Карма: 341
  • Отец modplus.org
    • ModPlus
Re: Обработка элементов в группах
« Ответ #2 : 22-07-2019, 12:35:41 »
doc.Create.NewGroup создает GroupType, когда назначаете новосозданной группе GroupType, получаете сиротливый GroupType от новосозданной группы.
Т.е. вот эти пустые GroupType - это те самые сиротки?
Значит их можно смело удалять сразу
А warning-и надо смотреть конкретнее, пока инфы не достаточно
Они вообще не проблема - я их все буду подавлять. Вообще данный функционал в плагине будет с пометкой "на свой страх и риск", потому как такие дела с группами всегда могут создать кучу проблем. Например, арматура при разгрупперовке будет сразу цеплять зависимости. И ничего тут не поделать - всех случаев не обработать

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 986
  • Карма: 296
  • Skype: alexandr.ignatovich.itc
Re: Обработка элементов в группах
« Ответ #3 : 22-07-2019, 12:43:56 »
Т.е. вот эти пустые GroupType - это те самые сиротки?

Ну да, присвоили существующий GroupType, запомнили id-шку сиротки. Потом скопом их удалить, например, там уже по ситуации смотреть, в теории, перед удалением регенерировать документ может понадобится (может и нет, надо попробовать)

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1572
  • Карма: 341
  • Отец modplus.org
    • ModPlus
Re: Обработка элементов в группах
« Ответ #4 : 22-07-2019, 12:45:27 »
Т.е. вот эти пустые GroupType - это те самые сиротки?

Ну да, присвоили существующий GroupType, запомнили id-шку сиротки. Потом скопом их удалить, например, там уже по ситуации смотреть, в теории, перед удалением регенерировать документ может понадобится (может и нет, надо попробовать)
Спасибо за разъяснение. Вечером буду пробовать

Оффлайн andy_pu

  • ADN Club
  • Сообщений: 30
  • Карма: 2
Re: Обработка элементов в группах
« Ответ #5 : 03-03-2021, 11:45:31 »
Здравствуйте. В модели добавлены общие параметры экземпляра с пометкой "значения могут изменяться по экземплярам группы".  Соответственно созданы группы с элементами, для которых включены и заполнены такие параметры. При смещении группы все значения таких параметров приходят к значениям, которые были в элементах на момент создания группы. Подскажите, пожалуйста, существует ли решение этой проблемы?

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 986
  • Карма: 296
  • Skype: alexandr.ignatovich.itc
Re: Обработка элементов в группах
« Ответ #6 : 03-03-2021, 11:54:58 »
Вопрос номер раз: имеет ли это отношение к Revit API?
Вопрос номер два: попробовал (в Revit 2019, ну какой уж был открыт в данный момент), воспроизвести не смог, какие-то особые элементы, какая-то конкретная версия Revit? Может быть, какие-то отдельно установленные плагины, в которых могут быть апдейтеры?

Ну и просьба вдогонку, на отдельные вопросы создавать отдельные темы, по крайней мере, в текущей постановке вопрос мне кажется отдельным от этой темы

Оффлайн andy_pu

  • ADN Club
  • Сообщений: 30
  • Карма: 2
Re: Обработка элементов в группах
« Ответ #7 : 03-03-2021, 12:57:26 »
Версия Revit 2019.
Вопрос в этой теме, так как появились сомнения по поводу задания значения параметра элемента, находящегося в группе, может что-то делаю не так.
Updater-ов никаких нет.
Только что перепроверил все в ручном режиме, создал новый проект, в нем нарисовал стену с дверью. Добавил строковый общий параметр "ADSK_Позиция" с пометкой "значения могут изменяться по экземплярам группы" в категорию стены и двери. Объединил стену с дверью в группу, задал значение этого параметра для двери равным "1", задал смещение для группы и проверил значение параметра "ADSK_Позиция" у двери, оно стало равным "".

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 986
  • Карма: 296
  • Skype: alexandr.ignatovich.itc
Re: Обработка элементов в группах
« Ответ #8 : 03-03-2021, 13:23:50 »
При смещении группы

Да, проблема есть, сначала просто не понял насчет смещения (что нужно было параметр задать, а не просто подвигать группу).

К сожалению, тут помочь ничем не сможем. Баг, причем именно продукта, а не API, поведение API и UI одинаковое


Оффлайн andy_pu

  • ADN Club
  • Сообщений: 30
  • Карма: 2
Re: Обработка элементов в группах
« Ответ #9 : 03-03-2021, 14:28:08 »
Думаю, что смещение может быть не единственной операцией, которая приводит к сбрасыванию значения. Это создает большие проблемы. По сути группы получаются не работоспособные как экземпляры, имеющие в некоторых параметрах разные значения.  Еще встречался с проблемой, когда при программном добавлении категории к параметру в некоторых случаях также очищаются значения параметров (но при ручной операции такого замечено не было). Причину последней проблемы также не нашел.

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 986
  • Карма: 296
  • Skype: alexandr.ignatovich.itc
Re: Обработка элементов в группах
« Ответ #10 : 03-03-2021, 15:03:46 »
Ну чтож, поплачем вместе  :'(

Причину последней проблемы также не нашел.

Тоже с таким встречался. Большое подозрение на то, что где-то когда-то добавили общий параметр с неким guid, руками поменяли имя параметра, потом нашли SharedParameterElement, удалили его и добавили снова, потом проект обновили на новую версию Revit. Но на 100% не уверен, потому как плавающая проблема.