| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  | import "pannellum" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  | import { Feature, Geometry, Point } from "geojson" | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  | import { GeoOperations } from "../../Logic/GeoOperations" | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  | import { HotspotProperties, PanoramaView } from "../../Logic/ImageProviders/ImageProvider" | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class PhotoSphereViewerWrapper { | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |     private imageInfo: Feature<Point, PanoramaView> | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  |     private readonly viewer: Pannellum.Viewer | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |     private nearbyFeatures: Feature<Geometry, HotspotProperties>[] = [] | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |     constructor( | 
					
						
							|  |  |  |         container: HTMLElement, | 
					
						
							|  |  |  |         imageInfo: Feature<Point, PanoramaView>, | 
					
						
							|  |  |  |         nearbyFeatures?: Feature<Geometry, HotspotProperties>[] | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |         this.imageInfo = imageInfo | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |         this.viewer = pannellum.viewer(container, <any>{ | 
					
						
							|  |  |  |             default: { | 
					
						
							|  |  |  |                 firstScene: imageInfo.properties.url, | 
					
						
							|  |  |  |                 sceneFadeDuration: 250, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             scenes: { | 
					
						
							|  |  |  |                 [imageInfo.properties.url]: { | 
					
						
							|  |  |  |                     type: "equirectangular", | 
					
						
							|  |  |  |                     hfov: 110, | 
					
						
							|  |  |  |                     panorama: imageInfo.properties.url, | 
					
						
							|  |  |  |                     autoLoad: true, | 
					
						
							|  |  |  |                     hotSpots: [], | 
					
						
							|  |  |  |                     sceneFadeDuration: 250, | 
					
						
							|  |  |  |                     compass: true, | 
					
						
							|  |  |  |                     showControls: false, | 
					
						
							|  |  |  |                     northOffset: imageInfo.properties.northOffset, | 
					
						
							|  |  |  |                     horizonPitch: imageInfo.properties.pitchOffset, | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         this.setNearbyFeatures(nearbyFeatures) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |     public calculatePitch(feature: Feature): number { | 
					
						
							|  |  |  |         const coors = this.imageInfo.geometry.coordinates | 
					
						
							|  |  |  |         const distance = GeoOperations.distanceBetween( | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |             <[number, number]>coors, | 
					
						
							|  |  |  |             GeoOperations.centerpointCoordinates(feature) | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // In: -pi/2 up to pi/2
 | 
					
						
							|  |  |  |         const alpha = Math.atan(distance / 4) // in radians
 | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |         const degrees = (alpha * 360) / (2 * Math.PI) | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |         return -degrees | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private setPanorama(imageInfo: Feature<Point, PanoramaView>) { | 
					
						
							|  |  |  |         if (this.viewer?.getScene() === imageInfo?.properties?.url) { | 
					
						
							|  |  |  |             // Already the current scene
 | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         this.clearHotspots() | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  |         this.imageInfo = imageInfo | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |         this.viewer.addScene(imageInfo.properties.url, <any>{ | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  |             panorama: imageInfo.properties.url, | 
					
						
							|  |  |  |             northOffset: imageInfo.properties.northOffset, | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |             type: "equirectangular", | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |         this.viewer.loadScene(imageInfo.properties.url, 0, imageInfo.properties.northOffset) | 
					
						
							|  |  |  |         this.setNearbyFeatures(this.nearbyFeatures) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |     private clearHotspots() { | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |         const hotspots = | 
					
						
							|  |  |  |             this.viewer.getConfig()["scenes"][this.imageInfo.properties.url].hotSpots ?? [] | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |         for (const hotspot of hotspots) { | 
					
						
							|  |  |  |             this.viewer.removeHotSpot(hotspot?.id, this.imageInfo.properties.url) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |     public setNearbyFeatures(nearbyFeatures: Feature<Geometry, HotspotProperties>[]) { | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  |         const imageInfo = this.imageInfo | 
					
						
							| 
									
										
										
										
											2025-04-10 04:53:01 +02:00
										 |  |  |         if (!this.imageInfo) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  |         const northOffs = imageInfo.properties.northOffset | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |         this.nearbyFeatures = nearbyFeatures | 
					
						
							|  |  |  |         this.clearHotspots() | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  |         for (const f of nearbyFeatures ?? []) { | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |             if (f.properties.gotoPanorama?.properties?.url === this.imageInfo.properties.url) { | 
					
						
							|  |  |  |                 continue // This is the current panorama, no need to show it
 | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  |             const yaw = GeoOperations.bearing(imageInfo, GeoOperations.centerpoint(f)) | 
					
						
							| 
									
										
										
										
											2025-03-30 19:38:36 +02:00
										 |  |  |             let pitch = 0 | 
					
						
							|  |  |  |             if (f.properties.pitch === "auto") { | 
					
						
							|  |  |  |                 pitch = this.calculatePitch(f) | 
					
						
							|  |  |  |             } else if (!isNaN(f.properties.pitch)) { | 
					
						
							|  |  |  |                 pitch = f.properties.pitch | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-04-15 18:18:44 +02:00
										 |  |  |             this.viewer.addHotSpot( | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     type: f.properties.gotoPanorama !== undefined ? "scene" : "info", | 
					
						
							|  |  |  |                     yaw: (yaw - northOffs) % 360, | 
					
						
							|  |  |  |                     pitch, | 
					
						
							|  |  |  |                     text: f.properties.name, | 
					
						
							|  |  |  |                     clickHandlerFunc: () => { | 
					
						
							|  |  |  |                         this.setPanorama(f.properties.gotoPanorama) | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 this.imageInfo.properties.url | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2025-03-30 03:16:36 +02:00
										 |  |  |             if (f.properties.focus) { | 
					
						
							|  |  |  |                 this.viewer.setYaw(yaw - northOffs) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-03-30 03:10:29 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |