Ticket #16948: improve_snap.patch
| File improve_snap.patch, 9.6 KB (added by , 7 years ago) |
|---|
-
src/org/openstreetmap/josm/plugins/buildings_tools/Building.java
12 12 import java.util.Arrays; 13 13 import java.util.Collection; 14 14 import java.util.Collections; 15 import java.util.LinkedHashSet; 15 16 import java.util.LinkedList; 16 17 import java.util.List; 17 18 import java.util.Map.Entry; 19 import java.util.Set; 18 20 19 21 import javax.swing.JOptionPane; 20 22 … … 26 28 import org.openstreetmap.josm.command.SequenceCommand; 27 29 import org.openstreetmap.josm.data.UndoRedoHandler; 28 30 import org.openstreetmap.josm.data.coor.EastNorth; 29 import org.openstreetmap.josm.data.coor.LatLon;30 31 import org.openstreetmap.josm.data.osm.BBox; 31 32 import org.openstreetmap.josm.data.osm.DataSet; 32 33 import org.openstreetmap.josm.data.osm.Node; … … 230 231 } 231 232 232 233 private Node findNode(EastNorth pos) { 233 DataSet ds = MainApplication.getLayerManager().getEditDataSet(); 234 LatLon l = eastNorth2latlon(pos); 235 List<Node> nodes = ds.searchNodes(new BBox(l.lon() - 0.0000001, l.lat() - 0.0000001, 236 l.lon() + 0.0000001, l.lat() + 0.0000001)); 237 Node bestnode = null; 238 double mindist = 0.0003; 239 for (Node n : nodes) { 240 double dist = n.getCoor().distanceSq(l); 241 if (dist < mindist && n.isUsable()) { 242 bestnode = n; 243 mindist = dist; 244 } 245 } 246 return bestnode; 234 MapView mv = MainApplication.getMap().mapView; 235 return mv.getNearestNode(mv.getPoint(pos), OsmPrimitive::isSelectable); 247 236 } 248 237 249 238 /** … … 403 392 404 393 if (snap) { 405 394 // calculate BBox which is slightly larger than the new building 406 BBox searchBox = new BBox();407 final double maxDist = 0.001;408 395 List<Node> wayNodes = w.getNodes(); 396 // find the ways which might be snapped to the new building 397 Set<Way> others = new LinkedHashSet<>(); 398 MapView mv = MainApplication.getMap().mapView; 409 399 for (Node n : nodes) { 410 LatLon l = eastNorth2latlon(n.getEastNorth());411 searchBox.add(new BBox(l.lon() - 0.0000001, l.lat() - 0.0000001,412 l.lon() + 0.0000001, l.lat() + 0.0000001));400 Way w2 = mv.getNearestWay(mv.getPoint(n), OsmPrimitive::isSelectable); 401 if (w2 != null && w2.get("building") != null) 402 others.add(w2); 413 403 } 414 // find the ways which might be snapped to the new building415 List<Way> others = ds.searchWays(searchBox);416 404 // add nodes of existing buildings to the new one 417 others.removeIf(o -> o.get("building") == null || !o.isUsable());418 405 for (Way other : others) { 419 snapToWay(wayNodes, other.getNodes() , maxDist);406 snapToWay(wayNodes, other.getNodes()); 420 407 w.setNodes(wayNodes); 421 408 } 422 409 // add new nodes to existing buildings 423 410 for (Way other : others) { 424 411 List<Node> otherNodes = other.getNodes(); 425 snapToWay(otherNodes, Arrays.asList(nodes) , maxDist);412 snapToWay(otherNodes, Arrays.asList(nodes)); 426 413 if (otherNodes.size() != other.getNodesCount()) { 427 414 Way newWay = new Way(other); 428 415 newWay.setNodes(otherNodes); … … 436 423 } 437 424 438 425 /** 439 * Add all nodes in otherNodes to wayNodes that are within maxDist to the440 * segments described by wayNodes.426 * Add all nodes in otherNodes to wayNodes that are within snap distance to 427 * the segments described by wayNodes. 441 428 * 442 429 * @param wayNodes 443 430 * List of nodes that might be changed 444 431 * @param otherNodes 445 432 * other nodes 446 * @param maxDist447 * maximum distance as square of the euclidean distance between448 * way segment and node449 433 */ 450 private static void snapToWay(List<Node> wayNodes, Collection<Node> otherNodes, double maxDist) { 434 private static void snapToWay(List<Node> wayNodes, Collection<Node> otherNodes) { 435 final double tolerance = MainApplication.getMap().mapView.getDist100Pixel() * 0.01 436 * MapView.PROP_SNAP_DISTANCE.get(); 437 451 438 for (int i = 0; i < wayNodes.size(); i++) { 452 439 Node n0 = wayNodes.get(i); 453 440 Node n1 = wayNodes.get(i + 1 == wayNodes.size() ? 0 : i + 1); … … 454 441 for (Node n2 : otherNodes) { 455 442 if (n2 == n0 || n2 == n1) 456 443 continue; 457 EastNorth x = Geometry.closestPointToSegment(n0.getEastNorth(), n1.getEastNorth(), 458 n2.getEastNorth()); 459 if (x.distanceSq(n2.getEastNorth()) < maxDist) { 444 EastNorth x = Geometry.closestPointToSegment(n0.getEastNorth(), n1.getEastNorth(), n2.getEastNorth()); 445 if (x.distance(n2.getEastNorth()) < tolerance && !wayNodes.contains(n2)) { 460 446 wayNodes.add(i + 1, n2); 461 i--; // we may add multiple nodes to one segment, so repeat462 // it447 // we may add multiple nodes to one segment, so repeat it 448 i--; 463 449 break; 464 450 } 465 451 } -
src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java
28 28 import org.openstreetmap.josm.data.osm.Node; 29 29 import org.openstreetmap.josm.data.osm.OsmPrimitive; 30 30 import org.openstreetmap.josm.data.osm.Way; 31 import org.openstreetmap.josm.data.osm.WaySegment; 31 32 import org.openstreetmap.josm.data.osm.event.SelectionEventManager; 32 33 import org.openstreetmap.josm.data.preferences.NamedColorProperty; 33 34 import org.openstreetmap.josm.gui.MainApplication; … … 38 39 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 39 40 import org.openstreetmap.josm.gui.util.KeyPressReleaseListener; 40 41 import org.openstreetmap.josm.gui.util.ModifierExListener; 42 import org.openstreetmap.josm.tools.Geometry; 41 43 import org.openstreetmap.josm.tools.ImageProvider; 42 44 import org.openstreetmap.josm.tools.Logging; 43 45 import org.openstreetmap.josm.tools.Shortcut; … … 50 52 51 53 private final Cursor cursorCrosshair; 52 54 private final Cursor cursorJoinNode; 55 private final Cursor cursorJoinWay; 53 56 private Cursor currCursor; 54 57 private Cursor customCursor; 55 58 … … 71 74 72 75 cursorCrosshair = getCursor(); 73 76 cursorJoinNode = ImageProvider.getCursor("crosshair", "joinnode"); 77 cursorJoinWay = ImageProvider.getCursor("crosshair", "joinway"); 74 78 currCursor = cursorCrosshair; 75 79 } 76 80 … … 294 298 building.setBase(latlon2eastNorth(MainApplication.getMap().mapView.getLatLon(mousePos.x, mousePos.y))); 295 299 } else { 296 300 Node n = MainApplication.getMap().mapView.getNearestNode(mousePos, OsmPrimitive::isUsable); 297 if (n == null) {298 building.setBase( latlon2eastNorth(MainApplication.getMap().mapView.getLatLon(mousePos.x, mousePos.y)));301 if (n != null) { 302 building.setBase(n); 299 303 } else { 300 building.setBase(n); 304 WaySegment ws = MainApplication.getMap().mapView.getNearestWaySegment(mousePos, 305 OsmPrimitive::isSelectable); 306 if (ws != null && ws.way.get("building") != null) { 307 EastNorth p1 = ws.getFirstNode().getEastNorth(); 308 EastNorth p2 = ws.getSecondNode().getEastNorth(); 309 EastNorth enX = Geometry.closestPointToSegment(p1, p2, 310 MainApplication.getMap().mapView.getEastNorth(mousePos.x, mousePos.y)); 311 if (enX != null) { 312 building.setBase(enX); 313 } 314 } else { 315 building.setBase( 316 latlon2eastNorth(MainApplication.getMap().mapView.getLatLon(mousePos.x, mousePos.y))); 317 } 301 318 } 302 319 } 303 320 mode = Mode.Drawing; … … 384 401 if (!MainApplication.isDisplayingMapView()) 385 402 return; 386 403 Node n = null; 387 if (!ctrl) 388 n = MainApplication.getMap().mapView.getNearestNode(mousePos, OsmPrimitive::isUsable); 389 if (n != null) { 390 setCursor(cursorJoinNode); 391 } else { 392 if (customCursor != null && (!ctrl || isRectDrawing())) 393 setCursor(customCursor); 394 else 395 setCursor(getCursor()); 404 if (!ctrl) { 405 n = MainApplication.getMap().mapView.getNearestNode(mousePos, OsmPrimitive::isSelectable); 406 if (n != null) { 407 setCursor(cursorJoinNode); 408 return; 409 } else { 410 Way w = MainApplication.getMap().mapView.getNearestWay(mousePos, OsmPrimitive::isSelectable); 411 if (w != null && w.get("building") != null) { 412 setCursor(cursorJoinWay); 413 return; 414 } 415 } 396 416 } 417 if (customCursor != null && (!ctrl || isRectDrawing())) 418 setCursor(customCursor); 419 else 420 setCursor(getCursor()); 397 421 398 422 } 399 423
