Contour lines

Download Sample Viewer

Description

This application shows how to use the Contour geoprocessing tool, via a local geoprocessing package (.gpk), to create a feature class of contours (isolines) from local raster data. To use the sample, specify an interval, then click on the 'Generate contours' button. The contour lines will be returned and drawn on the map as an ArcGISDynamicMapServiceLayer from the task's result map service.

Code snippet


    List<GPParameter> parameters = new ArrayList<GPParameter>();
    GPDouble interval = new GPDouble("Interval"); // parameter name from gpk
    interval.setValue(intervalValue);
    parameters.add(interval);
    
    // run geoprocessing task
    geoprocessor.submitJobAndGetResultsAsync(parameters, 
        new String[]{"Contour_Result"}, 
        new String[]{"Contour_Result"}, 
        new GPJobResultCallbackListener() {
    // ...
    });
  

Sample Code

/* Copyright 2014 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 com.esri.client.samples.geoprocessing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;

import com.esri.client.local.ArcGISLocalTiledLayer;
import com.esri.client.local.GPServiceType;
import com.esri.client.local.LocalGeoprocessingService;
import com.esri.client.local.LocalServiceStartCompleteEvent;
import com.esri.client.local.LocalServiceStartCompleteListener;
import com.esri.client.local.LocalServiceStatus;
import com.esri.core.tasks.ags.geoprocessing.GPDouble;
import com.esri.core.tasks.ags.geoprocessing.GPJobResource;
import com.esri.core.tasks.ags.geoprocessing.GPJobResultCallbackListener;
import com.esri.core.tasks.ags.geoprocessing.GPParameter;
import com.esri.core.tasks.ags.geoprocessing.Geoprocessor;
import com.esri.map.ArcGISDynamicMapServiceLayer;
import com.esri.map.JMap;
import com.esri.runtime.ArcGISRuntime;

/**
 * This application shows how to use the Contour geoprocessing tool to create a feature 
 * class of contours (isolines) from local raster data. To use the sample, specify an 
 * interval, then click on the 'Generate contours' button. The contour lines will be 
 * returned and drawn on the map as an ArcGISDynamicMapServiceLayer from the task's 
 * result map service.
 */
public class LocalContourApp {

  // ArcGIS components
  private JMap map;
  private LocalGeoprocessingService localGP;
  private Geoprocessor gp;
  private ArcGISLocalTiledLayer tiledLayer;

  // Swing components
  private JComponent contentPane;
  private JProgressBar progressBar;
  private JButton btnGenerate;
  private JTextField intervalInput;

  // other
  private boolean layerAdded;
  private static final String FSP = System.getProperty("file.separator");
  private static final String DEFAULT_INTERVAL_DISTANCE = "200";
  private static final int PANEL_WIDTH = 220;
  
  // Constructor
  public LocalContourApp() { }

  // ------------------------------------------------------------------------
  // Core functionality
  // ------------------------------------------------------------------------
  private void generateContours(double intervalValue) {
    List<GPParameter> parameters = new ArrayList<>();
    GPDouble interval = new GPDouble("Interval"); // parameter name from gpk
    interval.setValue(intervalValue);
    parameters.add(interval);

    gp.submitJobAndGetResultsAsync(parameters, 
        new String[]{"Contour_Result"}, 
        new String[]{"Contour_Result"}, 
        new GPJobResultCallbackListener() {

      @Override
      public void onError(Throwable e1) {
        System.err.println(e1.getMessage());
        updateProgressBarUI(null, false);
      }

      @Override
      public void onCallback(GPJobResource jobResource, GPParameter[] outParameters) {
        updateProgressBarUI(null, false);
        // Creates a dynamic map service layer from the returned GPJobResource and the geoprocessor URL
        ArcGISDynamicMapServiceLayer contourLayer = new ArcGISDynamicMapServiceLayer(gp.getUrl(), jobResource);
        contourLayer.setOpacity(.80f);
        layerAdded = map.getLayers().add(contourLayer);
      }
    });
  }

  protected void onClear() {
    // clears the first layer above the basemap
    if (layerAdded) {
      map.getLayers().remove(1);
      btnGenerate.setEnabled(true);
    }
    layerAdded = false;
  }

