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  }