Changeset 32707 in osm for applications/editors/josm/plugins/pt_assistant/src
- Timestamp:
- 2016-07-24T04:46:09+02:00 (8 years ago)
- Location:
- applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTRouteDataManager.java
r32656 r32707 5 5 6 6 import org.openstreetmap.josm.data.coor.LatLon; 7 import org.openstreetmap.josm.data.osm.Node; 7 8 import org.openstreetmap.josm.data.osm.Relation; 8 9 import org.openstreetmap.josm.data.osm.RelationMember; … … 181 182 return this.failedMembers; 182 183 } 184 185 /** 186 * Returns the route relation for which this manager was created: 187 * @return 188 */ 189 public Relation getRelation() { 190 return this.relation; 191 } 183 192 184 193 /** … … 218 227 return null; 219 228 } 229 230 /** 231 * Returns all PTWays of this route that contain the given way. 232 * 233 * @param way 234 * @return 235 */ 236 public List<PTWay> findPTWaysThatContain(Way way) { 237 238 List<PTWay> ptwaysThatContain = new ArrayList<>(); 239 for (PTWay ptway : ptways) { 240 if (ptway.getWays().contains(way)) { 241 ptwaysThatContain.add(ptway); 242 } 243 } 244 return ptwaysThatContain; 245 } 246 247 /** 248 * Returns all PTWays of this route that contain the given node as their 249 * first or last node. 250 * 251 * @return 252 */ 253 public List<PTWay> findPTWaysThatContainAsEndNode(Node node) { 254 255 List<PTWay> ptwaysThatContain = new ArrayList<>(); 256 for (PTWay ptway : ptways) { 257 List<Way> ways = ptway.getWays(); 258 if (ways.get(0).firstNode() == node || ways.get(0).lastNode() == node 259 || ways.get(ways.size() - 1).firstNode() == node || ways.get(ways.size() - 1).lastNode() == node) { 260 ptwaysThatContain.add(ptway); 261 } 262 } 263 return ptwaysThatContain; 264 265 } 266 267 /** 268 * Checks if at most one PTWay of this route refers to the given node 269 * 270 * @param node 271 * @return 272 */ 273 public boolean isDeadendNode(Node node) { 274 275 List<PTWay> referringPtways = this.findPTWaysThatContainAsEndNode(node); 276 if (referringPtways.size() <= 1) { 277 return true; 278 } 279 return false; 280 } 281 282 /** 283 * Returns the PTWay which comes directly after the given ptway according to 284 * the existing route member sorting 285 * 286 * @param ptway 287 * @return 288 */ 289 public PTWay getNextPTWay(PTWay ptway) { 290 291 for (int i = 0; i < ptways.size() - 1; i++) { 292 if (ptways.get(i) == ptway) { 293 return ptways.get(i + 1); 294 } 295 } 296 return null; 297 298 } 299 300 /** 301 * Returns the PTWay which comes directly before the given ptway according 302 * to the existing route member sorting 303 * 304 * @param ptway 305 * @return 306 */ 307 public PTWay getPreviousPTWay(PTWay ptway) { 308 309 for (int i = 1; i < ptways.size(); i++) { 310 if (ptways.get(i) == ptway) { 311 return ptways.get(i - 1); 312 } 313 } 314 return null; 315 } 316 317 /** 318 * Returns a sequence of PTWays that are between the start way and the end 319 * way. The resulting list includes the start and end PTWays. 320 * 321 * @param start 322 * @param end 323 * @return 324 */ 325 public List<PTWay> getPTWaysBetween(Way start, Way end) { 326 327 List<Integer> potentialStartIndices = new ArrayList<>(); 328 List<Integer> potentialEndIndices = new ArrayList<>(); 329 330 for (int i = 0; i < ptways.size(); i++) { 331 if (ptways.get(i).getWays().contains(start)) { 332 potentialStartIndices.add(i); 333 } 334 if (ptways.get(i).getWays().contains(end)) { 335 potentialEndIndices.add(i); 336 } 337 } 338 339 List<int[]> pairList = new ArrayList<>(); 340 for (Integer potentialStartIndex: potentialStartIndices) { 341 for (Integer potentialEndIndex: potentialEndIndices) { 342 if (potentialStartIndex <= potentialEndIndex) { 343 int[] pair = {potentialStartIndex, potentialEndIndex}; 344 pairList.add(pair); 345 } 346 } 347 } 348 349 int minDifference = Integer.MAX_VALUE; 350 int[] mostSuitablePair = {0, 0}; 351 for (int[] pair: pairList) { 352 int diff = pair[1] - pair[0]; 353 if (diff < minDifference) { 354 minDifference = diff; 355 mostSuitablePair = pair; 356 } 357 } 358 359 List<PTWay> result = new ArrayList<>(); 360 for (int i = mostSuitablePair[0]; i <= mostSuitablePair[1]; i++) { 361 result.add(ptways.get(i)); 362 } 363 return result; 364 } 365 366 /** 367 * Returns the common Node of two PTWays or null if there is no common Node 368 * @param way1 369 * @param way2 370 * @return 371 */ 372 public Node getCommonNode(PTWay way1, PTWay way2) { 373 374 List<Way> wayList1 = way1.getWays(); 375 List<Way> wayList2 = way2.getWays(); 376 377 for (int i = 0; i < wayList1.size(); i++) { 378 for (int j = 0; j < wayList2.size(); j++) { 379 if (wayList1.get(i).firstNode() == wayList2.get(j).firstNode() || wayList1.get(i).firstNode() == wayList2.get(j).lastNode()) { 380 return wayList1.get(i).firstNode(); 381 } 382 if (wayList1.get(i).lastNode() == wayList2.get(j).firstNode() || wayList1.get(i).lastNode() == wayList2.get(j).lastNode()) { 383 return wayList1.get(i).lastNode(); 384 } 385 } 386 } 387 return null; 388 } 389 220 390 } -
applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTRouteSegment.java
r32299 r32707 27 27 } 28 28 29 public PTRouteSegment(PTStop firstStop, PTStop lastStop) { 30 this.firstStop = firstStop; 31 this.lastStop = lastStop; 32 this.ptways = new ArrayList<>(); 33 } 34 29 35 public List<PTWay> getPTWays() { 30 36 return this.ptways; -
applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTWay.java
r32522 r32707 4 4 import java.util.List; 5 5 6 import org.openstreetmap.josm.data.osm.Node; 6 7 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 7 8 import org.openstreetmap.josm.data.osm.RelationMember; … … 63 64 return this.ways; 64 65 } 65 66 66 67 67 /** … … 74 74 return false; 75 75 } 76 76 77 77 /** 78 * Determines if this PTWay is modeled by an OsmPrimitieType.RELATION (i.e. this is a nested relation) 78 * Determines if this PTWay is modeled by an OsmPrimitieType.RELATION (i.e. 79 * this is a nested relation) 79 80 */ 80 81 public boolean isRelation() { … … 84 85 return false; 85 86 } 86 87 88 /** 89 * Returns the end nodes of this PTWay. If this PTWay is a nested relation, 90 * the order of the composing ways is assumed to be correct 91 * 92 * @return 93 */ 94 public Node[] getEndNodes() { 95 Node[] endNodes = new Node[2]; 96 97 if (this.isWay()) { 98 endNodes[0] = this.getWay().firstNode(); 99 endNodes[1] = this.getWay().lastNode(); 100 // TODO: if this is a roundabout 101 } else { // nested relation: 102 Way firstWay = this.getWays().get(0); 103 Way secondWay = this.getWays().get(1); 104 Way prelastWay = this.getWays().get(this.getWays().size() - 2); 105 Way lastWay = this.getWays().get(this.getWays().size() - 1); 106 if (firstWay.firstNode() == secondWay.firstNode() || firstWay.firstNode() == secondWay.lastNode()) { 107 endNodes[0] = firstWay.lastNode(); 108 } else { 109 endNodes[0] = firstWay.firstNode(); 110 } 111 if (lastWay.firstNode() == prelastWay.firstNode() || lastWay.firstNode() == prelastWay.lastNode()) { 112 endNodes[1] = lastWay.lastNode(); 113 } else { 114 endNodes[1] = lastWay.firstNode(); 115 } 116 } 117 118 return endNodes; 119 } 87 120 88 121 } -
applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/utils/StopToWayAssigner.java
r32656 r32707 4 4 import java.util.Collection; 5 5 import java.util.HashMap; 6 import java.util.HashSet; 6 7 import java.util.List; 7 8 import java.util.Set; … … 30 31 31 32 /* contains assigned stops */ 32 p rivate static HashMap<PTStop, PTWay> stopToWay = new HashMap<>();33 public static HashMap<PTStop, List<Way>> stopToWay = new HashMap<>(); 33 34 34 35 /* … … 36 37 * created 37 38 */ 38 private List<PTWay> ptways; 39 private HashSet<Way> ways; 40 41 /* route relation for which this StopToWayAssigner was created */ 39 42 40 43 public StopToWayAssigner(List<PTWay> ptways) { 41 this.ptways = ptways; 44 ways = new HashSet<Way>(); 45 for (PTWay ptway: ptways) { 46 ways.addAll(ptway.getWays()); 47 } 42 48 } 43 49 … … 48 54 * @return 49 55 */ 50 public PTWay get(PTStop stop) {56 public Way get(PTStop stop) { 51 57 52 58 // 1) Search if this stop has already been assigned: 53 59 if (stopToWay.containsKey(stop)) { 54 return stopToWay.get(stop); 60 List<Way> assignedWays = stopToWay.get(stop); 61 for (Way assignedWay: assignedWays) { 62 if (this.ways.contains(assignedWay)) { 63 return assignedWay; 64 } 65 } 55 66 } 56 67 57 68 // 2) Search if the stop has a stop position: 58 PTWay ptwayOfStopPosition = findPtwayForNode(stop.getStopPosition()); 59 if (ptwayOfStopPosition != null) { 60 stopToWay.put(stop, ptwayOfStopPosition); 61 return ptwayOfStopPosition; 62 } 69 Way wayOfStopPosition = findWayForNode(stop.getStopPosition()); 70 if (wayOfStopPosition != null) { 71 addAssignedWayToMap(stop, wayOfStopPosition); 72 return wayOfStopPosition; 73 } 74 75 // TODO: search if a stop position is in the vicinity of a platform 63 76 64 77 // 3) Search if the stop has a stop_area: … … 75 88 for (RelationMember rm : parentRelation.getMembers()) { 76 89 if (rm.getMember().hasTag("public_transport", "stop_position")) { 77 PTWay rmPtway = this.findPtwayForNode(rm.getNode());78 if (rm Ptway != null) {79 stopToWay.put(stop, rmPtway);80 return rm Ptway;90 Way rmWay = this.findWayForNode(rm.getNode()); 91 if (rmWay != null) { 92 addAssignedWayToMap(stop, rmWay); 93 return rmWay; 81 94 } 82 95 } … … 89 102 while (searchRadius < 0.005) { 90 103 91 PTWay foundWay = this.findNearestWayInRadius(stop.getPlatform(), searchRadius);104 Way foundWay = this.findNearestWayInRadius(stop.getPlatform(), searchRadius); 92 105 if (foundWay != null) { 93 stopToWay.put(stop, foundWay);106 addAssignedWayToMap(stop, foundWay); 94 107 return foundWay; 95 108 } … … 97 110 foundWay = this.findNearestWayInRadius(stop.getStopPosition(), searchRadius); 98 111 if (foundWay != null) { 99 stopToWay.put(stop, foundWay);112 addAssignedWayToMap(stop, foundWay); 100 113 return foundWay; 101 114 } … … 113 126 * @return 114 127 */ 115 private PTWay findPtwayForNode(Node stopPosition) {128 private Way findWayForNode(Node stopPosition) { 116 129 117 130 if (stopPosition == null) { … … 124 137 if (referredPrimitive.getType().equals(OsmPrimitiveType.WAY)) { 125 138 Way referredWay = (Way) referredPrimitive; 126 for (PTWay ptway : ptways) { 127 if (ptway.getWays().contains(referredWay)) { 128 return ptway; 129 } 139 if (this.ways.contains(referredWay)) { 140 return referredWay; 130 141 } 131 142 } … … 144 155 * @return 145 156 */ 146 private PTWay findNearestWayInRadius(OsmPrimitive platform, double searchRadius) {157 private Way findNearestWayInRadius(OsmPrimitive platform, double searchRadius) { 147 158 148 159 if (platform == null) { … … 157 168 BBox platformBBox = new BBox(ax, ay, bx, by); 158 169 159 List<Way> potentialWays = new ArrayList<>();170 Set<Way> potentialWays = new HashSet<>(); 160 171 161 172 Collection<Node> allNodes = platform.getDataSet().getNodes(); … … 166 177 if (referrer.getType().equals(OsmPrimitiveType.WAY)) { 167 178 Way referrerWay = (Way) referrer; 168 for (PTWay ptway : this.ptways) { 169 if (ptway.getWays().contains(referrerWay)) { 170 potentialWays.add(referrerWay); 171 } 179 if (this.ways.contains(referrerWay)) { 180 potentialWays.add(referrerWay); 172 181 } 173 182 } … … 176 185 } 177 186 } 178 187 179 188 Node platformNode = null; 180 189 if (platform.getType().equals(OsmPrimitiveType.NODE)) { … … 185 194 Way nearestWay = null; 186 195 Double minDistance = Double.MAX_VALUE; 187 for (Way potentialWay : potentialWays) {188 double distance = this.calculateMinDistance (platformNode, potentialWay);196 for (Way potentialWay : potentialWays) { 197 double distance = this.calculateMinDistanceToSegment(platformNode, potentialWay); 189 198 if (distance < minDistance) { 190 199 minDistance = distance; … … 193 202 } 194 203 195 for (PTWay ptway: this.ptways) { 196 if (ptway.getWays().contains(nearestWay)) { 197 return ptway; 198 } 199 } 200 201 return null; 204 return nearestWay; 202 205 } 203 206 204 207 /** 205 208 * Calculates the minimum distance between a node and a way 209 * 206 210 * @param node 207 211 * @param way 208 212 * @return 209 213 */ 210 private double calculateMinDistance (Node node, Way way) {214 private double calculateMinDistanceToSegment(Node node, Way way) { 211 215 212 216 double minDistance = Double.MAX_VALUE; 213 217 214 218 List<Pair<Node, Node>> waySegments = way.getNodePairs(false); 219 215 220 for (Pair<Node, Node> waySegment : waySegments) { 216 221 if (waySegment.a != node && waySegment.b != node) { 217 double distanceToLine = this.calculateDistance (node, waySegment);222 double distanceToLine = this.calculateDistanceToSegment(node, waySegment); 218 223 if (distanceToLine < minDistance) { 219 224 minDistance = distanceToLine; … … 227 232 228 233 /** 229 * // * Calculates the distance from point to segment using formulas for 230 * triangle area. 234 * Calculates the distance from point to segment and differentiates between 235 * acute, right and obtuse triangles. If a triangle is acute or right, the 236 * distance to segment is calculated as distance from point to line. If the 237 * triangle is obtuse, the distance is calculated as the distance to the 238 * nearest vertex of the segment. 239 * 240 * @param node 241 * @param segment 242 * @return 243 */ 244 private double calculateDistanceToSegment(Node node, Pair<Node, Node> segment) { 245 246 if (node == segment.a || node == segment.b) { 247 return 0.0; 248 } 249 250 double lengthA = node.getCoor().distance(segment.a.getCoor()); 251 double lengthB = node.getCoor().distance(segment.b.getCoor()); 252 double lengthC = segment.a.getCoor().distance(segment.b.getCoor()); 253 254 if (isObtuse(lengthC, lengthB, lengthA)) { 255 return lengthB; 256 } 257 258 if (isObtuse(lengthA, lengthC, lengthB)) { 259 return lengthA; 260 } 261 262 return calculateDistanceToLine(node, segment); 263 } 264 265 /** 266 * Calculates the distance from point to line using formulas for triangle 267 * area. Does not differentiate between acute, right and obtuse triangles 231 268 * 232 269 * @param node … … 234 271 * @return 235 272 */ 236 private double calculateDistance (Node node, Pair<Node, Node> segment) {273 private double calculateDistanceToLine(Node node, Pair<Node, Node> segment) { 237 274 238 275 /* … … 257 294 258 295 /** 296 * Checks if the angle opposite of the edge c is obtuse. Uses the cosine 297 * theorem 298 * 299 * @param lengthA 300 * @param lengthB 301 * @param lengthC 302 * the triangle edge which is testes 303 * @return true if the angle opposite of te edge c is obtuse 304 */ 305 private boolean isObtuse(double lengthA, double lengthB, double lengthC) { 306 307 /*- 308 * Law of cosines: 309 * c^2 = a^2 + b^2 - 2abcos 310 * if c^2 = a^2 + b^2, it is a right triangle 311 * if c^2 < a^2 + b^2, it is an acute triangle 312 * if c^2 > a^2 + b^2, it is an obtuse triangle 313 */ 314 315 if (lengthC * lengthC > lengthA * lengthA + lengthB * lengthB) { 316 return true; 317 } 318 319 return false; 320 } 321 322 /** 323 * Adds the given way to the map of assigned ways. Assumes that the given 324 * way is not contained in the map. 325 * 326 * @param stop 327 * @param way 328 */ 329 private void addAssignedWayToMap(PTStop stop, Way way) { 330 if (stopToWay.containsKey(stop)) { 331 List<Way> assignedWays = stopToWay.get(stop); 332 assignedWays.add(way); 333 } else { 334 List<Way> assignedWays = new ArrayList<Way>(); 335 assignedWays.add(way); 336 stopToWay.put(stop, assignedWays); 337 } 338 } 339 340 /** 259 341 * May be needed if the correspondence between stops and ways has changed 260 342 * significantly -
applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/PTAssistantValidatorTest.java
r32650 r32707 15 15 import org.openstreetmap.josm.data.osm.Node; 16 16 import org.openstreetmap.josm.data.osm.Relation; 17 import org.openstreetmap.josm.data.osm.Way; 17 18 import org.openstreetmap.josm.data.validation.Severity; 18 19 import org.openstreetmap.josm.data.validation.Test; … … 20 21 import org.openstreetmap.josm.plugins.pt_assistant.actions.FixTask; 21 22 import org.openstreetmap.josm.plugins.pt_assistant.actions.IncompleteMembersDownloadThread; 23 import org.openstreetmap.josm.plugins.pt_assistant.data.PTRouteDataManager; 24 import org.openstreetmap.josm.plugins.pt_assistant.data.PTRouteSegment; 25 import org.openstreetmap.josm.plugins.pt_assistant.data.PTStop; 26 import org.openstreetmap.josm.plugins.pt_assistant.data.PTWay; 22 27 import org.openstreetmap.josm.plugins.pt_assistant.gui.IncompleteMembersDownloadDialog; 23 28 import org.openstreetmap.josm.plugins.pt_assistant.gui.PTAssistantLayer; 24 29 import org.openstreetmap.josm.plugins.pt_assistant.gui.ProceedDialog; 25 30 import org.openstreetmap.josm.plugins.pt_assistant.utils.RouteUtils; 31 import org.openstreetmap.josm.plugins.pt_assistant.utils.StopToWayAssigner; 26 32 27 33 public class PTAssistantValidatorTest extends Test { … … 36 42 public static final int ERROR_CODE_SOLITARY_STOP_POSITION = 3751; 37 43 public static final int ERROR_CODE_PLATFORM_PART_OF_HIGHWAY = 3752; 44 public static final int ERROR_CODE_STOP_NOT_SERVED = 3753; 45 public static final int ERROR_CODE_STOP_BY_STOP = 3754; 46 38 47 39 48 private PTAssistantLayer layer; … … 280 289 if (!routeChecker.getHasGap()) { 281 290 // Variant 1 282 // TODO: add the segments of this route to the list correct route 283 // segments 291 // storeCorrectRouteSegments(r); 292 284 293 } 285 294 … … 302 311 segmentChecker.performFirstStopTest(); 303 312 segmentChecker.performLastStopTest(); 304 305 // TODO: perform segment test 313 segmentChecker.performStopByStopTest(); 314 306 315 this.errors.addAll(segmentChecker.getErrors()); 307 // performDummyTest(r); 316 } 317 318 /** 319 * Creates the PTRouteSegments of a route that has been found correct and stores them in the list of correct route segments 320 * @param r route relation 321 */ 322 @SuppressWarnings("unused") 323 private void storeCorrectRouteSegments(Relation r) { 324 PTRouteDataManager manager = new PTRouteDataManager(r); 325 StopToWayAssigner assigner = new StopToWayAssigner(manager.getPTWays()); 326 if (manager.getPTStops().size() > 1) { 327 for (int i = 1; i < manager.getPTStops().size(); i++) { 328 PTStop segmentStartStop = manager.getPTStops().get(i-1); 329 PTStop segmentEndStop = manager.getPTStops().get(i); 330 Way segmentStartWay = assigner.get(segmentStartStop); 331 Way segmentEndWay = assigner.get(segmentEndStop); 332 List<PTWay> waysBetweenStops = manager.getPTWaysBetween(segmentStartWay, segmentEndWay); 333 PTRouteSegment routeSegment = new PTRouteSegment(segmentStartStop, segmentEndStop, waysBetweenStops); 334 SegmentChecker.addCorrectSegment(routeSegment); 335 } 336 } 308 337 } 309 338 … … 340 369 } 341 370 342 if (testError.getCode() == ERROR_CODE_SOLITARY_STOP_POSITION || testError.getCode() == ERROR_CODE_PLATFORM_PART_OF_HIGHWAY) { 371 if (testError.getCode() == ERROR_CODE_SOLITARY_STOP_POSITION 372 || testError.getCode() == ERROR_CODE_PLATFORM_PART_OF_HIGHWAY) { 343 373 commands.add(NodeChecker.fixError(testError)); 344 374 } -
applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/SegmentChecker.java
r32567 r32707 6 6 import java.util.List; 7 7 8 import org.openstreetmap.josm.command.Command; 9 import org.openstreetmap.josm.data.coor.LatLon; 8 10 import org.openstreetmap.josm.data.osm.Node; 9 11 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 30 32 31 33 /* PTRouteSegments that have been validated and are correct */ 32 @SuppressWarnings("unused")33 34 private static List<PTRouteSegment> correctSegments = new ArrayList<PTRouteSegment>(); 34 35 … … 37 38 38 39 /* Assigns PTStops to nearest PTWays and stores that correspondence */ 39 @SuppressWarnings("unused")40 40 private StopToWayAssigner assigner; 41 41 42 /* 43 * Stores reference that shows in which direction the segment checker is 44 * moving 45 */ 46 private Node firstNodeOfRouteSegmentInDirectionOfTravel; 47 42 48 public SegmentChecker(Relation relation, Test test) { 43 49 … … 45 51 46 52 this.manager = new PTRouteDataManager(relation); 47 48 for (RelationMember rm : manager.getFailedMembers()) {53 54 for (RelationMember rm : manager.getFailedMembers()) { 49 55 List<Relation> primitives = new ArrayList<>(1); 50 56 primitives.add(relation); … … 56 62 } 57 63 58 59 60 64 this.assigner = new StopToWayAssigner(manager.getPTWays()); 61 65 66 } 67 68 /** 69 * Returns the number of route segments that have been already successfully 70 * verified 71 * 72 * @return 73 */ 74 public static int getCorrectSegmentCount() { 75 return correctSegments.size(); 76 } 77 78 /** 79 * Adds the given correct segment to the list of correct segments without 80 * checking its correctness 81 * 82 * @param segment 83 * to add to the list of correct segments 84 */ 85 public static void addCorrectSegment(PTRouteSegment segment) { 86 correctSegments.add(segment); 62 87 } 63 88 … … 153 178 } 154 179 155 @SuppressWarnings("unused")156 private void performSegmentTest() {157 // TODO158 }159 160 180 /** 161 181 * Checks if the given node belongs to the ways of this route. … … 192 212 } 193 213 214 public void performStopByStopTest() { 215 216 if (manager.getPTStopCount() < 2) { 217 return; 218 } 219 220 // Check each route segment: 221 for (int i = 1; i < manager.getPTStopCount(); i++) { 222 223 PTStop startStop = manager.getPTStops().get(i - 1); 224 PTStop endStop = manager.getPTStops().get(i); 225 226 Way startWay = assigner.get(startStop); 227 Way endWay = assigner.get(endStop); 228 if (startWay == null) { 229 this.firstNodeOfRouteSegmentInDirectionOfTravel = null; 230 continue; 231 } 232 if (endWay == null) { 233 this.firstNodeOfRouteSegmentInDirectionOfTravel = null; 234 continue; 235 } 236 // FIXME: throw error if cannot find the corresponding way (which 237 // means that the stop is too far away from way) 238 List<PTWay> segmentWays = manager.getPTWaysBetween(startWay, endWay); 239 240 if (this.firstNodeOfRouteSegmentInDirectionOfTravel == null) { 241 // if we are at the beginning of the route or after a gap / 242 // error: 243 244 this.firstNodeOfRouteSegmentInDirectionOfTravel = findFirstNodeOfRouteSegmentInDirectionOfTravel( 245 segmentWays.get(0)); 246 if (this.firstNodeOfRouteSegmentInDirectionOfTravel == null) { 247 // TODO: throw error 248 continue; 249 } 250 } 251 252 boolean sortingCorrect = existingWaySortingIsCorrect(segmentWays.get(0), 253 this.firstNodeOfRouteSegmentInDirectionOfTravel, segmentWays.get(segmentWays.size() - 1)); 254 if (sortingCorrect) { 255 PTRouteSegment routeSegment = new PTRouteSegment(startStop, endStop, segmentWays); 256 correctSegments.add(routeSegment); 257 } 258 } 259 260 } 261 262 private Node findFirstNodeOfRouteSegmentInDirectionOfTravel(PTWay startWay) { 263 264 // 1) at first check if one of the first or last node of the first ptway 265 // is a deadend node: 266 Node[] startWayEndnodes = startWay.getEndNodes(); 267 if (isDeadendNode(startWayEndnodes[0])) { 268 return startWayEndnodes[0]; 269 } 270 if (isDeadendNode(startWayEndnodes[1])) { 271 return startWayEndnodes[1]; 272 } 273 274 // 2) failing that, check which node this startWay shares with the 275 // following way: 276 PTWay nextWay = manager.getNextPTWay(startWay); 277 if (nextWay == null) { 278 return null; 279 } 280 Node[] nextWayEndnodes = nextWay.getEndNodes(); 281 if (startWayEndnodes[0] == nextWayEndnodes[0] || startWayEndnodes[0] == nextWayEndnodes[1]) { 282 return startWayEndnodes[1]; 283 } 284 if (startWayEndnodes[1] == nextWayEndnodes[0] || startWayEndnodes[1] == nextWayEndnodes[1]) { 285 return startWayEndnodes[0]; 286 } 287 288 return null; 289 290 } 291 292 private boolean isDeadendNode(Node node) { 293 int count = 0; 294 for (PTWay ptway : manager.getPTWays()) { 295 List<Way> ways = ptway.getWays(); 296 for (Way way : ways) { 297 if (way.firstNode() == node || way.lastNode() == node) { 298 count++; 299 } 300 } 301 } 302 return count == 1; 303 } 304 305 /** 306 * Finds the deadend node closest to the given node represented by its 307 * coordinates 308 * 309 * @param coord 310 * coordinates of the givenn node 311 * @param deadendNodes 312 * @return the closest deadend node 313 */ 314 @SuppressWarnings("unused") 315 private Node findClosestDeadendNode(LatLon coord, List<Node> deadendNodes) { 316 317 Node closestDeadendNode = null; 318 double minSqDistance = Double.MAX_VALUE; 319 for (Node deadendNode : deadendNodes) { 320 double distanceSq = coord.distanceSq(deadendNode.getCoor()); 321 if (distanceSq < minSqDistance) { 322 minSqDistance = distanceSq; 323 closestDeadendNode = deadendNode; 324 } 325 } 326 return closestDeadendNode; 327 328 } 329 330 private boolean existingWaySortingIsCorrect(PTWay start, Node startWayPreviousNodeInDirectionOfTravel, PTWay end) { 331 332 if (start == end) { 333 // if both PTStops are on the same PTWay 334 return true; 335 } 336 337 PTWay current = start; 338 339 while (!current.equals(end)) { 340 // "equals" is used here instead of "==" because when the same way 341 // is passed multiple times by the bus, the algorithm should stop no 342 // matter which of the geometrically equal PTWays it finds 343 344 // find the next node in direction of travel (which is part of the 345 // PTWay start): 346 firstNodeOfRouteSegmentInDirectionOfTravel = getOppositeEndNode(current, 347 firstNodeOfRouteSegmentInDirectionOfTravel); 348 349 List<PTWay> nextWaysInDirectionOfTravel = this.findNextPTWaysInDirectionOfTravel(current, 350 firstNodeOfRouteSegmentInDirectionOfTravel); 351 352 PTWay nextPTWayAccortingToExistingSorting = manager.getNextPTWay(current); 353 if (!nextWaysInDirectionOfTravel.contains(nextPTWayAccortingToExistingSorting)) { 354 List<Relation> primitives = new ArrayList<>(1); 355 primitives.add(relation); 356 List<OsmPrimitive> highlighted = new ArrayList<>(); 357 358 highlighted.addAll(current.getWays()); 359 highlighted.add(firstNodeOfRouteSegmentInDirectionOfTravel); 360 361 TestError e = new TestError(this.test, Severity.WARNING, tr("PT: Problem in the route segment"), 362 PTAssistantValidatorTest.ERROR_CODE_STOP_BY_STOP, primitives, highlighted); 363 this.errors.add(e); 364 this.firstNodeOfRouteSegmentInDirectionOfTravel = null; 365 return false; 366 } 367 368 current = nextPTWayAccortingToExistingSorting; 369 370 } 371 372 return true; 373 } 374 375 private Node getOppositeEndNode(Way way, Node node) { 376 377 if (node == way.firstNode()) { 378 return way.lastNode(); 379 } 380 381 if (node == way.lastNode()) { 382 return way.firstNode(); 383 } 384 385 return null; 386 } 387 388 private Node getOppositeEndNode(PTWay ptway, Node node) { 389 if (ptway.isWay()) { 390 return getOppositeEndNode(ptway.getWays().get(0), node); 391 } 392 393 Way firstWay = ptway.getWays().get(0); 394 Way lastWay = ptway.getWays().get(ptway.getWays().size() - 1); 395 Node oppositeNode = node; 396 if (firstWay.firstNode() == node || firstWay.lastNode() == node) { 397 for (int i = 0; i < ptway.getWays().size(); i++) { 398 oppositeNode = getOppositeEndNode(ptway.getWays().get(i), oppositeNode); 399 } 400 return oppositeNode; 401 } else if (lastWay.firstNode() == node || lastWay.lastNode() == node) { 402 for (int i = ptway.getWays().size() - 1; i >= 0; i--) { 403 oppositeNode = getOppositeEndNode(ptway.getWays().get(i), oppositeNode); 404 } 405 return oppositeNode; 406 } 407 408 return null; 409 410 } 411 412 /** 413 * 414 * @param way 415 * @param nodeInDirectionOfTravel 416 * @return 417 */ 418 private List<PTWay> findNextPTWaysInDirectionOfTravel(PTWay currentWay, Node nextNodeInDirectionOfTravel) { 419 420 List<PTWay> nextPtways = new ArrayList<>(); 421 422 List<PTWay> ptways = manager.getPTWays(); 423 424 for (PTWay ptway : ptways) { 425 426 if (ptway != currentWay) { 427 Node[] endNodes = ptway.getEndNodes(); 428 if (endNodes[0] == nextNodeInDirectionOfTravel || endNodes[1] == nextNodeInDirectionOfTravel) { 429 nextPtways.add(ptway); 430 } 431 } 432 } 433 434 return nextPtways; 435 436 } 437 438 protected static Command fixError(TestError testError) { 439 440 // FIXME 441 442 return null; 443 } 444 194 445 }
Note:
See TracChangeset
for help on using the changeset viewer.