Регенерация графики листа при чтении TitleBlock

Автор Тема: Регенерация графики листа при чтении TitleBlock  (Прочитано 3047 раз)

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

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Всем привет.
Мой плагин проходит по всем листам в проекте и получает данные из параметров штампов (TitleBlock). При этом нигде не участвует транзакций. Да и запускается это все из контекста модального окна.
Однако при работе плагина происходит регенерация графики на листах и работа происходит оооочень долго!
В основном методе я сначала получаю коллекцию листов
Код - C# [Выбрать]
  1. FilteredElementCollector collector = new FilteredElementCollector(doc);
  2. viewElems.AddRange(collector.OfClass(typeof(ViewSheet)).ToElements());
Затем делаю по ним итерацию с вызовом метода чтения из штампов
Код - C# [Выбрать]
  1. for (var i = 0; i < viewElems.Count; i++)
  2. {
  3.     // Progress
  4.     // ReSharper disable once PossibleLossOfFraction
  5.     CurrentProgress = (i + 1) * 100 / viewElems.Count;
  6.     OnPropertyChanged(nameof(CurrentProgress));
  7.     System.Windows.Forms.Application.DoEvents();
  8.     //------------------------------------------------
  9.     var element = viewElems[i];
  10.     ViewSheet view = (ViewSheet)element;
  11.     if (!view.IsTemplate && view.ViewType == ViewType.DrawingSheet)
  12.     {
  13.         GetDataFromTitleBlock(view, allowedParamsInStamp, allowedSignParams);
  14.         GetDataFromView(view, allowedParamsInStamp);
  15.         // Добавляем в глобальный список, чтобы в других действиях не получать его опять
  16.         _currentDocViewSheets.Add(view);
  17.         // Добавляем в список вывода
  18.         Sheets.Add(new SheetViewListItem
  19.         {
  20.             SheetNumber = view.SheetNumber,
  21.             Name = view.Name,
  22.             Id = view.Id,
  23.             Blocked = false,
  24.             BlockedBy = String.Empty
  25.         });
  26.     }
  27. }
Ну и сам метод:
Код - C# [Выбрать]
  1. private void GetDataFromTitleBlock(ViewSheet viewSheet, List<string> allowedParameters, List<string> allowedSignParams)
  2. {
  3.     var doc = Revit_ProjectCardCommand.RevitApp.ActiveUIDocument.Document;
  4.     FilteredElementCollector collector = new FilteredElementCollector(doc, viewSheet.Id).OfCategory(BuiltInCategory.OST_TitleBlocks);
  5.     foreach (Element element in collector)
  6.     {
  7.         if (element is FamilyInstance familyInstance)
  8.         {
  9.             if(_readedTitleBlocks.Contains(familyInstance.Name)) continue;
  10.             _readedTitleBlocks.Add(familyInstance.Name);
  11.             // get nested families
  12.             GetNestedFamiliesInstances(familyInstance, allowedSignParams, doc);
  13.  
  14.             foreach (Parameter parameter in element.Parameters)
  15.             {
  16.                 if (!HasStampDataItem(parameter.Definition.Name) &&
  17.                     allowedParameters.Contains(parameter.Definition.Name))
  18.                 {
  19.                     StampDataItems.Add(CreateStampDataItemFromParameter(parameter));
  20.                 }
  21.             }
  22.         }
  23.     }
  24. }
Сейчас вот добавил сохранение имен прочитанных штампов - в коде видно:
Код - C# [Выбрать]
  1. if(_readedTitleBlocks.Contains(familyInstance.Name)) continue;
  2. _readedTitleBlocks.Add(familyInstance.Name);
Однако это не повлияло на скорость вообще никак. Предполагаю, что регенерация вызывается при получении коллекции штампов:
Код - C# [Выбрать]
  1. FilteredElementCollector collector = new FilteredElementCollector(doc, viewSheet.Id).OfCategory(BuiltInCategory.OST_TitleBlocks);

Как бы мне этого избежать? Получается, что Ревит перерисовывает весь лист (все виды), а мне нужен только один элемент

Отмечено как Решение Александр Пекшев aka Modis 08-11-2017, 17:10:07

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Сам спросил - сам отвечу )) Надеюсь, кому-нибудь пригодится мой монолог
Было выдвинуто предположение, которое оказалось верным - при получении FilteredElementCollector для конкретного вида происходит регенерация графики вида.
Поэтому сделал небольшой ход конем:
1. Сначала получаю все штампы
Код - C# [Выбрать]
  1. // Получаю все штампы
  2. FilteredElementCollector titleBlocks = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_TitleBlocks);
