1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package s2
16
17 import (
18 "math"
19 "testing"
20
21 "github.com/golang/geo/r3"
22 )
23
24 func TestSTUV(t *testing.T) {
25 if x := stToUV(uvToST(.125)); x != .125 {
26 t.Error("stToUV(uvToST(.125) == ", x)
27 }
28 if x := uvToST(stToUV(.125)); x != .125 {
29 t.Error("uvToST(stToUV(.125) == ", x)
30 }
31 }
32
33 func TestUVNorms(t *testing.T) {
34 step := 1 / 1024.0
35 for face := 0; face < 6; face++ {
36 for x := -1.0; x <= 1; x += step {
37 if !float64Eq(float64(faceUVToXYZ(face, x, -1).Cross(faceUVToXYZ(face, x, 1)).Angle(uNorm(face, x))), 0.0) {
38 t.Errorf("UNorm not orthogonal to the face(%d)", face)
39 }
40 if !float64Eq(float64(faceUVToXYZ(face, -1, x).Cross(faceUVToXYZ(face, 1, x)).Angle(vNorm(face, x))), 0.0) {
41 t.Errorf("VNorm not orthogonal to the face(%d)", face)
42 }
43 }
44 }
45 }
46
47 func TestFaceUVToXYZ(t *testing.T) {
48
49 var sum r3.Vector
50 for face := 0; face < 6; face++ {
51 center := faceUVToXYZ(face, 0, 0)
52 if !center.ApproxEqual(unitNorm(face).Vector) {
53 t.Errorf("faceUVToXYZ(%d, 0, 0) != unitNorm(%d), should be equal", face, face)
54 }
55 switch center.LargestComponent() {
56 case r3.XAxis:
57 if math.Abs(center.X) != 1 {
58 t.Errorf("%v.X = %v, want %v", center, math.Abs(center.X), 1)
59 }
60 case r3.YAxis:
61 if math.Abs(center.Y) != 1 {
62 t.Errorf("%v.Y = %v, want %v", center, math.Abs(center.Y), 1)
63 }
64 default:
65 if math.Abs(center.Z) != 1 {
66 t.Errorf("%v.Z = %v, want %v", center, math.Abs(center.Z), 1)
67 }
68 }
69 sum = sum.Add(center.Abs())
70
71
72 if got := uAxis(face).Vector.Cross(vAxis(face).Vector).Dot(unitNorm(face).Vector); got != 1 {
73 t.Errorf("right-handed check failed. uAxis(%d).Cross(vAxis(%d)).Dot(unitNorm%v) = %f, want 1", face, face, face, got)
74 }
75
76
77
78
79
80 var sign float64 = 1
81 if face&swapMask == 1 {
82 sign = -1
83 }
84 if faceUVToXYZ(face, sign, -sign) != faceUVToXYZ((face+1)%6, -1, -1) {
85 t.Errorf("faceUVToXYZ(%v, %v, %v) != faceUVToXYZ(%v, -1, -1)", face, sign, -sign, (face+1)%6)
86 }
87 }
88
89
90 if !sum.ApproxEqual(r3.Vector{2, 2, 2}) {
91 t.Errorf("sum of the abs of the 6 face norms should = %v, got %v", r3.Vector{2, 2, 2}, sum)
92 }
93 }
94
95 func TestFaceXYZToUV(t *testing.T) {
96 var (
97 point = Point{r3.Vector{1.1, 1.2, 1.3}}
98 pointNeg = Point{r3.Vector{-1.1, -1.2, -1.3}}
99 )
100
101 tests := []struct {
102 face int
103 point Point
104 u float64
105 v float64
106 ok bool
107 }{
108 {0, point, 1 + (1.0 / 11), 1 + (2.0 / 11), true},
109 {0, pointNeg, 0, 0, false},
110 {1, point, -11.0 / 12, 1 + (1.0 / 12), true},
111 {1, pointNeg, 0, 0, false},
112 {2, point, -11.0 / 13, -12.0 / 13, true},
113 {2, pointNeg, 0, 0, false},
114 {3, point, 0, 0, false},
115 {3, pointNeg, 1 + (2.0 / 11), 1 + (1.0 / 11), true},
116 {4, point, 0, 0, false},
117 {4, pointNeg, 1 + (1.0 / 12), -(11.0 / 12), true},
118 {5, point, 0, 0, false},
119 {5, pointNeg, -12.0 / 13, -11.0 / 13, true},
120 }
121
122 for _, test := range tests {
123 if u, v, ok := faceXYZToUV(test.face, test.point); !float64Eq(u, test.u) || !float64Eq(v, test.v) || ok != test.ok {
124 t.Errorf("faceXYZToUV(%d, %v) = %f, %f, %t, want %f, %f, %t", test.face, test.point, u, v, ok, test.u, test.v, test.ok)
125 }
126 }
127 }
128
129 func TestFaceXYZtoUVW(t *testing.T) {
130 var (
131 origin = Point{r3.Vector{0, 0, 0}}
132 posX = Point{r3.Vector{1, 0, 0}}
133 negX = Point{r3.Vector{-1, 0, 0}}
134 posY = Point{r3.Vector{0, 1, 0}}
135 negY = Point{r3.Vector{0, -1, 0}}
136 posZ = Point{r3.Vector{0, 0, 1}}
137 negZ = Point{r3.Vector{0, 0, -1}}
138 )
139
140 for face := 0; face < 6; face++ {
141 if got := faceXYZtoUVW(face, origin); got != origin {
142 t.Errorf("faceXYZtoUVW(%d, %v) = %v, want %v", face, origin, got, origin)
143 }
144
145 if got := faceXYZtoUVW(face, uAxis(face)); got != posX {
146 t.Errorf("faceXYZtoUVW(%d, %v) = %v, want %v", face, uAxis(face), got, posX)
147 }
148
149 if got := faceXYZtoUVW(face, Point{uAxis(face).Mul(-1)}); got != negX {
150 t.Errorf("faceXYZtoUVW(%d, %v) = %v, want %v", face, uAxis(face).Mul(-1), got, negX)
151 }
152
153 if got := faceXYZtoUVW(face, vAxis(face)); got != posY {
154 t.Errorf("faceXYZtoUVW(%d, %v) = %v, want %v", face, vAxis(face), got, posY)
155 }
156
157 if got := faceXYZtoUVW(face, Point{vAxis(face).Mul(-1)}); got != negY {
158 t.Errorf("faceXYZtoUVW(%d, %v) = %v, want %v", face, vAxis(face).Mul(-1), got, negY)
159 }
160
161 if got := faceXYZtoUVW(face, unitNorm(face)); got != posZ {
162 t.Errorf("faceXYZtoUVW(%d, %v) = %v, want %v", face, unitNorm(face), got, posZ)
163 }
164
165 if got := faceXYZtoUVW(face, Point{unitNorm(face).Mul(-1)}); got != negZ {
166 t.Errorf("faceXYZtoUVW(%d, %v) = %v, want %v", face, unitNorm(face).Mul(-1), got, negZ)
167 }
168 }
169 }
170
171 func TestUVWAxis(t *testing.T) {
172 for face := 0; face < 6; face++ {
173
174 if faceUVToXYZ(face, 1, 0).Sub(faceUVToXYZ(face, 0, 0)) != uAxis(face).Vector {
175 t.Errorf("face 1,0 - face 0,0 should equal uAxis")
176 }
177 if faceUVToXYZ(face, 0, 1).Sub(faceUVToXYZ(face, 0, 0)) != vAxis(face).Vector {
178 t.Errorf("faceUVToXYZ(%d, 0, 1).Sub(faceUVToXYZ(%d, 0, 0)) != vAxis(%d), should be equal.", face, face, face)
179 }
180 if faceUVToXYZ(face, 0, 0) != unitNorm(face).Vector {
181 t.Errorf("faceUVToXYZ(%d, 0, 0) != unitNorm(%d), should be equal", face, face)
182 }
183
184
185 if got := uAxis(face).Vector.Cross(vAxis(face).Vector).Dot(unitNorm(face).Vector); got != 1 {
186 t.Errorf("right-handed check failed. got %f, want 1", got)
187 }
188
189
190 if uAxis(face) != uvwAxis(face, 0) {
191 t.Errorf("uAxis(%d) != uvwAxis(%d, 0), should be equal", face, face)
192 }
193 if vAxis(face) != uvwAxis(face, 1) {
194 t.Errorf("vAxis(%d) != uvwAxis(%d, 1), should be equal", face, face)
195 }
196 if unitNorm(face) != uvwAxis(face, 2) {
197 t.Errorf("unitNorm(%d) != uvwAxis(%d, 2), should be equal", face, face)
198 }
199 }
200 }
201
202 func TestSiTiSTRoundtrip(t *testing.T) {
203
204 for i := 0; i < 1000; i++ {
205 si := uint32(randomUniformInt(maxSiTi))
206 if got := stToSiTi(siTiToST(si)); got != si {
207 t.Errorf("stToSiTi(siTiToST(%v)) = %v, want %v", si, got, si)
208 }
209 }
210
211 for i := 0; i < 1000; i++ {
212 st := randomUniformFloat64(0, 1.0)
213
214
215 if got := siTiToST(stToSiTi(st)); !float64Near(got, st, 1e-8) {
216 t.Errorf("siTiToST(stToSiTi(%v)) = %v, want %v", st, got, st)
217 }
218 }
219 }
220
221 func TestUVWFace(t *testing.T) {
222
223 for f := 0; f < 6; f++ {
224 for axis := 0; axis < 3; axis++ {
225 if got, want := face(uvwAxis(f, axis).Mul(-1)), uvwFace(f, axis, 0); got != want {
226 t.Errorf("face(%v) in positive direction = %v, want %v", uvwAxis(f, axis).Mul(-1), got, want)
227 }
228 if got, want := face(uvwAxis(f, axis).Vector), uvwFace(f, axis, 1); got != want {
229 t.Errorf("face(%v) in negative direction = %v, want %v", uvwAxis(f, axis), got, want)
230 }
231 }
232 }
233 }
234
235 func TestXYZToFaceSiTi(t *testing.T) {
236 for level := 0; level < MaxLevel; level++ {
237 for i := 0; i < 1000; i++ {
238 ci := randomCellIDForLevel(level)
239 f, si, ti, gotLevel := xyzToFaceSiTi(ci.Point())
240 if gotLevel != level {
241 t.Errorf("level of CellID %v = %v, want %v", ci, gotLevel, level)
242 }
243 gotID := cellIDFromFaceIJ(f, int(si/2), int(ti/2)).Parent(level)
244 if gotID != ci {
245 t.Errorf("CellID = %b, want %b", gotID, ci)
246 }
247
248
249 pMoved := ci.Point().Add(r3.Vector{1e-13, 1e-13, 1e-13})
250 fMoved, siMoved, tiMoved, gotLevel := xyzToFaceSiTi(Point{pMoved})
251
252 if gotLevel != -1 {
253 t.Errorf("level of %v = %v, want %v", pMoved, gotLevel, -1)
254 }
255
256 if f != fMoved {
257 t.Errorf("face of %v = %v, want %v", pMoved, fMoved, f)
258 }
259
260 if si != siMoved {
261 t.Errorf("si of %v = %v, want %v", pMoved, siMoved, si)
262 }
263
264 if ti != tiMoved {
265 t.Errorf("ti of %v = %v, want %v", pMoved, tiMoved, ti)
266 }
267
268
269
270 faceRandom := randomUniformInt(NumFaces)
271 mask := -1 << uint32(MaxLevel-level)
272 siRandom := randomUint32() & uint32(mask)
273 tiRandom := randomUint32() & uint32(mask)
274 for siRandom > maxSiTi || tiRandom > maxSiTi {
275 siRandom = randomUint32() & uint32(mask)
276 tiRandom = randomUint32() & uint32(mask)
277 }
278
279 pRandom := faceSiTiToXYZ(faceRandom, siRandom, tiRandom)
280 f, si, ti, gotLevel = xyzToFaceSiTi(pRandom)
281
282
283 if f != faceRandom {
284 if gotLevel != -1 {
285 t.Errorf("level of random CellID = %v, want %v", gotLevel, -1)
286 }
287 if !(si == 0 || si == maxSiTi || ti == 0 || ti == maxSiTi) {
288 t.Errorf("face %d, si = %v, ti = %v, want 0 or %v for both", f, si, ti, maxSiTi)
289 }
290 continue
291 }
292
293 if siRandom != si {
294 t.Errorf("xyzToFaceSiTi(%v).si = %v, want %v", pRandom, siRandom, si)
295 }
296 if tiRandom != ti {
297 t.Errorf("xyzToFaceSiTi(%v).ti = %v, want %v", pRandom, tiRandom, ti)
298 }
299 if gotLevel >= 0 {
300 if got := cellIDFromFaceIJ(f, int(si/2), int(ti/2)).Parent(gotLevel).Point(); !pRandom.ApproxEqual(got) {
301 t.Errorf("cellIDFromFaceIJ(%d, %d, %d).Parent(%d) = %v, want %v", f, si/2, ti/2, gotLevel, got, pRandom)
302 }
303 }
304 }
305 }
306 }
307
308 func TestXYZFaceSiTiRoundtrip(t *testing.T) {
309 for level := 0; level < MaxLevel; level++ {
310 for i := 0; i < 1000; i++ {
311 ci := randomCellIDForLevel(level)
312 f, si, ti, _ := xyzToFaceSiTi(ci.Point())
313 op := faceSiTiToXYZ(f, si, ti)
314 if !ci.Point().ApproxEqual(op) {
315 t.Errorf("faceSiTiToXYZ(xyzToFaceSiTi(%v)) = %v, want %v", ci.Point(), op, ci.Point())
316 }
317 }
318 }
319 }
320
321 func TestSTUVFace(t *testing.T) {
322 tests := []struct {
323 v r3.Vector
324 want int
325 }{
326 {r3.Vector{-1, -1, -1}, 5},
327 {r3.Vector{-1, -1, 0}, 4},
328 {r3.Vector{-1, -1, 1}, 2},
329 {r3.Vector{-1, 0, -1}, 5},
330 {r3.Vector{-1, 0, 0}, 3},
331 {r3.Vector{-1, 0, 1}, 2},
332 {r3.Vector{-1, 1, -1}, 5},
333 {r3.Vector{-1, 1, 0}, 1},
334 {r3.Vector{-1, 1, 1}, 2},
335 {r3.Vector{0, -1, -1}, 5},
336 {r3.Vector{0, -1, 0}, 4},
337 {r3.Vector{0, -1, 1}, 2},
338 {r3.Vector{0, 0, -1}, 5},
339 {r3.Vector{0, 0, 0}, 2},
340 {r3.Vector{0, 0, 1}, 2},
341 {r3.Vector{0, 1, -1}, 5},
342 {r3.Vector{0, 1, 0}, 1},
343 {r3.Vector{0, 1, 1}, 2},
344 {r3.Vector{1, -1, -1}, 5},
345 {r3.Vector{1, -1, 0}, 4},
346 {r3.Vector{1, -1, 1}, 2},
347 {r3.Vector{1, 0, -1}, 5},
348 {r3.Vector{1, 0, 0}, 0},
349 {r3.Vector{1, 0, 1}, 2},
350 {r3.Vector{1, 1, -1}, 5},
351 {r3.Vector{1, 1, 0}, 1},
352 {r3.Vector{1, 1, 1}, 2},
353 }
354
355 for _, test := range tests {
356 if got := face(test.v); got != test.want {
357 t.Errorf("face(%v) = %d, want %d", test.v, got, test.want)
358 }
359 }
360 }
361
View as plain text