Ticket #16948: 16948_buildings-v3.patch

File 16948_buildings-v3.patch, 5.0 KB (added by GerdP, 8 years ago)
  • src/org/openstreetmap/josm/plugins/buildings_tools/Building.java

     
    99import java.awt.Point;
    1010import java.awt.geom.GeneralPath;
    1111import java.util.ArrayList;
     12import java.util.Arrays;
    1213import java.util.Collection;
    1314import java.util.Collections;
    1415import java.util.LinkedList;
     
    3637import org.openstreetmap.josm.data.osm.Way;
    3738import org.openstreetmap.josm.gui.MainApplication;
    3839import org.openstreetmap.josm.gui.MapView;
     40import org.openstreetmap.josm.tools.Geometry;
    3941
    4042class Building {
    4143    private final EastNorth[] en = new EastNorth[4];
     
    353355        return w;
    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]));
    366371                created[i] = true;
     
    396401
    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;
    402436    }
    403437
     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 in
     448     */
     449    private static void snapToWay(List<Node> wayNodes, Collection<Node> otherNodes, double maxDist) {
     450        for (int i = 0; i < wayNodes.size(); i++) {
     451            Node n0 = wayNodes.get(i);
     452            Node n1 = wayNodes.get(i + 1 == wayNodes.size() ? 0 : i + 1);
     453            for (Node n2 : otherNodes) {
     454                if (n2 == n0 || n2 == n1)
     455                    continue;
     456                EastNorth x = Geometry.closestPointToSegment(n0.getEastNorth(), n1.getEastNorth(),
     457                        n2.getEastNorth());
     458                if (x.distanceSq(n2.getEastNorth()) < maxDist) {
     459                    wayNodes.add(i + 1, n2);
     460                    i--; // we may add multiple nodes to one segment, so repeat
     461                         // it
     462                    break;
     463                }
     464            }
     465        }
     466    }
     467
    404468    private void addAddress(Way w) {
    405469        if (ToolSettings.PROP_USE_ADDR_NODE.get()) {
    406470            Node addrNode = getAddressNode();
  • src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java

     
    320320            if (ToolSettings.Shape.CIRCLE.equals(ToolSettings.getShape())) {
    321321                w = building.createCircle();
    322322            } else {
    323                 w = building.createRectangle();
     323                w = building.createRectangle(ctrl);
    324324            }
    325325            if (w != null) {
    326326                if (!alt || ToolSettings.isUsingAddr())