我正在编写一个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应该给出以下结果:
在我的应用程序中,只要忽略他提供的变换矩阵,我就可以绘制SVG。在这种情况下,我有一个连贯的结果,但当然,不符合预期的结果。
现在我尝试将变换矩阵应用于径向渐变值。我得到了完全不一致的结果。
这是我在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);
显然这不起作用。
那么有人可以向我解释我做错了什么,以及如何将变换矩阵应用于径向渐变值以获得正确的结果?
答案 0 :(得分:1)
考虑Inkscape在其UI中表示radialGradient的方式:
(我改变了你的例子,所以焦点与中心不同,它显示为中心下方的十字架。)
您可以使用此UI以立即应用gradientTransform的方式操纵渐变,而无需知道其确切参数。您看到的是中心和两个向量,或者,如果您需要,可以定义非简并平行四边形的点。缩放矢量使得它们的长度不同,但它们也是旋转的。虽然在这种情况下它们是垂直的,但它们还可能是倾斜的。
绘制渐变最终需要的是所有三个点的坐标(加上焦点)。这将是八个独立的值,而您当前的定义只设置六个。
设置四个2D坐标在数学上与设置两个加上一些额外的独立值相同(在尝试可能的宽度,高度,旋转和倾斜之后)。这取决于你的绘画方式。表示之间的转换是纯粹的数学问题。但正如你应该从线性代数中知道的那样:你总是需要八个独立的值。