Фильтры - Скрыть все элементы, кроме элементов заданной системы

Автор Тема: Фильтры - Скрыть все элементы, кроме элементов заданной системы  (Прочитано 8283 раз)

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

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
Доброго времени суток!
Теперь у меня следующая цель - при выборе воздуховода нужно что бы оставалась видима только та система,которой принадлежит этот воздуховод(остальные бы скрывались).Вот мои успехи
Код - C# [Выбрать]
  1.         Parameter Namesystem = elem.get_Parameter(BuiltInParameter.RBS_SYSTEM_NAME_PARAM);
  2.         View view = doc.ActiveView;
  3.  
  4.         IList<ElementId> categories = new List<ElementId>();
  5.         categories.Add(new ElementId(BuiltInCategory.OST_PlaceHolderDucts));
  6.         categories.Add(new ElementId(BuiltInCategory.OST_DuctLinings));
  7.         categories.Add(new ElementId(BuiltInCategory.OST_DuctInsulations));
  8.         categories.Add(new ElementId(BuiltInCategory.OST_DuctTerminal));
  9.         categories.Add(new ElementId(BuiltInCategory.OST_MechanicalEquipment));
  10.  
  11.         IList<FilterRule> rules = new List<FilterRule>();
  12.         rules.Add(ParameterFilterRuleFactory.CreateNotContainsRule(Namesystem.Id, Namesystem.AsString(), true));
  13.  
  14.         ParameterFilterElement filter = null;
  15.         using (Transaction t = new Transaction(doc, "Create and Apply Filter"))
  16.         {
  17.             t.Start();
  18.             filter = ParameterFilterElement.Create(doc, "2222", categories, rules);
  19.             view.AddFilter(filter.Id);
  20.             t.Commit();
  21.         }
  22.         using (Transaction t = new Transaction(doc, "Set Visibility Appearance"))
  23.         {
  24.             t.Start();
  25.             view.SetFilterVisibility(filter.Id, false);
  26.             t.Commit();
  27.         }
  28.  
у меня не все элементы исчезают ,которые принадлежат другим системам. я так понимаю нужно добавить строки categories.Add(new ElementId(BuiltInCategory.OST_PlaceHolderDucts)); все что начинается на OST_Duct ?
« Последнее редактирование: 23-01-2015, 08:27:48 от Виктор Чекалин »

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

  • Administrator
  • *****
  • Сообщений: 692
  • Карма: 106
  • Skype: chekalin-v
goblya,
Полезная у Вас задачка.

Попробую сформулировать вашу задача человеческим языком, а не программным.
Нужно спрятать все элементы на виде, кроме тех, у которых параметр Имя системы содержит имя интересуемой нас ситсемы.

В задаче ничего не говорится о категориях элементов. По сути, нам не важно, какая категрия у элемента. Важно, что элемент не находится в заданной системе.
Поставив ограничение на OST_Duct, ваша задача, к примеру, не будет работать с системамми трубопроводов.

Но, так нельзя создать фильтр без категорий, то задача заключается в том, чтобы спрятать все элементы всех категорий, у которых параметр Имя системы не содержит заданное значение.
Таким образом, надо включить все категории в фильтр. Получить все категории, доступные для фильтра, можно с помощью метода ParameterFilterUtilities.GetAllFilterableCategories()



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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
получается нужно создать следующую конструкцию
Код - C# [Выбрать]
  1.  
  2. categoryCheckedListBox.Items.Clear();
  3. ICollection<ElementId> filterCatIds = ParameterFilterUtilities.GetAllFilterableCategories();
  4. foreach (ElementId id in filterCatIds)
  5. {
  6. categoryCheckedListBox.Items.Add(EnumParseUtility<BuiltInCategory>.Parse((BuiltInCategory)id.IntegerValue));
  7. }
  8.  
каким образом дальше добавить полученные параметры в фильтр?

--
Для выделения кода C#, используйте пожалуйста тэг code=csharp. Так читать код гораздо приятнее.
« Последнее редактирование: 23-01-2015, 11:35:51 от Виктор Чекалин »

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

  • Administrator
  • *****
  • Сообщений: 692
  • Карма: 106
  • Skype: chekalin-v
goblya,
использовать для чего? У Вас здесь затесался список с чекбоксами для выделения категорий. Вы как его хотите использовать? В описаной первоначально задаче, пользователю не нужно ничего выделять..
Нужно просто взять все категории и передать их в фильтр.
в этой строке
Код - C# [Выбрать]
  1. filter = ParameterFilterElement.Create(doc, "2222", categories, rules);
третим параметром идет список категорий. Тип - ICollection<ElementId>

Метод ParameterFilterUtilities.GetAllFilterableCategories() возвращает тоже ICollection<ElementId>
Соответственно, нужно просто использовать этот список, вместо списка, сформированного вручную.
Код - C# [Выбрать]
  1. filter = ParameterFilterElement.Create(doc, "2222", ParameterFilterUtilities.GetAllFilterableCategories(), rules);

P.S.
Код - C# [Выбрать]
  1. EnumParseUtility<BuiltInCategory>.Parse((BuiltInCategory)id.IntegerValue)
что за велосипед? (BuiltInCategory)id.IntegerValue вполне достаточно.

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
что то он мне ошибку выдает в новой строчке
Код - C# [Выбрать]
  1.         View view = doc.ActiveView;
  2.         IList<FilterRule> rules = new List<FilterRule>();
  3.         rules.Add(ParameterFilterRuleFactory.CreateNotContainsRule(Namesystem.Id, Namesystem.AsString(), true));
  4.         ParameterFilterElement filter;
  5.         using (Transaction t = new Transaction(doc, "Create and Apply Filter"))
  6.         {
  7.             t.Start();
  8.             filter = ParameterFilterElement.Create(doc, "2222", ParameterFilterUtilities.GetAllFilterableCategories(), rules);
  9.             view.AddFilter(filter.Id);
  10.             t.Commit();
  11.         }
  12.         using (Transaction t = new Transaction(doc, "Set Visibility Appearance"))
  13.         {
  14.             t.Start();
  15.             view.SetFilterVisibility(filter.Id, false);
  16.             t.Commit();
  17.         }
  18.  
и мне не совсем понятно как данный метод ParameterFilterUtilities.GetAllFilterableCategories() отсеит именно то что содержит параметр BuiltInParameter.RBS_SYSTEM_NAME_PARAM
« Последнее редактирование: 23-01-2015, 13:19:39 от Виктор Чекалин »

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

  • Administrator
  • *****
  • Сообщений: 692
  • Карма: 106
  • Skype: chekalin-v
goblya,
Что за ошибка? Я сам не проверял метод, это только пока в теории.

не совсем понятно как данный метод ParameterFilterUtilities.GetAllFilterableCategories() отсеит именно то что содержит параметр BuiltInParameter.RBS_SYSTEM_NAME_PARAM

Метод ParameterFilterUtilities.GetAllFilterableCategories() никак не связан с параметром BuiltInParameter.RBS_SYSTEM_NAME_PARAM. Абсолютно никак. Метод лишь возвращает список категорий, которые можно использовать в фильтре. Отсеиванием занимается фильтр.

Повторюсь, Вам нужно сооздать фильтр, результатом которого будет список элементов, у которых параметр 'Имя системы' не содержит название заданной системы. Категории элементов здесь не важны. Но так как в фильтр обязатльно передать категории, то Вы просто передаете список всех возможных категорий, который как раз и возвращает метод ParameterFilterUtilities.GetAllFilterableCategories()

Мой совет. Прежде чем писать плагин, Вы попробуйте сделать абсолютно то же самое, что Вам нужно, но в пользовательском инетрфейсе. А потом дублируйте те действия, которые вы проделали в интерфейсе, с помощью кода. Так должно быть понятней, что в итоге надо реализовать.

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
выдает следующую ошибку, на всякий случай и код прикладываю

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

  • Administrator
  • *****
  • Сообщений: 692
  • Карма: 106
  • Skype: chekalin-v
Становится интересней.

Попробовал в интерфейсе сделать такой фильтр. Выбрав все категории, у меня не отображаются параметры совсем.
Исходя из описания, можно сделать вывод, что нельзя, например, для категории Стены, использовать в фильтре параметр 'Имя Системы'.

Пока все в теории, но похоже одним фильтром тут не обойтись.
1) Нужно выбрать все элементы, у которых нет параметра 'Имя системы'. Такие элементы уж точно не принадлежат ни одной системе и их, по условию задачи нужно скрыть на виде.
2) Для элементов, у которых есть свойство 'Имя системы', в значение параметра не должно содеражться название заданной системы. Это, по сути, то, что уже есть. Единственно надо как то определить правильные категории, у которых есть этот параметр.

Пока не могу сказать как.. Поищу.

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
На счет условий, 1 условие я считаю не нужным.Потому как если я работаю с планами и разрезами, то выполнение 1 условия повлечет выключения архитектуры и конструктива, тогда без архитектуры мне 1 система особо и не нужна.Если у меня 3d вид , тут возможны 2 варианта , либо у меня изометрии моих систем(при выключенной архитектуре) а значит отключать архитектуру и нет необходимости, 2 вариант это координация систем когда у меня включена инженерка и архитектура, опять же если нужно изолировать 1 систему , то просто 1 система на координации не нужна без архитектуры.
На счет фильтров, там получается что если не задавать категории или задать категорию у которой нет параметра "имя системы" (RBS_SYSTEM_NAME_PARAM) то правило обнуляется /становится пустым, т.е. нужно до создания правила обнаружить те категории у которых есть данный параметр.
На счет алгоритмов, я понимаю всю последовательность действий. если бы это был автокад и lisp то у меня бы вопросов не возникло, а вот с C# я впервые столкнулся.
« Последнее редактирование: 23-01-2015, 15:16:08 от goblya »

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

  • Administrator
  • *****
  • Сообщений: 692
  • Карма: 106
  • Skype: chekalin-v
