TransformOverrule : TransformBy - как получить смещенную точку?

Автор Тема: TransformOverrule : TransformBy - как получить смещенную точку?  (Прочитано 10822 раз)

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

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Допустим я сделал TransformOverrule для отрезка. И у меня есть расширенные данные, которые соответствуют точкам отрезка (начало и конец).
При работе метода TransformBy я попробовал такие действия:
1. Читаю данные из объекта
2. Обновляю данные типа так: Data.StartPoint = Data.StartPoint.TransformBy(transform);
3. Записываю данные обратно в примитив
Вот только мои "полученные точки" улетают очень далеко. Понимаю, что надо не так, но не могу пока представить как верно
Я пробовал пока-что только перемещение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
2. Обновляю данные типа так: Data.StartPoint = Data.StartPoint.TransformBy(transform);
Вот это неправильно. Насколько я понимаю transform при каждом вызове соответствует перемещению из начальной точки.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
2. Обновляю данные типа так: Data.StartPoint = Data.StartPoint.TransformBy(transform);
Вот это неправильно. Насколько я понимаю transform при каждом вызове соответствует перемещению из начальной точки.
Вот это я уже понял. Значит перед началом трансформации нужно временно сохранить первоначальные данные. Но вот вопрос - как и куда? На ум приходит мысль использовать обработку события CommandWillStart, но мне что-то не очень хочется. Но и в TransformOverrule я не вижу ничего подходящего

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Есть вариант в TransformOverrule.CloneMeForDragging возвращать false. В этом случае transform будет не из начальной точки, а из предыдущей.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Есть вариант в TransformOverrule.CloneMeForDragging возвращать false. В этом случае transform будет не из начальной точки, а из предыдущей.
Попробовал. Теперь при использовании команды Move перемещаемый примитив тоже уезжает от суммирования матриц трансформации. Зато вместе с расширенными данными  :D

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Нашел вроде более менее подходящий "костыль"
1. В вспомогательном классе делаю переменную для хранения экземпляра класса моих расширенных данных
2. В методе TransformBy получаю расширенные данные из примитива и если вспомогательная переменная равна null, то записываю в нее эти данные
3. В обработке событий CommandEnded, CommandCancelled и CommandFailed присваиваю переменной значение null

