gim: make outgoing edges also be split along the rectangle
This commit is contained in:
parent
905b182467
commit
faf41c7386
@ -41,6 +41,24 @@ func abs(i int) int {
|
|||||||
return i
|
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
|
// Len returns the length (aka magnitude) of the XY as a vector, using the
|
||||||
// Rounder to round to an int
|
// Rounder to round to an int
|
||||||
func (xy XY) Len(r Rounder) int {
|
func (xy XY) Len(r Rounder) int {
|
||||||
|
50
gim/line.go
50
gim/line.go
@ -41,58 +41,24 @@ var arrows = map[geo.XY]string{
|
|||||||
|
|
||||||
type line struct {
|
type line struct {
|
||||||
from, to *box
|
from, to *box
|
||||||
toI int
|
fromI, toI int
|
||||||
}
|
}
|
||||||
|
|
||||||
// given the "primary" direction the line should be headed, picks a possible
|
// 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
|
// 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)
|
// the destination (in the case that the two boxes are diagonal from each other)
|
||||||
func (l line) secondaryDir(primary geo.XY) geo.XY {
|
func secondaryDir(flowDir, start, end geo.XY) geo.XY {
|
||||||
fromRect, toRect := l.from.rect(), l.to.rect()
|
var perpDir geo.XY
|
||||||
rels := make([]int, len(geo.Units))
|
perpDir[0], perpDir[1] = flowDir[1], flowDir[0]
|
||||||
for i, dir := range geo.Units {
|
return end.Sub(start).Mul(perpDir.Abs()).Unit()
|
||||||
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 (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) {
|
func (l line) draw(term *terminal.Terminal, flowDir, secFlowDir geo.XY) {
|
||||||
from, to := *(l.from), *(l.to)
|
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)
|
mid := start.Midpoint(end, rounder)
|
||||||
|
|
||||||
along := func(xy, dir geo.XY) int {
|
along := func(xy, dir geo.XY) int {
|
||||||
|
11
gim/main.go
11
gim/main.go
@ -17,7 +17,7 @@ import (
|
|||||||
// - Absolute positioning of some/all vertices
|
// - Absolute positioning of some/all vertices
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// - assign edges to "slots" on boxes
|
// - in current example, order of edges leaving "a" is fucked
|
||||||
// - edge values
|
// - edge values
|
||||||
// - be able to draw circular graphs
|
// - be able to draw circular graphs
|
||||||
// - audit all steps, make sure everything is deterministic
|
// - audit all steps, make sure everything is deterministic
|
||||||
@ -76,8 +76,8 @@ func mkGraph() (*gg.Graph, gg.Value) {
|
|||||||
func main() {
|
func main() {
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
term := terminal.New()
|
term := terminal.New()
|
||||||
term.Reset()
|
//term.Reset()
|
||||||
term.HideCursor()
|
//term.HideCursor()
|
||||||
|
|
||||||
g, start := mkGraph()
|
g, start := mkGraph()
|
||||||
v := view{
|
v := view{
|
||||||
@ -88,9 +88,10 @@ func main() {
|
|||||||
center: geo.Zero.Midpoint(term.WindowSize(), rounder),
|
center: geo.Zero.Midpoint(term.WindowSize(), rounder),
|
||||||
}
|
}
|
||||||
|
|
||||||
for range time.Tick(frameperiod) {
|
//for range time.Tick(frameperiod) {
|
||||||
term.Reset()
|
term.Reset()
|
||||||
v.draw(term)
|
v.draw(term)
|
||||||
term.Flush()
|
term.Flush()
|
||||||
}
|
//}
|
||||||
|
time.Sleep(1 * time.Hour)
|
||||||
}
|
}
|
||||||
|
18
gim/view.go
18
gim/view.go
@ -146,13 +146,29 @@ func (view *view) draw(term *terminal.Terminal) {
|
|||||||
primPos += maxPrim + primPadding
|
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
|
// create lines
|
||||||
var lines []line
|
var lines []line
|
||||||
for _, b := range boxes {
|
for _, b := range boxes {
|
||||||
v := boxesM[b]
|
v := boxesM[b]
|
||||||
for i, e := range v.In {
|
for i, e := range v.In {
|
||||||
bFrom := boxesMr[e.From]
|
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,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user