goblya, условия я не навязываю. Ведь все от задачи зависит:)
Если нужно отобразить только элементы системы без всего остального, то нужно использовать условия, как я предложил. Если нужно скрыть только MEP элементы, но оставить элементы выбранной системы, то нужно так, как вы описали. Из иходного вопроса это не сильно было понятно.

А так, значит вам нужно использовать только второе условия, которые я описал выше.

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
так я не совсем понял как осуществить 2 вариант ,если заменить на вашу строчку
filter = ParameterFilterElement.Create(doc, "2222", ParameterFilterUtilities.GetAllFilterableCategories(), rules); то revit выдает ошибку и не создает ни фильтр ни правило

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

  • Administrator
  • *****
  • Сообщений: 692
  • Карма: 106
  • Skype: chekalin-v
goblya, полное решение задачи с примером и кодом описал в статье

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
awesome!
только у меня в этой части VS выдает ошибку
        try
        {
            r = uidoc.Selection.PickObject(ObjectType.Element,
                new SystemElementFilter(),
                "Выберите элемент системы");
        }
SystemElementFilter подчеркивает красным и пишет "the type of namespace name 'SystemElemtFilter' could not be found (are you missing a using directive or an assembly refererence?)"
и у меня еще один вопрос по этому поводу это Вы сделали только для 1 сисетмы. А если нужно выбрать 2 или 3 системы, а остальное отключить?В revit в ручную это сделать можно картинку прикладываю.
я так понимаю, нужно сделать множественный выбор(не более 3 элементов) и каким то образом сделать более сложное правило.

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

  • Administrator
  • *****
  • Сообщений: 692
  • Карма: 106
  • Skype: chekalin-v
только у меня в этой части VS выдает ошибку
Вы не скопировали класс SystemElementFilter из статьи.

А если нужно выбрать 2 или 3 системы, а остальное отключить?

Опять же в статье:) Есть пример, когда элемент находится в нескольких системах. В этом случае создается точно такой же фильтр, как ВЫ показали на скриншоте.
Код - C# [Выбрать]
  1. IList<FilterRule> rules = new List<FilterRule>();
  2.  
  3. var systems = systemName.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  4.  
  5. foreach (var system in systems)
  6. {
  7.     rules.Add(ParameterFilterRuleFactory
  8.         .CreateNotContainsRule(new ElementId(BuiltInParameter.RBS_SYSTEM_NAME_PARAM),
  9.         system.Trim(), true));
  10. }
Т.е. просто создается несколько условий.

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
на счет SystemElementFilter , это слово в статье встречается только 1 раз и только в 1 строке(поиск по статье с помощью ctrl+F выдает только 1 результат)

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

  • Administrator
  • *****
  • Сообщений: 692
  • Карма: 106
  • Skype: chekalin-v
goblya, виноват. Спасибо за замечание.
Добавил класс в статью.

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

  • ADN OPEN
  • Сообщений: 13
  • Карма: 0
да, то что доктор прописал , и если выбрать венустановку которая принадлежит 2 системам,то создается фильтр с 2 правилами.
только вот вопрос, как сделать чтобы можно было несколько элементов, которые будут принадлежать разным системам. по идее методы аналогичные
PickObject(ObjectType objectType,   ISelectionFilter selectionFilter,   string statusPrompt)
PickObjects(ObjectType objectType,ISelectionFilter selectionFilter,string statusPrompt)
но если заменить PickObject на PickObjects, выдает ошибку (файл прикладываю).
Заметил одну интересную особенность если создавать правило то при вводе вручную имени системы влезает только 26 символов "механизмы приточная вентил", но вот если программно добавлять то там свободно умещается значение "механизмы приточная вентиляция 22", мне вот интересно можно ли добавить больше 3 правил для одного фильтра программно?

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

  • Administrator
  • *****
  • Сообщений: 692
  • Карма: 106
  • Skype: chekalin-v
PickObject(ObjectType objectType,   ISelectionFilter selectionFilter,   string statusPrompt)
PickObjects(ObjectType objectType,ISelectionFilter selectionFilter,string statusPrompt)
но если заменить PickObject на PickObjects, выдает ошибку (файл прикладываю).
Описание ошибки достаточно подробно описывает причину. Меетод PickObject возвращает объект типа Reference - один выбранный объект, а PickObjects - IList<Reference> - список выбранных объектов.

мне вот интересно можно ли добавить больше 3 правил для одного фильтра программно?
Самый простой способ - проверить . По идее, так как при создании фильтра передается список правил филтрации, и в файле справке про максимальное число правил не сказано ничего, то должно работать.