gim: make rounder a global in geo, kinda gross but simplifies a lot of things
This commit is contained in:
parent
ef48a2d708
commit
0b36e4ec37
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user