source: osm/applications/editors/josm/plugins/waydownloader/src/WayDownloaderPlugin.java@ 16409

Last change on this file since 16409 was 16290, checked in by stoecker, 15 years ago

adapted plugins to JOSm 1722, UtilsPlugin still has a problem

File size: 9.8 KB
Line 
1import static org.openstreetmap.josm.tools.I18n.tr;
2
3import java.awt.event.ActionEvent;
4import java.awt.event.KeyEvent;
5import java.util.ArrayList;
6import java.util.Collection;
7import java.util.Iterator;
8import java.util.LinkedList;
9
10import javax.swing.JOptionPane;
11
12import org.openstreetmap.josm.Main;
13import org.openstreetmap.josm.actions.JosmAction;
14import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
15import org.openstreetmap.josm.actions.MergeNodesAction;
16import org.openstreetmap.josm.data.Bounds;
17import org.openstreetmap.josm.data.osm.DataSource;
18import org.openstreetmap.josm.data.osm.Node;
19import org.openstreetmap.josm.data.osm.OsmPrimitive;
20import org.openstreetmap.josm.data.osm.Way;
21import org.openstreetmap.josm.gui.MainMenu;
22import org.openstreetmap.josm.plugins.Plugin;
23import org.openstreetmap.josm.tools.Shortcut;
24
25/**
26 * Plugin class for the Way Downloader plugin
27 *
28 * @author Harry Wood
29 */
30public class WayDownloaderPlugin extends Plugin {
31
32 private Way priorConnectedWay = null;
33 private Node selectedNode = null;
34
35
36 /** Plugin constructor called at JOSM startup */
37 public WayDownloaderPlugin() {
38 //add WayDownloadAction to tools menu
39 MainMenu.add(Main.main.menu.toolsMenu, new WayDownloadAction());
40 }
41
42 private class WayDownloadAction extends JosmAction implements Runnable {
43
44 /** Set up the action (text appearing on the menu, keyboard shortcut etc */
45 public WayDownloadAction() {
46
47 super( "Way Download" ,
48 "way-download",
49 "Download map data on the end of selected way",
50 Shortcut.registerShortcut("waydownloader:waydownload", "Way Download", KeyEvent.VK_W, Shortcut.GROUP_MENU, Shortcut.SHIFT_DEFAULT),
51 true);
52 }
53
54 /** Called when the WayDownloadAction action is triggered (e.g. user clicked the menu option) */
55 public void actionPerformed(ActionEvent e) {
56
57 System.out.println("Way Download");
58
59 String errMsg = null;
60
61 selectedNode = null;
62 Collection<OsmPrimitive> selection = Main.ds.getSelectedNodes();
63
64 if (selection.size()==0) {
65 selection = Main.ds.getSelectedWays();
66 if (!workFromWaySelection(selection)) {
67 errMsg = tr("Select a starting node on the end of a way");
68 }
69 selection = Main.ds.getSelectedNodes();
70 }
71
72 if ( selection.size()==0 || selection.size()>1 ) {
73 errMsg = tr("Select a starting node on the end of a way");
74 } else {
75 OsmPrimitive p = selection.iterator().next();
76
77
78
79 if (!(p instanceof Node)) {
80 errMsg = tr("Select a starting node on the end of a way");
81 } else {
82 selectedNode = (Node) p;
83
84
85 Main.map.mapView.zoomTo(selectedNode.getEastNorth());
86
87 //Before downloading. Figure a few things out.
88 //Find connected way
89 ArrayList<Way> connectedWays = findConnectedWays();
90
91 if (connectedWays.size()==0) {
92 errMsg = tr("Select a starting node on the end of a way");
93 } else {
94 priorConnectedWay =(Way) connectedWays.get(0);
95
96 //Download a little rectangle around the selected node
97 double latbuffer=0.0003; //TODO make this an option
98 double lonbuffer=0.0005;
99 DownloadOsmTask downloadTask = new DownloadOsmTask();
100 downloadTask.download( null,
101 selectedNode.getCoor().lat()-latbuffer,
102 selectedNode.getCoor().lon()-lonbuffer,
103 selectedNode.getCoor().lat()+latbuffer,
104 selectedNode.getCoor().lon()+lonbuffer);
105
106 //The download is scheduled to be executed.
107 //Now schedule the run() method (below) to be executed once that's completed.
108 Main.worker.execute(this);
109 }
110 }
111 }
112
113 if(errMsg != null)
114 JOptionPane.showMessageDialog(Main.parent, errMsg);
115 }
116
117 /**
118 * Logic to excute after the download has happened
119 */
120 public void run() {
121 //Find ways connected to the node after the download
122 ArrayList<Way> connectedWays = findConnectedWays();
123
124 String errMsg = null;
125 if (connectedWays.size()==0) {
126 throw new RuntimeException("Way downloader data inconsistency. priorConnectedWay (" +
127 priorConnectedWay.toString() + ") wasn't discovered after download");
128
129 } else if (connectedWays.size()==1) {
130 //Just one way connecting the node still. Presumably the one which was there before
131
132 //Check if it's just a duplicate node
133 Node dupeNode = duplicateNode();
134 if (dupeNode!=null) {
135
136 if (JOptionPane.showConfirmDialog(null, "Merge duplicate node?")==JOptionPane.YES_OPTION) {
137 LinkedList<Node> dupeNodes = new LinkedList<Node>();
138 dupeNodes.add(dupeNode);
139 MergeNodesAction.mergeNodes(dupeNodes, selectedNode);
140
141 connectedWays = findConnectedWays(); //Carry on
142 }
143
144
145 } else {
146 errMsg = tr("Reached the end of the line");
147 }
148
149 }
150
151 if (connectedWays.size()>2) {
152 //Three or more ways meeting at this node. Means we have a junction.
153 errMsg = tr("Reached a junction");
154
155 } else if (connectedWays.size()==2) {
156 //Two connected ways (The "normal" way downloading case)
157 //Figure out which of the two is new.
158 System.out.println("connectedWays.toString()=" + connectedWays.toString());
159 Way wayA = (Way) connectedWays.get(0);
160 Way wayB = (Way) connectedWays.get(1);
161 Way nextWay = wayA;
162 if (priorConnectedWay.equals(wayA)) nextWay = wayB;
163
164 Node nextNode = findOtherEnd(nextWay, selectedNode);
165
166 //Select the next node
167 Main.ds.setSelected(nextNode);
168
169 Main.map.mapView.zoomTo(nextNode.getEastNorth());
170 }
171 if(errMsg != null)
172 JOptionPane.showMessageDialog(Main.parent, errMsg);
173 }
174 }
175
176 /** See if there's another node at the same coordinates. If so return it. Otherwise null */
177 private Node duplicateNode() {
178 Iterator nodesIter = Main.ds.nodes.iterator();
179 while (nodesIter.hasNext()) {
180 Node onNode = (Node) nodesIter.next();
181 if (!onNode.equals(this.selectedNode)
182 && onNode.getCoor().lat()==selectedNode.getCoor().lat()
183 && onNode.getCoor().lon()==selectedNode.getCoor().lon()) {
184 return onNode;
185 }
186 }
187 return null;
188 }
189
190 /** Given the the node on one end of the way, return the node on the other end */
191 private Node findOtherEnd(Way way, Node firstEnd) {
192 Node otherEnd = way.nodes.get(0);
193 if (otherEnd.equals(firstEnd)) otherEnd = way.nodes.get(way.nodes.size()-1);
194 return otherEnd;
195 }
196
197 /** find set of ways which have an end on the selectedNode */
198 private ArrayList<Way> findConnectedWays() {
199 ArrayList<Way> connectedWays = new ArrayList<Way>();
200
201 //loop through every way
202 Iterator waysIter = Main.ds.ways.iterator();
203 while (waysIter.hasNext()) {
204 Way onWay = (Way) waysIter.next();
205
206
207 Object[] nodes = onWay.nodes.toArray();
208 if (nodes.length<2) {
209 //Should never happen should it? TODO: investigate. For the moment ignore these
210 System.err.println("WayDownloader plugin encountered a way with " + nodes.length + " nodes :" + onWay.toString());
211 } else {
212 Node firstNode = (Node) nodes[0];
213 Node lastNode = (Node) nodes[nodes.length-1];
214
215 if (firstNode.equals(selectedNode) || lastNode.equals(selectedNode)) {
216 //Found it
217 connectedWays.add(onWay);
218 }
219 }
220 }
221 return connectedWays;
222 }
223
224 /**
225 * given a selected way, select a node on the end of the way which is not in a downloaded area
226 * return true if this worked
227 */
228 private boolean workFromWaySelection(Collection<OsmPrimitive> selection) {
229
230 if (selection.size()>1) {
231 //more than one way selected
232 return false;
233 } else {
234 Way selectedWay = (Way) selection.toArray()[0];
235 selectedNode = (Node) selectedWay.nodes.get(0);
236
237 if (isDownloaded(selectedNode)) {
238 selectedNode = findOtherEnd(selectedWay, selectedNode);
239
240 if (isDownloaded(selectedNode)) return false;
241 }
242 }
243 Main.ds.setSelected(selectedNode);
244 return true;
245 }
246
247 private boolean isDownloaded(Node node) {
248 Iterator downloadedAreasIter = Main.ds.dataSources.iterator();
249 while (downloadedAreasIter.hasNext()) {
250 DataSource datasource = (DataSource) downloadedAreasIter.next();
251 Bounds bounds = datasource.bounds;
252
253 if (node.getCoor().lat()>bounds.min.lat() &&
254 node.getCoor().lat()<bounds.max.lat() &&
255 node.getCoor().lon()>bounds.min.lon() &&
256 node.getCoor().lon()<bounds.max.lon()) {
257 return true;
258 }
259 }
260 return false;
261 }
262}
Note: See TracBrowser for help on using the repository browser.