mirror of https://github.com/tidwall/tile38.git
Updated geojson package
This commit is contained in:
parent
37d64f0466
commit
85b70e0d26
|
@ -221,7 +221,8 @@
|
||||||
version = "v1.1.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:cdab3bce90a53a124ac3982719abde77d779e961d9c180e55c23fb74fc62563a"
|
branch = "master"
|
||||||
|
digest = "1:16a87d3d8d3808f3206c4992d1fb50440bb7d5508fbe5bfab7d899b516c7f3b8"
|
||||||
name = "github.com/tidwall/geojson"
|
name = "github.com/tidwall/geojson"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
@ -229,8 +230,7 @@
|
||||||
"geometry",
|
"geometry",
|
||||||
]
|
]
|
||||||
pruneopts = ""
|
pruneopts = ""
|
||||||
revision = "eaf6e0a55a79c1e879bbbcc879a3176c720d99cd"
|
revision = "ff8d554639ee72ffa650eca1e02f03ab51193c7f"
|
||||||
version = "v1.1.3"
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:3ddca2bd5496c6922a2a9e636530e178a43c2a534ea6634211acdc7d10222794"
|
digest = "1:3ddca2bd5496c6922a2a9e636530e178a43c2a534ea6634211acdc7d10222794"
|
||||||
|
|
|
@ -34,8 +34,8 @@ required = [
|
||||||
name = "github.com/tidwall/boxtree"
|
name = "github.com/tidwall/boxtree"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
|
branch = "master"
|
||||||
name = "github.com/tidwall/geojson"
|
name = "github.com/tidwall/geojson"
|
||||||
version = "1.1.3"
|
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/Shopify/sarama"
|
name = "github.com/Shopify/sarama"
|
||||||
|
|
|
@ -93,75 +93,60 @@ func BearingTo(latA, lonA, latB, lonB float64) float64 {
|
||||||
func RectFromCenter(lat, lon, meters float64) (
|
func RectFromCenter(lat, lon, meters float64) (
|
||||||
minLat, minLon, maxLat, maxLon float64,
|
minLat, minLon, maxLat, maxLon float64,
|
||||||
) {
|
) {
|
||||||
|
// convert degrees to radians
|
||||||
// see http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates#Latitude
|
|
||||||
lat *= radians
|
lat *= radians
|
||||||
lon *= radians
|
lon *= radians
|
||||||
|
|
||||||
r := meters / earthRadius // angular radius
|
// Calculate ANGULAR RADIUS
|
||||||
|
// see http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates#UsingIndex
|
||||||
|
r := meters / earthRadius
|
||||||
|
|
||||||
|
// Calculate LATITUDE min and max
|
||||||
|
// see http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates#Latitude
|
||||||
minLat = lat - r
|
minLat = lat - r
|
||||||
maxLat = lat + r
|
maxLat = lat + r
|
||||||
|
|
||||||
|
// Calculate LONGITUDE min and max
|
||||||
|
// see http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates#Longitude
|
||||||
latT := math.Asin(math.Sin(lat) / math.Cos(r))
|
latT := math.Asin(math.Sin(lat) / math.Cos(r))
|
||||||
lonΔ := math.Acos((math.Cos(r) - math.Sin(latT)*math.Sin(lat)) / (math.Cos(latT) * math.Cos(lat)))
|
lonΔ := math.Acos((math.Cos(r) - math.Sin(latT)*math.Sin(lat)) / (math.Cos(latT) * math.Cos(lat)))
|
||||||
|
|
||||||
minLon = lon - lonΔ
|
minLon = lon - lonΔ
|
||||||
maxLon = lon + lonΔ
|
maxLon = lon + lonΔ
|
||||||
|
|
||||||
// Adjust for north poll
|
// ADJUST mins and maxes for edge-of-map cases
|
||||||
|
// see http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates#PolesAnd180thMeridian
|
||||||
|
|
||||||
|
// adjust for NORTH POLE
|
||||||
if maxLat > math.Pi/2 {
|
if maxLat > math.Pi/2 {
|
||||||
minLon = -math.Pi
|
minLon = -math.Pi
|
||||||
maxLat = math.Pi / 2
|
maxLat = math.Pi / 2
|
||||||
maxLon = math.Pi
|
maxLon = math.Pi
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust for south poll
|
// adjust for SOUTH POLE
|
||||||
if minLat < -math.Pi/2 {
|
if minLat < -math.Pi/2 {
|
||||||
minLat = -math.Pi / 2
|
minLat = -math.Pi / 2
|
||||||
minLon = -math.Pi
|
minLon = -math.Pi
|
||||||
maxLon = math.Pi
|
maxLon = math.Pi
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust for wraparound. Remove this if the commented-out condition below this block is added.
|
/* adjust for WRAPAROUND
|
||||||
|
|
||||||
|
Creates a bounding box that wraps around the Earth like a belt, which
|
||||||
|
results in returning false positive candidates (candidates that are
|
||||||
|
farther away from the center than the distance of the search radius).
|
||||||
|
|
||||||
|
An alternative method, possibly to be implemented in the future, would be
|
||||||
|
to split the bounding box into two boxes. This would return fewer (or no)
|
||||||
|
false positives, but will require significant changes to the API's of
|
||||||
|
geoJSON and any of its dependents. */
|
||||||
if minLon < -math.Pi || maxLon > math.Pi {
|
if minLon < -math.Pi || maxLon > math.Pi {
|
||||||
minLon = -math.Pi
|
minLon = -math.Pi
|
||||||
maxLon = math.Pi
|
maxLon = math.Pi
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// convert radians to degrees
|
||||||
// Consider splitting area into two bboxes, using the below checks, and erasing above block for performance. See http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates#PolesAnd180thMeridian
|
|
||||||
// Adjust for wraparound if minimum longitude is less than -180 degrees.
|
|
||||||
if lonMin < -math.Pi {
|
|
||||||
// box 1:
|
|
||||||
latMin = latMin
|
|
||||||
latMax = latMax
|
|
||||||
lonMin += 2*math.Pi
|
|
||||||
lonMax = math.Pi
|
|
||||||
// box 2:
|
|
||||||
latMin = latMin
|
|
||||||
latMax = latMax
|
|
||||||
lonMin = -math.Pi
|
|
||||||
lonMax = lonMax
|
|
||||||
}
|
|
||||||
// Adjust for wraparound if maximum longitude is greater than 180 degrees.
|
|
||||||
if lonMax > math.Pi {
|
|
||||||
// box 1:
|
|
||||||
latMin = latMin
|
|
||||||
latMax = latMax
|
|
||||||
lonMin = lonMin
|
|
||||||
lonMax = -math.Pi
|
|
||||||
// box 2:
|
|
||||||
latMin = latMin
|
|
||||||
latMax = latMax
|
|
||||||
lonMin = -math.Pi
|
|
||||||
lonMax -= 2*math.Pi
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
minLon = math.Mod(minLon+3*math.Pi, 2*math.Pi) - math.Pi // normalise to -180..+180°
|
|
||||||
maxLon = math.Mod(maxLon+3*math.Pi, 2*math.Pi) - math.Pi
|
|
||||||
|
|
||||||
minLat *= degrees
|
minLat *= degrees
|
||||||
minLon *= degrees
|
minLon *= degrees
|
||||||
maxLat *= degrees
|
maxLat *= degrees
|
||||||
|
|
|
@ -41,6 +41,68 @@ func TestGeoCalc(t *testing.T) {
|
||||||
if value2 != lonB {
|
if value2 != lonB {
|
||||||
t.Fatalf("expected '%v', got '%v'", lonB, value2)
|
t.Fatalf("expected '%v', got '%v'", lonB, value2)
|
||||||
}
|
}
|
||||||
|
// RectFromCenter
|
||||||
|
// expected mins and maxes for wraparound and pole tests
|
||||||
|
expMinLat := -90.0
|
||||||
|
expMinLon := -180.0
|
||||||
|
expMaxLat := 90.0
|
||||||
|
expMaxLon := 180.0
|
||||||
|
|
||||||
|
dist1 := 1600000.0
|
||||||
|
|
||||||
|
wraparoundTests := []struct {
|
||||||
|
name string
|
||||||
|
lat, lon, searchRadius float64
|
||||||
|
}{
|
||||||
|
{name: "Wraparound E", lat: 0.0, lon: 179.0, searchRadius: dist1}, // at equator near 180th meridian East
|
||||||
|
{name: "Wraparound W", lat: 0.0, lon: -179.0, searchRadius: dist1}, // at equator near 180th meridian West
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range wraparoundTests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
_, minLon, _, maxLon := RectFromCenter(tt.lat, tt.lon, tt.searchRadius)
|
||||||
|
if !(minLon == expMinLon && maxLon == expMaxLon) {
|
||||||
|
t.Errorf("\nexpected minLon = '%v', maxLon = '%v'"+"\ngot minLon = '%v', maxLon = '%v'\n",
|
||||||
|
expMinLon, expMaxLon,
|
||||||
|
minLon, maxLon)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
northPoleTests := []struct {
|
||||||
|
name string
|
||||||
|
lat, lon, searchRadius float64
|
||||||
|
}{
|
||||||
|
{name: "North Pole", lat: 89.0, lon: 90.0, searchRadius: dist1}, // near North Pole
|
||||||
|
{name: "North Pole: Tile38 iss422", lat: 13.0257553, lon: 77.6672509, searchRadius: 9000000.0},
|
||||||
|
}
|
||||||
|
for _, tt := range northPoleTests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
_, minLon, maxLat, maxLon := RectFromCenter(tt.lat, tt.lon, tt.searchRadius)
|
||||||
|
if !(minLon == expMinLon && maxLat == expMaxLat && maxLon == expMaxLon) {
|
||||||
|
t.Errorf("\nexpected minLon = '%v', maxLat = '%v', maxLon = '%v'"+"\ngot minLon = '%v', maxLat = '%v', maxLon = '%v'",
|
||||||
|
expMinLon, expMaxLat, expMaxLon,
|
||||||
|
minLon, maxLat, maxLon)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
southPoleTests := []struct {
|
||||||
|
name string
|
||||||
|
lat, lon, searchRadius float64
|
||||||
|
}{
|
||||||
|
{name: "South Pole", lat: -89.0, lon: 90.0, searchRadius: dist1}, // near South Pole
|
||||||
|
}
|
||||||
|
for _, tt := range southPoleTests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
minLat, minLon, _, maxLon := RectFromCenter(tt.lat, tt.lon, tt.searchRadius)
|
||||||
|
if !(minLat == expMinLat && minLon == expMinLon && maxLon == expMaxLon) {
|
||||||
|
t.Errorf("\nexpected minLat = '%v', minLon = '%v', maxLon = '%v'"+"\ngot minLat = '%v', minLon = '%v', maxLon = '%v'",
|
||||||
|
expMinLat, expMinLon, expMaxLon,
|
||||||
|
minLat, minLon, maxLon)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHaversine(t *testing.T) {
|
func TestHaversine(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue