2019-12-20 11:30:58 +01:00
|
|
|
package maps
|
|
|
|
|
|
|
|
import (
|
2019-12-20 12:04:26 +01:00
|
|
|
"errors"
|
2019-12-20 11:30:58 +01:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/photoprism/photoprism/internal/maps/osm"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Photo location
|
|
|
|
type Location struct {
|
2019-12-27 05:18:52 +01:00
|
|
|
ID string `gorm:"type:varbinary(16);primary_key;"`
|
|
|
|
LocLat float64
|
|
|
|
LocLng float64
|
|
|
|
LocName string `gorm:"type:varchar(100);"`
|
|
|
|
LocCategory string `gorm:"type:varchar(50);"`
|
|
|
|
LocSuburb string `gorm:"type:varchar(100);"`
|
|
|
|
LocPlace string `gorm:"type:varbinary(500);index;"`
|
|
|
|
LocCity string `gorm:"type:varchar(100);"`
|
|
|
|
LocState string `gorm:"type:varchar(100);"`
|
|
|
|
LocCountry string `gorm:"type:binary(2);"`
|
|
|
|
LocSource string `gorm:"type:varbinary(16);"`
|
2019-12-20 12:04:26 +01:00
|
|
|
}
|
|
|
|
|
2019-12-20 12:20:35 +01:00
|
|
|
type LocationSource interface {
|
2019-12-20 23:05:44 +01:00
|
|
|
CountryCode() string
|
2019-12-20 12:20:35 +01:00
|
|
|
Latitude() float64
|
|
|
|
Longitude() float64
|
2019-12-20 23:05:44 +01:00
|
|
|
Category() string
|
2019-12-27 05:18:52 +01:00
|
|
|
Name() string
|
2019-12-20 12:20:35 +01:00
|
|
|
City() string
|
|
|
|
Suburb() string
|
|
|
|
State() string
|
|
|
|
Source() string
|
2019-12-20 11:30:58 +01:00
|
|
|
}
|
|
|
|
|
2019-12-21 17:24:29 +01:00
|
|
|
func NewLocation(lat, lng float64) *Location {
|
2019-12-27 05:18:52 +01:00
|
|
|
id := ID(lat, lng)
|
2019-12-20 20:23:16 +01:00
|
|
|
|
|
|
|
result := &Location{
|
2019-12-21 17:24:29 +01:00
|
|
|
ID: id,
|
2019-12-20 20:23:16 +01:00
|
|
|
LocLat: lat,
|
|
|
|
LocLng: lng,
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Location) Query() error {
|
|
|
|
o, err := osm.FindLocation(l.LocLat, l.LocLng)
|
2019-12-20 12:04:26 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-12-20 12:20:35 +01:00
|
|
|
return l.Assign(o)
|
2019-12-20 12:04:26 +01:00
|
|
|
}
|
|
|
|
|
2019-12-20 12:20:35 +01:00
|
|
|
func (l *Location) Assign(s LocationSource) error {
|
|
|
|
l.LocSource = s.Source()
|
2019-12-20 20:23:16 +01:00
|
|
|
|
2019-12-21 17:24:29 +01:00
|
|
|
if l.LocLat == 0 {
|
|
|
|
l.LocLat = s.Latitude()
|
|
|
|
}
|
|
|
|
if l.LocLng == 0 {
|
|
|
|
l.LocLng = s.Longitude()
|
|
|
|
}
|
2019-12-20 11:30:58 +01:00
|
|
|
|
|
|
|
if l.Unknown() {
|
2019-12-20 23:05:44 +01:00
|
|
|
l.LocCategory = "unknown"
|
2019-12-20 12:04:26 +01:00
|
|
|
return errors.New("maps: unknown location")
|
2019-12-20 11:30:58 +01:00
|
|
|
}
|
|
|
|
|
2019-12-21 17:24:29 +01:00
|
|
|
if l.ID == "" {
|
2019-12-27 05:18:52 +01:00
|
|
|
l.ID = ID(l.LocLat, l.LocLng)
|
2019-12-21 17:24:29 +01:00
|
|
|
}
|
2019-12-20 20:23:16 +01:00
|
|
|
|
2019-12-27 05:18:52 +01:00
|
|
|
l.LocName = s.Name()
|
2019-12-20 12:20:35 +01:00
|
|
|
l.LocCity = s.City()
|
|
|
|
l.LocSuburb = s.Suburb()
|
|
|
|
l.LocState = s.State()
|
2019-12-27 05:18:52 +01:00
|
|
|
l.LocCountry = s.CountryCode()
|
2019-12-20 23:05:44 +01:00
|
|
|
l.LocCategory = s.Category()
|
2019-12-27 05:18:52 +01:00
|
|
|
l.LocPlace = l.place()
|
2019-12-20 12:04:26 +01:00
|
|
|
|
|
|
|
return nil
|
2019-12-20 11:30:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Location) Unknown() bool {
|
2019-12-20 12:04:26 +01:00
|
|
|
if l.LocLng == 0.0 && l.LocLat == 0.0 {
|
2019-12-20 11:30:58 +01:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-12-27 05:18:52 +01:00
|
|
|
func (l *Location) place() string {
|
2019-12-20 11:30:58 +01:00
|
|
|
if l.Unknown() {
|
|
|
|
return "Unknown"
|
|
|
|
}
|
|
|
|
|
2019-12-20 20:23:16 +01:00
|
|
|
var countryName = l.CountryName()
|
2019-12-20 11:30:58 +01:00
|
|
|
var loc []string
|
2019-12-20 20:23:16 +01:00
|
|
|
|
2019-12-20 11:30:58 +01:00
|
|
|
shortCountry := len([]rune(countryName)) <= 20
|
2019-12-20 12:04:26 +01:00
|
|
|
shortCity := len([]rune(l.LocCity)) <= 20
|
2019-12-20 11:30:58 +01:00
|
|
|
|
2019-12-20 12:04:26 +01:00
|
|
|
if shortCity && l.LocCity != "" {
|
|
|
|
loc = append(loc, l.LocCity)
|
2019-12-20 11:30:58 +01:00
|
|
|
}
|
|
|
|
|
2019-12-20 12:04:26 +01:00
|
|
|
if shortCountry && l.LocState != "" && l.LocCity != l.LocState {
|
|
|
|
loc = append(loc, l.LocState)
|
2019-12-20 11:30:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if countryName != "" {
|
|
|
|
loc = append(loc, countryName)
|
|
|
|
}
|
|
|
|
|
|
|
|
return strings.Join(loc[:], ", ")
|
|
|
|
}
|
2019-12-20 20:23:16 +01:00
|
|
|
|
|
|
|
func (l Location) Latitude() float64 {
|
|
|
|
return l.LocLat
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l Location) Longitude() float64 {
|
|
|
|
return l.LocLng
|
|
|
|
}
|
|
|
|
|
2019-12-27 05:18:52 +01:00
|
|
|
func (l Location) Name() string {
|
|
|
|
return l.LocName
|
2019-12-20 20:23:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l Location) City() string {
|
|
|
|
return l.LocCity
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l Location) Suburb() string {
|
|
|
|
return l.LocSuburb
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l Location) State() string {
|
|
|
|
return l.LocState
|
|
|
|
}
|
|
|
|
|
2019-12-20 23:05:44 +01:00
|
|
|
func (l Location) Category() string {
|
|
|
|
return l.LocCategory
|
2019-12-20 20:23:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l Location) Source() string {
|
|
|
|
return l.LocSource
|
|
|
|
}
|
|
|
|
|
2019-12-27 05:18:52 +01:00
|
|
|
func (l Location) Place() string {
|
|
|
|
return l.LocPlace
|
2019-12-20 20:23:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l Location) CountryCode() string {
|
2019-12-27 05:18:52 +01:00
|
|
|
return l.LocCountry
|
2019-12-20 20:23:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l Location) CountryName() string {
|
2019-12-27 05:18:52 +01:00
|
|
|
return CountryNames[l.LocCountry]
|
2019-12-20 20:23:16 +01:00
|
|
|
}
|