Записать ObjectId в XData

Автор Тема: Записать ObjectId в XData  (Прочитано 14164 раз)

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

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

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

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 166
    • Мои плагины к Автокаду
Записать ObjectId в XData
« : 29-09-2017, 16:34:30 »
Что-то я туплю наверно. Надо в xData одного объекта сохранить идентификатор другого. Вроде где-то видел, вроде все просто было...
Записывать наверно надо Handle как-то так:
Код - C# [Выбрать]
  1.     public static void AddVal(this ResultBuffer rb, ObjectId value)
  2.     {
  3.       rb.Add(new TypedValue((int)DxfCode.ExtendedDataHandle, value.Handle));
  4.     }
Или какой код DxfCode?
А считывать? Как из Handle получить ObjectId? Конструктора такого у ObjectId нет. Есть Database.GetObjectId, но ему еще какой-то идентификатор нужен...

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Записать ObjectId в XData
« Ответ #1 : 29-09-2017, 16:39:53 »
А в чем проблема взять ObjectId как строку и сохранить её в XData как строку?

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

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 166
    • Мои плагины к Автокаду
Re: Записать ObjectId в XData
« Ответ #2 : 29-09-2017, 16:42:32 »
А в чем проблема взять ObjectId как строку и сохранить её в XData как строку?
Не кошерно :) Собственно, с тем же успехом можно и как long сохранить. Но как считать обратно-то?

