package gg import "math" type Matrix struct { XX, YX, XY, YY, X0, Y0 float64 } func Identity() Matrix { return Matrix{ 1, 0, 0, 1, 0, 0, } } func Translate(x, y float64) Matrix { return Matrix{ 1, 0, 0, 1, x, y, } } func Scale(x, y float64) Matrix { return Matrix{ x, 0, 0, y, 0, 0, } } func ScaleAbout(sx, sy, x, y float64) Matrix { a := Translate(-x, -y) b := Scale(sx, sy) c := Translate(x, y) return a.Multiply(b).Multiply(c) } func Rotate(angle float64) Matrix { c := math.Cos(angle) s := math.Sin(angle) return Matrix{ c, s, -s, c, 0, 0, } } func RotateAbout(angle, x, y float64) Matrix { a := Translate(-x, -y) b := Rotate(angle) c := Translate(x, y) return a.Multiply(b).Multiply(c) } func Shear(x, y float64) Matrix { return Matrix{ 1, y, x, 1, 0, 0, } } func ShearAbout(sx, sy, x, y float64) Matrix { a := Translate(-x, -y) b := Shear(sx, sy) c := Translate(x, y) return a.Multiply(b).Multiply(c) } func (a Matrix) Multiply(b Matrix) Matrix { return Matrix{ a.XX*b.XX + a.YX*b.XY, a.XX*b.YX + a.YX*b.YY, a.XY*b.XX + a.YY*b.XY, a.XY*b.YX + a.YY*b.YY, a.X0*b.XX + a.Y0*b.XY + b.X0, a.X0*b.YX + a.Y0*b.YY + b.Y0, } } func (a Matrix) TransformVector(x, y float64) (tx, ty float64) { tx = a.XX*x + a.XY*y ty = a.YX*x + a.YY*y return } func (a Matrix) TransformPoint(x, y float64) (tx, ty float64) { tx = a.XX*x + a.XY*y + a.X0 ty = a.YX*x + a.YY*y + a.Y0 return } func (a Matrix) Translate(x, y float64) Matrix { return Translate(x, y).Multiply(a) } func (a Matrix) Scale(x, y float64) Matrix { return Scale(x, y).Multiply(a) } func (a Matrix) ScaleAbout(sx, sy, x, y float64) Matrix { return ScaleAbout(sx, sy, x, y).Multiply(a) } func (a Matrix) Rotate(angle float64) Matrix { return Rotate(angle).Multiply(a) } func (a Matrix) RotateAbout(angle, x, y float64) Matrix { return RotateAbout(angle, x, y).Multiply(a) } func (a Matrix) Shear(x, y float64) Matrix { return Shear(x, y).Multiply(a) } func (a Matrix) ShearAbout(sx, sy, x, y float64) Matrix { return ShearAbout(sx, sy, x, y).Multiply(a) }