github.com/liucxer/courier@v1.7.1/h3/algos_test.go (about) 1 package h3 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/require" 7 ) 8 9 func Test_h3SetToLinkedGeo(t *testing.T) { 10 t.Run("empty", func(t *testing.T) { 11 var polygon LinkedGeoPolygon 12 h3SetToLinkedGeo(nil, 0, &polygon) 13 require.True(t, countLinkedLoops(&polygon) == 0, "No loops added to polygon") 14 destroyLinkedPolygon(&polygon) 15 }) 16 17 t.Run("singleHex", func(t *testing.T) { 18 var polygon LinkedGeoPolygon 19 set := []H3Index{0x890dab6220bffff} 20 numHexes := len(set) 21 22 h3SetToLinkedGeo(set, numHexes, &polygon) 23 require.True(t, countLinkedLoops(&polygon) == 1, "1 loop added to polygon") 24 require.True(t, countLinkedCoords(polygon.first) == 6, 25 "6 coords added to loop") 26 destroyLinkedPolygon(&polygon) 27 }) 28 29 t.Run("contiguous2", func(t *testing.T) { 30 var polygon LinkedGeoPolygon 31 set := []H3Index{0x8928308291bffff, 0x89283082957ffff} 32 numHexes := len(set) 33 34 h3SetToLinkedGeo(set, numHexes, &polygon) 35 require.True(t, countLinkedLoops(&polygon) == 1, "1 loop added to polygon") 36 require.True(t, countLinkedCoords(polygon.first) == 10, 37 "All coords added to loop except 2 shared") 38 destroyLinkedPolygon(&polygon) 39 }) 40 41 // TODO: This test asserts incorrect behavior - we should be creating 42 // multiple polygons, each with their own single loop. Update when the 43 // algorithm is corrected. 44 t.Run("nonContiguous2", func(t *testing.T) { 45 var polygon LinkedGeoPolygon 46 set := []H3Index{0x8928308291bffff, 0x89283082943ffff} 47 numHexes := len(set) 48 49 h3SetToLinkedGeo(set, numHexes, &polygon) 50 require.True(t, countLinkedPolygons(&polygon) == 2, "2 polygons added") 51 require.True(t, countLinkedLoops(&polygon) == 1, "1 loop on the first polygon") 52 require.True(t, countLinkedCoords(polygon.first) == 6, "All coords for one hex added to first loop") 53 require.True(t, countLinkedLoops(polygon.next) == 1, "Loop count on second polygon correct") 54 require.True(t, countLinkedCoords(polygon.next.first) == 6, "All coords for one hex added to second polygon") 55 56 destroyLinkedPolygon(&polygon) 57 }) 58 59 t.Run("contiguous3", func(t *testing.T) { 60 var polygon LinkedGeoPolygon 61 set := []H3Index{0x8928308288bffff, 0x892830828d7ffff, 0x8928308289bffff} 62 numHexes := len(set) 63 64 h3SetToLinkedGeo(set, numHexes, &polygon) 65 require.True(t, countLinkedLoops(&polygon) == 1, "1 loop added to polygon") 66 require.True(t, countLinkedCoords(polygon.first) == 12, "All coords added to loop except 6 shared") 67 destroyLinkedPolygon(&polygon) 68 }) 69 70 t.Run("hole", func(t *testing.T) { 71 var polygon LinkedGeoPolygon 72 set := []H3Index{0x892830828c7ffff, 0x892830828d7ffff, 0x8928308289bffff, 0x89283082813ffff, 0x8928308288fffff, 0x89283082883ffff} 73 numHexes := len(set) 74 75 h3SetToLinkedGeo(set, numHexes, &polygon) 76 require.True(t, countLinkedLoops(&polygon) == 2, "2 loops added to polygon") 77 require.True(t, countLinkedCoords(polygon.first) == 6*3, "All outer coords added to first loop") 78 require.True(t, countLinkedCoords(polygon.first.next) == 6, "All inner coords added to second loop") 79 destroyLinkedPolygon(&polygon) 80 }) 81 82 t.Run("pentagon", func(t *testing.T) { 83 var polygon LinkedGeoPolygon 84 set := []H3Index{0x851c0003fffffff} 85 numHexes := len(set) 86 87 h3SetToLinkedGeo(set, numHexes, &polygon) 88 require.Equal(t, 1, countLinkedLoops(&polygon), "1 loop added to polygon") 89 require.Equal(t, 10, countLinkedCoords(polygon.first), "10 coords (distorted pentagon) added to loop") 90 destroyLinkedPolygon(&polygon) 91 }) 92 93 t.Run("2Ring", func(t *testing.T) { 94 var polygon LinkedGeoPolygon 95 // 2-ring, in order returned by k-ring algo 96 set := []H3Index{ 97 0x8930062838bffff, 0x8930062838fffff, 0x89300628383ffff, 98 0x8930062839bffff, 0x893006283d7ffff, 0x893006283c7ffff, 99 0x89300628313ffff, 0x89300628317ffff, 0x893006283bbffff, 100 0x89300628387ffff, 0x89300628397ffff, 0x89300628393ffff, 101 0x89300628067ffff, 0x8930062806fffff, 0x893006283d3ffff, 102 0x893006283c3ffff, 0x893006283cfffff, 0x8930062831bffff, 103 0x89300628303ffff} 104 numHexes := len(set) 105 106 h3SetToLinkedGeo(set, numHexes, &polygon) 107 require.True(t, countLinkedLoops(&polygon) == 1, "1 loop added to polygon") 108 require.True(t, countLinkedCoords(polygon.first) == (6*(2*2+1)), "Expected number of coords added to loop") 109 destroyLinkedPolygon(&polygon) 110 }) 111 112 t.Run("2RingUnordered", func(t *testing.T) { 113 var polygon LinkedGeoPolygon 114 // 2-ring in random order 115 set := []H3Index{ 116 0x89300628393ffff, 0x89300628383ffff, 0x89300628397ffff, 117 0x89300628067ffff, 0x89300628387ffff, 0x893006283bbffff, 118 0x89300628313ffff, 0x893006283cfffff, 0x89300628303ffff, 119 0x89300628317ffff, 0x8930062839bffff, 0x8930062838bffff, 120 0x8930062806fffff, 0x8930062838fffff, 0x893006283d3ffff, 121 0x893006283c3ffff, 0x8930062831bffff, 0x893006283d7ffff, 122 0x893006283c7ffff} 123 numHexes := len(set) 124 125 h3SetToLinkedGeo(set, numHexes, &polygon) 126 require.True(t, countLinkedLoops(&polygon) == 1, "1 loop added to polygon") 127 require.True(t, countLinkedCoords(polygon.first) == (6*(2*2+1)), 128 "Expected number of coords added to loop") 129 destroyLinkedPolygon(&polygon) 130 }) 131 132 t.Run("nestedDonut", func(t *testing.T) { 133 var polygon LinkedGeoPolygon 134 // hollow 1-ring + hollow 3-ring around the same hex 135 set := []H3Index{ 136 0x89283082813ffff, 0x8928308281bffff, 0x8928308280bffff, 137 0x8928308280fffff, 0x89283082807ffff, 0x89283082817ffff, 138 0x8928308289bffff, 0x892830828d7ffff, 0x892830828c3ffff, 139 0x892830828cbffff, 0x89283082853ffff, 0x89283082843ffff, 140 0x8928308284fffff, 0x8928308287bffff, 0x89283082863ffff, 141 0x89283082867ffff, 0x8928308282bffff, 0x89283082823ffff, 142 0x89283082837ffff, 0x892830828afffff, 0x892830828a3ffff, 143 0x892830828b3ffff, 0x89283082887ffff, 0x89283082883ffff} 144 numHexes := len(set) 145 146 h3SetToLinkedGeo(set, numHexes, &polygon) 147 148 // Note that the polygon order here is arbitrary, making this test 149 // somewhat brittle, but it's difficult to assert correctness otherwise 150 require.True(t, countLinkedPolygons(&polygon) == 2, "Polygon count correct") 151 require.True(t, countLinkedLoops(&polygon) == 2, "Loop count on first polygon correct") 152 require.True(t, countLinkedCoords(polygon.first) == 42, "Got expected big outer loop") 153 require.True(t, countLinkedCoords(polygon.first.next) == 30, "Got expected big inner loop") 154 require.True(t, countLinkedLoops(polygon.next) == 2, "Loop count on second polygon correct") 155 require.True(t, countLinkedCoords(polygon.next.first) == 18, "Got expected outer loop") 156 require.True(t, countLinkedCoords(polygon.next.first.next) == 6, "Got expected inner loop") 157 destroyLinkedPolygon(&polygon) 158 }) 159 160 t.Run("nestedDonutTransmeridian", func(t *testing.T) { 161 var polygon LinkedGeoPolygon 162 // hollow 1-ring + hollow 3-ring around the hex at (0, -180) 163 set := []H3Index{ 164 0x897eb5722c7ffff, 0x897eb5722cfffff, 0x897eb572257ffff, 165 0x897eb57220bffff, 0x897eb572203ffff, 0x897eb572213ffff, 166 0x897eb57266fffff, 0x897eb5722d3ffff, 0x897eb5722dbffff, 167 0x897eb573537ffff, 0x897eb573527ffff, 0x897eb57225bffff, 168 0x897eb57224bffff, 0x897eb57224fffff, 0x897eb57227bffff, 169 0x897eb572263ffff, 0x897eb572277ffff, 0x897eb57223bffff, 170 0x897eb572233ffff, 0x897eb5722abffff, 0x897eb5722bbffff, 171 0x897eb572287ffff, 0x897eb572283ffff, 0x897eb57229bffff} 172 numHexes := len(set) 173 174 h3SetToLinkedGeo(set, numHexes, &polygon) 175 176 // Note that the polygon order here is arbitrary, making this test 177 // somewhat brittle, but it's difficult to assert correctness otherwise 178 require.True(t, countLinkedPolygons(&polygon) == 2, "Polygon count correct") 179 require.True(t, countLinkedLoops(&polygon) == 2, 180 "Loop count on first polygon correct") 181 require.True(t, countLinkedCoords(polygon.first) == 18, 182 "Got expected outer loop") 183 require.True(t, countLinkedCoords(polygon.first.next) == 6, 184 "Got expected inner loop") 185 require.True(t, countLinkedLoops(polygon.next) == 2, 186 "Loop count on second polygon correct") 187 require.True(t, countLinkedCoords(polygon.next.first) == 42, 188 "Got expected big outer loop") 189 require.True(t, countLinkedCoords(polygon.next.first.next) == 30, 190 "Got expected big inner loop") 191 destroyLinkedPolygon(&polygon) 192 }) 193 194 t.Run("contiguous2distorted", func(t *testing.T) { 195 var polygon LinkedGeoPolygon 196 set := []H3Index{0x894cc5365afffff, 0x894cc536537ffff} 197 numHexes := len(set) 198 199 h3SetToLinkedGeo(set, numHexes, &polygon) 200 require.True(t, countLinkedLoops(&polygon) == 1, "1 loop added to polygon") 201 require.True(t, countLinkedCoords(polygon.first) == 12, 202 "All coords added to loop except 2 shared") 203 destroyLinkedPolygon(&polygon) 204 }) 205 206 t.Run("negativeHashedCoordinates", func(t *testing.T) { 207 var polygon LinkedGeoPolygon 208 set := []H3Index{0x88ad36c547fffff, 0x88ad36c467fffff} 209 numHexes := len(set) 210 h3SetToLinkedGeo(set, numHexes, &polygon) 211 require.True(t, countLinkedPolygons(&polygon) == 2, "2 polygons added") 212 require.True(t, countLinkedLoops(&polygon) == 1, 213 "1 loop on the first polygon") 214 require.True(t, countLinkedCoords(polygon.first) == 6, 215 "All coords for one hex added to first loop") 216 require.True(t, countLinkedLoops(polygon.next) == 1, 217 "Loop count on second polygon correct") 218 require.True(t, countLinkedCoords(polygon.next.first) == 6, 219 "All coords for one hex added to second polygon") 220 destroyLinkedPolygon(&polygon) 221 }) 222 } 223 224 func Test_h3SetToVertexGraph(t *testing.T) { 225 t.Run("empty", func(t *testing.T) { 226 var graph VertexGraph 227 h3SetToVertexGraph(nil, 0, &graph) 228 require.True(t, graph.size == 0, "No edges added to graph") 229 destroyVertexGraph(&graph) 230 }) 231 232 t.Run("singleHex", func(t *testing.T) { 233 var graph VertexGraph 234 set := []H3Index{0x890dab6220bffff} 235 numHexes := len(set) 236 h3SetToVertexGraph(set, numHexes, &graph) 237 require.True(t, graph.size == 6, "All edges of one hex added to graph") 238 destroyVertexGraph(&graph) 239 }) 240 241 t.Run("nonContiguous2", func(t *testing.T) { 242 var graph VertexGraph 243 set := []H3Index{0x8928308291bffff, 0x89283082943ffff} 244 numHexes := len(set) 245 h3SetToVertexGraph(set, numHexes, &graph) 246 247 require.Equal(t, 12, graph.size, "All edges of two non-contiguous hexes added to graph") 248 destroyVertexGraph(&graph) 249 }) 250 251 t.Run("contiguous2", func(t *testing.T) { 252 var graph VertexGraph 253 set := []H3Index{0x8928308291bffff, 0x89283082957ffff} 254 numHexes := len(set) 255 h3SetToVertexGraph(set, numHexes, &graph) 256 257 require.Equal(t, 10, graph.size, "All edges except 2 shared added to graph") 258 destroyVertexGraph(&graph) 259 }) 260 261 t.Run("contiguous2distorted", func(t *testing.T) { 262 var graph VertexGraph 263 set := []H3Index{0x894cc5365afffff, 0x894cc536537ffff} 264 numHexes := len(set) 265 266 h3SetToVertexGraph(set, numHexes, &graph) 267 require.Equal(t, 12, graph.size, "All edges except 2 shared added to graph") 268 destroyVertexGraph(&graph) 269 }) 270 271 t.Run("contiguous3", func(t *testing.T) { 272 var graph VertexGraph 273 set := []H3Index{0x8928308288bffff, 0x892830828d7ffff, 274 0x8928308289bffff} 275 numHexes := len(set) 276 277 h3SetToVertexGraph(set, numHexes, &graph) 278 require.True(t, graph.size == 3*4, "All edges except 6 shared added to graph") 279 destroyVertexGraph(&graph) 280 }) 281 282 t.Run("hole", func(t *testing.T) { 283 var graph VertexGraph 284 set := []H3Index{ 285 0x892830828c7ffff, 286 0x892830828d7ffff, 287 0x8928308289bffff, 288 0x89283082813ffff, 289 0x8928308288fffff, 290 0x89283082883ffff, 291 } 292 numHexes := len(set) 293 h3SetToVertexGraph(set, numHexes, &graph) 294 require.True(t, graph.size == (6*3)+6, "All outer edges and inner hole edges added to graph") 295 destroyVertexGraph(&graph) 296 }) 297 }