Значение порядка преобразований
Один объект Matrix может хранить одно преобразование или последовательность преобразований. Последнее называется составнымпреобразованием. Матрица составного преобразования получается путем умножения матриц отдельных преобразований.
В составном преобразовании важен порядок отдельных преобразований. Например, если применяется поворот, затем масштабирование, а затем сдвиг, получается совершенно иной результат, чем если бы сначала был применен сдвиг, затем поворот, а затем масштабирование. В Windows GDI+ составные преобразования создаются слева направо. Если S, R и T являются матрицами масштабирования, поворота и сдвига соответственно, тогда произведение SRT (именно в таком порядке) является матрицей составного преобразования, которое сначала масштабирует, затем поворачивает, а затем осуществляет сдвиг. Матрица, равная произведению SRT, отличается от матрицы, являющейся произведением TRS.
Одной из причин важности порядка выполнения преобразований является то, что такие преобразования, как поворот и масштабирование, осуществляются относительно начала координат. Масштабирование объекта, центрированного по началу координат, дает другой результат, чем масштабирование объекта, который куда-либо сдвинут относительно этой точки. Аналогично, поворот объекта, центрированного по началу координат, дает другой результат, чем поворот объекта, который куда-либо сдвинут относительно этой точки.
В следующем примере комбинация масштабирования, поворота и сдвига (именно в таком порядке) используется для конструирования составного преобразования. Аргумент MatrixOrderAppend , передаваемый методу Graphics::RotateTransform , указывает, что поворот будет следовать за масштабированием. Аналогичным образом, аргумент MatrixOrderAppend , переданный методу Graphics::TranslateTransform , указывает, что преобразование будет следовать за поворотом.
Rect rect(0, 0, 50, 50);
Pen pen(Color(255, 255, 0, 0), 0);
graphics.ScaleTransform(1.75f, 0.5f);
graphics.RotateTransform(28.0f, MatrixOrderAppend);
graphics.TranslateTransform(150.0f, 150.0f, MatrixOrderAppend);
graphics.DrawRectangle(&pen, rect);
В следующем примере выполняется тот же вызов метода, что и в предыдущем примере, но порядок вызовов обратный. Результирующий порядок операций сначала преобразуется, затем поворачивается, а затем масштабируется, что приводит к совершенно другому результату, чем при первом масштабировании, затем вращении, а затем переводе:
Rect rect(0, 0, 50, 50);
Pen pen(Color(255, 255, 0, 0), 0);
graphics.TranslateTransform(150.0f, 150.0f);
graphics.RotateTransform(28.0f, MatrixOrderAppend);
graphics.ScaleTransform(1.75f, 0.5f, MatrixOrderAppend);
graphics.DrawRectangle(&pen, rect);
Один из способов изменить порядок отдельных преобразований в составном преобразовании — изменить порядок последовательности вызовов методов. Второй способ управления порядком операций заключается в изменении значения аргумента порядка следования матриц. Следующий пример такой же, как и предыдущий, за исключением того, что MatrixOrderAppend был изменен на MatrixOrderPrepend. Перемножение матриц осуществляется в порядке SRT, где S, R и T являются матрицами масштабирования, поворота и сдвига соответственно. При применении составного преобразования сначала осуществляется масштабирование, затем поворот, а затем сдвиг.
Rect rect(0, 0, 50, 50);
Pen pen(Color(255, 255, 0, 0), 0);
graphics.TranslateTransform(150.0f, 150.0f,MatrixOrderPrepend);
graphics.RotateTransform(28.0f, MatrixOrderPrepend);
graphics.ScaleTransform(1.75f, 0.5f, MatrixOrderPrepend);
graphics.DrawRectangle(&pen, rect);
Результат предыдущего примера совпадает с результатом, достигнутым в первом примере этого раздела. Это объясняется тем, что были изменены на обратный как порядок вызовов методов, так и порядок умножения матриц.