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

Last change on this file since 14473 was 14473, checked in by GerdP, 5 years ago

see #17040 don't keep refs to OSM primitives in validation tests because this can prevent GC of Dataset instance

  • Property svn:eol-style set to native
File size: 6.9 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.List;
10
11import org.openstreetmap.josm.data.osm.Node;
12import org.openstreetmap.josm.data.osm.OsmPrimitive;
13import org.openstreetmap.josm.data.osm.Relation;
14import org.openstreetmap.josm.data.osm.Way;
15import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon;
16import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.JoinedWay;
17import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache;
18import org.openstreetmap.josm.data.validation.Severity;
19import org.openstreetmap.josm.data.validation.Test;
20import org.openstreetmap.josm.data.validation.TestError;
21import org.openstreetmap.josm.gui.progress.ProgressMonitor;
22import org.openstreetmap.josm.tools.Geometry;
23
24/**
25 * Checks for nodes in power lines/minor_lines that do not have a power=tower/pole tag.<br>
26 * See #7812 for discussions about this test.
27 */
28public class PowerLines extends Test {
29
30 /** Test identifier */
31 protected static final int POWER_LINES = 2501;
32
33 /** Values for {@code power} key interpreted as power lines */
34 static final Collection<String> POWER_LINE_TAGS = Arrays.asList("line", "minor_line");
35 /** Values for {@code power} key interpreted as power towers */
36 static final Collection<String> POWER_TOWER_TAGS = Arrays.asList("tower", "pole");
37 /** Values for {@code power} key interpreted as power stations */
38 static final Collection<String> POWER_STATION_TAGS = Arrays.asList("station", "sub_station", "substation", "plant", "generator");
39 /** Values for {@code building} key interpreted as power stations */
40 static final Collection<String> BUILDING_STATION_TAGS = Arrays.asList("transformer_tower");
41 /** Values for {@code power} key interpreted as allowed power items */
42 static final Collection<String> POWER_ALLOWED_TAGS = Arrays.asList("switch", "transformer", "busbar", "generator", "switchgear",
43 "portal", "terminal", "insulator");
44
45 private final List<TestError> potentialErrors = new ArrayList<>();
46
47 private final List<OsmPrimitive> powerStations = new ArrayList<>();
48
49 /**
50 * Constructs a new {@code PowerLines} test.
51 */
52 public PowerLines() {
53 super(tr("Power lines"), tr("Checks for nodes in power lines that do not have a power=tower/pole tag."));
54 }
55
56 @Override
57 public void visit(Way w) {
58 if (w.isUsable()) {
59 if (isPowerLine(w) && !w.hasTag("location", "underground")) {
60 for (Node n : w.getNodes()) {
61 if (!isPowerTower(n) && !isPowerAllowed(n) && IN_DOWNLOADED_AREA.test(n)
62 && (!w.isFirstLastNode(n) || !isPowerStation(n))) {
63 potentialErrors.add(TestError.builder(this, Severity.WARNING, POWER_LINES)
64 .message(tr("Missing power tower/pole within power line"))
65 .primitives(n)
66 .build());
67 }
68 }
69 } else if (w.isClosed() && isPowerStation(w)) {
70 powerStations.add(w);
71 }
72 }
73 }
74
75 @Override
76 public void visit(Relation r) {
77 if (r.isMultipolygon() && isPowerStation(r)) {
78 powerStations.add(r);
79 }
80 }
81
82 @Override
83 public void startTest(ProgressMonitor progressMonitor) {
84 super.startTest(progressMonitor);
85 powerStations.clear();
86 potentialErrors.clear();
87 }
88
89 @Override
90 public void endTest() {
91 for (TestError e : potentialErrors) {
92 e.getPrimitives().stream()
93 .map(Node.class::cast)
94 .filter(n -> !isInPowerStation(n))
95 .findAny()
96 .ifPresent(ignore -> errors.add(e));
97 }
98 potentialErrors.clear();
99 powerStations.clear();
100 super.endTest();
101 }
102
103 protected final boolean isInPowerStation(Node n) {
104 for (OsmPrimitive station : powerStations) {
105 List<List<Node>> nodesLists = new ArrayList<>();
106 if (station instanceof Way) {
107 nodesLists.add(((Way) station).getNodes());
108 } else if (station instanceof Relation) {
109 Multipolygon polygon = MultipolygonCache.getInstance().get((Relation) station);
110 if (polygon != null) {
111 for (JoinedWay outer : Multipolygon.joinWays(polygon.getOuterWays())) {
112 nodesLists.add(outer.getNodes());
113 }
114 }
115 }
116 for (List<Node> nodes : nodesLists) {
117 if (Geometry.nodeInsidePolygon(n, nodes)) {
118 return true;
119 }
120 }
121 }
122 return false;
123 }
124
125 /**
126 * Determines if the specified way denotes a power line.
127 * @param w The way to be tested
128 * @return {@code true} if power key is set and equal to line/minor_line
129 */
130 protected static final boolean isPowerLine(Way w) {
131 return isPowerIn(w, POWER_LINE_TAGS);
132 }
133
134 /**
135 * Determines if the specified primitive denotes a power station.
136 * @param p The primitive to be tested
137 * @return {@code true} if power key is set and equal to station/sub_station/plant
138 */
139 protected static final boolean isPowerStation(OsmPrimitive p) {
140 return isPowerIn(p, POWER_STATION_TAGS) || isBuildingIn(p, BUILDING_STATION_TAGS);
141 }
142
143 /**
144 * Determines if the specified node denotes a power tower/pole.
145 * @param n The node to be tested
146 * @return {@code true} if power key is set and equal to tower/pole
147 */
148 protected static final boolean isPowerTower(Node n) {
149 return isPowerIn(n, POWER_TOWER_TAGS);
150 }
151
152 /**
153 * Determines if the specified node denotes a power infrastructure allowed on a power line.
154 * @param n The node to be tested
155 * @return True if power key is set and equal to switch/tranformer/busbar/generator
156 */
157 protected static final boolean isPowerAllowed(Node n) {
158 return isPowerIn(n, POWER_ALLOWED_TAGS);
159 }
160
161 /**
162 * Helper function to check if power tag is a certain value.
163 * @param p The primitive to be tested
164 * @param values List of possible values
165 * @return {@code true} if power key is set and equal to possible values
166 */
167 private static boolean isPowerIn(OsmPrimitive p, Collection<String> values) {
168 return p.hasTag("power", values);
169 }
170
171 /**
172 * Helper function to check if building tag is a certain value.
173 * @param p The primitive to be tested
174 * @param values List of possible values
175 * @return {@code true} if power key is set and equal to possible values
176 */
177 private static boolean isBuildingIn(OsmPrimitive p, Collection<String> values) {
178 return p.hasTag("building", values);
179 }
180}
Note: See TracBrowser for help on using the repository browser.