|
1 | 1 | package ms2 |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "strconv" |
4 | 5 | "testing" |
5 | 6 |
|
6 | 7 | math "github.com/chewxy/math32" |
| 8 | + "github.com/soypat/geometry/internal" |
| 9 | + "github.com/soypat/geometry/ms1" |
7 | 10 | ) |
8 | 11 |
|
9 | 12 | var testoffsets = []Vec{{-1, -2}, {-2, 1}, {2, -1}, {}, {1, 0}, {0, 1}, {1, 1}} |
@@ -183,3 +186,44 @@ func TestArc_invalidArc(t *testing.T) { |
183 | 186 | } |
184 | 187 | } |
185 | 188 | } |
| 189 | + |
| 190 | +func TestArcUniformity(t *testing.T) { |
| 191 | + const tol = internal.Smallfloat32 |
| 192 | + var cases = []struct { |
| 193 | + start, end Vec |
| 194 | + radius float32 |
| 195 | + }{ |
| 196 | + {start: Vec{0, 0}, end: Vec{0, 4}, radius: 2}, |
| 197 | + } |
| 198 | + var poly PolygonBuilder |
| 199 | + var buf []Vec |
| 200 | + var err error |
| 201 | + for itest, test := range cases { |
| 202 | + for _, facets := range []int{2, 3, 5, 9} { |
| 203 | + t.Run("case="+strconv.Itoa(itest)+" facets="+strconv.Itoa(facets), func(t *testing.T) { |
| 204 | + poly.Reset() |
| 205 | + poly.Add(test.start) |
| 206 | + poly.Add(test.end).Arc(test.radius, facets) |
| 207 | + buf, err = poly.AppendVecs(buf[:0]) |
| 208 | + if err != nil { |
| 209 | + t.Fatal(err) |
| 210 | + } |
| 211 | + center, angle, err := arcCenterFrom2points(test.start, test.end, test.radius) |
| 212 | + if err != nil { |
| 213 | + t.Errorf("getting center: %s", err) |
| 214 | + } |
| 215 | + anglePerFacet := angle / float32(facets) |
| 216 | + dir0 := Sub(test.start, center) |
| 217 | + for i, v := range buf { |
| 218 | + dir := Sub(v, center) |
| 219 | + cosangle := Cos(dir, dir0) |
| 220 | + gotAngle := math.Acos(cosangle) |
| 221 | + wantAngle := float32(i) * anglePerFacet |
| 222 | + if !ms1.EqualWithinAbs(gotAngle, wantAngle, tol) { |
| 223 | + t.Errorf("%d/%d facet-dir want angle swept %f, got %f", i+1, len(buf), wantAngle, gotAngle) |
| 224 | + } |
| 225 | + } |
| 226 | + }) |
| 227 | + } |
| 228 | + } |
| 229 | +} |
0 commit comments