Ignore:
Timestamp:
2008-09-21T19:04:06+02:00 (16 years ago)
Author:
stotz
Message:

Check for ways that are (partially) outside of the downloaded data bounding box - in such a case a warning is displayed and the user has to confirm

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/utilsplugin/src/UtilsPlugin/SimplifyWayAction.java

    r10656 r10823  
    1010import java.util.HashSet;
    1111import java.util.LinkedList;
    12 import java.util.List;
    1312
    1413import javax.swing.JOptionPane;
    1514
    1615import org.openstreetmap.josm.Main;
     16import org.openstreetmap.josm.actions.JosmAction;
    1717import org.openstreetmap.josm.command.ChangeCommand;
    1818import org.openstreetmap.josm.command.Command;
    1919import org.openstreetmap.josm.command.DeleteCommand;
    2020import org.openstreetmap.josm.command.SequenceCommand;
    21 import org.openstreetmap.josm.data.coor.LatLon;
     21import org.openstreetmap.josm.data.Bounds;
     22import org.openstreetmap.josm.data.osm.DataSource;
    2223import org.openstreetmap.josm.data.osm.Node;
    2324import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2425import org.openstreetmap.josm.data.osm.Way;
    2526import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
    26 
    27 import org.openstreetmap.josm.data.osm.DataSet;
    28 import org.openstreetmap.josm.actions.JosmAction;
     27import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    2928
    3029public class SimplifyWayAction extends JosmAction {
    31         public SimplifyWayAction() {
    32                 super(tr("Simplify Way"), "simplify",
    33                         tr("Delete unnecessary nodes from a way."), KeyEvent.VK_Y, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK, true);
    34         }
     30    public SimplifyWayAction() {
     31        super(tr("Simplify Way"), "simplify", tr("Delete unnecessary nodes from a way."), KeyEvent.VK_Y,
     32                KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK, true);
     33    }
    3534
    36         public void actionPerformed(ActionEvent e) {
    37                 Collection<OsmPrimitive> selection = Main.ds.getSelected();
    38                
     35    public void actionPerformed(ActionEvent e) {
     36        Collection<OsmPrimitive> selection = Main.ds.getSelected();
     37
    3938        int ways = 0;
    40                 for (OsmPrimitive prim : selection) {
    41                         if (prim instanceof Way) {
    42                                 ways++;
    43                         }
    44                 }
     39        LinkedList<Bounds> bounds = new LinkedList<Bounds>();
     40        OsmDataLayer dataLayer = Main.main.editLayer();
     41        for (DataSource ds : dataLayer.data.dataSources) {
     42            bounds.add(ds.bounds);
     43        }
     44        for (OsmPrimitive prim : selection) {
     45            if (prim instanceof Way) {
     46                Way way = (Way) prim;
     47                // We check if each node of each way is at least in one download
     48                // bounding box. Otherwise nodes may get deleted that are necessary by
     49                // unloaded ways (see Ticket #1594)
     50                for (Node node : way.nodes) {
     51                    boolean isInsideOneBoundingBox = false;
     52                    for (Bounds b : bounds) {
     53                        if (b.contains(node.coor)) {
     54                            isInsideOneBoundingBox = true;
     55                            break;
     56                        }
     57                    }
     58                    if (!isInsideOneBoundingBox) {
     59                        int option = JOptionPane.showConfirmDialog(Main.parent,
     60                                tr("The selected way(s) have nodes outside of the downloaded data region."
     61                                        + "This can lead to nodes beeing deleted accidentially.\n"
     62                                        + "Are you really sure to continue?"), tr("Plase abort if you are not sure"),
     63                                JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
     64
     65                        if (option != JOptionPane.YES_OPTION)
     66                            return;
     67                        break;
     68                    }
     69                }
     70
     71                ways++;
     72            }
     73        }
    4574
    4675        if (ways == 0) {
    47             JOptionPane.showMessageDialog(Main.parent,
    48                 tr("Please select at least one way to simplify."));
     76            JOptionPane.showMessageDialog(Main.parent, tr("Please select at least one way to simplify."));
    4977            return;
    5078        } else if (ways > 10) {
    51             int option = JOptionPane.showConfirmDialog(Main.parent,
    52                 tr("The selection contains {0} ways. Are you sure you want to simplify them all?", ways), tr("Are you sure?"), JOptionPane.YES_NO_OPTION);
     79            int option = JOptionPane.showConfirmDialog(Main.parent, tr(
     80                    "The selection contains {0} ways. Are you sure you want to simplify them all?", ways),
     81                    tr("Are you sure?"), JOptionPane.YES_NO_OPTION);
    5382            if (option != JOptionPane.YES_OPTION)
    5483                return;
    5584        }
    5685
    57                 for (OsmPrimitive prim : selection) {
    58                         if (prim instanceof Way) {
    59                                 simplifyWay((Way) prim);
    60                         }
    61                 }
    62         }
     86        for (OsmPrimitive prim : selection) {
     87            if (prim instanceof Way) {
     88                simplifyWay((Way) prim);
     89            }
     90        }
     91    }
    6392
    64         public void simplifyWay(Way w) {
    65                 double threshold = Double.parseDouble(
    66                         Main.pref.get("simplify-way.max-error", "3"));
     93    public void simplifyWay(Way w) {
     94        double threshold = Double.parseDouble(Main.pref.get("simplify-way.max-error", "3"));
    6795
    68                 Way wnew = new Way(w);
     96        Way wnew = new Way(w);
    6997
    70                 int toI = wnew.nodes.size() - 1;
    71                 for (int i = wnew.nodes.size() - 1; i >= 0; i--) {
    72                         CollectBackReferencesVisitor backRefsV =
    73                                 new CollectBackReferencesVisitor(Main.ds, false);
    74                         backRefsV.visit(wnew.nodes.get(i));
    75                         boolean used = false;
    76                         if (backRefsV.data.size() == 1) {
    77                                 used = Collections.frequency(
    78                                         w.nodes, wnew.nodes.get(i)) > 1;
    79                         } else {
    80                                 backRefsV.data.remove(w);
    81                                 used = !backRefsV.data.isEmpty();
    82                         }
    83                         if (!used) used = wnew.nodes.get(i).tagged;
     98        int toI = wnew.nodes.size() - 1;
     99        for (int i = wnew.nodes.size() - 1; i >= 0; i--) {
     100            CollectBackReferencesVisitor backRefsV = new CollectBackReferencesVisitor(Main.ds, false);
     101            backRefsV.visit(wnew.nodes.get(i));
     102            boolean used = false;
     103            if (backRefsV.data.size() == 1) {
     104                used = Collections.frequency(w.nodes, wnew.nodes.get(i)) > 1;
     105            } else {
     106                backRefsV.data.remove(w);
     107                used = !backRefsV.data.isEmpty();
     108            }
     109            if (!used)
     110                used = wnew.nodes.get(i).tagged;
    84111
    85                         if (used) {
    86                                 simplifyWayRange(wnew, i, toI, threshold);
    87                                 toI = i;
    88                         }
    89                 }
    90                 simplifyWayRange(wnew, 0, toI, threshold);
     112            if (used) {
     113                simplifyWayRange(wnew, i, toI, threshold);
     114                toI = i;
     115            }
     116        }
     117        simplifyWayRange(wnew, 0, toI, threshold);
    91118
    92                 HashSet<Node> delNodes = new HashSet<Node>();
    93                 delNodes.addAll(w.nodes);
    94                 delNodes.removeAll(wnew.nodes);
     119        HashSet<Node> delNodes = new HashSet<Node>();
     120        delNodes.addAll(w.nodes);
     121        delNodes.removeAll(wnew.nodes);
    95122
    96                 if (wnew.nodes.size() != w.nodes.size()) {
    97                         Collection<Command> cmds = new LinkedList<Command>();
    98                         cmds.add(new ChangeCommand(w, wnew));
    99                         cmds.add(new DeleteCommand(delNodes));
    100                         Main.main.undoRedo.add(
    101                                 new SequenceCommand(tr("Simplify Way (remove {0} nodes)",
    102                                                 delNodes.size()),
    103                                         cmds));
    104                         Main.map.repaint();
    105                 }
    106         }
     123        if (wnew.nodes.size() != w.nodes.size()) {
     124            Collection<Command> cmds = new LinkedList<Command>();
     125            cmds.add(new ChangeCommand(w, wnew));
     126            cmds.add(new DeleteCommand(delNodes));
     127            Main.main.undoRedo.add(new SequenceCommand(tr("Simplify Way (remove {0} nodes)", delNodes.size()), cmds));
     128            Main.map.repaint();
     129        }
     130    }
    107131
    108         public void simplifyWayRange(Way wnew, int from, int to, double thr) {
    109                 if (to - from >= 2) {
    110                         ArrayList<Node> ns = new ArrayList<Node>();
    111                         simplifyWayRange(wnew, from, to, ns, thr);
    112                         for (int j = to-1; j > from; j--) wnew.nodes.remove(j);
    113                         wnew.nodes.addAll(from+1, ns);
    114                 }
    115         }
     132    public void simplifyWayRange(Way wnew, int from, int to, double thr) {
     133        if (to - from >= 2) {
     134            ArrayList<Node> ns = new ArrayList<Node>();
     135            simplifyWayRange(wnew, from, to, ns, thr);
     136            for (int j = to - 1; j > from; j--)
     137                wnew.nodes.remove(j);
     138            wnew.nodes.addAll(from + 1, ns);
     139        }
     140    }
    116141
    117         /*
    118         * Takes an interval [from,to] and adds nodes from (from,to) to ns.
    119         * (from and to are indices of wnew.nodes.)
    120         */
    121         public void simplifyWayRange(Way wnew, int from, int to, ArrayList<Node> ns, double thr) {
    122                 Node fromN = wnew.nodes.get(from), toN = wnew.nodes.get(to);
     142    /*
     143    * Takes an interval [from,to] and adds nodes from (from,to) to ns.
     144    * (from and to are indices of wnew.nodes.)
     145    */
     146    public void simplifyWayRange(Way wnew, int from, int to, ArrayList<Node> ns, double thr) {
     147        Node fromN = wnew.nodes.get(from), toN = wnew.nodes.get(to);
    123148
    124                 int imax = -1;
    125                 double xtemax = 0;
    126                 for (int i = from+1; i < to; i++) {
    127                         Node n = wnew.nodes.get(i);
    128                         double xte = Math.abs(EARTH_RAD * xtd(
    129                                 fromN.coor.lat() * Math.PI/180, fromN.coor.lon() * Math.PI/180,
    130                                 toN.coor.lat() * Math.PI/180, toN.coor.lon() * Math.PI/180,
    131                                 n.coor.lat() * Math.PI/180, n.coor.lon() * Math.PI/180));
    132                         if (xte > xtemax) {
    133                                 xtemax = xte;
    134                                 imax = i;
    135                         }
    136                 }
     149        int imax = -1;
     150        double xtemax = 0;
     151        for (int i = from + 1; i < to; i++) {
     152            Node n = wnew.nodes.get(i);
     153            double xte = Math.abs(EARTH_RAD
     154                    * xtd(fromN.coor.lat() * Math.PI / 180, fromN.coor.lon() * Math.PI / 180, toN.coor.lat() * Math.PI
     155                            / 180, toN.coor.lon() * Math.PI / 180, n.coor.lat() * Math.PI / 180, n.coor.lon() * Math.PI
     156                            / 180));
     157            if (xte > xtemax) {
     158                xtemax = xte;
     159                imax = i;
     160            }
     161        }
    137162
    138                 if (imax != -1 && xtemax >= thr) {
    139                         simplifyWayRange(wnew, from, imax, ns, thr);
    140                         ns.add(wnew.nodes.get(imax));
    141                         simplifyWayRange(wnew, imax, to, ns, thr);
    142                 }
    143         }
     163        if (imax != -1 && xtemax >= thr) {
     164            simplifyWayRange(wnew, from, imax, ns, thr);
     165            ns.add(wnew.nodes.get(imax));
     166            simplifyWayRange(wnew, imax, to, ns, thr);
     167        }
     168    }
    144169
    145         public static double EARTH_RAD = 6378137.0;
     170    public static double EARTH_RAD = 6378137.0;
    146171
    147         /* From Aviaton Formulary v1.3
    148         * http://williams.best.vwh.net/avform.htm
    149         */
    150         public static double dist(double lat1, double lon1, double lat2, double lon2) {
    151                 return 2*Math.asin(Math.sqrt(Math.pow(Math.sin((lat1-lat2)/2), 2) +
    152                         Math.cos(lat1)*Math.cos(lat2)*Math.pow(Math.sin((lon1-lon2)/2), 2)));
    153         }
     172    /* From Aviaton Formulary v1.3
     173    * http://williams.best.vwh.net/avform.htm
     174    */
     175    public static double dist(double lat1, double lon1, double lat2, double lon2) {
     176        return 2 * Math.asin(Math.sqrt(Math.pow(Math.sin((lat1 - lat2) / 2), 2) + Math.cos(lat1) * Math.cos(lat2)
     177                * Math.pow(Math.sin((lon1 - lon2) / 2), 2)));
     178    }
    154179
    155         public static double course(double lat1, double lon1, double lat2, double lon2) {
    156                 return Math.atan2(Math.sin(lon1-lon2)*Math.cos(lat2),
    157                     Math.cos(lat1)*Math.sin(lat2)-Math.sin(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2)) % (2*Math.PI);
    158         }
     180    public static double course(double lat1, double lon1, double lat2, double lon2) {
     181        return Math.atan2(Math.sin(lon1 - lon2) * Math.cos(lat2), Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
     182                * Math.cos(lat2) * Math.cos(lon1 - lon2))
     183                % (2 * Math.PI);
     184    }
    159185
    160         public static double xtd(double lat1, double lon1, double lat2, double lon2, double lat3, double lon3) {
    161                 double dist_AD = dist(lat1, lon1, lat3, lon3);
    162                 double crs_AD = course(lat1, lon1, lat3, lon3);
    163                 double crs_AB = course(lat1, lon1, lat2, lon2);
    164                 return Math.asin(Math.sin(dist_AD)*Math.sin(crs_AD-crs_AB));
    165         }
     186    public static double xtd(double lat1, double lon1, double lat2, double lon2, double lat3, double lon3) {
     187        double dist_AD = dist(lat1, lon1, lat3, lon3);
     188        double crs_AD = course(lat1, lon1, lat3, lon3);
     189        double crs_AB = course(lat1, lon1, lat2, lon2);
     190        return Math.asin(Math.sin(dist_AD) * Math.sin(crs_AD - crs_AB));
     191    }
    166192}
Note: See TracChangeset for help on using the changeset viewer.