arcgissamples\analyst3d\HillshadeCommand.java—ArcObjects 10.4 Help for Java | ArcGIS for Desktop
Hillshade command
arcgissamples\analyst3d\HillshadeCommand.java
/* Copyright 2015 ESRI
* 
* All rights reserved under the copyright laws of the United States
* and applicable international laws, treaties, and conventions.
* 
* You may freely redistribute and use this sample code, with or
* without modification, provided you include the original copyright
* notice and use restrictions.
* 
* See the use restrictions at <your ArcGIS install location>/DeveloperKit10.4/userestrictions.txt.
* 
*/
package arcgissamples.analyst3d;

import java.io.File;
import java.io.IOException;

import com.esri.arcgis.datasourcesfile.TinWorkspaceFactory;
import com.esri.arcgis.datasourcesraster.DblPnt;
import com.esri.arcgis.datasourcesraster.Raster;
import com.esri.arcgis.datasourcesraster.RasterBand;
import com.esri.arcgis.datasourcesraster.RasterDataset;
import com.esri.arcgis.datasourcesraster.RasterWorkspace;
import com.esri.arcgis.datasourcesraster.RasterWorkspaceFactory;
import com.esri.arcgis.geoanalyst.RasterSurfaceOp;
import com.esri.arcgis.geodatabase.IGeoDataset;
import com.esri.arcgis.geodatabase.IPixelBlock;
import com.esri.arcgis.geodatabase.IRaster;
import com.esri.arcgis.geodatabase.IRasterDataset;
import com.esri.arcgis.geodatabase.IRasterProxy;
import com.esri.arcgis.geodatabase.Tin;
import com.esri.arcgis.geodatabase.esriRasterizationType;
import com.esri.arcgis.geodatabase.rstPixelType;
import com.esri.arcgis.geometry.Envelope;
import com.esri.arcgis.geometry.ISpatialReference;
import com.esri.arcgis.geometry.Point;
import com.esri.arcgis.system.AoInitialize;
import com.esri.arcgis.system.EngineInitializer;
import com.esri.arcgis.system.esriLicenseExtensionCode;
import com.esri.arcgis.system.esriLicenseProductCode;
import com.esri.arcgis.system.esriLicenseStatus;

public class HillshadeCommand {
  
  public HillshadeCommand(){
    
  }
  
  /**
   * Main Method - The console application entry point.
   * 
   * @param args String[] Command line argument
   */  
  public static void main(String[] args) {
    System.out.println("Starting HillshadeCommand - An ArcObjects SDK Developer Sample");
    
    try{
      //Initialize engine console application
      EngineInitializer.initializeEngine();
      
      //Initialize ArcGIS license
      AoInitialize aoInit = new AoInitialize();
      initializeArcGISLicenses(aoInit);
      
      //Get DEVKITHOME Home
      String devKitHome = System.getenv("AGSDEVKITJAVA");
      
      //Data for an input Raster      
      double azimuth = 315;
      double altitude = 45;

      //Data access setup
      String inDataPath = devKitHome + "java" + File.separator + "samples" + File.separator 
                          + "data" + File.separator + "raster";
      System.out.println(inDataPath);
      String inDataName = "dem1";
      
      //Data for an input TIN (swap the above code with this code to test with TIN input)
      //String inDataPath = arcGISHome + "java" + File.separator + "samples" + File.separator
      //                   + "data" + File.separator + "site1";
      //String inDataName = "dtm_tin";
      
      //Data output setup
      String outDataPath = getOutputDir() + File.separator + "hillshadecommand";
      String outDataName = "hillshade";

      File outData = new File(outDataPath);
      
      if (outData.exists()) {
        System.out.println("Output datafile already exists: " + outData.getAbsolutePath());
        System.out.println("Delete it and rerun.");
        System.out.println("Exiting...");
        System.exit(-1);
      }else{
        outData.mkdirs();
      }
      
      System.out.println("Using default Azimuth value " + azimuth + " and Altitude " + altitude);
      
      HillshadeCommand hillshadeCommand = new HillshadeCommand();
      hillshadeCommand.createHillshade(inDataPath, inDataName, outData.getAbsolutePath(), outDataName, azimuth, altitude);
    
      System.out.println("Done.  Output files created in " + outData.getAbsolutePath());      
      
      //Ensure any ESRI libraries are unloaded in the correct order
      aoInit.checkInExtension(esriLicenseExtensionCode.esriLicenseExtensionCode3DAnalyst);
      aoInit.shutdown();
    }catch(Exception e){
      System.out.println("Error: " + e.getMessage());
      e.printStackTrace();
      System.exit(-1);
    }
  }