Отмечено как Решение avc 29-09-2017, 16:58:09

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Записать ObjectId в XData
« Ответ #3 : 29-09-2017, 16:50:42 »
Ну раз не кошерно, то вот пример:
1. Сохранение:
Код - C# [Выбрать]
  1.  vals = new TypedValue[] {
  2.                             new TypedValue(
  3.                                 (int)DxfCode.ExtendedDataRegAppName,
  4.                                 xDataAppName),
  5.                             new TypedValue(
  6.                                 (int)DxfCode.ExtendedDataAsciiString,
  7.                                 line.Handle.ToString())
2. Чтение:
Код - C# [Выбрать]
  1. if (!string.IsNullOrEmpty(handleString))
  2.                     {
  3.                         ObjectId entId =
  4.                             CadHelper.GetObjectIdFromHandleString(
  5.                             dbObject.Database, handleString);
  6.  
  7.                         if (!entId.IsNull)
  8.                         {
  9.                             _changeOtherEntity = true;
  10.                             _overruleAction(entId, dbObject);
  11.                             _changeOtherEntity = false;
  12.                         }
  13.                     }
3. Преобразование:
Код - C# [Выбрать]
  1. public static ObjectId GetObjectIdFromHandleString(
  2.             Database db, string handleString)
  3.         {
  4.             ObjectId id = ObjectId.Null;
  5.  
  6.             Handle hdl =
  7.                 new Handle(Int64.Parse(
  8.                 handleString,
  9.                 System.Globalization.NumberStyles.HexNumber));
  10.  
  11.             id = db.GetObjectId(false, hdl, 0);
  12.  
  13.             return id;
  14.         }
Взято отсюда. Там и видео и исходник есть

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

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 166
    • Мои плагины к Автокаду
Re: Записать ObjectId в XData
« Ответ #4 : 29-09-2017, 17:02:39 »
Странно, что нет прямого пути, ведь изрядная доля всех словарей в БД заполнена ссылками на объекты. Ну раз нет, то пойдем в обход. Собственно, все чего мне не хватало - это
Код - C# [Выбрать]
  1. id = db.GetObjectId(false, hdl, 0);
Значит просто нолик последний непонятный параметр.
Спасибо!

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Re: Записать ObjectId в XData
« Ответ #5 : 29-09-2017, 17:21:12 »
А в чем проблема взять ObjectId как строку и сохранить её в XData как строку?
В новой сессии все ObjectId пересчитываются и, соответственно, записанные таким образом данные становятся недействительными.

По теме:
http://spiderinnet1.typepad.com/blog/2012/11/autocad-net-xdata-xdata-handle-implications.html

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Записать ObjectId в XData
« Ответ #6 : 29-09-2017, 17:24:13 »
Собственно, все чего мне не хватало - это
Код - C# [Выбрать]

    id = db.GetObjectId(false, hdl, 0);

Значит просто нолик последний непонятный параметр.
лучше
Код - C# [Выбрать]
  1. Boolean isValidHandle = db.TryGetObjectId(hdl, out id);
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Записать ObjectId в XData
« Ответ #7 : 29-09-2017, 20:57:03 »
Странно, что нет прямого пути, ведь изрядная доля всех словарей в БД заполнена ссылками на объекты. Ну раз нет, то пойдем в обход.
В расширенных данных (Xdata) нельзя хранить ссылки на ObjectId в отличие от XRecord. Хранение Handle в ExtendedDataAsciiString имеет свои плюсы и минусы. Например, команда _WBLOCK создаёт новый чертеж с пересчитанными метками. В  ExtendedDataAsciiString метка пересчитана не будет и вероятнее всего она будет ссылаться или на неправильный объект или вообще на "ничто". Хранение в ExtendedDataHandle имеет тоже свои недостатки. При _WBLOCK метки пересчитаются, а вот что будет при обычной операции копирования? В этом случае метка не пересчитается и новый примитив будет ссылаться на оригинал, а не на копию. Так что потребуется еще некая логика обработки таких ситуаций.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 166
    • Мои плагины к Автокаду
Re: Записать ObjectId в XData
« Ответ #8 : 29-09-2017, 22:55:43 »
Спасибо. Я отчетливо понимаю проблемы связанные с хранением ссылок и до сих пор мне удавалось избежать этого. Подумаю как избежать и в этот раз.
А если я попытаюсь хранить пары id связанных объектов в словарях. Это улучшит ситуацию? Какие типы DxfCode предпочтительно использовать?

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Записать ObjectId в XData
« Ответ #9 : 29-09-2017, 23:20:17 »
А если я попытаюсь хранить пары id связанных объектов в словарях.
Не думаю. В любом случае есть проблемы логики. Универсального решения нет и быть не может.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн RevitTormentor

  • ADN OPEN
  • ***
  • Сообщений: 162
  • Карма: 6
Re: Записать ObjectId в XData
« Ответ #10 : 12-10-2017, 03:00:40 »
Спасибо. Я отчетливо понимаю проблемы связанные с хранением ссылок и до сих пор мне удавалось избежать этого. Подумаю как избежать и в этот раз.
А если я попытаюсь хранить пары id связанных объектов в словарях. Это улучшит ситуацию? Какие типы DxfCode предпочтительно использовать?

Этот вариант - не то?

Эх... Смешно до слез! Сколько времени я потратил на разработку этого инструмента! Сколько багов отловили пользователи! Сколько нервов это стоило и мне и им! А оказалось, что это просто велосипед. И все уже давно сделано и работает как надо.
Принцип прост: берем Id объекта и добавляем его в запись словаря другого объекта под кодом HardPointerId или SoftPointerId. И всё, больше ничего делать не надо! Все остальное берут на себя внутренние механизмы AutoCAD! Никаких обработчиков событий, актуализаторов и прочей головной боли! :-\
http://adn-cis.org/forum/index.php?topic=743.105

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Записать ObjectId в XData
« Ответ #11 : 12-10-2017, 11:45:34 »
Этот вариант - не то?
Вариант не универсален, как я указывал дальше в обсуждении, хотя в некоторых случаях может быть полезен.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн simson43

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Записать ObjectId в XData
« Ответ #12 : 15-02-2019, 12:44:25 »
а если записывать все же вот так
    public static void AddVal(this ResultBuffer rb, ObjectId value)
    {
      rb.Add(new TypedValue((int)DxfCode.ExtendedDataHandle, value.Handle));
    }

то как при чтении из XData из object получить Handle, чтобы вставить его сюда?
Boolean isValidHandle = db.TryGetObjectId(hdl, out id);

следующее выдает ошибку на этапе преобразования object в Handle - заданное приведение недопустимо
Код - C# [Выбрать]
  1. Handle[] handleArr = dataList.FindAll(x => x.TypeCode == 1005).Select(x => (Handle)x.Value).ToArray();


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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Записать ObjectId в XData
« Ответ #13 : 15-02-2019, 15:54:33 »
а если записывать все же вот так
Этого делать не следует, так как AutoCAD преобразовывает при некоторых операциях значения в группе 1005. Поэтому в какой-то момент вместо того значения, которое там было ты можешь получить совсем другое.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Записать ObjectId в XData
« Ответ #14 : 15-02-2019, 16:03:54 »
следующее выдает ошибку на этапе преобразования object в Handle - заданное приведение недопустимо
Код - C# [Выбрать]

    Handle[] handleArr = dataList.FindAll(x => x.TypeCode == 1005).Select(x => (Handle)x.Value).ToArray();
Думаю что вместо :
Код - C# [Выбрать]
  1. Handle[] handleArr = dataList.FindAll(x => x.TypeCode == 1005).Select(x => (Handle)x.Value).ToArray();
должно быть:
Код - C# [Выбрать]
  1. Handle[] handleArr = dataList.FindAll(x => x.TypeCode == 1005).Select(x => new Handle( Convert.ToInt64(x.Value.ToString(), 16)) ).ToArray();
Если я даже слегка в синтаксисе ошибся, то исправишь.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение