package org.openjump.core.rasterimage.sextante; import java.util.Arrays; import org.openjump.core.rasterimage.sextante.rasterWrappers.GridExtent; import org.openjump.core.rasterimage.sextante.rasterWrappers.GridWrapper; import org.openjump.core.rasterimage.sextante.rasterWrappers.GridWrapperInterpolated; import org.openjump.core.rasterimage.sextante.rasterWrappers.GridWrapperNotInterpolated; /** * A convenience class which implements some of the methods * of the IRasterLayer interface. Extending this class is recommended * instead of implementing the interface directly * @author volaya * */ public abstract class AbstractSextanteRasterLayer implements ISextanteRasterLayer { private final static int m_iOffsetX []= {0, 1, 1, 1, 0, -1, -1, -1}; private final static int m_iOffsetY []= {1, 1, 0, -1, -1, -1, 0, 1}; private final static double DEG_90_IN_RAD = Math.PI / 180. * 90.; private final static double DEG_180_IN_RAD = Math.PI ; private final static double DEG_270_IN_RAD = Math.PI / 180. * 270.; private GridWrapper m_GridWrapper; private double m_dDist[]; private double _2DX; private int[][] m_Histogram; private double[] m_dMax; private double[] m_dMin; private double[] m_dMean; private double[] m_dVariance; private boolean m_bStatisticsCalculated = false; private boolean m_bHistogramCalculated; protected Object m_BaseDataObject; public Object getBaseDataObject(){ return m_BaseDataObject; } public void setInterpolationMethod(int iMethod){ m_GridWrapper.setInterpolationMethod(iMethod); } public byte getCellValueAsByte(int x, int y) { return m_GridWrapper.getCellValueAsByte(x,y); } public byte getCellValueAsByte(int x, int y, int band) { return m_GridWrapper.getCellValueAsByte(x,y,band); } public short getCellValueAsShort(int x, int y) { return m_GridWrapper.getCellValueAsShort(x,y); } public short getCellValueAsShort(int x, int y, int band) { return m_GridWrapper.getCellValueAsShort(x,y,band); } public int getCellValueAsInt(int x, int y) { return m_GridWrapper.getCellValueAsInt(x,y); } public int getCellValueAsInt(int x, int y, int band) { return m_GridWrapper.getCellValueAsInt(x,y,band); } public float getCellValueAsFloat(int x, int y) { return m_GridWrapper.getCellValueAsFloat(x,y); } public float getCellValueAsFloat(int x, int y, int band) { return m_GridWrapper.getCellValueAsFloat(x,y,band); } public double getCellValueAsDouble(int x, int y) { return m_GridWrapper.getCellValueAsDouble(x,y); } public double getCellValueAsDouble(int x, int y, int band) { return m_GridWrapper.getCellValueAsDouble(x,y,band); } public double getValueAt(double x, double y){ return m_GridWrapper.getValueAt(x, y, 0); } public double getValueAt(double x, double y, int band){ return m_GridWrapper.getValueAt(x, y, band); } public boolean isNoDataValue(double dValue){ return dValue == getNoDataValue(); } public boolean isInWindow(int x, int y){ if (x < 0 || y < 0) return false; if (x >= m_GridWrapper.getNX() || y >= m_GridWrapper.getNY()) return false; return true; } public int getNX(){ return m_GridWrapper.getNX(); } public int getNY(){ return m_GridWrapper.getNY(); } public double getWindowCellSize(){ return m_GridWrapper.getCellSize(); } public GridExtent getWindowGridExtent(){ return m_GridWrapper.getGridExtent(); } public void assign(double dValue){ int iBand; int x,y; for (iBand = 0; iBand < this.getBandsCount(); iBand++){ for (x = 0; x < getNX(); x++){ for (y = 0; y < getNY(); y++){ setCellValue(x,y, iBand, dValue); } } } } public void assign(ISextanteRasterLayer layer){ double dValue; layer.setWindowExtent(getWindowGridExtent()); int iNX = layer.getNX(); int iNY = layer.getNY(); for (int x = 0; x < iNX; x++){ for (int y = 0; y < iNY; y++){ dValue = layer.getCellValueAsDouble(x, y); setCellValue(x, y, dValue); } } setNoDataValue(layer.getNoDataValue()); } public void add(ISextanteRasterLayer driver){ double dValue; if (driver.getWindowGridExtent().equals(getWindowGridExtent())){ for (int x = 0; x < getWindowGridExtent().getNX(); x++){ for (int y = 0; y < getWindowGridExtent().getNY(); y++){ dValue = driver.getCellValueAsDouble(x, y) + getCellValueAsDouble(x, y); setCellValue(x, y, dValue); } } setNoDataValue(driver.getNoDataValue()); } } public void assignNoData() { assign(getNoDataValue()); } public void setCellValue(int x, int y, double dValue) { setCellValue(x, y, 0, dValue); } public void setNoData(int x, int y){ setCellValue(x, y, getNoDataValue()); } public void setNoData(int x, int y, int iBand){ setCellValue(x, y, iBand, getNoDataValue()); } public void addToCellValue(int x, int y, int iBand, double dValue){ double dCellValue = getCellValueAsDouble(x, y, iBand); if (!isNoDataValue(dCellValue)){ dCellValue += dValue; setCellValue(x, y, iBand, dCellValue); } } public void addToCellValue(int x, int y, double dValue){ addToCellValue(x, y, 0, dValue); } public void multiply(double dValue){ int iBand; int x,y; for (iBand = 0; iBand < this.getBandsCount(); iBand++){ for (x = 0; x < getNX(); x++){ for (y = 0; y < getNY(); y++){ double dVal = getCellValueAsDouble(x, y, iBand); setCellValue(x,y, iBand, dValue * dVal); } } } } public void setWindowExtent(ISextanteRasterLayer layer){ GridExtent layerExtent = new GridExtent(layer); if (layerExtent.fitsIn(this.getLayerGridExtent())){ m_GridWrapper = new GridWrapperNotInterpolated(this, layerExtent); } else{ m_GridWrapper = new GridWrapperInterpolated(this, layerExtent); } setConstants(); } public void setWindowExtent(GridExtent extent){ if (extent.fitsIn(this.getLayerGridExtent())){ m_GridWrapper = new GridWrapperNotInterpolated(this, extent); } else{ m_GridWrapper = new GridWrapperInterpolated(this, extent); } setConstants(); } public void setFullExtent(){ m_GridWrapper = new GridWrapperNotInterpolated(this, getLayerGridExtent()); setConstants(); } ///////////////////////////////////Statistical stuff////////////////////// private void setConstants(){ int i; double dCellSize = getWindowCellSize(); m_dDist = new double[8]; for (i = 0; i < 8; i++){ m_dDist[i] = Math.sqrt ( m_iOffsetX[i] * dCellSize * m_iOffsetX[i] * dCellSize + m_iOffsetY[i] * dCellSize * m_iOffsetY[i] * dCellSize ); } _2DX = dCellSize * 2; } private void calculateStatistics(){ int x, y; double z; int iValues; int iBands = getBandsCount(); m_dMean = new double[iBands]; m_dVariance = new double[iBands]; m_dMin = new double[iBands]; m_dMax = new double[iBands]; for (int i = 0; i < this.getBandsCount(); i++) { m_dMean[i] = 0.0; m_dVariance[i] = 0.0; } if (m_GridWrapper == null){ this.setFullExtent(); } for (int i = 0; i < this.getBandsCount(); i++) { iValues = 0; for (y = 0; y < getNY(); y++){ for (x = 0; x < getNX(); x++){ z = getCellValueAsDouble(x,y,i); if( !isNoDataValue(z)) { if( iValues == 0 ){ m_dMin[i] = m_dMax[i] = z; } else if( m_dMin[i] > z ){ m_dMin[i] = z; } else if( m_dMax[i] < z ){ m_dMax[i] = z; } m_dMean[i] += z; m_dVariance[i] += z * z; iValues++; } } } if( iValues > 0 ){ m_dMean[i] /= (double) iValues; m_dVariance[i] = m_dVariance[i] / (double) iValues - m_dMean[i] * m_dMean[i]; } } m_bStatisticsCalculated = true; } private void calculateHistogram(){ int x,y; int iClass; double dValue; double dRange; if (!m_bStatisticsCalculated){ calculateStatistics(); } int iBands = getBandsCount(); m_Histogram = new int [iBands][256]; Arrays.fill(m_Histogram,0); for (int i = 0; i < iBands; i++) { dRange = m_dMax[i] - m_dMin[i]; for (y = 0; y < getNY(); y++){ for (x = 0; x < getNX(); x++){ dValue = getCellValueAsDouble(x,y,i); if( !isNoDataValue(dValue)) { iClass = (int) ((dValue - m_dMin[i]) / dRange * 255.); m_Histogram[i][iClass]++; } } } } m_bHistogramCalculated = true; } public int[] getHistogram(int iBand){ if (!m_bHistogramCalculated){ calculateHistogram(); } return m_Histogram[iBand]; } public int[] getHistogram(){ return getHistogram(0); } public int[] getAccumulatedHistogram(int iBand){ int [] accHistogram = new int[256]; Arrays.fill(accHistogram, 0); if (!m_bHistogramCalculated){ calculateHistogram(); } for (int i = 1; i < 256; i++) { accHistogram[i] = m_Histogram[iBand][i] + accHistogram[i-1]; } return accHistogram; } public int[] getAccumulatedHistogram(){ return getAccumulatedHistogram(0); } public double getMinValue(int iBand){ if (!m_bStatisticsCalculated){ calculateStatistics(); } return m_dMin[iBand]; } public double getMaxValue(int iBand){ if (!m_bStatisticsCalculated){ calculateStatistics(); } return m_dMax[iBand]; } public double getMeanValue(int iBand){ if (!m_bStatisticsCalculated){ calculateStatistics(); } return m_dMean[iBand]; } public double getVariance(int iBand){ if (!m_bStatisticsCalculated){ calculateStatistics(); } return m_dVariance[iBand]; } public double getMeanValue(){ return getMeanValue(0); } public double getMinValue(){ return getMinValue(0); } public double getMaxValue(){ return getMaxValue(0); } public double getVariance(){ return getVariance(0); } //////////////////////////////Additional methods for DEM analysis////// private boolean getSubMatrix3x3(int x, int y, double SubMatrix[]){ int i; int iDir; double z, z2; z = getCellValueAsDouble(x, y); if(isNoDataValue(z)){ return false; } else{ //SubMatrix[4] = 0.0; for(i=0; i<4; i++){ iDir = 2 * i; z2 = getCellValueAsDouble(x + m_iOffsetX[iDir], y + m_iOffsetY[iDir]); if( !isNoDataValue(z2)){ SubMatrix[i] = z2 - z; } else{ z2 = getCellValueAsDouble(x + m_iOffsetX[(iDir + 4) % 8], y + m_iOffsetY[(iDir + 4) % 8]); if( !isNoDataValue(z2)){ SubMatrix[i] = z - z2; } else{ SubMatrix[i] = 0.0; } } } return true; } } public double getSlope(int x, int y){ double zm[], G, H; zm = new double[4]; if( getSubMatrix3x3(x, y, zm) ){ G = (zm[0] - zm[2]) / _2DX; H = (zm[1] - zm[3]) / _2DX; return Math.atan(Math.sqrt(G*G + H*H)); } else{ return m_GridWrapper.getNoDataValue(); } } public double getAspect(int x, int y){ double zm[], G, H, dAspect; zm = new double[4]; if( getSubMatrix3x3(x, y, zm) ){ G = (zm[0] - zm[2]) / _2DX; H = (zm[1] - zm[3]) / _2DX; if( G != 0.0 ){ dAspect = DEG_180_IN_RAD + Math.atan2(H, G); } else{ dAspect = H > 0.0 ? DEG_270_IN_RAD : (H < 0.0 ? DEG_90_IN_RAD : -1.0); } return dAspect; } else{ return m_GridWrapper.getNoDataValue(); } } public double getDistToNeighborInDir(int iDir){ return m_dDist[iDir]; } public static double getUnitDistToNeighborInDir(int iDir){ return( (iDir % 2 != 0) ? Math.sqrt(2.0) : 1.0 ); } public int getDirToNextDownslopeCell(int x, int y){ return getDirToNextDownslopeCell(x, y, true); } public int getDirToNextDownslopeCell(int x, int y, boolean bForceDirToNoDataCell){ int i, iDir; double z, z2, dSlope, dMaxSlope; z = getCellValueAsDouble(x, y); if(isNoDataValue(z)){ return -1; } dMaxSlope = 0.0; for(iDir=-1, i=0; i<8; i++){ z2 = getCellValueAsDouble(x + m_iOffsetX[i], y + m_iOffsetY[i]); if(isNoDataValue(z2)){ if (bForceDirToNoDataCell){ return i; } else{ return -1; } } else{ dSlope = (z - z2) / getDistToNeighborInDir(i); if( dSlope > dMaxSlope ){ iDir = i; dMaxSlope = dSlope; } } } return iDir; } public String toString(){ return this.getName(); } }