// Other needed: boundary combination orientations // path analysis tools - based on calc shortest paths /** * BoundaryTypeAnalyst.java * * --Copyright notice-- * * Copyright (c) School of Geography, University of Leeds. * http://www.geog.leeds.ac.uk/ * This software is licensed under 'The Artistic License' which can be found at * the Open Source Initiative website at... * http://www.opensource.org/licenses/artistic-license.php * Please note that the optional Clause 8 does not apply to this code. * * The Standard Version source code, and associated documentation can be found at... * [online] http://www.ccg.leeds.ac.uk/software/ * * --End of Copyright notice-- * **/ // Line type statistics package uk.ac.leeds.ccg.boundarytypeanalyst; import java.io.*; import java.util.Properties; import com.esri.arcgis.addins.desktop.Extension; import com.esri.arcgis.arcmapui.*; import com.esri.arcgis.carto.*; import com.esri.arcgis.catalog.IGxCatalogDefaultDatabase; import com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory; import com.esri.arcgis.datasourcesfile.ShapefileWorkspaceFactory; import com.esri.arcgis.framework.*; import com.esri.arcgis.geodatabase.*; import com.esri.arcgis.geometry.IEnvelope; import com.esri.arcgis.interop.AutomationException; import com.esri.arcgis.system.IName; /** * ArcGIS extension to calculate various topological statistics. * * @author Andrew Evans * @version 0.1 */ public class BoundaryTypeAnalyst extends Extension { private static BoundaryTypeAnalyst bta = null; private IApplication app; private IMxDocument mxDoc; private IMap map; private IGeoFeatureLayer[] iGeoFeaturelayers; private TopologyLayer topologyLayer; private IFeatureDatasetProxy ifeatureDatasetProxyGot; private IWorkspaceProxy iWorkspaceProxy; private IWorkspace iWorkspace; private IFeatureWorkspace ifeatureWorkspace; private IFeatureDatasetProxy ifeatureDatasetProxyOpened; private IFeatureClassProxy[] iFeatureClassProxys; private ITopology it; private ITopologyGraph iTopologyGraph; private boolean debug = false; // Set true for messages private boolean select = false; // Set true to select treated elements on the map for debugging private String directoryString = null; // Initialisation methods ------------------------------------------------------- /** * Public constructor, but for Singleton. Do not use. * Note that unlike a usual singleton the constructor needs to * be public for ArcGIS to work its addIn magic. **/ public BoundaryTypeAnalyst() { bta = this; } /** * Singleton access method. **/ public static BoundaryTypeAnalyst getInstance() { return bta; } /** * Initializes this application extension with the ArcMap application instance it is hosted in. * * This method is automatically called by the host ArcMap application. * It marks the start of the dockable window's lifecycle. * Clients must not call this method. * * @param app is a reference to ArcMap's IApplication interface * @exception java.io.IOException if there are interop problems. * @exception com.esri.arcgis.interop.AutomationException if the component throws an ArcObjects exception. */ @Override public void init(IApplication app) throws IOException, AutomationException { this.app = app; mxDoc = (IMxDocument)app.getDocument(); //Set up an event to respond to a new document event in ArcMap. ((MxDocument)mxDoc).addIDocumentEventsListener(new IDocumentEventsAdapter(){ @Override public void openDocument(IDocumentEventsOpenDocumentEvent e){ try { map = mxDoc.getFocusMap(); if (map.getLayerCount() > 1) { initialiseMapVariables(); } } catch (AutomationException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } } }); } /** * Sets up map objects, feature class and layer arrays. */ public void initialiseMapVariables(){ try { // Set up arrays of the feature layers (- topology layer) and their classes. iGeoFeaturelayers = new IGeoFeatureLayer[map.getLayerCount() - 1]; iFeatureClassProxys = new IFeatureClassProxy[map.getLayerCount()]; // Loop through layers and set up the above arrays. Also find topology layer. ILayer iLayer = null; int countFeatureLayers = 0; for (int i=0; i < map.getLayerCount(); i++) { iLayer = map.getLayer(i); if (iLayer instanceof TopologyLayer) { topologyLayer = (TopologyLayer) map.getLayer(i); if (debug) System.out.println("topologyLayer = " + topologyLayer.getName()); } else { iGeoFeaturelayers[countFeatureLayers] = (IGeoFeatureLayer) map.getLayer(i); iFeatureClassProxys[countFeatureLayers] = (IFeatureClassProxy) iGeoFeaturelayers[countFeatureLayers].getFeatureClass(); if (debug) System.out.println("iGeoFeaturelayer = " + iGeoFeaturelayers[countFeatureLayers].getName()); if (debug) System.out.println("iFeatureClassProxys = " + iFeatureClassProxys[countFeatureLayers].getAliasName()); countFeatureLayers++; } } // Set up the workspace. ifeatureDatasetProxyGot = (IFeatureDatasetProxy) iGeoFeaturelayers[0].getFeatureClass().getFeatureDataset(); if (ifeatureDatasetProxyGot == null) { IWorkspaceFactory workspaceFactory = new FileGDBWorkspaceFactory () ; IWorkspaceName workspaceName = workspaceFactory.create("c:\temp","tempGDB",null,0); IName name = (IName) workspaceName; iWorkspace = (IWorkspace) name.open(); System.out.println(iWorkspace.getPathName()); } else { iWorkspaceProxy = (IWorkspaceProxy) ifeatureDatasetProxyGot.getWorkspace(); IWorkspaceFactory wf = iWorkspaceProxy.getWorkspaceFactory(); iWorkspace = wf.openFromFile(iWorkspaceProxy.getPathName(), 0); System.out.println(iWorkspaceProxy.getPathName()); } ifeatureWorkspace = (IFeatureWorkspace)iWorkspace; // Unused alternative... //ifeatureDatasetProxyOpened = (IFeatureDatasetProxy) ifeatureWorkspace.openFeatureDataset("Winchester"); // Set up topology and graph. it = topologyLayer.getTopology(); iTopologyGraph = (ITopologyGraph) it.getCache(); IEnvelope ie =((Map)map).getExtent(); iTopologyGraph.build(ie, true); ie = iTopologyGraph.getBuildExtent(); if (debug) System.out.println("Build extent width = " + ie.getWidth()); ie = iTopologyGraph.getExtent(); if (debug) System.out.println("Extent width = " + ie.getWidth()); } catch (AutomationException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } // Accessor/Mutator methods ------------------------------------------------------- /** * Convenience method for returning all the system and map variables you * might need in one go. The code to get the variables is: *
* *
* Object[] variables = extension.getVariables(); * * app = (IApplication) variables[0]; * mxDoc = (IMxDocument) variables[1]; * map = (IMap) variables[2]; * iGeoFeaturelayers = (IGeoFeatureLayer[]) variables[3]; * topologyLayer = (TopologyLayer) variables[4]; * ifeatureDatasetProxyGot = (IFeatureDatasetProxy) variables[5]; * iWorkspaceProxy = (IWorkspaceProxy) variables[6]; * iWorkspace = (IWorkspace) variables[7]; * ifeatureWorkspace = (IFeatureWorkspace) variables[8]; * ifeatureDatasetProxyOpened = (IFeatureDatasetProxy) variables[9]; * iFeatureClassProxys = (IFeatureClassProxy[]) variables[10]; * it = (ITopology) variables[11]; * iTopologyGraph = (ITopologyGraph) variables[12]; * debug = ((Boolean) variables[13]).booleanValue(); * select = ((Boolean) variables[14]).booleanValue(); **
* debug allows debugging console messages.
* select allows map elements to be selected as the code runs - for
* debugging
*
* @return Object array containing variables - see details.
*/
public Object[] getVariables() {
Object[] variables = new Object[15];
variables[0] = (Object) app;
variables[1] = (Object) mxDoc;
variables[2] = (Object) map;
variables[3] = (Object) iGeoFeaturelayers;
variables[4] = (Object) topologyLayer;
variables[5] = (Object) ifeatureDatasetProxyGot;
variables[6] = (Object) iWorkspaceProxy;
variables[7] = (Object) iWorkspace;
variables[8] = (Object) ifeatureWorkspace;
variables[9] = (Object) ifeatureDatasetProxyOpened;
variables[10] = (Object) iFeatureClassProxys;
variables[11] = (Object) it;
variables[12] = (Object) iTopologyGraph;
variables[13] = (Object) new Boolean(debug);
variables[14] = (Object) new Boolean(select);
return variables;
}
/**
* Method to get the output directory.
* Returns null if this can't be read from the properties file.
* @see readProperties()
* @return Path to output directory.
*/
public String getDirectoryString() {
return directoryString;
}
// Utility methods -------------------------------------------------------
/**
* Method to read properties from a file in the directory in which the default geodatabase resides.
* If it can't read the file it quietly returns with defaults. Ideally it would check the default geodatabase
* with the users, but the use cases are complicated.
* This method is called by external classes, in part because calling it at document openning isn't helpful -
* there seems to be no guarentee that other addin classes are available to receive the data.
*/
public void readProperties() {
IGxCatalogDefaultDatabase ig = (IGxCatalogDefaultDatabase) app;
Properties properties = new Properties();
FileInputStream fis = null;
try {
String defaultPath = ig.getDefaultDatabaseName().getPathName();
defaultPath = defaultPath.substring(0, defaultPath.lastIndexOf(File.separator));
File propertiesFile = new File(defaultPath + File.separator + "boundaryTypeAnalyst.properties");
if (propertiesFile.exists() && propertiesFile.canRead()) {
fis = new FileInputStream(propertiesFile);
properties.load(fis);
fis.close();
directoryString = properties.getProperty("OutputDirectory");
if (debug) System.out.println("Properties read from " + defaultPath + File.separator + "boundaryTypeAnalyst.properties");
} else {
directoryString = null; // Default - forces use of the user directory.
}
} catch (AutomationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Method to write properties file to the directory in which the default geodatabase resides.
* If it can't write to the file it quietly returns. Ideally it would reset the default geodatabase
* but the use cases are complicated.
* This method is called by external classes, in part because calling it at shutdown didn't seem to
* work, but also because the crash-rate of Arc means it is better to record properties as they change.
*/
public void writeProperties() {
IGxCatalogDefaultDatabase ig = (IGxCatalogDefaultDatabase) app;
FileOutputStream fos = null;
Properties properties = new Properties();
properties.put("OutputDirectory", ChangeOutputDirectory.getInstance().getDirectory().getAbsolutePath());
try {
String defaultPath = ig.getDefaultDatabaseName().getPathName();
defaultPath = defaultPath.substring(0, defaultPath.lastIndexOf(File.separator));
File propertiesFile = new File(defaultPath + File.separator + "boundaryTypeAnalyst.properties");
fos = new FileOutputStream(defaultPath + File.separator + "boundaryTypeAnalyst.properties");
properties.store(fos, null);
fos.close();
if (debug) System.out.println("Properties written to " + defaultPath + File.separator + "boundaryTypeAnalyst.properties");
} catch (AutomationException e) {
e.printStackTrace();
} catch (IOException e) {
if (debug) System.out.println("Can't write properties file");
}
}
/**
* Method for listing the FeatureDataSet and Topology names
*/
private void getTopologyNames() {
try {
FeatureDatasetName ifdn = (FeatureDatasetName)ifeatureDatasetProxyGot.getFullName();
System.out.println("name = " + ifdn.getName());
System.out.println("name = " + ifdn.getTopologyNames().next().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
// End of class
}