ADN Open CIS
Сообщество программистов Autodesk в СНГ

15/07/2014

Список элементов инженерной системы. Продолжение

Ранее я рассказывал, как можно получить список всех элементов, принадлежащих инженерной системе.

Для этого я использовал значение параметра элемента Имя системы и затем сравнивал его с наименованием конкретной системы. Для этого я использовал фильтр ElementParameterFilter, позволяющий выбирать элементы по значению параметра:

Код - C#: [Выделить]
  1.             FilterableValueProvider valueProvider =
  2.                 new ParameterValueProvider(new ElementId(BuiltInParameter.RBS_SYSTEM_NAME_PARAM));
  3.  
  4.             FilterRule filterRule =
  5.                 new FilterStringRule(valueProvider, new FilterStringEquals(), system.Name, true);
  6.  
  7.             ElementParameterFilter systemNameParameterFilter =
  8.                 new ElementParameterFilter(filterRule);

 

Однако, данный способ работает лишь в том случае, если элемент привязан только к одной системе.

Если элемент находится в нескольких системах, то параметр Имя системы содержит список всех систем, разделенный запятыми.

 

Очевидно, что в этом случае, простое сравнение не подходит.

Первое что приходит в голову, использовать не сравнение строк, а если наименование системы находится в строке, содержащей наименования системы.

Код - C#: [Выделить]
  1.             FilterableValueProvider valueProvider =
  2.                 new ParameterValueProvider(new ElementId(BuiltInParameter.RBS_SYSTEM_NAME_PARAM));
  3.  
  4.             FilterRule filterRule =
  5.                 //new FilterStringRule(valueProvider, new FilterStringEquals(), system.Name, true);
  6.                 new FilterStringRule(valueProvider, new FilterStringContains(), system.Name, true); // так как элемент может находится в нескольких системах.
  7.  
  8.             ElementParameterFilter systemNameParameterFilter =
  9.                 new ElementParameterFilter(filterRule);
  10.  

В принципе на этом можно было бы и остановится. Но, в таком случае возможны ложные срабатывания. Например, система называется ‘Механизмы Приточный воздух 1’. Если элемент входит в систему с названием ‘Механизмы Приточный воздух 11’, ‘Механизмы Приточный воздух 12’ и т.д., то, очевидно, что эти элементы так же попадут в выборку, так как строка ‘Механизмы Приточный воздух 1’ входит в строку ‘Механизмы Приточный воздух 12’.

Для решения этой проблемы, необходимо сделать пост-обработку выбранных элементов, исключив ложные элементы. Для этого возьмем значение параметра каждого элемента, полученного в результате первичной выборки. Так как список семейств разделен запятыми, то разделим эту строку на массив строк. Каждый элемент массива будет содержать только наименование семейства.

Затем проверим, если массив содержит название исходной системы, то элемент выбран верно. В противном случае, элемент надо исключить из выборки.

Код - C#: [Выделить]
  1.             // обрабатываем каждый элемент, так как
  2.             // в выборку могу попасть лишние элементы.
  3.             // Например, в случае если имя системы ‘Механизмы Приточный воздух 1’,
  4.             // а элемент входит в систему ‘Механизмы Приточный воздух 12’
  5.             foreach (var element in elements)
  6.             {
  7.                 // Ищем параметр Имя системы
  8.                 // Он должен быть,
  9.                 // но на всякий случае не помешает проверить
  10.                 var systemNameParameter = element.get_Parameter(BuiltInParameter.RBS_SYSTEM_NAME_PARAM);
  11.                 if (systemNameParameter == null)
  12.                     continue;
  13.  
  14.                 // Берем значние параметра
  15.                 var systemNames =
  16.                     systemNameParameter.AsString();
  17.  
  18.                 // оно тоже не должно быть пустым, но лучше проверить.
  19.                 if (string.IsNullOrWhiteSpace(systemNames))
  20.                     continue;
  21.  
  22.                 // получаем массив из строки с названиями семейств, разделенных запятыми
  23.                 var systems = systemNames.Split(new[] {','});
  24.  
  25.                 // Если массив содержит название исходного семейства, то возвращаем элемент
  26.                 if (systems.Contains(system.Name))
  27.                     yield return element;
  28.             }

Полный код обновленного метода-расширения:

Код - C#: [Выделить]
  1.         public static IEnumerable<Element> GetElements(this MEPSystem system)
  2.         {
  3.             var collector = new FilteredElementCollector(system.Document);
  4.  
  5.             FilterableValueProvider valueProvider =
  6.                 new ParameterValueProvider(new ElementId(BuiltInParameter.RBS_SYSTEM_NAME_PARAM));
  7.  
  8.             FilterRule filterRule =
  9.                 //new FilterStringRule(valueProvider, new FilterStringEquals(), system.Name, true);
  10.                 new FilterStringRule(valueProvider, new FilterStringContains(), system.Name, true); // так как элемент может находится в нескольких системах.
  11.  
  12.             ElementParameterFilter systemNameParameterFilter =
  13.                 new ElementParameterFilter(filterRule);
  14.  
  15.             ElementClassFilter familyInstanceClassFilter =
  16.                 new ElementClassFilter(typeof(FamilyInstance));
  17.             ElementClassFilter mepCurveClassFilter =
  18.                 new ElementClassFilter(typeof(MEPCurve));
  19.  
  20.             ElementLogicalFilter bothClassFilter =
  21.                 new LogicalOrFilter(familyInstanceClassFilter, mepCurveClassFilter);
  22.  
  23.             var elements =
  24.                 collector
  25.                     .WhereElementIsNotElementType()
  26.                     .WherePasses(bothClassFilter)
  27.                     .WherePasses(systemNameParameterFilter);
  28.  
  29.             // обрабатываем каждый элемент, так как
  30.             // в выборку могу попасть лишние элементы.
  31.             // Например, в случае если имя системы ‘Механизмы Приточный воздух 1’,
  32.             // а элемент входит в систему ‘Механизмы Приточный воздух 12’
  33.             foreach (var element in elements)
  34.             {
  35.                 // Ищем параметр Имя системы
  36.                 // Он должен быть,
  37.                 // но на всякий случае не помешает проверить
  38.                 var systemNameParameter = element.get_Parameter(BuiltInParameter.RBS_SYSTEM_NAME_PARAM);
  39.                 if (systemNameParameter == null)
  40.                     continue;
  41.  
  42.                 // Берем значние параметра
  43.                 var systemNames =
  44.                     systemNameParameter.AsString();
  45.  
  46.                 // оно тоже не должно быть пустым, но лучше проверить.
  47.                 if (string.IsNullOrWhiteSpace(systemNames))
  48.                     continue;
  49.  
  50.                 // получаем массив из строки с названиями семейств, разделенных запятыми
  51.                 var systems = systemNames.Split(new[] {','});
  52.  
  53.                 // Если массив содержит название исходного семейства, то возвращаем элемент
  54.                 if (systems.Contains(system.Name))
  55.                     yield return element;
  56.             }
  57.  
  58.             //return elements;
  59.         }

Автор: Виктор Чекалин
Автор перевода: Виктор Чекалин

Обсуждение: http://adn-cis.org/forum/index.php?topic=858

Опубликовано 15.07.2014