gim: make outgoing edges also be split along the rectangle

This commit is contained in:
Brian Picciano 2018-03-04 14:35:01 +00:00
parent 905b182467
commit faf41c7386
4 changed files with 53 additions and 52 deletions

View File

@ -41,6 +41,24 @@ func abs(i int) int {
return i
}
// Abs returns the XY with all fields made positive, if they weren't already
func (xy XY) Abs() XY {
return XY{abs(xy[0]), abs(xy[1])}
}
// Unit returns the XY with each field divided by its absolute value (i.e.
// scaled down to 1 or -1). Fields which are 0 are left alone
func (xy XY) Unit() XY {
for i := range xy {
if xy[i] > 0 {
xy[i] = 1
} else if xy[i] < 0 {
xy[i] = -1
}
}
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 {

View File

@ -40,59 +40,25 @@ var arrows = map[geo.XY]string{
}
type line struct {
from, to *box
toI int
from, to *box
fromI, toI int
}
// given the "primary" direction the line should be headed, picks a possible
// secondary one which may be used to detour along the path in order to reach
// the destination (in the case that the two boxes are diagonal from each other)
func (l line) secondaryDir(primary geo.XY) geo.XY {
fromRect, toRect := l.from.rect(), l.to.rect()
rels := make([]int, len(geo.Units))
for i, dir := range geo.Units {
rels[i] = toRect.EdgeCoord(dir.Inv()) - fromRect.EdgeCoord(dir)
if dir == geo.Up || dir == geo.Left {
rels[i] *= -1
}
}
var secondary geo.XY
var secondaryMax int
var secondarySet bool
for i, rel := range rels {
if geo.Units[i] == primary {
continue
} else if geo.Units[i][0] == 0 && primary[0] == 0 {
continue
} else if geo.Units[i][1] == 0 && primary[1] == 0 {
continue
} else if !secondarySet || rel > secondaryMax {
secondary = geo.Units[i]
secondaryMax = rel
secondarySet = true
}
}
return secondary
func secondaryDir(flowDir, start, end geo.XY) geo.XY {
var perpDir geo.XY
perpDir[0], perpDir[1] = flowDir[1], flowDir[0]
return end.Sub(start).Mul(perpDir.Abs()).Unit()
}
//func (l line) startEnd(flowDir, secFlowDir geo.XY) (geo.XY, geo.XY) {
// from, to := *(l.from), *(l.to)
// start := from.rect().EdgeMidpoint(flowDir, rounder) // ezpz
//}
func (l line) draw(term *terminal.Terminal, flowDir, secFlowDir geo.XY) {
from, to := *(l.from), *(l.to)
dirSec := l.secondaryDir(flowDir)
flowDirInv := flowDir.Inv()
start := from.rect().Edge(flowDir, secFlowDir).Midpoint(rounder)
endSlot := l.toI*2 + 1
endSlotXY := geo.XY{endSlot, endSlot}
end := to.rect().Edge(flowDirInv, secFlowDir)[0].Add(secFlowDir.Mul(endSlotXY))
start := from.rect().Edge(flowDir, secFlowDir)[0].Add(secFlowDir.Scale(l.fromI*2 + 1))
end := to.rect().Edge(flowDir.Inv(), secFlowDir)[0].Add(secFlowDir.Scale(l.toI*2 + 1))
dirSec := secondaryDir(flowDir, start, end)
mid := start.Midpoint(end, rounder)
along := func(xy, dir geo.XY) int {

View File

@ -17,7 +17,7 @@ import (
// - Absolute positioning of some/all vertices
// TODO
// - assign edges to "slots" on boxes
// - in current example, order of edges leaving "a" is fucked
// - edge values
// - be able to draw circular graphs
// - audit all steps, make sure everything is deterministic
@ -76,8 +76,8 @@ func mkGraph() (*gg.Graph, gg.Value) {
func main() {
rand.Seed(time.Now().UnixNano())
term := terminal.New()
term.Reset()
term.HideCursor()
//term.Reset()
//term.HideCursor()
g, start := mkGraph()
v := view{
@ -88,9 +88,10 @@ func main() {
center: geo.Zero.Midpoint(term.WindowSize(), rounder),
}
for range time.Tick(frameperiod) {
term.Reset()
v.draw(term)
term.Flush()
}
//for range time.Tick(frameperiod) {
term.Reset()
v.draw(term)
term.Flush()
//}
time.Sleep(1 * time.Hour)
}

View File

@ -146,13 +146,29 @@ func (view *view) draw(term *terminal.Terminal) {
primPos += maxPrim + primPadding
}
// returns the index of this edge in from's Out
// TODO this might not be deterministic? Out is never ordered technically
findFromI := func(from *gg.Vertex, e gg.Edge) int {
for i, fe := range from.Out {
if fe == e {
return i
}
}
panic("edge not found in from.Out")
}
// create lines
var lines []line
for _, b := range boxes {
v := boxesM[b]
for i, e := range v.In {
bFrom := boxesMr[e.From]
lines = append(lines, line{from: bFrom, to: b, toI: i})
lines = append(lines, line{
from: bFrom,
fromI: findFromI(e.From, e),
to: b,
toI: i,
})
}
}