package com.revolsys.elevation.gridded.compactbinary; import java.io.IOException; import java.io.OutputStream; import java.nio.channels.Channels; import java.nio.channels.WritableByteChannel; import java.util.zip.GZIPOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import com.revolsys.elevation.gridded.GriddedElevationModel; import com.revolsys.elevation.gridded.GriddedElevationModelWriter; import com.revolsys.elevation.gridded.IntArrayScaleGriddedElevationModel; import com.revolsys.geometry.model.BoundingBox; import com.revolsys.geometry.model.GeometryFactory; import com.revolsys.io.AbstractWriter; import com.revolsys.io.channels.ChannelWriter; import com.revolsys.spring.resource.Resource; import com.revolsys.util.Exceptions; public class CompactBinaryGriddedElevationWriter extends AbstractWriter<GriddedElevationModel> implements GriddedElevationModelWriter { public static void writeHeader(final ChannelWriter out, final BoundingBox boundingBox, final GeometryFactory geometryFactory, final int gridWidth, final int gridHeight, final int gridCellSize) throws IOException { final int coordinateSystemId = geometryFactory.getCoordinateSystemId(); double scaleXY = geometryFactory.getScaleXY(); if (scaleXY <= 0) { scaleXY = 1000; } double scaleZ = geometryFactory.getScaleZ(); if (scaleZ <= 0) { scaleZ = 1000; } out.putBytes(CompactBinaryGriddedElevation.FILE_FORMAT_BYTES); // File // // type out.putShort(CompactBinaryGriddedElevation.VERSION); // version out.putInt(coordinateSystemId); // Coordinate System ID for (int axisIndex = 0; axisIndex < 3; axisIndex++) { final double offset = geometryFactory.getOffset(axisIndex); out.putDouble(offset); final double scale = geometryFactory.getScale(axisIndex); out.putDouble(scale); } out.putDouble(boundingBox.getMinX()); // minX out.putDouble(boundingBox.getMinY()); // minY out.putDouble(boundingBox.getMinZ()); // minZ out.putDouble(boundingBox.getMaxX()); // maxX out.putDouble(boundingBox.getMaxY()); // maxY out.putDouble(boundingBox.getMaxZ()); // maxZ out.putInt(gridCellSize); // Grid Cell Size out.putInt(gridWidth); // Grid Width out.putInt(gridHeight); // Grid Height } private Resource resource; private ChannelWriter writer; private int gridWidth; private int gridHeight; CompactBinaryGriddedElevationWriter(final Resource resource) { this.resource = resource; } @Override public void close() { super.close(); if (this.writer != null) { try { this.writer.close(); } catch (final Throwable e) { } finally { this.writer = null; } } this.resource = null; } @Override public void open() { if (this.writer == null) { final String fileNameExtension = this.resource.getFileNameExtension(); if ("zip".equals(fileNameExtension) || CompactBinaryGriddedElevation.FILE_EXTENSION_ZIP.equals(fileNameExtension)) { try { final OutputStream bufferedOut = this.resource.newBufferedOutputStream(); final String fileName = this.resource.getBaseName(); final ZipOutputStream zipOut = new ZipOutputStream(bufferedOut); final ZipEntry zipEntry = new ZipEntry(fileName); zipOut.putNextEntry(zipEntry); final WritableByteChannel channel = Channels.newChannel(zipOut); this.writer = new ChannelWriter(channel); } catch (final IOException e) { throw Exceptions.wrap("Error creating: " + this.resource, e); } } else if ("gz".equals(fileNameExtension)) { try { String fileName = this.resource.getBaseName(); if (!fileName.endsWith("." + CompactBinaryGriddedElevation.FILE_EXTENSION)) { fileName += "." + CompactBinaryGriddedElevation.FILE_EXTENSION; } final OutputStream bufferedOut = this.resource.newBufferedOutputStream(); final GZIPOutputStream zipOut = new GZIPOutputStream(bufferedOut); final WritableByteChannel channel = Channels.newChannel(zipOut); this.writer = new ChannelWriter(channel); } catch (final IOException e) { throw Exceptions.wrap("Error creating: " + this.resource, e); } } else { this.writer = this.resource.newChannelWriter(); } } } @Override public void write(final GriddedElevationModel elevationModel) { open(); try { writeHeader(elevationModel); if (elevationModel instanceof IntArrayScaleGriddedElevationModel) { final IntArrayScaleGriddedElevationModel scaleModel = (IntArrayScaleGriddedElevationModel)elevationModel; scaleModel.writeIntArray(this, this.writer); } else { writeGrid(elevationModel); } } catch (final IOException e) { Exceptions.throwUncheckedException(e); } } private void writeGrid(final GriddedElevationModel elevationModel) throws IOException { final ChannelWriter out = this.writer; final int gridWidth = this.gridWidth; final int gridHeight = this.gridHeight; final GeometryFactory geometryFactory = elevationModel.getGeometryFactory(); for (int gridY = 0; gridY < gridHeight; gridY++) { for (int gridX = 0; gridX < gridWidth; gridX++) { final double elevation = elevationModel.getElevation(gridX, gridY); final int zInt = geometryFactory.toIntZ(elevation); out.putInt(zInt); } } } private void writeHeader(final GriddedElevationModel elevationModel) throws IOException { final GeometryFactory geometryFactory = elevationModel.getGeometryFactory(); elevationModel.updateZBoundingBox(); final BoundingBox boundingBox = elevationModel.getBoundingBox(); this.gridWidth = elevationModel.getGridWidth(); this.gridHeight = elevationModel.getGridHeight(); final int gridCellSize = elevationModel.getGridCellSize(); writeHeader(this.writer, boundingBox, geometryFactory, this.gridWidth, this.gridHeight, gridCellSize); } }