  // ------------------------------------------------------------------------
  // Static methods
  // ------------------------------------------------------------------------
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        try {
          // instance of this application
          LocalContourApp contourApp = new LocalContourApp();
          
          // create the UI, including the map, for the application.
          JFrame appWindow = contourApp.createWindow();
          appWindow.add(contourApp.createUI());
          appWindow.setVisible(true);
        } catch (Exception e) {
          // on any error, display the stack trace.
          e.printStackTrace();
        }
      }
    });
  }

  // ------------------------------------------------------------------------
  // Public methods
  // ------------------------------------------------------------------------
  public JComponent createUI() {

    // application content
    contentPane = createContentPane();

    // progress bar
    progressBar = createProgressBar(contentPane);

    // map
    map = createMap();
    
    // put together
    contentPane.add(createUserPanel());
    contentPane.add(progressBar);
    contentPane.add(map);

    return contentPane;
  }

  // ------------------------------------------------------------------------
  // Private methods
  // ------------------------------------------------------------------------
  private JMap createMap() {

    final JMap jMap = new JMap();

    // tiled layer
    tiledLayer = new ArcGISLocalTiledLayer(getPathSampleData() + "tpks" + FSP + "RasterHillshade.tpk");
    jMap.getLayers().add(tiledLayer);

    // create the local geoprocessing service from the local gpk
    localGP = new LocalGeoprocessingService();
    localGP.setPath(getPathSampleData() + "gpks" + FSP + "Contour" + FSP + "Contour.gpk");
    localGP.setServiceType(GPServiceType.SUBMIT_JOB_WITH_MAP_SERVER_RESULT);
    localGP.addLocalServiceStartCompleteListener(new LocalServiceStartCompleteListener() {
      @Override
      public void localServiceStartComplete(LocalServiceStartCompleteEvent arg0) {  

        if (arg0.getService().getStatus() == LocalServiceStatus.STARTED) {
          updateProgressBarUI(null, false);
          btnGenerate.setEnabled(true);
          gp = new Geoprocessor(localGP.getUrlGeoprocessingService() + "/Contour");
        } else {
          System.out.println("Error Starting GP Service");
          System.out.println("error message: "+arg0.getService().getError().toString());
        }   
      }
    });
    // start the service asynchronously
    updateProgressBarUI("Starting geoprocessing service...", true);
    localGP.startAsync();

    return jMap;
  }

  /**
   * Creates the panel to display instructions and capture user input.
   */
  private JPanel createUserPanel() {

    Dimension preferredSize = new Dimension(PANEL_WIDTH, 30);

    JTextArea description = new JTextArea("Specify the interval, or distance, between contour lines " +
        "and click the 'Generate contours' button.");
    description.setFont(new Font("Verdana", Font.PLAIN, 11));
    description.setForeground(Color.WHITE);
    description.setBackground(new Color(0, 0, 0, 180));
    description.setEditable(false);
    description.setLineWrap(true);
    description.setWrapStyleWord(true);
    description.setBorder(BorderFactory.createEmptyBorder(5,10,5,10));

    JLabel lblDistance = new JLabel(" Interval: ");
    lblDistance.setForeground(Color.BLACK);
    lblDistance.setFont(new Font("Verdana", Font.BOLD, 12));
    lblDistance.setMaximumSize(new Dimension(130, 20));

    // text field to input interval distance
    intervalInput = new JTextField(DEFAULT_INTERVAL_DISTANCE, 5);
    intervalInput.setMaximumSize(new Dimension(30, 20));

    final JPanel inputPanel = new JPanel();
    BoxLayout boxLayout = new BoxLayout(inputPanel, BoxLayout.X_AXIS);
    inputPanel.setLayout(boxLayout);
    inputPanel.setPreferredSize(preferredSize);
    inputPanel.setBorder(BorderFactory.createEmptyBorder(2,25,2,25));
    inputPanel.setBackground(Color.WHITE);
    inputPanel.add(Box.createRigidArea(new Dimension(20, 0)));
    inputPanel.add(lblDistance);
    inputPanel.add(Box.createRigidArea(new Dimension(10, 0)));
    inputPanel.add(intervalInput);

    // buttons
    btnGenerate = new JButton("Generate contours");
    btnGenerate.setMinimumSize(preferredSize);
    btnGenerate.setPreferredSize(preferredSize);
    btnGenerate.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        double interval = Double.parseDouble(intervalInput.getText());
        btnGenerate.setEnabled(false);
        updateProgressBarUI("Generating contours...", true);
        generateContours(interval);
      }
    });
    btnGenerate.setEnabled(false);

    final JButton btnClear = new JButton("Clear results");
    btnClear.setMinimumSize(preferredSize);
    btnClear.setPreferredSize(preferredSize);
    btnClear.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        onClear();
      }
    });

    final JPanel btnPanel = new JPanel();
    btnPanel.setLayout(new BorderLayout());
    btnPanel.add(btnGenerate, BorderLayout.NORTH);
    btnPanel.add(btnClear, BorderLayout.SOUTH);
    btnPanel.setBorder(null);
    btnPanel.setAlignmentX(Component.CENTER_ALIGNMENT);

    final JPanel userPanel = new JPanel();
    userPanel.setSize(PANEL_WIDTH, 90);
    userPanel.setLayout(new BorderLayout());
    userPanel.add(inputPanel, BorderLayout.CENTER);
    userPanel.add(btnPanel, BorderLayout.SOUTH);

    // the container panel for everything
    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout(0, 0));
    panel.setLocation(10, 10);
    panel.setSize(PANEL_WIDTH, 160);
    panel.setBackground(new Color(0, 0, 0, 0));
    panel.setBorder(new LineBorder(new Color(0, 0, 0, 60), 5, false));

    panel.add(description, BorderLayout.CENTER);
    panel.add(userPanel, BorderLayout.SOUTH);

    return panel;
  }
  
  /**
   * Creates a window.
   * @return a window.
   */
  private JFrame createWindow() {
    JFrame window = new JFrame();
    window.setBounds(100, 100, 1000, 700);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.getContentPane().setLayout(new BorderLayout(0, 0));
    window.addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosing(WindowEvent windowEvent) {
        super.windowClosing(windowEvent);
        map.dispose();
      }
    });
    return window;
  }

  /**
   * Creates a content pane.
   * @return a content pane.
   */
  private static JLayeredPane createContentPane() {
    JLayeredPane contentPane = new JLayeredPane();
    contentPane.setBounds(100, 100, 1000, 700);
    contentPane.setLayout(new BorderLayout());
    contentPane.setVisible(true);
    return contentPane;
  }

  /**
   * Creates a progress bar.
   * @param parent progress bar's parent. The horizontal axis of the progress bar will be
   * center-aligned to the parent.
   * @return a progress bar.
   */
  private static JProgressBar createProgressBar(final JComponent parent) {
    final JProgressBar progressBar = new JProgressBar();
    progressBar.setSize(260, 20);
    parent.addComponentListener(new ComponentAdapter() {
      @Override
      public void componentResized(ComponentEvent e) {
        progressBar.setLocation(
            parent.getWidth()/2 - progressBar.getWidth()/2,
            parent.getHeight() - progressBar.getHeight() - 20);
      }
    });
    progressBar.setStringPainted(true);
    progressBar.setIndeterminate(true);
    return progressBar;
  }

  /**
   * Updates progress bar UI from the Swing's Event Dispatch Thread.
   * @param str string to be set.
   * @param visible flag to indicate visibility of the progress bar.
   */
  private void updateProgressBarUI(final String str, final boolean visible) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        if (str != null) {
          progressBar.setString(str);
        }
        progressBar.setVisible(visible);
      }
    }); 
  }

  private String getPathSampleData() {
    String dataPath = null;
    String javaPath = ArcGISRuntime.getInstallDirectory();
    if (javaPath != null) {
      if (!(javaPath.endsWith("/") || javaPath.endsWith("\\"))){
        javaPath += FSP;
      }
      dataPath = javaPath + "sdk" + FSP + "samples" + FSP + "data" + FSP;
    }
    File dataFile = new File(dataPath);
    if (!dataFile.exists()) { 
      dataPath = ".." + FSP + "data" + FSP;
    }
    return dataPath;
  }

}
Feedback on this topic?