diff --git a/src/app/404/404.component.html b/src/app/404/404.component.html deleted file mode 100644 index ffa6f66..0000000 --- a/src/app/404/404.component.html +++ /dev/null @@ -1 +0,0 @@ -

404

diff --git a/src/app/404/404.component.ts b/src/app/404/404.component.ts deleted file mode 100644 index f7e6dd3..0000000 --- a/src/app/404/404.component.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {Component} from "@angular/core"; - -@Component({ - selector: 'not-found', - templateUrl: '404.component.html' -}) -export class NotFoundComponent { - -} diff --git a/src/app/geolocation/geolocation.service.ts b/src/app/geolocation/geolocation.service.ts deleted file mode 100644 index 2edbd8c..0000000 --- a/src/app/geolocation/geolocation.service.ts +++ /dev/null @@ -1,51 +0,0 @@ -import {Injectable, OnDestroy} from '@angular/core'; -import {BehaviorSubject} from "rxjs"; -import {MatSnackBar} from "@angular/material"; - -@Injectable({ - providedIn: 'root' -}) -export class GeolocationService implements OnDestroy { - private readonly watchRegistrationID; - private orientation: DeviceOrientationEvent; - - location = new BehaviorSubject(null); - - constructor(snackBar: MatSnackBar) { - window.addEventListener('deviceorientation', (orientation) => this.orientation = orientation, true); - - if(navigator.geolocation) { - this.watchRegistrationID = navigator.geolocation.watchPosition(pos => { - this.location.next({ - accuracy: pos.coords.accuracy, - altitude: pos.coords.altitude, - altitudeAccuracy: pos.coords.altitudeAccuracy, - heading: pos.coords.heading || this.orientation.alpha, - latitude: pos.coords.latitude, - longitude: pos.coords.longitude, - speed: pos.coords.speed - }); - }, (error) => { - switch(error.code) { - case error.PERMISSION_DENIED: - snackBar.open('Geolocation permission denied', null, {duration: 3000, horizontalPosition: 'right', panelClass: ['bg-warning', 'text-white']}); - break; - case error.POSITION_UNAVAILABLE: - snackBar.open('Geolocation unavailable', null, {duration: 3000, horizontalPosition: 'right', panelClass: ['bg-warning', 'text-white']}); - break; - case error.TIMEOUT: - snackBar.open('Geolocation timeout', null, {duration: 3000, horizontalPosition: 'right', panelClass: ['bg-warning', 'text-white']}); - break; - default: - snackBar.open('Geolocation experienced an unknown error', null, {duration: 3000, horizontalPosition: 'right', panelClass: ['bg-warning', 'text-white']}); - } - }, {enableHighAccuracy: true}); - } else { - snackBar.open('Geolocation is not supported', null, {duration: 3000, horizontalPosition: 'right', panelClass: ['bg-warning', 'text-white']}); - } - } - - ngOnDestroy() { - if(this.watchRegistrationID) navigator.geolocation.clearWatch(this.watchRegistrationID); - } -} diff --git a/src/app/map/map.component.html b/src/app/map/map.component.html index a2f1176..aee5c09 100644 --- a/src/app/map/map.component.html +++ b/src/app/map/map.component.html @@ -32,7 +32,7 @@
Heading: No Heading - {{position.heading | number : '0.0'}}° + {{position.heading | number : '0.0-0'}}°
Latitude: {{position.latitude | number : '0.0-5'}}
@@ -40,11 +40,11 @@
Altitude: No Altitude - {{position.altitude | number : '0.0'}} m + {{position.altitude | number : '0.0-0'}} m
Speed: No Speed - {{position.speed * 60 * 60 / 1000 | number : '1.1'}} km/h + {{position.speed * 60 * 60 / 1000 | number : '1.0-1'}} km/h
diff --git a/src/app/map/map.component.ts b/src/app/map/map.component.ts index 3348c22..a7d10a0 100644 --- a/src/app/map/map.component.ts +++ b/src/app/map/map.component.ts @@ -1,5 +1,5 @@ import {Component} from "@angular/core"; -import {GeolocationService} from "../geolocation/geolocation.service"; +import {PhysicsService} from "../physics/physics.service"; import {filter} from "rxjs/operators"; import {version} from "../../../package.json"; import {BreakpointObserver, Breakpoints} from "@angular/cdk/layout"; @@ -22,9 +22,9 @@ export class MapComponent { style: 'satellite' | 'terrain' | 'roadmap' | 'hybrid' = 'terrain'; version = version; - constructor(bpObserver: BreakpointObserver, geolocation: GeolocationService) { + constructor(bpObserver: BreakpointObserver, physicsService: PhysicsService) { bpObserver.observe([Breakpoints.Handset]).subscribe(results => this.mobile = results.matches); - geolocation.location.pipe(filter(coord => !!coord)).subscribe(pos => { + physicsService.info.pipe(filter(coord => !!coord)).subscribe(pos => { if(this.mapApi) { console.log(pos); if(!this.position) this.center(pos); diff --git a/src/app/physics/physics.service.ts b/src/app/physics/physics.service.ts new file mode 100644 index 0000000..ae5b37f --- /dev/null +++ b/src/app/physics/physics.service.ts @@ -0,0 +1,49 @@ +import {Injectable} from '@angular/core'; +import {BehaviorSubject, combineLatest} from "rxjs"; + +@Injectable({ + providedIn: 'root' +}) +export class PhysicsService { + private motionTimestamp; + + info = new BehaviorSubject(null); + motion = new BehaviorSubject(null); + speed = new BehaviorSubject(null); + orientation = new BehaviorSubject(null); + position = new BehaviorSubject(null); + + constructor() { + // Gather physical data + window.addEventListener('deviceorientation', orientation => this.orientation.next(orientation)); + window.addEventListener('devicemotion', motion => this.motion.next(motion)); + navigator.geolocation.watchPosition(pos => this.position.next(pos.coords)); + + // Calculate speed from motion events + this.motion.subscribe(event => { + if (!this.motionTimestamp) return this.motionTimestamp = new Date().getTime(); + + let currentTime = new Date().getTime(); + let {speedX, speedY, speedZ} = this.speed.value; + this.speed.next({ + speedX: speedX + event.acceleration.x / 1000 * ((currentTime - this.motionTimestamp) / 1000) / 3600, + speedY: speedY + event.acceleration.y / 1000 * ((currentTime - this.motionTimestamp) / 1000) / 3600, + speedZ: speedZ + event.acceleration.z / 1000 * ((currentTime - this.motionTimestamp) / 1000) / 3600 + }); + this.motionTimestamp = currentTime; + }); + + // Combine data into one nice package + combineLatest(this.position, this.orientation, this.speed).subscribe(data => { + this.info.next({ + accuracy: data[0].accuracy, + altitude: data[0].altitude, + altitudeAccuracy: data[0].altitudeAccuracy, + heading: data[0].heading || data[1].alpha, + latitude: data[0].latitude, + longitude: data[0].longitude, + speed: data[0].speed || Math.sqrt(data[2].x**2 + data[2].y**2 + data[2].z**2), + }); + }) + } +}