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

ADN Club => Civil 3D API => Тема начата: Doublefish от 11-06-2014, 08:18:59

Название: Как получить имя семейства трубы?
Отправлено: Doublefish от 11-06-2014, 08:18:59
Добрый день

подскажите пожалуйста

дано id трубы - как узнать имя семейства этой трубы?
Название: Re: Как получить имя семейства трубы?
Отправлено: Дмитрий Загорулькин от 11-06-2014, 09:03:19
С помощью NET API - никак. По крайней мере, так было в версии 2013. Я уже выяснял этот вопрос в ADN.
Вроде пока ничего не изменилось.
Как обходной путь - семейство можно получить с помощью COM API.

Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2.  
  3. using Autodesk.Civil.DatabaseServices;
  4.  
  5. using Autodesk.AutoCAD.Interop;
  6. using Autodesk.AECC.Interop.Land;
  7. using Autodesk.AECC.Interop.UiLand;
  8. using Autodesk.AECC.Interop.Pipe;
  9.  
  10. namespace Support
  11. {
  12.     public static class NetworkSupport
  13.     {
  14.         /// <summary>
  15.         /// Получение имени семейства элементов для колодца при помощи COM
  16.         /// </summary>
  17.         /// <param name="structure">Колодец, объект типа Autodesk.Civil.DatabaseServices.Structure</param>
  18.         /// <returns>Строка - имя семейства элементов из каталога для указанного колодца</returns>
  19.         public static string GetStructureFamilyCOM(this Structure structure)
  20.         {
  21.             try
  22.             {
  23.                 IAeccStructure structCOM = (IAeccStructure)structure.AcadObject;
  24.                 IAeccPartFamily partFamCOM = structCOM.PartFamily;
  25.                 return partFamCOM.Name;
  26.             }
  27.             catch
  28.             {
  29.                 Application.ShowAlertDialog(string.Format("Ошибка получения данных о семействе колодца {0}", structure.Name));
  30.                 return null;
  31.             }
  32.         }
  33.     }
  34. }
  35.  
