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

ADN Club => AutoCAD .NET API => Тема начата: Александр Пекшев aka Modis от 21-05-2017, 19:28:34

Название: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 21-05-2017, 19:28:34
Допустим я сделал TransformOverrule для отрезка. И у меня есть расширенные данные, которые соответствуют точкам отрезка (начало и конец).
При работе метода TransformBy я попробовал такие действия:
1. Читаю данные из объекта
2. Обновляю данные типа так: Data.StartPoint = Data.StartPoint.TransformBy(transform);
3. Записываю данные обратно в примитив
Вот только мои "полученные точки" улетают очень далеко. Понимаю, что надо не так, но не могу пока представить как верно
Я пробовал пока-что только перемещение
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 21-05-2017, 19:41:20
2. Обновляю данные типа так: Data.StartPoint = Data.StartPoint.TransformBy(transform);
Вот это неправильно. Насколько я понимаю transform при каждом вызове соответствует перемещению из начальной точки.
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 21-05-2017, 19:45:39
2. Обновляю данные типа так: Data.StartPoint = Data.StartPoint.TransformBy(transform);
Вот это неправильно. Насколько я понимаю transform при каждом вызове соответствует перемещению из начальной точки.
Вот это я уже понял. Значит перед началом трансформации нужно временно сохранить первоначальные данные. Но вот вопрос - как и куда? На ум приходит мысль использовать обработку события CommandWillStart, но мне что-то не очень хочется. Но и в TransformOverrule я не вижу ничего подходящего
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 21-05-2017, 20:26:09
Есть вариант в TransformOverrule.CloneMeForDragging возвращать false. В этом случае transform будет не из начальной точки, а из предыдущей.
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 21-05-2017, 20:36:24
Есть вариант в TransformOverrule.CloneMeForDragging возвращать false. В этом случае transform будет не из начальной точки, а из предыдущей.
Попробовал. Теперь при использовании команды Move перемещаемый примитив тоже уезжает от суммирования матриц трансформации. Зато вместе с расширенными данными  :D
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 21-05-2017, 20:55:12
Нашел вроде более менее подходящий "костыль"
1. В вспомогательном классе делаю переменную для хранения экземпляра класса моих расширенных данных
2. В методе TransformBy получаю расширенные данные из примитива и если вспомогательная переменная равна null, то записываю в нее эти данные
3. В обработке событий CommandEnded, CommandCancelled и CommandFailed присваиваю переменной значение null

