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

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

Название: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 31-05-2017, 11:51:37
Всем привет. Конечно в меня полетят тухлые помидоры от Ривилиса, но придется потерпеть  ;D
Касаемо матриц трансформации у меня дикое непонимание темы ((
В этой теме (http://adn-cis.org/forum/index.php?topic=7814.0) я выкладывал тестовый проект. Вот с ним же и продолжим разбираться (я его приложил к этой теме). В этом проекте для блока задаются две ручки. Первая равна точке вставки блока, а вторая создает геометрию.
Для контроля положения второй точки я использовал расширенные данные, которые хранят вектор между второй точкой и первой. Т.е. при получении ручек берется точка вставки блока и к ней прибавляется этот вектор - получаем вторую точку. В той теме (http://adn-cis.org/forum/index.php?topic=7814.0) есть видео примеры в которых видно, что это работает. Но это работает до тех пор, пока я не трансформирую сам блок - поверну, масштабирую или отзеркалю (перемещение не играет роли в данном случае) - тогда вторая точка не соответствует требуемому положению.
При получении расширенных данных из блока работает следующий метод:
Код - C# [Выбрать]
  1. public void GetParametersFromResBuf(ResultBuffer resBuf)
  2. {
  3.     TypedValue[] resBufArr = resBuf.AsArray();
  4.     foreach (TypedValue typedValue in resBufArr)
  5.     {
  6.         switch ((DxfCode)typedValue.TypeCode)
  7.         {
  8.             case DxfCode.ExtendedDataAsciiString:
  9.                 {
  10.                     Vector3d vectorFromEndToStart = SimplyEntityHelper.ConvertStringToVector3d(typedValue.Value.ToString());
  11.                     var pt = StartPoint + vectorFromEndToStart;
  12.                     EndPoint = pt;
  13.                     break;
  14.                 }
  15.         }
  16.     }
  17. }
Это как раз получение второй точки по вектору. Как я предполагаю - эту точку нужно еще трансформировать в зависимости от трансформации блока. У меня получалось учесть масштаб и поворот, используя свойства ScaleX и Rotation из блока. Но я застрял с отзеркаливанием. Поэтому я предположил, что можно взять значение BlockTransform из вхождения блока и трансформировать точку:
Код - C# [Выбрать]
  1. EndPoint = pt.TransformBy(BlockTransform);
Но мои предположения оказались неверными.
Прошу помощи с идеями и подсказками  ::)

Название: Re: Трансформация точки по трансформации блока
Отправлено: Дмитрий Загорулькин от 31-05-2017, 12:30:45
Возможно, имеет смысл хранить координаты точки во внутренней системе координат блока? Тогда BlockTransform поможет.
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Ривилис от 31-05-2017, 12:35:37
Попробуй:
Код - C# [Выбрать]
  1. EndPoint = pt.TransformBy(BlockTransform.Inverse());
Название: Re: Трансформация точки по трансформации блока
Отправлено: Дмитрий Загорулькин от 31-05-2017, 12:40:20
Насколько я понимаю, это переводит координаты точки из МСК в ОСК блока. Мне думается, что тут надо как-то грамотно использовать оба преобразования: из МСК в ОСК и обратно. Одно - до изменения точки, другое - после. Только что-то не сообразить каким способом. Надо тестировать.
Название: Re: Трансформация точки по трансформации блока
Отправлено: bender от 31-05-2017, 12:42:35
А почему
Цитировать
DxfCode.ExtendedDataAsciiString
?

http://help.autodesk.com/view/ACD/2016/RUS/?guid=GUID-A2A628B0-3699-4740-A215-C560E7242F63

Чем код 1012 не устроил-то?
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 31-05-2017, 12:45:38
Попробуй:
Код - C# [Выбрать]
  1. EndPoint = pt.TransformBy(BlockTransform.Inverse());
Нет, не помогает

Возможно, имеет смысл хранить координаты точки во внутренней системе координат блока?
А вот это идея. Только координаты точки я не храню вообще - я храню вектор от второй точки к первой. Значит перед тем как трансформировать точку с помощью BlockTransform, нужно произвести трансформацию координат. Или после... Запутался)) Да, нужно тестировать
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 31-05-2017, 12:47:29
А почему
Цитировать
DxfCode.ExtendedDataAsciiString
?

http://help.autodesk.com/view/ACD/2016/RUS/?guid=GUID-A2A628B0-3699-4740-A215-C560E7242F63

Чем код 1012 не устроил-то?
Вот в этой теме (http://adn-cis.org/forum/index.php?topic=7808.0) написано чем ) Эти коды не меняются при изменении блока через палитру свойств
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Ривилис от 31-05-2017, 12:49:05
Мне думается, что тут надо как-то грамотно использовать оба преобразования: из МСК в ОСК и обратно.
Думаю, что ты прав. Сначала МСК->ОСК, затем добавляем вектор, а затем ОСК->МСК.
Название: Re: Трансформация точки по трансформации блока
Отправлено: bender от 31-05-2017, 12:52:36
Цитировать
Вот в этой теме написано чем )

1011 и 1012 ... Разницу чувствуешь?
Цитировать
Для контроля положения второй точки я использовал расширенные данные, которые хранят вектор между второй точкой и первой.
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 31-05-2017, 12:58:28
Цитировать
Вот в этой теме написано чем )

