/* * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI * for visualizing and manipulating spatial features with geometry and attributes. * * JUMP is Copyright (C) 2003 Vivid Solutions * * This program implements extensions to JUMP and is * Copyright (C) Stefan Steiniger. * * 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: * Stefan Steiniger * perriger@gmx.de */ /***************************************************** * created: 30.01.2006 * last modified: * * * @author sstein * * description: * deletes items with same geometry * *****************************************************/ package org.openjump.core.ui.plugin.tools; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import javax.swing.JComboBox; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jump.I18N; import com.vividsolutions.jump.feature.AttributeType; import com.vividsolutions.jump.feature.Feature; import com.vividsolutions.jump.feature.FeatureCollection; import com.vividsolutions.jump.feature.FeatureDataset; import com.vividsolutions.jump.feature.FeatureSchema; import com.vividsolutions.jump.task.TaskMonitor; import com.vividsolutions.jump.workbench.WorkbenchContext; import com.vividsolutions.jump.workbench.model.Layer; import com.vividsolutions.jump.workbench.model.StandardCategoryNames; 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.plugin.ThreadedPlugIn; import com.vividsolutions.jump.workbench.ui.GUIUtil; import com.vividsolutions.jump.workbench.ui.GenericNames; import com.vividsolutions.jump.workbench.ui.LayerViewPanel; import com.vividsolutions.jump.workbench.ui.MenuNames; import com.vividsolutions.jump.workbench.ui.MultiInputDialog; import com.vividsolutions.jump.workbench.ui.plugin.FeatureInstaller; /** * Eliminates features that have exactly the same Geometry * * @author sstein * * TODO : use STRtree for faster testing. Right now I just go through the complete list. **/ public class DeleteDuplicateGeometriesPlugIn extends AbstractPlugIn implements ThreadedPlugIn{ private String CLAYER = "select layer"; private String sDescription = "deletes features with similar geometry"; private String deleteByAttribute = "delete only if attributes are the same"; private String sName = "Delete Duplicate Geometries"; private String sChecked = "checked"; private String sCleaned = "cleaned"; private Layer itemlayer = null; private boolean deleteOnlyForSameAttributes = false; public void initialize(PlugInContext context) throws Exception { this.CLAYER = GenericNames.SELECT_LAYER; this.sDescription = I18N.get("org.openjump.core.ui.plugin.tools.DeleteDuplicateGeometriesPlugIn.deletes-features-with-similar-geometry"); this.deleteByAttribute = I18N.get("org.openjump.core.ui.plugin.tools.DeleteDuplicateGeometriesPlugIn.delete-only-if-attributes-are-the-same"); this.sName = I18N.get("org.openjump.core.ui.plugin.tools.DeleteDuplicateGeometriesPlugIn.Delete-Duplicate-Geometries"); this.sChecked = I18N.get("org.openjump.core.ui.plugin.tools.DeleteDuplicateGeometriesPlugIn.checked"); this.sCleaned = I18N.get("org.openjump.core.ui.plugin.tools.DeleteDuplicateGeometriesPlugIn.cleaned"); /*//-- no need to be in mouse menu context.getFeatureInstaller().addPopupMenuItem( LayerViewPanel.popupMenu(), this, this.getName(), false, null, createEnableCheck(context.getWorkbenchContext())); */ FeatureInstaller featureInstaller = new FeatureInstaller(context.getWorkbenchContext()); featureInstaller.addMainMenuItem( this, //exe new String[] {MenuNames.TOOLS, MenuNames.TOOLS_QA}, //menu path this.getName() + "...", //name methode .getName received 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.createAtLeastNLayersMustExistCheck(1)); } public String getName(){ return sName; } public boolean execute(PlugInContext context) throws Exception{ this.reportNothingToUndoYet(context); MultiInputDialog 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; } private void setDialogValues(MultiInputDialog dialog, PlugInContext context) { dialog.setSideBarDescription(sDescription); JComboBox addLayerComboBoxBuild = dialog.addLayerComboBox(this.CLAYER, context.getCandidateLayer(0), null, context.getLayerManager()); dialog.addCheckBox(deleteByAttribute, this.deleteOnlyForSameAttributes); } private void getDialogValues(MultiInputDialog dialog) { this.itemlayer = dialog.getLayer(this.CLAYER); this.deleteOnlyForSameAttributes = dialog.getBoolean(deleteByAttribute); } public void run(TaskMonitor monitor, PlugInContext context) throws Exception{ this.delete(context, monitor); System.gc(); } private boolean delete(PlugInContext context, TaskMonitor monitor) throws Exception{ System.gc(); //flush garbage collector // -------------------------- //-- get selected items final Collection features = this.itemlayer.getFeatureCollectionWrapper().getFeatures(); ArrayList notFoundItemsOld = new ArrayList(); ArrayList notFoundItemsNew = new ArrayList(); ArrayList doneItems = new ArrayList(); int size = features.size(); Iterator iter = features.iterator(); Feature f = (Feature)iter.next(); FeatureSchema fs = f.getSchema(); //-- new collection for output : assuming that all features have same schema and // first feature has correct scheme FeatureCollection myCollA = new FeatureDataset(fs); Feature fi = null; int count=1; int dropped = 0; notFoundItemsOld.addAll(features); while(iter.hasNext()){ monitor.report(count, size, sChecked); count++; fi = (Feature)iter.next(); Geometry geom = (Geometry)fi.getGeometry(); int copycounter = 0; for (int j = 0; j < notFoundItemsOld.size(); j++){ boolean isequal = false; Feature testF = (Feature)notFoundItemsOld.get(j); try{ //-- test if other object has same geometry isequal = geom.equals(testF.getGeometry()); //-- test if objects have same attribute values if((isequal == true) && (this.deleteOnlyForSameAttributes == true)){ boolean attributesAreDifferent = false; for (int k=0; k < fs.getAttributeCount(); k++){ if(fs.getAttributeType(k) != AttributeType.GEOMETRY){ Object val1 = fi.getAttribute(k); Object val2 = testF.getAttribute(k); if(!val1.equals(val2)){ attributesAreDifferent = true; //System.out.println("Attribute vals are different: " + val1 + " and " + val2); } } } if (attributesAreDifferent == true){ isequal = false; } } } catch(Exception e){ System.out.println("items have problem (toplogy): " + testF.getID() + " and " + fi.getID()); System.out.println(e.getStackTrace()); } if (isequal){ copycounter = copycounter+1; if (copycounter == 1){ //-- hold at least one // checking of Feature-Id's does not help - since every item is checked, // even if it has been deleted already from the second notFoundList, since we are // walking through the original features list - still containing all items notFoundItemsNew.add(testF); } else{ //-- drop feature dropped= dropped+1; } } else{ //has same id or was not found notFoundItemsNew.add(testF); } } notFoundItemsOld.clear(); notFoundItemsOld.addAll(notFoundItemsNew); notFoundItemsNew.clear(); } for (Iterator iterator = notFoundItemsOld.iterator(); iterator.hasNext();) { Feature element = (Feature) iterator.next(); //-- clone! not link myCollA.add((Feature)element.clone()); } context.addLayer(StandardCategoryNames.WORKING, itemlayer.getName()+ "-" + sCleaned, myCollA); return true; } }