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: package com.vividsolutions.jump.workbench.ui.plugin;
033:
034: import java.util.ArrayList;
035: import java.util.Collection;
036: import java.util.Iterator;
037: import java.util.List;
038: import com.vividsolutions.jts.algorithm.PointLocator;
039: import com.vividsolutions.jts.geom.*;
040: import com.vividsolutions.jts.io.WKTWriter;
041: import com.vividsolutions.jump.I18N;
042: import com.vividsolutions.jump.feature.Feature;
043: import com.vividsolutions.jump.io.FUTURE_JTS_WKTWriter;
044: import com.vividsolutions.jump.util.Fmt;
045: import com.vividsolutions.jump.workbench.model.FenceLayerFinder;
046: import com.vividsolutions.jump.workbench.model.Layer;
047: import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn;
048: import com.vividsolutions.jump.workbench.plugin.PlugInContext;
049: import com.vividsolutions.jump.workbench.ui.GUIUtil;
050: import com.vividsolutions.jump.workbench.ui.TextFrame;
051:
052: public class VerticesInFencePlugIn extends AbstractPlugIn {
053: private FUTURE_JTS_WKTWriter wktWriter = new FUTURE_JTS_WKTWriter();
054: private GeometryFactory factory = new GeometryFactory();
055:
056: public VerticesInFencePlugIn() {
057: }
058:
059: public boolean execute(PlugInContext context) throws Exception {
060: reportNothingToUndoYet(context);
061: TextFrame textFrame = new TextFrame(context.getWorkbenchFrame());
062: textFrame
063: .setTitle(I18N
064: .get("ui.plugin.VerticesInFencePlugIn.vertices-in-fence"));
065: textFrame.clear();
066: textFrame.setText(description(context));
067: textFrame.setSize(550, 300);
068: context.getWorkbenchFrame().addInternalFrame(textFrame);
069: return true;
070: }
071:
072: private String description(PlugInContext context) {
073: FenceLayerFinder fenceLayerFinder = new FenceLayerFinder(
074: context);
075: StringBuffer description = new StringBuffer();
076: description.append("<html><body>");
077: for (Iterator i = context.getLayerManager().iterator(); i
078: .hasNext();) {
079: Layer layer = (Layer) i.next();
080: if (!layer.isVisible()) {
081: continue;
082: }
083: if (layer == fenceLayerFinder.getLayer()) {
084: continue;
085: }
086: description.append(description(layer, context));
087: }
088: description.append("</body></html>");
089: return description.toString();
090: }
091:
092: public static Collection verticesInFence(Collection geometries,
093: Geometry fence, boolean skipClosingVertex) {
094: ArrayList verticesInFence = new ArrayList();
095: for (Iterator i = geometries.iterator(); i.hasNext();) {
096: Geometry geometry = (Geometry) i.next();
097: verticesInFence.addAll(verticesInFence(geometry, fence,
098: skipClosingVertex).getCoordinates());
099: }
100: return verticesInFence;
101: }
102:
103: /**
104: * @param skipClosingVertex whether to ignore the duplicate point that closes off a
105: * LinearRing or Polygon
106: */
107: public static VerticesInFence verticesInFence(Geometry geometry,
108: final Geometry fence, final boolean skipClosingVertex) {
109: final ArrayList coordinates = new ArrayList();
110: final ArrayList indices = new ArrayList();
111: //PointLocator is non-re-entrant. Therefore, create a new instance for each fence.
112: //[Jon Aquino]
113: final PointLocator pointLocator = new PointLocator();
114: final IntWrapper index = new IntWrapper(-1);
115: geometry.apply(new GeometryComponentFilter() {
116: public void filter(Geometry geometry) {
117: if (geometry instanceof GeometryCollection
118: || geometry instanceof Polygon) {
119: //Wait for the elements to be passed into the filter [Jon Aquino]
120: return;
121: }
122: Coordinate[] component = geometry.getCoordinates();
123: for (int j = 0; j < component.length; j++) {
124: index.value++;
125: if (skipClosingVertex && (component.length > 1)
126: && (j == (component.length - 1))
127: && component[j].equals(component[0])) {
128: continue;
129: }
130: if (pointLocator.locate(component[j], fence) == Location.EXTERIOR) {
131: continue;
132: }
133: coordinates.add(component[j]);
134: indices.add(new Integer(index.value));
135: }
136: }
137: });
138: return new VerticesInFence() {
139: public List getCoordinates() {
140: return coordinates;
141: }
142:
143: public int getIndex(int i) {
144: return ((Integer) indices.get(i)).intValue();
145: }
146: };
147: }
148:
149: /**
150: *@return an empty String if the layer has no coordinates in the fence
151: */
152: private String description(Layer layer, PlugInContext context) {
153: boolean foundVertices = false;
154: String description = "<Table width=100%><tr><td colspan=2 valign=top><i>"
155: + I18N.get("ui.plugin.VerticesInFencePlugIn.layer")
156: + " </i><font color='#3300cc'><b>"
157: + layer.getName()
158: + "</b></font></td></tr>";
159: String bgcolor = "darkgrey";
160: for (Iterator i = layer.getFeatureCollectionWrapper().query(
161: context.getLayerViewPanel().getFence()
162: .getEnvelopeInternal()).iterator(); i.hasNext();) {
163: Feature feature = (Feature) i.next();
164: VerticesInFence verticesInFence = verticesInFence(feature
165: .getGeometry(), context.getLayerViewPanel()
166: .getFence(), true);
167: if (verticesInFence.getCoordinates().isEmpty()) {
168: continue;
169: }
170: if (bgcolor.equals("#faebd7")) {
171: bgcolor = "darkgrey";
172: } else {
173: bgcolor = "#faebd7";
174: }
175: foundVertices = true;
176: //<<TODO:DEFECT>> Get platform-specific newline rather than "\n" [Jon Aquino]
177: description += ("<tr bgcolor="
178: + bgcolor
179: + "><td width=10% valign=top><font size='-1'><i>"
180: + I18N
181: .get("ui.plugin.VerticesInFencePlugIn.feature-id")
182: + " </i></font><font size='-1' color='#3300cc'><b>"
183: + feature.getID() + "</b></font><td>");
184: description += description(verticesInFence, feature
185: .getGeometry());
186: description += "</td></tr>";
187: }
188: description += "</table>";
189: return foundVertices ? description : "";
190: }
191:
192: private WKTDisplayHelper helper = new WKTDisplayHelper();
193:
194: private String description(VerticesInFence verticesInFence,
195: Geometry geometry) {
196: StringBuffer description = new StringBuffer();
197: //<<TODO:FEATURE>> Perhaps we should change these \n's to the line separators
198: //specific to the current platform. Then the user could copy the text and
199: //paste it to any editor without any funny symbols potentially appearing. [Jon Aquino]
200: description.append("<pre>");
201: for (int i = 0; i < verticesInFence.getCoordinates().size(); i++) {
202: description.append(GUIUtil.escapeHTML("["
203: + Fmt.fmt(helper.annotation(geometry,
204: (Coordinate) verticesInFence
205: .getCoordinates().get(i)), 10)
206: + "] "
207: + wktWriter.write(factory
208: .createPoint((Coordinate) verticesInFence
209: .getCoordinates().get(i))) + "\n",
210: false, false));
211: }
212: description.append("</pre>");
213: return description.toString();
214: }
215:
216: public static interface VerticesInFence {
217: public List getCoordinates();
218:
219: public int getIndex(int i);
220: }
221:
222: private static class IntWrapper {
223: public int value;
224:
225: public IntWrapper(int value) {
226: this .value = value;
227: }
228: }
229:
230: public static void main(String[] args) {
231: new WKTWriter();
232: ((Geometry) (new Object())).toString();
233: }
234: }
|