Название: Re: Как получить имя семейства трубы?
Отправлено: Дмитрий Загорулькин от 11-06-2014, 17:05:19
Надеюсь, проблем с подключением COM библиотек и адаптацией кода под трубы (ID труб) нет? :)
Название: Re: Как получить имя семейства трубы?
Отправлено: Doublefish от 16-06-2014, 07:55:51
Работает  :)
Название: Re: Как получить имя семейства трубы?
Отправлено: German от 24-06-2014, 10:09:08
С помощью NET API - никак. По крайней мере, так было в версии 2013. Я уже выяснял этот вопрос в ADN.
Вроде пока ничего не изменилось.
Как обходной путь - семейство можно получить с помощью COM API.
Если я правильно понял, можно и без COM: http://forums.autodesk.com/t5/AutoCAD-Civil-3D-Customization/Finding-out-which-Part-Family-the-pipe-is-from/m-p/3645320#M6716
Название: Re: Как получить имя семейства трубы?
Отправлено: Александр Ривилис от 24-06-2014, 11:35:31
Если я правильно понял, можно и без COM: http://forums.autodesk.com/t5/AutoCAD-Civil-3D-Customization/Finding-out-which-Part-Family-the-pipe-is-from/m-p/3645320#M6716
Нет. Ты неправильно понял. Используется всё-равно ActiveX/COM, но благодаря позднему связыванию (Reflection) нет необходимости подключать COM-Interop сборки.
Название: Re: Как получить имя семейства трубы?
Отправлено: German от 24-06-2014, 13:42:17
Нет. Ты неправильно понял. Используется всё-равно ActiveX/COM, но благодаря позднему связыванию (Reflection) нет необходимости подключать COM-Interop сборки.
Александр, спасибо.
Подскажите, а вот такой метод возможно аналогично "обернуть" или нет:  AddFromPolyline  (http://docs.autodesk.com/CIV3D/2012/ENU/API_Reference_Guide/com/AeccXLandLib__IAeccLandFeatureLines.htm) ?
Название: Re: Как получить имя семейства трубы?
Отправлено: Александр Ривилис от 24-06-2014, 13:59:55
Подскажите, а вот такой метод возможно аналогично "обернуть" или нет: AddFromPolyline ?
Теоретически возможно, но я такое не напишу. Так что пользуйся ранним связыванием. :)
P.S.: Вообще-то можно попробовать через dynamic (http://msdn.microsoft.com/ru-ru/library/dd264736%28v=vs.100%29.aspx)
Кажется он появился в .NET 4.0
Название: Re: Как получить имя семейства трубы?
Отправлено: Дмитрий Загорулькин от 25-06-2014, 12:30:11
А я правильно понимаю, что используя позднее связывание вместо подключения COM библиотек, мы теряем в скорости работы программы?
Название: Re: Как получить имя семейства трубы?
Отправлено: Александр Ривилис от 25-06-2014, 12:57:19
В принципе да. Но реальные потери зависят от того, насколько это массовая операция, т.е. она выполняется один раз, десять или десять миллионов...
Название: Re: Как получить имя семейства трубы?
Отправлено: Дмитрий Загорулькин от 25-06-2014, 13:10:22
Ну если речь идет о сетях, то объектов в одном чертеже может быть несколько сотен максимум. Другое дело, что COM свойства и методы приходится использовать с завидной регулярностью... Навскидку, операций может набежать несколько тысяч: получение свойств каждого объекта, плюс какие-то методы, пока не реализованные в NET. Наверное, в этом случае стоит думать о сокращении времени работы отдельных методов? :)
Название: Re: Как получить имя семейства трубы?
Отправлено: Александр Ривилис от 25-06-2014, 13:15:26
Есть способ, который позволяет ускорить выполнение Reflection - Expression. Пример его использования: http://www.theswamp.org/index.php?topic=44191.msg494532#msg494532
Но насколько будет выигрыш я предугадать не берусь - нужно тестировать.
Название: Re: Как получить имя семейства трубы?
Отправлено: Дмитрий Загорулькин от 17-01-2017, 17:03:27
Как обходной путь - семейство можно получить с помощью COM API.
Вот же засада! Если попытаться получить имя семейства в событиях Database.ObjectOpenedForModify или Database.ObjectModified - возникает исключение, и имя семейства никак не получить. Вот как проверить, изменилось ли у элемента семейство или нет? Самое здравое - это смотреть исходное состояние в Database.ObjectOpenedForModify и сравнивать с состоянием в Database.ObjectModified. Но в этом случае такой подход никак не хочет работать!
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.Runtime;
  4. using Autodesk.Civil.DatabaseServices;
  5. using Autodesk.AECC.Interop.Pipe;
  6.  
  7. namespace CivilTest
  8. {
  9.     public class FamilySizeTest
  10.     {
  11.         [CommandMethod("RunComTest", CommandFlags.Modal | CommandFlags.NoBlockEditor)]
  12.         public void Run()
  13.         {
  14.             Document adoc = Application.DocumentManager.MdiActiveDocument;
  15.             Database db = adoc.Database;
  16.            
  17.             db.ObjectOpenedForModify -= Db_ObjectOpMod;
  18.             db.ObjectModified -= Db_ObjectMod;
  19.             db.ObjectOpenedForModify += Db_ObjectOpMod;
  20.             db.ObjectModified += Db_ObjectMod;
  21.         }
  22.  
  23.         [CommandMethod("StopComTest", CommandFlags.Modal | CommandFlags.NoBlockEditor)]
  24.         public void Stop()
  25.         {
  26.             Document adoc = Application.DocumentManager.MdiActiveDocument;
  27.             Database db = adoc.Database;
  28.  
  29.             db.ObjectOpenedForModify -= Db_ObjectOpMod;
  30.             db.ObjectModified -= Db_ObjectMod;
  31.         }
  32.  
  33.         private void Db_ObjectOpMod(object sender, ObjectEventArgs e)
  34.         {
  35.             if (e.DBObject is Part)
  36.             {
  37.                 string famName = GetPartFamilyName(e.DBObject as Part);
  38.                 Application.ShowAlertDialog("Part opened for modify. Part family: " + famName);
  39.             }
  40.         }
  41.  
  42.         private void Db_ObjectMod(object sender, ObjectEventArgs e)
  43.         {
  44.             if (e.DBObject is Part)
  45.             {
  46.                 string famName = GetPartFamilyName(e.DBObject as Part);
  47.                 Application.ShowAlertDialog("Part modified. Part family: " + famName);
  48.             }
  49.         }
  50.  
  51.         string GetPartFamilyName(Part part)
  52.         {
  53.             string ret;      
  54.             try
  55.             {      
  56.                 IAeccPipeNetworkPart partCom = (IAeccPipeNetworkPart)part.AcadObject;
  57.                 IAeccPartFamily partFamilyCom = (IAeccPartFamily)partCom.PartFamily;
  58.                 ret = partFamilyCom.Name;
  59.             }
  60.             catch
  61.             {
  62.                 ret = "*ERROR*";
  63.             }            
  64.             return ret;
  65.         }
  66.     }
  67. }
  68.  
