-
-
Notifications
You must be signed in to change notification settings - Fork 103
/
path_stroke_test.go
117 lines (102 loc) · 6.33 KB
/
path_stroke_test.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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package canvas
import (
"fmt"
"math"
"testing"
"github.com/tdewolff/test"
)
func TestPathStroke(t *testing.T) {
tolerance := 1.0
var tts = []struct {
orig string
w float64
cp Capper
jr Joiner
stroke string
}{
{"M10 10", 2.0, RoundCap, RoundJoin, ""},
{"M10 10z", 2.0, RoundCap, RoundJoin, ""},
//{"M10 10L10 5", 2.0, RoundCap, RoundJoin, "M9 5A1 1 0 0 1 11 5L11 10A1 1 0 0 1 9 10z"},
{"M10 10L10 5", 2.0, ButtCap, RoundJoin, "M9 5L11 5L11 10L9 10z"},
{"M10 10L10 5", 2.0, SquareCap, RoundJoin, "M9 4L11 4L11 5L11 10L11 11L9 11z"},
{"L10 0L20 0", 2.0, ButtCap, RoundJoin, "M0 -1L10 -1L20 -1L20 1L10 1L0 1z"},
//{"L10 0L10 10", 2.0, ButtCap, RoundJoin, "M9 1L0 1L0 -1L10 -1A1 1 0 0 1 11 0L11 10L9 10z"},
//{"L10 0L10 -10", 2.0, ButtCap, RoundJoin, "M9 -1L9 -10L11 -10L11 0A1 1 0 0 1 10 1L0 1L0 -1z"},
{"L10 0L20 0", 2.0, ButtCap, BevelJoin, "M0 -1L10 -1L20 -1L20 1L10 1L0 1z"},
{"L10 0L10 10", 2.0, ButtCap, BevelJoin, "M0 -1L10 -1L11 0L11 10L9 10L9 1L0 1z"},
{"L10 0L10 -10", 2.0, ButtCap, BevelJoin, "M0 -1L9 -1L9 -10L11 -10L11 0L10 1L0 1z"},
{"L10 0L20 0", 2.0, ButtCap, MiterJoiner{BevelJoin, 2.0}, "M0 -1L10 -1L20 -1L20 1L10 1L0 1z"},
{"L10 0L5 0", 2.0, ButtCap, MiterJoiner{BevelJoin, 2.0}, "M0 -1L10 -1L10 1L0 1z"},
{"L10 0L10 10", 2.0, ButtCap, MiterJoiner{BevelJoin, 1.0}, "M0 -1L10 -1L11 0L11 10L9 10L9 1L0 1z"},
{"L10 0L10 10", 2.0, ButtCap, MiterJoiner{BevelJoin, 2.0}, "M0 -1L10 -1L11 -1L11 0L11 10L9 10L9 1L0 1z"},
{"L10 0L10 -10", 2.0, ButtCap, MiterJoiner{BevelJoin, 2.0}, "M0 -1L9 -1L9 -10L11 -10L11 0L11 1L10 1L0 1z"},
{"L10 0L20 0", 2.0, ButtCap, ArcsJoiner{BevelJoin, 2.0}, "M0 -1L10 -1L20 -1L20 1L10 1L0 1z"},
{"L10 0L5 0", 2.0, ButtCap, ArcsJoiner{BevelJoin, 2.0}, "M0 -1L10 -1L10 1L0 1z"},
{"L10 0L10 10", 2.0, ButtCap, ArcsJoiner{BevelJoin, 1.0}, "M0 -1L10 -1L11 0L11 10L9 10L9 1L0 1z"},
{"L10 0L10 10L0 10z", 2.0, ButtCap, MiterJoin, "M-1 -1L11 -1L11 11L-1 11zM1 1L1 9L9 9L9 1z"},
{"L10 0L10 10L0 10z", 2.0, ButtCap, BevelJoin, "M-1 0L0 -1L10 -1L11 0L11 10L10 11L0 11L-1 10zM1 1L1 9L9 9L9 1z"},
{"L0 10L10 10L10 0z", 2.0, ButtCap, BevelJoin, "M-1 0L0 -1L10 -1L11 0L11 10L10 11L0 11L-1 10zM1 1L1 9L9 9L9 1z"},
{"Q10 0 10 10", 2.0, ButtCap, BevelJoin, "M0 -1L9.5137 3.4975L11 10L9 10L7.7845 4.5025L0 1z"},
{"C0 10 10 10 10 0", 2.0, ButtCap, BevelJoin, "M-1 0L1 0L3.5291 6.0900L7.4502 5.2589L9 0L11 0L8.9701 6.5589L2.5234 7.8188z"},
//{"A10 5 0 0 0 20 0", 2.0, ButtCap, BevelJoin, "M1 0A9 4 0 0 0 19 0L21 0A11 6 0 0 1 -1 0z"}, // TODO: enable tests for ellipses when Settle supports them
//{"A10 5 0 0 1 20 0", 2.0, ButtCap, BevelJoin, "M-1 0A11 6 0 0 1 21 0L19 0A9 4 0 0 0 1 0z"},
//{"M5 2L2 2A2 2 0 0 0 0 0", 2.0, ButtCap, BevelJoin, "M2.8284 1L5 1L5 3L2 3L1 2A1 1 0 0 0 0 1L0 -1A3 3 0 0 1 2.8284 1z"},
// two circle quadrants joining at 90 degrees
//{"A10 10 0 0 1 10 10A10 10 0 0 1 0 0z", 2.0, ButtCap, ArcsJoin, "M0 -1A11 11 0 0 1 11 10A11 11 0 0 1 10.958 10.958A11 11 0 0 1 10 11A11 11 0 0 1 -1 0A11 11 0 0 1 -0.958 -0.958A11 11 0 0 1 0 -1zM1.06230 1.06230A9 9 0 0 0 8.9370 8.9370A9 9 0 0 0 1.06230 1.0630z"},
// circles joining at one point (10,0), stroke will never join
//{"A5 5 0 0 0 10 0A10 10 0 0 1 0 10", 2.0, ButtCap, ArcsJoin, "M7 5.6569A6 6 0 0 1 -1 0L1 0A4 4 0 0 0 9 0L11 0A11 11 0 0 1 0 11L0 9A9 9 0 0 0 7 5.6569z"},
// circle and line intersecting in one point
//{"A2 2 0 0 1 2 2L5 2", 2.0, ButtCap, ArcsJoiner{BevelJoin, 10.0}, "M2.8284 1L5 1L5 3L0 3A1 1 0 0 0 1 2A1 1 0 0 0 0 1L0 -1A3 3 0 0 1 2.8284 1z"},
//{"M0 4A2 2 0 0 0 2 2L5 2", 2.0, ButtCap, ArcsJoiner{BevelJoin, 10.0}, "M2.8284 3A3 3 0 0 1 0 5L0 3A1 1 0 0 0 1 2A1 1 0 0 0 0 1L5 1L5 3z"},
//{"M5 2L2 2A2 2 0 0 0 0 0", 2.0, ButtCap, ArcsJoiner{BevelJoin, 10.0}, "M2.8284 1L5 1L5 3L0 3A1 1 0 0 0 1 2A1 1 0 0 0 0 1L0 -1A3 3 0 0 1 2.8284 1z"},
//{"M5 2L2 2A2 2 0 0 1 0 4", 2.0, ButtCap, ArcsJoiner{BevelJoin, 10.0}, "M2.8284 3A3 3 0 0 1 0 5L0 3A1 1 0 0 0 1 2A1 1 0 0 0 0 1L5 1L5 3z"},
// cut by limit
//{"A2 2 0 0 1 2 2L5 2", 2.0, ButtCap, ArcsJoiner{BevelJoin, 1.0}, "M2.8284 1L5 1L5 3L2 3L1 2A1 1 0 0 0 0 1L0 -1A3 3 0 0 1 2.8284 1z"},
// no intersection
//{"A2 2 0 0 1 2 2L5 2", 3.0, ButtCap, ArcsJoiner{BevelJoin, 10.0}, "M3.1623 0.5L5 0.5L5 3.5L2 3.5L0.5 2A0.5 0.5 0 0 0 0 1.5L0 -1.5A3.5 3.5 0 0 1 3.1623 0.5z"},
}
origEpsilon := Epsilon
for _, tt := range tts {
t.Run(tt.orig, func(t *testing.T) {
Epsilon = origEpsilon
stroke := MustParseSVGPath(tt.orig).Stroke(tt.w, tt.cp, tt.jr, tolerance)
Epsilon = 1e-3
test.T(t, stroke, MustParseSVGPath(tt.stroke))
})
}
Epsilon = origEpsilon
}
func TestPathStrokeEllipse(t *testing.T) {
rx, ry := 20.0, 10.0
nphi := 12
ntheta := 120
for iphi := 0; iphi < nphi; iphi++ {
phi := float64(iphi) / float64(nphi) * math.Pi
for itheta := 0; itheta < ntheta; itheta++ {
theta := float64(itheta) / float64(ntheta) * 2.0 * math.Pi
outer := EllipsePos(rx+1.0, ry+1.0, phi, 0.0, 0.0, theta)
inner := EllipsePos(rx-1.0, ry-1.0, phi, 0.0, 0.0, theta)
test.Float(t, outer.Sub(inner).Length(), 2.0, fmt.Sprintf("phi=%g theta=%g", phi, theta))
}
}
}
func TestPathOffset(t *testing.T) {
tolerance := 0.01
var tts = []struct {
orig string
w float64
offset string
}{
{"L10 0L10 10L0 10z", 0.0, "L10 0L10 10L0 10z"},
//{"L10 0L10 10L0 10", 1.0, "M0 -1L10 -1A1 1 0 0 1 11 0L11 10A1 1 0 0 1 10 11L0 11"},
//{"L10 0L10 10L0 10z", 1.0, "M10 -1A1 1 0 0 1 11 0L11 10A1 1 0 0 1 10 11L0 11A1 1 0 0 1 -1 10L-1 0A1 1 0 0 1 0 -1z"},
{"L10 0L10 10L0 10z", -1.0, "M1 1L9 1L9 9L1 9z"},
{"L10 0L5 0z", -1.0, "M-0.9927266539729243 -0.18099839425163974L-0.9927266539729241 0.1809983942516404L-0.8649717420129762 0.5197023318679524L-0.6259028159621725 0.7915252953636877L-0.3062858771943538 0.9614861359693313L0 1L10 1L10.306285877194354 0.9614861359693312L10.625902815962172 0.7915252953636873L10.864971742012976 0.5197023318679519L10.992726653972925 0.18099839425163988L10.992726653972925 -0.1809983942516403L10.864971742012976 -0.5197023318679523L10.625902815962172 -0.7915252953636875L10.306285877194354 -0.9614861359693313L10 -1L0 -1L-0.306285877194354 -0.9614861359693312L-0.625902815962173 -0.7915252953636872L-0.8649717420129767 -0.5197023318679518z"},
}
for _, tt := range tts {
t.Run(fmt.Sprintf("%v/%v", tt.orig, tt.w), func(t *testing.T) {
offset := MustParseSVGPath(tt.orig).Offset(tt.w, NonZero, tolerance)
test.T(t, offset, MustParseSVGPath(tt.offset))
})
}
}