Changeset 5981 in josm for trunk/src/org/openstreetmap/josm


Ignore:
Timestamp:
2013-06-01T22:33:47+02:00 (11 years ago)
Author:
Don-vip
Message:

fix #8631 - Make ParallelWays more robust to self-intersecting ways

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWays.java

    r4134 r5981  
    66import java.util.Collections;
    77import java.util.HashMap;
     8import java.util.HashSet;
    89import java.util.List;
     10import java.util.Set;
    911
    1012import org.openstreetmap.josm.Main;
     
    3638        // Possible/sensible to use PrimetiveDeepCopy here?
    3739
    38         //// Make a deep copy of the ways, keeping the copied ways connected
     40        // Make a deep copy of the ways, keeping the copied ways connected
    3941        // TODO: This assumes the first/last nodes of the ways are the only possible shared nodes.
    4042        HashMap<Node, Node> splitNodeMap = new HashMap<Node, Node>(sourceWays.size());
     
    6264        sourceWays = null; // Ensure that we only use the copies from now
    6365
    64         //// Find a linear ordering of the nodes. Fail if there isn't one.
     66        // Find a linear ordering of the nodes. Fail if there isn't one.
    6567        CombineWayAction.NodeGraph nodeGraph = CombineWayAction.NodeGraph.createUndirectedGraphFromNodeWays(ways);
    66         sortedNodes = nodeGraph.buildSpanningPath();
    67         if (sortedNodes == null)
     68        List<Node> sortedNodesPath = nodeGraph.buildSpanningPath();
     69        if (sortedNodesPath == null)
    6870            throw new IllegalArgumentException("Ways must have spanning path"); // Create a dedicated exception?
     71       
     72        // Fix #8631 - Remove duplicated nodes from graph to be robust with self-intersecting ways
     73        Set<Node> removedNodes = new HashSet<Node>();
     74        sortedNodes = new ArrayList<Node>();
     75        for (int i = 0; i < sortedNodesPath.size(); i++) {
     76            Node n = sortedNodesPath.get(i);
     77            if (i < sortedNodesPath.size()-1) {
     78                if (sortedNodesPath.get(i+1).getCoor().equals(n.getCoor())) {
     79                    removedNodes.add(n);
     80                    for (Way w : ways)
     81                        w.removeNode(n);
     82                    continue;
     83                }
     84            }
     85            if (!removedNodes.contains(n)) {
     86                sortedNodes.add(n);
     87            }
     88        }
    6989
    70         //// Ugly method of ensuring that the offset isn't inverted. I'm sure there is a better and more elegant way, but I'm starting to get sleepy, so I do this for now.
     90        // Ugly method of ensuring that the offset isn't inverted. I'm sure there is a better and more elegant way, but I'm starting to get sleepy, so I do this for now.
    7191        {
    7292            Way refWay = ways.get(refWayIndex);
     
    83103        }
    84104
    85         //// Initialize the required parameters. (segment normals, etc.)
     105        // Initialize the required parameters. (segment normals, etc.)
    86106        nodeCount = sortedNodes.size();
    87107        pts = new EastNorth[nodeCount];
     
    110130     */
    111131    public void changeOffset(double d) {
    112         //// This is the core algorithm:
    113         /* 1. Calculate a parallel line, offset by 'd', to each segment in
    114          *    the path
    115          * 2. Find the intersection of lines belonging to neighboring
    116          *    segments. These become the new node positions
     132        // This is the core algorithm:
     133        /* 1. Calculate a parallel line, offset by 'd', to each segment in the path
     134         * 2. Find the intersection of lines belonging to neighboring segments. These become the new node positions
    117135         * 3. Do some special casing for closed paths
    118136         *
     
    161179    private List<Command> makeAddWayAndNodesCommandList() {
    162180        ArrayList<Command> commands = new ArrayList<Command>(sortedNodes.size() + ways.size());
    163         for (int i = 0; i < sortedNodes.size() - 1; i++) {
     181        for (int i = 0; i < sortedNodes.size() - (isClosedPath() ? 1 : 0); i++) {
    164182            commands.add(new AddCommand(sortedNodes.get(i)));
    165         }
    166         if (!isClosedPath()) {
    167             commands.add(new AddCommand(sortedNodes.get(sortedNodes.size() - 1)));
    168183        }
    169184        for (Way w : ways) {
Note: See TracChangeset for help on using the changeset viewer.