Changeset 34721 in osm for applications/editors


Ignore:
Timestamp:
2018-11-12T10:17:35+01:00 (6 years ago)
Author:
gerdp
Message:

fix #16948josm

  • snap to other buildings when they are very close so that the new building and the nearby buildings are connected
  • don't snap if Ctrl key is pressed
Location:
applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/Building.java

    r34572 r34721  
    1010import java.awt.geom.GeneralPath;
    1111import java.util.ArrayList;
     12import java.util.Arrays;
    1213import java.util.Collection;
    1314import java.util.Collections;
     
    3738import org.openstreetmap.josm.gui.MainApplication;
    3839import org.openstreetmap.josm.gui.MapView;
     40import org.openstreetmap.josm.tools.Geometry;
    3941
    4042class Building {
     
    354356    }
    355357
    356     public Way createRectangle() {
     358    public Way createRectangle(boolean ctrl) {
    357359        if (len == 0)
    358360            return null;
    359361        final boolean[] created = new boolean[4];
    360362        final Node[] nodes = new Node[4];
     363        final boolean snap = !ctrl; // don't snap if Ctrl is held
    361364        for (int i = 0; i < 4; i++) {
    362 
    363             Node n = findNode(en[i]);
     365            Node n = null;
     366            if (snap) {
     367                n = findNode(en[i]);
     368            }
    364369            if (n == null) {
    365370                nodes[i] = new Node(eastNorth2latlon(en[i]));
     
    397402        addAddress(w);
    398403
     404        if (snap) {
     405            // calculate BBox which is slightly larger than the new building
     406            BBox searchBox = new BBox();
     407            final double maxDist = 0.001;
     408            List<Node> wayNodes = w.getNodes();
     409            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));
     413            }
     414            // find the ways which might be snapped to the new building
     415            List<Way> others = ds.searchWays(searchBox);
     416            // add nodes of existing buildings to the new one
     417            others.removeIf(o -> o.get("building") == null || !o.isUsable());
     418            for (Way other : others) {
     419                snapToWay(wayNodes, other.getNodes(), maxDist);
     420                w.setNodes(wayNodes);
     421            }
     422            // add new nodes to existing buildings
     423            for (Way other : others) {
     424                List<Node> otherNodes = other.getNodes();
     425                snapToWay(otherNodes, Arrays.asList(nodes), maxDist);
     426                if (otherNodes.size() != other.getNodesCount()) {
     427                    Way newWay = new Way(other);
     428                    newWay.setNodes(otherNodes);
     429                    cmds.add(new ChangeCommand(other, newWay));
     430                }
     431            }
     432        }
    399433        Command c = new SequenceCommand(tr("Create building"), cmds);
    400434        UndoRedoHandler.getInstance().add(c);
    401435        return w;
     436    }
     437
     438    /**
     439     * Add all nodes in otherNodes to wayNodes that are within maxDist to the
     440     * segments described by wayNodes.
     441     *
     442     * @param wayNodes
     443     *            List of nodes that might be changed
     444     * @param otherNodes
     445     *            other nodes
     446     * @param maxDist
     447     *            maximum distance as square of the euclidean distance between
     448     *            way segment and node
     449     */
     450    private static void snapToWay(List<Node> wayNodes, Collection<Node> otherNodes, double maxDist) {
     451        for (int i = 0; i < wayNodes.size(); i++) {
     452            Node n0 = wayNodes.get(i);
     453            Node n1 = wayNodes.get(i + 1 == wayNodes.size() ? 0 : i + 1);
     454            for (Node n2 : otherNodes) {
     455                if (n2 == n0 || n2 == n1)
     456                    continue;
     457                EastNorth x = Geometry.closestPointToSegment(n0.getEastNorth(), n1.getEastNorth(),
     458                        n2.getEastNorth());
     459                if (x.distanceSq(n2.getEastNorth()) < maxDist) {
     460                    wayNodes.add(i + 1, n2);
     461                    i--; // we may add multiple nodes to one segment, so repeat
     462                         // it
     463                    break;
     464                }
     465            }
     466        }
    402467    }
    403468
  • applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java

    r34572 r34721  
    321321                w = building.createCircle();
    322322            } else {
    323                 w = building.createRectangle();
     323                w = building.createRectangle(ctrl);
    324324            }
    325325            if (w != null) {
Note: See TracChangeset for help on using the changeset viewer.