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

Last change on this file since 17705 was 17654, checked in by stoecker, 15 years ago

fixed some minor issues

File size: 9.3 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.LinkedList;
8
9import javax.swing.JOptionPane;
10
11import org.openstreetmap.josm.Main;
12import org.openstreetmap.josm.actions.JosmAction;
13import org.openstreetmap.josm.actions.MergeNodesAction;
14import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
15import org.openstreetmap.josm.data.Bounds;
16import org.openstreetmap.josm.data.osm.DataSource;
17import org.openstreetmap.josm.data.osm.Node;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.data.osm.Way;
20import org.openstreetmap.josm.gui.MainMenu;
21import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
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.main.getCurrentDataSet().getSelectedNodes();
63
64 if (selection.size()==0) {
65 selection = Main.main.getCurrentDataSet().getSelectedWays();
66 if (!workFromWaySelection(selection)) {
67 errMsg = tr("Select a starting node on the end of a way");
68 }
69 selection = Main.main.getCurrentDataSet().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 =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 new PleaseWaitProgressMonitor());
106
107 //The download is scheduled to be executed.
108 //Now schedule the run() method (below) to be executed once that's completed.
109 Main.worker.execute(this);
110 }
111 }
112 }
113
114 if(errMsg != null)
115 JOptionPane.showMessageDialog(Main.parent, errMsg);
116 }
117
118 /**
119 * Logic to excute after the download has happened
120 */
121 public void run() {
122 //Find ways connected to the node after the download
123 ArrayList<Way> connectedWays = findConnectedWays();
124
125 String errMsg = null;
126 if (connectedWays.size()==0) {
127 throw new RuntimeException("Way downloader data inconsistency. priorConnectedWay (" +
128 priorConnectedWay.toString() + ") wasn't discovered after download");
129
130 } else if (connectedWays.size()==1) {
131 //Just one way connecting the node still. Presumably the one which was there before
132
133 //Check if it's just a duplicate node
134 Node dupeNode = duplicateNode();
135 if (dupeNode!=null) {
136
137 if (JOptionPane.showConfirmDialog(null, "Merge duplicate node?")==JOptionPane.YES_OPTION) {
138 LinkedList<Node> dupeNodes = new LinkedList<Node>();
139 dupeNodes.add(dupeNode);
140 MergeNodesAction.mergeNodes(Main.main.getEditLayer(),
141 dupeNodes, selectedNode);
142
143 connectedWays = findConnectedWays(); //Carry on
144 }
145
146
147 } else {
148 errMsg = tr("Reached the end of the line");
149 }
150
151 }
152
153 if (connectedWays.size()>2) {
154 //Three or more ways meeting at this node. Means we have a junction.
155 errMsg = tr("Reached a junction");
156
157 } else if (connectedWays.size()==2) {
158 //Two connected ways (The "normal" way downloading case)
159 //Figure out which of the two is new.
160 System.out.println("connectedWays.toString()=" + connectedWays.toString());
161 Way wayA = connectedWays.get(0);
162 Way wayB = connectedWays.get(1);
163 Way nextWay = wayA;
164 if (priorConnectedWay.equals(wayA)) nextWay = wayB;
165
166 Node nextNode = findOtherEnd(nextWay, selectedNode);
167
168 //Select the next node
169 Main.main.getCurrentDataSet().setSelected(nextNode);
170
171 Main.map.mapView.zoomTo(nextNode.getEastNorth());
172 }
173 if(errMsg != null)
174 JOptionPane.showMessageDialog(Main.parent, errMsg);
175 }
176 }
177
178 /** See if there's another node at the same coordinates. If so return it. Otherwise null */
179 private Node duplicateNode() {
180 for (Node onNode:Main.main.getCurrentDataSet().nodes) {
181 if (!onNode.equals(this.selectedNode)
182 && !onNode.incomplete
183 && onNode.getCoor().lat()==selectedNode.getCoor().lat()
184 && onNode.getCoor().lon()==selectedNode.getCoor().lon()) {
185 return onNode;
186 }
187 }
188 return null;
189 }
190
191 /** Given the the node on one end of the way, return the node on the other end */
192 private Node findOtherEnd(Way way, Node firstEnd) {
193 Node otherEnd = way.firstNode();
194 if (otherEnd.equals(firstEnd)) otherEnd = way.lastNode();
195 return otherEnd;
196 }
197
198 /** find set of ways which have an end on the selectedNode */
199 private ArrayList<Way> findConnectedWays() {
200 ArrayList<Way> connectedWays = new ArrayList<Way>();
201
202 //loop through every way
203 for (Way onWay:Main.main.getCurrentDataSet().ways) {
204 if (onWay.getNodesCount() >= 2) {
205 if (onWay.isFirstLastNode(selectedNode)) {
206 //Found it
207 connectedWays.add(onWay);
208 }
209 }
210 }
211 return connectedWays;
212 }
213
214 /**
215 * given a selected way, select a node on the end of the way which is not in a downloaded area
216 * return true if this worked
217 */
218 private boolean workFromWaySelection(Collection<OsmPrimitive> selection) {
219
220 if (selection.size() != 1)
221 return false;
222 Way selectedWay = (Way) selection.iterator().next();
223 selectedNode = selectedWay.firstNode();
224
225 if (isDownloaded(selectedNode)) {
226 selectedNode = selectedWay.lastNode();
227
228 if (isDownloaded(selectedNode)) return false;
229 }
230 Main.main.getCurrentDataSet().setSelected(selectedNode);
231 return true;
232 }
233
234 private boolean isDownloaded(Node node) {
235 for (DataSource datasource:Main.main.getCurrentDataSet().dataSources) {
236 Bounds bounds = datasource.bounds;
237
238 if (node.getCoor().lat()>bounds.min.lat() &&
239 node.getCoor().lat()<bounds.max.lat() &&
240 node.getCoor().lon()>bounds.min.lon() &&
241 node.getCoor().lon()<bounds.max.lon()) {
242 return true;
243 }
244 }
245 return false;
246 }
247}
Note: See TracBrowser for help on using the repository browser.