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  }