Один два раза срабатывает нормально, а потом начинаются глюки )) Тут уже нужно подробно ковыряться где и что происходит
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 22-05-2017, 09:31:23
А вот еще интересный момент - при работе команды COPY также срабатывает TransformBy. Вопрос - как при этом получить скопированный объект?
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 22-05-2017, 09:33:46
Вопрос - как при этом получить скопированный объект?
Наверное через Database.ObjectAppended
Впрочем если ты воспользуешься MGDDBG или ARXDBG, то сможешь отследить события, которые возникают в команде COPY.
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Дмитрий Загорулькин от 22-05-2017, 11:57:24
Допустим я сделал 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
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 22-05-2017, 12:41:25
Кстати, возможно, пригодится в данном случае. В расширенные данные можно поместить координаты точки под определенным кодом и они будут изменяться вместе с объектом (World Space Position и далее)
Да, хорошая возможность. У меня мало опыта работы с XData и сразу возникает вопрос - я смогу ведь только одну такую точку сохранить? Я сейчас именно про World Space Position говорю. А если у меня несколько таких "важных" точек?
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 22-05-2017, 12:44:33
Кстати, возможно, пригодится в данном случае. В расширенные данные можно поместить координаты точки под определенным кодом и они будут изменяться вместе с объектом (World Space Position и далее): http://help.autodesk.com/view/ACD/2016/ENU/?guid=GUID-3481BF7B-73CB-4FD5-B421-C25BE92C6D56
Когда-то (очень-очень давно) я пробовал использовать эти коды. К сожалению они не всегда трансформировались и мне пришлось тогда от них отказаться в пользу реакторов.
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 22-05-2017, 12:46:58
я смогу ведь только одну такую точку сохранить?
Нет. Их может быть произвольное количество. Просто тебе нужно будет учитывать их порядок для того чтобы понять, что первый 1011 - это точка начала, второй 1011 - конец и т.д. Но советую тщательно потестировать работоспособность.
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 22-05-2017, 12:52:00
Нашел чуть подробнее тут - https://www.autodesk.com/techpubs/autocad/acad2000/dxf/extended_data_dxf_ab.htm
Данных с именем World space position всего три - 1011, 1021, 1031. Мало
Хотя, мне сегодня в голову пришла идея (ну конкретно в моем варианте) - мне нужно две основных точки хранить и вектор между ними. Одна из этих точек соответствует точке вставки блока (В моем случае работа с блоком). Вся геометрия в блоке зависит от этих двух точек в принципе. В теории мне достаточно знать только вектор между точками и я смогу восстановить всю геометрию. Я сейчас говорю о варианте копирования примитива. Все пока-что в теории, т.к. вопрос очень объемный и долговременный и нужно много пробовать
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 22-05-2017, 12:55:41
Данных с именем 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))
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 22-05-2017, 13:02:07
Данных с именем 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[]) ?
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 22-05-2017, 13:28:37
Я правильно понимаю, что можно делать что-то типа того: new TypedValue(1011, Points3d[]) ?
Именно. И так можно делать несколько раз.
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 22-05-2017, 13:31:28
А можно и вот так:
Код - C# [Выбрать]
  1.   new TypedValue((int)DxfCode.ExtendedDataWorldXCoordinate, new Point3d(1.0, 2.0, 3.0))
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 22-05-2017, 13:34:08
Я правильно понимаю, что можно делать что-то типа того: 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.
По описанию - прям отличный вариант. И если я в этот код несколько точек помещу - они все меняться будут? Вот тут что-то не уверен. Но потом вы написали:
Когда-то (очень-очень давно) я пробовал использовать эти коды. К сожалению они не всегда трансформировались и мне пришлось тогда от них отказаться в пользу реакторов.
И теперь я даже не знаю - пробовать или нет  :-\
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 22-05-2017, 13:41:38
И если я в этот код несколько точек помещу - они все меняться будут?
Да. Должны меняться все.
И теперь я даже не знаю - пробовать или нет
Это было, если мне не изменяет память, еще в DOS'овской версии AutoCAD R12. Так что если я пишу, что это очень-очень давно, то это так и есть. Уже почти 25 лет прошло. Возможно это был баг, который потом исправили. Так что советую проверить.
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 22-05-2017, 13:49:21
Это было, если мне не изменяет память, еще в DOS'овской версии AutoCAD R12. Так что если я пишу, что это очень-очень давно, то это так и есть. Уже почти 25 лет прошло. Возможно это был баг, который потом исправили. Так что советую проверить
Вот как раз сегодня и займусь) Начинал с XRecord, затем скаканул к сериализации в XData, теперь попробую вообще обычные dxfCode. Иду к упрощению =)
Попробую как-раз на получении ручек. Отпишусь потом получилось или нет
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 22-05-2017, 17:31:52
Я правильно понимаю, что можно делать что-то типа того: 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. }
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Дмитрий Загорулькин от 22-05-2017, 17:35:26
Но я впал в небольшой ступор - а как их теперь получить?
По индексу в массиве:
Код - C# [Выбрать]
  1. InsertionPoint = (Point3d)resBufArr[0];
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 22-05-2017, 17:39:35
Но я впал в небольшой ступор - а как их теперь получить?
По индексу в массиве:
Код - 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. }
Но если точек будет больше, то это можно решить введя вспомогательный счетчик. Ну или еще что придумать. В общем - варианты есть. Я просто поспешил задать вопрос ))
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 22-05-2017, 18:08:04
А вот и нет)) Вываливается ошибка, если я пробую сразу добавить массив. А вот так добавляются:
Значит я просто тебя не понял.
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 22-05-2017, 20:51:42
Попробую как-раз на получении ручек. Отпишусь потом получилось или нет
Итак - попробовал. Работает! С перемещением и копированием все хорошо. Даже с копированием в другой документ. Но счастье длилось не долго - до тех пор как я повернул примитив. Вот тут началось что-то такое, что я уже пол вечера понять не могу.
Пример:
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). Даже не соображу куда копать и что читать  :(
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 22-05-2017, 20:56:11
Шутишь? На числа внимательно посмотри и вспомни про точность представления чисел типа double.
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Пекшев aka Modis от 22-05-2017, 21:15:19
7.105427357601E-15
Неудачный пример привел ))
Ну в общем смысл в том, что проблема у меня после поворота присутствует, но я пока не могу сообразить даже где. Наверно это уже не вопрос для данной темы
Название: Re: TransformOverrule : TransformBy - как получить смещенную точку?
Отправлено: Александр Ривилис от 22-05-2017, 21:43:34
Если:
3. Использую команду из Express Tools - List Xdata и получаю такое значение: * Code 1011, 3D World space position: (0 50 0). Т.е. то значение, которое мне и нужно, НО!
то и в .NET API ты получишь тоже значение.