source: josm/trunk/src/org/openstreetmap/josm/data/validation/tests/OverlappingWays.java@ 3775

Last change on this file since 3775 was 3674, checked in by bastiK, 13 years ago

Replace Bag by MultiMap.
Both collections are quite similar, but there is a technical difference: Bag is backed by an ArrayList and MultiMap by a LinkedHashSet. So with a Bag you could map a key multiple times to a certain value. I haven't found any usage where this behaviour is required or intended.
Also there could be a certain performance drawback with LinkedHashSet compared to ArrayList. However in the typical validator use case the value collection represents duplicate or crossing ways, so the number of elements is usually 1 or 2 and mostly smaller than the initial capacity (LHS=16, AL=10). (But I could have overlooked some use cases.)

  • Property svn:eol-style set to native
File size: 5.8 KB
Line 
1// License: GPL. See LICENSE file for details.
2package org.openstreetmap.josm.data.validation.tests;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.HashMap;
9import java.util.LinkedHashSet;
10import java.util.List;
11import java.util.Map;
12
13import org.openstreetmap.josm.data.osm.Node;
14import org.openstreetmap.josm.data.osm.OsmPrimitive;
15import org.openstreetmap.josm.data.osm.OsmUtils;
16import org.openstreetmap.josm.data.osm.Way;
17import org.openstreetmap.josm.data.osm.WaySegment;
18import org.openstreetmap.josm.data.validation.Severity;
19import org.openstreetmap.josm.data.validation.Test;
20import org.openstreetmap.josm.data.validation.TestError;
21import org.openstreetmap.josm.gui.progress.ProgressMonitor;
22import org.openstreetmap.josm.tools.MultiMap;
23import org.openstreetmap.josm.tools.Pair;
24
25/**
26 * Tests if there are overlapping ways
27 *
28 * @author frsantos
29 */
30public class OverlappingWays extends Test {
31
32 /** Bag of all way segments */
33 MultiMap<Pair<Node,Node>, WaySegment> nodePairs;
34
35 protected static int OVERLAPPING_HIGHWAY = 101;
36 protected static int OVERLAPPING_RAILWAY = 102;
37 protected static int OVERLAPPING_WAY = 103;
38 protected static int OVERLAPPING_HIGHWAY_AREA = 111;
39 protected static int OVERLAPPING_RAILWAY_AREA = 112;
40 protected static int OVERLAPPING_WAY_AREA = 113;
41 protected static int OVERLAPPING_AREA = 120;
42
43 /** Constructor */
44 public OverlappingWays() {
45 super(tr("Overlapping ways."),
46 tr("This test checks that a connection between two nodes "
47 + "is not used by more than one way."));
48 }
49
50 @Override
51 public void startTest(ProgressMonitor monitor) {
52 super.startTest(monitor);
53 nodePairs = new MultiMap<Pair<Node,Node>, WaySegment>(1000);
54 }
55
56 @Override
57 public void endTest() {
58 Map<List<Way>, LinkedHashSet<WaySegment>> ways_seen = new HashMap<List<Way>, LinkedHashSet<WaySegment>>(500);
59
60 for (LinkedHashSet<WaySegment> duplicated : nodePairs.values()) {
61 int ways = duplicated.size();
62
63 if (ways > 1) {
64 List<OsmPrimitive> prims = new ArrayList<OsmPrimitive>();
65 List<Way> current_ways = new ArrayList<Way>();
66 Collection<WaySegment> highlight;
67 int highway = 0;
68 int railway = 0;
69 int area = 0;
70
71 for (WaySegment ws : duplicated) {
72 if (ws.way.get("highway") != null) {
73 highway++;
74 } else if (ws.way.get("railway") != null) {
75 railway++;
76 }
77 Boolean ar = OsmUtils.getOsmBoolean(ws.way.get("area"));
78 if (ar != null && ar) {
79 area++;
80 }
81 if (ws.way.get("landuse") != null
82 || ws.way.get("natural") != null
83 || ws.way.get("amenity") != null
84 || ws.way.get("leisure") != null
85 || ws.way.get("building") != null) {
86 area++;
87 ways--;
88 }
89
90 prims.add(ws.way);
91 current_ways.add(ws.way);
92 }
93 /* These ways not seen before
94 * If two or more of the overlapping ways are
95 * highways or railways mark a separate error
96 */
97 if ((highlight = ways_seen.get(current_ways)) == null) {
98 String errortype;
99 int type;
100
101 if (area > 0) {
102 if (ways == 0 || duplicated.size() == area) {
103 errortype = tr("Overlapping areas");
104 type = OVERLAPPING_AREA;
105 } else if (highway == ways) {
106 errortype = tr("Overlapping highways (with area)");
107 type = OVERLAPPING_HIGHWAY_AREA;
108 } else if (railway == ways) {
109 errortype = tr("Overlapping railways (with area)");
110 type = OVERLAPPING_RAILWAY_AREA;
111 } else {
112 errortype = tr("Overlapping ways (with area)");
113 type = OVERLAPPING_WAY_AREA;
114 }
115 }
116 else if (highway == ways) {
117 errortype = tr("Overlapping highways");
118 type = OVERLAPPING_HIGHWAY;
119 } else if (railway == ways) {
120 errortype = tr("Overlapping railways");
121 type = OVERLAPPING_RAILWAY;
122 } else {
123 errortype = tr("Overlapping ways");
124 type = OVERLAPPING_WAY;
125 }
126
127 errors.add(new TestError(this,
128 type < OVERLAPPING_HIGHWAY_AREA ? Severity.WARNING : Severity.OTHER,
129 tr(errortype), type, prims, duplicated));
130 ways_seen.put(current_ways, duplicated);
131 } else { /* way seen, mark highlight layer only */
132 for (WaySegment ws : duplicated) {
133 highlight.add(ws);
134 }
135 }
136 }
137 }
138 super.endTest();
139 nodePairs = null;
140 }
141
142 @Override
143 public void visit(Way w) {
144 Node lastN = null;
145 int i = -2;
146 for (Node n : w.getNodes()) {
147 i++;
148 if (lastN == null) {
149 lastN = n;
150 continue;
151 }
152 nodePairs.put(Pair.sort(new Pair<Node,Node>(lastN, n)),
153 new WaySegment(w, i));
154 lastN = n;
155 }
156 }
157}
Note: See TracBrowser for help on using the repository browser.