Ticket #5109: forward_backward.2.patch

File forward_backward.2.patch, 32.6 KB (added by PetrDlouhy, 15 years ago)

new version of the patch

  • src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableLinkedCellRenderer.java

    diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableLinkedCellRenderer.java b/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableLinkedCellRenderer.java
    index 5344a6e..6a25ec7 100644
    a b  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.gui.dialogs.relation;
    33
    4 import java.awt.BasicStroke;
    54import java.awt.Color;
    65import java.awt.Component;
    76import java.awt.Graphics;
    8 import java.awt.Graphics2D;
    97import java.awt.Image;
    108
    119import javax.swing.JTable;
    public class MemberTableLinkedCellRenderer extends MemberTableCellRenderer {  
    4139            return;
    4240
    4341        int ymax=this.getSize().height - 1;
    44         int xloop = 10;
    45         int xowloop = 0;
    46         if(value.isOnewayLoopForwardPart) xowloop = -3;
    47         if(value.isOnewayLoopBackwardPart) xowloop = 3;
    48        
     42        int xloop = 8;
    4943        int xoff = this.getSize().width / 2;
    5044        if (value.isLoop) {
    5145            xoff -= xloop / 2 - 1;
    public class MemberTableLinkedCellRenderer extends MemberTableCellRenderer {  
    5751
    5852        if (value.linkPrev) {
    5953            g.setColor(Color.black);
    60             if(value.isOnewayHead)
    61                 g.fillRect(xoff - 1, 0, 3, 1);
    62             else
    63                 g.fillRect(xoff - 1 + xowloop, 0, 3, 1);
     54            g.fillRect(xoff - 1, 0, 3, 1);
    6455            y1 = 0;
    6556        } else {
    6657            if (value.isLoop) {
    public class MemberTableLinkedCellRenderer extends MemberTableCellRenderer {  
    7263            }
    7364            else {
    7465                g.setColor(Color.red);
    75                 if(value.isOnewayHead)
    76                     g.drawRect(xoff-1, p - 3 - w, w, w);
    77                 else
    78                     g.drawRect(xoff-1 + xowloop, p - 1 - w, w, w);
     66                g.drawRect(xoff-1, p - 1 - w, w, w);
    7967                y1 = p;
    8068            }
    8169        }
    8270
    8371        if (value.linkNext) {
    8472            g.setColor(Color.black);
    85             if(value.isOnewayTail)
    86                 g.fillRect(xoff - 1, ymax, 3, 1);
    87             else
    88                 g.fillRect(xoff - 1 + xowloop, ymax, 3, 1);
     73            g.fillRect(xoff - 1, ymax, 3, 1);
    8974            y2 = ymax;
    9075        } else {
    9176            if (value.isLoop) {
    public class MemberTableLinkedCellRenderer extends MemberTableCellRenderer {  
    9883            }
    9984            else {
    10085                g.setColor(Color.red);
    101                 if(value.isOnewayTail)
    102                     g.drawRect(xoff-1, ymax - p + 3, w, w);
    103                 else
    104                     g.drawRect(xoff-1 + xowloop, ymax - p + 1, w, w);
    105 //                g.drawRect(xoff-1, ymax - p + 1, ssw, w);
     86                g.drawRect(xoff-1, ymax - p + 1, w, w);
    10687                y2 = ymax - p;
    10788            }
    10889        }
    10990
    11091        /* vertical lines */
    11192        g.setColor(Color.black);
     93        g.drawLine(xoff, y1, xoff, y2);
    11294        if (value.isLoop) {
    11395            g.drawLine(xoff+xloop, y1, xoff+xloop, y2);
    11496        }
    11597
    116         if (value.isOnewayHead) {
    117             setDotted(g);
    118             y1 = 7;
    119 
    120             int xValues [] = {xoff - xowloop + 1, xoff - xowloop + 1, xoff};
    121             int yValues [] = {ymax, y1+1, 1};
    122             g.drawPolyline(xValues, yValues, 3);
    123             unsetDotted(g);
    124             g.drawLine(xoff + xowloop, y1+1, xoff, 1);
    125         }
    126 
    127         if(value.isOnewayTail){
    128             setDotted(g);
    129             y2 = ymax - 7;
    130 
    131             int xValues [] = {xoff+1, xoff - xowloop + 1, xoff - xowloop + 1};
    132             int yValues [] = {ymax-1, y2, y1};
    133             g.drawPolyline(xValues, yValues, 3);
    134             unsetDotted(g);
    135             g.drawLine(xoff + xowloop, y2, xoff, ymax-1);
    136         }
    137 
    138         if ((value.isOnewayLoopForwardPart || value.isOnewayLoopBackwardPart) && !value.isOnewayTail && !value.isOnewayHead) {
    139             setDotted(g);
    140             g.drawLine(xoff - xowloop+1, y1, xoff - xowloop+1, y2 + 1);
    141             unsetDotted(g);
    142         }
    143 
    144         if (!value.isOnewayLoopForwardPart && !value.isOnewayLoopBackwardPart){
    145             g.drawLine(xoff, y1, xoff, y2);
    146         }
    147        
    148         g.drawLine(xoff+xowloop, y1, xoff+xowloop, y2);
    149      
    15098        /* special icons */
    15199        Image arrow = null;
    152100        switch (value.direction) {
    public class MemberTableLinkedCellRenderer extends MemberTableCellRenderer {  
    157105            arrow = arrowUp;
    158106            break;
    159107        }
    160         if (value.direction == Direction.ROUNDABOUT_LEFT) {
     108        if ((arrow != null) && (value.linkPrev || value.linkNext)) {
     109            g.drawImage(arrow, xoff-3, (y1 + y2) / 2 - 2, null);
     110        }
     111        else if (value.direction == Direction.ROUNDABOUT_LEFT) {
    161112            g.drawImage(roundabout_left, xoff-6, 1, null);
    162113        } else if (value.direction == Direction.ROUNDABOUT_RIGHT) {
    163114            g.drawImage(roundabout_right, xoff-6, 1, null);
    164115        }
    165 
    166         if (!value.isOnewayLoopForwardPart && !value.isOnewayLoopBackwardPart &&
    167                 (arrow != null)) {
    168             g.drawImage(arrow, xoff-3, (y1 + y2) / 2 - 2, null);
    169         }
    170 
    171         if (value.isOnewayLoopBackwardPart) {
    172             if(value.isOnewayLoopForwardPart) {
    173                 if(arrow == arrowDown)
    174                     arrow = arrowUp;
    175                 else if (arrow == arrowUp)
    176                     arrow = arrowDown;
    177             }
    178         }
    179 
    180         if ((arrow != null)) {
    181             g.drawImage(arrow, xoff+xowloop-3, (y1 + y2) / 2 - 2, null);
    182         }
    183     }
    184 
    185     private void setDotted(Graphics g) {
    186         ((Graphics2D)g).setStroke(new BasicStroke(
    187               1f,
    188               BasicStroke.CAP_BUTT,
    189               BasicStroke.CAP_BUTT,
    190               5f,
    191               new float[] {1f, 2f},
    192               0f));
    193     }
    194 
    195     private void unsetDotted(Graphics g) {
    196         ((Graphics2D)g).setStroke(new BasicStroke());
    197116    }
    198117}
  • src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java

    diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java b/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java
    index b254ef3..beb01aa 100644
    a b public class MemberTableModel extends AbstractTableModel implements TableModelLi  
    5757    private CopyOnWriteArrayList<IMemberModelListener> listeners;
    5858    private OsmDataLayer layer;
    5959
    60     private final int UNCONNECTED = Integer.MIN_VALUE;
    61 
    6260    /**
    6361     * constructor
    6462     */
    public class MemberTableModel extends AbstractTableModel implements TableModelLi  
    788786        setSelectedMembers(sortedMembers);
    789787    }
    790788
    791     private Direction determineDirection(int ref_i, Direction ref_direction, int k) {
    792         return determineDirection(ref_i, ref_direction, k, false);
    793     }
    794789    /**
    795790     * Determines the direction of way k with respect to the way ref_i.
    796791     * The way ref_i is assumed to have the direction ref_direction and
    public class MemberTableModel extends AbstractTableModel implements TableModelLi  
    800795     *
    801796     * Else the direction is given as follows:
    802797     * Let the relation be a route of oneway streets, and someone travels them in the given order.
    803      * Direction is FORWARD if it is legal and BACKWARD if it is illegal to do so for the given way.
     798     * Direction is FORWARD if it is legel and BACKWARD if it is illegal to do so for the given way.
    804799     *
    805800     **/
    806     private Direction determineDirection(int ref_i, Direction ref_direction, int k, boolean reversed) {
     801    private Direction determineDirection(int ref_i,Direction ref_direction, int k) {
    807802        if (ref_i < 0 || k < 0 || ref_i >= members.size() || k >= members.size())
    808803            return NONE;
    809804        if (ref_direction == NONE)
    public class MemberTableModel extends AbstractTableModel implements TableModelLi  
    829824
    830825        switch (ref_direction) {
    831826        case FORWARD:
    832                 refNodes.add(way_ref.lastNode());
     827            refNodes.add(way_ref.lastNode());
    833828            break;
    834829        case BACKWARD:
    835                 refNodes.add(way_ref.firstNode());
     830            refNodes.add(way_ref.firstNode());
    836831            break;
    837832        case ROUNDABOUT_LEFT:
    838833        case ROUNDABOUT_RIGHT:
    public class MemberTableModel extends AbstractTableModel implements TableModelLi  
    852847                    if (n == nn)
    853848                        return roundaboutType(k);
    854849                }
    855             } else if(isOneway(m)) {
    856                 if (n == RelationNodeMap.firstOnewayNode(m) && !reversed) {
    857                     if(m.getRole().equals("backward"))
    858                         return BACKWARD;
    859                     else
    860                         return FORWARD;
    861                 }
    862                 if (n == RelationNodeMap.lastOnewayNode(m) && reversed) {
    863                     if(m.getRole().equals("backward"))
    864                         return FORWARD;
    865                     else
    866                         return BACKWARD;
    867                 }
    868850            } else {
    869851                if (n == way.firstNode())
    870852                    return FORWARD;
    public class MemberTableModel extends AbstractTableModel implements TableModelLi  
    949931     */
    950932    public void updateLinks() {
    951933        connectionType = null;
    952         List<WayConnectionType> con = new ArrayList<WayConnectionType>();
     934        ArrayList<WayConnectionType> con = new ArrayList<WayConnectionType>();
    953935
    954936        for (int i=0; i<members.size(); ++i) {
    955937            con.add(null);
    public class MemberTableModel extends AbstractTableModel implements TableModelLi  
    958940        int firstGroupIdx=0;
    959941        boolean resetFirstGoupIdx=false;
    960942
    961         int lastForwardWay = UNCONNECTED;
    962         int lastBackwardWay = UNCONNECTED;
    963         boolean onewayBeginning = false;
    964 
    965943        for (int i=0; i<members.size(); ++i) {
    966944            if (resetFirstGoupIdx) {
    967945                firstGroupIdx = i;
    public class MemberTableModel extends AbstractTableModel implements TableModelLi  
    983961            }
    984962
    985963            boolean linkPrev = (i != firstGroupIdx);
    986             boolean linkNext = false;
    987 
    988             con.set(i, new WayConnectionType(false));
    989 
    990             if(isOneway(m) || roundaboutType(i) != NONE){
    991                 if(i>0 && con.get(i-1).isOnewayTail)
    992                     con.get(i).isOnewayHead = true;
    993                 if(lastBackwardWay == UNCONNECTED && lastForwardWay == UNCONNECTED){ //Beginning of new oneway
    994                     con.get(i).isOnewayHead = true;
    995                     lastForwardWay = i-1;
    996                     lastBackwardWay = i;
    997                     onewayBeginning = true;
    998                 }
     964            boolean linkNext;
     965            Direction dir;
     966            if (linkPrev) {
     967                dir = determineDirection(i-1, con.get(i-1).direction, i);
     968                linkNext = (determineDirection(i, dir, i+1) != NONE);
    999969            }
    1000 
    1001             Direction dir = NONE;
    1002             if (linkPrev) {     
    1003                 if(lastBackwardWay != UNCONNECTED && lastForwardWay != UNCONNECTED) {
    1004                     Direction dirFW = determineDirection(lastForwardWay, con.get(lastForwardWay).direction, i);
    1005                     Direction dirBW = NONE;
    1006                     if(onewayBeginning) {
    1007                         if(lastBackwardWay != i)
    1008                             dirBW = determineDirection(lastBackwardWay, reverse(con.get(lastBackwardWay).direction), i, true);
    1009                         if(dirBW != NONE)
    1010                             onewayBeginning = false;
    1011                     } else
    1012                         dirBW = determineDirection(lastBackwardWay, con.get(lastBackwardWay).direction, i, true);
    1013 
    1014                     if(isOneway(m) || roundaboutType(i) != NONE) {
    1015                         if(dirBW != NONE){
    1016                             dir = dirBW;
    1017                             lastBackwardWay = i;
    1018                             con.get(i).isOnewayLoopBackwardPart = true;
    1019                         }
    1020                         if(dirFW != NONE){
    1021                             dir = dirFW;
    1022                             lastForwardWay = i;
    1023                             con.get(i).isOnewayLoopForwardPart = true;
    1024                         }
    1025                         if(dirFW == NONE && dirBW == NONE) {
    1026     //                        unconnectPreviousLink(con, i, true);
    1027     //                        unconnectPreviousLink(con, i, false);
    1028                             if(i>0) con.get(i-1).linkNext = false;
    1029                             if(isOneway(m)){
    1030                                 lastForwardWay = i-1;
    1031                                 lastBackwardWay = i;
    1032                             } else {
    1033                                 lastForwardWay = UNCONNECTED;
    1034                                 lastBackwardWay = UNCONNECTED;
    1035                             }
    1036                             firstGroupIdx = i;
    1037                             linkPrev = false;
    1038                         }
    1039 
    1040                         if(dirFW != NONE && dirBW != NONE) {
    1041                             if(i+1<members.size() && determineDirection(i, dirFW, i+1) != NONE) {
    1042                                 con.get(i).isOnewayLoopBackwardPart = false;
    1043                                 dirBW = NONE;
    1044                                 dir = dirFW;
    1045                             } else {
    1046                                 con.get(i).isOnewayLoopForwardPart = false;
    1047                                 dirFW = NONE;
    1048                                 dir = dirBW;
    1049                             }
    1050 
    1051                             con.get(i).isOnewayTail = true;
    1052                         }
    1053 
    1054                         linkNext = (i+1!=members.size());
    1055                     } else {
    1056                         lastForwardWay = UNCONNECTED;
    1057                         lastBackwardWay = UNCONNECTED;
    1058                         if(dirFW == NONE | dirBW == NONE) {
    1059                             linkPrev = false;
    1060                         }
    1061                     }
    1062                 }
    1063 
    1064                 if(!isOneway(m)) {
    1065                     dir = determineDirection(i-1, con.get(i-1).direction, i);
    1066                     linkNext = (determineDirection(i, dir, i+1) != NONE);
    1067                 }                   
    1068             }
    1069            
    1070             if (!linkPrev) {
    1071                 if (isOneway(m)){
    1072                     if(m.getRole().equals("backward")) dir = BACKWARD;
    1073                     else dir = FORWARD;
    1074                     con.get(i).isOnewayLoopForwardPart = true;
    1075                     lastForwardWay = i;
    1076                 } else
     970            else {
    1077971                if (roundaboutType(i) != NONE) {
    1078972                    dir = determineDirection(i, roundaboutType(i), i+1) != NONE ? roundaboutType(i) : NONE;
    1079973                } else { /** guess the direction and see if it fits with the next member */
    public class MemberTableModel extends AbstractTableModel implements TableModelLi  
    1091985
    1092986            }
    1093987
    1094             con.get(i).direction = dir;
    1095             con.get(i).linkNext = linkNext;
    1096             con.get(i).linkPrev = linkPrev;
     988            con.set(i, new WayConnectionType(linkPrev, linkNext, dir));
    1097989
    1098990            if (! linkNext) {
    1099991                boolean loop;
    1100                 int lastGroupIdx = i;
    1101                 if (lastGroupIdx == firstGroupIdx) { //is primitive loop
    1102                     loop = determineDirection(lastGroupIdx, FORWARD, lastGroupIdx) == FORWARD;
    1103                } else {
    1104                     loop = determineDirection(lastGroupIdx, con.get(lastGroupIdx).direction, firstGroupIdx) == con.get(firstGroupIdx).direction;
     992                if (i == firstGroupIdx) {
     993                    loop = determineDirection(i, FORWARD, i) == FORWARD;
     994                } else {
     995                    loop = determineDirection(i, dir, firstGroupIdx) == con.get(firstGroupIdx).direction;
    1105996                }
    1106997                if (loop) {
    1107998                    for (int j=firstGroupIdx; j <= i; ++j) {
    public class MemberTableModel extends AbstractTableModel implements TableModelLi  
    11111002                resetFirstGoupIdx = true;
    11121003            }
    11131004        }
    1114 
    11151005        connectionType = con;
    11161006        //        for (int i=0; i<con.size(); ++i) {
    11171007        //            System.err.println(con.get(i));
    11181008        //        }
    11191009    }
    1120 
    1121 //    private static void unconnectPreviousLink(List<WayConnectionType> con, int beg, boolean backward){
    1122 //        int i = beg;
    1123 //        while(true){
    1124 //            WayConnectionType t = con.get(i--);
    1125 //            t.isOnewayOppositeConnected = false;
    1126 //            if(backward && t.isOnewayLoopBackwardPart) break;
    1127 //            if(!backward && t.isOnewayLoopForwardPart) break;
    1128 //        }
    1129 //    }
    1130 
    1131     private static Direction reverse(Direction dir){
    1132         if(dir == FORWARD) return BACKWARD;
    1133         if(dir == BACKWARD) return FORWARD;
    1134         return dir;
    1135     }
    1136 
    1137     public static boolean isOneway(RelationMember m){
    1138         return m.getRole().equals("forward") || m.getRole().equals("backward");
    1139     }
    11401010}
  • src/org/openstreetmap/josm/gui/dialogs/relation/RelationNodeMap.java

    diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/RelationNodeMap.java b/src/org/openstreetmap/josm/gui/dialogs/relation/RelationNodeMap.java
    index 1f4b388..d6e1d8d 100644
    a b package org.openstreetmap.josm.gui.dialogs.relation;  
    44import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.NONE;
    55
    66import java.util.ArrayList;
     7import java.util.Iterator;
    78import java.util.List;
    89import java.util.Map;
    9 import java.util.Set;
    1010import java.util.TreeMap;
    1111import java.util.TreeSet;
    1212
    import org.openstreetmap.josm.data.osm.Way;  
    2929 *
    3030 */
    3131public class RelationNodeMap {
    32     private class NodesWays{
    33         public Map<Node, Set<Integer>> nodes = new TreeMap<Node, Set<Integer>>();
    34         public Map<Integer, Set<Node>> ways = new TreeMap<Integer, Set<Node>>();
    35         public boolean oneWay;
    36         public NodesWays(boolean oneWay){
    37             this.oneWay = oneWay;
    38         }
    39     }
    40 
    4132    /*
    4233     * the maps. (Need TreeMap for efficiency.)
    4334     */
    44     private NodesWays map = new NodesWays(false);
    45     /*
    46      * Maps for oneways (forward/backward roles)
    47      */
    48 
    49     private NodesWays onewayMap = new NodesWays(true);
    50     private NodesWays onewayReverseMap = new NodesWays(true);
     35    private TreeMap<Node, TreeSet<Integer>> nodesMap;
     36    private TreeMap<Integer, TreeSet<Node>> waysMap;
    5137    /*
    5238     * Used to keep track of what members are done.
    5339     */
    54     private Set<Integer> remaining;
    55     private Map<Integer, Set<Node>> remainingOneway = new TreeMap<Integer, Set<Node>>();;
     40    private TreeSet<Integer> remaining;
    5641
    5742    /**
    5843     * All members that are incomplete or not a way
    5944     */
    6045    private List<Integer> notSortable = new ArrayList<Integer>();
    6146
    62     public static Node firstOnewayNode(RelationMember m){
    63         if(!m.isWay()) return null;
    64         if(m.getRole().equals("backward")) return m.getWay().lastNode();
    65         return m.getWay().firstNode();
    66     }
    67 
    68     public static Node lastOnewayNode(RelationMember m){
    69         if(!m.isWay()) return null;
    70         if(m.getRole().equals("backward")) return m.getWay().firstNode();
    71         return m.getWay().lastNode();
    72     }
    73 
    7447    RelationNodeMap(List<RelationMember> members) {
    75         map.nodes = new TreeMap<Node, Set<Integer>>();
    76         map.ways = new TreeMap<Integer, Set<Node>>();
     48        nodesMap = new TreeMap<Node, TreeSet<Integer>>();
     49        waysMap = new TreeMap<Integer, TreeSet<Node>>();
    7750
    7851        for (int i = 0; i < members.size(); ++i) {
    7952            RelationMember m = members.get(i);
    80             if (m.getMember().isIncomplete() || !m.isWay()) {
     53            if (m.getMember().isIncomplete() || !m.isWay())
     54            {
    8155                notSortable.add(i);
    82                 continue;
    8356            }
    84 
    85             Way w = m.getWay();
    86             if ((MemberTableModel.roundaboutType(w) != NONE)) {
    87                 for (Node nd : w.getNodes()) {
    88                     addPair(nd, i);
     57            else {
     58                Way w = m.getWay();
     59                if (MemberTableModel.roundaboutType(w) != NONE) {
     60                    for (Node nd : w.getNodes()) {
     61                        addPair(nd, i);
     62                    }
     63                } else {
     64                    addPair(w.firstNode(), i);
     65                    addPair(w.lastNode(), i);
    8966                }
    90             } else if(MemberTableModel.isOneway(m)) {
    91                 addNodeWayMap(firstOnewayNode(m), i);
    92                 addWayNodeMap(lastOnewayNode(m), i);
    93                 addNodeWayMapReverse(lastOnewayNode(m), i);
    94                 addWayNodeMapReverse(firstOnewayNode(m), i);
    95                 addRemainingForward(firstOnewayNode(m), i);
    96                 addRemainingForward(lastOnewayNode(m), i);
    97             } else {
    98                 addPair(w.firstNode(), i);
    99                 addPair(w.lastNode(), i);
    10067            }
    10168        }
    10269
    10370        remaining = new TreeSet<Integer>();
    104         remaining.addAll(map.ways.keySet());
     71        for (Integer k : waysMap.keySet()) {
     72            remaining.add(k);
     73        }
    10574
    10675        /*
    10776         * Clean up the maps, i.e. remove nodes from roundabouts and dead ends that
    10877         * cannot be used in future. (only for performance)
    10978         */
    110 //        Iterator<Map.Entry<Node,TreeSet<Integer>>> it = map.nodes.entrySet().iterator();
    111 //        while (it.hasNext()) {
    112 //            Map.Entry<Node,TreeSet<Integer>> nodeLinks = it.next();
    113 //
    114 //            if (nodeLinks.getValue().size() < 2) {
    115 //                if (nodeLinks.getValue().size() != 1) throw new AssertionError();
    116 //
    117 //                Integer d_way = nodeLinks.getValue().iterator().next();
    118 //                TreeSet<Node> d_way_nodes = map.ways.get(d_way);
    119 //                d_way_nodes.remove(nodeLinks.getKey());
    120 //
    121 //                it.remove();
    122 //                continue;
    123 //            }
    124 //        }
    125             }
     79        Iterator<Map.Entry<Node,TreeSet<Integer>>> it = nodesMap.entrySet().iterator();
     80        while (it.hasNext()) {
     81            Map.Entry<Node,TreeSet<Integer>> nodeLinks = it.next();
    12682
    127     private void addPair(Node n, int i) {
    128         Set<Integer> ts = map.nodes.get(n);
    129         if (ts == null) {
    130             ts = new TreeSet<Integer>();
    131             map.nodes.put(n, ts);
    132         }
    133         ts.add(i);
     83            if (nodeLinks.getValue().size() < 2) {
     84                if (nodeLinks.getValue().size() != 1) throw new AssertionError();
    13485
    135         Set<Node> ts2 = map.ways.get(i);
    136         if (ts2 == null) {
    137             ts2 = new TreeSet<Node>();
    138             map.ways.put(i, ts2);
    139         }
    140         ts2.add(n);
    141     }
     86                Integer d_way = nodeLinks.getValue().iterator().next();
     87                TreeSet<Node> d_way_nodes = waysMap.get(d_way);
     88                d_way_nodes.remove(nodeLinks.getKey());
    14289
    143     private void addNodeWayMap(Node n, int i) {
    144         Set<Integer> ts = onewayMap.nodes.get(n);
    145         if (ts == null) {
    146             ts = new TreeSet<Integer>();
    147             onewayMap.nodes.put(n, ts);
    148         }
    149         ts.add(i);
    150     }
    151 
    152     private void addWayNodeMap(Node n, int i) {
    153         Set<Node> ts2 = onewayMap.ways.get(i);
    154         if (ts2 == null) {
    155             ts2 = new TreeSet<Node>();
    156             onewayMap.ways.put(i, ts2);
     90                it.remove();
     91                continue;
     92            }
    15793        }
    158         ts2.add(n);
    15994    }
    16095
    161     private void addNodeWayMapReverse(Node n, int i) {
    162         Set<Integer> ts = onewayReverseMap.nodes.get(n);
     96    private void addPair(Node n, int i) {
     97        TreeSet<Integer> ts = nodesMap.get(n);
    16398        if (ts == null) {
    16499            ts = new TreeSet<Integer>();
    165             onewayReverseMap.nodes.put(n, ts);
     100            nodesMap.put(n, ts);
    166101        }
    167102        ts.add(i);
    168     }
    169103
    170     private void addWayNodeMapReverse(Node n, int i) {
    171         Set<Node> ts2 = onewayReverseMap.ways.get(i);
     104        TreeSet<Node> ts2 = waysMap.get(i);
    172105        if (ts2 == null) {
    173106            ts2 = new TreeSet<Node>();
    174             onewayReverseMap.ways.put(i, ts2);
     107            waysMap.put(i, ts2);
    175108        }
    176109        ts2.add(n);
    177110    }
    178111
    179     private void addRemainingForward(Node n, int i) {
    180         Set<Node> ts2 = remainingOneway.get(i);
    181         if (ts2 == null) {
    182             ts2 = new TreeSet<Node>();
    183             remainingOneway.put(i, ts2);
    184         }
    185         ts2.add(n);
    186     }
    187 
    188     Integer firstOneway = null;
    189     Node lastOnewayNode = null;
    190     Node firstCircular = null;
    191 
    192112    /**
    193113     * Return a relation member that is linked to the
    194      * member 'i', but has not been popped yet.
     114     * member 'i', but has not been popped jet.
    195115     * Return null if there is no such member left.
    196116     */
    197     public Integer popAdjacent(Integer way) {
    198         if (lastOnewayNode != null) return popBackwardOnewayPart(way);
    199         if (firstOneway != null) return popForwardOnewayPart(way);
    200 
    201         if (map.ways.containsKey(way)){
    202             for (Node n : map.ways.get(way)) {
    203                 Integer i = deleteAndGetAdjacentNode(map, n);
    204                 if(i != null) return i;
    205 
    206                 Integer j = deleteAndGetAdjacentNode(onewayMap, n);
    207                 if(j != null) {
    208                     firstOneway = j;
    209                     return j;
    210                 }
    211             }
    212         }
    213        
    214         firstOneway = way;
    215         return popForwardOnewayPart(way);
    216     }
    217 
    218     private Integer popForwardOnewayPart(Integer way) {
    219         if(onewayMap.ways.containsKey(way)) {
    220             for (Node n : onewayMap.ways.get(way)) {
    221                 Integer i = findAdjacentWay(onewayMap, n);
    222                 if(i == null) continue;
    223 
    224                 lastOnewayNode = processBackwardIfEndOfLoopReached(i);
    225                 if(lastOnewayNode != null){
    226                     return popBackwardOnewayPart(firstOneway);
    227                 }
    228 
    229                 deleteWayNode(onewayMap, i, n);
    230                 return i;
    231             }
    232         }
    233        
    234         firstOneway = null;
    235         return null;
    236     }
    237 
    238     private Node processBackwardIfEndOfLoopReached(Integer way) { //find if we didn't reach end of the loop (and process backward part)
    239         if (onewayReverseMap.ways.containsKey(way)) {
    240             for (Node n : onewayReverseMap.ways.get(way)) {
    241                 if((map.nodes.containsKey(n))
    242                         || (onewayMap.nodes.containsKey(n) && onewayMap.nodes.get(n).size() > 1)) {
    243                     return n;
    244                 }
    245                 if(firstCircular != null && firstCircular == n) {
    246                     return firstCircular;
    247                 }
    248             }
    249         }
    250         return null;
    251     }
    252    
    253     private Integer popBackwardOnewayPart(int way){
    254         if (lastOnewayNode != null) {
    255             TreeSet<Node> nodes = new TreeSet<Node>();
    256             if (onewayReverseMap.ways.containsKey(way)) nodes.addAll(onewayReverseMap.ways.get(way));
    257             if (map.ways.containsKey(way)) nodes.addAll(map.ways.get(way));
    258             for (Node n : nodes) {
    259                 if(n == lastOnewayNode) { //if oneway part ends
    260                     firstOneway = null;
    261                     lastOnewayNode = null;
    262                     Integer j = deleteAndGetAdjacentNode(map, n);
    263                     if(j != null) return j;
    264 
    265                     Integer k = deleteAndGetAdjacentNode(onewayMap, n);
    266                     if(k != null) {
    267                         firstOneway = k;
    268                         return k;
    269                     }
    270                 }
    271 
    272                 Integer j = deleteAndGetAdjacentNode(onewayReverseMap, n);
    273                 if(j != null) return j;
     117    public Integer popAdjacent(Integer i) {
     118        TreeSet<Node> nodes = waysMap.get(i);
     119        for (Node n : nodes) {
     120            TreeSet<Integer> adj = nodesMap.get(n);
     121            if (!adj.isEmpty()) {
     122                Integer j = adj.iterator().next();
     123                done(j);
     124                waysMap.get(j).remove(n);
     125                return j;
    274126            }
    275127        }
    276 
    277         firstOneway = null;
    278         lastOnewayNode = null;
    279        
    280128        return null;
    281129    }
    282130
    283131    /**
    284      * find next node in nw NodeWays structure, if the node is found delete and return it
    285      * @param nw
    286      * @param n
    287      * @return node next to n
    288      */
    289     private Integer deleteAndGetAdjacentNode(NodesWays nw, Node n){
    290         Integer j = findAdjacentWay(nw, n);
    291         if(j == null) return null;
    292         deleteWayNode(nw, j, n);
    293         return j;
    294     }
    295 
    296     private Integer findAdjacentWay(NodesWays nw, Node n) {
    297         Set<Integer> adj = nw.nodes.get(n);
    298         if (adj == null || adj.isEmpty()) return null;
    299         Integer j = adj.iterator().next();
    300         return j;
    301     }
    302 
    303     private void deleteWayNode(NodesWays nw, Integer way, Node n){
    304         if(nw.oneWay)
    305             doneOneway(way);
    306         else
    307             done(way);
    308         nw.ways.get(way).remove(n);
    309     }
    310 
    311     /**
    312132     * Returns some remaining member or null if
    313133     * every sortable member has been processed.
    314134     */
    315135    public Integer pop() {
    316         if (!remaining.isEmpty()){
    317             Integer i = remaining.iterator().next();
    318             done(i);
    319             return i;
    320         }
    321 
    322         if (remainingOneway.isEmpty()) return null;
    323         for(Integer i :remainingOneway.keySet()){ //find oneway, whic is connected to more than one way (is between two oneway loops)
    324             for(Node n : onewayReverseMap.ways.get(i)){
    325                 if(onewayReverseMap.nodes.containsKey(n) && onewayReverseMap.nodes.get(n).size() > 1) {
    326                     doneOneway(i);
    327                     firstCircular = n;
    328                     return i;
    329                 }
    330             }
    331         }
    332 
    333         Integer i = remainingOneway.keySet().iterator().next();
    334         doneOneway(i);
     136        if (remaining.isEmpty()) return null;
     137        Integer i = remaining.iterator().next();
     138        done(i);
    335139        return i;
    336140    }
    337141
    338142    /**
    339143     * This relation member has been processed.
    340      * Remove references in the map.nodes.
     144     * Remove references in the nodesMap.
    341145     */
    342     private void doneOneway(Integer i) {
    343         Set<Node> nodesForward = remainingOneway.get(i);
    344         for (Node n : nodesForward) {
    345             if(onewayMap.nodes.containsKey(n)) onewayMap.nodes.get(n).remove(i);
    346             if(onewayReverseMap.nodes.containsKey(n)) onewayReverseMap.nodes.get(n).remove(i);
    347         }
    348         remainingOneway.remove(i);
    349     }
    350 
    351146    private void done(Integer i) {
    352147        remaining.remove(i);
    353         Set<Node> nodes = map.ways.get(i);
     148        TreeSet<Node> nodes = waysMap.get(i);
    354149        for (Node n : nodes) {
    355             boolean result = map.nodes.get(n).remove(i);
     150            boolean result = nodesMap.get(n).remove(i);
    356151            if (!result) throw new AssertionError();
    357152        }
    358153    }
  • src/org/openstreetmap/josm/gui/dialogs/relation/WayConnectionType.java

    diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/WayConnectionType.java b/src/org/openstreetmap/josm/gui/dialogs/relation/WayConnectionType.java
    index 5beb882..347c722 100644
    a b public class WayConnectionType {  
    1010    private final boolean invalid;
    1111
    1212    /** True, if linked to the previous / next member.  */
    13     public boolean linkPrev;
    14     public boolean linkNext;
     13    public final boolean linkPrev;
     14    public final boolean linkNext;
    1515
    1616    /**
    1717     * direction is FORWARD if the first node of this way is connected to the previous way
    public class WayConnectionType {  
    2222     * If there is no connection to the previous or next member, then
    2323     * direction has the value NONE.
    2424     */
    25     public Direction direction;
     25    public final Direction direction;
    2626
    2727    public enum Direction {
    2828        FORWARD, BACKWARD, ROUNDABOUT_LEFT, ROUNDABOUT_RIGHT, NONE;
    public class WayConnectionType {  
    3535    /** True, if the element is part of a closed loop of ways. */
    3636    public boolean isLoop;
    3737
    38     public boolean isOnewayLoopForwardPart = false;
    39     public boolean isOnewayLoopBackwardPart = false;
    40     public boolean isOnewayHead = false;
    41     public boolean isOnewayTail = false;
    42 //    public boolean isOnewayOppositeConnected = true;
    43 
    4438    public boolean isRoundabout = false;
    4539
    4640    public WayConnectionType(boolean linkPrev, boolean linkNext, Direction direction) {
    public class WayConnectionType {  
    5145        invalid = false;
    5246    }
    5347
    54     public WayConnectionType(boolean invalid){
    55         this.invalid = invalid;
    56     }
    57 
    5848    /** construct invalid instance */
    5949    public WayConnectionType() {
    6050        this.linkPrev = false;