/
paths.go
66 lines (58 loc) · 1.47 KB
/
paths.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Package paths provides tools for manipulating 2d paths consisting
// of line segments.
package paths
// Vec2 is a 2-dimensional vector.
type Vec2 [2]float64
// A Path is a contiguous series of line segments, from the
// first point in the V slice to the last.
type Path struct {
V []Vec2
}
// Bounds describes an axis-aligned bounding box.
type Bounds struct {
Min, Max Vec2
}
// Paths is a set of paths, along with a view bounds.
type Paths struct {
Bounds Bounds
P []Path
}
// Transform resizes all paths so that the rectangle forming the
// current bounds is the size of the new bounds. The bounds
// are also updated to the new bounds.
func (ps *Paths) Transform(nb Bounds) {
ob := ps.Bounds
for _, p := range ps.P {
for i, v := range p.V {
x, y := v[0], v[1]
x -= ob.Min[0]
x /= ob.Max[0] - ob.Min[0]
x *= nb.Max[0] - nb.Min[0]
x += nb.Min[0]
y -= ob.Min[1]
y /= ob.Max[1] - ob.Min[1]
y *= nb.Max[1] - nb.Min[1]
y += nb.Min[1]
p.V[i] = [2]float64{x, y}
}
}
ps.Bounds = nb
}
// move adds a new (initially empty) path starting at x,
// unless the last path already ends at x.
func (ps *Paths) move(x Vec2) {
if len(ps.P) == 0 {
ps.P = append(ps.P, Path{V: []Vec2{x}})
return
}
p := &ps.P[len(ps.P)-1]
if len(p.V) > 0 && p.V[len(p.V)-1] == x {
return
}
ps.P = append(ps.P, Path{V: []Vec2{x}})
}
// line extends the last path with an edge that goes to x.
func (ps *Paths) line(x Vec2) {
p := &ps.P[len(ps.P)-1]
p.V = append(p.V, x)
}