private static Long getApproximateZoomLevel ( double [ ] lengths , List < TileMatrix > tileMatrices , double length ) { Long lengthZoomLevel = null ; double minLength = lengths [ 0 ] ; double maxLength = lengths [ lengths . length - 1 ] ; // Length is zoomed in further than available tiles if ( length < minLength ) { double levelsIn = Math . log ( length / minLength ) / Math . log ( .5 ) ; long zoomAbove = ( long ) Math . floor ( levelsIn ) ; long zoomBelow = ( long ) Math . ceil ( levelsIn ) ; double lengthAbove = minLength * Math . pow ( .5 , zoomAbove ) ; double lengthBelow = minLength * Math . pow ( .5 , zoomBelow ) ; lengthZoomLevel = tileMatrices . get ( tileMatrices . size ( ) - 1 ) . getZoomLevel ( ) ; if ( lengthAbove - length <= length - lengthBelow ) { lengthZoomLevel += zoomAbove ; } else { lengthZoomLevel += zoomBelow ; } } // Length is zoomed out further than available tiles else if ( length > maxLength ) { double levelsOut = Math . log ( length / maxLength ) / Math . log ( 2 ) ; long zoomAbove = ( long ) Math . ceil ( levelsOut ) ; long zoomBelow = ( long ) Math . floor ( levelsOut ) ; double lengthAbove = maxLength * Math . pow ( 2 , zoomAbove ) ; double lengthBelow = maxLength * Math . pow ( 2 , zoomBelow ) ; lengthZoomLevel = tileMatrices . get ( 0 ) . getZoomLevel ( ) ; if ( length - lengthBelow <= lengthAbove - length ) { lengthZoomLevel -= zoomBelow ; } else { lengthZoomLevel -= zoomAbove ; } } // Length is between the available tiles else { int lengthIndex = Arrays . binarySearch ( lengths , length ) ; if ( lengthIndex < 0 ) { lengthIndex = ( lengthIndex + 1 ) * - 1 ; } double zoomDistance = Math . log ( length / lengths [ lengthIndex ] ) / Math . log ( .5 ) ; long zoomLevelAbove = getTileMatrixAtLengthIndex ( tileMatrices , lengthIndex ) . getZoomLevel ( ) ; zoomLevelAbove += Math . round ( zoomDistance ) ; lengthZoomLevel = zoomLevelAbove ; } return lengthZoomLevel ; }
Get the approximate zoom level for length using the factor of 2 rule between zoom levels