1 | // License: GPL. See LICENSE file for details.
|
---|
2 | package org.openstreetmap.josm.data.validation.tests;
|
---|
3 |
|
---|
4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
5 |
|
---|
6 | import java.util.ArrayList;
|
---|
7 | import java.util.List;
|
---|
8 |
|
---|
9 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
10 | import org.openstreetmap.josm.data.osm.Way;
|
---|
11 | import org.openstreetmap.josm.data.validation.Severity;
|
---|
12 | import org.openstreetmap.josm.data.validation.Test;
|
---|
13 | import org.openstreetmap.josm.data.validation.TestError;
|
---|
14 | import org.openstreetmap.josm.data.validation.util.Bag;
|
---|
15 | import org.openstreetmap.josm.gui.progress.ProgressMonitor;
|
---|
16 |
|
---|
17 | /**
|
---|
18 | * Check cyclic ways for errors
|
---|
19 | *
|
---|
20 | * @author jrreid
|
---|
21 | */
|
---|
22 | public class WronglyOrderedWays extends Test {
|
---|
23 |
|
---|
24 | protected static int WRONGLY_ORDERED_COAST = 1001;
|
---|
25 | protected static int WRONGLY_ORDERED_WATER = 1002;
|
---|
26 | protected static int WRONGLY_ORDERED_LAND = 1003;
|
---|
27 |
|
---|
28 | /** The already detected errors */
|
---|
29 | protected Bag<Way, Way> errorWays;
|
---|
30 |
|
---|
31 | /**
|
---|
32 | * Constructor
|
---|
33 | */
|
---|
34 | public WronglyOrderedWays() {
|
---|
35 | super(tr("Wrongly Ordered Ways."),
|
---|
36 | tr("This test checks the direction of water, land and coastline ways."));
|
---|
37 | }
|
---|
38 |
|
---|
39 | @Override
|
---|
40 | public void startTest(ProgressMonitor monitor) {
|
---|
41 | super.startTest(monitor);
|
---|
42 | errorWays = new Bag<Way, Way>();
|
---|
43 | }
|
---|
44 |
|
---|
45 | @Override
|
---|
46 | public void endTest() {
|
---|
47 | errorWays = null;
|
---|
48 | super.endTest();
|
---|
49 | }
|
---|
50 |
|
---|
51 | @Override
|
---|
52 | public void visit(Way w) {
|
---|
53 | String errortype = "";
|
---|
54 | int type;
|
---|
55 |
|
---|
56 | if (!w.isUsable())
|
---|
57 | return;
|
---|
58 | if (w.getNodesCount() <= 0)
|
---|
59 | return;
|
---|
60 |
|
---|
61 | String natural = w.get("natural");
|
---|
62 | if (natural == null)
|
---|
63 | return;
|
---|
64 |
|
---|
65 | if (natural.equals("coastline")) {
|
---|
66 | errortype = tr("Reversed coastline: land not on left side");
|
---|
67 | type= WRONGLY_ORDERED_COAST;
|
---|
68 | } else if (natural.equals("water")) {
|
---|
69 | errortype = tr("Reversed water: land not on left side");
|
---|
70 | type= WRONGLY_ORDERED_WATER;
|
---|
71 | } else if (natural.equals("land")) {
|
---|
72 | errortype = tr("Reversed land: land not on left side");
|
---|
73 | type= WRONGLY_ORDERED_LAND;
|
---|
74 | } else
|
---|
75 | return;
|
---|
76 |
|
---|
77 | /**
|
---|
78 | * Test the directionality of the way
|
---|
79 | *
|
---|
80 | * Assuming a closed non-looping way, compute twice the area
|
---|
81 | * of the polygon using the formula 2*a = sum (Xn * Yn+1 - Xn+1 * Yn)
|
---|
82 | * If the area is negative the way is ordered in a clockwise direction
|
---|
83 | *
|
---|
84 | */
|
---|
85 | if(w.getNode(0) == w.getNode(w.getNodesCount()-1)) {
|
---|
86 | double area2 = 0;
|
---|
87 |
|
---|
88 | for (int node = 1; node < w.getNodesCount(); node++) {
|
---|
89 | area2 += (w.getNode(node-1).getCoor().lon() * w.getNode(node).getCoor().lat()
|
---|
90 | - w.getNode(node).getCoor().lon() * w.getNode(node-1).getCoor().lat());
|
---|
91 | }
|
---|
92 |
|
---|
93 | if (((natural.equals("coastline") || natural.equals("land")) && area2 < 0.)
|
---|
94 | || (natural.equals("water") && area2 > 0.)) {
|
---|
95 | List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
|
---|
96 | primitives.add(w);
|
---|
97 | errors.add( new TestError(this, Severity.OTHER, errortype, type, primitives) );
|
---|
98 | errorWays.add(w,w);
|
---|
99 | }
|
---|
100 | }
|
---|
101 | }
|
---|
102 | }
|
---|