  /**
   * Checks to see if an ArcGIS Engine Runtime license or an Basic License
   * is available. If so, then the appropriate ArcGIS License is initialized.
   * 
   * @param aoInit The AoInitialize object instantiated in the main method.
   */
  private static void initializeArcGISLicenses(AoInitialize aoInit) {
    try {
      if (aoInit.isProductCodeAvailable(esriLicenseProductCode.esriLicenseProductCodeEngine) 
          == esriLicenseStatus.esriLicenseAvailable)
        aoInit.initialize(esriLicenseProductCode.esriLicenseProductCodeEngine);
      else if (aoInit.isProductCodeAvailable(esriLicenseProductCode.esriLicenseProductCodeBasic) 
          == esriLicenseStatus.esriLicenseAvailable)
        aoInit.initialize(esriLicenseProductCode.esriLicenseProductCodeBasic);
      else{
        System.err.println("Could not initialize an Engine or Basic License. Exiting application.");
        System.exit(-1);
      }
      
      aoInit.checkOutExtension(esriLicenseExtensionCode.esriLicenseExtensionCode3DAnalyst);
    } catch (Exception e) {e.printStackTrace();}
  }

  /**
   * @param inDataPath - path to input data source
   * @param inDataName - name of input data source
   * @param outDataPath - path to output data source
   * @param outDataName - name of output data source
   * @param azimuth - angular direction of the sun, measured from north in clockwise
   *                              degrees from 0 to 360
   * @param altitude - the slope or angle of the illumination source above the horizon.
   *                              the units are degress from 0 (on the horizon) to 90 (overhead)
   * @throws Exception
   * @throws IOException
   */
  private void createHillshade(String inDataPath, String inDataName, String outDataPath, String outDataName, double azimuth, double altitude) throws Exception {
    try {
      //Define raster workspace factory object
      RasterWorkspaceFactory rasWkspFactory = new RasterWorkspaceFactory();
      
      //Define tin workspace factory object
      TinWorkspaceFactory tinWkspFactory = new TinWorkspaceFactory();
      
      //Test what type of workspace we are dealing with. There are two possible
      //cases: 1. RasterWorkspaceFactory
      //     2. TinWorkspaceFactory
      //The first case handles raster workspace factories, while the second handles
      //tin workspace factories.
      if (rasWkspFactory.isWorkspace(inDataPath) && !tinWkspFactory.isWorkspace(inDataPath)){
        //Ouputting some useful information to let developer know which workspace 
        //is being processed by the hillshade command
        File workspaceDir = new File(inDataPath, inDataName);
        System.out.println("Opening raster workspace " + workspaceDir.getAbsolutePath() + " and getting its dataset ...");

        //Get the raster workspace and it's dataset
        RasterWorkspace rasWksp = new RasterWorkspace(rasWkspFactory.openFromFile(inDataPath, 0));
        IRasterDataset iRasterDataset = rasWksp.openRasterDataset(inDataName);

        //Check if the raster is not of type RasterDataset
        if (!(iRasterDataset instanceof RasterDataset)) {
          System.out.println("The raster isn't a RasterDataset");
          throw new Exception();
        }
        
        //Cast to RasterDataset
        RasterDataset inRasDataset = (RasterDataset) iRasterDataset;;
        
        //RasterSurfaceOp contains the hillshade command
        RasterSurfaceOp surface = new RasterSurfaceOp();
        
        //Create the hillshade data
        System.out.println("Creating hillshade data ...");
        IGeoDataset geoDataset = surface.hillShade(inRasDataset, azimuth, altitude, true, null);
        
        //Castto raster
        IRaster outRaster = new IRasterProxy(geoDataset);
        
        //Save the raster to disk
        saveGridToDisk(new Raster(outRaster), outDataPath, outDataName);
      }else if (tinWkspFactory.isWorkspace(inDataPath)){
        //Ouputting some useful information to let developer know which workspace 
        //is being processed by the hillshade command
        File workspaceDir = new File(inDataPath, inDataName);
        System.out.println("  " + workspaceDir.getAbsolutePath() + " is a valid Tin Workspace");

        //Instantiate a tin object
        Tin tin = new Tin();
        
        //Get a path to the source data including the file name
        String path = inDataPath + File.separator + inDataName;
        System.out.println("  Path to Tin: " + path);
        
        //Initialize the tin
        tin.init(path);

        //Use the tin's extent to get width and height of the Envelope
        //(i.e. Minimum bounding box)
        Envelope extent = (Envelope) tin.getExtent();
        double dx = extent.getWidth();
        double dy = extent.getHeight();
        
        //Determine the cell size
        double cellsize;
        if(dx > dy){
          cellsize = Math.round(dx/249);
        }else{
          cellsize = Math.round(dy/249);
        }
        
        //Supported pixel types limited to float and long because
        //output currently limited to native ESRI Grid
        tinToRaster(tin, esriRasterizationType.esriHillShadeAsRaster, outDataPath, outDataName, cellsize, extent);
      }else{
        System.out.println("Program failed.  Check input data path and name.");
        throw new Exception();
      }
    }catch (Exception e) {
      e.printStackTrace();
      throw e;
    }
  }
  
