Ignore:
Timestamp:
2009-11-15T11:51:34+01:00 (15 years ago)
Author:
guggis
Message:

Fixed merging of nodes
improved messages
completed I18n
now uses referrers and searching of nodes in a bounding box
now only enabled if current layer is a data layer
updated build.xml

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/waydownloader/src/org/openstreetmap/josm/plugins/waydownloader/WayDownloaderPlugin.java

    r18417 r18613  
    77import java.util.ArrayList;
    88import java.util.Collection;
     9import java.util.Collections;
    910import java.util.LinkedList;
     11import java.util.List;
    1012import java.util.concurrent.Future;
    1113
     
    1618import org.openstreetmap.josm.actions.MergeNodesAction;
    1719import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
     20import org.openstreetmap.josm.command.Command;
    1821import org.openstreetmap.josm.data.Bounds;
     22import org.openstreetmap.josm.data.osm.BBox;
     23import org.openstreetmap.josm.data.osm.DataSet;
    1924import org.openstreetmap.josm.data.osm.DataSource;
    2025import org.openstreetmap.josm.data.osm.Node;
    2126import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2227import org.openstreetmap.josm.data.osm.Way;
     28import org.openstreetmap.josm.gui.DefaultNameFormatter;
    2329import org.openstreetmap.josm.gui.MainMenu;
    2430import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
     
    4753        /** Set up the action (text appearing on the menu, keyboard shortcut etc */
    4854        public WayDownloadAction() {
    49 
    50             super( "Way Download" ,
     55            super( tr("Way Download") ,
    5156                    "way-download",
    52                     "Download map data on the end of selected way",
     57                    tr("Download map data on the end of selected way"),
    5358                    Shortcut.registerShortcut("waydownloader:waydownload", "Way Download", KeyEvent.VK_W, Shortcut.GROUP_MENU, Shortcut.SHIFT_DEFAULT),
    5459                    true);
    5560        }
    5661
     62        protected void showWarningMessage(String msg) {
     63                 if(msg == null) return;
     64             JOptionPane.showMessageDialog(
     65                        Main.parent,
     66                        msg,
     67                        tr("Warning"),
     68                        JOptionPane.WARNING_MESSAGE                             
     69             );
     70        }
     71       
     72        protected void showErrorMessage(String msg) {
     73         if(msg == null) return;
     74                JOptionPane.showMessageDialog(
     75                                Main.parent,
     76                                msg,
     77                                tr("Error"),
     78                                JOptionPane.ERROR_MESSAGE                               
     79                );
     80       }
     81       
     82        protected void showInfoMessage(String msg) {
     83                 if(msg == null) return;
     84               JOptionPane.showMessageDialog(
     85                        Main.parent,
     86                        msg,
     87                        tr("Information"),
     88                        JOptionPane.INFORMATION_MESSAGE                         
     89               );
     90          }
     91       
    5792        /** Called when the WayDownloadAction action is triggered (e.g. user clicked the menu option) */
    5893        public void actionPerformed(ActionEvent e) {
    59 
    60             System.out.println("Way Download");
    61 
    62             String errMsg = null;
    63 
    6494            selectedNode = null;
    6595            Collection<OsmPrimitive> selection = Main.main.getCurrentDataSet().getSelectedNodes();
    66 
    6796            if (selection.size()==0) {
    6897                selection = Main.main.getCurrentDataSet().getSelectedWays();
    6998                if (!workFromWaySelection(selection)) {
    70                     errMsg = tr("Select a starting node on the end of a way");
     99                        showWarningMessage(tr("<html>Neither a node nor a way with an endpoint outside of the<br>current download areas is selected.<br>Select a node on the start or end of a way or an entire way first.</html>"));
     100                        return;
    71101                }
    72102                selection = Main.main.getCurrentDataSet().getSelectedNodes();
    73103            }
    74104
    75             if ( selection.size()==0 || selection.size()>1 ) {
    76                 errMsg = tr("Select a starting node on the end of a way");
    77             } else {
    78                 OsmPrimitive p = selection.iterator().next();
    79 
    80 
    81 
    82                 if (!(p instanceof Node)) {
    83                     errMsg = tr("Select a starting node on the end of a way");
    84                 } else {
    85                     selectedNode = (Node) p;
    86 
    87 
    88                     Main.map.mapView.zoomTo(selectedNode.getEastNorth());
    89 
    90                     //Before downloading. Figure a few things out.
    91                     //Find connected way
    92                     ArrayList<Way> connectedWays = findConnectedWays();
    93 
    94                     if (connectedWays.size()==0) {
    95                         errMsg = tr("Select a starting node on the end of a way");
    96                     } else {
    97                         priorConnectedWay =connectedWays.get(0);
    98 
    99                         //Download a little rectangle around the selected node
    100                         double latbuffer=0.0003; //TODO make this an option
    101                         double lonbuffer=0.0005;
    102                         DownloadOsmTask downloadTask = new DownloadOsmTask();
    103                         final PleaseWaitProgressMonitor monitor = new PleaseWaitProgressMonitor();
    104                         final Future<?> future = downloadTask.download(
    105                                         false /* no new layer */,
    106                                         new Bounds(
    107                                                         selectedNode.getCoor().lat()- latbuffer,
    108                                                         selectedNode.getCoor().lon()- lonbuffer,
    109                                                         selectedNode.getCoor().lat()+ latbuffer,
    110                                                         selectedNode.getCoor().lon()+ lonbuffer
    111                                         ),
    112                                         monitor
    113                         );
    114                         // schedule closing of the progress monitor after the download
    115                         // job has finished
    116                         Main.worker.submit(
    117                                 new Runnable() {
    118                                     public void run() {
    119                                         try {
    120                                             future.get();
    121                                         } catch(Exception e) {
    122                                             e.printStackTrace();
    123                                             return;
    124                                         }
    125                                         monitor.close();
    126                                     }
    127                                 }
    128                         );
    129                         //The download is scheduled to be executed.
    130                         //Now schedule the run() method (below) to be executed once that's completed.
    131                         Main.worker.execute(this);
     105            if ( selection.size()==0 || selection.size()>1 || ! (selection.iterator().next() instanceof Node)) {
     106                showWarningMessage(tr("<html>Could not find a unique node to start downloading from.</html>"));
     107                return;
     108            }
     109       
     110            selectedNode = (Node) selection.iterator().next();
     111            Main.map.mapView.zoomTo(selectedNode.getEastNorth());
     112
     113            //Before downloading. Figure a few things out.
     114            //Find connected way
     115            List<Way> connectedWays = findConnectedWays(selectedNode);
     116            if (connectedWays.size()==0) {
     117                showWarningMessage(
     118                                tr("<html>There are no ways connected to node ''{0}''. Aborting.</html>",
     119                                selectedNode.getDisplayName(DefaultNameFormatter.getInstance()))
     120                );
     121                return;
     122            }
     123            priorConnectedWay =connectedWays.get(0);
     124
     125            //Download a little rectangle around the selected node
     126            double latbuffer=0.0003; //TODO make this an option
     127            double lonbuffer=0.0005;
     128            DownloadOsmTask downloadTask = new DownloadOsmTask();
     129            final PleaseWaitProgressMonitor monitor = new PleaseWaitProgressMonitor();
     130            final Future<?> future = downloadTask.download(
     131                        false /* no new layer */,
     132                        new Bounds(
     133                                        selectedNode.getCoor().lat()- latbuffer,
     134                                        selectedNode.getCoor().lon()- lonbuffer,
     135                                        selectedNode.getCoor().lat()+ latbuffer,
     136                                        selectedNode.getCoor().lon()+ lonbuffer
     137                        ),
     138                        monitor
     139            );
     140            // schedule closing of the progress monitor after the download
     141            // job has finished
     142            Main.worker.submit(
     143                    new Runnable() {
     144                        public void run() {
     145                            try {
     146                                future.get();
     147                            } catch(Exception e) {
     148                                e.printStackTrace();
     149                                return;
     150                            }
     151                            monitor.close();
     152                        }
    132153                    }
    133                 }
    134             }
    135 
    136             if(errMsg != null)
    137                 JOptionPane.showMessageDialog(Main.parent, errMsg);
     154            );
     155            //The download is scheduled to be executed.
     156            //Now schedule the run() method (below) to be executed once that's completed.
     157            Main.worker.execute(this);
    138158        }
    139159
     
    143163        public void run() {
    144164            //Find ways connected to the node after the download
    145             ArrayList<Way> connectedWays = findConnectedWays();
    146 
    147             String errMsg = null;
     165            List<Way> connectedWays = findConnectedWays(selectedNode);
     166
    148167            if (connectedWays.size()==0) {
    149                 throw new RuntimeException("Way downloader data inconsistency. priorConnectedWay (" +
    150                         priorConnectedWay.toString() + ") wasn't discovered after download");
    151 
    152             } else if (connectedWays.size()==1) {
    153                 //Just one way connecting the node still. Presumably the one which was there before
    154 
     168                String msg = tr("Way downloader data inconsistency. Prior connected way ''{0}'' wasn''t discovered after download",
     169                                                priorConnectedWay.getDisplayName(DefaultNameFormatter.getInstance())
     170                                );
     171                System.err.println(msg);
     172                showErrorMessage(msg);
     173                return;               
     174            }
     175           
     176            if (connectedWays.size()==1) {
     177                //Just one way connecting still to the node . Presumably the one which was there before
    155178                //Check if it's just a duplicate node
    156                 Node dupeNode = duplicateNode();
     179               
     180                Node dupeNode = findDuplicateNode(selectedNode);
    157181                if (dupeNode!=null) {
    158 
    159                     if (JOptionPane.showConfirmDialog(null, "Merge duplicate node?")==JOptionPane.YES_OPTION) {
    160                         LinkedList<Node> dupeNodes = new LinkedList<Node>();
    161                         dupeNodes.add(dupeNode);
    162                         MergeNodesAction.mergeNodes(Main.main.getEditLayer(),
    163                         dupeNodes, selectedNode);
    164 
    165                         connectedWays = findConnectedWays(); //Carry on
     182                        String msg = tr("<html>There aren''t further connected ways to download.<br>"
     183                                        + "A potential duplicate node of the currently selected node was found, though.<br><br>"
     184                                        + "The currently selected node is ''{0}''<br>"
     185                                        + "The potential duplicate node is ''{1}''<br>"
     186                                        + "Merge the duplicate node onto the currently selected node and continue way downloading?"
     187                                        + "</html>",
     188                                        selectedNode.getDisplayName(DefaultNameFormatter.getInstance()),
     189                                        dupeNode.getDisplayName(DefaultNameFormatter.getInstance())
     190                        );
     191                                       
     192                        int ret = JOptionPane.showConfirmDialog(
     193                                        Main.parent,
     194                                        msg,
     195                                        tr("Merge duplicate node?"),
     196                                        JOptionPane.YES_NO_OPTION,
     197                                        JOptionPane.QUESTION_MESSAGE
     198                        );
     199                        if (ret != JOptionPane.YES_OPTION)
     200                                return;
     201                    Command cmd = MergeNodesAction.mergeNodes(
     202                                Main.main.getEditLayer(),
     203                                Collections.singletonList(dupeNode),
     204                                selectedNode
     205                    );
     206                    if (cmd != null) {
     207                        Main.main.undoRedo.add(cmd);
     208                        Main.main.getEditLayer().data.setSelected(selectedNode);
    166209                    }
    167 
    168 
     210                    connectedWays = findConnectedWays(selectedNode);
    169211                } else {
    170                     errMsg = tr("Reached the end of the line");
    171                 }
    172 
    173             }
    174 
     212                        showInfoMessage(tr("<html>No more connected ways to download.</html>"));
     213                        return;
     214                }               
     215                return;
     216            }
     217           
    175218            if (connectedWays.size()>2) {
    176219                //Three or more ways meeting at this node. Means we have a junction.
    177                 errMsg = tr("Reached a junction");
    178 
    179             } else if (connectedWays.size()==2) {
     220                String msg = tr(
     221                                "Node ''{0}'' is a junction with more than 2 connected ways.",
     222                                selectedNode.getDisplayName(DefaultNameFormatter.getInstance())
     223                );
     224                showWarningMessage(msg);
     225                return;
     226            }
     227           
     228            if (connectedWays.size()==2) {
    180229                //Two connected ways (The "normal" way downloading case)
    181230                //Figure out which of the two is new.
    182                 System.out.println("connectedWays.toString()=" + connectedWays.toString());
    183231                Way wayA = connectedWays.get(0);
    184232                Way wayB = connectedWays.get(1);
     
    190238                //Select the next node
    191239                Main.main.getCurrentDataSet().setSelected(nextNode);
    192 
    193240                Main.map.mapView.zoomTo(nextNode.getEastNorth());
    194241            }
    195             if(errMsg != null)
    196                 JOptionPane.showMessageDialog(Main.parent, errMsg);
    197         }
    198     }
    199 
    200     /** See if there's another node at the same coordinates. If so return it. Otherwise null */
    201     private Node duplicateNode() {
    202         for (Node onNode:Main.main.getCurrentDataSet().getNodes()) {
    203             if (!onNode.equals(this.selectedNode)
    204                     && !onNode.incomplete
    205                     && onNode.getCoor().lat()==selectedNode.getCoor().lat()
    206                     && onNode.getCoor().lon()==selectedNode.getCoor().lon()) {
    207                 return onNode;
    208             }
     242        }
     243
     244                @Override
     245                protected void updateEnabledState() {
     246                        setEnabled(getEditLayer() != null);
     247                }
     248
     249                @Override
     250                protected void updateEnabledState(
     251                                Collection<? extends OsmPrimitive> selection) {
     252                        // do nothing
     253                }
     254    }
     255
     256    /**
     257     * Check whether there is a potentially duplicate node for <code>referenceNode</code>.
     258     *
     259     * @param referenceNode the reference node
     260     * @return the potential duplicate node. null, if no duplicate found.
     261     */
     262    private Node findDuplicateNode(Node referenceNode) {
     263        DataSet ds = Main.main.getCurrentDataSet();
     264        List<Node> candidates = ds.searchNodes(new BBox(new Bounds(referenceNode.getCoor(), 0.0003, 0.0005)));
     265        for (Node candidate: candidates) {
     266            if (!candidate.equals(referenceNode)
     267                    && !candidate.incomplete
     268                    && candidate.getCoor().equals(referenceNode.getCoor()))
     269                return candidate;           
    209270        }
    210271        return null;
     
    218279    }
    219280
    220     /** find set of ways which have an end on the selectedNode */
    221     private ArrayList<Way> findConnectedWays() {
    222         ArrayList<Way> connectedWays = new ArrayList<Way>();
    223 
    224         //loop through every way
    225         for (Way onWay:Main.main.getCurrentDataSet().getWays()) {
    226             if (onWay.getNodesCount() >= 2) {
    227                 if (onWay.isFirstLastNode(selectedNode)) {
    228                     //Found it
    229                     connectedWays.add(onWay);
    230                 }
     281    /**
     282     * Replies the list of ways <code>referenceNode</code> is either the first or the
     283     * last node in.
     284     *
     285     * @param referenceNode the reference node
     286     * @return the list of ways. May be empty, but null.
     287     */
     288    private List<Way> findConnectedWays(Node referenceNode) {
     289        List<Way> referers = OsmPrimitive.getFilteredList(referenceNode.getReferrers(), Way.class);
     290        ArrayList<Way> connectedWays = new ArrayList<Way>(referers.size());
     291
     292        //loop through referers
     293        for (Way way: referers) {
     294            if (way.getNodesCount() >= 2 && way.isFirstLastNode(referenceNode)) {
     295                    connectedWays.add(way);
    231296            }
    232297        }
     
    239304     */
    240305    private boolean workFromWaySelection(Collection<OsmPrimitive> selection) {
    241 
    242306        if (selection.size() != 1)
    243307            return false;
     
    257321        for (DataSource datasource:Main.main.getCurrentDataSet().dataSources) {
    258322            Bounds bounds = datasource.bounds;
    259 
    260             if (node.getCoor().lat()>bounds.getMin().lat() &&
    261                 node.getCoor().lat()<bounds.getMax().lat() &&
    262                 node.getCoor().lon()>bounds.getMin().lon() &&
    263                 node.getCoor().lon()<bounds.getMax().lon()) {
    264                 return true;
    265             }
     323            if (bounds != null && bounds.contains(node.getCoor())) return true;
    266324        }
    267325        return false;
Note: See TracChangeset for help on using the changeset viewer.