1011 и 1012 ... Разницу чувствуешь?
Можно попробовать. По коду 1012 я буду получать вектор, указывающий направление второй точки. Но вопрос в том-же - точка по коду 1012 будет меняться с объектом при изменении из палитры свойств? Если 1011 не меняется. то я на 80% уверен, что и 1012 не будет
Название: Re: Трансформация точки по трансформации блока
Отправлено: Дмитрий Загорулькин от 31-05-2017, 12:59:42
Не зря же значения динпараметров хранятся во внутренней системе измерений блока.
Тут получается так: если хранить точку (вектор) в МСК, то ее нужно пересчитывать перезаписывать и в случае редактирования "ручкой" и в случае изменения блока (поворот, масштаб, зеркало). А если хранить в ОСК - то только при изменении "ручкой".
Название: Re: Трансформация точки по трансформации блока
Отправлено: bender от 31-05-2017, 13:00:59
Цитировать
Но вопрос в том-же - точка по коду 1012 будет меняться с объектом при изменении из палитры свойств?

А зачем ей меняться?
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Ривилис от 31-05-2017, 13:05:47
Если 1011 не меняется. то я на 80% уверен, что и 1012 не будет
Я уверен в этом на 99%
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 31-05-2017, 13:07:43
Не зря же значения динпараметров хранятся во внутренней системе измерений блока.
Тут получается так: если хранить точку (вектор) в МСК, то ее нужно пересчитывать перезаписывать и в случае редактирования "ручкой" и в случае изменения блока (поворот, масштаб, зеркало). А если хранить в ОСК - то только при изменении "ручкой".
Думаю, достаточно будет только трансформаций в методе GetParametersFromResBuf(), который я отобразил в вопросе темы. Как я понимаю, в BlockTransform хранится информация относительно координат блока, а не относительно WCS. Сейчас попробую идейку...
Цитировать
Но вопрос в том-же - точка по коду 1012 будет меняться с объектом при изменении из палитры свойств?

А зачем ей меняться?
А затем, что когда я через палитру свойств задам блоку масштаб, то точка с кодом 1012 останется в своем старом состоянии. Она не изменится, хотя должна будет
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 31-05-2017, 14:43:52
Вроде вот так получается:
Код - C# [Выбрать]
  1. Vector3d vectorFromEndToStart = SimplyEntityHelper.ConvertStringToVector3d(typedValue.Value.ToString());
  2. var pt = StartPoint.TransformBy(BlockTransform.Inverse()) + vectorFromEndToStart;
  3. EndPoint = pt.TransformBy(BlockTransform);
Но еще тестировать нужно
Правда возникают новые проблемы (касаемо самой графики в блоке после отзеркаливания), но это уже вопрос другой темы
Название: Re: Трансформация точки по трансформации блока
Отправлено: Дмитрий Загорулькин от 31-05-2017, 14:57:04
bender, наверное, имел в виду следующее: зачем конвертировать вектор в строку, если есть специальные коды в РД для хранения координат? Только он не те коды указал. В данном случае, можно использовать 1010, 1020 и 1030.
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 31-05-2017, 14:59:52
bender, наверное, имел в виду следующее: зачем конвертировать вектор в строку, если есть специальные коды в РД для хранения координат? Только он не те коды указал. В данном случае, можно использовать 1010, 1020 и 1030
Хорошее замечание и предложение. Хотя к вопросу не относится ))
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Ривилис от 31-05-2017, 18:41:44
В данном случае, можно использовать 1010, 1020 и 1030.
Только 1010. 1020 и 1030 - это Y и Z в dxf-файле. А в Lisp/ARX/.NET всё объединено в точку в группу 1010.
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 31-05-2017, 18:53:50
Вроде вот так получается:
Код - C# [Выбрать]
  1. Vector3d vectorFromEndToStart = SimplyEntityHelper.ConvertStringToVector3d(typedValue.Value.ToString());
  2. var pt = StartPoint.TransformBy(BlockTransform.Inverse()) + vectorFromEndToStart;
  3. EndPoint = pt.TransformBy(BlockTransform);
Но еще тестировать нужно
А тем временем - плохой вариант  :(
Название: Re: Трансформация точки по трансформации блока
Отправлено: Дмитрий Загорулькин от 31-05-2017, 18:54:39
Цитировать
Только 1010. 1020 и 1030 - это Y и Z в dxf-файле. А в Lisp/ARX/.NET всё объединено в точку в группу 1010.
Возможно. Я не проверял :)
Меня настораживает, что этот скриншот я делал из ObjectBrowser в Visual Studio. Как-то нелогично получается. Предположим я создаю TypedValue с этим кодом:
Код - C# [Выбрать]
  1. Point3d pt = new Point3d();
  2. TypedValue tv = new TypedValue((int)DxfCode.ExtendedDataXCoordinate, pt);
  3.  
