diff --git a/brouter-map-creator/src/main/java/btools/mapcreator/ConvertLidarTile.java b/brouter-map-creator/src/main/java/btools/mapcreator/ConvertLidarTile.java new file mode 100644 index 0000000..0866c7d --- /dev/null +++ b/brouter-map-creator/src/main/java/btools/mapcreator/ConvertLidarTile.java @@ -0,0 +1,220 @@ +package btools.mapcreator; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class ConvertLidarTile +{ + public static int NROWS; + public static int NCOLS; + + public static final short NODATA2 = -32767; // hgt-formats nodata + public static final short NODATA = Short.MIN_VALUE; + + static short[] imagePixels; + + private static void readHgtZip( String filename, int rowOffset, int colOffset ) throws Exception + { + ZipInputStream zis = new ZipInputStream( new BufferedInputStream( new FileInputStream( filename ) ) ); + try + { + for ( ;; ) + { + ZipEntry ze = zis.getNextEntry(); + if ( ze.getName().endsWith( ".hgt" ) ) + { + readHgtFromStream( zis, rowOffset, colOffset ); + return; + } + } + } + finally + { + zis.close(); + } + } + + private static void readHgtFromStream( InputStream is, int rowOffset, int colOffset ) + throws Exception + { + DataInputStream dis = new DataInputStream( new BufferedInputStream( is ) ); + for ( int ir = 0; ir < 1201; ir++ ) + { + int row = rowOffset + ir; + + for ( int ic = 0; ic < 1201; ic++ ) + { + int col = colOffset + ic; + + int i1 = dis.read(); // msb first! + int i0 = dis.read(); + + if ( i0 == -1 || i1 == -1 ) + throw new RuntimeException( "unexcepted end of file reading hgt entry!" ); + + short val = (short) ( ( i1 << 8 ) | i0 ); + + if ( val == NODATA2 ) + { + val = NODATA; + } + + setPixel( row, col, val ); + } + } + } + + + private static void setPixel( int row, int col, short val ) + { + if ( row >= 0 && row < NROWS && col >= 0 && col < NCOLS ) + { + imagePixels[row * NCOLS + col] = val; + } + } + + private static short getPixel( int row, int col ) + { + if ( row >= 0 && row < NROWS && col >= 0 && col < NCOLS ) + { + return imagePixels[row * NCOLS + col]; + } + return NODATA; + } + + + public static void doConvert( String inputDir, int lonDegreeStart, int latDegreeStart, String outputFile ) throws Exception + { + int extraBorder = 0; + + NROWS = 5 * 1200 + 1 + 2 * extraBorder; + NCOLS = 5 * 1200 + 1 + 2 * extraBorder; + + imagePixels = new short[NROWS * NCOLS]; // 650 MB ! + + // prefill as NODATA + for ( int row = 0; row < NROWS; row++ ) + { + for ( int col = 0; col < NCOLS; col++ ) + { + imagePixels[row * NCOLS + col] = NODATA; + } + } + + for ( int latIdx = -1; latIdx <= 5; latIdx++ ) + { + int latDegree = latDegreeStart + latIdx; + int rowOffset = extraBorder + ( 4 - latIdx ) * 1200; + + for ( int lonIdx = -1; lonIdx <= 5; lonIdx++ ) + { + int lonDegree = lonDegreeStart + lonIdx; + int colOffset = extraBorder + lonIdx * 1200; + + String filename = inputDir + "/" + formatLat( latDegree ) + formatLon( lonDegree ) + ".zip"; + File f = new File( filename ); + if ( f.exists() && f.length() > 0 ) + { + System.out.println( "exist: " + filename ); + readHgtZip( filename, rowOffset, colOffset ); + } + else + { + System.out.println( "none : " + filename ); + } + } + } + + boolean halfCol5 = false; // no halfcol tiles in lidar data (?) + + + SrtmRaster raster = new SrtmRaster(); + raster.nrows = NROWS; + raster.ncols = NCOLS; + raster.halfcol = halfCol5; + raster.noDataValue = NODATA; + raster.cellsize = 1 / 1200.; + raster.xllcorner = lonDegreeStart - ( 0.5 + extraBorder ) * raster.cellsize; + raster.yllcorner = latDegreeStart - ( 0.5 + extraBorder ) * raster.cellsize; + raster.eval_array = imagePixels; + + // encode the raster + OutputStream os = new BufferedOutputStream( new FileOutputStream( outputFile ) ); + new RasterCoder().encodeRaster( raster, os ); + os.close(); + + // decode the raster + InputStream is = new BufferedInputStream( new FileInputStream( outputFile ) ); + SrtmRaster raster2 = new RasterCoder().decodeRaster( is ); + is.close(); + + short[] pix2 = raster2.eval_array; + if ( pix2.length != imagePixels.length ) + throw new RuntimeException( "length mismatch!" ); + + // compare decoding result + for ( int row = 0; row < NROWS; row++ ) + { + int colstep = halfCol5 ? 2 : 1; + for ( int col = 0; col < NCOLS; col += colstep ) + { + int idx = row * NCOLS + col; + short p2 = pix2[idx]; + if ( p2 != imagePixels[idx] ) + { + throw new RuntimeException( "content mismatch: p2=" + p2 + " p1=" + imagePixels[idx] ); + } + } + } + } + + private static String formatLon( int lon ) + { + if ( lon >= 180 ) + lon -= 180; // TODO: w180 oder E180 ? + + String s = "E"; + if ( lon < 0 ) + { + lon = -lon; + s = "E"; + } + String n = "000" + lon; + return s + n.substring( n.length() - 3 ); + } + + private static String formatLat( int lat ) + { + String s = "N"; + if ( lat < 0 ) + { + lat = -lat; + s = "S"; + } + String n = "00" + lat; + return s + n.substring( n.length() - 2 ); + } + + public static void main( String[] args ) throws Exception + { + String filename90 = args[0]; + String filename30 = filename90.substring( 0, filename90.length() - 3 ) + "bef"; + + int srtmLonIdx = Integer.parseInt( filename90.substring( 5, 7 ).toLowerCase() ); + int srtmLatIdx = Integer.parseInt( filename90.substring( 8, 10 ).toLowerCase() ); + + int ilon_base = ( srtmLonIdx - 1 ) * 5 - 180; + int ilat_base = 150 - srtmLatIdx * 5 - 90; + + doConvert( args[1], ilon_base, ilat_base, filename30 ); + } + +}