Level -> Rooms

Автор Тема: Level -> Rooms  (Прочитано 1875 раз)

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

Оффлайн AgensАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 223
  • Карма: 0
Level -> Rooms
« : 13-01-2020, 16:53:53 »
Вопрос может быть и дурацкий, но лучше 5 минут позора... Спрашиваю, чтобы быстрей разобраться с API...
Как, получив уровень (level) через".OfClass(typeof(Level))", определить все помещения (rooms) уровня, какой класс нужно использовать?

Пока приходится сравнивать:
Код - C# [Выбрать]
  1. if (level.Name == room.Level.Name)
...и делать выборку из всех помещений. Хочется красоты...
Спасибо...
VS2019, VBA 7.1, VB.NET, C#, ACAD2019, Revit 2020

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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Level -> Rooms
« Ответ #1 : 13-01-2020, 18:51:08 »
Есть у меня одно красивое. Правда нужен Revit 2018.1 или старше:

Код - C# [Выбрать]
  1. var roomsIds = level.GetDependentElements(new ElementCategoryFilter(BuiltInCategory.OST_Rooms));

Вообще, если сравниваете элементы, то лучшим вариантом будет сравнивать по Id, а не по имени

Оффлайн maksl

  • ADN OPEN
  • Сообщений: 21
  • Карма: 4
Re: Level -> Rooms
« Ответ #2 : 14-01-2020, 09:45:36 »
ну либо так, для более старых версий:
Код - C# [Выбрать]
  1. using Autodesk.Revit.DB.Architecture;
  2.  
  3. List<Room> roomElements = new FilteredElementCollector(Doc)
  4.                                                    .OfCategory(BuiltInCategory.OST_Rooms)
  5.                                                    .Where(r => r.LevelId.Equals(level.Id))
  6.                                                    .Select(r => r as Room)
  7.                                                    .ToList();
  8.  
  9.  

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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Level -> Rooms
« Ответ #3 : 14-01-2020, 09:52:43 »
Если уж на то пошло, то лучше так:
Код - C# [Выбрать]
  1. var levelRule = ParameterFilterRuleFactory.CreateEqualsRule(new ElementId(BuiltInParameter.ROOM_LEVEL_ID), level.Id);
  2.  
  3. var filter = new LogicalAndFilter(new ElementCategoryFilter(BuiltInCategory.OST_Rooms), new ElementParameterFilter(levelRule));
  4.  
  5. var collector = new FilteredElementCollector(doc);
  6.  
  7. var rooms = collector.WherePasses(filter).Cast<Room>();

Оффлайн maksl

  • ADN OPEN
  • Сообщений: 21
  • Карма: 4
Re: Level -> Rooms
« Ответ #4 : 14-01-2020, 10:46:07 »
Если упростить  мой вариант:
Код - C# [Выбрать]
  1. var rooms = new FilteredElementCollector(Doc)
  2.                                                    .OfCategory(BuiltInCategory.OST_Rooms)
  3.                                                    .Where(r => r.LevelId.Equals(level.Id))
  4.                                                    .Cast<Room>();
  5.  

то получается по сути то же самое. Разница в том, что у меня проверка айди уровня через Equals(), а у тебя через фильтр LogicalAndFilter (создаются новое правило и новый фильтр).

Что я упускаю, почему так будет лучше?

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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Level -> Rooms
« Ответ #5 : 14-01-2020, 10:56:56 »
Производительность.

Native код выполняется быстрее .Net-овской обёртки.

Оффлайн maksl

  • ADN OPEN
  • Сообщений: 21
  • Карма: 4
Re: Level -> Rooms
« Ответ #6 : 20-01-2020, 11:10:06 »
выдалась свободная минутка, решил посчитать, сколько эти способы будут выполняться по времени.

в тестовом проекте 30 уровней, на каждом 9 помещений.

вот такие получились выводы:
1. При каждом запуске время выполнения всегда разное. Я не знаю, что на это влияет, Ревит, CLR, DateTime...
2. Ожидаемо, нэйтив ощутимо быстрее.
3. Неожиданно, если вынести создание collector из цикла, время выполнения нэйтив-варианта вырастает в среднем до 150 мс. Видимо, магия оптимизации, какая-то.



Код - C# [Выбрать]
  1.                         Document Doc = this.ActiveUIDocument.Document;
  2.  
  3.  
  4.  
  5.                         // linq
  6.                         var startTime = DateTime.Now;
  7.                         var allRooms = new FilteredElementCollector(Doc).OfCategory(BuiltInCategory.OST_Rooms);
  8.                         foreach(Level lv in new FilteredElementCollector(Doc).OfCategory(BuiltInCategory.OST_Levels).WhereElementIsNotElementType())
  9.                         {
  10.                                 var rooms = allRooms
  11.                                         .Where(r => r.LevelId.Equals(lv.Id))
  12.                                         .Cast<Room>().ToList();
  13.                         }
  14.                        
  15.                         string linqTime = DateTime.Now.Subtract(startTime).Milliseconds.ToString();
  16.                        
  17.  
  18.                         // native
  19.                         startTime = DateTime.Now;
  20.                         foreach(Level lv in new FilteredElementCollector(Doc).OfCategory(BuiltInCategory.OST_Levels).WhereElementIsNotElementType())
  21.                         {
  22.                                 var levelRule = ParameterFilterRuleFactory.CreateEqualsRule(new ElementId(BuiltInParameter.ROOM_LEVEL_ID), lv.Id);
  23.                                 var filter = new LogicalAndFilter(new ElementCategoryFilter(BuiltInCategory.OST_Rooms), new ElementParameterFilter(levelRule));
  24.                                 var collector = new FilteredElementCollector(Doc);
  25.                                 var rooms = collector.WherePasses(filter).Cast<Room>().ToList();
  26.                         }
  27.                        
  28.                         string nativeTime = DateTime.Now.Subtract(startTime).Milliseconds.ToString();;
  29.                        
  30.                        
  31.                         // if
  32.                         startTime = DateTime.Now;
  33.                         var allRooms2 = new FilteredElementCollector(Doc).OfCategory(BuiltInCategory.OST_Rooms);
  34.                         foreach(Level lv in new FilteredElementCollector(Doc).OfCategory(BuiltInCategory.OST_Levels).WhereElementIsNotElementType())
  35.                         {
  36.                                 List<Room> rms = new List<Room>();
  37.                                 foreach(Room r in allRooms2)
  38.                                         if(r.LevelId.Equals(lv.Id))rms.Add(r);
  39.                         }
  40.                        
  41.                         string ifTime = DateTime.Now.Subtract(startTime).Milliseconds.ToString();
  42.  
  43.                         TaskDialog.Show("!", String.Format("LINQ time: {0}\r\nNATIVE time: {1}\r\nIF time: {2}",
  44.                                                                                                                                           linqTime,
  45.                                                                                                                                           nativeTime,
  46.                                                                                                                                           ifTime
  47.                                                                                                                                          ));
  48.