Ticket #16948: 16948_buildings-v1.patch

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

     
    3434import org.openstreetmap.josm.data.osm.Relation;
    3535import org.openstreetmap.josm.data.osm.RelationMember;
    3636import org.openstreetmap.josm.data.osm.Way;
     37import org.openstreetmap.josm.data.osm.WaySegment;
    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];
     
    244246        return bestnode;
    245247    }
    246248
     249    private WaySegment findSnapWay(EastNorth pos) {
     250        MapView mapView = MainApplication.getMap().mapView;
     251        List<WaySegment> wss = mapView.getNearestWaySegments(mapView.getPoint(pos), OsmPrimitive::isSelectable);
     252        double minDist = 0.0001;
     253
     254        WaySegment wsBest = null;
     255        for (WaySegment ws : wss) {
     256            EastNorth x = Geometry.closestPointToSegment(ws.getFirstNode().getEastNorth(),
     257                    ws.getSecondNode().getEastNorth(), pos);
     258            double dist = x.distanceSq(pos);
     259            if (dist < minDist) {
     260                minDist = dist;
     261                wsBest = ws;
     262            }
     263        }
     264        return wsBest;
     265    }
     266
    247267    /**
    248268     * Returns a node with address tags under the building.
    249269     *
     
    358378            return null;
    359379        final boolean[] created = new boolean[4];
    360380        final Node[] nodes = new Node[4];
     381        WaySegment snapWaySegment = null;
     382        Node snapNode = null;
    361383        for (int i = 0; i < 4; i++) {
    362384
    363385            Node n = findNode(en[i]);
    364386            if (n == null) {
    365387                nodes[i] = new Node(eastNorth2latlon(en[i]));
     388                if (snapWaySegment == null) {
     389                    snapWaySegment = findSnapWay(en[i]);
     390                    if (snapWaySegment != null) {
     391                        snapNode = nodes[i];
     392                    }
     393                }
    366394                created[i] = true;
    367395            } else {
    368396                nodes[i] = n;
     
    386414            w.addNode(nodes[1]);
    387415        }
    388416        w.addNode(nodes[0]);
     417
     418        if (!created[0]) {
     419            // first node was snapped, check if we have to snap to other nodes
     420            List<Node> wayNodes = w.getNodes();
     421            List<OsmPrimitive> refs = nodes[0].getReferrers();
     422            final double maxDist = 0.001;
     423            for (OsmPrimitive ref : refs) {
     424                if (ref instanceof Way && ref.hasKey("building")) {
     425                    Way other = (Way) ref;
     426                    for (int i = 0; i < wayNodes.size(); i++) {
     427                        Node n0 = wayNodes.get(i);
     428                        Node n1 = wayNodes.get(i + 1 == wayNodes.size() ? 0 : i + 1);
     429
     430                        for (Node n2 : other.getNodes()) {
     431                            if (n2 == n0 || n2 == n1)
     432                                continue;
     433                            EastNorth x = Geometry.closestPointToSegment(n0.getEastNorth(), n1.getEastNorth(),
     434                                    n2.getEastNorth());
     435                            if (x.distanceSq(n2.getEastNorth()) < maxDist) {
     436                                wayNodes.add(i + 1, n2);
     437                            }
     438                        }
     439                        if (wayNodes.size() > 5)
     440                            break;
     441                    }
     442                }
     443            }
     444            w.setNodes(wayNodes);
     445        }
     446
    389447        DataSet ds = MainApplication.getLayerManager().getEditDataSet();
    390448        Collection<Command> cmds = new LinkedList<>();
    391449        for (int i = 0; i < 4; i++) {
     
    396454
    397455        addAddress(w);
    398456
     457        if (!created[0]) {
     458            if (snapWaySegment != null && snapNode != null) {
     459                Way newWay = new Way(snapWaySegment.way);
     460                List<Node> nodesCopy = snapWaySegment.way.getNodes();
     461                nodesCopy.add(snapWaySegment.lowerIndex + 1, snapNode);
     462                newWay.setNodes(nodesCopy);
     463                cmds.add(new ChangeCommand(snapWaySegment.way, newWay));
     464            }
     465        }
    399466        Command c = new SequenceCommand(tr("Create building"), cmds);
    400467        UndoRedoHandler.getInstance().add(c);
    401468        return w;