diff --git a/projects/common-map/src/fm-map/common-map.module.ts b/projects/common-map/src/fm-map/common-map.module.ts index acb8c3c..1db6307 100644 --- a/projects/common-map/src/fm-map/common-map.module.ts +++ b/projects/common-map/src/fm-map/common-map.module.ts @@ -60,6 +60,7 @@ import { LegendComponent } from './components/legend/legend.component'; import { LayerVectorImageComponent } from './components/aol/layer-vector-image/layer-vector-image.component'; import { StateSerializerService } from './services/state-serializer.service'; import { GeolocationService } from './services/geolocation.service'; +import {DeviceOrientationService} from './services/device-orientation.service'; import { localStorageSync } from 'ngrx-store-localstorage'; import { WidgetStatusComponent } from './components/widget-status/widget-status.component'; import { ForChild} from './components/for-item/for-child.decorator'; @@ -114,6 +115,7 @@ export { AbstractItemListComponent, StateSerializerService, GeolocationService, + DeviceOrientationService, IMapState, ISelectedFeatures, IItemLayer, @@ -232,6 +234,7 @@ export class AppCommonMapModule { providers: [ StateSerializerService, GeolocationService, + DeviceOrientationService, { provide: AbstractFeatureListComponent, useClass: FeatureListCroppingschemeComponent, multi: true }, { provide: AbstractFeatureListComponent, useClass: FeatureListCropfieldComponent, multi: true }, { provide: AbstractFeatureListFeatureComponent, useClass: FeatureListFeatureComponent, multi: true }, diff --git a/projects/common-map/src/fm-map/components/aol/gps-location/gps-location.component.ts b/projects/common-map/src/fm-map/components/aol/gps-location/gps-location.component.ts index fa366fe..815d9e2 100644 --- a/projects/common-map/src/fm-map/components/aol/gps-location/gps-location.component.ts +++ b/projects/common-map/src/fm-map/components/aol/gps-location/gps-location.component.ts @@ -62,7 +62,9 @@ export class GpsLocation implements OnInit,OnChanges{ this.instance.setPosition(fromLonLat([p.coords.longitude, p.coords.latitude])); this.locationTolerance = p.coords.accuracy; this.recalcLocationTolerance(); - this.heading = p.coords.heading; + } + if(changes.heading && this.instance) { + this.rotate = "rotate(" + Math.round(changes.heading.currentValue) + " 500 500)"; } } } diff --git a/projects/common-map/src/fm-map/components/map/map.component.html b/projects/common-map/src/fm-map/components/map/map.component.html index 39d1306..2b1aad5 100644 --- a/projects/common-map/src/fm-map/components/map/map.component.html +++ b/projects/common-map/src/fm-map/components/map/map.component.html @@ -16,7 +16,8 @@ menuVisible:menuVisible$|async, searchCollapsed:searchCollapsed$|async, clearEnabled:clearEnabled$|async, - period:period$|async + period:period$|async, + compassHeading:compassHeading$|async } as state">
@@ -34,7 +35,7 @@ - +
diff --git a/projects/common-map/src/fm-map/components/map/map.component.ts b/projects/common-map/src/fm-map/components/map/map.component.ts index 714023b..05159c3 100644 --- a/projects/common-map/src/fm-map/components/map/map.component.ts +++ b/projects/common-map/src/fm-map/components/map/map.component.ts @@ -18,6 +18,7 @@ import { IDroppedFile } from '../aol/file-drop-target/file-drop-target.component import { IMetaData } from '../meta-data-modal/meta-data-modal.component'; import { StateSerializerService } from '../../services/state-serializer.service'; import { GeolocationService} from '../../services/geolocation.service'; +import {DeviceOrientationService} from '../../services/device-orientation.service'; // AppCommon import { ResumableFileUploadService, ItemTypeService } from '@farmmaps/common'; @@ -69,6 +70,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { public menuVisible$: Observable; public query$: Observable; public position$: Observable; + public compassHeading$: Observable; public baseLayersCollapsed:boolean = true; public overlayLayersCollapsed: boolean = true; public extent$: Observable; @@ -82,7 +84,8 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { public itemTypeService: ItemTypeService, private location: Location, private geolocationService: GeolocationService, - private zone: NgZone) { + private zone: NgZone, + private deviceorientationService:DeviceOrientationService) { } @HostListener('document:keyup', ['$event']) @@ -143,6 +146,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { this.selectedItemLayer$ = this.store.select(mapReducers.selectGetSelectedItemLayer); this.period$ = this.store.select(mapReducers.selectGetPeriod); this.position$ = this.geolocationService.getCurrentPosition(); + this.compassHeading$ = this.deviceorientationService.getCurrentCompassHeading(); this.mapState$.pipe(withLatestFrom(this.queryState$)).subscribe((state) => { this.replaceUrl(state[0], state[1], true); diff --git a/projects/common-map/src/fm-map/services/device-orientation.service.ts b/projects/common-map/src/fm-map/services/device-orientation.service.ts index 7959fea..0bc2f52 100644 --- a/projects/common-map/src/fm-map/services/device-orientation.service.ts +++ b/projects/common-map/src/fm-map/services/device-orientation.service.ts @@ -5,19 +5,43 @@ import { Observer, Observable } from 'rxjs'; @Injectable() export class DeviceOrientationService { - /** - * Tries HTML5 geolocation. - * - * Wraps the Geolocation API into an observable. - * - * @return An observable of Bearing - */ - getCurrentBearing(): Observable { - return Observable.create((observer: Observer) => { - let sensor = new Magnetometer(); - sensor.onreading= (ev:Event) => { - observer.next(Math.atan2(sensor.y, sensor.x) * (180 / Math.PI)); - }; + compassHeading(alpha, beta, gamma):number { + + // Convert degrees to radians + var alphaRad = alpha * (Math.PI / 180); + var betaRad = beta * (Math.PI / 180); + var gammaRad = gamma * (Math.PI / 180); + + // Calculate equation components + var cA = Math.cos(alphaRad); + var sA = Math.sin(alphaRad); + var cB = Math.cos(betaRad); + var sB = Math.sin(betaRad); + var cG = Math.cos(gammaRad); + var sG = Math.sin(gammaRad); + + // Calculate A, B, C rotation components + var rA = - cA * sG - sA * sB * cG; + var rB = - sA * sG + cA * sB * cG; + var rC = - cB * cG; + + // Calculate compass heading + var compassHeading = Math.atan(rA / rB); + + // Convert from half unit circle to whole unit circle + if(rB < 0) { + compassHeading += Math.PI; + }else if(rA < 0) { + compassHeading += 2 * Math.PI; + } + return compassHeading * (180/Math.PI); + } + + getCurrentCompassHeading(): Observable { + return Observable.create((observer: Observer) => { + window.addEventListener("deviceorientation", (event:DeviceOrientationEvent)=>{ + observer.next(this.compassHeading(event.alpha,event.beta,event.gamma)); + } ); }); }