|
1 | 1 | package phase5
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "slices" |
| 5 | + |
4 | 6 | "github.com/nulab/autog/internal/geom"
|
5 | 7 | "github.com/nulab/autog/internal/graph"
|
| 8 | + imonitor "github.com/nulab/autog/internal/monitor" |
6 | 9 | )
|
7 | 10 |
|
8 |
| -// todo: work in progress |
9 |
| -func execSplines(g *graph.DGraph, params graph.Params) { |
10 |
| - for _, e := range g.Edges { |
11 |
| - rects := []geom.Rect{ |
12 |
| - // todo: build rects |
13 |
| - } |
| 11 | +func execSplines(g *graph.DGraph, routes []routableEdge) { |
| 12 | + for _, e := range routes { |
| 13 | + imonitor.Log("spline", e) |
14 | 14 |
|
15 |
| - poly := geom.MergeRects(rects) |
| 15 | + rects := buildRects(g, e) |
| 16 | + |
| 17 | + for _, r := range rects { |
| 18 | + imonitor.Log("rect", r) |
| 19 | + } |
16 | 20 |
|
17 | 21 | start := geom.P{e.From.X + e.From.W/2, e.From.Y + e.From.H}
|
18 | 22 | end := geom.P{e.To.X + e.To.W/2, e.To.Y}
|
19 | 23 |
|
| 24 | + imonitor.Log("shortest-start", start) |
| 25 | + imonitor.Log("shortest-end", end) |
| 26 | + for _, n := range e.ns { |
| 27 | + imonitor.Log("route-node", n) |
| 28 | + } |
| 29 | + |
20 | 30 | path := geom.Shortest(start, end, rects)
|
| 31 | + |
| 32 | + poly := geom.MergeRects(rects) |
21 | 33 | ctrls := geom.FitSpline(path, geom.P{}, geom.P{}, poly.Sides())
|
22 |
| - _ = ctrls |
| 34 | + slices.Reverse(ctrls) |
| 35 | + |
| 36 | + e.Points = make([][2]float64, 0, len(ctrls)*4) |
| 37 | + for _, c := range ctrls { |
| 38 | + s := c.Float64Slice() |
| 39 | + e.Points = append(e.Points, [][2]float64{s[3], s[2], s[1], s[0]}...) |
| 40 | + } |
| 41 | + } |
| 42 | +} |
| 43 | + |
| 44 | +func buildRects(g *graph.DGraph, r routableEdge) (rects []geom.Rect) { |
| 45 | + for i := 1; i < len(r.ns); i++ { |
| 46 | + top, btm := r.ns[i-1], r.ns[i] |
| 47 | + switch { |
| 48 | + |
| 49 | + case !top.IsVirtual && !btm.IsVirtual: |
| 50 | + // add one rectangle that spans from the leftmost point to the rightmost point of the two nodes |
| 51 | + r := geom.Rect{ |
| 52 | + TL: geom.P{min(top.X, btm.X), top.Y + top.H}, |
| 53 | + BR: geom.P{max(top.X+top.W, btm.X+btm.W), btm.Y}, |
| 54 | + } |
| 55 | + rects = append(rects, r) |
| 56 | + |
| 57 | + case btm.IsVirtual: |
| 58 | + // add one rectangle that spans the entire space between the top and bottom layers |
| 59 | + // and one that spans the space around the virtual node |
| 60 | + tl := g.Layers[top.Layer] |
| 61 | + bl := g.Layers[btm.Layer] |
| 62 | + rects = append(rects, rectBetweenLayers(tl, bl)) |
| 63 | + rects = append(rects, rectVirtualNode(btm, bl)) |
| 64 | + |
| 65 | + case top.IsVirtual: |
| 66 | + tl := g.Layers[top.Layer] |
| 67 | + bl := g.Layers[btm.Layer] |
| 68 | + rects = append(rects, rectBetweenLayers(tl, bl)) |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + return |
| 73 | +} |
| 74 | + |
| 75 | +func rectBetweenLayers(l1, l2 *graph.Layer) geom.Rect { |
| 76 | + h := l1.Head() |
| 77 | + t := l2.Tail() |
| 78 | + return geom.Rect{ |
| 79 | + TL: geom.P{h.X, h.Y + h.H}, |
| 80 | + BR: geom.P{t.X + t.W, t.Y}, |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +func rectVirtualNode(vn *graph.Node, vl *graph.Layer) geom.Rect { |
| 85 | + switch p := vn.LayerPos; { |
| 86 | + case p == 0: |
| 87 | + // this p+1 access is safe: a layer cannot contain only one virtual node |
| 88 | + n := vl.Nodes[p+1] |
| 89 | + return geom.Rect{ |
| 90 | + TL: geom.P{vn.X - 10, n.Y}, |
| 91 | + BR: geom.P{n.X, n.Y + n.H}, |
| 92 | + } |
| 93 | + |
| 94 | + case p == vl.Len()-1: |
| 95 | + // this p-1 access is safe: a layer cannot contain only one virtual node |
| 96 | + n := vl.Nodes[p-1] |
| 97 | + return geom.Rect{ |
| 98 | + TL: geom.P{n.X + n.W, n.Y}, |
| 99 | + BR: geom.P{vn.X + 10, n.Y + n.H}, |
| 100 | + } |
| 101 | + |
| 102 | + default: |
| 103 | + n1 := vl.Nodes[p-1] |
| 104 | + n2 := vl.Nodes[p+1] |
| 105 | + return rectBetweenNodes(n1, n2) |
| 106 | + } |
| 107 | +} |
| 108 | + |
| 109 | +func rectBetweenNodes(n1, n2 *graph.Node) geom.Rect { |
| 110 | + d := n2.X - (n1.X + n1.W) |
| 111 | + return geom.Rect{ |
| 112 | + TL: geom.P{n1.X + n1.W + d/3, n1.Y}, |
| 113 | + BR: geom.P{n2.X - d/3, n2.Y + n2.H}, |
23 | 114 | }
|
24 | 115 | }
|
0 commit comments