Changeset 19872 in osm for applications/editors/josm/plugins/tracer
- Timestamp:
- 2010-02-04T22:39:37+01:00 (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/tracer/src/org/openstreetmap/josm/plugins/tracer/TracerAction.java
r19867 r19872 9 9 import java.awt.Cursor; 10 10 import java.awt.Point; 11 import java.awt.event.ActionEvent; 12 import java.awt.event.InputEvent; 11 13 import java.awt.event.KeyEvent; 12 14 import java.awt.event.MouseEvent; … … 21 23 import org.openstreetmap.josm.command.ChangeCommand; 22 24 import org.openstreetmap.josm.command.Command; 25 import org.openstreetmap.josm.command.DeleteCommand; 23 26 import org.openstreetmap.josm.command.SequenceCommand; 24 27 import org.openstreetmap.josm.data.coor.LatLon; … … 32 35 import org.xml.sax.SAXException; 33 36 import org.openstreetmap.josm.data.osm.BBox; 37 import org.openstreetmap.josm.data.osm.OsmPrimitive; 34 38 35 39 class TracerAction extends MapMode implements MouseListener { 36 40 37 pr otected TracerServer traceServer = new TracerServer();41 private static final long serialVersionUID = 1L; 38 42 protected boolean cancel; 39 protected Collection<Command> commands = new LinkedList<Command>(); 40 protected Collection<Way> ways = new ArrayList<Way>(); 43 private boolean ctrl; 44 private boolean alt; 45 private boolean shift; 46 protected TracerServer server = new TracerServer(); 41 47 42 48 public TracerAction(MapFrame mapFrame) { … … 65 71 66 72 protected void traceAsync(Point clickPoint) { 67 68 73 cancel = false; 69 74 /** 75 * Positional data 76 */ 70 77 final LatLon pos = Main.map.mapView.getLatLon(clickPoint.x, clickPoint.y); 71 78 … … 87 94 } 88 95 }; 89 Thread executeT hread = new Thread(tracerTask);90 executeT hread.start();96 Thread executeTraceThread = new Thread(tracerTask); 97 executeTraceThread.start(); 91 98 } catch (Exception e) { 92 99 e.printStackTrace(); … … 94 101 } 95 102 103 private boolean isBuilding(Way w) { 104 return (w.getKeys().get("building") == null ? false : w.getKeys().get("building").equals("yes")); 105 } 106 107 private boolean isInBuilding(Node n) { 108 for (OsmPrimitive op : n.getReferrers()) { 109 if (op instanceof Way) { 110 if (isBuilding((Way) op)) { 111 return true; 112 } 113 } 114 } 115 return false; 116 } 117 118 /** 119 * Try connect way to other buidings. 120 * @param way Way to connect. 121 * @return Commands. 122 */ 123 private Command connectObjects(Way way) { 124 final double MIN_DISTANCE = 0.000015; 125 126 List<Command> cmds = new LinkedList<Command>(); 127 Way newWay = new Way(way); 128 for (int i = 1; i < way.getNodesCount(); i++) { 129 Node n = way.getNode(i); 130 LatLon ll = n.getCoor(); 131 BBox bbox = new BBox( 132 ll.getX() - MIN_DISTANCE, 133 ll.getY() - MIN_DISTANCE, 134 ll.getX() + MIN_DISTANCE, 135 ll.getY() + MIN_DISTANCE); 136 137 // bude se node slucovat s jinym? 138 double minDistanceSq = MIN_DISTANCE; 139 List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(bbox); 140 Node nearestNode = null; 141 for (Node nn : nodes) { 142 if (!nn.isUsable() || way.containsNode(nn) || newWay.containsNode(nn) || !isInBuilding(nn)) { 143 continue; 144 } 145 double dist = nn.getCoor().distance(ll); 146 if (dist < minDistanceSq) { 147 minDistanceSq = dist; 148 nearestNode = nn; 149 } 150 } 151 152 //System.out.println("Nearest: " + nearestNode); 153 //System.out.println("-------"); 154 if (nearestNode == null) { 155 tryConnectNodeToAnyWay(way, newWay, n, cmds); 156 } else { 157 nearestNode.setCoor(ll.getCenter(nearestNode.getCoor())); 158 int j = newWay.getNodes().indexOf(n); 159 newWay.addNode(j, nearestNode); 160 if (j == 0) { 161 // first + last point 162 newWay.addNode(newWay.getNodesCount(), nearestNode); 163 } 164 newWay.removeNode(n); 165 cmds.add(new DeleteCommand(n)); 166 } 167 } 168 trySplitWayByAnyNodes(way, newWay); 169 170 cmds.add(new ChangeCommand(way, newWay)); 171 172 Command cmd = new SequenceCommand(tr("Merge objects nodes"), cmds); 173 return cmd; 174 } 175 176 /** 177 * Try connect node "node" from way "oldWay" to way of other building. 178 * 179 * Zkusi zjistit, zda node neni tak blizko nejake usecky existujici budovy, 180 * ze by mel byt zacnenen do teto usecky. Pokud ano, provede to. 181 * 182 * @param oldWay Way which contains node "node". 183 * @param newWay Modified way. 184 * @param node Node to connect. 185 * @param cmds Command list. 186 * @throws IllegalStateException 187 * @throws IndexOutOfBoundsException 188 */ 189 private void tryConnectNodeToAnyWay(Way oldWay, Way newWay, Node node, List<Command> cmds) 190 throws IllegalStateException, IndexOutOfBoundsException { 191 192 final double MIN_DISTANCE = 0.000015; 193 194 LatLon ll = node.getCoor(); 195 BBox bbox = new BBox( 196 ll.getX() - MIN_DISTANCE, 197 ll.getY() - MIN_DISTANCE, 198 ll.getX() + MIN_DISTANCE, 199 ll.getY() + MIN_DISTANCE); 200 201 // node nebyl slouceny s jinym 202 // hledani pripadne blizke usecky, kam bod pridat 203 List<Way> ways = Main.main.getCurrentDataSet().searchWays(bbox); 204 double minDist = Double.MAX_VALUE; 205 Way nearestWay = null; 206 int nearestNodeIndex = 0; 207 for (Way ww : ways) { 208 if (!ww.isUsable() || ww == oldWay || ww == newWay || !isBuilding(ww)) { 209 continue; 210 } 211 for (int nindex = 0; nindex < ww.getNodesCount(); nindex++) { 212 Node n1 = ww.getNode(nindex); 213 Node n2 = ww.getNode((nindex + 1) % ww.getNodesCount()); 214 double dist = TracerGeometry.distanceFromSegment(ll, n1.getCoor(), n2.getCoor()); 215 if (dist < minDist) { 216 minDist = dist; 217 nearestWay = ww; 218 nearestNodeIndex = nindex; 219 } 220 } 221 } 222 //System.out.println("Nearest way:" + nearestWay); 223 if (minDist < MIN_DISTANCE) { 224 Way newNWay = new Way(nearestWay); 225 newNWay.addNode(nearestNodeIndex + 1, node); 226 //System.out.println("New way:" + newNWay); 227 cmds.add(new ChangeCommand(nearestWay, newNWay)); 228 } 229 } 230 231 /** 232 * Try split way by any existing buiding nodes. 233 * 234 * Zkusi zjistit zda nejake usecka z oldWay by nemela prochazet nejakym existujicim bodem, 235 * ktery je ji velmi blizko. Pokud ano, tak puvodni usecku rozdeli na dve tak, aby 236 * prochazela takovym bodem. 237 * 238 * @param oldWay Way to split. 239 * @param newWay Modified way. 240 * @throws IndexOutOfBoundsException 241 * @throws IllegalStateException 242 */ 243 private void trySplitWayByAnyNodes(Way oldWay, Way newWay) 244 throws IndexOutOfBoundsException, IllegalStateException { 245 246 // projdi kazdou novou usecku a zjisti, zda by nemela vest pres existujici body 247 int i = 0; 248 while (i < newWay.getNodesCount()) { 249 // usecka n1, n2 250 LatLon n1 = newWay.getNodes().get(i).getCoor(); 251 LatLon n2 = newWay.getNodes().get((i + 1) % newWay.getNodesCount()).getCoor(); 252 //System.out.println(newWay.getNodes().get(i) + "-----" + newWay.getNodes().get((i + 1) % newWay.getNodesCount())); 253 double minDistanceSq = 0.000015; 254 double maxAngle = 15; 255 List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(new BBox(Math.min(n1.getX(), n2.getX()) - minDistanceSq, Math.min(n1.getY(), n2.getY()) - minDistanceSq, Math.max(n1.getX(), n2.getX()) + minDistanceSq, Math.max(n1.getY(), n2.getY()) + minDistanceSq)); 256 Node nearestNode = null; 257 for (Node nod : nodes) { 258 if (!nod.isUsable() || oldWay.containsNode(nod) || newWay.containsNode(nod) || !isInBuilding(nod)) { 259 continue; 260 } 261 LatLon nn = nod.getCoor(); 262 double dist = TracerGeometry.distanceFromSegment(nn, n1, n2); 263 double angle = TracerGeometry.angleOfLines(n1, nn, nn, n2); 264 if (!n1.equalsEpsilon(nn) && !n2.equalsEpsilon(nn) && dist < minDistanceSq && Math.abs(angle) < maxAngle) { 265 maxAngle = angle; 266 nearestNode = nod; 267 } 268 } 269 //System.out.println("Nearest_: " + nearestNode); 270 //System.out.println(""); 271 if (nearestNode == null) { 272 // tato usecka se nerozdeli 273 i++; 274 continue; 275 } else { 276 // rozdeleni usecky 277 newWay.addNode(i + 1, nearestNode); 278 continue; // i nezvetsuji, treba bude treba rozdelit usecku znovu 279 } 280 } 281 } 282 283 private void tagBuilding(Way way) { 284 way.put("building", "yes"); 285 way.put("source", "cuzk:km"); 286 } 287 96 288 private void traceSync(LatLon pos, ProgressMonitor progressMonitor) { 97 289 Collection<Command> commands = new LinkedList<Command>(); 290 98 291 progressMonitor.beginTask(null, 3); 99 292 try { 100 ArrayList<double[]> nodelist = new ArrayList<double[]>(); 101 nodelist = traceServer.trace(pos); 102 103 if (nodelist.size() == 0) { 293 ArrayList<LatLon> coordList = server.trace(pos); 294 295 if (coordList.size() == 0) { 104 296 return; 105 297 } 106 298 107 /** 108 * Turn the arraylist into osm nodes 109 */ 299 // make nodes a way 110 300 Way way = new Way(); 111 Node n = null; 112 Node fn = null; 113 114 double eastOffset = 0; 115 double northOffset = 0; 116 117 118 int nodesinway = 0; 119 120 for (int i = 0; i < nodelist.size(); i++) { 121 if (cancel) { 122 return; 123 } 124 125 try { 126 LatLon ll = new LatLon(nodelist.get(i)[0] + northOffset, nodelist.get(i)[1] + eastOffset); 127 128 double minDistanceSq = 0.00001; 129 BBox box = new BBox( 130 ll.getX() - minDistanceSq, 131 ll.getY() - minDistanceSq, 132 ll.getX() + minDistanceSq, 133 ll.getY() + minDistanceSq); 134 List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(box); 135 List<Way> nodeWays = Main.main.getCurrentDataSet().searchWays(box); 136 Node nearestNode = null; 137 for (Node nn : nodes) { 138 if (!nn.isUsable()) { 139 continue; 140 } 141 142 boolean buildingNode = false; 143 for (Way w : nodeWays) { 144 if (w.containsNode(nn) && w.hasKey("building")) { 145 buildingNode = true; 146 break; 147 } 148 } 149 if (!buildingNode) { 150 continue; 151 } 152 153 LatLon ll2 = nn.getCoor(); 154 double dist = ll2.distance(ll); 155 if (dist < minDistanceSq) { 156 minDistanceSq = dist; 157 nearestNode = nn; 158 } 159 } 160 161 if (nearestNode == null) { 162 // hledani blizke usecky, kam bod pridat ... nebo vytvorit samostatny bod? 163 List<Way> ways = Main.main.getCurrentDataSet().searchWays(new BBox( 164 ll.getX() - minDistanceSq, 165 ll.getY() - minDistanceSq, 166 ll.getX() + minDistanceSq, 167 ll.getY() + minDistanceSq)); 168 double minDist = Double.MAX_VALUE; 169 Way nearestWay = null; 170 int nearestNodeIndex = 0; 171 172 173 for (Way ww : ways) { 174 if (!ww.hasKey("building")) { 175 continue; 176 } 177 for (int nindex = 0; nindex < ww.getNodesCount(); nindex++) { 178 Node n1 = ww.getNode(nindex); 179 Node n2 = ww.getNode((nindex + 1) % ww.getNodesCount()); 180 181 double dist = TracerGeometry.distanceFromSegment(ll, n1.getCoor(), n2.getCoor()); 182 if (dist < minDist) { 183 minDist = dist; 184 nearestWay = ww; 185 nearestNodeIndex = nindex; 186 } 187 } 188 } 189 190 if (minDist < 0.00001) { 191 n = new Node(ll); 192 commands.add(new AddCommand(n)); 193 Way newWay = new Way(nearestWay); 194 newWay.addNode(nearestNodeIndex + 1, n); 195 commands.add(new ChangeCommand(nearestWay, newWay)); 196 } else { 197 n = new Node(ll); 198 commands.add(new AddCommand(n)); 199 } 200 } else { 201 n = nearestNode; 202 } 203 204 if (fn == null) { 205 fn = n; 206 } 207 208 } catch (Exception ex) { 209 ex.printStackTrace(); 210 } 211 212 way.addNode(n); 213 nodesinway++; 214 } 215 /**/ 216 // projdi kazdou novou usecku a zjisti, zda by nemela vest pres existujici body 217 int i = 0; 218 while (i < nodelist.size()) { 219 if (cancel) { 220 return; 221 } 222 223 traceServer.log("i/" + i); 224 225 // usecka n1, n2 226 double d[] = nodelist.get(i); 227 LatLon n1 = new LatLon(d[0], d[1]); 228 d = nodelist.get((i + 1) % nodelist.size()); 229 LatLon n2 = new LatLon(d[0], d[1]); 230 231 double minDistanceSq = 0.00001; 232 double maxAngle = 10; 233 BBox box = new BBox( 234 Math.min(n1.getX(), n2.getX()) - minDistanceSq, 235 Math.min(n1.getY(), n2.getY()) - minDistanceSq, 236 Math.max(n1.getX(), n2.getX()) + minDistanceSq, 237 Math.max(n1.getY(), n2.getY()) + minDistanceSq); 238 List<Node> nodes = Main.main.getCurrentDataSet().searchNodes(box); 239 List<Way> nodeWays = Main.main.getCurrentDataSet().searchWays(box); 240 Node nearestNode = null; 241 for (Node nod : nodes) { 242 if (!nod.isUsable()) { 243 continue; 244 } 245 boolean buildingNode = false; 246 for (Way w : nodeWays) { 247 if (w.containsNode(nod) && w.hasKey("building")) { 248 buildingNode = true; 249 break; 250 } 251 } 252 if (!buildingNode) { 253 continue; 254 } 255 256 LatLon nn = nod.getCoor(); 257 double dist = TracerGeometry.distanceFromSegment(nn, n1, n2); 258 double angle = TracerGeometry.angleOfLines(n1, nn, nn, n2); 259 260 if (!n1.equalsEpsilon(nn) && !n2.equalsEpsilon(nn) && dist < minDistanceSq) { 261 traceServer.log("n1/" + n1.toDisplayString()); 262 traceServer.log("nn/" + nn.toDisplayString()); 263 traceServer.log("n2/" + n2.toDisplayString()); 264 traceServer.log("angle/" + Math.abs(angle)); 265 } 266 if (!n1.equalsEpsilon(nn) && !n2.equalsEpsilon(nn) && dist < minDistanceSq && Math.abs(angle) < maxAngle) { 267 traceServer.log("ok"); 268 maxAngle = angle; 269 nearestNode = nod; 270 } 271 } 272 273 if (nearestNode == null) { 274 // tato usecka se nerozdeli 275 i++; 276 continue; 277 } else { 278 // rozdeleni usecky 279 nodelist.add(i + 1, new double[]{nearestNode.getCoor().getY(), nearestNode.getCoor().getX()}); 280 way.addNode(i + 1, nearestNode); 281 continue; // i nezvetsuji, treba bude treba rozdelit usecku znovu 282 } 283 284 } 285 /**/ 286 way.put("building", "yes"); 287 way.put("source", "cuzk:km"); 288 289 way.addNode(fn); 290 301 Node firstNode = null; 302 for (LatLon coord : coordList) { 303 Node node = new Node(coord); 304 if (firstNode == null) { 305 firstNode = node; 306 } 307 commands.add(new AddCommand(node)); 308 way.addNode(node); 309 } 310 way.addNode(firstNode); 311 312 tagBuilding(way); 291 313 commands.add(new AddCommand(way)); 314 315 // connect to other buildings 316 if (!ctrl) { 317 commands.add(connectObjects(way)); 318 } 292 319 293 320 if (!commands.isEmpty()) { 294 321 Main.main.undoRedo.add(new SequenceCommand(tr("Tracer building"), commands)); 295 Main.main.getCurrentDataSet().setSelected(ways); 322 323 if (shift) { 324 Main.main.getCurrentDataSet().addSelected(way); 325 } else { 326 Main.main.getCurrentDataSet().setSelected(way); 327 } 296 328 } else { 297 329 System.out.println("Failed"); 298 330 } 299 331 300 commands = new LinkedList<Command>();301 ways = new ArrayList<Way>();302 332 } finally { 303 333 progressMonitor.finishTask(); … … 309 339 } 310 340 341 @Override 311 342 public void mouseClicked(MouseEvent e) { 312 343 } 313 344 345 @Override 314 346 public void mouseEntered(MouseEvent e) { 315 347 } 316 348 349 @Override 317 350 public void mouseExited(MouseEvent e) { 318 351 } 319 352 353 @Override 320 354 public void mousePressed(MouseEvent e) { 321 355 if (!Main.map.mapView.isActiveLayerDrawable()) { … … 323 357 } 324 358 359 updateKeyModifiers(e); 325 360 if (e.getButton() == MouseEvent.BUTTON1) { 326 361 traceAsync(e.getPoint()); … … 328 363 } 329 364 365 private void updateKeyModifiers(MouseEvent e) { 366 ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 367 alt = (e.getModifiers() & (ActionEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0; 368 shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 369 } 370 371 @Override 330 372 public void mouseReleased(MouseEvent e) { 331 373 }
Note:
See TracChangeset
for help on using the changeset viewer.