Матрицы преобразования ECS, DCS, UCS и т.д.

Автор Тема: Матрицы преобразования ECS, DCS, UCS и т.д.  (Прочитано 21446 раз)

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

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Короче говоря мы пришли к выводу, что в документации неточность и AcDbLine должен быть отнесен к классам, у которых своя собственная ECS. С точки зрения моей логики это бред, но так оно есть. В любом случае матрица ECS вычисляется на основе свойства normal (вектор нормали). Алгоритм вычисления матрицы преобразования ECS->WCS на основе вектора нормали: http://www.autodesk.com/techpubs/autocad/acadr14/dxf/arbitrary_axis_algorithm_al_u05_c.htm
Или в виде кода (C/C++): http://adn-cis.org/forum/index.php?topic=358.msg16203#msg16203 (ECS - Entity Coordinate System, OCS - Object Coordinate System - это одно и тоже).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Еще одно дополнение, которое мне сегодня прислали по поводу ECS у отрезка. Отрезок (AcDbLine) один из старейших примитивов в AutoCAD и так исторически сложилось, что у него наряду с другими плоскими примитивами есть понятие уровень, направление выдавливания и толщина (thickness):



Так вот выдавливание и толщина направлены по вектору нормали примитива. Соотвественно вектор нормали у отрезка должен быть и соотвественно по этому вектору нормали вычисляется ECS.
« Последнее редактирование: 25-05-2016, 18:36:18 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Привалов ДмитрийАвтор темы

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Так вот выдавливание и толщина направлены по вектору нормали примитива. Соотвественно вектор нормали у отрезка должен быть и соотвественно по этому вектору нормали вычисляется ECS.
Про выдавливание вдоль нормали, направленной произвольно, т.е. не вдоль оси 0Z я натыкался с десяток раз.)))))

Но у меня возник вопрос что же на самом деле первично, вектор нормали или  ECS и что из чего высчитывается?
Вы указываете уже не первый раз, что вектор нормали первичен, а из него высчитывается ECS.

Но мне почему-то упорно кажется, что первично ECS а вектор нормали вычисляется каждый раз из ECS. Данное предположение основано на том, что ECS помимо поворота, который нужен для вычисления вектора нормали содержит еще и смещение и масштабирование по осям, которые вектор нормали не содержит. Иначе смещение и масштабирование должны храниться вместе с вектором нормали где-то еще. Из этого и предполагаю что все дополнительные трансформации хранятся в одном месте в ECS, а вектора нормали как отдельного свойства примитива нет, он вычисляется каждый раз из матрицы поворота ECS.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Вы указываете уже не первый раз, что вектор нормали первичен, а из него высчитывается ECS.
Именно так. Это касается плоских объектов, о которых мы говорили.
Данное предположение основано на том, что ECS помимо поворота, который нужен для вычисления вектора нормали содержит еще и смещение и масштабирование по осям, которые вектор нормали не содержит.
Смещение определяется свойством elevation для 2D-объектов, а масштабирование по осям есть только у вставки блока, и эти масштабы содержатся отдельно в свойстве scaleFactors. Для вставки блока вообще всё иначе. Как я блок не крутил, не зеркалил и не масштабировал его ECS оставалась единичной.


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

Оффлайн Привалов ДмитрийАвтор темы

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Это касается плоских объектов, о которых мы говорили.
Ну мы же определили что они хорошо содержат в себе ECS. о которой ниже распишу.

Смещение определяется свойством elevation для 2D-объектов, а масштабирование по осям есть только у вставки блока, и эти масштабы содержатся отдельно в свойстве scaleFactors. Для вставки блока вообще всё иначе. Как я блок не крутил, не зеркалил и не масштабировал его ECS оставалась единичной.
у меня другие выводы....просто почти уверен что прав, т.к. просмотрел с несколько десятков объектов с матрицей. И смотрел иерархию наследования объектов.
Есть матрица у объекта. Это именно Matrix3d. Она задает трансформацию координат объекта относительно MCS.
1. смещения вдоль осей
2. повороты относительно осей
3. масштабирование объекта

ECS может применяться к любому Entity. Даже подозреваю, что программно можно навешать на BlockBegin и это прокатит.

public abstract class Entity : DBObject
{
....
public virtual Matrix3d Ecs { get; }
...
}
...матрица определена в базовом классе для графических объектов Entity и никакого вектора нормали в Entity не определяется!

Дальше объекты, наследуемые от Entity определяют поверх свойства выдавливания и т.д.
Curve : Entity


...далее
public class Line : Curve
{
   ....
   public Vector3d Normal { get; set; }
   public double Thickness { get; set; }
   ...
}


Т.е. все Entity уже содержат в себе ECS
Все свойства, типо Normal и Thickness  уже появляются позже в результате наследования. Т.е. они реализованы поверх ECS и учитывают ее.

Я думаю что происходит все следующим образом. Когда к объекту Entity применяется трансформация, то функции трансформации, переопределенные для каждого объекта, т.е. в конкретном классе Line, BlockReference и т.д. пытаются раскидать матрицу по свойствам, т.е. для линии при трансформации вдоль осей пересчитаются координаты с учетом матрицы и матрица будет единичной. Но вот поворот другое дело, он изменяет поведение Thickness, поэтому при повороте, будет записана матрица поворота в Line.

