arcgissamples\geoprocessing\CalculateLineOfSight.java—ArcObjects 10.4 Help for Java | ArcGIS for Desktop
Calculate line of sight
arcgissamples\geoprocessing\CalculateLineOfSight.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.geoprocessing;

import java.io.File;

import com.esri.arcgis.datasourcesfile.ShapefileWorkspaceFactory;
import com.esri.arcgis.datasourcesraster.RasterDataset;
import com.esri.arcgis.datasourcesraster.RasterWorkspace;
import com.esri.arcgis.datasourcesraster.RasterWorkspaceFactory;
import com.esri.arcgis.geodatabase.IFeature;
import com.esri.arcgis.geodatabase.IFeatureClass;
import com.esri.arcgis.geodatabase.IGPMessages;
import com.esri.arcgis.geodatabase.IWorkspace;
import com.esri.arcgis.geodatabase.Workspace;
import com.esri.arcgis.geometry.ISpatialReference;
import com.esri.arcgis.geometry.Point;
import com.esri.arcgis.geometry.Polyline;
import com.esri.arcgis.geoprocessing.GeoProcessor;
import com.esri.arcgis.geoprocessing.tools.analyst3dtools.LineOfSight;
import com.esri.arcgis.geoprocessing.tools.datamanagementtools.AddField;
import com.esri.arcgis.geoprocessing.tools.datamanagementtools.CreateFeatureclass;
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;

/**
 * This class demonstrates the use of Line Of Sight (LOS) Geoprocessing tool. It assumes you points for the observer and
 * target and it calculates whether the two points are visible. It also calculates the visibility of surface features
 * along the path between the two points. The line defining the two points can either be 2D or 3D (Z-Aware). A 3D line
 * assumes the target and observer are at a height above sea level equal to the Z value. If it is 2D then the LOS tool
 * assumes that the target and observer are on the surface with an offset of 1 for the observer. By setting values for
 * the offsetA and offsetB fields the target and observer can be raised off the surface or above their z value.
 */
public class CalculateLineOfSight
{
  GeoProcessor gp = null;
  
  public CalculateLineOfSight()
  {  
    // create the geoprocessor and allow it to overwrite output
    try
    {
      gp = new GeoProcessor();
      gp.setOverwriteOutput(true);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }
  
  /**
   * Calculates line of sight
   * @param demFolder
   * @param demName
   * @param outputFolder
   * @return
   */
  private boolean lineOfSight(String demFolder, String demName, String outputFolder)
  {
    final double startX = 476265.710;
    final double startY = 224771.386;
    // the z values will be used for the 3D dataset
    final double startZ = 3091.00;
    // this offset is for the 2D dataset and represent the difference between the height of the DEM and
    // startZ at the start point
    final double startOffset = 100.0;

    final double endX = 488347.964;
    final double endY = 213629.843;
    final double endZ = 3140.00;
    final double endOffset = 100.00;

    String Line2DName = File.separator + "2dLine.shp";
    String Line3DName = File.separator + "3dLine.shp";

    // open the DEM to get it's spatial reference and to pass into the line of sight
    ISpatialReference demSR = null;
    RasterDataset rdataset = null;
    try
    {
      RasterWorkspaceFactory rwf = new RasterWorkspaceFactory();
      IWorkspace workspace = rwf.openFromFile(demFolder, 0);
      RasterWorkspace rworkspace = new RasterWorkspace(workspace);
      rdataset = (RasterDataset) rworkspace.openRasterDataset(demName);
      demSR = rdataset.getSpatialReference();

    }
    catch (Exception e)
    {
      e.printStackTrace();
      return false;
    }

    // create the new feature class containing the points to be used for calculating line of sight
    try
    {
      // This sample creates a 2d and a 3d polyline feature class for the line of sight of interest. The
      // geoprocessing
      // tool for line of sight handles 2d and 3d polylines differently in terms of assumed heights for targets.
      // Please
      // see the documentation for the Line of Sight tool for a further explanation
      CreateFeatureclass cfc = new CreateFeatureclass(outputFolder, Line2DName);
      cfc.setGeometryType("polyline");
      cfc.setSpatialReference(demSR);

      gp.execute(cfc, null);
      System.out.println("Made the 2D polyline");

      cfc.setOutName(Line3DName);
      cfc.setHasZ("enabled");
      gp.execute(cfc, null);
      System.out.println("Created the 3d polyline");
    }
    catch (Exception e)
    {
      // iterate through the GP messages to see what went wrong
      try
      {
        IGPMessages gpMessages = gp.getReturnMessages();
        for (int i = 0; i < gpMessages.getCount(); i++)
        {
          System.out.println(gpMessages.getMessage(i).getDescription());
        }
      }
      catch (Exception e2)
      {
      }
      e.printStackTrace();
      return false;
    }

    // add the offsetA and offsetB fields for the 2d line
    try
    {
      AddField addField = new AddField(outputFolder + Line2DName, "OffsetA", "double");
      gp.execute(addField, null);

      addField.setFieldName("OffsetB");
      gp.execute(addField, null);
    }
    catch (Exception e)
    {
      e.printStackTrace();
      try
      {
        IGPMessages gpMessages = gp.getReturnMessages();
        for (int i = 0; i < gpMessages.getCount(); i++)
        {
          System.out.println(gpMessages.getMessage(i).getDescription());
        }
      }
      catch (Exception e2)
      {
      }
      return false;
    }

    // add the points - there is no way to do this though GP so we have to use lower level arcobjects
    try
    {
      ShapefileWorkspaceFactory swf = new ShapefileWorkspaceFactory();
      Workspace sfworkspace = (Workspace) swf.openFromFile(outputFolder, 0);
      IFeatureClass fc2d = sfworkspace.openFeatureClass(Line2DName.substring(0, Line2DName.lastIndexOf('.')));

      Point startPoint = new Point();
      startPoint.setX(startX);
      startPoint.setY(startY);

      Point endPoint = new Point();
      endPoint.setX(endX);
      endPoint.setY(endY);

      Polyline polyline2d = new Polyline();
      polyline2d.setFromPoint(startPoint);
      polyline2d.setToPoint(endPoint);

      // this method for adding a feature is easier but does not give the ability to undo. Use a cursor and
      // edit operations to have undo capabilities
      IFeature feature = fc2d.createFeature();
      int a_id = feature.getFields().findField("OffsetA");
      int b_id = feature.getFields().findField("OffsetB");
      feature.setShapeByRef(polyline2d);
      feature.setValue(a_id, new Double(startOffset));
      feature.setValue(b_id, new Double(endOffset));
      feature.store();

      // now edit the 3d dataset
      IFeatureClass fc3d = sfworkspace.openFeatureClass(Line3DName.substring(0, Line3DName.lastIndexOf('.')));
      Point startPoint3d = new Point();
      startPoint3d.setZAware(true);
      startPoint3d.setX(startX);
      startPoint3d.setY(startY);
      startPoint3d.setZ(startZ);

      Point endPoint3d = new Point();
      endPoint3d.setZAware(true);
      endPoint3d.setX(endX);
      endPoint3d.setY(endY);
      endPoint3d.setZ(endZ);

      Polyline polyline3d = new Polyline();
      polyline3d.setZAware(true);
      polyline3d.setFromPoint(startPoint3d);
      polyline3d.setToPoint(endPoint3d);

      IFeature feature3d = fc3d.createFeature();
      feature3d.setShapeByRef(polyline3d);

      feature3d.store();

    }
    catch (Exception e)
    {
      e.printStackTrace();
      return false;
    }

    // call line of sight
    try
    {
      LineOfSight los = new LineOfSight(demFolder + File.separator + demName, outputFolder + Line2DName, outputFolder
          + File.separator + "result2d.shp");
      gp.execute(los, null);
      System.out.println("Created the 2D results");

      los.setInLineFeatureClass(outputFolder + Line3DName);
      los.setOutLosFeatureClass(outputFolder + File.separator + "result3d.shp");
      gp.execute(los, null);
      System.out.println("Created the 3D results");

    }
    catch (Exception e)
    {
      e.printStackTrace();
      try
      {
        IGPMessages gpMessages = gp.getReturnMessages();
        for (int i = 0; i < gpMessages.getCount(); i++)
        {
          System.out.println(gpMessages.getMessage(i).getDescription());
        }
      }
      catch (Exception e2)
      {
      }
      return false;
    }
    return true;
  }
  
  public static void main(String[] args)
  {
    System.out.println("Line of Sight - An ArcObjects Java SDK Developer Sample");
    
    try
    {
      // Initialize the engine and licenses.
      EngineInitializer.initializeEngine();

      AoInitialize aoInit = new AoInitialize();
      initializeArcGISLicenses(aoInit);

      //Get DEVKITHOME Home
      String devKitHome = System.getenv("AGSDEVKITJAVA");

      // Change the following lines if you want to use different data but you will also have to change the coordinates
      // for the points
      String inDEM = devKitHome + "java" + 
      File.separator + "samples" + 
      File.separator + "data" + 
      File.separator + "raster";
      
      String inDEMName = "dem1";
      String outShapePath = getOutputDir() + File.separator + "lineOfSight";

      File outShapefileDir = new File(outShapePath);
      outShapefileDir.mkdir();  
        
      CalculateLineOfSight los = new CalculateLineOfSight();
      if (los.lineOfSight(inDEM, inDEMName, outShapePath))
      {
        System.out.println("Everything worked - please go look in " + outShapePath);
      }
      else
      {
        System.out.println("Something went wrong please consult error messages");
      }
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }

  /**
   * Initializes the lowest available ArcGIS License
   */
  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();
    }
  }  

  /**
   * Retrieve output directory
   * @return
   */
  private static String getOutputDir()
  {
    String userDir;
    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;

  }
}