Описание слоя

Автор Тема: Описание слоя  (Прочитано 8988 раз)

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

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

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Описание слоя
« : 24-10-2015, 12:20:26 »
Всем привет. При попытке погуглить проблему нашел только такой-же вопрос и тот в комментариях к записи
Суть проблемы следующая - при создании и добавлении новых слоев им не добавляются описания (Description)
На всякий случай прикладываю часть кода:
- Создаю список слоев
Код - C# [Выбрать]
  1. private static List<LayerTableRecord> GetMpStandardsLayers()
  2. {
  3.     var layers = new List<LayerTableRecord>();
  4.     var acLyrTblRec = new LayerTableRecord
  5.     {
  6.         Name = "Mp_Основная",
  7.         Color = Color.FromColorIndex(ColorMethod.ByAci, 7),
  8.         LineWeight = LineWeight.LineWeight040,
  9.         Description = "Слой для основных линий"
  10.     };
  11.     layers.Add(acLyrTblRec);
  12.     acLyrTblRec = new LayerTableRecord
  13.     {
  14.         Name = "Mp_Тонкая",
  15.         Color = Color.FromColorIndex(ColorMethod.ByColor, 253),
  16.         LineWeight = LineWeight.LineWeight020,
  17.         Description = "Слой для тонких линий"
  18.     };
  19.     layers.Add(acLyrTblRec);
  20.     ///...................... и так далее еще слои..................///
  21.     return layers;
  22. }
- добавляю список в чертеж
Код - C# [Выбрать]
  1. var doc = AcApp.DocumentManager.MdiActiveDocument;
  2. var db = doc.Database;
  3. using (doc.LockDocument())
  4. {
  5.     using (var tr = doc.TransactionManager.StartTransaction())
  6.     {
  7.         // layers
  8.         using (var lyrTbl = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable)
  9.         {
  10.             if (lyrTbl != null)
  11.                 foreach (var layersList in LayersLists)
  12.                 {
  13.                     if (!layersList.Selected) continue;
  14.                     foreach (var layer in layersList.Layers)
  15.                     {
  16.                         if (lyrTbl.Has(layer.Name)) continue;
  17.                         lyrTbl.UpgradeOpen();
  18.                         lyrTbl.Add(layer);
  19.                         tr.AddNewlyCreatedDBObject(layer, true);
  20.                     }
  21.                 }
  22.         }
  23.         tr.Commit();
  24.     }
  25. }
Я тестировал только на 2010 автокаде, хотя в комментарии (что в ссылке выше) человек говорит, что в 2012, 2013 такая-же проблема

Оффлайн art_rrc

  • ADN Club
  • **
  • Сообщений: 70
  • Карма: 1
  • Skype: art_sapranovich
Re: Описание слоя
« Ответ #1 : 24-10-2015, 13:05:31 »
Интересно, причем даже если задать описание вручную, а потом скопировать объекты в другой чертеж, без данного слоя, то описание не сохраняется. Т.е. даже при успешной реализации, в дальнейшей работе могут быть неудобства. Похоже на баг.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Описание слоя
« Ответ #2 : 24-10-2015, 14:28:47 »
Суть проблемы следующая - при создании и добавлении новых слоев им не добавляются описания (Description)
Проверю. Если ошибка будет воспроизводится в последней версии AutoCAD - отправлю в ADN DevHelp.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Описание слоя
« Ответ #3 : 24-10-2015, 15:32:20 »
Проверил в AutoCAD 2015 следующий код:

Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.EditorInput;
  7.  
  8. #pragma warning disable 0618
  9.  
  10. [assembly: CommandClass(typeof(Rivilis.AddLayerDescription))]
  11.  
  12. namespace Rivilis
  13. {
  14.   public class AddLayerDescription
  15.   {
  16.     const string LayerName = "Rivilis_Layer";
  17.     const string LayerDescription = "Rivilis Layer";
  18.     [CommandMethod("AddDescription")]
  19.     public void AddDescription()
  20.     {
  21.       Document doc = Application.DocumentManager.MdiActiveDocument;
  22.       if (doc == null) return;
  23.       Editor ed = doc.Editor;
  24.       Database db = doc.Database;
  25.       using (SymbolTable st = db.LayerTableId.Open(OpenMode.ForRead) as SymbolTable) {
  26.         LayerTable lt = st.IncludingErased as LayerTable;
  27.         if (lt.Has(LayerName)) {
  28.           using (LayerTableRecord ltr = lt[LayerName].Open(OpenMode.ForWrite) as LayerTableRecord) {
  29.             ltr.Description = LayerDescription;
  30.           }
  31.         } else {
  32.           using (LayerTableRecord ltr = new LayerTableRecord()) {
  33.             ltr.Name = LayerName;
  34.             lt.UpgradeOpen();
  35.             lt.Add(ltr);
  36.             lt.DowngradeOpen();
  37.             ltr.Description = LayerDescription;
  38.           }
  39.         }
  40.       }
  41.     }
  42.   }
  43. }

Смотрим видео:



Как видишь код работает. Похоже в одной из последних версий исправили. Хотя можешь на всякий случай проверить у себя мой код.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Описание слоя
« Ответ #4 : 24-10-2015, 15:44:10 »
На всякий случай проверил в AutoCAD 2012 (2010-го у меня под руками нет):



