/**
 * Coordinate transformations between SUMO and three.js.
 *
 * SUMO uses a coordinate system where the ground is the xy-plane and z points up.
 * Increasing x values go from left to right and increasing y goes from top to bottom.
 * This is a left-handed coordinate system.
 *
 * In three.js, it's conventional to have the ground be the xz-plane and have y point up.
 * To convert between these systems, we invert y (y --> bottom - y) and swap the
 * y and z coordinates. We use (bottom - y) instead of (-y) to keep the coordinates positive.
 */ import * as proj4 from 'proj4' ; import { Network } from './api' ; export interface LatLng { lat : number ; lng : number ; } export interface Transform { left : number ; top : number ; bottom : number ; right : number ; width ( ) : number ; height ( ) : number ; xyToXz ( xy ) : [ number , number ] ; xyToXyz ( xy ) : [ number , number , number ] ; xzToSumoXy ( xz ) : [ number , number ] ; sumoXyzToXyz ( xyz ) : [ number , number , number ] ; center ( ) : [ number , number ] ; latLngToXZ ( latLng ) : [ number , number ] | null ; toLatLng ( xz ) : LatLng | null ; } export function getTransforms ( network ) { const location = network . net . location ; const [ dx , dy ] = location . netOffset . split ( ',' ) . map ( Number ) ; const [ left , top , right , bottom ] = location . convBoundary . split ( ',' ) . map ( Number ) ; const { projParameter } = location ; const t = { left , top , bottom , right , xyToXz ( [ x , y ] ) { return [ x , bottom - y ] ; } , xyToXyz ( [ x , y ] ) { return [ x , 0 , bottom - y ] ; } , center ( ) { return [ ( left + right ) / 2 , ( top + bottom ) / 2 ] ; } , width ( ) { return Math . abs ( right - left ) ; } , height ( ) { return Math . abs ( bottom - top ) ; } , sumoXyzToXyz ( [ x , y , z ] ) { const [ xp , , zp ] = this . xyToXyz ( [ x , y ] ) ; return [ xp , z , zp ] ; } , xzToSumoXy ( [ x , z ] ) { return [ x , bottom - z ] ; } , latLngToXZ ( latLng ) { if ( projParameter === '!' ) return null ; const [ x , y ] = proj4 ( projParameter ) . forward ( [ latLng . lng , latLng . lat ] ) ; return this . xyToXz ( [ x + dx , y + dy ] ) ; } , toLatLng ( xz ) { if ( projParameter === '!' ) return null ; const [ sumoX , sumoY ] = t . xzToSumoXy ( xz ) ; const projX = sumoX - dx ; const projY = sumoY - dy ; const [ lng , lat ] = proj4 ( projParameter ) . inverse ( [ projX , projY ] ) ; return { lat , lng } ; } , } ; return t ; }