source: josm/trunk/src/org/openstreetmap/josm/data/validation/tests/Coastlines.java@ 7489

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

see #8465 - use diamond operator where applicable

  • Property svn:eol-style set to native
File size: 7.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.awt.geom.Area;
7import java.util.ArrayList;
8import java.util.Collection;
9import java.util.Collections;
10import java.util.Iterator;
11import java.util.LinkedList;
12import java.util.List;
13
14import org.openstreetmap.josm.Main;
15import org.openstreetmap.josm.command.ChangeCommand;
16import org.openstreetmap.josm.command.Command;
17import org.openstreetmap.josm.data.osm.Node;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.data.osm.Way;
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.gui.layer.OsmDataLayer;
24import org.openstreetmap.josm.gui.progress.ProgressMonitor;
25
26/**
27 * Check coastlines for errors
28 *
29 * @author frsantos
30 * @author Teemu Koskinen
31 */
32public class Coastlines extends Test {
33
34 protected static final int UNORDERED_COASTLINE = 901;
35 protected static final int REVERSED_COASTLINE = 902;
36 protected static final int UNCONNECTED_COASTLINE = 903;
37
38 private List<Way> coastlines;
39
40 private Area downloadedArea = null;
41
42 /**
43 * Constructor
44 */
45 public Coastlines() {
46 super(tr("Coastlines"),
47 tr("This test checks that coastlines are correct."));
48 }
49
50 @Override
51 public void startTest(ProgressMonitor monitor) {
52
53 super.startTest(monitor);
54
55 OsmDataLayer layer = Main.main.getEditLayer();
56
57 if (layer != null) {
58 downloadedArea = layer.data.getDataSourceArea();
59 }
60
61 coastlines = new LinkedList<>();
62 }
63
64 @Override
65 public void endTest() {
66 for (Way c1 : coastlines) {
67 Node head = c1.firstNode();
68 Node tail = c1.lastNode();
69
70 if (c1.getNodesCount() == 0 || head.equals(tail)) {
71 continue;
72 }
73
74 int headWays = 0;
75 int tailWays = 0;
76 boolean headReversed = false;
77 boolean tailReversed = false;
78 boolean headUnordered = false;
79 boolean tailUnordered = false;
80 Way next = null;
81 Way prev = null;
82
83 for (Way c2 : coastlines) {
84 if (c1 == c2) {
85 continue;
86 }
87
88 if (c2.containsNode(head)) {
89 headWays++;
90 next = c2;
91
92 if (head.equals(c2.firstNode())) {
93 headReversed = true;
94 } else if (!head.equals(c2.lastNode())) {
95 headUnordered = true;
96 }
97 }
98
99 if (c2.containsNode(tail)) {
100 tailWays++;
101 prev = c2;
102
103 if (tail.equals(c2.lastNode())) {
104 tailReversed = true;
105 } else if (!tail.equals(c2.firstNode())) {
106 tailUnordered = true;
107 }
108 }
109 }
110
111 // To avoid false positives on upload (only modified primitives
112 // are visited), we have to check possible connection to ways
113 // that are not in the set of validated primitives.
114 if (headWays == 0) {
115 Collection<OsmPrimitive> refs = head.getReferrers();
116 for (OsmPrimitive ref : refs) {
117 if (ref != c1 && isCoastline(ref)) {
118 // ref cannot be in <code>coastlines</code>, otherwise we would
119 // have picked it up already
120 headWays++;
121 next = (Way) ref;
122
123 if (head.equals(next.firstNode())) {
124 headReversed = true;
125 } else if (!head.equals(next.lastNode())) {
126 headUnordered = true;
127 }
128 }
129 }
130 }
131 if (tailWays == 0) {
132 Collection<OsmPrimitive> refs = tail.getReferrers();
133 for (OsmPrimitive ref : refs) {
134 if (ref != c1 && isCoastline(ref)) {
135 tailWays++;
136 prev = (Way) ref;
137
138 if (tail.equals(prev.lastNode())) {
139 tailReversed = true;
140 } else if (!tail.equals(prev.firstNode())) {
141 tailUnordered = true;
142 }
143 }
144 }
145 }
146
147 List<OsmPrimitive> primitives = new ArrayList<>();
148 primitives.add(c1);
149
150 if (headWays == 0 || tailWays == 0) {
151 List<OsmPrimitive> highlight = new ArrayList<>();
152
153 if (headWays == 0 && head.getCoor().isIn(downloadedArea)) {
154 highlight.add(head);
155 }
156 if (tailWays == 0 && tail.getCoor().isIn(downloadedArea)) {
157 highlight.add(tail);
158 }
159
160 if (!highlight.isEmpty()) {
161 errors.add(new TestError(this, Severity.ERROR, tr("Unconnected coastline"),
162 UNCONNECTED_COASTLINE, primitives, highlight));
163 }
164 }
165
166 boolean unordered = false;
167 boolean reversed = headWays == 1 && headReversed && tailWays == 1 && tailReversed;
168
169 if (headWays > 1 || tailWays > 1) {
170 unordered = true;
171 } else if (headUnordered || tailUnordered) {
172 unordered = true;
173 } else if (reversed && next == prev) {
174 unordered = true;
175 } else if ((headReversed || tailReversed) && headReversed != tailReversed) {
176 unordered = true;
177 }
178
179 if (unordered) {
180 List<OsmPrimitive> highlight = new ArrayList<>();
181
182 if (headWays > 1 || headUnordered || headReversed || reversed) {
183 highlight.add(head);
184 }
185 if (tailWays > 1 || tailUnordered || tailReversed || reversed) {
186 highlight.add(tail);
187 }
188
189 errors.add(new TestError(this, Severity.ERROR, tr("Unordered coastline"),
190 UNORDERED_COASTLINE, primitives, highlight));
191 }
192 else if (reversed) {
193 errors.add(new TestError(this, Severity.ERROR, tr("Reversed coastline"),
194 REVERSED_COASTLINE, primitives));
195 }
196 }
197
198 coastlines = null;
199 downloadedArea = null;
200
201 super.endTest();
202 }
203
204 @Override
205 public void visit(Way way) {
206 if (!way.isUsable())
207 return;
208
209 if (isCoastline(way)) {
210 coastlines.add(way);
211 }
212 }
213
214 private static boolean isCoastline(OsmPrimitive osm) {
215 return osm instanceof Way && "coastline".equals(osm.get("natural"));
216 }
217
218 @Override
219 public Command fixError(TestError testError) {
220 if (isFixable(testError)) {
221 // primitives list can be empty if all primitives have been purged
222 Iterator<? extends OsmPrimitive> it = testError.getPrimitives().iterator();
223 if (it.hasNext()) {
224 Way way = (Way) it.next();
225 Way newWay = new Way(way);
226
227 List<Node> nodesCopy = newWay.getNodes();
228 Collections.reverse(nodesCopy);
229 newWay.setNodes(nodesCopy);
230
231 return new ChangeCommand(way, newWay);
232 }
233 }
234 return null;
235 }
236
237 @Override
238 public boolean isFixable(TestError testError) {
239 if (testError.getTester() instanceof Coastlines)
240 return (testError.getCode() == REVERSED_COASTLINE);
241
242 return false;
243 }
244}
Note: See TracBrowser for help on using the repository browser.