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

Last change on this file since 4806 was 4806, checked in by stoecker, 12 years ago

unify texts for validator tests, move command where it belongs

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