SVG - Как применить матрицу преобразования к радиальному градиенту? - PullRequest
0 голосов
/ 26 мая 2018

Я пишу приложение на c ++, которое может открыть несколько файлов SVG и нарисовать их на экране.Некоторые из них содержат радиальный градиент, в котором предусмотрена матрица преобразования.Мне нужно вычислить окончательные значения градиента, которые нужно применить перед выполнением рисования, но у меня есть некоторые проблемы с этим.

Например, рассмотрим следующий SVG:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   version="1.1"
   id="svg2"
   viewBox="0 0 250 250"
   height="250"
   width="250">
  <defs
     id="defs4">
    <linearGradient
       osb:paint="gradient"
       id="linearGradient4162">
      <stop
         id="stop4164"
         offset="0"
         style="stop-color:#d4ca67;stop-opacity:1" />
      <stop
         id="stop4166"
         offset="1"
         style="stop-color:#64caea;stop-opacity:1;" />
    </linearGradient>
    <radialGradient
       gradientUnits="userSpaceOnUse"
       gradientTransform="matrix(0.43766035,0.50852999,-0.28201922,0.24271652,332.30951,640.28863)"
       spreadMethod="reflect"
       r="125.35714"
       fy="938.15851"
       fx="14.381515"
       cy="938.15851"
       cx="14.381515"
       id="radialGradient4172"
       xlink:href="#linearGradient4162" />
  </defs>
  <g
     transform="translate(0,-802.36216)"
     id="layer1">
    <path
       id="rect4136"
       d="m 0.45358449,802.63 250.71427551,0 0,250.3572 -250.71427551,0 z"
       style="opacity:1;fill:url(#radialGradient4172);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
  </g>
</svg>

После того, как нарисовано,этот SVG должен дать следующий результат:

enter image description here

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

enter image description here

Теперь я пытаюсь применить матрицу преобразования кзначения радиального градиента.Я получаю совершенно противоречивый результат.

enter image description here

Вот псевдокод того, что я пытаюсь сделать в своем коде c ++, чтобыполучите правильные преобразованные значения градиента:

Vector2 brushRadius(brush.Radius.Width, brush.Radius.Height);
Vector2 brushCenter(brush.Center.X, brush.Center.Y);
Vector2 brushFocus(brush.Focus.X, brush.Focus.Y);

brushRadius = brush.Matrix.Transform(brushRadius);
brushCenter = brush.Matrix.Transform(brushCenter);
brushFocus  = brush.Matrix.Transform(brushFocus);

brush.m_Radius = Size(brushRadius.X, brushRadius.Y);
brush.m_Center = Point(brushCenter.X, brushCenter.Y);
brush.m_Focus  = Point(brushFocus.X, brushFocus.Y);

Очевидно, это не работает.

Так что кто-то может объяснить мне, что я делаю неправильно, и как применить матрицу преобразования кЗначения радиального градиента для получения правильного результата?

1 Ответ

0 голосов
/ 26 мая 2018

Рассмотрим, как Inkscape представляет radialGradient в своем пользовательском интерфейсе:

enter image description here

(я изменил ваш пример, поэтому фокус не идентиченв центре, он показан как крест под центром.)

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

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

Установка четырех 2D координат математически идентична установке двух плюс некоторые дополнительные независимые значения (после вашей попытки, вероятно, ширина, высота, поворот и наклон).Это будет зависеть от того, как вы рисуете.Преобразование между представлениями является чисто математической проблемой.Но, как вы должны знать из линейной алгебры: вам всегда нужно восемь независимых значений.

...