source: josm/trunk/src/org/openstreetmap/josm/data/validation/tests/CrossingWays.java@ 6386

Last change on this file since 6386 was 6381, checked in by Don-vip, 10 years ago

fix #9288 - validator: ignore railway=proposed in crossing ways

  • Property svn:eol-style set to native
File size: 9.2 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.awt.geom.Line2D;
7import java.awt.geom.Point2D;
8import java.util.ArrayList;
9import java.util.Arrays;
10import java.util.HashMap;
11import java.util.HashSet;
12import java.util.List;
13import java.util.Map;
14import java.util.Set;
15
16import org.openstreetmap.josm.data.osm.Node;
17import org.openstreetmap.josm.data.osm.Way;
18import org.openstreetmap.josm.data.osm.WaySegment;
19import org.openstreetmap.josm.data.validation.OsmValidator;
20import org.openstreetmap.josm.data.validation.Severity;
21import org.openstreetmap.josm.data.validation.Test;
22import org.openstreetmap.josm.data.validation.TestError;
23import org.openstreetmap.josm.data.validation.util.ValUtil;
24import org.openstreetmap.josm.gui.progress.ProgressMonitor;
25
26/**
27 * Tests if there are segments that crosses in the same layer
28 *
29 * @author frsantos
30 */
31public class CrossingWays extends Test {
32 protected static final int CROSSING_WAYS = 601;
33
34 /** All way segments, grouped by cells */
35 private Map<Point2D,List<ExtendedSegment>> cellSegments;
36 /** The already detected errors */
37 private Set<WaySegment> errorSegments;
38 /** The already detected ways in error */
39 private Map<List<Way>, List<WaySegment>> seenWays;
40
41 /**
42 * Constructor
43 */
44 public CrossingWays() {
45 super(tr("Crossing ways."),
46 tr("This test checks if two roads, railways, waterways or buildings crosses in the same layer, but are not connected by a node."));
47 }
48
49 @Override
50 public void startTest(ProgressMonitor monitor) {
51 super.startTest(monitor);
52 cellSegments = new HashMap<Point2D,List<ExtendedSegment>>(1000);
53 errorSegments = new HashSet<WaySegment>();
54 seenWays = new HashMap<List<Way>, List<WaySegment>>(50);
55 }
56
57 @Override
58 public void endTest() {
59 super.endTest();
60 cellSegments = null;
61 errorSegments = null;
62 seenWays = null;
63 }
64
65 @Override
66 public void visit(Way w) {
67 if(!w.isUsable())
68 return;
69
70 String natural1 = w.get("natural");
71 String landuse1 = w.get("landuse");
72 boolean isCoastline1 = "water".equals(natural1) || "coastline".equals(natural1) || "reservoir".equals(landuse1);
73 String highway1 = w.get("highway");
74 String railway1 = w.get("railway");
75 boolean isSubway1 = "subway".equals(railway1);
76 boolean isTram1 = "tram".equals(railway1);
77 boolean isBuilding = isBuilding(w);
78 String waterway1 = w.get("waterway");
79
80 if (w.get("highway") == null && w.get("waterway") == null
81 && (railway1 == null || isSubway1 || isTram1)
82 && !isCoastline1 && !isBuilding)
83 return;
84
85 String layer1 = w.get("layer");
86 if ("0".equals(layer1)) {
87 layer1 = null; //0 is default value
88 }
89
90 int nodesSize = w.getNodesCount();
91 for (int i = 0; i < nodesSize - 1; i++) {
92 WaySegment ws = new WaySegment(w, i);
93 ExtendedSegment es1 = new ExtendedSegment(ws, layer1, highway1, railway1, isCoastline1, waterway1);
94 for (List<ExtendedSegment> segments : getSegments(es1.n1, es1.n2)) {
95 for (ExtendedSegment es2 : segments) {
96 List<Way> prims;
97 List<WaySegment> highlight;
98
99 if (errorSegments.contains(ws) && errorSegments.contains(es2.ws)) {
100 continue;
101 }
102
103 String layer2 = es2.layer;
104 String highway2 = es2.highway;
105 String railway2 = es2.railway;
106 boolean isCoastline2 = es2.coastline;
107 if (layer1 == null ? layer2 != null : !layer1.equals(layer2)) {
108 continue;
109 }
110
111 if (!es1.intersects(es2) ) {
112 continue;
113 }
114 if (isSubway1 && "subway".equals(railway2)) {
115 continue;
116 }
117 if (isTram1 && "tram".equals(railway2)) {
118 continue;
119 }
120
121 if (isCoastline1 != isCoastline2) {
122 continue;
123 }
124 if (("river".equals(waterway1) && "riverbank".equals(es2.waterway))
125 || ("riverbank".equals(waterway1) && "river".equals(es2.waterway))) {
126 continue;
127 }
128
129 if ("proposed".equals(es1.highway) || "proposed".equals(highway2)
130 || "proposed".equals(es1.railway) || "proposed".equals(railway2)
131 || "abandoned".equals(es1.railway) || "abandoned".equals(railway2)) {
132 continue;
133 }
134
135 prims = Arrays.asList(es1.ws.way, es2.ws.way);
136 if ((highlight = seenWays.get(prims)) == null) {
137 highlight = new ArrayList<WaySegment>();
138 highlight.add(es1.ws);
139 highlight.add(es2.ws);
140
141 String message;
142 if (isBuilding) {
143 message = tr("Crossing buildings");
144 } else if ((es1.waterway != null && es2.waterway != null)) {
145 message = tr("Crossing waterways");
146 } else if ((es1.waterway != null && es2.highway != null)
147 || (es2.waterway != null && es1.highway != null)) {
148 message = tr("Crossing waterway/highway");
149 } else {
150 message = tr("Crossing ways");
151 }
152
153 errors.add(new TestError(this, Severity.WARNING,
154 message,
155 CROSSING_WAYS,
156 prims,
157 highlight));
158 seenWays.put(prims, highlight);
159 } else {
160 highlight.add(es1.ws);
161 highlight.add(es2.ws);
162 }
163 }
164 segments.add(es1);
165 }
166 }
167 }
168
169 /**
170 * Returns all the cells this segment crosses. Each cell contains the list
171 * of segments already processed
172 *
173 * @param n1 The first node
174 * @param n2 The second node
175 * @return A list with all the cells the segment crosses
176 */
177 public List<List<ExtendedSegment>> getSegments(Node n1, Node n2) {
178
179 List<List<ExtendedSegment>> cells = new ArrayList<List<ExtendedSegment>>();
180 for(Point2D cell : ValUtil.getSegmentCells(n1, n2, OsmValidator.griddetail)) {
181 List<ExtendedSegment> segments = cellSegments.get(cell);
182 if (segments == null) {
183 segments = new ArrayList<ExtendedSegment>();
184 cellSegments.put(cell, segments);
185 }
186 cells.add(segments);
187 }
188 return cells;
189 }
190
191 /**
192 * A way segment with some additional information
193 */
194 public static class ExtendedSegment {
195 private final Node n1, n2;
196
197 private final WaySegment ws;
198
199 /** The layer */
200 private final String layer;
201
202 /** The highway type */
203 private final String highway;
204
205 /** The railway type */
206 private final String railway;
207
208 /** The waterway type */
209 private final String waterway;
210
211 /** The coastline type */
212 private final boolean coastline;
213
214 /**
215 * Constructor
216 * @param ws The way segment
217 * @param layer The layer of the way this segment is in
218 * @param highway The highway type of the way this segment is in
219 * @param railway The railway type of the way this segment is in
220 * @param coastline The coastline flag of the way the segment is in
221 * @param waterway The waterway type of the way this segment is in
222 */
223 public ExtendedSegment(WaySegment ws, String layer, String highway, String railway, boolean coastline, String waterway) {
224 this.ws = ws;
225 this.n1 = ws.way.getNodes().get(ws.lowerIndex);
226 this.n2 = ws.way.getNodes().get(ws.lowerIndex + 1);
227 this.layer = layer;
228 this.highway = highway;
229 this.railway = railway;
230 this.coastline = coastline;
231 this.waterway = waterway;
232 }
233
234 /**
235 * Checks whether this segment crosses other segment
236 * @param s2 The other segment
237 * @return true if both segments crosses
238 */
239 public boolean intersects(ExtendedSegment s2) {
240 if (n1.equals(s2.n1) || n2.equals(s2.n2) ||
241 n1.equals(s2.n2) || n2.equals(s2.n1))
242 return false;
243
244 return Line2D.linesIntersect(
245 n1.getEastNorth().east(), n1.getEastNorth().north(),
246 n2.getEastNorth().east(), n2.getEastNorth().north(),
247 s2.n1.getEastNorth().east(), s2.n1.getEastNorth().north(),
248 s2.n2.getEastNorth().east(), s2.n2.getEastNorth().north());
249 }
250 }
251}
Note: See TracBrowser for help on using the repository browser.