2. В метод GetDataFromTitleBlock передаю эту коллекцию, а там уже получаю из нее нужные (относящиеся к виду):
Код - C# [Выбрать]
  1. private void GetDataFromTitleBlock(ViewSheet viewSheet, FilteredElementCollector allTitleBlocks, List<string> allowedParameters, List<string> allowedSignParams)
  2. {
  3.     var doc = Revit_ProjectCardCommand.RevitApp.ActiveUIDocument.Document;
  4.  
  5.     var titleBlocks = allTitleBlocks.Where(x => x.OwnerViewId.IntegerValue == viewSheet.Id.IntegerValue).ToList();
  6.  
  7.      foreach (Element element in titleBlocks)
  8.     ///.......

Скорость работы сразу возросла в разы

Оффлайн Виктор Чекалин

  • Administrator
  • *****
  • Сообщений: 694
  • Карма: 111
  • Skype: chekalin-v
Александр, спасибо за разъяснение, полезная информация. Не знал о такой "фишке"

Оффлайн Павел Тер-Микаэлян

  • ADN OPEN
  • ***
  • Сообщений: 124
  • Карма: 5
Александр Пекшев aka Modis,
Добрый день. Объясните пожалуйста. Пытаюсь получить все основные надписи на листе. Делаю по аналогии:
Код - C# [Выбрать]
  1. TitleBlocks = new FilteredElementCollector(doc)
  2.                                            .OfClass(typeof(FamilySymbol))
  3.                                            .OfCategory(BuiltInCategory.OST_TitleBlocks);
  4. FamilySymbol fs = (FamilySymbol)TitleBlocks.FirstOrDefault(q =>
  5.                                             q.OwnerViewId.IntegerValue == DrawingSheet.Id.IntegerValue);
  6.  
Но q.OwnerViewId.IntegerValue всегда равно -1. Почему?
« Последнее редактирование: 31-01-2018, 10:09:44 от Pabloa »

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Но q.OwnerViewId.IntegerValue всегда равно -1. Почему?
Файл можете показать?


Оффлайн Павел Тер-Микаэлян

  • ADN OPEN
  • ***
  • Сообщений: 124
  • Карма: 5
Понял, почему не работало, мне надо было писать не .OfClass(typeof(FamilySymbol)), а .OfClass(typeof(FamilyInstance)).
Код - C# [Выбрать]
  1. IEnumerable<View> DrawingSheets = new FilteredElementCollector(doc)
  2.                                       .OfClass(typeof(ViewSheet))
  3.                                       .Cast<ViewSheet>()
  4.                                       .Where(q => q.IsTemplate == false)
  5.                                       .Where(q => q.CanBePrinted == true);
  6.  foreach (View DrawingSheet in DrawingSheets)
  7. {
  8.    FilteredElementCollector FI = new FilteredElementCollector(doc)
  9.                                             .OfClass(typeof(FamilyInstance))
  10.                                             .OfCategory(BuiltInCategory.OST_TitleBlocks);
  11.    //Первая найденная основная надпись на чертеже
  12.    Element El = FI.FirstOrDefault(q => q.OwnerViewId.IntegerValue == DrawingSheet.Id.IntegerValue);
  13. }
  14.  
И можно даже еще проще оказывается, если писать FilteredElementCollector(doc, DrawingSheet.Id)
Код - C# [Выбрать]
  1. IEnumerable<View> DrawingSheets = new FilteredElementCollector(doc)
  2.                                       .OfClass(typeof(ViewSheet))
  3.                                       .Cast<ViewSheet>()
  4.                                       .Where(q => q.IsTemplate == false)
  5.                                       .Where(q => q.CanBePrinted == true);
  6.  foreach (View DrawingSheet in DrawingSheets)
  7. {
  8. //Первая найденная основная надпись на чертеже
  9.  FamilyInstance FI = new FilteredElementCollector(doc, DrawingSheet.Id)
  10.                                             .OfClass(typeof(FamilyInstance))
  11.                                             .OfCategory(BuiltInCategory.OST_TitleBlocks)
  12.                                             .Cast<FamilyInstance>()
  13.                                             .FirstOrDefault();
  14. }
  15.  

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
мне надо было писать не .OfClass(typeof(FamilySymbol)), а .OfClass(typeof(FamilyInstance))
Можно было вообще не писать, если уже написано OfCategory(BuiltInCategory.OST_TitleBlocks)
И можно даже еще проще оказывается, если писать FilteredElementCollector(doc, DrawingSheet.Id)
Так вы ответ-то мой (отмеченный как решение) еще раз прочитайте) Да и вопрос темы...

Оффлайн Павел Тер-Микаэлян

  • ADN OPEN
  • ***
  • Сообщений: 124
  • Карма: 5
Так вы ответ-то мой (отмеченный как решение) еще раз прочитайте) Да и вопрос темы...
Ну да, я пришел к тому, с чего вы начинали) Теперь все понятно)
Действительно, ваш способ экономит кучу времени)
« Последнее редактирование: 31-01-2018, 15:30:32 от Pabloa »