Подтвердить что ты не робот

Hittest с использованием экранных координат в изображениях SVG в координатах мира

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

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

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

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

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

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

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

ИЗМЕНИТЬ

В качестве альтернативы

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

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

4b9b3361

Ответ 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.

Я думаю, что это может быть хорошим местом для начала:)

Ответ 2

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