clean Transform

This commit is contained in:
Laurent Le Goff 2015-04-29 16:19:49 +02:00
parent 966a9b73f7
commit 511954196b
2 changed files with 39 additions and 78 deletions

View file

@ -107,8 +107,7 @@ func cubic(offset, v0, v1, v2, v3 float64) uint32 {
func DrawImage(src image.Image, dest draw.Image, tr draw2d.MatrixTransform, op draw.Op, filter ImageFilter) { func DrawImage(src image.Image, dest draw.Image, tr draw2d.MatrixTransform, op draw.Op, filter ImageFilter) {
bounds := src.Bounds() bounds := src.Bounds()
x0, y0, x1, y1 := float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Max.X), float64(bounds.Max.Y) x0, y0, x1, y1 := tr.TransformRectangle(float64(bounds.Min.X), float64(bounds.Min.Y), float64(bounds.Max.X), float64(bounds.Max.Y))
tr.TransformRectangle(&x0, &y0, &x1, &y1)
var x, y, u, v float64 var x, y, u, v float64
var c1, c2, cr color.Color var c1, c2, cr color.Color
var r, g, b, a, ia, r1, g1, b1, a1, r2, g2, b2, a2 uint32 var r, g, b, a, ia, r1, g1, b1, a1, r2, g2, b2, a2 uint32
@ -117,7 +116,7 @@ func DrawImage(src image.Image, dest draw.Image, tr draw2d.MatrixTransform, op d
for y = y0; y < y1; y++ { for y = y0; y < y1; y++ {
u = x u = x
v = y v = y
tr.InverseTransform(&u, &v) u, v = tr.InverseTransformPoint(u, v)
if bounds.Min.X <= int(u) && bounds.Max.X > int(u) && bounds.Min.Y <= int(v) && bounds.Max.Y > int(v) { if bounds.Min.X <= int(u) && bounds.Max.X > int(u) && bounds.Min.Y <= int(v) && bounds.Max.Y > int(v) {
c1 = dest.At(int(x), int(y)) c1 = dest.At(int(x), int(y))
switch filter { switch filter {

View file

@ -5,8 +5,6 @@ package draw2d
import ( import (
"math" "math"
"code.google.com/p/freetype-go/freetype/raster"
) )
type MatrixTransform [6]float64 type MatrixTransform [6]float64
@ -19,16 +17,8 @@ func (tr MatrixTransform) Determinant() float64 {
return tr[0]*tr[3] - tr[1]*tr[2] return tr[0]*tr[3] - tr[1]*tr[2]
} }
func (tr MatrixTransform) Transform(points ...*float64) { // Transform apply the Affine Matrix to points. It modify the points passed in parameter.
for i, j := 0, 1; j < len(points); i, j = i+2, j+2 { func (tr MatrixTransform) Transform(points []float64) {
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 { for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
x := points[i] x := points[i]
y := points[j] y := points[j]
@ -37,6 +27,12 @@ func (tr MatrixTransform) TransformArray(points []float64) {
} }
} }
func (tr MatrixTransform) 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) { func minMax(x, y float64) (min, max float64) {
if x > y { if x > y {
return y, x return y, x
@ -44,50 +40,46 @@ func minMax(x, y float64) (min, max float64) {
return x, y return x, y
} }
func (tr MatrixTransform) TransformRectangle(x0, y0, x2, y2 *float64) { func (tr MatrixTransform) TransformRectangle(x0, y0, x2, y2 float64) (nx0, ny0, nx2, ny2 float64) {
x1 := *x2 points := []float64{x0, y0, x2, y0, x2, y2, x0, y2}
y1 := *y0 tr.Transform(points)
x3 := *x0 points[0], points[2] = minMax(points[0], points[2])
y3 := *y2 points[4], points[6] = minMax(points[4], points[6])
tr.Transform(x0, y0, &x1, &y1, x2, y2, &x3, &y3) points[1], points[3] = minMax(points[1], points[3])
*x0, x1 = minMax(*x0, x1) points[5], points[7] = minMax(points[5], points[7])
*x2, x3 = minMax(*x2, x3)
*y0, y1 = minMax(*y0, y1)
*y2, y3 = minMax(*y2, y3)
*x0 = math.Min(*x0, *x2) nx0 = math.Min(points[0], points[4])
*y0 = math.Min(*y0, *y2) ny0 = math.Min(points[1], points[5])
*x2 = math.Max(x1, x3) nx2 = math.Max(points[2], points[6])
*y2 = math.Max(y1, y3) ny2 = math.Max(points[3], points[7])
return nx0, ny0, nx2, ny2
} }
func (tr MatrixTransform) TransformRasterPoint(points ...*raster.Point) { func (tr MatrixTransform) InverseTransform(points []float64) {
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 d := tr.Determinant() // matrix determinant
for i, j := 0, 1; j < len(points); i, j = i+2, j+2 { for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
x := *points[i] x := points[i]
y := *points[j] y := points[j]
*points[i] = ((x-tr[4])*tr[3] - (y-tr[5])*tr[2]) / d 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 points[j] = ((y-tr[5])*tr[0] - (x-tr[4])*tr[1]) / d
} }
} }
func (tr MatrixTransform) InverseTransformPoint(x, y float64) (xres, yres float64) {
d := tr.Determinant() // matrix 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
}
// ******************** Vector transformations ******************** // ******************** Vector transformations ********************
func (tr MatrixTransform) VectorTransform(points ...*float64) { func (tr MatrixTransform) VectorTransform(points []float64) {
for i, j := 0, 1; j < len(points); i, j = i+2, j+2 { for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
x := *points[i] x := points[i]
y := *points[j] y := points[j]
*points[i] = x*tr[0] + y*tr[2] points[i] = x*tr[0] + y*tr[2]
*points[j] = x*tr[1] + y*tr[3] points[j] = x*tr[1] + y*tr[3]
} }
} }
@ -287,33 +279,3 @@ func (t Transformer) Close() {
func (t Transformer) End() { func (t Transformer) End() {
t.Flattener.End() t.Flattener.End()
} }
// this adder apply a Matrix transformation to points
type MatrixTransformAdder struct {
tr MatrixTransform
next raster.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)
}