Feature: add provider to photosphereview

This commit is contained in:
Pieter Vander Vennet 2025-06-05 11:40:56 +02:00
parent 236d4d87da
commit b269d210bb
5 changed files with 19 additions and 12 deletions

View file

@ -36,6 +36,7 @@ export interface PanoramaView {
*/ */
northOffset?: number northOffset?: number
pitchOffset?: number pitchOffset?: number
provider: ImageProvider | string
} }
/** /**
@ -124,7 +125,7 @@ export default abstract class ImageProvider {
public abstract DownloadAttribution(providedImage: { public abstract DownloadAttribution(providedImage: {
url: string url: string
id: string id?: string
}): Promise<LicenseInfo> }): Promise<LicenseInfo>
public abstract apiUrls(): string[] public abstract apiUrls(): string[]

View file

@ -169,6 +169,8 @@ export class Mapillary extends ImageProvider {
properties: { properties: {
url: response.thumb_2048_url, url: response.thumb_2048_url,
northOffset: response.computed_compass_angle, northOffset: response.computed_compass_angle,
provider: this,
imageMeta: <any>image
}, },
} }
} }

View file

@ -208,8 +208,8 @@ export default class PanoramaxImageProvider extends ImageProvider {
} }
public async DownloadAttribution(providedImage: { public async DownloadAttribution(providedImage: {
url: string id: string,
id: string url: string // Actually not used
}): Promise<LicenseInfo> { }): Promise<LicenseInfo> {
const meta = await this.getInfoFor(providedImage.id) const meta = await this.getInfoFor(providedImage.id)
@ -245,10 +245,12 @@ export default class PanoramaxImageProvider extends ImageProvider {
return <Feature<Point, PanoramaView>>{ return <Feature<Point, PanoramaView>>{
type: "Feature", type: "Feature",
geometry: imageInfo.geometry, geometry: imageInfo.geometry,
properties: { properties: <PanoramaView>{
url, url,
northOffset, northOffset,
pitchOffset, pitchOffset,
provider: this,
imageMeta: imageInfo
}, },
} }
} }

View file

@ -17,7 +17,7 @@ interface ImageFetcher {
* @param lat * @param lat
* @param lon * @param lon
*/ */
fetchImages(lat: number, lon: number): Promise<P4CPicture[]> fetchImages(lat: number, lon: number): Promise<(P4CPicture & { id: string })[]>
readonly name: string readonly name: string
} }
@ -25,7 +25,7 @@ interface ImageFetcher {
class CachedFetcher implements ImageFetcher { class CachedFetcher implements ImageFetcher {
private readonly _fetcher: ImageFetcher private readonly _fetcher: ImageFetcher
private readonly _zoomlevel: number private readonly _zoomlevel: number
private readonly cache: Map<number, Promise<P4CPicture[]>> = new Map< private readonly cache: Map<number, Promise<(P4CPicture & { id: string })[]>> = new Map<
number, number,
Promise<P4CPicture[]> Promise<P4CPicture[]>
>() >()
@ -37,7 +37,7 @@ class CachedFetcher implements ImageFetcher {
this.name = fetcher.name this.name = fetcher.name
} }
fetchImages(lat: number, lon: number): Promise<P4CPicture[]> { fetchImages(lat: number, lon: number): Promise<(P4CPicture & { id: string })[]> {
const tile = Tiles.embedded_tile(lat, lon, this._zoomlevel) const tile = Tiles.embedded_tile(lat, lon, this._zoomlevel)
const tileIndex = Tiles.tile_index(tile.z, tile.x, tile.y) const tileIndex = Tiles.tile_index(tile.z, tile.x, tile.y)
if (this.cache.has(tileIndex)) { if (this.cache.has(tileIndex)) {
@ -80,7 +80,7 @@ class NearbyImageUtils {
} }
class P4CImageFetcher implements ImageFetcher { class P4CImageFetcher implements ImageFetcher {
public static readonly services = ["mapillary", "flickr", "kartaview", "wikicommons"] as const public static readonly services = ["flickr", "kartaview", "wikicommons"] as const
public static readonly apiUrls = ["https://api.flickr.com"] public static readonly apiUrls = ["https://api.flickr.com"]
private _options: { maxDaysOld: number; searchRadius: number } private _options: { maxDaysOld: number; searchRadius: number }
public readonly name: P4CService public readonly name: P4CService
@ -90,7 +90,7 @@ class P4CImageFetcher implements ImageFetcher {
this._options = options this._options = options
} }
async fetchImages(lat: number, lon: number): Promise<P4CPicture[]> { async fetchImages(lat: number, lon: number): Promise<(P4CPicture & { id: string })[]> {
const picManager = new P4C.PicturesManager({ usefetchers: [this.name] }) const picManager = new P4C.PicturesManager({ usefetchers: [this.name] })
const maxAgeSeconds = (this._options?.maxDaysOld ?? 3 * 365) * 24 * 60 * 60 * 1000 const maxAgeSeconds = (this._options?.maxDaysOld ?? 3 * 365) * 24 * 60 * 60 * 1000
const searchRadius = this._options?.searchRadius ?? 100 const searchRadius = this._options?.searchRadius ?? 100
@ -272,7 +272,7 @@ class MapillaryFetcher implements ImageFetcher {
this.end_captured_at = options?.end_captured_at this.end_captured_at = options?.end_captured_at
} }
async fetchImages(lat: number, lon: number): Promise<P4CPicture[]> { async fetchImages(lat: number, lon: number): Promise<(P4CPicture & { id: string })[]> {
const boundingBox = new BBox([[lon, lat]]).padAbsolute(0.003) const boundingBox = new BBox([[lon, lat]]).padAbsolute(0.003)
let url = let url =
"https://graph.mapillary.com/images?fields=geometry,computed_geometry,creator,id,captured_at,thumb_256_url,thumb_original_url,compass_angle&bbox=" + "https://graph.mapillary.com/images?fields=geometry,computed_geometry,creator,id,captured_at,thumb_256_url,thumb_original_url,compass_angle&bbox=" +
@ -313,7 +313,7 @@ class MapillaryFetcher implements ImageFetcher {
captured_at: number captured_at: number
}[] }[]
}>(url) }>(url)
const pics: P4CPicture[] = [] const pics: (P4CPicture & { id: string })[] = []
for (const img of response.data) { for (const img of response.data) {
const c = img.computed_geometry?.coordinates ?? img.geometry.coordinates const c = img.computed_geometry?.coordinates ?? img.geometry.coordinates
if (img.thumb_original_url === undefined) { if (img.thumb_original_url === undefined) {
@ -322,6 +322,7 @@ class MapillaryFetcher implements ImageFetcher {
const [lon, lat] = img.computed_geometry.coordinates const [lon, lat] = img.computed_geometry.coordinates
pics.push({ pics.push({
pictureUrl: img.thumb_original_url, pictureUrl: img.thumb_original_url,
id: img.id,
provider: "Mapillary", provider: "Mapillary",
coordinates: { lng: c[0], lat: c[1] }, coordinates: { lng: c[0], lat: c[1] },
thumbUrl: img.thumb_256_url, thumbUrl: img.thumb_256_url,
@ -411,7 +412,7 @@ export class CombinedFetcher {
lon: number, lon: number,
lat: number lat: number
): { ): {
images: Store<P4CPicture[]> images: Store<(P4CPicture & { provider })[]>
state: Store<Record<string, "loading" | "done" | "error">> state: Store<Record<string, "loading" | "done" | "error">>
} { } {
const sink = new UIEventSource<P4CPicture[]>([]) const sink = new UIEventSource<P4CPicture[]>([])

View file

@ -68,6 +68,7 @@
northOffset: p4c.direction, northOffset: p4c.direction,
rotation: p4c.direction, rotation: p4c.direction,
spherical: p4c.details.isSpherical ? "yes" : "no", spherical: p4c.details.isSpherical ? "yes" : "no",
provider: p4c.provider
}, },
} }
) )