arcgissamples\networkanalyst\SolveServiceArea.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.networkanalyst; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.SystemColor; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.text.NumberFormat; import java.util.StringTokenizer; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.SoftBevelBorder; import com.esri.arcgis.beans.map.MapBean; import com.esri.arcgis.carto.ILayer; import com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory; import com.esri.arcgis.geodatabase.GPMessages; import com.esri.arcgis.geodatabase.ICursor; import com.esri.arcgis.geodatabase.ICursorProxy; import com.esri.arcgis.geodatabase.IDENetworkDataset; import com.esri.arcgis.geodatabase.IDataset; import com.esri.arcgis.geodatabase.IDatasetComponent; import com.esri.arcgis.geodatabase.IDatasetComponentProxy; import com.esri.arcgis.geodatabase.IDatasetContainer2; import com.esri.arcgis.geodatabase.IDatasetContainer2Proxy; import com.esri.arcgis.geodatabase.IFeatureClass; import com.esri.arcgis.geodatabase.IFeatureClassContainer; import com.esri.arcgis.geodatabase.IFeatureClassContainerProxy; import com.esri.arcgis.geodatabase.IFeatureDataset; import com.esri.arcgis.geodatabase.IFeatureDatasetExtension; import com.esri.arcgis.geodatabase.IFeatureDatasetExtensionContainer; import com.esri.arcgis.geodatabase.IFeatureDatasetExtensionContainerProxy; import com.esri.arcgis.geodatabase.IFeatureWorkspace; import com.esri.arcgis.geodatabase.IFeatureWorkspaceProxy; import com.esri.arcgis.geodatabase.IGPMessages; import com.esri.arcgis.geodatabase.IGeoDataset; import com.esri.arcgis.geodatabase.IGeoDatasetProxy; import com.esri.arcgis.geodatabase.INetworkAttribute; import com.esri.arcgis.geodatabase.INetworkDataset; import com.esri.arcgis.geodatabase.IRow; import com.esri.arcgis.geodatabase.ITable; import com.esri.arcgis.geodatabase.IWorkspaceFactory; import com.esri.arcgis.geodatabase.NetworkDataset; import com.esri.arcgis.geodatabase.esriDatasetType; import com.esri.arcgis.geodatabase.esriGPMessageType; import com.esri.arcgis.geodatabase.esriNetworkAttributeUsageType; import com.esri.arcgis.geodatabase.esriNetworkForwardStarBacktrack; import com.esri.arcgis.geometry.IEnvelope; import com.esri.arcgis.networkanalyst.INAClass; import com.esri.arcgis.networkanalyst.INAClassFieldMap; import com.esri.arcgis.networkanalyst.INAClassLoader; import com.esri.arcgis.networkanalyst.INAContext; import com.esri.arcgis.networkanalyst.INAContextEdit; import com.esri.arcgis.networkanalyst.INALayer; import com.esri.arcgis.networkanalyst.INAServiceAreaSolver; import com.esri.arcgis.networkanalyst.INASolver; import com.esri.arcgis.networkanalyst.INASolverSettings; import com.esri.arcgis.networkanalyst.INamedSet; import com.esri.arcgis.networkanalyst.NAClassFieldMap; import com.esri.arcgis.networkanalyst.NAClassLoader; import com.esri.arcgis.networkanalyst.NAServiceAreaSolver; import com.esri.arcgis.networkanalyst.esriNAOutputLineType; import com.esri.arcgis.networkanalyst.esriNAOutputPolygonType; import com.esri.arcgis.networkanalyst.esriNATravelDirection; import com.esri.arcgis.system.AoInitialize; import com.esri.arcgis.system.DoubleArray; import com.esri.arcgis.system.EngineInitializer; import com.esri.arcgis.system.IDoubleArray; import com.esri.arcgis.system.IStringArray; import com.esri.arcgis.system.esriLicenseExtensionCode; import com.esri.arcgis.system.esriLicenseProductCode; import com.esri.arcgis.system.esriLicenseStatus; public class SolveServiceArea extends JFrame implements ActionListener { private INAContext naContext; private MapBean map = null; private static final String CRLF = "\r\n"; private static final long serialVersionUID = 1L; public static void main(String[] args) throws Exception { // initialize the interop initializeInterop(); // initialize to a license level initializeArcGISLicenses(); // set native look and feel for application UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); // start the sample final SolveServiceArea thisClass = new SolveServiceArea(); thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); SwingUtilities.invokeLater(new Runnable() { public void run() { try { thisClass.initialize(); thisClass.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } private void initialize() throws Exception { // Build the UI this.initializeUI(); //Get DEVKITHOME Home String devKitHome = System.getenv("AGSDEVKITJAVA"); if (devKitHome == null) { System.err.println("Environment variable 'devKitHome' not set. Exiting application"); System.exit(-2); } String dataPath = devKitHome + File.separator + "java" + File.separator + "samples" + File.separator + "data" + File.separator + "SanFrancisco" + File.separator; getMap().loadMxFile(dataPath + "SanFrancisco.mxd", null, null); // Open the workspace IFeatureWorkspace featureWorkspace = openWorkspace(dataPath + "SanFrancisco.gdb"); // Get the network dataset String networkDatasetFeatureDataset = "Transportation"; String networkDatasetName = "Streets_ND"; INetworkDataset nwDataset = openNetworkDataset( featureWorkspace ,networkDatasetFeatureDataset ,networkDatasetName ); // Create NAContext and NASolver this.naContext = createSolverContext(nwDataset); // Get Cost Attributes for (int i = 0; i < nwDataset.getAttributeCount(); i++) { INetworkAttribute nwAttribute = nwDataset.getAttribute(i); if (nwAttribute.getUsageType() == esriNetworkAttributeUsageType.esriNAUTCost) getComboboxCost().addItem(nwAttribute.getName()); } // Load locations from FC IFeatureDataset featureDataset = featureWorkspace.openFeatureDataset("Analysis"); IFeatureClassContainer inputStopsFCC = new IFeatureClassContainerProxy(featureDataset); IFeatureClass inputStopsFC = inputStopsFCC.getClassByName("CompetitorStores"); loadNANetworkLocations("Facilities", inputStopsFC, 100, this.naContext); // Create a Network Analysis Layer and add to Map INALayer naLayer = this.naContext.getSolver().createLayer(this.naContext); ((ILayer) naLayer).setName(this.naContext.getSolver().getDisplayName()); getMap().addLayer((ILayer) naLayer, 0); } private IFeatureWorkspace openWorkspace(String path) throws Exception { IWorkspaceFactory workspaceFactory = new FileGDBWorkspaceFactory(); return new IFeatureWorkspaceProxy(workspaceFactory.openFromFile(path, 0)); } private INetworkDataset openNetworkDataset( IFeatureWorkspace workspace ,String networkDatasetFeatureDataset ,String networkDatasetName ) throws Exception { IFeatureDataset featureDataset = workspace.openFeatureDataset(networkDatasetFeatureDataset); IFeatureDatasetExtensionContainer fdsExtCont = new IFeatureDatasetExtensionContainerProxy(featureDataset); IFeatureDatasetExtension fdsExt = fdsExtCont.findExtension(esriDatasetType.esriDTNetworkDataset); IDatasetContainer2 dsCont = new IDatasetContainer2Proxy(fdsExt); IDataset dataset = dsCont.getDatasetByName(esriDatasetType.esriDTNetworkDataset, networkDatasetName); NetworkDataset networkDataset = new NetworkDataset(dataset); return networkDataset; } private INAContext createSolverContext(INetworkDataset nwDataset) throws Exception { IDENetworkDataset deNetworkDataset = getDENetworkDataset(nwDataset); // Create the ServiceArea Solver INASolver saSolver = new NAServiceAreaSolver(); // Create a context for the solver INAContext naContext = saSolver.createContext(deNetworkDataset, saSolver.getName()); // Bind the context with the network dataset ((INAContextEdit) naContext).bind(nwDataset, new GPMessages()); return naContext; } private IDENetworkDataset getDENetworkDataset(INetworkDataset nwDataset) throws Exception { IDatasetComponent datasetComponent = new IDatasetComponentProxy(nwDataset); return ((IDENetworkDataset) datasetComponent.getDataElement()); } private void loadNANetworkLocations(String className, IFeatureClass inputFC, int tolerance, INAContext context) throws Exception { // Get teh NA classes INamedSet classes = context.getNAClasses(); // Get the specific class we're interested in INAClass naClass = (INAClass) classes.getItemByName(className); // delete existing Locations except if that a barriers naClass.deleteAllRows(); // Create a NAClassLoader and set the snap tolerance (meters unit) INAClassLoader loader = new NAClassLoader(); loader.setLocatorByRef(context.getLocator()); if (tolerance > 0) loader.getLocator().setSnapTolerance(tolerance); // link the loader and the NA class loader.setNAClassByRef(naClass); // Create field map to automatically map fields from input class to // naclass INAClassFieldMap mapping = new NAClassFieldMap(); mapping.createMapping(naClass.getClassDefinition(), inputFC.getFields()); loader.setFieldMapByRef(mapping); // Load Network Locations loader.load(new ICursorProxy(inputFC.search(null, true)), null, null, null); } public void actionPerformed(ActionEvent arg0) { // solve here getButtonSolve().setText("Solving..."); getButtonSolve().setEnabled(false); // Don't engage the EDT, it might make the app unresponsive // Delegate to a worker thread Thread t = new Thread("ServiceAreaSolver Worker Thread") { public void run() { try { // apply the constraints specified by the user applySolverSettings(); IGPMessages messages = new GPMessages(); if (!naContext.getSolver().solve(naContext, messages, null)) { displayOutput("SAPolygons"); } else { getTextareaNotifications().setText( getTextareaNotifications().getText() + "Partial Result" + CRLF); // Display Error/Warning/Informative Messages for (int i = 0; i < messages.getCount(); i++) { switch (messages.getMessage(i).getType()) { case esriGPMessageType.esriGPMessageTypeError: getTextareaNotifications().setText( getTextareaNotifications().getText() + "Error " + messages.getMessage(i).getErrorCode() + ":" + messages.getMessage(i).getDescription() + CRLF); break; case esriGPMessageType.esriGPMessageTypeWarning: getTextareaNotifications().setText( getTextareaNotifications().getText() + "Warning " + messages.getMessage(i).getErrorCode() + ":" + messages.getMessage(i).getDescription() + CRLF); break; default: getTextareaNotifications().setText( getTextareaNotifications().getText() + "Information " + messages.getMessage(i).getErrorCode() + ":" + messages.getMessage(i).getDescription() + CRLF); } } } // Zoom to the extent of the result IGeoDataset geodataset = new IGeoDatasetProxy(naContext.getNAClasses().getItemByName("SAPolygons")); IEnvelope envelope = geodataset.getExtent(); if (!envelope.isEmpty()) { envelope.expand(1.1, 1.1, true); getMap().setExtent(envelope); } naContext.getSolver().updateLayer((INALayer) getMap().getLayer(0)); // Refresh the map getMap().getActiveView().refresh(); } catch (Exception e) { e.printStackTrace(); } } }; t.start(); } private void applySolverSettings() throws Exception { // Set ServiceArea specific Settings INASolver naSolver = this.naContext.getSolver(); INAServiceAreaSolver saSolver = (INAServiceAreaSolver) naSolver; // Set generic Solver settings saSolver.setDefaultBreaks(parseBreaks(getTextBreaks().getText())); saSolver.setMergeSimilarPolygonRanges(false); if (getCheckboxShowLines().isSelected()) saSolver.setOutputLines(esriNAOutputLineType.esriNAOutputLineTrueShape); else saSolver.setOutputLines(esriNAOutputLineType.esriNAOutputLineNone); saSolver.setOutputPolygons(esriNAOutputPolygonType.esriNAOutputPolygonDetailed); saSolver.setOverlapLines(true); saSolver.setSplitLinesAtBreaks(false); saSolver.setTravelDirection(esriNATravelDirection.esriNATravelDirectionFromFacility); // set the impedance attribute INASolverSettings settings = (INASolverSettings) naSolver; settings.setImpedanceAttributeName(getComboboxCost().getSelectedItem().toString()); // Set the OneWay Restriction if necessary IStringArray restrictions = settings.getRestrictionAttributeNames(); restrictions.removeAll(); if (getCheckboxOneway().isSelected()) restrictions.add("oneway"); settings.setRestrictionAttributeNamesByRef(restrictions); // Restrict UTurns settings.setRestrictUTurns(esriNetworkForwardStarBacktrack.esriNFSBNoBacktrack); // Do not forget to update the context after you set your impedance naSolver.updateContext(this.naContext, getDENetworkDataset(this.naContext.getNetworkDataset()), new GPMessages()); } private IDoubleArray parseBreaks(String breaks) throws Exception { // Tokenize the comma-separated values to get the individual breaks StringTokenizer tokenizer = new StringTokenizer(breaks, " ,;"); IDoubleArray array = new DoubleArray(); while (tokenizer.hasMoreTokens()) { array.add(Double.valueOf(tokenizer.nextToken())); } return array; } private void displayOutput(final String naClass) throws Exception { ITable table = (ITable) this.naContext.getNAClasses().getItemByName(naClass); if (table == null) { SwingUtilities.invokeLater(new Runnable() { public void run() { getTextareaNotifications().setText("Couldn't get the " + naClass + " table"); } }); return; } String result = ""; ICursor cursor = table.ITable_search(null, false); IRow pRow = cursor.nextRow(); NumberFormat formatter = NumberFormat.getNumberInstance(); formatter.setMaximumFractionDigits(4); while (pRow != null) { result += CRLF; int FacilityID = (Integer) pRow.getValue(table.findField("FacilityID")); double fromBreak = (Double) pRow.getValue(table.findField("FromBreak")); double toBreak = (Double) pRow.getValue(table.findField("ToBreak")); result += ("FacilityID:" + FacilityID + CRLF + "FromBreak:" + formatter.format(fromBreak) + CRLF + "ToBreak:" + formatter.format(toBreak) + CRLF); pRow = cursor.nextRow(); } final String finalResult = result; SwingUtilities.invokeLater(new Runnable() { public void run() { getButtonSolve().setText("Find Service Area"); getButtonSolve().setEnabled(true); getTextareaNotifications().setText(finalResult); } }); } private void initializeUI() { Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize(); this.setSize((int) (dimension.getWidth() * 0.75), (int) (dimension.getHeight() * 0.75)); this.setContentPane(getJContentPane()); this.setTitle("ServiceArea Solver"); } private JPanel getJContentPane() { if (jContentPane == null) { jContentPane = new JPanel(); jContentPane.setLayout(new BorderLayout()); jContentPane.add(getMap(), BorderLayout.CENTER); jContentPane.add(getRightOuterPanel(), BorderLayout.EAST); } return jContentPane; } private MapBean getMap() { if (map == null) { try { map = new MapBean(); } catch (java.lang.Throwable e) { e.printStackTrace(); } } return map; } private JPanel getRightOuterPanel() { if (rightOuterPanel == null) { try { GridBagConstraints gridBagConstraints4 = new GridBagConstraints(); gridBagConstraints4.fill = GridBagConstraints.BOTH; gridBagConstraints4.weighty = 1.0; gridBagConstraints4.weightx = 1.0; GridBagConstraints gridBagConstraints10 = new GridBagConstraints(); gridBagConstraints10.fill = GridBagConstraints.BOTH; gridBagConstraints10.gridy = 1; gridBagConstraints10.weightx = 1.0; gridBagConstraints10.weighty = 1.0; gridBagConstraints10.gridx = 0; GridBagConstraints gridBagConstraints8 = new GridBagConstraints(); gridBagConstraints8.fill = GridBagConstraints.HORIZONTAL; gridBagConstraints8.gridx = 0; gridBagConstraints8.gridy = 0; gridBagConstraints8.anchor = GridBagConstraints.NORTH; rightOuterPanel = new JPanel(); rightOuterPanel.setLayout(new GridBagLayout()); rightOuterPanel.setBorder(BorderFactory.createLineBorder(SystemColor.activeCaption, 1)); rightOuterPanel.add(getRightPanel(), gridBagConstraints8); rightOuterPanel.add(getScroller(), gridBagConstraints10); } catch (java.lang.Throwable e) { e.printStackTrace(); } } return rightOuterPanel; } private JPanel getRightPanel() { if (rightPanel == null) { try { GridBagConstraints gridBagConstraints = new GridBagConstraints(); gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; gridBagConstraints.gridy = 0; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new Insets(0, 0, 0, 5); gridBagConstraints.gridx = 1; GridBagConstraints gridBagConstraints9 = new GridBagConstraints(); gridBagConstraints9.gridx = 0; gridBagConstraints9.gridwidth = 2; gridBagConstraints9.anchor = GridBagConstraints.WEST; gridBagConstraints9.insets = new Insets(0, 5, 2, 5); gridBagConstraints9.gridy = 5; GridBagConstraints gridBagConstraints7 = new GridBagConstraints(); gridBagConstraints7.gridx = 0; gridBagConstraints7.anchor = GridBagConstraints.WEST; gridBagConstraints7.insets = new Insets(0, 0, 0, 0); gridBagConstraints7.gridwidth = 2; gridBagConstraints7.gridy = 4; GridBagConstraints gridBagConstraints6 = new GridBagConstraints(); gridBagConstraints6.gridx = 0; gridBagConstraints6.anchor = GridBagConstraints.WEST; gridBagConstraints6.insets = new Insets(0, 0, 0, 0); gridBagConstraints6.gridwidth = 2; gridBagConstraints6.gridy = 3; GridBagConstraints gridBagConstraints3 = new GridBagConstraints(); gridBagConstraints3.fill = GridBagConstraints.HORIZONTAL; gridBagConstraints3.gridy = 1; gridBagConstraints3.weightx = 1.0; gridBagConstraints3.ipadx = 5; gridBagConstraints3.ipady = 0; gridBagConstraints3.insets = new Insets(0, 0, 0, 5); gridBagConstraints3.gridx = 1; GridBagConstraints gridBagConstraints2 = new GridBagConstraints(); gridBagConstraints2.gridx = 0; gridBagConstraints2.ipadx = 5; gridBagConstraints2.ipady = 0; gridBagConstraints2.anchor = GridBagConstraints.WEST; gridBagConstraints2.insets = new Insets(0, 5, 0, 0); gridBagConstraints2.gridy = 1; labelBreaks = new JLabel(); labelBreaks.setText("Breaks:"); GridBagConstraints gridBagConstraints1 = new GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.anchor = GridBagConstraints.WEST; gridBagConstraints1.ipadx = 5; gridBagConstraints1.ipady = 0; gridBagConstraints1.insets = new Insets(0, 5, 0, 0); gridBagConstraints1.gridy = 0; labelCost = new JLabel(); labelCost.setText("Cost Attribute:"); labelCost.setVerticalTextPosition(SwingConstants.CENTER); labelCost.setVerticalAlignment(SwingConstants.CENTER); rightPanel = new JPanel(); rightPanel.setLayout(new GridBagLayout()); rightPanel.setBorder(new SoftBevelBorder(SoftBevelBorder.RAISED)); rightPanel.add(labelCost, gridBagConstraints1); rightPanel.add(labelBreaks, gridBagConstraints2); rightPanel.add(getTextBreaks(), gridBagConstraints3); rightPanel.add(getCheckboxOneway(), gridBagConstraints6); rightPanel.add(getCheckboxShowLines(), gridBagConstraints7); rightPanel.add(getButtonSolve(), gridBagConstraints9); rightPanel.add(getComboboxCost(), gridBagConstraints); } catch (java.lang.Throwable e) { e.printStackTrace(); } } return rightPanel; } private JCheckBox getCheckboxOneway() { if (checkboxOneway == null) { try { checkboxOneway = new JCheckBox(); checkboxOneway.setText("Use One-Way Restrictions"); } catch (java.lang.Throwable e) { e.printStackTrace(); } } return checkboxOneway; } private JCheckBox getCheckboxShowLines() { if (checkboxShowLines == null) { try { checkboxShowLines = new JCheckBox(); checkboxShowLines.setText("Show Lines"); } catch (java.lang.Throwable e) { e.printStackTrace(); } } return checkboxShowLines; } private JButton getButtonSolve() { if (buttonSolve == null) { try { buttonSolve = new JButton(); buttonSolve.setText("Find Service Area"); buttonSolve.setBackground(Color.lightGray); buttonSolve.addActionListener(this); } catch (java.lang.Throwable e) { e.printStackTrace(); } } return buttonSolve; } private JTextArea getTextareaNotifications() { if (textareaNotifications == null) { try { textareaNotifications = new JTextArea(); textareaNotifications.setLineWrap(true); textareaNotifications.setEditable(false); } catch (java.lang.Throwable e) { e.printStackTrace(); } } return textareaNotifications; } private JComboBox getComboboxCost() { if (comboboxCost == null) { try { comboboxCost = new JComboBox(); } catch (java.lang.Throwable e) { e.printStackTrace(); } } return comboboxCost; } private JTextField getTextBreaks() { if (textBreaks == null) { try { textBreaks = new JTextField(); textBreaks.setPreferredSize(new Dimension(80, 25)); textBreaks.setText("1 2 3"); } catch (java.lang.Throwable e) { e.printStackTrace(); } } return textBreaks; } private JScrollPane getScroller() { if (scroller == null) { try { scroller = new JScrollPane(getTextareaNotifications()); } catch (java.lang.Throwable e) { e.printStackTrace(); } } return scroller; } static void initializeInterop() { // Visual beans mode required for multi-threaded applciations like Swing. EngineInitializer.initializeVisualBeans(); } static void initializeArcGISLicenses() { try { AoInitialize ao = new AoInitialize(); if (ao.isProductCodeAvailable(esriLicenseProductCode.esriLicenseProductCodeEngine) == esriLicenseStatus.esriLicenseAvailable) ao.initialize(esriLicenseProductCode.esriLicenseProductCodeEngine); else if (ao.isProductCodeAvailable(esriLicenseProductCode.esriLicenseProductCodeArcView) == esriLicenseStatus.esriLicenseAvailable) ao.initialize(esriLicenseProductCode.esriLicenseProductCodeArcView); else { System.err.println("Could not initialize an Engine or ArcView license. Exiting application."); System.exit(-1); } ao.checkOutExtension(esriLicenseExtensionCode.esriLicenseExtensionCodeNetwork); } catch (Exception e) { e.printStackTrace(); } } private JPanel jContentPane = null; private JPanel rightPanel = null; private JLabel labelCost = null; private JLabel labelBreaks = null; private JTextField textBreaks = null; private JCheckBox checkboxOneway = null; private JCheckBox checkboxShowLines = null; private JPanel rightOuterPanel = null; private JButton buttonSolve = null; private JTextArea textareaNotifications = null; private JComboBox comboboxCost = null; private JScrollPane scroller = null; }