Название: Re: Как получить имя семейства трубы?
Отправлено: Александр Ривилис от 17-01-2017, 17:22:47
Интересно, а через DXF добраться до PartFamily нельзя?
Название: Re: Как получить имя семейства трубы?
Отправлено: Дмитрий Загорулькин от 17-01-2017, 17:28:12
Похоже, что нет  :(.
Я проверил и в ARXDBG и в MGDDBG - у элемента нет никаких ссылок на семейство.
Уже весь мозг себе сломал пытаясь найти выход.
Название: Re: Как получить имя семейства трубы?
Отправлено: Александр Ривилис от 17-01-2017, 17:34:10
А какое исключение возникает в событиях?
Название: Re: Как получить имя семейства трубы?
Отправлено: Дмитрий Загорулькин от 17-01-2017, 17:48:25
Неопознанное  ???
Название: Re: Как получить имя семейства трубы?
Отправлено: Александр Ривилис от 17-01-2017, 18:07:42
Хм. А если попробовать как-то так:

Код - C# [Выбрать]
  1. string GetPartFamilyName(Part part)
  2. {
  3.     string ret;
  4.     bool isUpgrade = false;      
  5.     try
  6.     {  
  7.         isUpgrade = part.UpgradeFromNotify();  
  8.         IAeccPipeNetworkPart partCom = (IAeccPipeNetworkPart)part.AcadObject;
  9.         IAeccPartFamily partFamilyCom = (IAeccPartFamily)partCom.PartFamily;
  10.         ret = partFamilyCom.Name;
  11.     }
  12.     catch
  13.     {
  14.         ret = "*ERROR*";
  15.     }  
  16.     if (isUpgrade) part.DowngradeToNotify();
  17.     return ret;
  18. }
Название: Re: Как получить имя семейства трубы?
Отправлено: Дмитрий Загорулькин от 17-01-2017, 18:34:18
eNotApplicable на строке:
Код - C# [Выбрать]
  1. isUpgrade = part.UpgradeFromNotify();
Название: Re: Как получить имя семейства трубы?
Отправлено: Александр Ривилис от 17-01-2017, 18:37:06
Тогда увы...
Название: Re: Как получить имя семейства трубы?
Отправлено: Дмитрий Загорулькин от 17-01-2017, 19:40:37
В общем-то, небольшую обходную лазейку нащупал. Изменение семейства у элемента в Civil возможно только при выполнении команды "AECCSWAPNETWORKPART". Если объект был предварительно выбран перед запуском этой команды, то такой код работает:
Извините, вам запрещён просмотр содержимого спойлеров.

Если удастся отловить выбор объектов после запуска команды, то можно считать, что проблема решена.
Название: Re: Как получить имя семейства трубы?
Отправлено: Дмитрий Загорулькин от 17-01-2017, 20:07:23
Фух... Не самый простой путь, но работает, зараза  :D
Извините, вам запрещён просмотр содержимого спойлеров.