import { inRange , isEqual } from 'lodash' ; import proj4 from 'proj4' ; import { Inject , Injectable } from '@angular/core' ; import { IMapFacadeConfig } from '../models/map-config.model' ; import { mapFacadeConfig } from '../models/map-facade.config' ; import { EPSG_4326 } from '@ansyn/imagery' ; export interface IUtmZone { zone : number ; utmProj : string ; } export interface ICoordinatesSystem { datum : 'wgs84' | 'ed50' ; projection : 'geo' | 'utm' ; } @ Injectable ( ) export class ProjectionConverterService { constructor ( @ Inject ( mapFacadeConfig ) protected mapfacadeConfigProj ) { } static isValidCoordinates ( coords , minLength ) { return coords . length >= minLength && coords . every ( c => typeof c === 'number' ) ; } static isValidGeoWGS84 ( coords ) { const coordinatesValid = ProjectionConverterService . isValidCoordinates ( coords , 2 ) ; if ( coordinatesValid ) { const validLong = inRange ( coords [ 0 ] , - 179.9999 , 180 ) ; const validLat = inRange ( coords [ 1 ] , - 89.9999 , 90 ) ; return validLat && validLong ; } return false ; } static isValidUTM ( coords ) { const coordinatesValid = ProjectionConverterService . isValidCoordinates ( coords , 3 ) ; if ( coordinatesValid ) { const validX = inRange ( coords [ 0 ] , - 16198192 , 17198193 ) ; const validY = typeof coords [ 1 ] === 'number' ; const validZone = inRange ( coords [ 2 ] , 0 , 61 ) ; return validX && validY && validZone ; } return false ; } isValidConversion ( coords , from ) { let isValid = Boolean ( coords ) ; const fromWgs84Geo = from . datum === 'wgs84' && from . projection === 'geo' ; const fromUtm = from . projection === 'utm' ; if ( isValid && fromWgs84Geo ) { isValid = ProjectionConverterService . isValidGeoWGS84 ( coords ) ; } if ( isValid && fromUtm ) { isValid = ProjectionConverterService . isValidUTM ( coords ) ; } return isValid ; } convertGeoWgs84ToUtmEd50 ( coords ) { const lng = coords [ 0 ] ; const hemisphere = coords [ 1 ] ; const zoneUtmEd50Proj = this . getZoneUtmProj ( lng , hemisphere ) ; const conv = proj4 ( EPSG_4326 , zoneUtmEd50Proj . utmProj , coords ) ; if ( conv [ 1 ] < 0 ) { conv [ 1 ] += 10000000 ; } return [ ... conv , zoneUtmEd50Proj . zone ] ; } convertUtmEd50ToWgs84Geo ( coords ) { let [ x , y , zone ] = coords ; if ( y > 5000000 ) { y -= 10000000 ; } const utmEd50Proj = this . getUtmFromConf ( zone ) ; const conv = proj4 ( utmEd50Proj , EPSG_4326 , [ x , y ] ) ; return [ ... conv ] ; } convertUtmWgs84ToGeoWgs84 ( coords ) { let [ x , y , zone ] = coords ; if ( y > 5000000 ) { y -= 10000000 ; } const utmWgs84Proj = `+proj=utm +zone=${ zone } +datum=WGS84` ; const conv = proj4 ( utmWgs84Proj , EPSG_4326 , [ x , y ] ) ; return [ ... conv ] ; } convertGeoWgs84ToUtmWgs84 ( coords ) { const lng = coords [ 0 ] ; const zone = ( Math . floor ( ( lng + 180 ) / 6 ) % 60 ) + 1 ; const projection = `+proj=utm +zone=${ zone } +datum=WGS84` ; const conv = proj4 ( EPSG_4326 , projection , coords ) ; if ( conv [ 1 ] < 0 ) { conv [ 1 ] += 10000000 ; } return [ ... conv , zone ] ; } convertUtmEd50ToUtmWgs84 ( coords ) { const geoWgs84Coords = this . convertUtmEd50ToWgs84Geo ( coords ) ; return this . convertGeoWgs84ToUtmWgs84 ( geoWgs84Coords ) ; } convertUtmWgs84ToUtmEd50 ( coords ) { const geoWgs84Coords = this . convertUtmWgs84ToGeoWgs84 ( coords ) ; return this . convertGeoWgs84ToUtmEd50 ( geoWgs84Coords ) ; } convertByProjectionDatum ( coords , from , to ) { if ( isEqual ( from , to ) ) { return [ ... coords ] ; } const fromWgs84Geo = from . datum === 'wgs84' && from . projection === 'geo' ; const toWgs84Geo = to . datum === 'wgs84' && to . projection === 'geo' ; const fromWgs84Utm = from . datum === 'wgs84' && from . projection === 'utm' ; const toWgs84Utm = to . datum === 'wgs84' && to . projection === 'utm' ; const fromEd50Utm = from . datum === 'ed50' && from . projection === 'utm' ; const toEd50Utm = to . datum === 'ed50' && to . projection === 'utm' ; if ( fromWgs84Geo && toEd50Utm ) { return this . convertGeoWgs84ToUtmEd50 ( coords ) ; } if ( fromEd50Utm && toWgs84Geo ) { return this . convertUtmEd50ToWgs84Geo ( coords ) ; } if ( fromEd50Utm && toWgs84Utm ) { return this . convertUtmEd50ToUtmWgs84 ( coords ) ; } if ( fromWgs84Geo && toWgs84Utm ) { return this . convertGeoWgs84ToUtmWgs84 ( coords ) ; } if ( fromWgs84Utm && toWgs84Geo ) { return this . convertUtmWgs84ToGeoWgs84 ( coords ) ; } if ( fromWgs84Utm && toEd50Utm ) { return this . convertUtmWgs84ToUtmEd50 ( coords ) ; } } getZoneUtmProj ( lng , hemisphere ) { const zone = ( Math . floor ( ( lng + 180 ) / 6 ) % 60 ) + 1 ; return { zone : zone , utmProj : this . getUtmFromConf ( zone ) } ; } getUtmFromConf ( zone ) { return this . mapfacadeConfigProj . Proj4 . ed50 . replace ( '${zone}' , zone . toString ( ) ) ; } }