Один два раза срабатывает нормально, а потом начинаются глюки )) Тут уже нужно подробно ковыряться где и что происходит

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
А вот еще интересный момент - при работе команды COPY также срабатывает TransformBy. Вопрос - как при этом получить скопированный объект?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Вопрос - как при этом получить скопированный объект?
Наверное через Database.ObjectAppended
Впрочем если ты воспользуешься MGDDBG или ARXDBG, то сможешь отследить события, которые возникают в команде COPY.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Допустим я сделал TransformOverrule для отрезка. И у меня есть расширенные данные, которые соответствуют точкам отрезка (начало и конец).
При работе метода TransformBy я попробовал такие действия:
1. Читаю данные из объекта
2. Обновляю данные типа так: Data.StartPoint = Data.StartPoint.TransformBy(transform);
3. Записываю данные обратно в примитив
TransformOverrule используется только для того, чтобы отследить изменение отрезка и актуализировать его расширенные данные?
Кстати, возможно, пригодится в данном случае. В расширенные данные можно поместить координаты точки под определенным кодом и они будут изменяться вместе с объектом (World Space Position и далее): http://help.autodesk.com/view/ACD/2016/ENU/?guid=GUID-3481BF7B-73CB-4FD5-B421-C25BE92C6D56

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Кстати, возможно, пригодится в данном случае. В расширенные данные можно поместить координаты точки под определенным кодом и они будут изменяться вместе с объектом (World Space Position и далее)
Да, хорошая возможность. У меня мало опыта работы с XData и сразу возникает вопрос - я смогу ведь только одну такую точку сохранить? Я сейчас именно про World Space Position говорю. А если у меня несколько таких "важных" точек?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Кстати, возможно, пригодится в данном случае. В расширенные данные можно поместить координаты точки под определенным кодом и они будут изменяться вместе с объектом (World Space Position и далее): http://help.autodesk.com/view/ACD/2016/ENU/?guid=GUID-3481BF7B-73CB-4FD5-B421-C25BE92C6D56
Когда-то (очень-очень давно) я пробовал использовать эти коды. К сожалению они не всегда трансформировались и мне пришлось тогда от них отказаться в пользу реакторов.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
я смогу ведь только одну такую точку сохранить?
Нет. Их может быть произвольное количество. Просто тебе нужно будет учитывать их порядок для того чтобы понять, что первый 1011 - это точка начала, второй 1011 - конец и т.д. Но советую тщательно потестировать работоспособность.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Нашел чуть подробнее тут - https://www.autodesk.com/techpubs/autocad/acad2000/dxf/extended_data_dxf_ab.htm
Данных с именем World space position всего три - 1011, 1021, 1031. Мало
Хотя, мне сегодня в голову пришла идея (ну конкретно в моем варианте) - мне нужно две основных точки хранить и вектор между ними. Одна из этих точек соответствует точке вставки блока (В моем случае работа с блоком). Вся геометрия в блоке зависит от этих двух точек в принципе. В теории мне достаточно знать только вектор между точками и я смогу восстановить всю геометрию. Я сейчас говорю о варианте копирования примитива. Все пока-что в теории, т.к. вопрос очень объемный и долговременный и нужно много пробовать

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Данных с именем World space position всего три - 1011, 1021, 1031. Мало
Не путай "мягкое с теплым". В DXF-файле это три группы (1011, 1021, 1031). А в lisp/arx/.NET - это одна группа 1011. Но элементов с этой группой в XData может быть несколько. Например: '((1011 . (0.0 0.0 0.0)) (1011 . (1.0 1.0 1.0)) (1011 . (2.0 2.0 2.0))
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Данных с именем World space position всего три - 1011, 1021, 1031. Мало
Не путай "мягкое с теплым". В DXF-файле это три группы (1011, 1021, 1031). А в lisp/arx/.NET - это одна группа 1011. Но элементов с этой группой в XData может быть несколько. Например: '((1011 . (0.0 0.0 0.0)) (1011 . (1.0 1.0 1.0)) (1011 . (2.0 2.0 2.0))
Я правильно понимаю, что можно делать что-то типа того: new TypedValue(1011, Points3d[]) ?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Я правильно понимаю, что можно делать что-то типа того: new TypedValue(1011, Points3d[]) ?
Именно. И так можно делать несколько раз.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А можно и вот так:
Код - C# [Выбрать]
  1.   new TypedValue((int)DxfCode.ExtendedDataWorldXCoordinate, new Point3d(1.0, 2.0, 3.0))
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Я правильно понимаю, что можно делать что-то типа того: new TypedValue(1011, Points3d[]) ?
Именно. И так можно делать несколько раз.
По ссылке, что Дмитрий дал, написано:
Цитировать
World Space Position
1011. Unlike a simple 3D point, the WCS coordinates are moved, scaled, rotated, and mirrored along with the parent entity to which the extended data belongs. The WCS position is also stretched when the AutoCAD STRETCH command is applied to the parent entity and when this point lies within the select window.
По описанию - прям отличный вариант. И если я в этот код несколько точек помещу - они все меняться будут? Вот тут что-то не уверен. Но потом вы написали:
Когда-то (очень-очень давно) я пробовал использовать эти коды. К сожалению они не всегда трансформировались и мне пришлось тогда от них отказаться в пользу реакторов.
И теперь я даже не знаю - пробовать или нет  :-\

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
И если я в этот код несколько точек помещу - они все меняться будут?
Да. Должны меняться все.
И теперь я даже не знаю - пробовать или нет
Это было, если мне не изменяет память, еще в DOS'овской версии AutoCAD R12. Так что если я пишу, что это очень-очень давно, то это так и есть. Уже почти 25 лет прошло. Возможно это был баг, который потом исправили. Так что советую проверить.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Это было, если мне не изменяет память, еще в DOS'овской версии AutoCAD R12. Так что если я пишу, что это очень-очень давно, то это так и есть. Уже почти 25 лет прошло. Возможно это был баг, который потом исправили. Так что советую проверить
Вот как раз сегодня и займусь) Начинал с XRecord, затем скаканул к сериализации в XData, теперь попробую вообще обычные dxfCode. Иду к упрощению =)
Попробую как-раз на получении ручек. Отпишусь потом получилось или нет

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Я правильно понимаю, что можно делать что-то типа того: new TypedValue(1011, Points3d[]) ?
Именно. И так можно делать несколько раз.
А вот и нет)) Вываливается ошибка, если я пробую сразу добавить массив. А вот так добавляются:
Код - C# [Выбрать]
  1. resBuf.Add(new TypedValue((int)DxfCode.ExtendedDataWorldXCoordinate, InsertionPoint)); // 1011
  2. resBuf.Add(new TypedValue((int)DxfCode.ExtendedDataWorldXCoordinate, EndPoint)); // 1011
