001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032:
033: package com.vividsolutions.jump.workbench.ui.plugin;
034:
035: import java.util.Iterator;
036:
037: import com.vividsolutions.jts.geom.Coordinate;
038: import com.vividsolutions.jts.geom.Envelope;
039: import com.vividsolutions.jts.geom.Geometry;
040: import com.vividsolutions.jts.geom.GeometryCollection;
041: import com.vividsolutions.jts.geom.Polygon;
042: import com.vividsolutions.jump.I18N;
043: import com.vividsolutions.jump.feature.Feature;
044: import com.vividsolutions.jump.workbench.model.Layer;
045: import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn;
046: import com.vividsolutions.jump.workbench.plugin.PlugInContext;
047: import com.vividsolutions.jump.workbench.ui.HTMLFrame;
048:
049: /**
050: * Computes various statistics for selected layers.
051: */
052: public class LayerStatisticsPlugIn extends AbstractPlugIn {
053: public LayerStatisticsPlugIn() {
054: }
055:
056: public boolean execute(PlugInContext context) throws Exception {
057: //Call #getSelectedLayers before #clear, because #clear will surface
058: //output window. [Jon Aquino]
059: Layer[] selectedLayers = context.getSelectedLayers();
060: HTMLFrame out = context.getOutputFrame();
061: out.createNewDocument();
062: out
063: .addHeader(
064: 1,
065: I18N
066: .get("ui.plugin.LayerStatisticsPlugIn.layer-statistics"));
067:
068: LayerStatistics totalStats = new LayerStatistics();
069: Envelope totalEnv = new Envelope();
070:
071: for (int i = 0; i < selectedLayers.length; i++) {
072: Layer layer = selectedLayers[i];
073: LayerStatistics ls = layerStatistics(layer, totalStats);
074:
075: out.addHeader(2, I18N
076: .get("ui.plugin.LayerStatisticsPlugIn.layer")
077: + " " + layer.getName());
078:
079: Envelope layerEnv = layer.getFeatureCollectionWrapper()
080: .getEnvelope();
081: out.addField(I18N
082: .get("ui.plugin.LayerStatisticsPlugIn.envelope"),
083: layerEnv.toString());
084: totalEnv.expandToInclude(layerEnv);
085: output(ls, out);
086: }
087:
088: if (selectedLayers.length > 1) {
089: out
090: .addHeader(
091: 2,
092: I18N
093: .get("ui.plugin.LayerStatisticsPlugIn.summary-for-all-layers"));
094: out.addField(I18N
095: .get("ui.plugin.LayerStatisticsPlugIn.envelope"),
096: totalEnv.toString());
097: output(totalStats, out);
098: }
099: out.surface();
100:
101: return true;
102: }
103:
104: private LayerStatistics layerStatistics(final Layer layer,
105: LayerStatistics totalStats) {
106: LayerStatistics ls = new LayerStatistics();
107:
108: for (Iterator i = layer.getFeatureCollectionWrapper()
109: .iterator(); i.hasNext();) {
110: Feature f = (Feature) i.next();
111: Geometry g = f.getGeometry();
112: double area = g.getArea();
113: double length = g.getLength();
114:
115: // these both need work - need to recurse into geometries
116: int comps = 1;
117:
118: if (g instanceof GeometryCollection) {
119: comps = ((GeometryCollection) g).getNumGeometries();
120: }
121:
122: Coordinate[] pts = g.getCoordinates();
123: int holes = 0;
124:
125: if (g instanceof Polygon) {
126: holes = ((Polygon) g).getNumInteriorRing();
127: }
128:
129: ls.addFeature(pts.length, holes, comps, area, length);
130: totalStats.addFeature(pts.length, holes, comps, area,
131: length);
132: }
133:
134: return ls;
135: }
136:
137: public void output(LayerStatistics ls, HTMLFrame out) {
138: //========= Output ===============
139: out.addField("# Features:", ls.featureCount + "");
140:
141: out.append("<table border='1'>");
142: out
143: .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'> "
144: + I18N
145: .get("ui.plugin.LayerStatisticsPlugIn.avg")
146: + " </td><td bgcolor=#CCCCCC align='center'> Total </td></tr>");
147: out
148: .append("<tr><td bgcolor=#CCCCCC> Pts </td><td align='right'>"
149: + ls.minCoord
150: + "</td><td align='right'>"
151: + ls.maxCoord
152: + "</td><td align='right'>"
153: + ls.avgCoord()
154: + "</td><td align='right'>"
155: + ls.totalCoord + "</td></tr>");
156: out.append("<tr><td bgcolor=#CCCCCC> "
157: + I18N.get("ui.plugin.LayerStatisticsPlugIn.holes")
158: + " </td><td align='right'>" + ls.minHoles
159: + "</td><td align='right'>" + ls.maxHoles
160: + "</td><td align='right'>" + ls.avgHoles()
161: + "</td><td align='right'>" + ls.totalHoles
162: + "</td></tr>");
163: out
164: .append("<tr><td bgcolor=#CCCCCC> "
165: + I18N
166: .get("ui.plugin.LayerStatisticsPlugIn.components")
167: + " </td><td align='right'>" + ls.minComp
168: + "</td><td align='right'>" + ls.maxComp
169: + "</td><td align='right'>" + ls.avgComp()
170: + "</td><td align='right'>" + ls.totalComp
171: + "</td></tr>");
172: out.append("<tr><td bgcolor=#CCCCCC> "
173: + I18N.get("ui.plugin.LayerStatisticsPlugIn.area")
174: + " </td><td align='right'>" + ls.minArea
175: + "</td><td align='right'>" + ls.maxArea
176: + "</td><td align='right'>" + ls.avgArea()
177: + "</td><td align='right'>" + ls.totalArea
178: + "</td></tr>");
179: out.append("<tr><td bgcolor=#CCCCCC> "
180: + I18N.get("ui.plugin.LayerStatisticsPlugIn.length")
181: + " </td><td align='right'>" + ls.minLength
182: + "</td><td align='right'>" + ls.maxLength
183: + "</td><td align='right'>" + ls.avgLength()
184: + "</td><td align='right'>" + ls.totalLength
185: + "</td></tr>");
186: out.append("</table>");
187: }
188:
189: public class LayerStatistics {
190: boolean isFirst = true;
191: int minCoord = 0;
192: int maxCoord = 0;
193: int totalCoord = 0;
194: int minComp = 0;
195: int maxComp = 0;
196: int totalComp = 0;
197: int minHoles = 0;
198: int maxHoles = 0;
199: int totalHoles = 0;
200: double minArea = 0.0;
201: double maxArea = 0.0;
202: double totalArea = 0.0;
203: double minLength = 0.0;
204: double maxLength = 0.0;
205: double totalLength = 0.0;
206: int featureCount = 0;
207:
208: public void addFeature(int coordCount, int holeCount,
209: int compCount, double area, double length) {
210: featureCount++;
211:
212: if (isFirst || (coordCount < minCoord)) {
213: minCoord = coordCount;
214: }
215:
216: if (isFirst || (coordCount > maxCoord)) {
217: maxCoord = coordCount;
218: }
219:
220: totalCoord += coordCount;
221:
222: if (isFirst || (holeCount < minHoles)) {
223: minHoles = holeCount;
224: }
225:
226: if (isFirst || (holeCount > maxHoles)) {
227: maxHoles = holeCount;
228: }
229:
230: totalHoles += holeCount;
231:
232: if (isFirst || (compCount < minComp)) {
233: minComp = compCount;
234: }
235:
236: if (isFirst || (compCount > maxComp)) {
237: maxComp = compCount;
238: }
239:
240: totalComp += compCount;
241:
242: if (isFirst || (area < minArea)) {
243: minArea = area;
244: }
245:
246: if (isFirst || (area > maxArea)) {
247: maxArea = area;
248: }
249:
250: totalArea += area;
251:
252: if (isFirst || (length < minLength)) {
253: minLength = length;
254: }
255:
256: if (isFirst || (length > maxLength)) {
257: maxLength = length;
258: }
259:
260: totalLength += length;
261:
262: isFirst = false;
263: }
264:
265: public double avgCoord() {
266: return (featureCount == 0) ? 0.0
267: : (totalCoord / featureCount);
268: }
269:
270: public double avgHoles() {
271: return (featureCount == 0) ? 0.0
272: : (totalHoles / featureCount);
273: }
274:
275: public double avgComp() {
276: return (featureCount == 0) ? 0.0
277: : (totalComp / featureCount);
278: }
279:
280: public double avgArea() {
281: return (featureCount == 0) ? 0.0
282: : (totalArea / featureCount);
283: }
284:
285: public double avgLength() {
286: return (featureCount == 0) ? 0.0
287: : (totalLength / featureCount);
288: }
289: }
290: }
|