diff --git a/gim/box.go b/gim/box.go index af9d181..5dfaf89 100644 --- a/gim/box.go +++ b/gim/box.go @@ -63,8 +63,8 @@ func (b box) draw(buf *terminal.Buffer) { buf.DrawRect(rect, terminal.SingleLine) if b.bodyBuf != nil { - center := rect.Center(rounder) + center := rect.Center() bodyBufRect := geo.Rect{Size: b.bodyBuf.Size()} - buf.DrawBuffer(bodyBufRect.Centered(center, rounder).TopLeft, b.bodyBuf) + buf.DrawBuffer(bodyBufRect.Centered(center).TopLeft, b.bodyBuf) } } diff --git a/gim/geo/geo.go b/gim/geo/geo.go index a93256b..44900d4 100644 --- a/gim/geo/geo.go +++ b/gim/geo/geo.go @@ -59,9 +59,8 @@ func (xy XY) Unit() XY { return xy } -// Len returns the length (aka magnitude) of the XY as a vector, using the -// Rounder to round to an int -func (xy XY) Len(r Rounder) int { +// Len returns the length (aka magnitude) of the XY as a vector. +func (xy XY) Len() int { if xy[0] == 0 { return abs(xy[1]) } else if xy[1] == 0 { @@ -70,7 +69,7 @@ func (xy XY) Len(r Rounder) int { xyf := xy.toF64() lf := math.Sqrt((xyf[0] * xyf[0]) + (xyf[1] * xyf[1])) - return r.Round(lf) + return Rounder.Round(lf) } // Add returns the result of adding the two XYs' fields individually @@ -87,13 +86,12 @@ func (xy XY) Mul(xy2 XY) XY { return xy } -// Div returns the results of dividing the two XYs' field individually, using -// the Rounder to resolve floating results -func (xy XY) Div(xy2 XY, r Rounder) XY { +// Div returns the results of dividing the two XYs' field individually. +func (xy XY) Div(xy2 XY) XY { xyf, xy2f := xy.toF64(), xy2.toF64() return XY{ - r.Round(xyf[0] / xy2f[0]), - r.Round(xyf[1] / xy2f[1]), + Rounder.Round(xyf[0] / xy2f[0]), + Rounder.Round(xyf[1] / xy2f[1]), } } @@ -113,10 +111,9 @@ func (xy XY) Sub(xy2 XY) XY { return xy.Add(xy2.Inv()) } -// Midpoint returns the midpoint between the two XYs. The rounder indicates what -// to do about non-whole values when they're come across -func (xy XY) Midpoint(xy2 XY, r Rounder) XY { - return xy.Add(xy2.Sub(xy).Div(XY{2, 2}, r)) +// Midpoint returns the midpoint between the two XYs. +func (xy XY) Midpoint(xy2 XY) XY { + return xy.Add(xy2.Sub(xy).Div(XY{2, 2})) } // Min returns an XY whose fields are the minimum values of the two XYs' diff --git a/gim/geo/rect.go b/gim/geo/rect.go index a38f72b..a0d3391 100644 --- a/gim/geo/rect.go +++ b/gim/geo/rect.go @@ -82,32 +82,30 @@ func (r Rect) Edge(dir, secDir XY) Edge { } // Midpoint returns the point which is the midpoint of the Edge -func (e Edge) Midpoint(rounder Rounder) XY { - return e[0].Midpoint(e[1], rounder) +func (e Edge) Midpoint() XY { + return e[0].Midpoint(e[1]) } -func (r Rect) halfSize(rounder Rounder) XY { - return r.Size.Div(XY{2, 2}, rounder) +func (r Rect) halfSize() XY { + return r.Size.Div(XY{2, 2}) } -// Center returns the centerpoint of the rectangle, using the given Rounder to -// resolve non-integers -func (r Rect) Center(rounder Rounder) XY { - return r.TopLeft.Add(r.halfSize(rounder)) +// Center returns the centerpoint of the rectangle. +func (r Rect) Center() XY { + return r.TopLeft.Add(r.halfSize()) } // Translate returns an instance of Rect which is the same as this one but -// translated by the given amount +// translated by the given amount. func (r Rect) Translate(by XY) Rect { r.TopLeft = r.TopLeft.Add(by) return r } // Centered returns an instance of Rect which is this one but translated to be -// centered on the given point. It will use the given Rounder to resolve -// non-integers -func (r Rect) Centered(on XY, rounder Rounder) Rect { - r.TopLeft = on.Sub(r.halfSize(rounder)) +// centered on the given point. +func (r Rect) Centered(on XY) Rect { + r.TopLeft = on.Sub(r.halfSize()) return r } diff --git a/gim/geo/rect_test.go b/gim/geo/rect_test.go index d7301bf..80b2274 100644 --- a/gim/geo/rect_test.go +++ b/gim/geo/rect_test.go @@ -38,30 +38,20 @@ func TestRect(t *T) { } func TestRectCenter(t *T) { - assertCentered := func(exp, given Rect, center XY, rounder Rounder) { - got := given.Centered(center, rounder) + assertCentered := func(exp, given Rect, center XY) { + got := given.Centered(center) assert.Equal(t, exp, got) - assert.Equal(t, center, got.Center(rounder)) + assert.Equal(t, center, got.Center()) } { r := Rect{ Size: XY{4, 4}, } - assert.Equal(t, XY{2, 2}, r.Center(Round)) - assert.Equal(t, XY{2, 2}, r.Center(Floor)) - assert.Equal(t, XY{2, 2}, r.Center(Ceil)) + assert.Equal(t, XY{2, 2}, r.Center()) assertCentered( Rect{TopLeft: XY{1, 1}, Size: XY{4, 4}}, - r, XY{3, 3}, Round, - ) - assertCentered( - Rect{TopLeft: XY{1, 1}, Size: XY{4, 4}}, - r, XY{3, 3}, Floor, - ) - assertCentered( - Rect{TopLeft: XY{1, 1}, Size: XY{4, 4}}, - r, XY{3, 3}, Ceil, + r, XY{3, 3}, ) } @@ -69,20 +59,10 @@ func TestRectCenter(t *T) { r := Rect{ Size: XY{5, 5}, } - assert.Equal(t, XY{3, 3}, r.Center(Round)) - assert.Equal(t, XY{2, 2}, r.Center(Floor)) - assert.Equal(t, XY{3, 3}, r.Center(Ceil)) + assert.Equal(t, XY{3, 3}, r.Center()) assertCentered( Rect{TopLeft: XY{0, 0}, Size: XY{5, 5}}, - r, XY{3, 3}, Round, - ) - assertCentered( - Rect{TopLeft: XY{1, 1}, Size: XY{5, 5}}, - r, XY{3, 3}, Floor, - ) - assertCentered( - Rect{TopLeft: XY{0, 0}, Size: XY{5, 5}}, - r, XY{3, 3}, Ceil, + r, XY{3, 3}, ) } } diff --git a/gim/geo/round.go b/gim/geo/round.go index 822a4e2..b869831 100644 --- a/gim/geo/round.go +++ b/gim/geo/round.go @@ -1,44 +1,33 @@ package geo import ( - "fmt" "math" ) -// Rounder describes how a floating point number should be converted to an int -type Rounder int +// RounderFunc is a function which converts a floating point number into an +// integer. +type RounderFunc func(float64) int64 -const ( - // Round will round up or down depending on the number itself - Round Rounder = iota +// Round is helper for calling the RounderFunc and converting the result to an +// int. +func (rf RounderFunc) Round(f float64) int { + return int(rf(f)) +} - // Floor will use the math.Floor function - Floor - - // Ceil will use the math.Ceil function - Ceil -) - -// Round64 converts a float to an in64 based on the rounding function indicated -// by the Rounder's value -func (r Rounder) Round64(f float64) int64 { - switch r { - case Round: +// A few RounderFuncs which can be used. Set the Rounder global variable to pick +// one. +var ( + Floor RounderFunc = func(f float64) int64 { return int64(math.Floor(f)) } + Ceil RounderFunc = func(f float64) int64 { return int64(math.Ceil(f)) } + Round RounderFunc = func(f float64) int64 { if f < 0 { f = math.Ceil(f - 0.5) } f = math.Floor(f + 0.5) - case Floor: - f = math.Floor(f) - case Ceil: - f = math.Ceil(f) - default: - panic(fmt.Sprintf("invalid Rounder: %#v", r)) + return int64(f) } - return int64(f) -} +) -// Round is like Round64 but convers the int64 to an int -func (r Rounder) Round(f float64) int { - return int(r.Round64(f)) -} +// Rounder is the RounderFunc which will be used by all functions and methods in +// this package when needed. +var Rounder = Ceil diff --git a/gim/line.go b/gim/line.go index ebcf8e1..cb6c9ec 100644 --- a/gim/line.go +++ b/gim/line.go @@ -26,8 +26,8 @@ func (l line) draw(buf *terminal.Buffer, flowDir, secFlowDir geo.XY) { // draw the body if l.bodyBuf != nil { - mid := start.Midpoint(end, rounder) + mid := start.Midpoint(end) bodyBufRect := geo.Rect{Size: l.bodyBuf.Size()} - buf.DrawBuffer(bodyBufRect.Centered(mid, rounder).TopLeft, l.bodyBuf) + buf.DrawBuffer(bodyBufRect.Centered(mid).TopLeft, l.bodyBuf) } } diff --git a/gim/main.go b/gim/main.go index c2ac47d..2c37487 100644 --- a/gim/main.go +++ b/gim/main.go @@ -23,7 +23,6 @@ import ( const ( framerate = 10 frameperiod = time.Second / time.Duration(framerate) - rounder = geo.Ceil ) func debugf(str string, args ...interface{}) { @@ -81,7 +80,7 @@ func main() { rand.Seed(time.Now().UnixNano()) term := terminal.New() wSize := term.WindowSize() - center := geo.Zero.Midpoint(wSize, rounder) + center := geo.Zero.Midpoint(wSize) g, start := mkGraph() v := view{ @@ -93,7 +92,7 @@ func main() { buf := terminal.NewBuffer() v.draw(buf) - bufRect := geo.Rect{Size: buf.Size()}.Centered(center, rounder) + bufRect := geo.Rect{Size: buf.Size()}.Centered(center) term.Clear() term.WriteBuffer(bufRect.TopLeft, buf) diff --git a/gim/terminal/shape.go b/gim/terminal/shape.go index a2fcd85..3bbfb88 100644 --- a/gim/terminal/shape.go +++ b/gim/terminal/shape.go @@ -144,10 +144,7 @@ func (b *Buffer) DrawLine(start, end, dir geo.XY, ls LineStyle) { var perpDir geo.XY perpDir[0], perpDir[1] = dir[1], dir[0] dirSec := end.Sub(start).Mul(perpDir.Abs()).Unit() - - // TODO gross that this doesn't have some way of discovering the rounder. - // Maybe rounder should just be a global? ugh... - mid := start.Midpoint(end, geo.Round) + mid := start.Midpoint(end) along := func(xy, dir geo.XY) int { if dir[0] != 0 { diff --git a/gim/view.go b/gim/view.go index ca869cf..07548de 100644 --- a/gim/view.go +++ b/gim/view.go @@ -120,8 +120,8 @@ func (view *view) draw(buf *terminal.Buffer) { boxesMr[v] = &b bSize := b.rect().Size - primBoxLen := bSize.Mul(view.primFlowDir).Len(rounder) - secBoxLen := bSize.Mul(view.secFlowDir).Len(rounder) + primBoxLen := bSize.Mul(view.primFlowDir).Len() + secBoxLen := bSize.Mul(view.secFlowDir).Len() if primBoxLen > maxPrim { maxPrim = primBoxLen }