Revision: 6650 http://sourceforge.net/p/jump-pilot/code/6650 Author: michaudm Date: 2020-12-20 11:59:38 +0000 (Sun, 20 Dec 2020) Log Message: ----------- replace MergeSelectedPolygonsWithNeighbourPlugIn by MergePolygonsWithNeighbourPlugIn :faster, transactional, more options
Modified Paths: -------------- core/trunk/Changes.txt core/trunk/src/language/jump.properties core/trunk/src/language/jump_cz.properties core/trunk/src/language/jump_de.properties core/trunk/src/language/jump_es.properties core/trunk/src/language/jump_fi.properties core/trunk/src/language/jump_fr.properties core/trunk/src/language/jump_hu.properties core/trunk/src/language/jump_it.properties core/trunk/src/language/jump_ja_JP.properties core/trunk/src/language/jump_ml.properties core/trunk/src/language/jump_pt.properties core/trunk/src/language/jump_pt_BR.properties core/trunk/src/language/jump_ta_IN.properties core/trunk/src/language/jump_te.properties core/trunk/src/language/jump_zh_CN.properties core/trunk/src/language/jump_zh_HK.properties core/trunk/src/org/openjump/core/ui/plugin/tools/analysis/onelayer/MergePolygonsWithNeighbourPlugIn.java Modified: core/trunk/Changes.txt =================================================================== --- core/trunk/Changes.txt 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/Changes.txt 2020-12-20 11:59:38 UTC (rev 6650) @@ -28,6 +28,7 @@ Improvements + * make MergePolygonsWithNeighbourPlugIn fast and transactional * Symbolizing : Updated CadTool plugin to ver. 1.0 - added capability to load Python console and tools * Raster : Added gdal support for debian/ubuntu Modified: core/trunk/src/language/jump.properties =================================================================== --- core/trunk/src/language/jump.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -1577,6 +1577,7 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute = Use an attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip = Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute = Select the attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=Feature with id={0} is not valid : merging of features is canceled org.openjump.core.ui.plugin.tools.MergeTwoSelectedPolygonsPlugIn.Merge-Two-Polygons = Merge Two Polygons org.openjump.core.ui.plugin.tools.MultiRingBufferSelectedPlugIn.Multiple-Ring-Buffer = Multiple Ring Buffer org.openjump.core.ui.plugin.tools.MultiRingBufferSelectedPlugIn.Reset-all-buffer-options = Reset all buffer options Modified: core/trunk/src/language/jump_cz.properties =================================================================== --- core/trunk/src/language/jump_cz.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_cz.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -2987,3 +2987,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/language/jump_de.properties =================================================================== --- core/trunk/src/language/jump_de.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_de.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -2980,3 +2980,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/language/jump_es.properties =================================================================== --- core/trunk/src/language/jump_es.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_es.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -2957,4 +2957,5 @@ com.vividsolutions.jump.workbench.imagery.geoimg.GeoReferencedRaster.no-georeference-found=Ninguna referencia geografica encontrada org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value -org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute \ No newline at end of file +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled \ No newline at end of file Modified: core/trunk/src/language/jump_fi.properties =================================================================== --- core/trunk/src/language/jump_fi.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_fi.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -2957,3 +2957,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/language/jump_fr.properties =================================================================== --- core/trunk/src/language/jump_fr.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_fr.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -2992,3 +2992,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=S\xE9lectionner l'attribut org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=Fusionner uniquement avec des objets de m\xEAme valeur d'attribut org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=Utiliser un attribut +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=L''objet d''id={0} n''est pas valide : la fusion est annul\xE9e Modified: core/trunk/src/language/jump_hu.properties =================================================================== --- core/trunk/src/language/jump_hu.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_hu.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -2978,3 +2978,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/language/jump_it.properties =================================================================== --- core/trunk/src/language/jump_it.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_it.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -2959,4 +2959,5 @@ com.vividsolutions.jump.workbench.imagery.geoimg.GeoReferencedRaster.no-georeference-found=Nessun riferimento geografico trovato org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value -org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute \ No newline at end of file +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled \ No newline at end of file Modified: core/trunk/src/language/jump_ja_JP.properties =================================================================== --- core/trunk/src/language/jump_ja_JP.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_ja_JP.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -2982,3 +2982,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/language/jump_ml.properties =================================================================== --- core/trunk/src/language/jump_ml.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_ml.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -3757,3 +3757,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/language/jump_pt.properties =================================================================== --- core/trunk/src/language/jump_pt.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_pt.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -2981,3 +2981,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/language/jump_pt_BR.properties =================================================================== --- core/trunk/src/language/jump_pt_BR.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_pt_BR.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -2981,3 +2981,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/language/jump_ta_IN.properties =================================================================== --- core/trunk/src/language/jump_ta_IN.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_ta_IN.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -2980,3 +2980,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/language/jump_te.properties =================================================================== --- core/trunk/src/language/jump_te.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_te.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -3487,3 +3487,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/language/jump_zh_CN.properties =================================================================== --- core/trunk/src/language/jump_zh_CN.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_zh_CN.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -3144,3 +3144,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/language/jump_zh_HK.properties =================================================================== --- core/trunk/src/language/jump_zh_HK.properties 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/language/jump_zh_HK.properties 2020-12-20 11:59:38 UTC (rev 6650) @@ -3143,3 +3143,4 @@ org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute=#T:Select the attribute org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip=#T:Only merge with features having the same attribute value org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute=#T:Use an attribute +org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid=#T:Feature with id={0} is not valid : merging of features is canceled Modified: core/trunk/src/org/openjump/core/ui/plugin/tools/analysis/onelayer/MergePolygonsWithNeighbourPlugIn.java =================================================================== --- core/trunk/src/org/openjump/core/ui/plugin/tools/analysis/onelayer/MergePolygonsWithNeighbourPlugIn.java 2020-12-19 23:57:38 UTC (rev 6649) +++ core/trunk/src/org/openjump/core/ui/plugin/tools/analysis/onelayer/MergePolygonsWithNeighbourPlugIn.java 2020-12-20 11:59:38 UTC (rev 6650) @@ -18,6 +18,7 @@ import javax.swing.*; import java.util.*; +import java.util.stream.Collectors; public class MergePolygonsWithNeighbourPlugIn extends ThreadedBasePlugIn { @@ -41,6 +42,7 @@ String sAttributeToUse = "Attribute to use"; String attribute = null; String layerName; + //String sInvalidFeatureMessage = "Features must be valid to be merged"; final static String sMERGEMETHOD = "MERGE METHOD"; private MultiInputDialog dialog; @@ -59,6 +61,7 @@ sUseAttribute = I18N.get("org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute"); sUseAttributeTooltip = I18N.get("org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Use-attribute-tooltip"); sAttributeToUse = I18N.get("org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Attribute"); + //sInvalidFeatureMessage = I18N.get("org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid"); FeatureInstaller featureInstaller = new FeatureInstaller(context.getWorkbenchContext()); featureInstaller.addMainMenuPlugin( @@ -124,7 +127,9 @@ private void getDialogValues(MultiInputDialog dialog) { this.useArea = dialog.getBoolean(this.sUseArea); this.useBorder = dialog.getBoolean(this.sUseBoder); - if (dialog.getBoolean(sUseAttribute)) attribute = (String)dialog.getComboBox(sAttributeToUse).getSelectedItem(); + if (dialog.getBoolean(sUseAttribute)) { + attribute = (String)dialog.getComboBox(sAttributeToUse).getSelectedItem(); + } else attribute = null; } @@ -134,58 +139,55 @@ context.getWorkbenchContext().getLayerManager().setFiringEvents(false); Layer activeLayer = context.getLayerManager().getLayer(layerName); + Collection<Feature> selection = context.getWorkbenchContext().getLayerViewPanel() + .getSelectionManager().getFeaturesWithSelectedItems(); + Set<Integer> selectedIds = selection.stream().map(Feature::getID).collect(Collectors.toSet()); FeatureCollection fc = activeLayer.getFeatureCollectionWrapper(); - STRtree index = new STRtree(); monitor.report("Indexing..."); - for (Feature f : fc.getFeatures()) { - index.insert(f.getGeometry().getEnvelopeInternal(), f); - } + STRtree index = index(fc); - Collection<Feature> selection = context.getWorkbenchContext().getLayerViewPanel() - .getSelectionManager().getFeaturesWithSelectedItems(); + monitor.report("Building the graph"); + Map<Integer,Set<Integer>> graph = getPolygonGraph(index, selection, monitor); - Map<Integer,Set<Integer>> graph = getPolygonGraph(index, selection, monitor); - // ids of a all features which may change - Set<Integer> ids = new HashSet<>(); - for (Map.Entry<Integer,Set<Integer>> entry : graph.entrySet()) { - ids.add(entry.getKey()); - ids.addAll(entry.getValue()); - } + // ids of all features which may change (selection + neighbouring) + Set<Integer> graphIds = getGraphIds(graph); // Preserve original geometries + Map<Integer,Geometry> sourceGeometries = new HashMap<>(); Map<Integer,Feature> currentFeatures = new HashMap<>(); - Map<Integer, Geometry> sourceGeometries = new HashMap<>(); + Map<Integer,Geometry> newGeometries = new HashMap<>(); for (Feature f : fc.getFeatures()) { - if (ids.contains(f.getID())) currentFeatures.put(f.getID(), f); - if (ids.contains(f.getID())) sourceGeometries.put(f.getID(), (Geometry)f.getGeometry().clone()); + if (graphIds.contains(f.getID())) currentFeatures.put(f.getID(), f); + if (graphIds.contains(f.getID())) sourceGeometries.put(f.getID(), (Geometry)f.getGeometry().clone()); } monitor.report(sMergingPolygons); - int count = 0; - for (Feature f : selection) { - Feature target = useArea ? chooseMaxAreaNeighbour(f.getID(), graph, currentFeatures) - : chooseLongestBoundaryNeighbour(f.getID(), graph, currentFeatures); - monitor.report(++count, selection.size(), sMerged); - if (target != null) { - merge(f.getID(), target.getID(), graph, currentFeatures); - //fc.remove(f); + try { + int count = 0; + for (Feature f : selection) { + Feature target = useArea ? chooseMaxAreaNeighbour(f.getID(), graph, currentFeatures) + : chooseLongestBoundaryNeighbour(f.getID(), graph, currentFeatures); + monitor.report(++count, selection.size(), sMerged); + if (target != null) { + merge(f.getID(), target.getID(), graph, currentFeatures); + } } + } finally { + // restore original geometries, even if something wrong happened during the merge + // but before, save new geometries to prepare the transaction which will be executed + // if no exception occured (transaction is postponed because of the iterative nature + // of the process where each feature may be modified several times) + for (int i : currentFeatures.keySet()) { + // Save new geometries from currentFeatures + if (selectedIds.contains(i) && !graph.containsKey(i)) newGeometries.put(i, null); + else newGeometries.put(i, currentFeatures.get(i).getGeometry()); + // Restore original geometries in currentFeatures + currentFeatures.get(i).setGeometry(sourceGeometries.get(i)); + } } + monitor.report("Prepare transaction"); - // Preserve new calculated geometries and restore original one as - // because the graph calculation was not transactional (it is difficult - // to make it transactional beacause of its iterative nature) - Map<Integer,Geometry> newGeometries = new HashMap<>(); - ids.clear(); - for (Feature f : selection) ids.add(f.getID()); - for (int i : currentFeatures.keySet()) { - if (ids.contains(i) && !graph.containsKey(i)) newGeometries.put(i, null); - else newGeometries.put(i, currentFeatures.get(i).getGeometry()); - currentFeatures.get(i).setGeometry(sourceGeometries.get(i)); - } - // Now make the changes within a transaction - reportNothingToUndoYet(context); activeLayer.getLayerManager().getUndoableEditReceiver().startReceiving(); try { @@ -198,8 +200,8 @@ context.getLayerViewPanel() ); for (int i : currentFeatures.keySet()) { - if (!graph.containsKey(i)) - if (ids.contains(i)) { + //if (!graph.containsKey(i)) + if (selectedIds.contains(i)) { transaction.deleteFeature(currentFeatures.get(i)); } else { transaction.modifyFeatureGeometry(currentFeatures.get(i), newGeometries.get(i)); @@ -206,28 +208,38 @@ } } transaction.commit(); - context.getWorkbenchContext().getLayerManager().setFiringEvents(true); + context.getWorkbenchContext().getLayerViewPanel().getSelectionManager().clear(); context.getWorkbenchContext().getLayerViewPanel().repaint(); - transaction.commit(); - activeLayer.getLayerManager().getUndoableEditReceiver().stopReceiving(); } finally { + context.getWorkbenchContext().getLayerManager().setFiringEvents(true); activeLayer.getLayerManager().getUndoableEditReceiver().stopReceiving(); } } + private STRtree index(FeatureCollection fc) { + STRtree index = new STRtree(); + for (Feature f : fc.getFeatures()) { + index.insert(f.getGeometry().getEnvelopeInternal(), f); + } + return index; + } + // Create a map containing relations between each selected feature and adjacent features private Map<Integer,Set<Integer>> getPolygonGraph(SpatialIndex index, Collection<Feature> selection, - TaskMonitor monitor) { + TaskMonitor monitor) throws Exception { Map<Integer,Set<Integer>> graph = new HashMap<>(); - monitor.report("Building the graph"); + Set<Integer> validated = new HashSet<>(); int count = 0; int total = selection.size(); for (Feature f : selection) { monitor.report(++count, total, "polygons"); if (f.getGeometry().getDimension() != 2) continue; + if (!f.getGeometry().isValid()) + throw new Exception(I18N.getMessage("org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid", f.getID())); + validated.add(f.getID()); List<Feature> candidates = index.query(f.getGeometry().getEnvelopeInternal()); int fid = f.getID(); Set<Integer> neighbours = graph.get(fid); @@ -236,11 +248,14 @@ int cid = candidate.getID(); if (cid == fid) continue; if (candidate.getGeometry().getDimension() != 2) continue; + if (!validated.contains(cid) && !candidate.getGeometry().isValid()) + throw new Exception(I18N.getMessage("org.openjump.core.ui.plugin.tools.MergeSelectedPolygonsWithNeighbourPlugIn.Features-must-be-valid", candidate.getID())); + validated.add(cid); if (attribute != null && !Objects.equals(f.getAttribute(attribute), candidate.getAttribute(attribute))) continue; - // Non, \xE7a fait des trous ! - //if (c.getGeometry().getArea() < f.getGeometry().getArea()) continue; if (f.getGeometry().intersects(candidate.getGeometry())) { - //if (f.getGeometry().relate(c.getGeometry(),"****1****")) { + //relate is slower than intersects and has small benefit + //for the following step (choosing the best candidate) + //if (f.getGeometry().relate(c.getGeometry(),"****1****")) { neighbours.add(candidate.getID()); } } @@ -249,25 +264,36 @@ return graph; } + private Set<Integer> getGraphIds(Map<Integer,Set<Integer>> graph) { + Set<Integer> ids = new HashSet<>(); + for (Map.Entry<Integer,Set<Integer>> entry : graph.entrySet()) { + ids.add(entry.getKey()); + ids.addAll(entry.getValue()); + } + return ids; + } + + private boolean merge(int srcId, int dstId, Map<Integer,Set<Integer>> graph, Map<Integer,Feature> currentFeatures) { Feature src = currentFeatures.get(srcId); Feature dst = currentFeatures.get(dstId); dst.setGeometry(dst.getGeometry().union(src.getGeometry())); - Set<Integer> newDestSet = graph.get(dstId); - if (newDestSet != null) newDestSet.remove(srcId); - // Neighbours of src - for (Integer id : graph.get(srcId)) { - if (id != srcId && id != dstId) { - if (newDestSet != null) newDestSet.add(id); - } - if (graph.containsKey(id)) graph.get(id).remove(srcId); + Set<Integer> neighboursOfDst = graph.get(dstId); + // graph only contains neighbours of selected features + if (neighboursOfDst != null) { + neighboursOfDst.remove(srcId); } - if (graph.containsKey(dst.getID())) { - for (Integer id : graph.get(dstId)) { - if (id != srcId && id != dstId) { - if (newDestSet != null) newDestSet.add(id); - } + // Avoid concurrent modification + Set<Integer> neighboursOfSrc = new HashSet<>(graph.get(srcId)); + for (int id : neighboursOfSrc) { + if (id != srcId && id != dstId && neighboursOfDst != null) { + neighboursOfDst.add(id); } + // If id is also a selected feature, update its neighbours + if (graph.containsKey(id)) { + graph.get(id).remove(srcId); + graph.get(id).add(dstId); + } } graph.remove(srcId); return true; @@ -275,19 +301,16 @@ private Feature chooseMaxAreaNeighbour(int fid, Map<Integer,Set<Integer>> graph, Map<Integer,Feature> currentFeatures) { - Set<Integer> candidates = graph.get(fid); - Feature src = currentFeatures.get(fid); - double srcArea = src.getGeometry().getArea(); + Set<Integer> neighbours = graph.get(fid); double max = 0; Feature selected = null; - for (Integer cid : candidates) { - Feature candidate = currentFeatures.get(cid); + for (int cid : neighbours) { if (cid == fid) continue; - double area = candidate.getGeometry().getArea(); - //if (area < srcArea) continue; + Feature neighbour = currentFeatures.get(cid); + double area = neighbour.getGeometry().getArea(); if (area > max) { max = area; - selected = candidate; + selected = neighbour; } } return selected; @@ -295,24 +318,18 @@ private Feature chooseLongestBoundaryNeighbour(int fid, Map<Integer,Set<Integer>> graph, Map<Integer,Feature> currentFeatures) { - Set<Integer> candidates = graph.get(fid); + Set<Integer> neighbours = graph.get(fid); Feature src = currentFeatures.get(fid); - double srcArea = src.getGeometry().getArea(); double max = 0; Feature selected = null; - if (candidates != null) { - for (Integer cid : candidates) { - Feature candidate = currentFeatures.get(cid); - if (cid == fid) continue; - //if (candidate.getGeometry().getArea() < srcArea) continue; - double length = candidate.getGeometry().intersection(src.getGeometry()).getLength(); - if (length > max) { - max = length; - selected = candidate; - } + for (int cid : neighbours) { + if (cid == fid) continue; + Feature neighbour = currentFeatures.get(cid); + double length = neighbour.getGeometry().intersection(src.getGeometry()).getLength(); + if (length > max) { + max = length; + selected = neighbour; } - } else { - System.out.println("L'objet " + fid + " n'est plus dans le graph"); } return selected; } _______________________________________________ Jump-pilot-devel mailing list Jump-pilot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel