github.com/liucxer/courier@v1.7.1/h3/linked_geo_test.go (about) 1 package h3 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/require" 7 ) 8 9 func createLinkedLoop(loop *LinkedGeoLoop, verts []GeoCoord, numVerts int) { 10 *loop = LinkedGeoLoop{} 11 12 for i := 0; i < numVerts; i++ { 13 addLinkedCoord(loop, &verts[i]) 14 } 15 } 16 17 func Test_pointInsideLinkedGeoLoop(t *testing.T) { 18 somewhere := GeoCoord{1, 2} 19 inside := GeoCoord{0.659, -2.136} 20 var loop LinkedGeoLoop 21 createLinkedLoop(&loop, sfVerts, 6) 22 23 var bbox BBox 24 bboxFrom(&loop, &bbox) 25 26 require.True(t, pointInside(&loop, &bbox, &inside), "contains exact4") 27 require.True(t, !pointInside(&loop, &bbox, &somewhere), "contains somewhere else") 28 29 destroyLinkedGeoLoop(&loop) 30 } 31 32 func Test_bboxFromGeofenceNoVertices(t *testing.T) { 33 geofence := Geofence{} 34 geofence.verts = nil 35 geofence.numVerts = 0 36 expected := BBox{0.0, 0.0, 0.0, 0.0} 37 38 var result BBox 39 bboxFrom(&geofence, &result) 40 require.True(t, bboxEquals(&result, &expected), "Got expected bbox") 41 } 42 43 func Test_bboxFromLinkedGeoLoop(t *testing.T) { 44 verts := []GeoCoord{{0.8, 0.3}, {0.7, 0.6}, {1.1, 0.7}, {1.0, 0.2}} 45 var loop LinkedGeoLoop 46 createLinkedLoop(&loop, verts, 4) 47 48 expected := BBox{1.1, 0.7, 0.7, 0.2} 49 var result BBox 50 bboxFrom(&loop, &result) 51 require.True(t, bboxEquals(&result, &expected), "Got expected bbox") 52 destroyLinkedGeoLoop(&loop) 53 } 54 55 func Test_bboxFromLinkedGeoLoopNoVertices(t *testing.T) { 56 loop := LinkedGeoLoop{} 57 expected := BBox{0.0, 0.0, 0.0, 0.0} 58 var result BBox 59 bboxFrom(&loop, &result) 60 61 require.True(t, bboxEquals(&result, &expected), "Got expected bbox") 62 destroyLinkedGeoLoop(&loop) 63 } 64 65 func Test_isClockwiseLinkedGeoLoop(t *testing.T) { 66 verts := []GeoCoord{{0.1, 0.1}, {0.2, 0.2}, {0.1, 0.2}} 67 var loop LinkedGeoLoop 68 createLinkedLoop(&loop, verts, 3) 69 70 require.True(t, isClockwise(&loop), "Got true for clockwise loop") 71 destroyLinkedGeoLoop(&loop) 72 } 73 74 func Test_isNotClockwiseLinkedGeoLoop(t *testing.T) { 75 verts := []GeoCoord{{0, 0}, {0, 0.4}, {0.4, 0.4}, {0.4, 0}} 76 var loop LinkedGeoLoop 77 createLinkedLoop(&loop, verts, 4) 78 require.True(t, !isClockwise(&loop), "Got false for counter-clockwise loop") 79 destroyLinkedGeoLoop(&loop) 80 } 81 82 func Test_isClockwiseLinkedGeoLoopTransmeridian(t *testing.T) { 83 verts := []GeoCoord{{0.4, M_PI - 0.1}, 84 {0.4, -M_PI + 0.1}, 85 {-0.4, -M_PI + 0.1}, 86 {-0.4, M_PI - 0.1}} 87 var loop LinkedGeoLoop 88 createLinkedLoop(&loop, verts, 4) 89 require.True(t, isClockwise(&loop), 90 "Got true for clockwise transmeridian loop") 91 destroyLinkedGeoLoop(&loop) 92 } 93 94 func Test_isNotClockwiseLinkedGeoLoopTransmeridian(t *testing.T) { 95 verts := []GeoCoord{{0.4, M_PI - 0.1}, 96 {-0.4, M_PI - 0.1}, 97 {-0.4, -M_PI + 0.1}, 98 {0.4, -M_PI + 0.1}} 99 var loop LinkedGeoLoop 100 createLinkedLoop(&loop, verts, 4) 101 require.True(t, !isClockwise(&loop), "Got false for counter-clockwise transmeridian loop") 102 destroyLinkedGeoLoop(&loop) 103 } 104 105 func Test_normalizeMultiPolygonSingle(t *testing.T) { 106 verts := []GeoCoord{{0, 0}, {0, 1}, {1, 1}} 107 outer := &LinkedGeoLoop{} 108 createLinkedLoop(outer, verts, 3) 109 polygon := LinkedGeoPolygon{} 110 addLinkedLoop(&polygon, outer) 111 result := normalizeMultiPolygon(&polygon) 112 require.True(t, result == NORMALIZATION_SUCCESS, "No error code returned") 113 require.True(t, countLinkedPolygons(&polygon) == 1, "Polygon count correct") 114 require.True(t, countLinkedLoops(&polygon) == 1, "Loop count correct") 115 require.True(t, polygon.first == outer, "Got expected loop") 116 destroyLinkedPolygon(&polygon) 117 } 118 119 func Test_normalizeMultiPolygonTwoOuterLoops(t *testing.T) { 120 verts1 := []GeoCoord{{0, 0}, {0, 1}, {1, 1}} 121 outer1 := &LinkedGeoLoop{} 122 createLinkedLoop(outer1, verts1, 3) 123 verts2 := []GeoCoord{{2, 2}, {2, 3}, {3, 3}} 124 outer2 := &LinkedGeoLoop{} 125 createLinkedLoop(outer2, verts2, 3) 126 polygon := LinkedGeoPolygon{} 127 addLinkedLoop(&polygon, outer1) 128 addLinkedLoop(&polygon, outer2) 129 result := normalizeMultiPolygon(&polygon) 130 require.True(t, result == NORMALIZATION_SUCCESS, "No error code returned") 131 require.True(t, countLinkedPolygons(&polygon) == 2, "Polygon count correct") 132 require.True(t, countLinkedLoops(&polygon) == 1, 133 "Loop count on first polygon correct") 134 require.True(t, countLinkedLoops(polygon.next) == 1, 135 "Loop count on second polygon correct") 136 destroyLinkedPolygon(&polygon) 137 } 138 139 func Test_normalizeMultiPolygonOneHole(t *testing.T) { 140 verts := []GeoCoord{{0, 0}, {0, 3}, {3, 3}, {3, 0}} 141 outer := &LinkedGeoLoop{} 142 createLinkedLoop(outer, verts, 4) 143 verts2 := []GeoCoord{{1, 1}, {2, 2}, {1, 2}} 144 inner := &LinkedGeoLoop{} 145 createLinkedLoop(inner, verts2, 3) 146 polygon := LinkedGeoPolygon{} 147 addLinkedLoop(&polygon, inner) 148 addLinkedLoop(&polygon, outer) 149 result := normalizeMultiPolygon(&polygon) 150 require.True(t, result == NORMALIZATION_SUCCESS, "No error code returned") 151 require.True(t, countLinkedPolygons(&polygon) == 1, "Polygon count correct") 152 require.True(t, countLinkedLoops(&polygon) == 2, 153 "Loop count on first polygon correct") 154 require.True(t, polygon.first == outer, "Got expected outer loop") 155 require.True(t, polygon.first.next == inner, "Got expected inner loop") 156 destroyLinkedPolygon(&polygon) 157 } 158 159 func Test_normalizeMultiPolygonTwoHoles(t *testing.T) { 160 verts := []GeoCoord{{0, 0}, {0, 0.4}, {0.4, 0.4}, {0.4, 0}} 161 outer := &LinkedGeoLoop{} 162 require.True(t, outer != nil) 163 createLinkedLoop(outer, verts, 4) 164 verts2 := []GeoCoord{{0.1, 0.1}, {0.2, 0.2}, {0.1, 0.2}} 165 inner1 := &LinkedGeoLoop{} 166 require.True(t, inner1 != nil) 167 createLinkedLoop(inner1, verts2, 3) 168 verts3 := []GeoCoord{{0.2, 0.2}, {0.3, 0.3}, {0.2, 0.3}} 169 inner2 := &LinkedGeoLoop{} 170 171 createLinkedLoop(inner2, verts3, 3) 172 polygon := LinkedGeoPolygon{} 173 addLinkedLoop(&polygon, inner2) 174 addLinkedLoop(&polygon, outer) 175 addLinkedLoop(&polygon, inner1) 176 result := normalizeMultiPolygon(&polygon) 177 require.True(t, result == NORMALIZATION_SUCCESS, "No error code returned") 178 require.True(t, countLinkedPolygons(&polygon) == 1, 179 "Polygon count correct for 2 holes") 180 require.True(t, polygon.first == outer, "Got expected outer loop") 181 require.True(t, countLinkedLoops(&polygon) == 3, 182 "Loop count on first polygon correct") 183 destroyLinkedPolygon(&polygon) 184 } 185 186 func Test_normalizeMultiPolygonTwoDonuts(t *testing.T) { 187 verts := []GeoCoord{{0, 0}, {0, 3}, {3, 3}, {3, 0}} 188 outer := &LinkedGeoLoop{} 189 createLinkedLoop(outer, verts, 4) 190 verts2 := []GeoCoord{{1, 1}, {2, 2}, {1, 2}} 191 inner := &LinkedGeoLoop{} 192 createLinkedLoop(inner, verts2, 3) 193 verts3 := []GeoCoord{{0, 0}, {0, -3}, {-3, -3}, {-3, 0}} 194 outer2 := &LinkedGeoLoop{} 195 createLinkedLoop(outer2, verts3, 4) 196 verts4 := []GeoCoord{{-1, -1}, {-2, -2}, {-1, -2}} 197 inner2 := &LinkedGeoLoop{} 198 createLinkedLoop(inner2, verts4, 3) 199 polygon := LinkedGeoPolygon{} 200 addLinkedLoop(&polygon, inner2) 201 addLinkedLoop(&polygon, inner) 202 addLinkedLoop(&polygon, outer) 203 addLinkedLoop(&polygon, outer2) 204 result := normalizeMultiPolygon(&polygon) 205 require.True(t, result == NORMALIZATION_SUCCESS, "No error code returned") 206 require.True(t, countLinkedPolygons(&polygon) == 2, "Polygon count correct") 207 require.True(t, countLinkedLoops(&polygon) == 2, 208 "Loop count on first polygon correct") 209 require.True(t, countLinkedCoords(polygon.first) == 4, 210 "Got expected outer loop") 211 require.True(t, countLinkedCoords(polygon.first.next) == 3, 212 "Got expected inner loop") 213 require.True(t, countLinkedLoops(polygon.next) == 2, 214 "Loop count on second polygon correct") 215 require.True(t, countLinkedCoords(polygon.next.first) == 4, 216 "Got expected outer loop") 217 require.True(t, countLinkedCoords(polygon.next.first.next) == 3, 218 "Got expected inner loop") 219 destroyLinkedPolygon(&polygon) 220 } 221 222 func Test_normalizeMultiPolygonNestedDonuts(t *testing.T) { 223 verts := []GeoCoord{{0.2, 0.2}, {0.2, -0.2}, {-0.2, -0.2}, {-0.2, 0.2}} 224 outer := &LinkedGeoLoop{} 225 createLinkedLoop(outer, verts, 4) 226 verts2 := []GeoCoord{ 227 {0.1, 0.1}, {-0.1, 0.1}, {-0.1, -0.1}, {0.1, -0.1}} 228 inner := &LinkedGeoLoop{} 229 createLinkedLoop(inner, verts2, 4) 230 verts3 := []GeoCoord{ 231 {0.6, 0.6}, {0.6, -0.6}, {-0.6, -0.6}, {-0.6, 0.6}} 232 outerBig := &LinkedGeoLoop{} 233 createLinkedLoop(outerBig, verts3, 4) 234 verts4 := []GeoCoord{ 235 {0.5, 0.5}, {-0.5, 0.5}, {-0.5, -0.5}, {0.5, -0.5}} 236 innerBig := &LinkedGeoLoop{} 237 createLinkedLoop(innerBig, verts4, 4) 238 polygon := LinkedGeoPolygon{} 239 addLinkedLoop(&polygon, inner) 240 addLinkedLoop(&polygon, outerBig) 241 addLinkedLoop(&polygon, innerBig) 242 addLinkedLoop(&polygon, outer) 243 result := normalizeMultiPolygon(&polygon) 244 require.True(t, result == NORMALIZATION_SUCCESS, "No error code returned") 245 require.True(t, countLinkedPolygons(&polygon) == 2, "Polygon count correct") 246 require.True(t, countLinkedLoops(&polygon) == 2, 247 "Loop count on first polygon correct") 248 require.True(t, polygon.first == outerBig, "Got expected outer loop") 249 require.True(t, polygon.first.next == innerBig, "Got expected inner loop") 250 require.True(t, countLinkedLoops(polygon.next) == 2, 251 "Loop count on second polygon correct") 252 require.True(t, polygon.next.first == outer, "Got expected outer loop") 253 require.True(t, polygon.next.first.next == inner, "Got expected inner loop") 254 destroyLinkedPolygon(&polygon) 255 } 256 257 func Test_normalizeMultiPolygonNoOuterLoops(t *testing.T) { 258 verts1 := []GeoCoord{{0, 0}, {1, 1}, {0, 1}} 259 outer1 := &LinkedGeoLoop{} 260 createLinkedLoop(outer1, verts1, 3) 261 verts2 := []GeoCoord{{2, 2}, {3, 3}, {2, 3}} 262 outer2 := &LinkedGeoLoop{} 263 createLinkedLoop(outer2, verts2, 3) 264 polygon := LinkedGeoPolygon{} 265 addLinkedLoop(&polygon, outer1) 266 addLinkedLoop(&polygon, outer2) 267 result := normalizeMultiPolygon(&polygon) 268 require.True(t, result == NORMALIZATION_ERR_UNASSIGNED_HOLES, 269 "Expected error code returned") 270 require.True(t, countLinkedPolygons(&polygon) == 1, "Polygon count correct") 271 require.True(t, countLinkedLoops(&polygon) == 0, 272 "Loop count as expected with invalid input") 273 destroyLinkedPolygon(&polygon) 274 } 275 276 func Test_normalizeMultiPolygonAlreadyNormalized(t *testing.T) { 277 verts1 := []GeoCoord{{0, 0}, {0, 1}, {1, 1}} 278 outer1 := &LinkedGeoLoop{} 279 createLinkedLoop(outer1, verts1, 3) 280 verts2 := []GeoCoord{{2, 2}, {2, 3}, {3, 3}} 281 outer2 := &LinkedGeoLoop{} 282 createLinkedLoop(outer2, verts2, 3) 283 polygon := LinkedGeoPolygon{} 284 addLinkedLoop(&polygon, outer1) 285 next := addNewLinkedPolygon(&polygon) 286 addLinkedLoop(next, outer2) 287 288 // Should be a no-op 289 result := normalizeMultiPolygon(&polygon) 290 require.True(t, result == NORMALIZATION_ERR_MULTIPLE_POLYGONS, 291 "Expected error code returned") 292 require.True(t, countLinkedPolygons(&polygon) == 2, "Polygon count correct") 293 require.True(t, countLinkedLoops(&polygon) == 1, 294 "Loop count on first polygon correct") 295 require.True(t, polygon.first == outer1, "Got expected outer loop") 296 require.True(t, countLinkedLoops(polygon.next) == 1, 297 "Loop count on second polygon correct") 298 require.True(t, polygon.next.first == outer2, "Got expected outer loop") 299 destroyLinkedPolygon(&polygon) 300 } 301 302 func Test_normalizeMultiPolygon_unassignedHole(t *testing.T) { 303 verts := []GeoCoord{{0, 0}, {0, 1}, {1, 1}, {1, 0}} 304 outer := &LinkedGeoLoop{} 305 createLinkedLoop(outer, verts, 4) 306 verts2 := []GeoCoord{{2, 2}, {3, 3}, {2, 3}} 307 inner := &LinkedGeoLoop{} 308 createLinkedLoop(inner, verts2, 3) 309 polygon := LinkedGeoPolygon{} 310 addLinkedLoop(&polygon, inner) 311 addLinkedLoop(&polygon, outer) 312 result := normalizeMultiPolygon(&polygon) 313 require.True(t, result == NORMALIZATION_ERR_UNASSIGNED_HOLES, "Expected error code returned") 314 destroyLinkedPolygon(&polygon) 315 }