diff --git a/pkg/geo/grids/latlon/latlon.go b/pkg/geo/grids/latlon/latlon.go index 96bca4f..096fb6e 100644 --- a/pkg/geo/grids/latlon/latlon.go +++ b/pkg/geo/grids/latlon/latlon.go @@ -60,26 +60,33 @@ func newLatLonGrid(minLat, maxLat, minLon, maxLon, latStep, lonStep float64) *la lonStep: lonStep, } + intMaxLat := int(math.Round(maxLat * 1e6)) + intMinLat := int(math.Round(minLat * 1e6)) + intMaxLon := int(math.Round(maxLon * 1e6)) + intMinLon := int(math.Round(minLon * 1e6)) + intLatStep := int(math.Round(latStep * 1e6)) + intLonStep := int(math.Round(lonStep * 1e6)) + // 计算点数 - ll.latCount = int(math.Abs(maxLat-minLat)/latStep) + 1 - ll.lonCount = int((maxLon-minLon)/lonStep) + 1 + ll.latCount = int(math.Round(float64(intMaxLat-intMinLat)/float64(intLatStep))) + 1 + ll.lonCount = int(math.Round(float64(intMaxLon-intMinLon)/float64(intLonStep))) + 1 // 纬度数组总是从北到南排列 ll.lats = make([]float64, ll.latCount) for i := 0; i < ll.latCount; i++ { - ll.lats[i] = ll.maxLat - float64(i)*latStep + ll.lats[i] = float64(intMaxLat-i*intLatStep) / 1e6 } // 经度数组总是从西到东排列 ll.lons = make([]float64, ll.lonCount) for i := 0; i < ll.lonCount; i++ { - ll.lons[i] = ll.minLon + float64(i)*lonStep + ll.lons[i] = float64(intMinLon+i*intLonStep) / 1e6 } isSphere := func() bool { - maxLon := int(maxLon * 1e6) - minLon := int(minLon * 1e6) - return maxLon+int(lonStep*1e6) == minLon+360*1e6 + maxLon := int(math.Round(maxLon * 1e6)) + minLon := int(math.Round(minLon * 1e6)) + return maxLon+int(math.Round(lonStep*1e6)) == minLon+360*1e6 }() ll.isSphere = isSphere diff --git a/pkg/geo/grids/latlon/latlon_test.go b/pkg/geo/grids/latlon/latlon_test.go index ff20947..e03abe5 100644 --- a/pkg/geo/grids/latlon/latlon_test.go +++ b/pkg/geo/grids/latlon/latlon_test.go @@ -159,6 +159,45 @@ func TestGridPoint(t *testing.T) { } } +func TestGridPoint_Wave0p16(t *testing.T) { + grid := latlon.NewLatLonGrid(-15.0, 52.5, 0.0, 359.833, 0.166667, 0.166667) + assert.Equal(t, 406, len(grid.Latitudes())) + assert.Equal(t, 2160, len(grid.Longitudes())) + assert.Equal(t, 876960, grid.Size()) + + tests := []struct { + lat, lon float64 + index int + }{ + {lat: 52.5, lon: 0.0, index: 0}, + {lat: 52.5, lon: 0.166667, index: 1}, + {lat: 52.5, lon: 0.333333, index: 2}, + {lat: 52.5, lon: 0.5, index: 3}, + {lat: 52.5, lon: 0.666667, index: 4}, + {lat: 52.5, lon: 0.833333, index: 5}, + {lat: 52.5, lon: 1, index: 6}, + {lat: 52.5, lon: 2, index: 12}, + {lat: 52.5, lon: 3, index: 18}, + {lat: 52.5, lon: 359, index: 359 * 6}, + {lat: 52.5, lon: 359.166667, index: 359*6 + 1}, + {lat: 52.5, lon: 359.333333, index: 359*6 + 2}, + {lat: 52.5, lon: 359.5, index: 359*6 + 3}, + {lat: 52.5, lon: 359.666667, index: 359*6 + 4}, + {lat: 52.5, lon: 359.833333, index: 359*6 + 5}, + {lat: -15.0, lon: 0, index: 874800}, + {lat: -15.0, lon: 359.833, index: 876959}, + } + + for _, tt := range tests { + t.Run(fmt.Sprintf("lat=%.2f, lon=%.2f", tt.lat, tt.lon), func(t *testing.T) { + lat, lon, ok := grids.GridPoint(grid, tt.index, 0) + assert.InDelta(t, tt.lat, lat, 1e-2) + assert.InDelta(t, tt.lon, lon, 1e-2) + assert.True(t, ok) + }) + } +} + func TestGridRoundTrip(t *testing.T) { grid := latlon.NewLatLonGrid(30.0, 35.0, 110.0, 115.0, 0.5, 0.5)