Feature: first working version of inspecting 360° images

This commit is contained in:
Pieter Vander Vennet 2025-03-30 03:10:29 +02:00
parent 7d104b4266
commit 01ba98a820
24 changed files with 330 additions and 436 deletions

View file

@ -7,8 +7,6 @@ import { BBox } from "../BBox"
import Constants from "../../Models/Constants"
import { Utils } from "../../Utils"
import { Point } from "geojson"
import MvtSource from "../FeatureSource/Sources/MvtSource"
import AllImageProviders from "../ImageProviders/AllImageProviders"
import { Imgur } from "../ImageProviders/Imgur"
import { Panoramax, PanoramaxXYZ } from "panoramax-js/dist"
@ -211,111 +209,6 @@ class ImagesFromPanoramaxFetcher implements ImageFetcher {
}
}
class ImagesFromCacheServerFetcher implements ImageFetcher {
private readonly _searchRadius: number
public readonly name = "fromCacheServer"
private readonly _serverUrl: string
constructor(searchRadius: number = 500, serverUrl: string = Constants.VectorTileServer) {
this._searchRadius = searchRadius
this._serverUrl = serverUrl
}
async fetchImages(lat: number, lon: number): Promise<P4CPicture[]> {
return (
await Promise.all([
this.fetchImagesForType(lat, lon, "lines"),
this.fetchImagesForType(lat, lon, "pois"),
this.fetchImagesForType(lat, lon, "polygons"),
])
).flatMap((x) => x)
}
async fetchImagesForType(
targetlat: number,
targetlon: number,
type: "lines" | "pois" | "polygons"
): Promise<P4CPicture[]> {
const { x, y, z } = Tiles.embedded_tile(targetlat, targetlon, 14)
const url = this._serverUrl
async function getFeatures(x: number, y: number) {
const src = new MvtSource(
Utils.SubstituteKeys(url, {
type,
x,
y,
z,
layer: "item_with_image",
}),
x,
y,
z
)
await src.updateAsync()
return src.features.data
}
const features = (
await Promise.all([
getFeatures(x, y),
getFeatures(x, y + 1),
getFeatures(x, y - 1),
getFeatures(x + 1, y + 1),
getFeatures(x + 1, y),
getFeatures(x + 1, y - 1),
getFeatures(x - 1, y - 1),
getFeatures(x - 1, y),
getFeatures(x - 1, y + 1),
])
).flatMap((x) => x)
const pics: P4CPicture[] = []
for (const f of features) {
const [lng, lat] = GeoOperations.centerpointCoordinates(f)
if (
GeoOperations.distanceBetween([targetlon, targetlat], [lng, lat]) >
this._searchRadius
) {
return []
}
for (let i = -1; i < 50; i++) {
let key = "image"
if (i >= 0) {
key += ":" + i
}
const v = f.properties[key]
console.log(v)
if (!v) {
continue
}
let provider = "unkown"
try {
provider = (await AllImageProviders.selectBestProvider("image", v))?.name
} catch (e) {
console.error("Could not detect provider for", "image", v)
}
pics.push({
pictureUrl: v,
coordinates: { lat, lng },
details: {
isSpherical: false,
},
osmTags: {
image: v,
},
thumbUrl: v,
provider,
})
}
}
return pics
}
}
class MapillaryFetcher implements ImageFetcher {
public readonly name = "mapillary_new"
private readonly _panoramas: "only" | "no" | undefined
@ -390,7 +283,7 @@ class MapillaryFetcher implements ImageFetcher {
mapillary: img.id,
},
details: {
isSpherical: img.is_pano,
isSpherical: this._panoramas === "only"
},
})
}
@ -407,15 +300,20 @@ export class CombinedFetcher {
constructor(radius: number, maxage: Date, indexedFeatures: IndexedFeatureSource) {
this.sources = [
new ImagesInLoadedDataFetcher(indexedFeatures, radius),
new ImagesFromCacheServerFetcher(radius),
new ImagesFromPanoramaxFetcher(),
new ImagesFromPanoramaxFetcher(Constants.panoramax.url),
// For mapillary, we need to query both with and without panoramas. See https://www.mapillary.com/developer/api-documentation/
new MapillaryFetcher({
max_images: 25,
start_captured_at: maxage,
panoramas: "only"
}),
new P4CImageFetcher("mapillary"),
new P4CImageFetcher("wikicommons"),
new MapillaryFetcher({
max_images: 25,
start_captured_at: maxage,
panoramas: "no"
}), new P4CImageFetcher("mapillary"),
new P4CImageFetcher("wikicommons")
].map((f) => new CachedFetcher(f))
}