package mil.nga.giat.geowave.adapter.raster.adapter.merge.nodata; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import mil.nga.giat.geowave.core.geotime.GeometryUtils; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; public class NoDataByFilter implements NoDataMetadata { private final static Logger LOGGER = LoggerFactory.getLogger(NoDataByFilter.class); private Geometry shape; private double[][] noDataPerBand; protected NoDataByFilter() {} public NoDataByFilter( final Geometry shape, final double[][] noDataPerBand ) { this.shape = shape; this.noDataPerBand = noDataPerBand; } public Geometry getShape() { return shape; } public double[][] getNoDataPerBand() { return noDataPerBand; } @Override public boolean isNoData( final SampleIndex index, final double value ) { if ((noDataPerBand != null) && (noDataPerBand.length > index.getBand())) { for (final double noDataVal : noDataPerBand[index.getBand()]) { // use object equality to capture NaN, and positive and negative // infinite equality if (new Double( value).equals(new Double( noDataVal))) { return true; } } } if ((shape != null) && !shape.intersects(new GeometryFactory().createPoint(new Coordinate( index.getX(), index.getY())))) { return true; } return false; } @Override public byte[] toBinary() { final byte[] noDataBinary; if ((noDataPerBand != null) && (noDataPerBand.length > 0)) { int totalBytes = 4; final List<byte[]> noDataValuesBytes = new ArrayList<byte[]>( noDataPerBand.length); for (final double[] noDataValues : noDataPerBand) { final int thisBytes = 4 + (noDataValues.length * 8); totalBytes += thisBytes; final ByteBuffer noDataBuf = ByteBuffer.allocate(thisBytes); noDataBuf.putInt(noDataValues.length); for (final double noDataValue : noDataValues) { noDataBuf.putDouble(noDataValue); } noDataValuesBytes.add(noDataBuf.array()); } final ByteBuffer noDataBuf = ByteBuffer.allocate(totalBytes); noDataBuf.putInt(noDataPerBand.length); for (final byte[] noDataValueBytes : noDataValuesBytes) { noDataBuf.put(noDataValueBytes); } noDataBinary = noDataBuf.array(); } else { noDataBinary = new byte[] {}; } final byte[] geometryBinary; if (shape == null) { geometryBinary = new byte[0]; } else { geometryBinary = GeometryUtils.geometryToBinary(shape); } final ByteBuffer buf = ByteBuffer.allocate(geometryBinary.length + noDataBinary.length + 4); buf.putInt(noDataBinary.length); buf.put(noDataBinary); buf.put(geometryBinary); return buf.array(); } @Override public void fromBinary( final byte[] bytes ) { final ByteBuffer buf = ByteBuffer.wrap(bytes); final int noDataBinaryLength = buf.getInt(); final byte[] geometryBinary = new byte[bytes.length - noDataBinaryLength - 4]; if (noDataBinaryLength == 0) { noDataPerBand = new double[][] {}; } else { noDataPerBand = new double[buf.getInt()][]; for (int b = 0; b < noDataPerBand.length; b++) { noDataPerBand[b] = new double[buf.getInt()]; for (int i = 0; i < noDataPerBand[b].length; i++) { noDataPerBand[b][i] = buf.getDouble(); } } } if (geometryBinary.length > 0) { buf.get(geometryBinary); shape = GeometryUtils.geometryFromBinary(geometryBinary); } else { shape = null; } } @Override public Set<SampleIndex> getNoDataIndices() { return null; } }