/* * 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.analysis; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.*; import javax.swing.DefaultComboBoxModel; import javax.swing.ImageIcon; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import com.vividsolutions.jts.geom.*; import com.vividsolutions.jump.I18N; import com.vividsolutions.jts.operation.buffer.BufferOp; import com.vividsolutions.jts.operation.union.UnaryUnionOp; import com.vividsolutions.jump.feature.*; import com.vividsolutions.jump.task.*; import com.vividsolutions.jump.workbench.WorkbenchContext; import com.vividsolutions.jump.workbench.model.*; import com.vividsolutions.jump.workbench.plugin.*; import com.vividsolutions.jump.workbench.ui.*; import com.vividsolutions.jump.workbench.ui.images.IconLoader; import com.vividsolutions.jump.workbench.ui.plugin.FeatureInstaller; import com.vividsolutions.jump.workbench.ui.plugin.clipboard.PasteItemsPlugIn; public class BufferPlugIn extends AbstractPlugIn implements ThreadedPlugIn { public static final ImageIcon ICON = IconLoader.icon("buffer.gif"); private String LAYER ; private String DISTANCE; private String END_CAP_STYLE; private String QUADRANT_SEGMENTS; private String SELECTED_ONLY; private String UNION_RESULT; private String COPY_ATTRIUBTES; private String CAP_STYLE_ROUND; private String CAP_STYLE_SQUARE; private String CAP_STYLE_BUTT; private String ATTRIBUTE; private String FROMATTRIBUTE; private List endCapStyles; private MultiInputDialog dialog; private Layer layer; private double bufferDistance = 1.0; private String endCapStyle; private boolean exceptionThrown = false; private boolean useSelected = false; private int quadrantSegments = 16; private boolean unionResult = false; private String sideBarText = ""; private boolean copyAttributes = true; private boolean fromAttribute = false; private int attributeIndex = 0; public BufferPlugIn() { } private final String ROUND = "Round"; //Don't translate private final String SQUARE = "Square"; //Don't translate private final String BUTT = "Butt"; //Don't translate private String categoryName = StandardCategoryNames.RESULT; public void setCategoryName(String value) { categoryName = value; } public void initialize(PlugInContext context) throws Exception { FeatureInstaller featureInstaller = new FeatureInstaller(context.getWorkbenchContext()); featureInstaller.addMainMenuItem( this, //exe new String[] {MenuNames.TOOLS, MenuNames.TOOLS_ANALYSIS}, //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.createAtLeastNLayersMustExistCheck(1)); } public boolean execute(PlugInContext context) throws Exception { //[sstein, 16.07.2006] set again to obtain correct language //[LDB: 31.08.2007] moved all initialization of strings here LAYER = I18N.get("ui.plugin.analysis.BufferPlugIn.layer"); DISTANCE = I18N.get("ui.plugin.analysis.BufferPlugIn.buffer-distance"); END_CAP_STYLE = I18N.get("ui.plugin.analysis.BufferPlugIn.End-Cap-Style"); QUADRANT_SEGMENTS = I18N.get( "org.openjump.core.ui.plugin.edittoolbox.cursortools.DrawCircleWithGivenRadiusTool.Number-of-segments-per-circle-quarter"); SELECTED_ONLY = I18N.get("ui.plugin.analysis.GeometryFunctionPlugIn.Use-selected-features-only"); UNION_RESULT = I18N.get("ui.plugin.analysis.UnionPlugIn.union"); COPY_ATTRIUBTES = I18N.get("org.openjump.sigle.plugin.PlanarGraphPlugIn.Keep-attributes"); CAP_STYLE_ROUND = I18N.get("ui.plugin.analysis.BufferPlugIn.Round"); CAP_STYLE_SQUARE = I18N.get("ui.plugin.analysis.BufferPlugIn.Square"); CAP_STYLE_BUTT = I18N.get("ui.plugin.analysis.BufferPlugIn.Butt"); endCapStyles = new ArrayList(); endCapStyles.add(CAP_STYLE_ROUND); endCapStyles.add(CAP_STYLE_SQUARE); endCapStyles.add(CAP_STYLE_BUTT); endCapStyle = CAP_STYLE_ROUND; ATTRIBUTE = I18N.get("ui.plugin.analysis.BufferPlugIn.attribute-to-use"); FROMATTRIBUTE = I18N.get("ui.plugin.analysis.BufferPlugIn.Get-distance-from-attribute-value"); dialog = new MultiInputDialog(context.getWorkbenchFrame(), getName(), true); int n = context.getLayerViewPanel().getSelectionManager().getFeaturesWithSelectedItems().size(); useSelected = (n > 0); if (useSelected) sideBarText = SELECTED_ONLY; else sideBarText = I18N.get("ui.plugin.analysis.BufferPlugIn.buffers-all-geometries-in-the-input-layer"); setDialogValues(dialog, context); updateControls(); 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(); FeatureSchema featureSchema = new FeatureSchema(); featureSchema.addAttribute("GEOMETRY", AttributeType.GEOMETRY); FeatureCollection resultFC = new FeatureDataset(featureSchema); Collection inputC; if (useSelected) { inputC = context.getLayerViewPanel().getSelectionManager().getFeaturesWithSelectedItems(); Feature feature = (Feature) inputC.iterator().next(); featureSchema = feature.getSchema(); inputC = PasteItemsPlugIn.conform(inputC,featureSchema ); } else { inputC = layer.getFeatureCollectionWrapper().getFeatures(); featureSchema = layer.getFeatureCollectionWrapper().getFeatureSchema(); resultFC = new FeatureDataset(featureSchema); } FeatureDataset inputFD = new FeatureDataset(inputC, featureSchema); Collection resultGeomColl = runBuffer(monitor, inputFD); if (copyAttributes) { FeatureCollection resultFeatureColl = new FeatureDataset(featureSchema); Iterator iResult = resultGeomColl.iterator(); for (Iterator iSource = inputFD.iterator(); iSource.hasNext(); ) { Feature sourceFeature = (Feature) iSource.next(); Geometry gResult = (Geometry) iResult.next(); if (!(gResult == null || gResult.isEmpty())) { Feature newFeature = sourceFeature.clone(true); newFeature.setGeometry(gResult); resultFeatureColl.add(newFeature); } if (monitor.isCancelRequested()) break; } resultFC = resultFeatureColl; } else { resultFC = FeatureDatasetFactory.createFromGeometry(resultGeomColl); } if (unionResult) { Collection geoms = FeatureUtil.toGeometries(resultFC.getFeatures()); Geometry g = UnaryUnionOp.union(geoms); geoms.clear(); geoms.add(g); resultFC = FeatureDatasetFactory.createFromGeometry(geoms); } context.getLayerManager().addCategory(categoryName); String name; if (!useSelected) name = layer.getName(); else name = I18N.get("ui.MenuNames.SELECTION"); name = I18N.get("com.vividsolutions.jump.workbench.ui.plugin.analysis.BufferPlugIn") + "-" + name; if (endCapStyle != CAP_STYLE_ROUND) name = name + "-" + endCapStyle; context.addLayer(categoryName, name, resultFC); if (exceptionThrown) context.getWorkbenchFrame().warnUser(I18N.get("ui.plugin.analysis.BufferPlugIn.errors-found-while-executing-buffer")); } private Collection runBuffer(TaskMonitor monitor, FeatureCollection fcA) { exceptionThrown = false; int total = fcA.size(); int count = 0; Collection resultColl = new ArrayList(); for (Iterator ia = fcA.iterator(); ia.hasNext(); ) { monitor.report(count++, total, I18N.get("com.vividsolutions.jump.qa.diff.DiffGeometry.features")); if (monitor.isCancelRequested()) break; Feature fa = (Feature) ia.next(); Geometry ga = fa.getGeometry(); if (fromAttribute) { Object o = fa.getAttribute(attributeIndex); if (o instanceof Double) bufferDistance = ((Double) o).doubleValue(); else if (o instanceof Integer) bufferDistance = ((Integer) o).doubleValue(); } Geometry result = runBuffer(ga); if (result != null) resultColl.add(result); } return resultColl; } private Geometry runBuffer(Geometry a) { Geometry result = null; try { BufferOp bufOp = new BufferOp(a); bufOp.setQuadrantSegments(quadrantSegments); bufOp.setEndCapStyle(endCapStyleCode(endCapStyle)); result = bufOp.getResultGeometry(bufferDistance); return result; } catch (RuntimeException ex) { // simply eat exceptions and report them by returning null exceptionThrown = true; } return null; } private void setDialogValues(MultiInputDialog dialog, PlugInContext context) { dialog.setSideBarDescription(sideBarText); try{ dialog.setSideBarImage(IconLoader.icon("Round.gif"));}catch (Exception ex){} // dialog.addCheckBox(SELECTED_ONLY, useSelected); if (useSelected) dialog.addLabel(SELECTED_ONLY); else { dialog.addLayerComboBox(LAYER, context.getCandidateLayer(0), context.getLayerManager()); initComboFields(dialog, FROMATTRIBUTE, ATTRIBUTE); final MultiInputDialog fdialog = dialog; dialog.getCheckBox(FROMATTRIBUTE).addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { fromAttribute = fdialog.getCheckBox(FROMATTRIBUTE).isSelected(); fdialog.getComboBox(ATTRIBUTE).setEnabled(fromAttribute); //fdialog.getCheckBox(UNION_RESULT).setEnabled(!fromAttribute); } }); } dialog.addDoubleField(DISTANCE, bufferDistance, 10, null); JComboBox endCapComboBox = dialog.addComboBox(END_CAP_STYLE, endCapStyle, endCapStyles, null); endCapComboBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { updateControls(); } }); dialog.addIntegerField(QUADRANT_SEGMENTS,quadrantSegments,3,null); JCheckBox unionCheckBox = dialog.addCheckBox(UNION_RESULT, unionResult); unionCheckBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { updateControls(); } }); JCheckBox copyAttributesCheckBox = dialog.addCheckBox(COPY_ATTRIUBTES, copyAttributes); } private void getDialogValues(MultiInputDialog dialog) { if (!useSelected) layer = dialog.getLayer(LAYER); bufferDistance = dialog.getDouble(DISTANCE); endCapStyle = dialog.getText(END_CAP_STYLE); quadrantSegments = dialog.getInteger(QUADRANT_SEGMENTS); // if (useSelectedAvailable) // useSelected = dialog.getBoolean(SELECTED_ONLY); unionResult = dialog.getBoolean(UNION_RESULT); copyAttributes = dialog.getBoolean(COPY_ATTRIUBTES); if (fromAttribute) { if (dialog.getCheckBox(FROMATTRIBUTE).isEnabled()) { Layer destinationLayer = dialog.getLayer(LAYER); FeatureSchema schema = destinationLayer.getFeatureCollectionWrapper().getFeatureSchema(); String attributeName = dialog.getText(ATTRIBUTE); attributeIndex = schema.getAttributeIndex(attributeName); } else { fromAttribute = false; } } } private void initComboFields( final MultiInputDialog dialog, final String checkBoxFieldName, final String comboBoxFieldName) { JCheckBox checkBox = dialog.addCheckBox(checkBoxFieldName, false); JComboBox comboBox = dialog.addComboBox(comboBoxFieldName, null, new ArrayList(), null); Layer newLayer = (Layer) dialog.getComboBox(LAYER).getSelectedItem(); if (newLayer != null) dialog.getComboBox(comboBoxFieldName).setModel( new DefaultComboBoxModel( new Vector(candidateAttributeNames(newLayer)))); boolean numericAttributesPresent = !(candidateAttributeNames(newLayer).size() == 0); checkBox.setEnabled(numericAttributesPresent); //comboBox.setEnabled(numericAttributesPresent); comboBox.setEnabled(false); dialog.getComboBox(LAYER).addActionListener(new ActionListener() { private Layer lastLayer = null; public void actionPerformed(ActionEvent e) { Layer newLayer = (Layer) dialog.getComboBox(LAYER).getSelectedItem(); if (lastLayer == newLayer) { return; } lastLayer = newLayer; dialog.getComboBox(comboBoxFieldName).setModel( new DefaultComboBoxModel( new Vector(candidateAttributeNames(newLayer)))); boolean notEmpty = !(candidateAttributeNames(newLayer).size() == 0); dialog.getCheckBox(checkBoxFieldName).setEnabled(notEmpty); if (notEmpty) { dialog.getComboBox(comboBoxFieldName).setSelectedItem( candidateAttributeNames(newLayer).get(0)); } } }); dialog .addEnableChecks( comboBoxFieldName, Arrays .asList( new Object[] { new EnableCheck() { public String check(JComponent component) { return dialog.getBoolean(checkBoxFieldName) && dialog.getComboBox(comboBoxFieldName).getItemCount() == 0 ? " " : null; } } })); dialog.indentLabel(comboBoxFieldName); } private List candidateAttributeNames(Layer layer) { ArrayList candidateAttributeNames = new ArrayList(); FeatureSchema schema = layer.getFeatureCollectionWrapper().getFeatureSchema(); for (int i = 0; i < schema.getAttributeCount(); i++) { if ((schema.getAttributeType(i) == AttributeType.DOUBLE) || (schema.getAttributeType(i) == AttributeType.INTEGER)) { candidateAttributeNames.add(schema.getAttributeName(i)); } } return candidateAttributeNames; } private int endCapStyleCode(String capStyle) { if (capStyle == CAP_STYLE_BUTT) return BufferOp.CAP_BUTT; if (capStyle == CAP_STYLE_SQUARE) return BufferOp.CAP_SQUARE; return BufferOp.CAP_ROUND; } private Feature combine(Collection originalFeatures) { GeometryFactory factory = new GeometryFactory(); Feature feature = (Feature) ((Feature) originalFeatures.iterator().next()).clone(); feature.setGeometry( factory.createGeometryCollection( (Geometry[]) FeatureUtil.toGeometries(originalFeatures).toArray( new Geometry[originalFeatures.size()]))); return feature; } protected void updateControls() { getDialogValues(dialog); dialog.getCheckBox(COPY_ATTRIUBTES).setEnabled(!unionResult); int capCode = endCapStyleCode(endCapStyle); if (capCode == BufferOp.CAP_BUTT) updateUIForFunction( BUTT); else if (capCode == BufferOp.CAP_SQUARE) updateUIForFunction( SQUARE); else updateUIForFunction(ROUND); } private void updateUIForFunction(String capName) { if ( unionResult) { try{dialog.setSideBarImage(IconLoader.icon(capName + "-union.gif"));}catch (Exception ex){} //dialog.setSideBarDescription(); } else { try{dialog.setSideBarImage(IconLoader.icon(capName + ".gif"));}catch (Exception ex){} //dialog.setSideBarDescription(); } } }