source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationNodeMap.java@ 3218

Last change on this file since 3218 was 3095, checked in by jttt, 14 years ago

Changes in multipolygon handling (see #4661), cosmetics

  • Property svn:eol-style set to native
File size: 4.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation;
3
4import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.NONE;
5
6import java.util.ArrayList;
7import java.util.Iterator;
8import java.util.List;
9import java.util.Map;
10import java.util.TreeMap;
11import java.util.TreeSet;
12
13import org.openstreetmap.josm.data.osm.Node;
14import org.openstreetmap.josm.data.osm.RelationMember;
15import org.openstreetmap.josm.data.osm.Way;
16
17/**
18 * Auxiliary class for relation sorting.
19 *
20 * Constructs two mappings: One that maps each way to its nodes and the inverse mapping that
21 * maps each node to all ways that have this node.
22 * After construction both maps are consistent, but later on objects that are no longer needed
23 * are removed from the value sets.
24 * However the corresponding keys are not deleted even if they map to an empty set.
25 * Note that normal ways have 2 nodes (beginning and end) but roundabouts can have less or more
26 * (that are shared by other members).
27 *
28 * @author Christiaan Welvaart <cjw@time4t.net>
29 *
30 */
31public class RelationNodeMap {
32 /*
33 * the maps. (Need TreeMap for efficiency.)
34 */
35 private TreeMap<Node, TreeSet<Integer>> nodesMap;
36 private TreeMap<Integer, TreeSet<Node>> waysMap;
37 /*
38 * Used to keep track of what members are done.
39 */
40 private TreeSet<Integer> remaining;
41
42 /**
43 * All members that are incomplete or not a way
44 */
45 private List<Integer> notSortable = new ArrayList<Integer>();
46
47 RelationNodeMap(List<RelationMember> members) {
48 nodesMap = new TreeMap<Node, TreeSet<Integer>>();
49 waysMap = new TreeMap<Integer, TreeSet<Node>>();
50
51 for (int i = 0; i < members.size(); ++i) {
52 RelationMember m = members.get(i);
53 if (m.getMember().isIncomplete() || !m.isWay())
54 {
55 notSortable.add(i);
56 }
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);
66 }
67 }
68 }
69
70 remaining = new TreeSet<Integer>();
71 for (Integer k : waysMap.keySet()) {
72 remaining.add(k);
73 }
74
75 /*
76 * Clean up the maps, i.e. remove nodes from roundabouts and dead ends that
77 * cannot be used in future. (only for performance)
78 */
79 Iterator<Map.Entry<Node,TreeSet<Integer>>> it = nodesMap.entrySet().iterator();
80 while (it.hasNext()) {
81 Map.Entry<Node,TreeSet<Integer>> nodeLinks = it.next();
82
83 if (nodeLinks.getValue().size() < 2) {
84 if (nodeLinks.getValue().size() != 1) throw new AssertionError();
85
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());
89
90 it.remove();
91 continue;
92 }
93 }
94 }
95
96 private void addPair(Node n, int i) {
97 TreeSet<Integer> ts = nodesMap.get(n);
98 if (ts == null) {
99 ts = new TreeSet<Integer>();
100 nodesMap.put(n, ts);
101 }
102 ts.add(i);
103
104 TreeSet<Node> ts2 = waysMap.get(i);
105 if (ts2 == null) {
106 ts2 = new TreeSet<Node>();
107 waysMap.put(i, ts2);
108 }
109 ts2.add(n);
110 }
111
112 /**
113 * Return a relation member that is linked to the
114 * member 'i', but has not been popped jet.
115 * Return null if there is no such member left.
116 */
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;
126 }
127 }
128 return null;
129 }
130
131 /**
132 * Returns some remaining member or null if
133 * every sortable member has been processed.
134 */
135 public Integer pop() {
136 if (remaining.isEmpty()) return null;
137 Integer i = remaining.iterator().next();
138 done(i);
139 return i;
140 }
141
142 /**
143 * This relation member has been processed.
144 * Remove references in the nodesMap.
145 */
146 private void done(Integer i) {
147 remaining.remove(i);
148 TreeSet<Node> nodes = waysMap.get(i);
149 for (Node n : nodes) {
150 boolean result = nodesMap.get(n).remove(i);
151 if (!result) throw new AssertionError();
152 }
153 }
154
155 public List<Integer> getNotSortableMembers() {
156 return notSortable;
157 }
158}
Note: See TracBrowser for help on using the repository browser.