Как видишь тоже работает. В коде пришлось сделать одну правку. Строка 26 теперь выглядит так:

Код - C# [Выбрать]
  1.         LayerTable lt = /* st.IncludingErased */ st  as LayerTable;
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Описание слоя
« Ответ #5 : 24-10-2015, 15:57:38 »
Интересно, причем даже если задать описание вручную, а потом скопировать объекты в другой чертеж, без данного слоя, то описание не сохраняется. Т.е. даже при успешной реализации, в дальнейшей работе могут быть неудобства. Похоже на баг.

Не подтверждаю:

Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Описание слоя
« Ответ #6 : 24-10-2015, 16:14:17 »
Как видишь код работает. Похоже в одной из последних версий исправили. Хотя можешь на всякий случай проверить у себя мой код.
Подтверждаю - работает...НО!
Если в вашем коде поменять строки 32-37 на такой вариант
Код - C# [Выбрать]
  1. using (LayerTableRecord ltr = new LayerTableRecord())
  2. {
  3.     ltr.Name = LayerName;
  4.     ltr.Description = LayerDescription;
  5.     lt.UpgradeOpen();
  6.     lt.Add(ltr);
  7.     lt.DowngradeOpen();
  8. }
то не работает! И это важно, к сожалению.
Попробуйте сначала создать коллекцию c LayerTableRecord, а потом эту коллекцию добавить в чертеж. Соответственно с описаниями. Я пока не вижу вариантов как это сделать, чтобы описания появились...

Отмечено как Решение Александр Ривилис 24-10-2015, 17:17:08

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Описание слоя
« Ответ #7 : 24-10-2015, 16:16:41 »
Значит не будешь менять строки, а будешь использовать вариант, который работает.
Работает и такой вариант:
Код - C# [Выбрать]
  1.           using (LayerTableRecord ltr = new LayerTableRecord()) {
  2.             ltr.Name = LayerName;
  3.             lt.UpgradeOpen();
  4.             lt.Add(ltr);
  5.             lt.DowngradeOpen();
  6.             ltr.Description = LayerDescription;
  7.           }
  8.  
Т.е. добавлять описание к слою можно только после того, как он добавлен в базу.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Описание слоя
« Ответ #8 : 24-10-2015, 16:38:01 »
Фишка в том, что после работы кода, который я предоставил в самом начале:
Код - C# [Выбрать]
  1. private static List<LayerTableRecord> GetMpStandardsLayers()
  2. {
  3.     var layers = new List<LayerTableRecord>();
  4.     var acLyrTblRec = new LayerTableRecord
  5.     {
  6.         Name = "Mp_Основная",
  7.         Color = Color.FromColorIndex(ColorMethod.ByAci, 7),
  8.         LineWeight = LineWeight.LineWeight040,
  9.         Description = "Слой для основных линий"
  10.     };
  11.     layers.Add(acLyrTblRec);
  12.     acLyrTblRec = new LayerTableRecord
  13.     {
  14.         Name = "Mp_Тонкая",
  15.         Color = Color.FromColorIndex(ColorMethod.ByColor, 253),
  16.         LineWeight = LineWeight.LineWeight020,
  17.         Description = "Слой для тонких линий"
  18.     };
  19.     layers.Add(acLyrTblRec);
  20.     ///...................... и так далее еще слои..................///
  21.     return layers;
  22. }
Возвращается список LayerTableRecord у которых Description уже пустое!
Таким образом мы можем добавлять описание только в момент добавления слоя в чертеж (причем уже после строки lt.Add(ltr);). Значит полноценное хранение заранее заготовленных слоев накрывается медным тазом (если только не придумать какие-нибудь "костыли" или особую методику хранения/добавления слоев)
Т.е. добавлять описание к слою можно только после того, как он добавлен в базу.
Странное решение разработчиков. Более похоже на баг

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Описание слоя
« Ответ #9 : 24-10-2015, 16:48:57 »
Значит будешь хранить их иначе (например в виде Dictionary<LayerTableRecord,string>, где string - это Description). Хотя для меня полная загадка зачем нужно "хранить", т.е. держать в памяти, коллекцию LayerTableRecord.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Описание слоя
« Ответ #10 : 24-10-2015, 16:51:49 »
Странное решение разработчиков. Более похоже на баг
Ничего странного я в этом не вижу. Более того, не исключено, что Description хранится не в самой LayerTableRecord, а в некой связанной с ней таблице в Database, и поиск в ней идёт по ObjectId, которого не существует до момента добавления к LayerTable (т.е. в базу).

Нашёл тот же вопрос и ответ, аналогичный моему: http://www.theswamp.org/index.php?topic=43953.msg492233#msg492233
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Описание слоя
« Ответ #11 : 24-10-2015, 17:06:24 »
Причина оказалась еще проще. Смотрим на картинку:



Описание (Description) слоя содержится в его расширенных данных в группе 1000 приложения "AcAecLayerStandard". Эти расширенные данные можно добавить только после того, как объект добавлен в базу и в базе создано имя приложения "AcAecLayerStandard" (смотрим код группы 1001). Всё!

P.S.: Вот что значит начинать с AutoCAD .NET API, а не с ObjectARX. В описании метода AcDbObject::setXdata (который и добавляет расширенные данные к объекту) четко написано:

Цитировать
If any of the regappNames in xdata are not in the APPID table, then Acad::eRegappIdNotFound is returned.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение