Как удалить образцы линии и штриховки?

Автор Тема: Как удалить образцы линии и штриховки?  (Прочитано 9018 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Всем добрый день!

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

Метод Delete(Element.Id) не срабатывает!

Транзакция не срабатывает:

Код - vb.net [Выбрать]
  1.     Private Sub DataTransferStartButton_Click(sender As Object, e As EventArgs) Handles DataTransferStartButton.Click
  2.  
  3.         Dim App As Autodesk.Revit.UI.UIApplication = myCD.Application()
  4.         Dim UIDoc As UIDocument = App.ActiveUIDocument
  5.         Dim Doc As Document = App.ActiveUIDocument.Document
  6.  
  7.         App.OpenAndActivateDocument("C:\Users\Pashin.Evgeniy\Desktop\001_Проба.rfa")
  8.  
  9.         Dim tr As New Transaction(Doc, "Delete all materials")
  10.         tr.Start()
  11.  
  12.         Try
  13.             Dim coll As FilteredElementCollector = New FilteredElementCollector(Doc).OfClass(GetType(Material))
  14.             For Each dtSomeElement As Autodesk.Revit.DB.Material In coll
  15.  
  16.                 Doc.Delete(dtSomeElement.Id)
  17.  
  18.                 MsgBox("I kill material with name " & dtSomeElement.Name.ToString)
  19.  
  20.             Next
  21.  
  22.         Catch ex As Exception
  23.             MsgBox(ex.Message)
  24.         End Try
  25.  
  26.         tr.Commit()
  27.         tr.Dispose()
  28.  
  29.     End Sub


Что не так с этим процессом?


В Revit 2015 была проблема с удалением образцов линий и штриховок.
http://forums.autodesk.com/t5/revit-api/deleting-fill-patterns/td-p/5288817
после чего я установил Revit 2016.
Может есть проблемы с самим методом?
« Последнее редактирование: 14-03-2016, 11:43:17 от Пашин Евгений »

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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Может все дело в том, что выбираются материалы?
.OfClass(GetType(Material))

А если попробовать искать FillPaternElement ?

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
А если попробовать искать FillPaternElement ?

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


Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Суть задачи сводится к тому, чтобы из готового проекта семейства удалить стандартные образцы линий, штриховок и материалов.

То есть необходимо удалить элементы Material, LinePatternElement и FillPatternElement.

Отмечено как Решение Пашин Евгений 14-03-2016, 13:04:15

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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Вот пример удаления образцов линий:
Код - C# [Выбрать]
  1.     [Transaction(TransactionMode.Manual)]
  2.     public class Command : IExternalCommand
  3.     {
  4.         public Result Execute(
  5.           ExternalCommandData commandData,
  6.           ref string message,
  7.           ElementSet elements)
  8.         {
  9.             var uiapp = commandData.Application;
  10.             var uidoc = uiapp.ActiveUIDocument;
  11.             var doc = uidoc.Document;
  12.  
  13.             var collector = new FilteredElementCollector(doc);
  14.             var patternElementsIds = collector
  15.                 .OfClass(typeof (LinePatternElement))
  16.                 .Where(x => x.Name.IndexOf("Пунктирная", StringComparison.Ordinal) == 0)
  17.                 .Select(x => x.Id)
  18.                 .ToList();
  19.  
  20.             using (var transaction = new Transaction(doc, "delete line patterns"))
  21.             {
  22.                 transaction.Start();
  23.                 doc.Delete(patternElementsIds);
  24.                 transaction.Commit();
  25.             }
  26.            
  27.             return Result.Succeeded;
  28.         }
  29.     }

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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Проблема выше, скорее всего в том, что удаление происходит в цикле, о чем ревит вполне понятно должен ругаться. Плюс (возможно), нельзя удалять последний материал... Плюс (возможно), в семействе есть какие-нибудь зависимости, материал где-то используется, но это надо смотреть уже предметно

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Александр Игнатович, ты гений!!! Спасибо тебе!

Все сработало, но как всегда не обошлось без моих ошибок.

1. App.OpenAndActivateDocument("C:\Users\Pashin.Evgeniy\Desktop\001_Проба.rfa") должно было идти перед объявлением параметров:

Код - vb.net [Выбрать]
  1.         Dim App As Autodesk.Revit.UI.UIApplication = myCD.Application()
  2.         Dim UIDoc As UIDocument = App.ActiveUIDocument
  3.         Dim Doc As Document = App.ActiveUIDocument.Document

2. Удаление элементов Material и LinePatternElement происходит полностью, а вот FillPatternElement - кроме одной «Сплошной заливки». Здесь мне нужно было сделать проверку.
3. Удаление в цикле действительно не срабатывало... Тут я немного ошарашен, поскольку недопонимаю, причем тут цикл? Если можешь, дай ссылку, где об этой особенности можно почитать.

Я использовал форму с кнопкой, что примечательно, что форма должна запускаться именно в режиме ShowDialog.

В общем мое решение получилось таким:

Для внешней команды запускающей форму:
Код - vb.net [Выбрать]
  1. <Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)> _
  2. Public Class Ribbon_Menu_DataTransfer
  3.     Implements Autodesk.Revit.UI.IExternalCommand
  4.  
  5.     Public Function Execute(ByVal commandData As Autodesk.Revit.UI.ExternalCommandData, _
  6.             ByRef message As String, ByVal elements As Autodesk.Revit.DB.ElementSet) _
  7.             As Autodesk.Revit.UI.Result Implements Autodesk.Revit.UI.IExternalCommand.Execute
  8.         Dim myNewForm As New Data_Transfer(commandData)
  9.         myNewForm.ShowDialog()
  10.         Return Autodesk.Revit.UI.Result.Succeeded
  11.     End Function
  12. End Class

