Backend: Refactor maps and osm packages

Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
Michael Mayer 2019-12-20 12:04:26 +01:00
parent 52b57e9fba
commit 1d0b1f8533
4 changed files with 125 additions and 58 deletions

View file

@ -1,48 +1,70 @@
package maps
import (
"errors"
"strings"
olc "github.com/google/open-location-code/go"
"github.com/photoprism/photoprism/internal/maps/osm"
)
const SourceOSM = "osm"
// Photo location
type Location struct {
ID string `gorm:"primary_key"`
Lat float64
Lng float64
Title string
City string
Suburb string
State string
Country string
Region string
Label string
ID string `gorm:"primary_key"`
LocLat float64
LocLng float64
LocTitle string
LocCity string
LocSuburb string
LocState string
LocCountry string
LocRegion string
LocLabel string
LocSource string
}
func (l *Location) FromOSM(o osm.Location) {
l.Lat = o.Latitude()
l.Lng = o.Longitude()
func (l *Location) Query(lat, lng float64) error {
return l.QueryOpenStreetMap(lat, lng)
}
if l.Unknown() {
log.Warnf("maps: unknown location")
l.Label = "unknown"
return
func (l *Location) QueryOpenStreetMap(lat, lng float64) error {
o, err := osm.FindLocation(lat, lng)
if err != nil {
return err
}
l.ID = olc.Encode(l.Lat, l.Lng, 11)
l.Title = o.Title()
l.City = o.City()
l.Suburb = o.Suburb()
l.State = o.State()
l.Country = o.Country()
l.Region = l.region()
l.Label = o.Label()
return l.OpenStreetMap(o)
}
func (l *Location) OpenStreetMap(o osm.Location) error {
l.LocSource = SourceOSM
l.LocLat = o.Latitude()
l.LocLng = o.Longitude()
if l.Unknown() {
l.LocLabel = "unknown"
return errors.New("maps: unknown location")
}
l.ID = olc.Encode(l.LocLat, l.LocLng, 11)
l.LocTitle = o.Title()
l.LocCity = o.City()
l.LocSuburb = o.Suburb()
l.LocState = o.State()
l.LocCountry = o.Country()
l.LocRegion = l.region()
l.LocLabel = o.Label()
return nil
}
func (l *Location) Unknown() bool {
if l.Lng == 0.0 && l.Lat == 0.0 {
if l.LocLng == 0.0 && l.LocLat == 0.0 {
return true
}
@ -54,17 +76,17 @@ func (l *Location) region() string {
return "Unknown"
}
var countryName = Countries[l.Country]
var countryName = Countries[l.LocCountry]
var loc []string
shortCountry := len([]rune(countryName)) <= 20
shortCity := len([]rune(l.City)) <= 20
shortCity := len([]rune(l.LocCity)) <= 20
if shortCity && l.City != "" {
loc = append(loc, l.City)
if shortCity && l.LocCity != "" {
loc = append(loc, l.LocCity)
}
if shortCountry && l.State != "" && l.City != l.State {
loc = append(loc, l.State)
if shortCountry && l.LocState != "" && l.LocCity != l.LocState {
loc = append(loc, l.LocState)
}
if countryName != "" {

View file

@ -7,7 +7,39 @@ import (
"github.com/stretchr/testify/assert"
)
func TestFindLocation(t *testing.T) {
func TestLocation_Query(t *testing.T) {
t.Run("BerlinFernsehturm", func(t *testing.T) {
lat := 52.5208
lng := 13.40953
var l Location
if err := l.Query(lat, lng); err != nil {
t.Fatal(err)
}
assert.Equal(t, "Fernsehturm Berlin", l.LocTitle)
assert.Equal(t, "Berlin, Germany", l.LocRegion)
})
}
func TestLocation_QueryOpenStreetMap(t *testing.T) {
t.Run("BerlinFernsehturm", func(t *testing.T) {
lat := 52.5208
lng := 13.40953
var l Location
if err := l.QueryOpenStreetMap(lat, lng); err != nil {
t.Fatal(err)
}
assert.Equal(t, "Fernsehturm Berlin", l.LocTitle)
assert.Equal(t, "Berlin, Germany", l.LocRegion)
})
}
func TestLocation_OpenStreetMap(t *testing.T) {
t.Run("BerlinFernsehturm", func(t *testing.T) {
lat := 52.5208
lng := 13.40953
@ -18,7 +50,6 @@ func TestFindLocation(t *testing.T) {
t.Fatal(err)
}
assert.False(t, o.Cached)
assert.Equal(t, 189675302, o.PlaceID)
assert.Equal(t, "Fernsehturm Berlin", o.Name)
assert.Equal(t, "10178", o.Address.Postcode)
@ -28,10 +59,12 @@ func TestFindLocation(t *testing.T) {
var l Location
l.FromOSM(o)
if err := l.OpenStreetMap(o); err != nil {
t.Fatal(err)
}
assert.Equal(t, "Fernsehturm Berlin", l.Title)
assert.Equal(t, "Berlin, Germany", l.Region)
assert.Equal(t, "Fernsehturm Berlin", l.LocTitle)
assert.Equal(t, "Berlin, Germany", l.LocRegion)
})
t.Run("SantaMonica", func(t *testing.T) {
@ -54,10 +87,12 @@ func TestFindLocation(t *testing.T) {
var l Location
l.FromOSM(o)
if err := l.OpenStreetMap(o); err != nil {
t.Fatal(err)
}
assert.Equal(t, "Santa Monica Pier", l.Title)
assert.Equal(t, "Santa Monica, California, USA", l.Region)
assert.Equal(t, "Santa Monica Pier", l.LocTitle)
assert.Equal(t, "Santa Monica, California, USA", l.LocRegion)
})
t.Run("AirportZurich", func(t *testing.T) {
@ -81,10 +116,12 @@ func TestFindLocation(t *testing.T) {
var l Location
l.FromOSM(o)
if err := l.OpenStreetMap(o); err != nil {
t.Fatal(err)
}
assert.Equal(t, "Airport", l.Title)
assert.Equal(t, "Kloten, Zurich, Switzerland", l.Region)
assert.Equal(t, "Airport", l.LocTitle)
assert.Equal(t, "Kloten, Zurich, Switzerland", l.LocRegion)
})
t.Run("AirportTegel", func(t *testing.T) {
@ -108,10 +145,12 @@ func TestFindLocation(t *testing.T) {
var l Location
l.FromOSM(o)
if err := l.OpenStreetMap(o); err != nil {
t.Fatal(err)
}
assert.Equal(t, "Airport", l.Title)
assert.Equal(t, "Berlin, Germany", l.Region)
assert.Equal(t, "Airport", l.LocTitle)
assert.Equal(t, "Berlin, Germany", l.LocRegion)
})
t.Run("PinkBeach", func(t *testing.T) {
@ -135,11 +174,13 @@ func TestFindLocation(t *testing.T) {
var l Location
l.FromOSM(o)
if err := l.OpenStreetMap(o); err != nil {
t.Fatal(err)
}
assert.Equal(t, "8G757G9P+R5C", l.ID)
assert.Equal(t, "Pink Beach", l.Title)
assert.Equal(t, "Crete, Greece", l.Region)
assert.Equal(t, "Pink Beach", l.LocTitle)
assert.Equal(t, "Crete, Greece", l.LocRegion)
})
t.Run("NewJersey", func(t *testing.T) {
@ -163,11 +204,13 @@ func TestFindLocation(t *testing.T) {
var l Location
l.FromOSM(o)
if err := l.OpenStreetMap(o); err != nil {
t.Fatal(err)
}
assert.Equal(t, "87G7PXV2+4G9", l.ID)
assert.Equal(t, "", l.Title)
assert.Equal(t, "Jersey City, New Jersey, USA", l.Region)
assert.Equal(t, "", l.LocTitle)
assert.Equal(t, "Jersey City, New Jersey, USA", l.LocRegion)
})
t.Run("SouthAfrica", func(t *testing.T) {
@ -191,10 +234,12 @@ func TestFindLocation(t *testing.T) {
var l Location
l.FromOSM(o)
if err := l.OpenStreetMap(o); err != nil {
t.Fatal(err)
}
assert.Equal(t, "4GWF24FX+F5H", l.ID)
assert.Equal(t, "Route R411", l.Title)
assert.Equal(t, "Eastern Cape, South Africa", l.Region)
assert.Equal(t, "Route R411", l.LocTitle)
assert.Equal(t, "Eastern Cape, South Africa", l.LocRegion)
})
}

View file

@ -29,13 +29,13 @@ var ReverseLookupURL = "https://nominatim.openstreetmap.org/reverse?lat=%f&lon=%
// API docs see https://wiki.openstreetmap.org/wiki/Nominatim#Reverse_Geocoding
func FindLocation(lat, lng float64) (result Location, err error) {
if lat == 0.0 || lng == 0.0 {
return result, fmt.Errorf("osm: skipping lat %f / lng %f", lat, lng)
return result, fmt.Errorf("osm: skipping lat %f, lng %f", lat, lng)
}
point := geocache.GeoPoint{Latitude: lat, Longitude: lng}
if hit, ok := geoCache.Get(point); ok {
log.Debugf("osm: cache hit for lat %f / lng %f", lat, lng)
log.Debugf("osm: cache hit for lat %f, lng %f", lat, lng)
result = hit.(Location)
result.Cached = true
return result, nil

View file

@ -73,7 +73,7 @@ func TestFindLocation(t *testing.T) {
t.Fatal("err should not be nil")
}
assert.Equal(t, "osm: skipping lat 0.000000 / lng 0.000000", err.Error())
assert.Equal(t, "osm: skipping lat 0.000000, lng 0.000000", err.Error())
assert.False(t, l.Cached)
})
}