...

Source file src/github.com/golang/geo/s2/latlng_test.go

Documentation: github.com/golang/geo/s2

     1  // Copyright 2014 Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package s2
    16  
    17  import (
    18  	"math"
    19  	"testing"
    20  
    21  	"github.com/golang/geo/s1"
    22  )
    23  
    24  func TestLatLngNormalized(t *testing.T) {
    25  	tests := []struct {
    26  		desc string
    27  		pos  LatLng
    28  		want LatLng
    29  	}{
    30  		{
    31  			desc: "Valid lat/lng",
    32  			pos:  LatLngFromDegrees(21.8275043, 151.1979675),
    33  			want: LatLngFromDegrees(21.8275043, 151.1979675),
    34  		},
    35  		{
    36  			desc: "Valid lat/lng in the West",
    37  			pos:  LatLngFromDegrees(21.8275043, -151.1979675),
    38  			want: LatLngFromDegrees(21.8275043, -151.1979675),
    39  		},
    40  		{
    41  			desc: "Beyond the North pole",
    42  			pos:  LatLngFromDegrees(95, 151.1979675),
    43  			want: LatLngFromDegrees(90, 151.1979675),
    44  		},
    45  		{
    46  			desc: "Beyond the South pole",
    47  			pos:  LatLngFromDegrees(-95, 151.1979675),
    48  			want: LatLngFromDegrees(-90, 151.1979675),
    49  		},
    50  		{
    51  			desc: "At the date line (from East)",
    52  			pos:  LatLngFromDegrees(21.8275043, 180),
    53  			want: LatLngFromDegrees(21.8275043, 180),
    54  		},
    55  		{
    56  			desc: "At the date line (from West)",
    57  			pos:  LatLngFromDegrees(21.8275043, -180),
    58  			want: LatLngFromDegrees(21.8275043, -180),
    59  		},
    60  		{
    61  			desc: "Across the date line going East",
    62  			pos:  LatLngFromDegrees(21.8275043, 181.0012),
    63  			want: LatLngFromDegrees(21.8275043, -178.9988),
    64  		},
    65  		{
    66  			desc: "Across the date line going West",
    67  			pos:  LatLngFromDegrees(21.8275043, -181.0012),
    68  			want: LatLngFromDegrees(21.8275043, 178.9988),
    69  		},
    70  		{
    71  			desc: "All wrong",
    72  			pos:  LatLngFromDegrees(256, 256),
    73  			want: LatLngFromDegrees(90, -104),
    74  		},
    75  	}
    76  
    77  	for _, test := range tests {
    78  		got := test.pos.Normalized()
    79  		if !got.IsValid() {
    80  			t.Errorf("%s: A LatLng should be valid after normalization but isn't: %v", test.desc, got)
    81  		} else if got.Distance(test.want) > 1e-13*s1.Degree {
    82  			t.Errorf("%s: %v.Normalized() = %v, want %v", test.desc, test.pos, got, test.want)
    83  		}
    84  	}
    85  }
    86  
    87  func TestLatLngString(t *testing.T) {
    88  	const expected string = "[1.4142136, -2.2360680]"
    89  	s := LatLngFromDegrees(math.Sqrt2, -math.Sqrt(5)).String()
    90  	if s != expected {
    91  		t.Errorf("LatLng{√2, -√5}.String() = %q, want %q", s, expected)
    92  	}
    93  }
    94  
    95  func TestLatLngPointConversion(t *testing.T) {
    96  	// All test cases here have been verified against the C++ S2 implementation.
    97  	tests := []struct {
    98  		lat, lng float64 // degrees
    99  		x, y, z  float64
   100  	}{
   101  		{0, 0, 1, 0, 0},
   102  		{90, 0, 6.12323e-17, 0, 1},
   103  		{-90, 0, 6.12323e-17, 0, -1},
   104  		{0, 180, -1, 1.22465e-16, 0},
   105  		{0, -180, -1, -1.22465e-16, 0},
   106  		{90, 180, -6.12323e-17, 7.4988e-33, 1},
   107  		{90, -180, -6.12323e-17, -7.4988e-33, 1},
   108  		{-90, 180, -6.12323e-17, 7.4988e-33, -1},
   109  		{-90, -180, -6.12323e-17, -7.4988e-33, -1},
   110  		{-81.82750430354997, 151.19796752929685,
   111  			-0.12456788151479525, 0.0684875268284729, -0.989844584550441},
   112  	}
   113  	for _, test := range tests {
   114  		ll := LatLngFromDegrees(test.lat, test.lng)
   115  		p := PointFromLatLng(ll)
   116  		want := PointFromCoords(test.x, test.y, test.z)
   117  		if !p.ApproxEqual(want) {
   118  			t.Errorf("PointFromLatLng({%v°, %v°}) = %v, want %v", test.lat, test.lng, p, want)
   119  		}
   120  		ll = LatLngFromPoint(p)
   121  		// We need to be careful here, since if the latitude is +/- 90, any longitude
   122  		// is now a valid conversion.
   123  		isPolar := (test.lat == 90 || test.lat == -90)
   124  		if !float64Eq(ll.Lat.Degrees(), test.lat) ||
   125  			(!isPolar && (!float64Eq(ll.Lng.Degrees(), test.lng))) {
   126  			t.Errorf("Converting ll %v,%v to point (%v) and back gave %v.",
   127  				test.lat, test.lng, p, ll)
   128  		}
   129  	}
   130  }
   131  
   132  func TestLatLngDistance(t *testing.T) {
   133  	// Based on C++ S2LatLng::TestDistance.
   134  	tests := []struct {
   135  		lat1, lng1, lat2, lng2 float64
   136  		want, tolerance        float64
   137  	}{
   138  		{90, 0, 90, 0, 0, 0},
   139  		{-37, 25, -66, -155, 77, 1e-13},
   140  		{0, 165, 0, -80, 115, 1e-13},
   141  		{47, -127, -47, 53, 180, 2e-6},
   142  	}
   143  	for _, test := range tests {
   144  		ll1 := LatLngFromDegrees(test.lat1, test.lng1)
   145  		ll2 := LatLngFromDegrees(test.lat2, test.lng2)
   146  		d := ll1.Distance(ll2).Degrees()
   147  		if math.Abs(d-test.want) > test.tolerance {
   148  			t.Errorf("LatLng{%v, %v}.Distance(LatLng{%v, %v}).Degrees() = %v, want %v",
   149  				test.lat1, test.lng1, test.lat2, test.lng2, d, test.want)
   150  		}
   151  	}
   152  }
   153  
   154  func TestLatLngApproxEqual(t *testing.T) {
   155  	const ε = epsilon / 10
   156  	tests := []struct {
   157  		a, b LatLng
   158  		want bool
   159  	}{
   160  		{LatLngFromDegrees(30, 50), LatLngFromDegrees(30, 50+ε), true},
   161  		{LatLngFromDegrees(30, 50), LatLngFromDegrees(30-ε, 50), true},
   162  		{LatLngFromDegrees(1, 5), LatLngFromDegrees(2, 3), false},
   163  	}
   164  
   165  	for _, test := range tests {
   166  		if got := test.a.ApproxEqual(test.b); got != test.want {
   167  			t.Errorf("%v.ApproxEqual(%v) = %t, want %t", test.a, test.b, got, test.want)
   168  		}
   169  	}
   170  }
   171  

View as plain text