From faf41c738600a0f864836684ce6eb10830505aff Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Sun, 4 Mar 2018 14:35:01 +0000 Subject: [PATCH] gim: make outgoing edges also be split along the rectangle --- gim/geo/geo.go | 18 +++++++++++++++++ gim/line.go | 52 +++++++++----------------------------------------- gim/main.go | 17 +++++++++-------- gim/view.go | 18 ++++++++++++++++- 4 files changed, 53 insertions(+), 52 deletions(-) diff --git a/gim/geo/geo.go b/gim/geo/geo.go index 1935e59..a93256b 100644 --- a/gim/geo/geo.go +++ b/gim/geo/geo.go @@ -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 { diff --git a/gim/line.go b/gim/line.go index 8f241c1..ce38938 100644 --- a/gim/line.go +++ b/gim/line.go @@ -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 { diff --git a/gim/main.go b/gim/main.go index 9a1698a..f435f61 100644 --- a/gim/main.go +++ b/gim/main.go @@ -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) } diff --git a/gim/view.go b/gim/view.go index 41948ae..8ab9ee3 100644 --- a/gim/view.go +++ b/gim/view.go @@ -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, + }) } }