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

18/05/2015

Метод CopyElements и параметр View

Параметр View при использовании метода CopyElements, нужно использовать только в случае, если вы работает с элементами, зависимыми от конкретного вида, т.е. 2D элементами.

Это отметил Arnošt Löbel на форуме по Revit API в теме ElementTransformUtils.CopyElements из связанного документа.

Вопрос: Я пытаюсь скопировать и вставить связанные элементы в текущий документ.

Эти действия я легко могу проделать вручную в Revit: выделить связанный элемент, нажать Ctrl+C и, затем Ctrl+V.

Но я полагаю есть какой-то подвох при использование API и вот этот код не работает:

Код - C#: [Выделить]
  1.   ElementTransformUtils.CopyElements( view3DInLink,
  2.     ids, view3DInHost, null, new CopyPasteOptions() )

Выскакивает ошибка: Заданный вид не может быть использован ни в качестве источника ни в качестве назначения при копировании элементов (The specified view cannot be used as a source or destination for copying elements between two views.). Я так полагаю, это потому что вид из связанного документа.

Оно работает, если вы просто хотите скопировать семейства из связанного документа (без вставки экземпляров семейства), например, вот так:

Код - C#: [Выделить]
  1.   ElementTransformUtils.CopyElements( linkedDoc, ids,
  2.     thisDoc, null, new CopyPasteOptions() );

Может есть какой-то другой способ копирования и вставки элементов из связанного файла? Или должен работать и этот?

Если нет, то видимо Create.NewFamilyInstance это единственный способ решения задачи.

Ответ: На сколько мне известно, метод должен работать.

Возможно стоит сделать эти действия в несколько шагов. Например, сначала скопировать некоторые вспомогательные элементы, такие как стили, затем сами экземпляры семейств.

Скорее всего из документации не очень очевидно, что метод Copy, который принимает View в качестве параметра, работает только с видо-зависимыми элементами. А судя по всему вы копируете как раз такие из 3D вида, которые не могут содержать видо-зависимые объекты, а значит и не могут быть применены в этой реализации метода. Собственно, поэтому вы и видите ошибку.

Решить проблему просто. Используйте реализацию метода Copy, которая принимает в качестве параметров два документа, а не виды. Это должно сработать.

Ответ: Спасибо за ответ.

Я наконец то понял, в чем моя ошибка. Где-то я прочитал, что нужно передать идентификаторы типоразмеров FamilySymbolIds. Я это и делал. Т.е. я передавал типоразмеры, а не экземпляры семейств.

В конце концов, я передал идентификаторы элементов, которые являются экземплярами семейств и все заработало.

Для интересующихся, вот код:

Код - C#: [Выделить]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections;
  4. using System.Collections.ObjectModel;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Windows;
  9. using Autodesk.Revit.DB;
  10. using Autodesk.Revit.UI;
  11. using Autodesk.Revit.ApplicationServices;
  12. using Autodesk.Revit.Attributes;
  13.  
  14. namespace TransferFamilys
  15. {
  16.   [TransactionAttribute(TransactionMode.Manual)]
  17.   public class CopyPasteFamilys : IExternalCommand
  18.   {
  19.     public class CopyUseDestination
  20.       : IDuplicateTypeNamesHandler
  21.     {
  22.       public DuplicateTypeAction
  23.         OnDuplicateTypeNamesFound(
  24.           DuplicateTypeNamesHandlerArgs args )
  25.       {
  26.         return DuplicateTypeAction.UseDestinationTypes;
  27.       }
  28.     }
  29.  
  30.     public Result Execute(
  31.       ExternalCommandData commandData,
  32.       ref string message,
  33.       ElementSet elements )
  34.     {
  35.       Document hostDoc = commandData.Application
  36.         .ActiveUIDocument.Document;
  37.  
  38.       // Получаем ссылки
  39.  
  40.       FilteredElementCollector links
  41.         = new FilteredElementCollector( hostDoc )
  42.           .OfClass( typeof( RevitLinkInstance ) );
  43.  
  44.       Document linkedDoc = links.Cast<RevitLinkInstance>()
  45.         .FirstOrDefault().GetLinkDocument();
  46.  
  47.       // находим семейство в связанном файле.
  48.  
  49.       FilteredElementCollector linkedFamCollector
  50.         = new FilteredElementCollector( linkedDoc );
  51.  
  52.       ICollection<ElementId> ids = linkedFamCollector
  53.         .OfClass( typeof( FamilyInstance ) )
  54.         .OfCategory( BuiltInCategory.OST_GenericModel )
  55.         .ToElementIds();
  56.  
  57.       if( ids.Count == 0 )
  58.       {
  59.         TaskDialog.Show( "Copy Paste",
  60.           "В связанном файле не содержатся элементы данной категории" );
  61.       }
  62.       else
  63.       {
  64.         using( Transaction targetTrans
  65.           = new Transaction( hostDoc ) )
  66.         {
  67.           CopyPasteOptions copyOptions
  68.             = new CopyPasteOptions();
  69.  
  70.           copyOptions.SetDuplicateTypeNamesHandler(
  71.             new CopyUseDestination() );
  72.  
  73.           targetTrans.Start(
  74.             "Копирование и вставка элементов" );
  75.  
  76.           ElementTransformUtils.CopyElements(
  77.             linkedDoc, ids, hostDoc, null,
  78.             copyOptions );
  79.  
  80.           //hostDoc.Regenerate();
  81.           targetTrans.Commit();
  82.         }
  83.       }
  84.       return Result.Succeeded;
  85.     }
  86.   }
  87. }

Источник: http://thebuildingcoder.typepad.com/blog/2015/05/copyelements-revit-2016-scalability-python-and-ruby-shells.html#2

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

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

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