/* * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI * for visualizing and manipulating spatial features with geometry and attributes. * * Copyright (C) 2003 Vivid Solutions * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jump.workbench.ui.plugin; import java.util.Iterator; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jump.I18N; import com.vividsolutions.jump.feature.Feature; import com.vividsolutions.jump.workbench.WorkbenchContext; import com.vividsolutions.jump.workbench.model.Layer; import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn; import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory; import com.vividsolutions.jump.workbench.plugin.MultiEnableCheck; import com.vividsolutions.jump.workbench.plugin.PlugInContext; import com.vividsolutions.jump.workbench.ui.HTMLFrame; import com.vividsolutions.jump.workbench.ui.MenuNames; /** * Computes various statistics for selected layers. */ public class LayerStatisticsPlugIn extends AbstractPlugIn { public LayerStatisticsPlugIn() { } public void initialize(PlugInContext context) throws Exception { FeatureInstaller featureInstaller = new FeatureInstaller(context.getWorkbenchContext()); featureInstaller.addMainMenuItem( this, //exe new String[] {MenuNames.TOOLS, MenuNames.STATISTICS}, //menu path this.getName() + "...", //name methode .getName recieved by AbstractPlugIn false, //checkbox null, //icon createEnableCheck(context.getWorkbenchContext())); //enable check } public static MultiEnableCheck createEnableCheck(WorkbenchContext workbenchContext) { EnableCheckFactory checkFactory = new EnableCheckFactory(workbenchContext); return new MultiEnableCheck() .add(checkFactory.createWindowWithLayerNamePanelMustBeActiveCheck()) .add(checkFactory.createAtLeastNLayersMustBeSelectedCheck(1)); } public boolean execute(PlugInContext context) throws Exception { //Call #getSelectedLayers before #clear, because #clear will surface //output window. [Jon Aquino] Layer[] selectedLayers = context.getSelectedLayers(); HTMLFrame out = context.getOutputFrame(); out.createNewDocument(); out.addHeader(1, I18N.get("ui.plugin.LayerStatisticsPlugIn.layer-statistics")); LayerStatistics totalStats = new LayerStatistics(); Envelope totalEnv = new Envelope(); for (int i = 0; i < selectedLayers.length; i++) { Layer layer = selectedLayers[i]; LayerStatistics ls = layerStatistics(layer, totalStats); out.addHeader(2, I18N.get("ui.plugin.LayerStatisticsPlugIn.layer")+" " + layer.getName()); Envelope layerEnv = layer.getFeatureCollectionWrapper().getEnvelope(); out.addField(I18N.get("ui.plugin.LayerStatisticsPlugIn.envelope"), layerEnv.toString()); totalEnv.expandToInclude(layerEnv); output(ls, out); } if (selectedLayers.length > 1) { out.addHeader(2, I18N.get("ui.plugin.LayerStatisticsPlugIn.summary-for-all-layers")); out.addField(I18N.get("ui.plugin.LayerStatisticsPlugIn.envelope"), totalEnv.toString()); output(totalStats, out); } out.surface(); return true; } private LayerStatistics layerStatistics(final Layer layer, LayerStatistics totalStats) { LayerStatistics ls = new LayerStatistics(); for (Iterator i = layer.getFeatureCollectionWrapper().iterator(); i.hasNext();) { Feature f = (Feature) i.next(); Geometry g = f.getGeometry(); double area = g.getArea(); double length = g.getLength(); // these both need work - need to recurse into geometries // work done by mmichaud on 2010-12-12 int[] comps_and_holes = new int[]{0,0}; comps_and_holes = recurse(g, comps_and_holes); int comps = comps_and_holes[0]; int holes = comps_and_holes[1]; Coordinate[] pts = g.getCoordinates(); ls.addFeature(pts.length, holes, comps, area, length); totalStats.addFeature(pts.length, holes, comps, area, length); } return ls; } private int[] recurse(Geometry g, int[] comps_holes) { if (g instanceof GeometryCollection) { for (int i = 0 ; i < g.getNumGeometries() ; i++) { comps_holes = recurse(g.getGeometryN(i), comps_holes); } } else { comps_holes[0]++; if (g instanceof Polygon) { comps_holes[1] += ((Polygon)g).getNumInteriorRing(); } } return comps_holes; } public void output(LayerStatistics ls, HTMLFrame out) { //========= Output =============== out.addField("# Features:", ls.featureCount + ""); out.append("<table border='1'>"); out.append( "<tr><td bgcolor=#CCCCCC> </td><td bgcolor=#CCCCCC align='center'> Min </td><td bgcolor=#CCCCCC align='center'> Max </td><td bgcolor=#CCCCCC align='center'> "+I18N.get("ui.plugin.LayerStatisticsPlugIn.avg")+" </td><td bgcolor=#CCCCCC align='center'> Total </td></tr>"); out.append("<tr><td bgcolor=#CCCCCC> Pts </td><td align='right'>" + ls.minCoord + "</td><td align='right'>" + ls.maxCoord + "</td><td align='right'>" + ls.avgCoord() + "</td><td align='right'>" + ls.totalCoord + "</td></tr>"); out.append("<tr><td bgcolor=#CCCCCC> "+I18N.get("ui.plugin.LayerStatisticsPlugIn.holes")+" </td><td align='right'>" + ls.minHoles + "</td><td align='right'>" + ls.maxHoles + "</td><td align='right'>" + ls.avgHoles() + "</td><td align='right'>" + ls.totalHoles + "</td></tr>"); out.append( "<tr><td bgcolor=#CCCCCC> "+I18N.get("ui.plugin.LayerStatisticsPlugIn.components")+" </td><td align='right'>" + ls.minComp + "</td><td align='right'>" + ls.maxComp + "</td><td align='right'>" + ls.avgComp() + "</td><td align='right'>" + ls.totalComp + "</td></tr>"); out.append("<tr><td bgcolor=#CCCCCC> "+I18N.get("ui.plugin.LayerStatisticsPlugIn.area")+" </td><td align='right'>" + ls.minArea + "</td><td align='right'>" + ls.maxArea + "</td><td align='right'>" + ls.avgArea() + "</td><td align='right'>" + ls.totalArea + "</td></tr>"); out.append("<tr><td bgcolor=#CCCCCC> "+I18N.get("ui.plugin.LayerStatisticsPlugIn.length")+" </td><td align='right'>" + ls.minLength + "</td><td align='right'>" + ls.maxLength + "</td><td align='right'>" + ls.avgLength() + "</td><td align='right'>" + ls.totalLength + "</td></tr>"); out.append("</table>"); } public class LayerStatistics { boolean isFirst = true; int minCoord = 0; int maxCoord = 0; int totalCoord = 0; int minComp = 0; int maxComp = 0; int totalComp = 0; int minHoles = 0; int maxHoles = 0; int totalHoles = 0; double minArea = 0.0; double maxArea = 0.0; double totalArea = 0.0; double minLength = 0.0; double maxLength = 0.0; double totalLength = 0.0; int featureCount = 0; public void addFeature(int coordCount, int holeCount, int compCount, double area, double length) { featureCount++; if (isFirst || (coordCount < minCoord)) { minCoord = coordCount; } if (isFirst || (coordCount > maxCoord)) { maxCoord = coordCount; } totalCoord += coordCount; if (isFirst || (holeCount < minHoles)) { minHoles = holeCount; } if (isFirst || (holeCount > maxHoles)) { maxHoles = holeCount; } totalHoles += holeCount; if (isFirst || (compCount < minComp)) { minComp = compCount; } if (isFirst || (compCount > maxComp)) { maxComp = compCount; } totalComp += compCount; if (isFirst || (area < minArea)) { minArea = area; } if (isFirst || (area > maxArea)) { maxArea = area; } totalArea += area; if (isFirst || (length < minLength)) { minLength = length; } if (isFirst || (length > maxLength)) { maxLength = length; } totalLength += length; isFirst = false; } public double avgCoord() { return (featureCount == 0) ? 0.0 : ((double)totalCoord / featureCount); } public double avgHoles() { return (featureCount == 0) ? 0.0 : ((double)totalHoles / featureCount); } public double avgComp() { return (featureCount == 0) ? 0.0 : ((double)totalComp / featureCount); } public double avgArea() { return (featureCount == 0) ? 0.0 : (totalArea / featureCount); } public double avgLength() { return (featureCount == 0) ? 0.0 : (totalLength / featureCount); } } }