MCPcopy
hub / github.com/tdewolff/canvas / Transform

Method Transform

path.go:1267–1341  ·  view source on GitHub ↗

Transform transforms the path by the given transformation matrix. It modifies the path in-place.

(m Matrix)

Source from the content-addressed store, hash-verified

1265
1266// Transform transforms the path by the given transformation matrix. It modifies the path in-place.
1267func (p *Path) Transform(m Matrix) *Path {
1268 _, _, _, xscale, yscale, _ := m.Decompose()
1269 for i := 0; i < len(p.d); {
1270 cmd := p.d[i]
1271 switch cmd {
1272 case MoveToCmd, LineToCmd, CloseCmd:
1273 end := m.Dot(Point{p.d[i+1], p.d[i+2]})
1274 p.d[i+1] = end.X
1275 p.d[i+2] = end.Y
1276 case QuadToCmd:
1277 cp := m.Dot(Point{p.d[i+1], p.d[i+2]})
1278 end := m.Dot(Point{p.d[i+3], p.d[i+4]})
1279 p.d[i+1] = cp.X
1280 p.d[i+2] = cp.Y
1281 p.d[i+3] = end.X
1282 p.d[i+4] = end.Y
1283 case CubeToCmd:
1284 cp1 := m.Dot(Point{p.d[i+1], p.d[i+2]})
1285 cp2 := m.Dot(Point{p.d[i+3], p.d[i+4]})
1286 end := m.Dot(Point{p.d[i+5], p.d[i+6]})
1287 p.d[i+1] = cp1.X
1288 p.d[i+2] = cp1.Y
1289 p.d[i+3] = cp2.X
1290 p.d[i+4] = cp2.Y
1291 p.d[i+5] = end.X
1292 p.d[i+6] = end.Y
1293 case ArcToCmd:
1294 rx := p.d[i+1]
1295 ry := p.d[i+2]
1296 phi := p.d[i+3]
1297 large, sweep := toArcFlags(p.d[i+4])
1298 end := Point{p.d[i+5], p.d[i+6]}
1299
1300 // For ellipses written as the conic section equation in matrix form, we have:
1301 // [x, y] E [x; y] = 0, with E = [1/rx^2, 0; 0, 1/ry^2]
1302 // For our transformed ellipse we have [x', y'] = T [x, y], with T the affine
1303 // transformation matrix so that
1304 // (T^-1 [x'; y'])^T E (T^-1 [x'; y'] = 0 => [x', y'] T^(-T) E T^(-1) [x'; y'] = 0
1305 // We define Q = T^(-1,T) E T^(-1) the new ellipse equation which is typically rotated
1306 // from the x-axis. That's why we find the eigenvalues and eigenvectors (the new
1307 // direction and length of the major and minor axes).
1308 T := m.Rotate(phi * 180.0 / math.Pi)
1309 invT := T.Inv()
1310 Q := Identity.Scale(1.0/rx/rx, 1.0/ry/ry)
1311 Q = invT.T().Mul(Q).Mul(invT)
1312
1313 lambda1, lambda2, v1, v2 := Q.Eigen()
1314 rx = 1 / math.Sqrt(lambda1)
1315 ry = 1 / math.Sqrt(lambda2)
1316 phi = v1.Angle()
1317 if rx < ry {
1318 rx, ry = ry, rx
1319 phi = v2.Angle()
1320 }
1321 phi = angleNorm(phi)
1322 if math.Pi <= phi { // phi is canonical within 0 <= phi < 180
1323 phi -= math.Pi
1324 }

Callers 9

ParseLaTeXFunction · 0.95
TranslateMethod · 0.95
ScaleMethod · 0.95
RotateMethod · 0.95
toPathMethod · 0.95
floretTilingFunction · 0.95
cairoTilingFunction · 0.95
RenderPathMethod · 0.95
mainFunction · 0.95

Calls 13

toArcFlagsFunction · 0.85
angleNormFunction · 0.85
fromArcFlagsFunction · 0.85
cmdLenFunction · 0.85
DecomposeMethod · 0.80
InvMethod · 0.80
TMethod · 0.80
EigenMethod · 0.80
AngleMethod · 0.80
DotMethod · 0.45
RotateMethod · 0.45
ScaleMethod · 0.45

Tested by

no test coverage detected