summaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/code.google.com/p/draw2d/draw2d/transform.go
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/code.google.com/p/draw2d/draw2d/transform.go')
-rw-r--r--Godeps/_workspace/src/code.google.com/p/draw2d/draw2d/transform.go306
1 files changed, 306 insertions, 0 deletions
diff --git a/Godeps/_workspace/src/code.google.com/p/draw2d/draw2d/transform.go b/Godeps/_workspace/src/code.google.com/p/draw2d/draw2d/transform.go
new file mode 100644
index 000000000..1d89bfa9b
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/draw2d/draw2d/transform.go
@@ -0,0 +1,306 @@
+// Copyright 2010 The draw2d Authors. All rights reserved.
+// created: 21/11/2010 by Laurent Le Goff
+
+package draw2d
+
+import (
+ "code.google.com/p/freetype-go/freetype/raster"
+ "math"
+)
+
+type MatrixTransform [6]float64
+
+const (
+ epsilon = 1e-6
+)
+
+func (tr MatrixTransform) Determinant() float64 {
+ return tr[0]*tr[3] - tr[1]*tr[2]
+}
+
+func (tr MatrixTransform) 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 MatrixTransform) TransformArray(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 MatrixTransform) TransformRectangle(x0, y0, x2, y2 *float64) {
+ x1 := *x2
+ y1 := *y0
+ x3 := *x0
+ y3 := *y2
+ tr.Transform(x0, y0, &x1, &y1, x2, y2, &x3, &y3)
+ *x0, x1 = minMax(*x0, x1)
+ *x2, x3 = minMax(*x2, x3)
+ *y0, y1 = minMax(*y0, y1)
+ *y2, y3 = minMax(*y2, y3)
+
+ *x0 = min(*x0, *x2)
+ *y0 = min(*y0, *y2)
+ *x2 = max(x1, x3)
+ *y2 = max(y1, y3)
+}
+
+func (tr MatrixTransform) TransformRasterPoint(points ...*raster.Point) {
+ for _, point := range points {
+ x := float64(point.X) / 256
+ y := float64(point.Y) / 256
+ point.X = raster.Fix32((x*tr[0] + y*tr[2] + tr[4]) * 256)
+ point.Y = raster.Fix32((x*tr[1] + y*tr[3] + tr[5]) * 256)
+ }
+}
+
+func (tr MatrixTransform) InverseTransform(points ...*float64) {
+ d := tr.Determinant() // matrix 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
+ }
+}
+
+// ******************** Vector transformations ********************
+
+func (tr MatrixTransform) 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]
+ }
+}
+
+// ******************** Transformations creation ********************
+
+/** Creates an identity transformation. */
+func NewIdentityMatrix() MatrixTransform {
+ return [6]float64{1, 0, 0, 1, 0, 0}
+}
+
+/**
+ * Creates a transformation with a translation, that,
+ * transform point1 into point2.
+ */
+func NewTranslationMatrix(tx, ty float64) MatrixTransform {
+ return [6]float64{1, 0, 0, 1, tx, ty}
+}
+
+/**
+ * Creates a transformation with a sx, sy scale factor
+ */
+func NewScaleMatrix(sx, sy float64) MatrixTransform {
+ return [6]float64{sx, 0, 0, sy, 0, 0}
+}
+
+/**
+ * Creates a rotation transformation.
+ */
+func NewRotationMatrix(angle float64) MatrixTransform {
+ c := math.Cos(angle)
+ s := math.Sin(angle)
+ return [6]float64{c, s, -s, c, 0, 0}
+}
+
+/**
+ * Creates a transformation, combining a scale and a translation, that transform rectangle1 into rectangle2.
+ */
+func NewMatrixTransform(rectangle1, rectangle2 [4]float64) MatrixTransform {
+ 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 [6]float64{xScale, 0, 0, yScale, xOffset, yOffset}
+}
+
+// ******************** Transformations operations ********************
+
+/**
+ * Returns a transformation that is the inverse of the given transformation.
+ */
+func (tr MatrixTransform) GetInverseTransformation() MatrixTransform {
+ d := tr.Determinant() // matrix determinant
+ return [6]float64{
+ tr[3] / d,
+ -tr[1] / d,
+ -tr[2] / d,
+ tr[0] / d,
+ (tr[2]*tr[5] - tr[3]*tr[4]) / d,
+ (tr[1]*tr[4] - tr[0]*tr[5]) / d}
+}
+
+func (tr1 MatrixTransform) Multiply(tr2 MatrixTransform) MatrixTransform {
+ return [6]float64{
+ tr1[0]*tr2[0] + tr1[1]*tr2[2],
+ tr1[1]*tr2[3] + tr1[0]*tr2[1],
+ tr1[2]*tr2[0] + tr1[3]*tr2[2],
+ tr1[3]*tr2[3] + tr1[2]*tr2[1],
+ tr1[4]*tr2[0] + tr1[5]*tr2[2] + tr2[4],
+ tr1[5]*tr2[3] + tr1[4]*tr2[1] + tr2[5]}
+}
+
+func (tr *MatrixTransform) Scale(sx, sy float64) *MatrixTransform {
+ tr[0] = sx * tr[0]
+ tr[1] = sx * tr[1]
+ tr[2] = sy * tr[2]
+ tr[3] = sy * tr[3]
+ return tr
+}
+
+func (tr *MatrixTransform) Translate(tx, ty float64) *MatrixTransform {
+ tr[4] = tx*tr[0] + ty*tr[2] + tr[4]
+ tr[5] = ty*tr[3] + tx*tr[1] + tr[5]
+ return tr
+}
+
+func (tr *MatrixTransform) Rotate(angle float64) *MatrixTransform {
+ c := math.Cos(angle)
+ s := math.Sin(angle)
+ t0 := c*tr[0] + s*tr[2]
+ t1 := s*tr[3] + c*tr[1]
+ t2 := c*tr[2] - s*tr[0]
+ t3 := c*tr[3] - s*tr[1]
+ tr[0] = t0
+ tr[1] = t1
+ tr[2] = t2
+ tr[3] = t3
+ return tr
+}
+
+func (tr MatrixTransform) GetTranslation() (x, y float64) {
+ return tr[4], tr[5]
+}
+
+func (tr MatrixTransform) GetScaling() (x, y float64) {
+ return tr[0], tr[3]
+}
+
+func (tr MatrixTransform) GetScale() float64 {
+ x := 0.707106781*tr[0] + 0.707106781*tr[1]
+ y := 0.707106781*tr[2] + 0.707106781*tr[3]
+ return math.Sqrt(x*x + y*y)
+}
+
+func (tr MatrixTransform) GetMaxAbsScaling() (s float64) {
+ sx := math.Abs(tr[0])
+ sy := math.Abs(tr[3])
+ if sx > sy {
+ return sx
+ }
+ return sy
+}
+
+func (tr MatrixTransform) GetMinAbsScaling() (s float64) {
+ sx := math.Abs(tr[0])
+ sy := math.Abs(tr[3])
+ if sx > sy {
+ return sy
+ }
+ return sx
+}
+
+// ******************** Testing ********************
+
+/**
+ * Tests if a two transformation are equal. A tolerance is applied when
+ * comparing matrix elements.
+ */
+func (tr1 MatrixTransform) Equals(tr2 MatrixTransform) bool {
+ for i := 0; i < 6; i = i + 1 {
+ if !fequals(tr1[i], tr2[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+/**
+ * Tests if a transformation is the identity transformation. A tolerance
+ * is applied when comparing matrix elements.
+ */
+func (tr MatrixTransform) IsIdentity() bool {
+ return fequals(tr[4], 0) && fequals(tr[5], 0) && tr.IsTranslation()
+}
+
+/**
+ * Tests if a transformation is is a pure translation. A tolerance
+ * is applied when comparing matrix elements.
+ */
+func (tr MatrixTransform) IsTranslation() bool {
+ return fequals(tr[0], 1) && fequals(tr[1], 0) && fequals(tr[2], 0) && fequals(tr[3], 1)
+}
+
+/**
+ * Compares two floats.
+ * return true if the distance between the two floats is less than epsilon, false otherwise
+ */
+func fequals(float1, float2 float64) bool {
+ return math.Abs(float1-float2) <= epsilon
+}
+
+// this VertexConverter apply the Matrix transformation tr
+type VertexMatrixTransform struct {
+ tr MatrixTransform
+ Next VertexConverter
+}
+
+func NewVertexMatrixTransform(tr MatrixTransform, converter VertexConverter) *VertexMatrixTransform {
+ return &VertexMatrixTransform{tr, converter}
+}
+
+// Vertex Matrix Transform
+func (vmt *VertexMatrixTransform) NextCommand(command VertexCommand) {
+ vmt.Next.NextCommand(command)
+}
+
+func (vmt *VertexMatrixTransform) Vertex(x, y float64) {
+ u := x*vmt.tr[0] + y*vmt.tr[2] + vmt.tr[4]
+ v := x*vmt.tr[1] + y*vmt.tr[3] + vmt.tr[5]
+ vmt.Next.Vertex(u, v)
+}
+
+// this adder apply a Matrix transformation to points
+type MatrixTransformAdder struct {
+ tr MatrixTransform
+ next raster.Adder
+}
+
+func NewMatrixTransformAdder(tr MatrixTransform, adder raster.Adder) *MatrixTransformAdder {
+ return &MatrixTransformAdder{tr, adder}
+}
+
+// Start starts a new curve at the given point.
+func (mta MatrixTransformAdder) Start(a raster.Point) {
+ mta.tr.TransformRasterPoint(&a)
+ mta.next.Start(a)
+}
+
+// Add1 adds a linear segment to the current curve.
+func (mta MatrixTransformAdder) Add1(b raster.Point) {
+ mta.tr.TransformRasterPoint(&b)
+ mta.next.Add1(b)
+}
+
+// Add2 adds a quadratic segment to the current curve.
+func (mta MatrixTransformAdder) Add2(b, c raster.Point) {
+ mta.tr.TransformRasterPoint(&b, &c)
+ mta.next.Add2(b, c)
+}
+
+// Add3 adds a cubic segment to the current curve.
+func (mta MatrixTransformAdder) Add3(b, c, d raster.Point) {
+ mta.tr.TransformRasterPoint(&b, &c, &d)
+ mta.next.Add3(b, c, d)
+}