Но я впал в небольшой ступор - а как их теперь получить?
Код - C# [Выбрать]
  1. TypedValue[] resBufArr = resBuf.AsArray();
  2. foreach (TypedValue typedValue in resBufArr)
  3. {
  4.     switch ((DxfCode)typedValue.TypeCode)
  5.     {
  6.         case DxfCode.ExtendedDataWorldXCoordinate:
  7.             {
  8.                 InsertionPoint = ???;
  9.                 EndPoint = ???;
  10.                 break;
  11.             }
  12.     }
  13. }

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Но я впал в небольшой ступор - а как их теперь получить?
По индексу в массиве:
Код - C# [Выбрать]
  1. InsertionPoint = (Point3d)resBufArr[0];

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Но я впал в небольшой ступор - а как их теперь получить?
По индексу в массиве:
Код - C# [Выбрать]
  1. InsertionPoint = (Point3d)resBufArr[0];
Не думаю, что так будет хорошо. Нужно точно знать эти индексы, а в процессе написания кода можно внести изменения и упустить этот момент.
В данном примере (но у меня всего две точки) я сделал так:
Код - C# [Выбрать]
  1. TypedValue[] resBufArr = resBuf.AsArray();
  2. var wasInsertionPoint = false;
  3. foreach (TypedValue typedValue in resBufArr)
  4. {
  5.     switch ((DxfCode)typedValue.TypeCode)
  6.     {
  7.         case DxfCode.ExtendedDataWorldXCoordinate:
  8.             {
  9.                 if (!wasInsertionPoint)
  10.                 {
  11.                     InsertionPoint = (Point3d)typedValue.Value;
  12.                     wasInsertionPoint = true;
  13.                 }
  14.                 else
  15.                 {
  16.                     EndPoint = (Point3d)typedValue.Value;
  17.                 }
  18.                 break;
  19.             }
  20.     }
  21. }
Но если точек будет больше, то это можно решить введя вспомогательный счетчик. Ну или еще что придумать. В общем - варианты есть. Я просто поспешил задать вопрос ))

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А вот и нет)) Вываливается ошибка, если я пробую сразу добавить массив. А вот так добавляются:
Значит я просто тебя не понял.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Попробую как-раз на получении ручек. Отпишусь потом получилось или нет
Итак - попробовал. Работает! С перемещением и копированием все хорошо. Даже с копированием в другой документ. Но счастье длилось не долго - до тех пор как я повернул примитив. Вот тут началось что-то такое, что я уже пол вечера понять не могу.
Пример:
1. Строю примитив с расширенными данными так, чтобы первая точка была в (0,0,0)
2. Затем поворачиваю примитив так, чтобы эта точка переместилась в (0,50,0)
3. Использую команду из Express Tools - List Xdata и получаю такое значение: * Code 1011, 3D World space position: (0 50 0). Т.е. то значение, которое мне и нужно, НО!
4. При чтении из Xdata я получаю другую координату! При этом:
Код - C# [Выбрать]
  1. TypedValue[] resBufArr = resBuf.AsArray();
  2. var wasInsertionPoint = false;
  3. foreach (TypedValue typedValue in resBufArr)
  4. {
  5.     switch ((DxfCode)typedValue.TypeCode)
  6.     {
  7.         case DxfCode.ExtendedDataWorldXCoordinate:
  8.             {
  9.                 if (!wasInsertionPoint)
  10.                 {
  11.                     AcadHelpers.Editor.WriteMessage("\n(Point3d)typedValue.Value: " + (Point3d)typedValue.Value);
  12.                     InsertionPoint = (Point3d)typedValue.Value;
  13.                     wasInsertionPoint = true;
  14.                 }
  15.                 else
  16.                 {
  17.                     EndPoint = (Point3d)typedValue.Value;
  18.                 }
  19.                 break;
  20.             }
  21.     }
  22. }
вижу в командной строке (Point3d)typedValue.Value: (7.105427357601E-15,50,0). Даже не соображу куда копать и что читать  :(

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Шутишь? На числа внимательно посмотри и вспомни про точность представления чисел типа double.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
7.105427357601E-15
Неудачный пример привел ))
Ну в общем смысл в том, что проблема у меня после поворота присутствует, но я пока не могу сообразить даже где. Наверно это уже не вопрос для данной темы

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Если:
3. Использую команду из Express Tools - List Xdata и получаю такое значение: * Code 1011, 3D World space position: (0 50 0). Т.е. то значение, которое мне и нужно, НО!
то и в .NET API ты получишь тоже значение.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение