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

Last change on this file since 6301 was 6301, checked in by Don-vip, 11 years ago

see #4582, see #7236 - Fix validator false positive "overlapping ways" for adjacent multipolygons

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