Хиттест с использованием экранных координат в изображениях SVG в мировых координатах - PullRequest
17 голосов
/ 13 апреля 2011

Как мне перевести координаты мыши в мировые координаты, используя GDI +? Или получите ограничивающие рамки (или даже лучше) старых областей skool для форм SVG, нарисованных с использованием GDI +?

В любом случае. Я искал код SVG и нашел:
http://development.mwcs.de/svgimage.html
Это первый компонент Delphi, который на самом деле работает для SVG, но я отвлекся.

Этот компонент использует GDI + для отображения кругов, кривых и т. Д.
GDI + использует матрицы для преобразования мировых координат, поворотов и искажений в экранные координаты.
Эту часть я понимаю. Вы используете умножение матриц для перевода.

Проблема в этом
Если я наведу курсор мыши на замкнутую фигуру:

  1. Где взять матрицу, которая переведет мою точку экрана моей мыши в точку мира, которую я могу ударить в круг, который я вижу нарисованным на экране?
    Во всех этих объектах GDI можно выбирать из множества матриц.
  2. Пожалуйста, не давайте мне ничего о рисовании на растровом изображении и проверке магических цветов под курсором, это не то, что я ищу.
  3. Если есть цепочка матриц, как мне пройти их в правильном (перевернутом?) Порядке, чтобы моя экранная координата правильно направлялась к мировой координате?

Другими словами
Фигуры, которые считываются с изображения SVG, являются примитивами, которые искажаются матрицами в экранные координаты. Как сделать обратное преобразование из экранной координаты в координаты, которые я могу использовать, чтобы увидеть, нахожусь ли я внутри фигуры.

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

EDIT

С другой стороны

  1. Могу ли я получить ограничивающий прямоугольник для фигуры в экранных координатах, чтобы я мог проверить мои координаты мыши по этому.
  2. Могу ли я получить старый GDI регион skool, где я могу сделать PtInRegion с экранными координатами.

Надеюсь, вы поможете мне сориентироваться во всех этих искаженных путях: -).

Ответы [ 2 ]

7 голосов
/ 16 апреля 2011

Я не копался в коде, но могу немного помочь с матрицами (пункт 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 .

.

Полагаю, это может быть хорошее место для старта :) 1038 *

0 голосов
/ 31 мая 2011

С GDI + вы должны следить за тем, что вы делаете / сделали, так как сам GDI + забывает все, кроме самих пикселей после их прорисовки. Модуль SVG должен следить за всем, что нужно для рисования всех фигур и установки окна просмотра GDI +. Так что было бы легче получить информацию, которую вы ищете, из библиотеки SVG.

...