Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
parent
b65362b35a
commit
85506f9373
9 changed files with 79 additions and 53 deletions
|
@ -134,13 +134,16 @@ export default {
|
|||
}
|
||||
|
||||
const settings = this.$config.settings();
|
||||
const features = settings.features;
|
||||
|
||||
if (settings && settings.features.private) {
|
||||
filter.public = "true";
|
||||
}
|
||||
if (settings) {
|
||||
if (features.private) {
|
||||
filter.public = "true";
|
||||
}
|
||||
|
||||
if (settings && settings.features.review && (!this.staticFilter || !("quality" in this.staticFilter))) {
|
||||
filter.quality = "3";
|
||||
if (features.review && (!this.staticFilter || !("quality" in this.staticFilter))) {
|
||||
filter.quality = "3";
|
||||
}
|
||||
}
|
||||
|
||||
switch (style) {
|
||||
|
@ -351,16 +354,16 @@ export default {
|
|||
let latNorth, lngEast, latSouth, lngWest;
|
||||
for (const feature of clusterFeatures) {
|
||||
const [lng, lat] = feature.geometry.coordinates;
|
||||
if (latNorth === undefined || lat < latNorth) {
|
||||
if (latNorth === undefined || lat > latNorth) {
|
||||
latNorth = lat;
|
||||
}
|
||||
if (lngEast === undefined || lng < lngEast) {
|
||||
if (lngEast === undefined || lng > lngEast) {
|
||||
lngEast = lng;
|
||||
}
|
||||
if (latSouth === undefined || lat > latSouth) {
|
||||
if (latSouth === undefined || lat < latSouth) {
|
||||
latSouth = lat;
|
||||
}
|
||||
if (lngWest === undefined || lng > lngWest) {
|
||||
if (lngWest === undefined || lng < lngWest) {
|
||||
lngWest = lng;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,9 +46,9 @@ type SearchPhotos struct {
|
|||
Lat float32 `form:"lat" notes:"GPS Position (Latitude)"`
|
||||
Lng float32 `form:"lng" notes:"GPS Position (Longitude)"`
|
||||
Dist uint `form:"dist" example:"dist:5" notes:"Distance to GPS Position (km)"`
|
||||
LatLng string `form:"latlng" notes:"GPS Bounding Box (Lat N, Lng E, Lat S, Lng W)"`
|
||||
Latlng string `form:"latlng" notes:"GPS Bounding Box (Lat N, Lng E, Lat S, Lng W)"`
|
||||
S2 string `form:"s2" notes:"S2 Position (Cell ID)"`
|
||||
OLC string `form:"olc" notes:"Open Location Code (OLC)"`
|
||||
Olc string `form:"olc" notes:"Open Location Code (OLC)"`
|
||||
Fmin float32 `form:"fmin" notes:"F-number (min)"`
|
||||
Fmax float32 `form:"fmax" notes:"F-number (max)"`
|
||||
Chroma int16 `form:"chroma" example:"chroma:70" notes:"Chroma (0-100)"`
|
||||
|
|
|
@ -45,9 +45,9 @@ type SearchPhotosGeo struct {
|
|||
Lat float32 `form:"lat" notes:"GPS Position (Latitude)"`
|
||||
Lng float32 `form:"lng" notes:"GPS Position (Longitude)"`
|
||||
Dist uint `form:"dist" example:"dist:5" notes:"Distance to GPS Position (km)"`
|
||||
LatLng string `form:"latlng" notes:"GPS Bounding Box (Lat N, Lng E, Lat S, Lng W)"`
|
||||
Latlng string `form:"latlng" notes:"GPS Bounding Box (Lat N, Lng E, Lat S, Lng W)"`
|
||||
S2 string `form:"s2" notes:"S2 Position (Cell ID)"`
|
||||
OLC string `form:"olc" notes:"Open Location Code (OLC)"`
|
||||
Olc string `form:"olc" notes:"Open Location Code (OLC)"`
|
||||
Person string `form:"person"` // Alias for Subject
|
||||
Subjects string `form:"subjects"` // Text
|
||||
People string `form:"people"` // Alias for Subjects
|
||||
|
|
|
@ -628,19 +628,21 @@ func searchPhotos(f form.SearchPhotos, sess *entity.Session, resultCols string)
|
|||
s = s.Where("photos.photo_f_number <= ?", f.Fmax)
|
||||
}
|
||||
|
||||
// Filter by location.
|
||||
// Filter by location code.
|
||||
if f.S2 != "" {
|
||||
// S2 Cell ID.
|
||||
s2Min, s2Max := s2.PrefixedRange(f.S2, S2Levels)
|
||||
s = s.Where("photos.cell_id BETWEEN ? AND ?", s2Min, s2Max)
|
||||
} else if f.OLC != "" {
|
||||
} else if f.Olc != "" {
|
||||
// Open Location Code (OLC).
|
||||
s2Min, s2Max := s2.PrefixedRange(pluscode.S2(f.OLC), S2Levels)
|
||||
s2Min, s2Max := s2.PrefixedRange(pluscode.S2(f.Olc), S2Levels)
|
||||
s = s.Where("photos.cell_id BETWEEN ? AND ?", s2Min, s2Max)
|
||||
} else if latNorth, lngEast, latSouth, lngWest, parseErr := clean.GPSBounds(f.LatLng); parseErr == nil {
|
||||
// GPS Bounds (Lat N, Lng E, Lat S, Lng W).
|
||||
s = s.Where("photos.photo_lat BETWEEN ? AND ?", latNorth, latSouth)
|
||||
s = s.Where("photos.photo_lng BETWEEN ? AND ?", lngEast, lngWest)
|
||||
}
|
||||
|
||||
// Filter by GPS Bounds (Lat N, Lng E, Lat S, Lng W).
|
||||
if latNorth, lngEast, latSouth, lngWest, parseErr := clean.GPSBounds(f.Latlng); parseErr == nil {
|
||||
s = s.Where("photos.photo_lat BETWEEN ? AND ?", latSouth, latNorth)
|
||||
s = s.Where("photos.photo_lng BETWEEN ? AND ?", lngWest, lngEast)
|
||||
}
|
||||
|
||||
// Filter by approx distance to coordinates.
|
||||
|
|
|
@ -509,19 +509,21 @@ func UserPhotosGeo(f form.SearchPhotosGeo, sess *entity.Session) (results GeoRes
|
|||
s = s.Where("files.file_chroma > 0 AND files.file_chroma <= ?", f.Chroma)
|
||||
}
|
||||
|
||||
// Filter by location.
|
||||
// Filter by location code.
|
||||
if f.S2 != "" {
|
||||
// S2 Cell ID.
|
||||
s2Min, s2Max := s2.PrefixedRange(f.S2, S2Levels)
|
||||
s = s.Where("photos.cell_id BETWEEN ? AND ?", s2Min, s2Max)
|
||||
} else if f.OLC != "" {
|
||||
} else if f.Olc != "" {
|
||||
// Open Location Code (OLC).
|
||||
s2Min, s2Max := s2.PrefixedRange(pluscode.S2(f.OLC), S2Levels)
|
||||
s2Min, s2Max := s2.PrefixedRange(pluscode.S2(f.Olc), S2Levels)
|
||||
s = s.Where("photos.cell_id BETWEEN ? AND ?", s2Min, s2Max)
|
||||
} else if latNorth, lngEast, latSouth, lngWest, parseErr := clean.GPSBounds(f.LatLng); parseErr == nil {
|
||||
// GPS Bounds (Lat N, Lng E, Lat S, Lng W).
|
||||
s = s.Where("photos.photo_lat BETWEEN ? AND ?", latNorth, latSouth)
|
||||
s = s.Where("photos.photo_lng BETWEEN ? AND ?", lngEast, lngWest)
|
||||
}
|
||||
|
||||
// Filter by GPS Bounds (Lat N, Lng E, Lat S, Lng W).
|
||||
if latNorth, lngEast, latSouth, lngWest, parseErr := clean.GPSBounds(f.Latlng); parseErr == nil {
|
||||
s = s.Where("photos.photo_lat BETWEEN ? AND ?", latSouth, latNorth)
|
||||
s = s.Where("photos.photo_lng BETWEEN ? AND ?", lngWest, lngEast)
|
||||
}
|
||||
|
||||
// Filter by approx distance to coordinates.
|
||||
|
|
|
@ -130,7 +130,7 @@ func TestGeo(t *testing.T) {
|
|||
Lat: 1.234,
|
||||
Lng: 4.321,
|
||||
S2: "",
|
||||
OLC: "",
|
||||
Olc: "",
|
||||
Dist: 0,
|
||||
Quality: 0,
|
||||
Review: true,
|
||||
|
@ -158,7 +158,7 @@ func TestGeo(t *testing.T) {
|
|||
Lat: 0,
|
||||
Lng: 0,
|
||||
S2: "",
|
||||
OLC: "",
|
||||
Olc: "",
|
||||
Dist: 0,
|
||||
Quality: 3,
|
||||
Review: false,
|
||||
|
@ -181,7 +181,7 @@ func TestGeo(t *testing.T) {
|
|||
Lat: 0,
|
||||
Lng: 0,
|
||||
S2: "85",
|
||||
OLC: "",
|
||||
Olc: "",
|
||||
Dist: 0,
|
||||
Quality: 0,
|
||||
Review: false,
|
||||
|
@ -204,7 +204,7 @@ func TestGeo(t *testing.T) {
|
|||
Lat: 0,
|
||||
Lng: 0,
|
||||
S2: "",
|
||||
OLC: "9",
|
||||
Olc: "9",
|
||||
Dist: 0,
|
||||
Quality: 0,
|
||||
Review: false,
|
||||
|
|
|
@ -667,9 +667,9 @@ func TestPhotos(t *testing.T) {
|
|||
assert.LessOrEqual(t, 2, len(photos))
|
||||
|
||||
})
|
||||
t.Run("LatLng:33.453431,-180.0,49.519234,180.0", func(t *testing.T) {
|
||||
t.Run("latlng:33.453431,-180.0,49.519234,180.0", func(t *testing.T) {
|
||||
var f form.SearchPhotos
|
||||
f.Query = "LatLng:33.453431,-180.0,49.519234,180.0"
|
||||
f.Query = "latlng:33.453431,-180.0,49.519234,180.0"
|
||||
f.Count = 10
|
||||
f.Offset = 0
|
||||
f.Order = "imported"
|
||||
|
@ -688,9 +688,9 @@ func TestPhotos(t *testing.T) {
|
|||
assert.LessOrEqual(t, 2, len(photos))
|
||||
|
||||
})
|
||||
t.Run("LatLng:0.00,-30.123.0,49.519234,9.1001234", func(t *testing.T) {
|
||||
t.Run("latlng:0.00,-30.123.0,49.519234,9.1001234", func(t *testing.T) {
|
||||
var f form.SearchPhotos
|
||||
f.Query = "LatLng:0.00,-30.123.0,49.519234,9.1001234"
|
||||
f.Query = "latlng:0.00,-30.123.0,49.519234,9.1001234"
|
||||
f.Count = 10
|
||||
f.Offset = 0
|
||||
f.Order = "imported"
|
||||
|
|
|
@ -2,17 +2,33 @@ package clean
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
||||
// gpsCeil converts a GPS coordinate to a rounded float32 for use in queries.
|
||||
func gpsCeil(f float64) float32 {
|
||||
return float32((math.Ceil(f*10000) / 10000) + 0.0001)
|
||||
}
|
||||
|
||||
// gpsFloor converts a GPS coordinate to a rounded float32 for use in queries.
|
||||
func gpsFloor(f float64) float32 {
|
||||
return float32((math.Floor(f*10000) / 10000) - 0.0001)
|
||||
}
|
||||
|
||||
// GPSBounds parses the GPS bounds (Lat N, Lng E, Lat S, Lng W) and returns the coordinates if any.
|
||||
func GPSBounds(bounds string) (latNorth, lngEast, latSouth, lngWest float32, err error) {
|
||||
func GPSBounds(bounds string) (latN, lngE, latS, lngW float32, err error) {
|
||||
// Bounds string not long enough?
|
||||
if len(bounds) < 7 {
|
||||
return 0, 0, 0, 0, fmt.Errorf("no coordinates found")
|
||||
}
|
||||
|
||||
// Trim whitespace and invalid characters.
|
||||
bounds = strings.Trim(bounds, " |\\<>\n\r\t\"'#$%!^*()[]{}")
|
||||
|
||||
// Split string into values.
|
||||
values := strings.SplitN(bounds, ",", 5)
|
||||
found := len(values)
|
||||
|
||||
|
@ -22,7 +38,7 @@ func GPSBounds(bounds string) (latNorth, lngEast, latSouth, lngWest float32, err
|
|||
}
|
||||
|
||||
// Parse floating point coordinates.
|
||||
latNorth, lngEast, latSouth, lngWest = txt.Float32(values[0]), txt.Float32(values[1]), txt.Float32(values[2]), txt.Float32(values[3])
|
||||
latNorth, lngEast, latSouth, lngWest := txt.Float(values[0]), txt.Float(values[1]), txt.Float(values[2]), txt.Float(values[3])
|
||||
|
||||
// Latitudes (from +90 to -90 degrees).
|
||||
if latNorth > 90 {
|
||||
|
@ -37,11 +53,12 @@ func GPSBounds(bounds string) (latNorth, lngEast, latSouth, lngWest float32, err
|
|||
latSouth = -90
|
||||
}
|
||||
|
||||
if latNorth > latSouth {
|
||||
// latSouth must be smaller.
|
||||
if latSouth > latNorth {
|
||||
latNorth, latSouth = latSouth, latNorth
|
||||
}
|
||||
|
||||
// Longitudes (from -180 to 180 degrees).
|
||||
// Longitudes (from -180 to +180 degrees).
|
||||
if lngEast > 180 {
|
||||
lngEast = 180
|
||||
} else if lngEast < -180 {
|
||||
|
@ -54,9 +71,11 @@ func GPSBounds(bounds string) (latNorth, lngEast, latSouth, lngWest float32, err
|
|||
lngWest = -180
|
||||
}
|
||||
|
||||
if lngEast > lngWest {
|
||||
// lngWest must be smaller.
|
||||
if lngWest > lngEast {
|
||||
lngEast, lngWest = lngWest, lngEast
|
||||
}
|
||||
|
||||
return latNorth, lngEast, latSouth, lngWest, nil
|
||||
// Return rounded coordinates.
|
||||
return gpsCeil(latNorth), gpsCeil(lngEast), gpsFloor(latSouth), gpsFloor(lngWest), nil
|
||||
}
|
||||
|
|
|
@ -9,26 +9,26 @@ import (
|
|||
func TestGPSBounds(t *testing.T) {
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
latNorth, lngEast, latSouth, lngWest, err := GPSBounds("41.87760543823242,-87.62521362304688,41.89404296875,-87.6215591430664")
|
||||
assert.Equal(t, float32(41.87760543823242), latNorth)
|
||||
assert.Equal(t, float32(-87.62521362304688), lngEast)
|
||||
assert.Equal(t, float32(41.89404296875), latSouth)
|
||||
assert.Equal(t, float32(-87.6215591430664), lngWest)
|
||||
assert.Equal(t, float32(41.8942), latNorth)
|
||||
assert.Equal(t, float32(41.8775), latSouth)
|
||||
assert.Equal(t, float32(-87.6254), lngWest)
|
||||
assert.Equal(t, float32(-87.6214), lngEast)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("FlippedLat", func(t *testing.T) {
|
||||
latNorth, lngEast, latSouth, lngWest, err := GPSBounds("41.89404296875,-87.62521362304688,41.87760543823242,-87.6215591430664")
|
||||
assert.Equal(t, float32(41.87760543823242), latNorth)
|
||||
assert.Equal(t, float32(-87.62521362304688), lngEast)
|
||||
assert.Equal(t, float32(41.89404296875), latSouth)
|
||||
assert.Equal(t, float32(-87.6215591430664), lngWest)
|
||||
assert.Equal(t, float32(41.8942), latNorth)
|
||||
assert.Equal(t, float32(41.8775), latSouth)
|
||||
assert.Equal(t, float32(-87.6254), lngWest)
|
||||
assert.Equal(t, float32(-87.6214), lngEast)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("FlippedLng", func(t *testing.T) {
|
||||
latNorth, lngEast, latSouth, lngWest, err := GPSBounds("41.87760543823242,-87.6215591430664,41.89404296875,-87.62521362304688")
|
||||
assert.Equal(t, float32(41.87760543823242), latNorth)
|
||||
assert.Equal(t, float32(-87.62521362304688), lngEast)
|
||||
assert.Equal(t, float32(41.89404296875), latSouth)
|
||||
assert.Equal(t, float32(-87.6215591430664), lngWest)
|
||||
assert.Equal(t, float32(41.8942), latNorth)
|
||||
assert.Equal(t, float32(41.8775), latSouth)
|
||||
assert.Equal(t, float32(-87.6254), lngWest)
|
||||
assert.Equal(t, float32(-87.6214), lngEast)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("Empty", func(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue