/* * 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.plugin.edit; import java.awt.Color; import javax.swing.ImageIcon; import javax.swing.JComboBox; import java.util.*; import com.vividsolutions.jump.I18N; import com.vividsolutions.jump.workbench.*; import com.vividsolutions.jump.workbench.model.*; import com.vividsolutions.jump.workbench.plugin.*; import com.vividsolutions.jump.workbench.ui.GUIUtil; import com.vividsolutions.jump.workbench.ui.MenuNames; import com.vividsolutions.jump.workbench.ui.MultiInputDialog; import com.vividsolutions.jump.workbench.ui.plugin.*; import com.vividsolutions.jump.feature.*; import com.vividsolutions.jts.util.*; import com.vividsolutions.jts.geom.*; import com.vividsolutions.jts.operation.polygonize.*; import com.vividsolutions.jts.geom.util.LinearComponentExtracter; import com.vividsolutions.jump.task.*; import com.vividsolutions.jump.workbench.ui.*; public class LineNoderPlugIn extends ThreadedBasePlugIn { private boolean useSelected = false; private MultiInputDialog dialog; private String layerName; private GeometryFactory fact = new GeometryFactory(); public LineNoderPlugIn() { } /** * Returns a very brief description of this task. * @return the name of this task */ public String getName() { return I18N.get("jump.plugin.edit.LineNoderPlugIn.Node-Lines"); } public void initialize(PlugInContext context) throws Exception { FeatureInstaller featureInstaller = new FeatureInstaller(context.getWorkbenchContext()); featureInstaller.addMainMenuItem( this, //exe new String[] {MenuNames.TOOLS, MenuNames.TOOLS_EDIT_GEOMETRY}, //menu path this.getName() + "...", //name methode .getName recieved by AbstractPlugIn false, //checkbox null, //icon createEnableCheck(context.getWorkbenchContext())); //enable check } public EnableCheck createEnableCheck(WorkbenchContext workbenchContext) { EnableCheckFactory checkFactory = new EnableCheckFactory(workbenchContext); return new MultiEnableCheck() .add(checkFactory.createWindowWithLayerManagerMustBeActiveCheck()) .add(checkFactory.createAtLeastNLayersMustExistCheck(1)); } public boolean execute(PlugInContext context) throws Exception { dialog = new MultiInputDialog( context.getWorkbenchFrame(), getName(), true); setDialogValues(dialog, context); GUIUtil.centreOnWindow(dialog); dialog.setVisible(true); if (!dialog.wasOKPressed()) { return false; } getDialogValues(dialog); return true; } public void run(TaskMonitor monitor, PlugInContext context) throws Exception { monitor.allowCancellationRequests(); Polygonizer polygonizer = new Polygonizer(); // polygonizer.setSplitLineStrings(splitLineStrings); monitor.report(I18N.get("jump.plugin.edit.LineNoderPlugIn.Noding")); Layer layer = dialog.getLayer(SRC_LAYER); Collection inputFeatures = getFeaturesToProcess(layer, context); Collection lines = getLines(inputFeatures); monitor.report(I18N.get("jump.plugin.edit.LineNoderPlugIn.Noding-input-lines")); Geometry nodedGeom = nodeLines((List) lines); Collection nodedLines = toLines(nodedGeom); if (monitor.isCancelRequested()) return; createLayer(context, nodedLines); } private Collection getFeaturesToProcess(Layer lyr, PlugInContext context){ if (useSelected) return context.getLayerViewPanel() .getSelectionManager().getFeaturesWithSelectedItems(lyr); return lyr.getFeatureCollectionWrapper().getFeatures(); } private Collection getLines(Collection inputFeatures) { List linesList = new ArrayList(); LinearComponentExtracter lineFilter = new LinearComponentExtracter(linesList); for (Iterator i = inputFeatures.iterator(); i.hasNext(); ) { Feature f = (Feature) i.next(); Geometry g = f.getGeometry(); g.apply(lineFilter); } return linesList; } /** * Nodes a collection of linestrings. * Noding is done via JTS union, which is reasonably effective but * may exhibit robustness failures. * * @param lines the linear geometries to node * @return a collection of linear geometries, noded together */ private Geometry nodeLines(Collection lines) { Geometry linesGeom = fact.createMultiLineString(fact.toLineStringArray(lines)); Geometry unionInput = fact.createMultiLineString(null); // force the unionInput to be non-empty if possible, to ensure union is not optimized away Geometry minLine = extractPoint(lines); if (minLine != null) unionInput = minLine; Geometry noded = linesGeom.union(unionInput); return noded; } private static List toLines(Geometry geom) { List linesList = new ArrayList(); LinearComponentExtracter lineFilter = new LinearComponentExtracter(linesList); geom.apply(lineFilter); return linesList; } private Geometry extractPoint(Collection lines) { int minPts = Integer.MAX_VALUE; Geometry point = null; // extract first point from first non-empty geometry for (Iterator i = lines.iterator(); i.hasNext(); ) { Geometry g = (Geometry) i.next(); if (! g.isEmpty()) { Coordinate p = g.getCoordinate(); point = g.getFactory().createPoint(p); } } return point; } private void createLayer(PlugInContext context, Collection nodedLines) throws Exception { FeatureCollection polyFC = FeatureDatasetFactory.createFromGeometry(nodedLines); context.addLayer( StandardCategoryNames.RESULT, layerName + " " +I18N.get("jump.plugin.edit.LineNoderPlugIn.Noded-Lines"), polyFC); } private final static String SRC_LAYER = I18N.get("jump.plugin.edit.LineNoderPlugIn.Line-Layer"); private final static String SELECTED_ONLY = GenericNames.USE_SELECTED_FEATURES_ONLY; private void setDialogValues(MultiInputDialog dialog, PlugInContext context) { dialog.setSideBarImage(new ImageIcon(getClass().getResource("Polygonize.png"))); dialog.setSideBarDescription(I18N.get("jump.plugin.edit.LineNoderPlugIn.Nodes-the-lines-in-a-layer")); String fieldName = SRC_LAYER; JComboBox addLayerComboBox = dialog.addLayerComboBox(fieldName, context.getCandidateLayer(0), null, context.getLayerManager()); dialog.addCheckBox(SELECTED_ONLY, useSelected); } private void getDialogValues(MultiInputDialog dialog) { Layer layer = dialog.getLayer(SRC_LAYER); layerName = layer.getName(); useSelected = dialog.getBoolean(SELECTED_ONLY); } }