Ответ 1
Я не врывался в код, но могу немного помочь с матрицами (пункт 3).
Я предполагаю, что используются три основные матрицы преобразования: матрица вращения, масштабирования и трансляции. Пусть назовем их R, S и T соответственно.
Там сложная часть о применении матриц к точке. Скажем, вы хотите перевести точку, а затем повернуть вокруг центра начала координат. Другими словами, вы хотите применить поворот к эффекту перевода точки. Итак, матрицы будут применяться следующим образом:
R (T (P)) = R * T * P = S
Где * - матричное умножение. Обратите внимание, что порядок умноженных матриц меняется на противоположные по отношению к вашему намерению.
Однако, если вы хотите сделать обратное преобразование, помимо изменения порядка матриц, вы также должны оценить их обратные. Мы перевели точку, затем повернули - так что теперь мы повернем ее назад, а затем переведем назад:
T ^ -1 (R ^ -1 (S)) = T ^ -1 * R ^ -1 * S = P
Обратите внимание, что вам не нужно вычислять каждую обратную матрицу, так как очевидно, что T ^ -1 (x) = T (-x), R ^ -1 (угол) = R (-англ) и т.д., Однако вам придется вывести аргумент преобразования, который может быть нелегким, если у вас есть доступ только к матрице преобразования.
Я бы предположил, что координаты мира преобразуются в координаты экрана с помощью комбинации трансляции и масштабной матрицы. Последний отвечает за "изменение единицы" от мировых координат до пикселей в отношении коэффициента масштабирования всей сцены (и, возможно, DPI дисплея). С другой стороны, матрица перевода отражает панорамирование сцены и может применяться либо до, либо после матрицы шкалы; в первом случае панорамирование хранится в мировых координатах, во втором - панорамирование сохраняется в координатах экрана.
Я бы также предположил, что все преобразования объектов выполняются в мировых координатах (для меня это более удобно, чем в координатах экрана). Таким образом, вы можете ожидать, что каждая точка объекта подвергается следующему преобразованию:
W (S (R (T (P)))) = W * S * R * T * P,
где W - преобразование между экранами, S - масштаб, R - вращение, а T - перевод.
Надеюсь, я помог хотя бы немного...
Обновлено 17-04-2011
Хорошо, я просмотрел код сейчас. Метод PaintTo объекта SVG выглядит следующим образом:
procedure TSVG.PaintTo(Graphics: TGPGraphics; Bounds: TGPRectF;
Rects: PRectArray; RectCount: Integer);
var
M: TGPMatrix;
MA: TMatrixArray;
begin
M := TGPMatrix.Create;
try
Graphics.GetTransform(M);
try
M.GetElements(MA);
FInitialMatrix.Cells[0, 0] := MA[0];
FInitialMatrix.Cells[0, 1] := MA[1];
FInitialMatrix.Cells[1, 0] := MA[2];
FInitialMatrix.Cells[1, 1] := MA[3];
FInitialMatrix.Cells[2, 0] := MA[4];
FInitialMatrix.Cells[2, 1] := MA[5];
FInitialMatrix.Cells[2, 2] := 1;
SetBounds(Bounds);
Paint(Graphics, Rects, RectCount);
finally
Graphics.SetTransform(M);
end;
finally
M.Free;
end;
end;
До любого чертежа метод вызывает Graphics.GetTransform(M). Это, в свою очередь, вызывает GdipGetWorldTransform, который, как представляется, является оберткой на WinAPI GetWorldTransform.
Я думаю, что это может быть хорошим местом для начала:)