func (tr *Matrix) Scale(sx, sy float64) {
	tr[0] = sx * tr[0]
	tr[1] = sx * tr[1]
	tr[2] = sy * tr[2]
	tr[3] = sy * tr[3]
}
Scale adds a scale to the matrix
package draw2d
import (
	"math"
)
type Matrix [6]float64
const (
	epsilon = 1e-6
)
func (tr Matrix) Determinant() float64 {
	return tr[0]*tr[3] - tr[1]*tr[2]
}
func (tr Matrix) Transform(points []float64) {
	for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
		x := points[i]
		y := points[j]
		points[i] = x*tr[0] + y*tr[2] + tr[4]
		points[j] = x*tr[1] + y*tr[3] + tr[5]
	}
}
func (tr Matrix) TransformPoint(x, y float64) (xres, yres float64) {
	xres = x*tr[0] + y*tr[2] + tr[4]
	yres = x*tr[1] + y*tr[3] + tr[5]
	return xres, yres
}
func minMax(x, y float64) (min, max float64) {
	if x > y {
		return y, x
	}
	return x, y
}
func (tr Matrix) TransformRectangle(x0, y0, x2, y2 float64) (nx0, ny0, nx2, ny2 float64) {
	points := []float64{x0, y0, x2, y0, x2, y2, x0, y2}
	tr.Transform(points)
	points[0], points[2] = minMax(points[0], points[2])
	points[4], points[6] = minMax(points[4], points[6])
	points[1], points[3] = minMax(points[1], points[3])
	points[5], points[7] = minMax(points[5], points[7])
	nx0 = math.Min(points[0], points[4])
	ny0 = math.Min(points[1], points[5])
	nx2 = math.Max(points[2], points[6])
	ny2 = math.Max(points[3], points[7])
	return nx0, ny0, nx2, ny2
}
func (tr Matrix) InverseTransform(points []float64) {
	d := tr.Determinant()  
	for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
		x := points[i]
		y := points[j]
		points[i] = ((x-tr[4])*tr[3] - (y-tr[5])*tr[2]) / d
		points[j] = ((y-tr[5])*tr[0] - (x-tr[4])*tr[1]) / d
	}
}
func (tr Matrix) InverseTransformPoint(x, y float64) (xres, yres float64) {
	d := tr.Determinant()  
	xres = ((x-tr[4])*tr[3] - (y-tr[5])*tr[2]) / d
	yres = ((y-tr[5])*tr[0] - (x-tr[4])*tr[1]) / d
	return xres, yres
}
func (tr Matrix) VectorTransform(points []float64) {
	for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
		x := points[i]
		y := points[j]
		points[i] = x*tr[0] + y*tr[2]
		points[j] = x*tr[1] + y*tr[3]
	}
}
func NewIdentityMatrix() Matrix {
	return Matrix{1, 0, 0, 1, 0, 0}
}
func NewTranslationMatrix(tx, ty float64) Matrix {
	return Matrix{1, 0, 0, 1, tx, ty}
}
func NewScaleMatrix(sx, sy float64) Matrix {
	return Matrix{sx, 0, 0, sy, 0, 0}
}
func NewRotationMatrix(angle float64) Matrix {
	c := math.Cos(angle)
	s := math.Sin(angle)
	return Matrix{c, s, -s, c, 0, 0}
}
func NewMatrixFromRects(rectangle1, rectangle2 [4]float64) Matrix {
	xScale := (rectangle2[2] - rectangle2[0]) / (rectangle1[2] - rectangle1[0])
	yScale := (rectangle2[3] - rectangle2[1]) / (rectangle1[3] - rectangle1[1])
	xOffset := rectangle2[0] - (rectangle1[0] * xScale)
	yOffset := rectangle2[1] - (rectangle1[1] * yScale)
	return Matrix{xScale, 0, 0, yScale, xOffset, yOffset}
}
func (tr *Matrix) Inverse() {
	d := tr.Determinant()  
	tr0, tr1, tr2, tr3, tr4, tr5 := tr[0], tr[1], tr[2], tr[3], tr[4], tr[5]
	tr[0] = tr3 / d
	tr[1] = -tr1 / d
	tr[2] = -tr2 / d
	tr[3] = tr0 / d
	tr[4] = (tr2*tr5 - tr3*tr4) / d
	tr[5] = (tr1*tr4 - tr0*tr5) / d
}
func (tr Matrix) Copy() Matrix {
	var result Matrix
	copy(result[:], tr[:])
	return result
}
func (tr *Matrix) Compose(trToCompose Matrix) {
	tr0, tr1, tr2, tr3, tr4, tr5 := tr[0], tr[1], tr[2], tr[3], tr[4], tr[5]
	tr[0] = trToCompose[0]*tr0 + trToCompose[1]*tr2
	tr[1] = trToCompose[1]*tr3 + trToCompose[0]*tr1
	tr[2] = trToCompose[2]*tr0 + trToCompose[3]*tr2
	tr[3] = trToCompose[3]*tr3 + trToCompose[2]*tr1
	tr[4] = trToCompose[4]*tr0 + trToCompose[5]*tr2 + tr4
	tr[5] = trToCompose[5]*tr3 + trToCompose[4]*tr1 + tr5
}