ExtendedDataXCoordinate - "расширенные данные X координата", а там вдруг точка.
 
Название: Re: Трансформация точки по трансформации блока
Отправлено: bender от 31-05-2017, 19:04:27
зачем конвертировать вектор в строку, если есть специальные коды в РД для хранения координат

Именно. А потом обратно танцевать с бубном.

Только он не те коды указал

Те. Если нужен вектор, то его и надо хранить.

А затем, что когда я через палитру свойств задам блоку масштаб, то точка с кодом 1012 останется в своем старом состоянии. Она не изменится, хотя должна будет

А строка чего, изменяется?
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 31-05-2017, 19:27:27
bender, так в том-то и дело - данные с кодом 1012 будут изменяться вместе с объектом. Причем не учитывая перемещение и растягивание. Но не будут изменяться если делать это через палитру свойств. Так что получается, что в определенный момент этот вектор будет становится неактуальным

Да и зачем вообще эту тему обсуждаем? Как хранить вектор - дело десятое. Сейчас вопрос - как трансформировать точку по блоку
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Ривилис от 31-05-2017, 20:36:47
В какой системе координат у тебя точки (и соответственно вектор)?
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 31-05-2017, 20:46:08
В какой системе координат у тебя точки (и соответственно вектор)?
Точки в мировой системе координат. Вектор я получаю между двумя точками, поэтому логично предположить, что что он не зависит системы координат.
Я почти догадываюсь в чем проблема, но не могу пока сформулировать... В общем, если первая точка (которая соответствует blockReference.Position) будет находится в координатах 0,0,0 - тогда почти получается. Нужно как-то учитывать это расстояние между началом координат и точкой вставки блока. Я уже сам себя запутал  :-\
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Ривилис от 31-05-2017, 20:55:22
Нужно как-то учитывать это расстояние между началом координат и точкой вставки блока.
Тогда скорее не расстояние, а вектор из  blockReference.Position в начало координат.
Название: Re: Трансформация точки по трансформации блока
Отправлено: Дмитрий Загорулькин от 31-05-2017, 21:51:50
Возможно, имеет смысл хранить координаты точки во внутренней системе координат блока?
Протестировал идею. Вроде отлично работает. Максимально упростил проект: убрал из проекта Jigs, оставил только ручки и XData.
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 01-06-2017, 09:10:24
Дмитрий Загорулькин, спасибо. Идею понял. Сегодня (если будет время) постараюсь прикрутить к рабочему проекту, где так уже не упростить =)
Название: Re: Трансформация точки по трансформации блока
Отправлено: Дмитрий Загорулькин от 01-06-2017, 13:46:57
Вообще, интересный и полезный опыт. Поэтому, причесал проект, исправил мелкие баги, убрал лишнее, добавил комментариев. Т.к. проект тестово-демонстрационный, то проверок вообще почти никаких нет. В рабочем коде я бы основательно подстраховался.
Только 1010. 1020 и 1030 - это Y и Z в dxf-файле. А в Lisp/ARX/.NET всё объединено в точку в группу 1010.
Проверил - да, так и есть. Причем, код 1010 отказался принимать вектор, только точку. Пришлось преобразовывать туда-обратно.
Александр Пекшев aka Modis, зачем именно вектор? Его всегда можно получить через разницу точек. Но уже не нужно будет этих преобразований при чтении/записи XData.
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 01-06-2017, 14:00:21
Александр Пекшев aka Modis, зачем именно вектор? Его всегда можно получить через разницу точек. Но уже не нужно будет этих преобразований при чтении/записи XData
Все началось с того, что нужно получать вторую точку всегда в актуальном месте. Т.е. при любом преобразовании блока (как ручками, так и обычными методами автокада) эта точка всегда должна быть в верном положении. В какой-то момент (причин честно уже не помню) я решил использовать именно вектор. Но на тот момент я не смотрел в сторону BlockTransform, да и как вы могли заметить - не совсем так располагались примитивы внутри блока. Сейчас уже после не одного десятка всяких попыток и вариантов я начинаю склоняться к тому, что при использовании BlockTransform в XData уже можно попробовать располагать саму точку. И читая ее оттуда, преобразовывать с помощью BlockTransform.  Просто после многократных тестов выплывают проблемы в совершенно разных местах, вот и получается - пробую разные варианты и начинаю засорять проект "остатками" от прошлых вариантов
Кстати, если прокатит вариант с BlockTransform и преобразованием точки, то скорее всего отпадет надобность в ObjectOverrule
Название: Re: Трансформация точки по трансформации блока
Отправлено: Александр Пекшев aka Modis от 01-06-2017, 14:48:01
Все отлично! "Прикрутил" к рабочему проекту идею с точками в системе координат блока - все работает. Оставил вектор - где-то в душе чувствую, что я для чего-то еще решил хранить в векторе ))
Дмитрий Загорулькин, спасибо за идею и за потраченное время