arcgissamples\analyst3d\HillshadeCommand.java
/* Copyright 2010 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. * */ 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 ArcView 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.esriLicenseProductCodeArcView) == esriLicenseStatus.esriLicenseAvailable) aoInit.initialize(esriLicenseProductCode.esriLicenseProductCodeArcView); else{ System.err.println("Could not initialize an Engine or ArcView 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; } }