2019-12-20 10:30:58 +00:00
|
|
|
package maps
|
|
|
|
|
|
|
|
import (
|
2019-12-20 11:04:26 +00:00
|
|
|
"errors"
|
2019-12-20 10:30:58 +00:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
olc "github.com/google/open-location-code/go"
|
|
|
|
"github.com/photoprism/photoprism/internal/maps/osm"
|
|
|
|
)
|
|
|
|
|
2019-12-20 11:04:26 +00:00
|
|
|
const SourceOSM = "osm"
|
|
|
|
|
2019-12-20 10:30:58 +00:00
|
|
|
// Photo location
|
|
|
|
type Location struct {
|
2019-12-20 11:04:26 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-12-20 11:20:35 +00:00
|
|
|
type LocationSource interface {
|
|
|
|
Latitude() float64
|
|
|
|
Longitude() float64
|
|
|
|
Title() string
|
|
|
|
City() string
|
|
|
|
Suburb() string
|
|
|
|
State() string
|
|
|
|
Country() string
|
|
|
|
Label() string
|
|
|
|
Source() string
|
2019-12-20 10:30:58 +00:00
|
|
|
}
|
|
|
|
|
2019-12-20 11:20:35 +00:00
|
|
|
func (l *Location) Query(lat, lng float64) error {
|
2019-12-20 11:04:26 +00:00
|
|
|
o, err := osm.FindLocation(lat, lng)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-12-20 11:20:35 +00:00
|
|
|
return l.Assign(o)
|
2019-12-20 11:04:26 +00:00
|
|
|
}
|
|
|
|
|
2019-12-20 11:20:35 +00:00
|
|
|
func (l *Location) Assign(s LocationSource) error {
|
|
|
|
l.LocSource = s.Source()
|
|
|
|
l.LocLat = s.Latitude()
|
|
|
|
l.LocLng = s.Longitude()
|
2019-12-20 10:30:58 +00:00
|
|
|
|
|
|
|
if l.Unknown() {
|
2019-12-20 11:04:26 +00:00
|
|
|
l.LocLabel = "unknown"
|
|
|
|
return errors.New("maps: unknown location")
|
2019-12-20 10:30:58 +00:00
|
|
|
}
|
|
|
|
|
2019-12-20 11:04:26 +00:00
|
|
|
l.ID = olc.Encode(l.LocLat, l.LocLng, 11)
|
2019-12-20 11:20:35 +00:00
|
|
|
l.LocTitle = s.Title()
|
|
|
|
l.LocCity = s.City()
|
|
|
|
l.LocSuburb = s.Suburb()
|
|
|
|
l.LocState = s.State()
|
|
|
|
l.LocCountry = s.Country()
|
2019-12-20 11:04:26 +00:00
|
|
|
l.LocRegion = l.region()
|
2019-12-20 11:20:35 +00:00
|
|
|
l.LocLabel = s.Label()
|
2019-12-20 11:04:26 +00:00
|
|
|
|
|
|
|
return nil
|
2019-12-20 10:30:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Location) Unknown() bool {
|
2019-12-20 11:04:26 +00:00
|
|
|
if l.LocLng == 0.0 && l.LocLat == 0.0 {
|
2019-12-20 10:30:58 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Location) region() string {
|
|
|
|
if l.Unknown() {
|
|
|
|
return "Unknown"
|
|
|
|
}
|
|
|
|
|
2019-12-20 11:04:26 +00:00
|
|
|
var countryName = Countries[l.LocCountry]
|
2019-12-20 10:30:58 +00:00
|
|
|
var loc []string
|
|
|
|
shortCountry := len([]rune(countryName)) <= 20
|
2019-12-20 11:04:26 +00:00
|
|
|
shortCity := len([]rune(l.LocCity)) <= 20
|
2019-12-20 10:30:58 +00:00
|
|
|
|
2019-12-20 11:04:26 +00:00
|
|
|
if shortCity && l.LocCity != "" {
|
|
|
|
loc = append(loc, l.LocCity)
|
2019-12-20 10:30:58 +00:00
|
|
|
}
|
|
|
|
|
2019-12-20 11:04:26 +00:00
|
|
|
if shortCountry && l.LocState != "" && l.LocCity != l.LocState {
|
|
|
|
loc = append(loc, l.LocState)
|
2019-12-20 10:30:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if countryName != "" {
|
|
|
|
loc = append(loc, countryName)
|
|
|
|
}
|
|
|
|
|
|
|
|
return strings.Join(loc[:], ", ")
|
|
|
|
}
|