У блока есть побольше свойств
public class BlockReference : Entity
{
public virtual Matrix3d BlockTransform { get; set; }
public virtual Point3d Position { get; set; }
public virtual double Rotation { get; set; }
public virtual Scale3d ScaleFactors { get; set; }
}

т.е. есть куда разгуляться и раскидать трансформации из ECS на свойства блока.
ну как-то так.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Есть матрица у объекта. Это именно Matrix3d. Она задает трансформацию координат объекта относительно MCS.
Сохрани объект в DXF и поищи там матрицу.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Еще одно подтверждение моих слов. Посмотри в документации функцию ObjectARX с именем acdbEcs2Wcs, которая преобразует координаты из ECS в WCS. Так вот она на вход получает не матрицу ECS, а единичный вектор нормали:
Код - C++ [Выбрать]
  1. bool acdbEcs2Wcs(
  2.     ads_point p, // точка или вектор исходный
  3.     ads_point q, // точка или вектор результирующий
  4.     ads_point norm, // вектор нормали ECS
  5.     bool vec // преобразуется точка или вектор
  6. );
  7.  
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Привалов ДмитрийАвтор темы

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Сохрани объект в DXF и поищи там матрицу.
Еще одно подтверждение моих слов

Ну скорее всего правда ваша. Провел несколько экспериментов над подопытными.

1 В dxf в свойствах действительно только Normal сохраняется, Ecs нет.

если только ECS не храниться в отдельном месте в зашифрованном виде, т.к. поиском текста не нашел. Но для того чтоб выяснить нужно вникать в структуру DXF, чего быстро я не смогу сделать.(но дальнейшие тесты подтверждают, что ECS все-таки нет)

2. Проверил "на кроликах"
Код - C# [Выбрать]
  1. Document document = Cad.DocumentManager.MdiActiveDocument;
  2. DocumentLock documentLock = document.LockDocument();
  3.  
  4. Database db = HostApplicationServices.WorkingDatabase;
  5. Transaction tr = db.TransactionManager.StartTransaction();
  6.  
  7. BlockTable blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
  8. BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead, false);
  9.  
  10. ObjectId blockBeginId = modelSpace.BlockBeginId;
  11. BlockBegin blockBegin = tr.GetObject(blockBeginId, OpenMode.ForWrite, false) as BlockBegin;
  12.  
  13. Matrix3d rotation = Matrix3d.Rotation(35, new Vector3d(0, 1, 1), new Point3d(-1000, -1000, -1000));
  14. blockBegin.TransformBy(rotation);
  15.  
  16. tr.Commit();
  17. tr.Dispose();
  18. documentLock.Dispose();

BlockBegin  не поддался. eNotApplicable и это к лучшему. ))))
Вывод не на все Entity применим TransformBy и это уже  частично подтверждает вашу правоту.

3. Попробовал трансформировать разные примитивы, тем же методом что и для BlockBegin 
MText, Text, Line, Polyline, Circle, Spline, Hatch
все плоские объекты IsPlanar(если я правильно понял это и есть флаг что объекты плоские) успешно повернулись.
Text и Spline единственные, кто оставил единичную матрицу.

При этом Text повернулся. Text.Ecs выдает единичную матрицу((1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1)), а Normal (-0.302770869187287,0.951846102545754,0.0481538974542467).
Подозреваю, что это баг Text.Ecs(acad 2014SP1)!!! И подтверждение ваших слов, что Normal первична, а Ecs высчитывается из нее.

Вобщем выводы такие:
1. Normal первична. Ecs высчитывается из нее.
2. Скорее всего в Entity определено, что всегда выдается единичная матрица, а наследуемый примитив должен переопределить выдаваемую матрицу на основе своих свойств. Что похоже не реализовано в Text.
3. Spline не содержит Normal соответственно всегда выдаст единичную матрицу
4. При применении TransformBy пересчитываются внутренние координаты, и назначается нормаль(если она задана). На основе этих данных и выдается Ecs, что и говорил Александр.
5. Скорее всего из всех матриц, что были применены к объекту с помощью TransformBy , Еcs вернет только поворот, а перемещения и масштаб пересчитают координаты объекта, и не будут возвращены Ecs.(по крайней мере для плоских объектов)
« Последнее редактирование: 26-05-2016, 10:37:05 от Привалов Дмитрий »

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
2. Скорее всего в Entity определено, что всегда выдается нулевая матрица, а наследуемый примитив должен переопределить выдаваемую матрицу на основе своих свойств. Что похоже не реализовано в Text.
1. Не "нулевая", а "единичная" (identity) матрица.
2. Об этом четко сказано в документации:
Цитировать
Description
This function is intended to be overridden by derived classes that need to be able to provide access to an object coordinate system for objects of the class. The intent is that this function provide a transformation matrix that can be used to transform vectors or points from the object's object coordinate system (OCS) to the World Coordinate System (WCS).

Default implementation: Return the identity matrix (ones along the diagonal, zeros elsewhere) in retVal.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Привалов ДмитрийАвтор темы

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
1. Не "нулевая", а "единичная" (identity) матрица.
чет я плавно от единичной перешел к нулевой)))...поправил