Ticket #2760: 2760-simplify.diff

File 2760-simplify.diff, 10.4 KB (added by Bjoeni, 7 years ago)
  • src/org/openstreetmap/josm/actions/SimplifyWayAction.java

     
    55import static org.openstreetmap.josm.tools.I18n.tr;
    66import static org.openstreetmap.josm.tools.I18n.trn;
    77
     8import java.awt.GridBagLayout;
    89import java.awt.event.ActionEvent;
    910import java.awt.event.KeyEvent;
    1011import java.util.ArrayList;
     
    1718import java.util.Set;
    1819import java.util.stream.Collectors;
    1920
     21import javax.swing.BorderFactory;
     22import javax.swing.JCheckBox;
     23import javax.swing.JLabel;
    2024import javax.swing.JOptionPane;
     25import javax.swing.JPanel;
     26import javax.swing.JSpinner;
     27import javax.swing.SpinnerNumberModel;
    2128import javax.swing.SwingUtilities;
    2229
    2330import org.openstreetmap.josm.command.ChangeCommand;
     
    2431import org.openstreetmap.josm.command.Command;
    2532import org.openstreetmap.josm.command.DeleteCommand;
    2633import org.openstreetmap.josm.command.SequenceCommand;
     34import org.openstreetmap.josm.data.SystemOfMeasurement;
    2735import org.openstreetmap.josm.data.UndoRedoHandler;
    2836import org.openstreetmap.josm.data.osm.DataSet;
    2937import org.openstreetmap.josm.data.osm.Node;
     
    3038import org.openstreetmap.josm.data.osm.OsmPrimitive;
    3139import org.openstreetmap.josm.data.osm.Way;
    3240import org.openstreetmap.josm.data.projection.Ellipsoid;
     41import org.openstreetmap.josm.gui.ExtendedDialog;
    3342import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    3443import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
    3544import org.openstreetmap.josm.gui.MainApplication;
    3645import org.openstreetmap.josm.gui.Notification;
    3746import org.openstreetmap.josm.spi.preferences.Config;
     47import org.openstreetmap.josm.spi.preferences.IPreferences;
     48import org.openstreetmap.josm.tools.GBC;
    3849import org.openstreetmap.josm.tools.ImageProvider;
    3950import org.openstreetmap.josm.tools.Shortcut;
    4051
     
    93104                );
    94105    }
    95106
     107    /**
     108     * Asks the user for max-err value used to simplify ways, if not remembered before
     109     * @param text the text being shown
     110     * @param auto whether it's called automatically (conversion) or by the user
     111     * @return the max-err value or -1 if canceled
     112     */
     113    public static double askSimplifyWays(String text, boolean auto) {
     114        IPreferences s = Config.getPref();
     115        String key = "simplify-way.";
     116        String keyRemember = key + (auto ? "auto" : "manual");
     117        String keyError = key + "max-error";
     118
     119        String r = s.get(keyRemember, "ask");
     120        if (auto && "no".equals(r)) {
     121            return -1;
     122        } else if ("yes".equals(r)) {
     123            return s.getDouble(keyError, 3.0);
     124        }
     125
     126        JPanel p = new JPanel(new GridBagLayout());
     127        p.add(new JLabel("<html><body style=\"width: 375px;\">" + text + "<br><br>" +
     128                tr("This reduces unnecessary nodes along the way and is especially recommended if GPS tracks were recorded by time "
     129                 + "(i.e. one point per second) or when the accuracy was low (reduces \"zigzag\" tracks).")
     130                + "</body></html>"), GBC.eol());
     131        p.setBorder(BorderFactory.createEmptyBorder(5, 10, 10, 5));
     132        JPanel q = new JPanel(new GridBagLayout());
     133        q.add(new JLabel(tr("Maximum error (meters): ")));
     134        JSpinner n = new JSpinner(new SpinnerNumberModel(
     135                s.getDouble(keyError, 3.0), 0.01, 100, 0.5));
     136        q.add(n);
     137        q.setBorder(BorderFactory.createEmptyBorder(14, 0, 10, 0));
     138        p.add(q, GBC.eol());
     139        JCheckBox c = new JCheckBox(tr("Do not ask again"));
     140        p.add(c, GBC.eol());
     141
     142        ExtendedDialog ed = new ExtendedDialog(MainApplication.getMainFrame(),
     143                tr("Simplify way"), tr("Simplify"),
     144                auto ? tr("Proceed without simplifying") : tr("Cancel"))
     145                .setContent(p)
     146                .configureContextsensitiveHelp(("Action/SimplifyWay"), true);
     147        if (auto) {
     148            ed.setButtonIcons("simplify", "ok");
     149        } else {
     150            ed.setButtonIcons("ok", "cancel");
     151        }
     152
     153        int ret = ed.showDialog().getValue();
     154        double val = (double) n.getValue();
     155        if (ret == 1) {
     156            s.putDouble(keyError, val);
     157            if (c.isSelected()) {
     158                s.put(keyRemember, "yes");
     159            }
     160            return val;
     161        } else {
     162            if (auto && c.isSelected()) { //do not remember cancel for manual simplify, otherwise nothing would happen
     163                s.put(keyRemember, "no");
     164            }
     165            return -1;
     166        }
     167    }
     168
    96169    @Override
    97170    public void actionPerformed(ActionEvent e) {
    98171        DataSet ds = getLayerManager().getEditDataSet();
     
    108181                return;
    109182            }
    110183
    111             Collection<Command> allCommands = new LinkedList<>();
    112             for (Way way: ways) {
    113                 SequenceCommand simplifyCommand = simplifyWay(way);
    114                 if (simplifyCommand == null) {
    115                     continue;
    116                 }
    117                 allCommands.add(simplifyCommand);
     184            String lengthstr = SystemOfMeasurement.getSystemOfMeasurement().getDistText(
     185                    ways.stream().collect(
     186                            Collectors.summingDouble(w -> {
     187                                return w.getLength();
     188                            })));
     189
     190            double err = askSimplifyWays(trn(
     191                    "You are about to simplify {0} way with a total length of {1}.",
     192                    "You are about to simplify {0} ways with a total length of {1}.",
     193                    ways.size(), ways.size(), lengthstr), false);
     194
     195            if (err > 0) {
     196                simplifyWays(ways, err);
    118197            }
    119             if (allCommands.isEmpty()) return;
    120             SequenceCommand rootCommand = new SequenceCommand(
    121                     trn("Simplify {0} way", "Simplify {0} ways", allCommands.size(), allCommands.size()),
    122                     allCommands
    123                     );
    124             UndoRedoHandler.getInstance().add(rootCommand);
    125198        } finally {
    126199            ds.endUpdate();
    127200        }
     
    156229    }
    157230
    158231    /**
    159      * Simplifies a way with default threshold (read from preferences).
    160      *
    161      * @param w the way to simplify
    162      * @return The sequence of commands to run
    163      * @since 6411
    164      */
    165     public final SequenceCommand simplifyWay(Way w) {
    166         return simplifyWay(w, Config.getPref().getDouble("simplify-way.max-error", 3.0));
    167     }
    168 
    169     /**
    170232     * Calculate a set of nodes which occurs more than once in the way
    171233     * @param w the way
    172234     * @return a set of nodes which occurs more than once in the way
     
    182244    }
    183245
    184246    /**
    185      * Simplifies a way with a given threshold.
     247     * Runs the commands to simplify the ways with the given treshold
    186248     *
     249     * @param ways the ways to simplify
     250     * @param treshold the max error threshold
     251     * @since xxx
     252     */
     253    public static void simplifyWays(List<Way> ways, double treshold) {
     254        Collection<Command> allCommands = new LinkedList<>();
     255        for (Way way : ways) {
     256            SequenceCommand simplifyCommand = createSimplifyCommand(way, treshold);
     257            if (simplifyCommand == null) {
     258                continue;
     259            }
     260            allCommands.add(simplifyCommand);
     261        }
     262        if (allCommands.isEmpty())
     263            return;
     264        SequenceCommand rootCommand = new SequenceCommand(
     265                trn("Simplify {0} way", "Simplify {0} ways", allCommands.size(), allCommands.size()),
     266                allCommands);
     267        UndoRedoHandler.getInstance().add(rootCommand);
     268    }
     269
     270    /**
     271     * Creates the SequenceCommand to simplify a way with a given threshold.
     272     *
    187273     * @param w the way to simplify
    188274     * @param threshold the max error threshold
    189275     * @return The sequence of commands to run
    190276     * @since 6411
    191277     */
    192     public static SequenceCommand simplifyWay(Way w, double threshold) {
     278    public static SequenceCommand createSimplifyCommand(Way w, double threshold) {
    193279        int lower = 0;
    194280        int i = 0;
    195281
  • src/org/openstreetmap/josm/gui/layer/gpx/ConvertToDataLayerAction.java

     
    77import java.awt.GridBagLayout;
    88import java.awt.event.ActionEvent;
    99import java.io.File;
     10import java.util.ArrayList;
    1011
    1112import javax.swing.AbstractAction;
    1213import javax.swing.JLabel;
     
    1314import javax.swing.JOptionPane;
    1415import javax.swing.JPanel;
    1516
     17import org.openstreetmap.josm.actions.SimplifyWayAction;
    1618import org.openstreetmap.josm.data.osm.DataSet;
    1719import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
    1820import org.openstreetmap.josm.gui.MainApplication;
     
    6264        }
    6365        final DataSet ds = convert();
    6466        if (ds != null) {
     67            double err = SimplifyWayAction.askSimplifyWays(tr("Would you like to simplify the ways in the converted layer?"), true);
     68            if (err > 0) {
     69                SimplifyWayAction.simplifyWays(new ArrayList<>(ds.getWays()), err);
     70            }
    6571            final OsmDataLayer osmLayer = new OsmDataLayer(ds, tr("Converted from: {0}", layer.getName()), null);
    6672            if (layer.getAssociatedFile() != null) {
    6773                osmLayer.setAssociatedFile(new File(layer.getAssociatedFile().getParentFile(),
  • test/unit/org/openstreetmap/josm/actions/SimplifyWayActionTest.java

     
    129129        final Way w = new Way();
    130130        Stream.of(n1, n2, n3, n4, w).forEach(ds::addPrimitive);
    131131        Stream.of(n1, n2, n3, n4, n1).forEach(w::addNode);
    132         final SequenceCommand command = action.simplifyWay(w);
     132        final SequenceCommand command = SimplifyWayAction.createSimplifyCommand(w, 3);
    133133        assertNotNull(command);
    134134        assertEquals(2, command.getChildren().size());
    135135        final Collection<DeleteCommand> deleteCommands = Utils.filteredCollection(command.getChildren(), DeleteCommand.class);