  /**
   * Converts a tin to raster 
   * 
   * @param tin
   * @param aRasterizationType
   * @param inDataPath
   * @param inDataName
   * @param cellsize
   * @param extent
   * @return
   * @throws IOException
   */
  private RasterDataset tinToRaster(Tin tin, int aRasterizationType, String inDataPath, String inDataName, double cellsize, Envelope extent) throws IOException {
    Point origin = (Point) extent.getLowerLeft();
    origin.setX(origin.getX() - (cellsize * .05));
    origin.setY(origin.getY() - (cellsize * .05));

    int nCol = (int)Math.round((extent.getWidth() / cellsize) + 1);
    int nRow = (int)Math.round((extent.getHeight() / cellsize) + 1);

    ISpatialReference spatialRef = tin.getSpatialReference();

    RasterDataset rasterDataset = createRasterDataset(inDataPath, inDataName, "GRID", origin, nCol, nRow, cellsize, cellsize, rstPixelType.PT_LONG, spatialRef, true);
    RasterBand rasterBand = (RasterBand) rasterDataset.item(0);
    Object nodataInt = rasterBand.getNoDataValue();

    DblPnt offset = new DblPnt();
    int mxblk_x = 2048;
    int mxblk_y = 2048;

    if(nCol < mxblk_x){
      mxblk_x = nCol;
    }
    
    if(nRow < mxblk_y){
      mxblk_y = nRow;
    }
    
    DblPnt blkSize = new DblPnt();
    blkSize.setX(mxblk_x);
    blkSize.setY(mxblk_y);

    Object blkArray;
    IPixelBlock pixelBlk = rasterBand.createPixelBlock(blkSize);
    blkArray = pixelBlk.getSafeArray(0);
    Point blkOrigin = new Point();

    for (int iRowOffset = 0; iRowOffset < nRow; iRowOffset = iRowOffset + mxblk_y) {
      for (int iColOffset = 0; iColOffset < nCol; iColOffset = iColOffset + mxblk_x) {
        if ((nCol - iColOffset) < mxblk_x) {
          blkSize.setX(nCol - iColOffset);
          pixelBlk = rasterBand.createPixelBlock(blkSize);
          blkArray = pixelBlk.getSafeArray(0);
        }
        
        blkOrigin.setX(origin.getX() + (iColOffset * cellsize) + (cellsize * 0.5));
        blkOrigin.setY(origin.getY() + ((nRow - iRowOffset) * cellsize) - (cellsize * 0.5));
        tin.queryPixelBlock(blkOrigin.getX(), blkOrigin.getY(), cellsize, cellsize, aRasterizationType, nodataInt, blkArray);
        offset.setX(iColOffset);
        offset.setY(iRowOffset);
        rasterBand.write(offset, pixelBlk);
      }
      
      boolean reset = false;
      
      if (!(blkSize.getX() == mxblk_x)){
        blkSize.setX(mxblk_x);
        reset = true;
      }
      
      if ((nRow - iRowOffset) < mxblk_y){
        blkSize.setY(nRow - iRowOffset);
      }
      
      if (reset){
        pixelBlk = rasterBand.createPixelBlock(blkSize);
        blkArray = pixelBlk.getSafeArray(0);
      }
    }
    
    return rasterDataset;
  }

  /**
   * Create a raster dataset
   * 
   * @param inDataPath
   * @param inDataName
   * @param format
   * @param origin
   * @param nCol
   * @param nRow
   * @param cellsizeX
   * @param cellsizeY
   * @param ePixelType
   * @param spatialRef
   * @param permanent
   * @return
   * @throws IOException
   */
  private RasterDataset createRasterDataset(String inDataPath, String inDataName, String format, Point origin, int nCol, int nRow, double cellsizeX, double cellsizeY, int ePixelType, ISpatialReference spatialRef, boolean permanent) throws IOException {
    RasterWorkspaceFactory rasterWorkspaceFactory = new RasterWorkspaceFactory();
    RasterWorkspace rasterWorkspace = new RasterWorkspace(rasterWorkspaceFactory.openFromFile(inDataPath, 0));
    
    int numbands = 1;
    RasterDataset rasterDataset = (RasterDataset) rasterWorkspace.createRasterDataset(inDataName, format, origin, nCol, nRow, cellsizeX, cellsizeY, numbands, ePixelType,spatialRef, permanent);

    return rasterDataset;
  }

  /**
   * Saves a raster to disk
   * 
   * @param raster - input raster
   * @param outDataPath - path to output data source
   * @param outDataName - name of input data source
   */
  private void saveGridToDisk(Raster raster, String outDataPath, String outDataName) throws IOException  {
    try {
      //Obtain a raster workspace factory object
      RasterWorkspaceFactory rasWkspFactory = new RasterWorkspaceFactory();
      
      //Get the raster workspace
      //We can safely assume that this is RasterWorkspace based on the conditional
      //testing done in the createHillshade().
      RasterWorkspace rasterWorkspace = new RasterWorkspace(rasWkspFactory.openFromFile(outDataPath, 0));
      
      raster.saveAs(outDataName, rasterWorkspace, "GRID");
    } catch (IOException e) {
      System.out.println("Could not save raster as grid data to disk.");
      e.printStackTrace();
      throw e;
    }
  }

  /**
   * Convenience method to generate an output directory based on the operating
   * system that the sample is being executed on. 
   * 
   * @return A path to the new directory is return
   */
  private static String getOutputDir() {
    String userDir;
    
    //Get the operating systems user profile or home location depending
    //on which operating system this sample is executed on.
    if(System.getProperty("os.name").toLowerCase().indexOf("win") > -1){
      userDir = System.getenv("UserProfile");
    }else{
      userDir = System.getenv("HOME");
    }
      
    String outputDir = userDir + File.separator + "arcgis_sample_output";
    
    System.out.println("Creating output directory - " + outputDir);
    
    new File(outputDir).mkdir();
    
    return outputDir;
  }
}