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

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

Sonar/Findbugs - fix various problems, javadoc

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.util.ArrayList;
7import java.util.Arrays;
8import java.util.Collection;
9import java.util.HashMap;
10import java.util.List;
11import java.util.Map;
12
13import org.openstreetmap.josm.Main;
14import org.openstreetmap.josm.command.ChangePropertyCommand;
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.Relation;
19import org.openstreetmap.josm.data.osm.Way;
20import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon;
21import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.JoinedWay;
22import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache;
23import org.openstreetmap.josm.data.validation.Severity;
24import org.openstreetmap.josm.data.validation.Test;
25import org.openstreetmap.josm.data.validation.TestError;
26import org.openstreetmap.josm.tools.Geometry;
27
28/**
29 * Checks for nodes in power lines/minor_lines that do not have a power=tower/pole tag.<br/>
30 * See #7812 for discussions about this test.
31 */
32public class PowerLines extends Test {
33
34 protected static final int POWER_LINES = 2501;
35
36 /** Values for {@code power} key interpreted as power lines */
37 public static final Collection<String> POWER_LINE_TAGS = Arrays.asList("line", "minor_line");
38 /** Values for {@code power} key interpreted as power towers */
39 public static final Collection<String> POWER_TOWER_TAGS = Arrays.asList("tower", "pole");
40 /** Values for {@code power} key interpreted as power stations */
41 public static final Collection<String> POWER_STATION_TAGS = Arrays.asList("station", "sub_station", "plant", "generator");
42 /** Values for {@code power} key interpreted as allowed power items */
43 public static final Collection<String> POWER_ALLOWED_TAGS = Arrays.asList("switch", "transformer", "busbar", "generator");
44
45 private final Map<Way, String> towerPoleTagMap = new HashMap<Way, String>();
46
47 private final List<PowerLineError> potentialErrors = new ArrayList<PowerLineError>();
48
49 private final List<OsmPrimitive> powerStations = new ArrayList<OsmPrimitive>();
50
51 /**
52 * Constructs a new {@code PowerLines} test.
53 */
54 public PowerLines() {
55 super(tr("Power lines"), tr("Checks for nodes in power lines that do not have a power=tower/pole tag."));
56 }
57
58 @Override
59 public void visit(Way w) {
60 if (w.isUsable()) {
61 if (isPowerLine(w)) {
62 String fixValue = null;
63 boolean erroneous = false;
64 boolean canFix = false;
65 for (Node n : w.getNodes()) {
66 if (!isPowerTower(n)) {
67 if (!isPowerAllowed(n)) {
68 potentialErrors.add(new PowerLineError(n, w));
69 erroneous = true;
70 }
71 } else if (fixValue == null) {
72 // First tower/pole tag found, remember it
73 fixValue = n.get("power");
74 canFix = true;
75 } else if (!fixValue.equals(n.get("power"))) {
76 // The power line contains both "tower" and "pole" -> cannot fix this error
77 canFix = false;
78 }
79 }
80 if (erroneous && canFix) {
81 towerPoleTagMap.put(w, fixValue);
82 }
83 } else if (w.isClosed() && isPowerStation(w)) {
84 powerStations.add(w);
85 }
86 }
87 }
88
89 @Override
90 public void visit(Relation r) {
91 if (r.isMultipolygon() && isPowerStation(r)) {
92 powerStations.add(r);
93 }
94 }
95
96 @Override
97 public void endTest() {
98 for (PowerLineError e : potentialErrors) {
99 if (!isInPowerStation(e.getNode())) {
100 errors.add(e);
101 }
102 }
103 super.endTest();
104 }
105
106 protected final boolean isInPowerStation(Node n) {
107 for (OsmPrimitive station : powerStations) {
108 List<List<Node>> nodesLists = new ArrayList<List<Node>>();
109 if (station instanceof Way) {
110 nodesLists.add(((Way)station).getNodes());
111 } else if (station instanceof Relation) {
112 Multipolygon polygon = MultipolygonCache.getInstance().get(Main.map.mapView, (Relation) station);
113 if (polygon != null) {
114 for (JoinedWay outer : Multipolygon.joinWays(polygon.getOuterWays())) {
115 nodesLists.add(outer.getNodes());
116 }
117 }
118 }
119 for (List<Node> nodes : nodesLists) {
120 if (Geometry.nodeInsidePolygon(n, nodes)) {
121 return true;
122 }
123 }
124 }
125 return false;
126 }
127
128 @Override
129 public Command fixError(TestError testError) {
130 if (testError instanceof PowerLineError && isFixable(testError)) {
131 return new ChangePropertyCommand(
132 testError.getPrimitives().iterator().next(),
133 "power", towerPoleTagMap.get(((PowerLineError)testError).line));
134 }
135 return null;
136 }
137
138 @Override
139 public boolean isFixable(TestError testError) {
140 return testError instanceof PowerLineError && towerPoleTagMap.containsKey(((PowerLineError)testError).line);
141 }
142
143 /**
144 * Determines if the specified way denotes a power line.
145 * @param w The way to be tested
146 * @return {@code true} if power key is set and equal to line/minor_line
147 */
148 protected static final boolean isPowerLine(Way w) {
149 return isPowerIn(w, POWER_LINE_TAGS);
150 }
151
152 /**
153 * Determines if the specified primitive denotes a power station.
154 * @param p The primitive to be tested
155 * @return {@code true} if power key is set and equal to station/sub_station/plant
156 */
157 protected static final boolean isPowerStation(OsmPrimitive p) {
158 return isPowerIn(p, POWER_STATION_TAGS);
159 }
160
161 /**
162 * Determines if the specified node denotes a power tower/pole.
163 * @param n The node to be tested
164 * @return {@code true} if power key is set and equal to tower/pole
165 */
166 protected static final boolean isPowerTower(Node n) {
167 return isPowerIn(n, POWER_TOWER_TAGS);
168 }
169
170 /**
171 * Determines if the specified node denotes a power infrastructure allowed on a power line.
172 * @param n The node to be tested
173 * @return True if power key is set and equal to switch/tranformer/busbar/generator
174 */
175 protected static final boolean isPowerAllowed(Node n) {
176 return isPowerIn(n, POWER_ALLOWED_TAGS);
177 }
178
179 /**
180 * Helper function to check if power tags is a certain value.
181 * @param p The primitive to be tested
182 * @param values List of possible values
183 * @return {@code true} if power key is set and equal to possible values
184 */
185 private static final boolean isPowerIn(OsmPrimitive p, Collection<String> values) {
186 String v = p.get("power");
187 return v != null && values != null && values.contains(v);
188 }
189
190 protected class PowerLineError extends TestError {
191 private final Way line;
192 public PowerLineError(Node n, Way line) {
193 super(PowerLines.this, Severity.WARNING,
194 tr("Missing power tower/pole within power line"), POWER_LINES, n);
195 this.line = line;
196 }
197 public final Node getNode() {
198 return (Node) getPrimitives().iterator().next();
199 }
200 }
201}
Note: See TracBrowser for help on using the repository browser.