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

Last change on this file since 17243 was 17111, checked in by GerdP, 4 years ago

fix #16247: Validator issues on power related items

  • replace mapcss tests by java code, use new code 2502 for warning Node connects a power line or cable with an object which is not related to the power infrastructure.
  • Property svn:eol-style set to native
File size: 8.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
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.LinkedHashSet;
10import java.util.List;
11import java.util.Set;
12
13import org.openstreetmap.josm.data.osm.Node;
14import org.openstreetmap.josm.data.osm.OsmPrimitive;
15import org.openstreetmap.josm.data.osm.Relation;
16import org.openstreetmap.josm.data.osm.RelationMember;
17import org.openstreetmap.josm.data.osm.Way;
18import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon;
19import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.JoinedWay;
20import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache;
21import org.openstreetmap.josm.data.validation.Severity;
22import org.openstreetmap.josm.data.validation.Test;
23import org.openstreetmap.josm.data.validation.TestError;
24import org.openstreetmap.josm.gui.progress.ProgressMonitor;
25import org.openstreetmap.josm.tools.Geometry;
26
27/**
28 * Checks for nodes in power lines/minor_lines that do not have a power=tower/pole tag.<br>
29 * See #7812 for discussions about this test.
30 */
31public class PowerLines extends Test {
32
33 /** Test identifier */
34 protected static final int POWER_LINES = 2501;
35 protected static final int POWER_CONNECTION = 2502;
36
37 /** Values for {@code power} key interpreted as power lines */
38 static final Collection<String> POWER_LINE_TAGS = Arrays.asList("line", "minor_line");
39 /** Values for {@code power} key interpreted as power towers */
40 static final Collection<String> POWER_TOWER_TAGS = Arrays.asList("tower", "pole");
41 /** Values for {@code power} key interpreted as power stations */
42 static final Collection<String> POWER_STATION_TAGS = Arrays.asList("station", "sub_station", "substation", "plant", "generator");
43 /** Values for {@code building} key interpreted as power stations */
44 static final Collection<String> BUILDING_STATION_TAGS = Arrays.asList("transformer_tower");
45 /** Values for {@code power} key interpreted as allowed power items */
46 static final Collection<String> POWER_ALLOWED_TAGS = Arrays.asList("switch", "transformer", "busbar", "generator", "switchgear",
47 "portal", "terminal", "insulator");
48
49 private final Set<Node> badConnections = new LinkedHashSet<>();
50 private final Set<Node> missingTowerOrPole = new LinkedHashSet<>();
51
52 private final List<OsmPrimitive> powerStations = new ArrayList<>();
53
54 /**
55 * Constructs a new {@code PowerLines} test.
56 */
57 public PowerLines() {
58 super(tr("Power lines"), tr("Checks for nodes in power lines that do not have a power=tower/pole tag."));
59 }
60
61 @Override
62 public void visit(Way w) {
63 if (w.isUsable()) {
64 if (isPowerLine(w) && !w.hasTag("location", "underground")) {
65 for (Node n : w.getNodes()) {
66 if (!isPowerTower(n) && !isPowerAllowed(n) && IN_DOWNLOADED_AREA.test(n)
67 && (!w.isFirstLastNode(n) || !isPowerStation(n))) {
68 missingTowerOrPole.add(n);
69 }
70 }
71 } else if (w.isClosed() && isPowerStation(w)) {
72 powerStations.add(w);
73 }
74 }
75 }
76
77 @Override
78 public void visit(Node n) {
79 boolean nodeInLineOrCable = false;
80 boolean connectedToUnrelated = false;
81 for (Way parent : n.getParentWays()) {
82 if (parent.hasTag("power", "line", "minor_line", "cable"))
83 nodeInLineOrCable = true;
84 else if (!isRelatedToPower(parent)) {
85 connectedToUnrelated = true;
86 }
87 }
88 if (nodeInLineOrCable && connectedToUnrelated)
89 badConnections.add(n);
90 }
91
92 private static boolean isRelatedToPower(Way way) {
93 if (way.hasTag("power") || way.hasTag("building"))
94 return true;
95 for (OsmPrimitive ref : way.getReferrers()) {
96 if (ref instanceof Relation && ref.isMultipolygon() && (ref.hasTag("power") || ref.hasTag("building"))) {
97 for (RelationMember rm : ((Relation) ref).getMembers()) {
98 if (way == rm.getMember())
99 return true;
100 }
101 }
102 }
103 return false;
104 }
105
106 @Override
107 public void visit(Relation r) {
108 if (r.isMultipolygon() && isPowerStation(r)) {
109 powerStations.add(r);
110 }
111 }
112
113 @Override
114 public void startTest(ProgressMonitor progressMonitor) {
115 super.startTest(progressMonitor);
116 clearCollections();
117 }
118
119 @Override
120 public void endTest() {
121 for (Node n : missingTowerOrPole) {
122 if (!isInPowerStation(n)) {
123 errors.add(TestError.builder(this, Severity.WARNING, POWER_LINES)
124 .message(tr("Missing power tower/pole within power line"))
125 .primitives(n)
126 .build());
127 }
128 }
129
130 for (Node n : badConnections) {
131 errors.add(TestError.builder(this, Severity.WARNING, POWER_CONNECTION)
132 .message(tr("Node connects a power line or cable with an object "
133 + "which is not related to the power infrastructure."))
134 .primitives(n).build());
135 }
136 clearCollections();
137 super.endTest();
138 }
139
140 protected final boolean isInPowerStation(Node n) {
141 for (OsmPrimitive station : powerStations) {
142 List<List<Node>> nodesLists = new ArrayList<>();
143 if (station instanceof Way) {
144 nodesLists.add(((Way) station).getNodes());
145 } else if (station instanceof Relation) {
146 Multipolygon polygon = MultipolygonCache.getInstance().get((Relation) station);
147 if (polygon != null) {
148 for (JoinedWay outer : Multipolygon.joinWays(polygon.getOuterWays())) {
149 nodesLists.add(outer.getNodes());
150 }
151 }
152 }
153 for (List<Node> nodes : nodesLists) {
154 if (Geometry.nodeInsidePolygon(n, nodes)) {
155 return true;
156 }
157 }
158 }
159 return false;
160 }
161
162 /**
163 * Determines if the specified way denotes a power line.
164 * @param w The way to be tested
165 * @return {@code true} if power key is set and equal to line/minor_line
166 */
167 protected static final boolean isPowerLine(Way w) {
168 return isPowerIn(w, POWER_LINE_TAGS);
169 }
170
171 /**
172 * Determines if the specified primitive denotes a power station.
173 * @param p The primitive to be tested
174 * @return {@code true} if power key is set and equal to station/sub_station/plant
175 */
176 protected static final boolean isPowerStation(OsmPrimitive p) {
177 return isPowerIn(p, POWER_STATION_TAGS) || isBuildingIn(p, BUILDING_STATION_TAGS);
178 }
179
180 /**
181 * Determines if the specified node denotes a power tower/pole.
182 * @param n The node to be tested
183 * @return {@code true} if power key is set and equal to tower/pole
184 */
185 protected static final boolean isPowerTower(Node n) {
186 return isPowerIn(n, POWER_TOWER_TAGS);
187 }
188
189 /**
190 * Determines if the specified node denotes a power infrastructure allowed on a power line.
191 * @param n The node to be tested
192 * @return True if power key is set and equal to switch/tranformer/busbar/generator
193 */
194 protected static final boolean isPowerAllowed(Node n) {
195 return isPowerIn(n, POWER_ALLOWED_TAGS);
196 }
197
198 /**
199 * Helper function to check if power tag is a certain value.
200 * @param p The primitive to be tested
201 * @param values List of possible values
202 * @return {@code true} if power key is set and equal to possible values
203 */
204 private static boolean isPowerIn(OsmPrimitive p, Collection<String> values) {
205 return p.hasTag("power", values);
206 }
207
208 /**
209 * Helper function to check if building tag is a certain value.
210 * @param p The primitive to be tested
211 * @param values List of possible values
212 * @return {@code true} if power key is set and equal to possible values
213 */
214 private static boolean isBuildingIn(OsmPrimitive p, Collection<String> values) {
215 return p.hasTag("building", values);
216 }
217
218 private void clearCollections() {
219 powerStations.clear();
220 badConnections.clear();
221 missingTowerOrPole.clear();
222 }
223}
Note: See TracBrowser for help on using the repository browser.