import VectorLayer from 'ol/layer/Vector' ; import VectorSource from 'ol/source/Vector' ; import { Draw } from 'ol/interaction' ; import { Feature } from 'ol' ; import { Fill , Stroke , Style } from 'ol/style' ; import { Geometry , LineString , Polygon } from 'ol/geom' ; import { Injectable } from '@angular/core' ; import { HsEventBusService } from '../core/event-bus.service' ; import { HsMapService } from '../map/map.service' ; import { HsUtilsService , Measurement } from '../utils/utils.service' ; import { setTitle } from '../../common/layer-extensions' ; @ Injectable ( { providedIn : 'root' , } ) export class HsMeasureService { map ; draw : Draw ; data = { measurements : [ ] , multipleShapeMode : false , } ; property sketches : Feature < Geometry > [ ] = [ ] ; lastMeasurementId : number ; measureVector = new VectorLayer ( { source : new VectorSource ( ) , style : new Style ( { fill : new Fill ( { color : 'rgba(255, 255, 255, 0.2)' , } ) , stroke : new Stroke ( { color : '#ffcc33' , width : 2 , } ) , } ) , } ) ; constructor ( public HsMapService , public HsUtilsService , public HsEventBusService ) { setTitle ( this . measureVector , 'Measurement sketches' ) ; HsMapService . loaded ( ) . then ( ( m ) => { this . map = m ; } ) ; } public param { boolean ? } mode description switchMultipleMode ( mode ? ) { if ( mode !== undefined ) { this . data . multipleShapeMode = mode ; } else { this . data . multipleShapeMode = ! this . data . multipleShapeMode ; } } public param { string } type description changeMeasureParams ( type ) { this . map . removeInteraction ( this . draw ) ; this . sketches = [ ] ; this . addInteraction ( type ) ; } public description clearMeasurement ( ) { this . draw . setActive ( false ) ; this . data . measurements = [ ] ; this . measureVector . getSource ( ) . clear ( ) ; this . sketches = [ ] ; this . draw . setActive ( true ) ; } public param type description activateMeasuring ( type ) { if ( ! this . map ) { setTimeout ( ( ) => { this . activateMeasuring ( type ) ; } , 500 ) ; return ; } this . map . addLayer ( this . measureVector ) ; this . map . getViewport ( ) . addEventListener ( 'mousemove' , ( evt ) => { this . mouseMoveHandler ( evt ) ; } ) ; this . map . getViewport ( ) . addEventListener ( 'touchmove' , ( evt ) => { this . mouseMoveHandler ( evt ) ; } ) ; this . map . getViewport ( ) . addEventListener ( 'touchend' , ( evt ) => { this . mouseMoveHandler ( evt ) ; } ) ; this . addInteraction ( type ) ; } public description deactivateMeasuring ( ) { this . HsMapService . loaded ( ) . then ( ( map ) => { map . getViewport ( ) . removeEventListener ( 'mousemove' , ( evt ) => { this . mouseMoveHandler ( evt ) ; } ) ; map . getViewport ( ) . removeEventListener ( 'touchmove' , ( evt ) => { this . mouseMoveHandler ( evt ) ; } ) ; map . getViewport ( ) . removeEventListener ( 'touchend' , ( evt ) => { this . mouseMoveHandler ( evt ) ; } ) ; map . removeInteraction ( this . draw ) ; map . removeLayer ( this . measureVector ) ; } ) ; this . HsEventBusService . measurementEnds . next ( ) ; } private param { object } evt description mouseMoveHandler ( evt ) { if ( this . sketches . length > 0 ) { let output ; for ( const sketch of this . sketches ) { const geom = sketch . getGeometry ( ) ; if ( this . HsUtilsService . instOf ( geom , Polygon ) ) { output = this . addMultiple ( this . HsUtilsService . formatArea ( geom as Polygon , this . HsMapService . getCurrentProj ( ) ) , output ) ; } else if ( this . HsUtilsService . instOf ( geom , LineString ) ) { output = this . addMultiple ( this . HsUtilsService . formatLength ( geom as LineString , this . HsMapService . getCurrentProj ( ) ) , output ) ; } } setTimeout ( ( ) => { this . data . measurements [ this . lastMeasurementId ] = output ; } , 0 ) ; } } private param { Measurement } val1 param { Measurement } val2 returns { Measurement } description addMultiple ( val1 , val2 ) { if ( val2 == undefined ) { return val1 ; } let unit = val1 . unit ; const type = val1 . type ; let value ; if ( val1 . unit == val2 . unit ) { value = Math . round ( ( val1 . size + val2 . size ) * 100 ) / 100 ; if ( unit == 'm' && type == 'length' && value > 1000 ) { value = Math . round ( ( value / 1000 ) * 100 ) / 100 ; unit = 'km' ; } else if ( unit == 'm' && type == 'area' && value > 10000 ) { value = Math . round ( ( value / 1000000 ) * 100 ) / 100 ; unit = 'km' ; } } else { const arr = [ val1 , val2 ] ; for ( let i = 0 ; i < arr . length ; i ++ ) { if ( arr [ i ] . unit == 'm' ) { type == 'length' ? ( arr [ i ] . size /= 1000 ) : ( arr [ i ] . size /= 1000000 ) ; } } value = Math . round ( ( arr [ 0 ] . size + arr [ 1 ] . size ) * 100 ) / 100 ; unit = 'km' ; } return { size : value , type : type , unit : unit , } ; } private param { string } type description addInteraction ( type ) { const drawType = type == 'area' ? 'Polygon' : 'LineString' ; this . draw = new Draw ( { source : this . measureVector . getSource ( ) , type : drawType , dragVertexDelay : 150 , } ) ; this . map . addInteraction ( this . draw ) ; this . draw . on ( 'drawstart' , ( evt ) => { this . HsEventBusService . measurementStarts . next ( ) ; if ( this . data . multipleShapeMode ) { if ( ! Array . isArray ( this . sketches ) ) { this . sketches = [ ] ; this . data . measurements . push ( { size : 0 , unit : '' , } ) ; } this . sketches . push ( evt . feature ) ; } else { this . sketches = [ evt . feature ] ; this . data . measurements . push ( { size : 0 , unit : '' , } ) ; } this . lastMeasurementId = this . data . measurements . length - 1 ; } ) ; this . draw . on ( 'drawend' , ( evt ) => { this . HsEventBusService . measurementEnds . next ( ) ; } ) ; } }