69 lines
1.5 KiB
Go
69 lines
1.5 KiB
Go
package query
|
|
|
|
import (
|
|
"github.com/tidwall/geodesic"
|
|
"sort"
|
|
)
|
|
|
|
type IGeoLocation interface {
|
|
HasGeoLocation() bool
|
|
Lat() float64
|
|
Lon() float64
|
|
Dist(lat, lon float64) float64
|
|
Register(map[string]struct{}) bool
|
|
}
|
|
|
|
type GeoLocation struct {
|
|
Latitude float64
|
|
Longitude float64
|
|
}
|
|
|
|
func (b GeoLocation) HasGeoLocation() bool { return true }
|
|
|
|
func (b GeoLocation) Lat() float64 { return b.Latitude }
|
|
func (b GeoLocation) Lon() float64 { return b.Longitude }
|
|
|
|
func (b GeoLocation) Dist(lat float64, lon float64) float64 {
|
|
var dist float64
|
|
geodesic.WGS84.Inverse(
|
|
lat, lon,
|
|
b.Lat(), b.Lon(),
|
|
&dist, nil, nil,
|
|
)
|
|
return dist
|
|
}
|
|
|
|
type NoGeoLocation struct{}
|
|
|
|
func (b NoGeoLocation) HasGeoLocation() bool { return false }
|
|
func (b NoGeoLocation) Lat() float64 { return 0 }
|
|
func (b NoGeoLocation) Lon() float64 { return 0 }
|
|
func (b NoGeoLocation) Dist(lat, lon float64) float64 { return 0 }
|
|
func (b NoGeoLocation) Register(map[string]struct{}) bool {
|
|
return false
|
|
}
|
|
|
|
type GeoLocations []ISearchable
|
|
|
|
func (m GeoLocations) SortByNearest(p IGeoLocation) {
|
|
sort.Slice(m, func(i, j int) bool {
|
|
return m[i].Dist(p.Lat(), p.Lon()) < m[j].Dist(p.Lat(), p.Lon())
|
|
})
|
|
}
|
|
|
|
func (b GeoLocation) Register(map[string]struct{}) bool {
|
|
panic("GeoLocation: Default is called")
|
|
return false
|
|
}
|
|
|
|
func (m GeoLocations) Clean() *GeoLocations {
|
|
registers := map[string]struct{}{}
|
|
items := &GeoLocations{}
|
|
for _, item := range m {
|
|
if item.HasGeoLocation() && item.Register(registers) {
|
|
*items = append(*items, item)
|
|
}
|
|
}
|
|
return items
|
|
}
|