Для процедуры, выполняющей удаление образцов линий, штриховок и материалов по нажатию кнопки на форме:

Код - vb.net [Выбрать]
  1.     Private Sub DataTransferStartButton_Click(sender As Object, e As EventArgs) Handles DataTransferStartButton.Click
  2.         ' Открываем требуемый документ
  3.         myCD.Application.OpenAndActivateDocument("C:\Users\Pashin.Evgeniy\Desktop\001_Проба.rfa")
  4.         ' Объявляем переменные
  5.         Dim App As Autodesk.Revit.UI.UIApplication = myCD.Application()
  6.         Dim UIDoc As UIDocument = App.ActiveUIDocument
  7.         Dim Doc As Document = App.ActiveUIDocument.Document
  8.         ' Формируем список элементов на удаление «Штриховки»
  9.         Try
  10.             Dim coll As FilteredElementCollector = New FilteredElementCollector(Doc).OfClass(GetType(FillPatternElement))
  11.  
  12.             Dim myListOfElement As New List(Of ElementId)
  13.  
  14.             For Each dtSomeElement As Autodesk.Revit.DB.FillPatternElement In coll
  15.                 If dtSomeElement.Name.ToString <> "Сплошная заливка" Then
  16.                     myListOfElement.Add(dtSomeElement.Id)
  17.                 End If
  18.             Next
  19.             Delete_Element_By_Id(myListOfElement)
  20.         Catch ex As Exception
  21.             MsgBox(ex.Message)
  22.         End Try
  23.         ' Формируем список элементов на удаление «Матриалы»
  24.         Try
  25.             Dim coll As FilteredElementCollector = New FilteredElementCollector(Doc).OfClass(GetType(Material))
  26.  
  27.             Dim myListOfElement As New List(Of ElementId)
  28.  
  29.             For Each dtSomeElement As Autodesk.Revit.DB.Material In coll
  30.                 myListOfElement.Add(dtSomeElement.Id)
  31.             Next
  32.             Delete_Element_By_Id(myListOfElement)
  33.         Catch ex As Exception
  34.             MsgBox(ex.Message)
  35.         End Try
  36.         ' Формируем список элементов на удаление «Образцы линий»
  37.         Try
  38.             Dim coll As FilteredElementCollector = New FilteredElementCollector(Doc).OfClass(GetType(LinePatternElement))
  39.  
  40.             Dim myListOfElement As New List(Of ElementId)
  41.  
  42.             For Each dtSomeElement As Autodesk.Revit.DB.LinePatternElement In coll
  43.                 myListOfElement.Add(dtSomeElement.Id)
  44.             Next
  45.             Delete_Element_By_Id(myListOfElement)
  46.         Catch ex As Exception
  47.             MsgBox(ex.Message)
  48.         End Try
  49.     End Sub
  50.  
  51.     Public Sub Delete_Element_By_Id(ByVal lstElement As List(Of ElementId))
  52.         Dim tr As New Transaction(myCD.Application.ActiveUIDocument.Document, "Delete current element")
  53.         Try
  54.             tr.Start()
  55.             myCD.Application.ActiveUIDocument.Document.Delete(lstElement)
  56.             tr.Commit()
  57.         Catch ex As Exception
  58.             tr.Commit()
  59.             tr.Dispose()
  60.             MsgBox(ex.Message)
  61.         End Try
  62.     End Sub

Все работает!!! Спасибо!


Да, и еще... проработаю свое решение с учетом LINQ и поправлю код, но после того как пойму )))
« Последнее редактирование: 14-03-2016, 14:41:30 от Пашин Евгений »

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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Удаление в цикле действительно не срабатывало... Тут я немного ошарашен, поскольку не недопонимаю, причем тут цикл? Если можешь, дай ссылку, где об этой особенности можно почитать.

У Тэммика статья целая есть на эту тему, возможно даже не одна :-):
http://thebuildingcoder.typepad.com/blog/2012/08/do-not-delete-during-iteration.html

Ну если вкратце, удаление некоего элемента x может повлечь за собой удаление элементов y и z, изменяется структура документа, отслеживать это - слишком много геммора, поэтому просто запретили такой кейс

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Ну если вкратце, удаление некоего элемента x может повлечь за собой удаление элементов y и z, изменяется структура документа, отслеживать это - слишком много геммора, поэтому просто запретили такой кейс

Понятно. Буду читать. Спасибо за доступное объяснение. В принципе, я действительно никогда ничего не удалял в цикле, потому такой конфуз вышел )

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

  • Administrator
  • *****
  • Сообщений: 694
  • Карма: 111
  • Skype: chekalin-v
Раз уже проблема решена, то поддержу Сашу. Действительно скорее всего проблема в удалении элементов в цикле.
У Тэммика статья целая есть на эту тему, возможно даже не одна :-):
http://thebuildingcoder.typepad.com/blog/2012/08/do-not-delete-during-iteration.html
Да, точно не одна. Вот я переводил еще одну похожую статью

Оффлайн Windcastle

  • ADN OPEN
  • **
  • Сообщений: 58
  • Карма: 0
Действительно скорее всего проблема в удалении элементов в цикле.

То-то я заметил, что действие будто выполняется, а на самом деле ничего не происходит. По-отдельности все окей, а в цикле - никак! Поэтому и создал эту тему. Ну все равно большое спасибо. Завтра задача усложнится )