// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.pt_assistant.data; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.data.osm.BBox; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.data.osm.OsmPrimitiveType; import org.openstreetmap.josm.data.osm.RelationMember; /** * Model a stop with one or two elements (platform and/or stop_position) * * @author darya * */ public class PTStop extends RelationMember { /* stop_position element of this stop */ private Node stopPosition = null; /* platform element of this stop */ private OsmPrimitive platform = null; /* the name of this stop */ private String name = ""; /** * Constructor * * @param other other relation member * @throws IllegalArgumentException * if the given relation member does not fit to the data model * used in the plugin */ public PTStop(RelationMember other) throws IllegalArgumentException { super(other); // if ((other.hasRole("stop") || other.hasRole("stop_entry_only") || // other.hasRole("stop_exit_only")) // && other.getType().equals(OsmPrimitiveType.NODE)) { if (other.getMember().hasTag("public_transport", "stop_position")) { this.stopPosition = other.getNode(); this.name = stopPosition.get("name"); // } else if (other.getRole().equals("platform") || // other.getRole().equals("platform_entry_only") // || other.getRole().equals("platform_exit_only")) { } else if (other.getMember().hasTag("highway", "bus_stop") || other.getMember().hasTag("public_transport", "platform") || other.getMember().hasTag("highway", "platform") || other.getMember().hasTag("railway", "platform")) { this.platform = other.getMember(); this.name = platform.get("name"); } else { throw new IllegalArgumentException( "The RelationMember type does not match its role " + other.getMember().getName()); } } /** * Adds the given element to the stop after a check * * @param member * Element to add * @return true if added successfully, false otherwise. A false value * indicates either that the OsmPrimitiveType of the given * RelationMember does not match its role or that this PTStop * already has an attribute with that role. */ protected boolean addStopElement(RelationMember member) { // each element is only allowed once per stop // add stop position: // if (member.hasRole("stop") || member.hasRole("stop_entry_only") || // member.hasRole("stop_exit_only")) { if (member.getMember().hasTag("public_transport", "stop_position")) { if (member.getType().equals(OsmPrimitiveType.NODE) && stopPosition == null) { this.stopPosition = member.getNode(); return true; } } // add platform: // if (member.getRole().equals("platform") || // member.getRole().equals("platform_entry_only") // || member.getRole().equals("platform_exit_only")) { if (member.getMember().hasTag("highway", "bus_stop") || member.getMember().hasTag("public_transport", "platform") || member.getMember().hasTag("highway", "platform") || member.getMember().hasTag("railway", "platform")) { if (platform == null) { platform = member.getMember(); return true; } } return false; } /** * Returns the stop_position for this PTstop. If the stop_position is not * available directly, the method searches for a stop_area relation * * @return the stop_position for this PTstop */ public Node getStopPosition() { return this.stopPosition; } /** * Returns platform (including platform_entry_only and platform_exit_only) * * @return platform (including platform_entry_only and platform_exit_only) */ public OsmPrimitive getPlatform() { return this.platform; } /** * Returns the name of this stop * @return the name of this stop */ protected String getName() { return this.name; } /** * Sets the stop_position for this stop to the given node * @param newStopPosition the stop_position for this stop to the given node */ public void setStopPosition(Node newStopPosition) { this.stopPosition = newStopPosition; } /** * Finds potential stop_positions of the platform of this PTStop. It only * makes sense to call this method if the stop_position attribute is null. * The stop_positions are potential because they may refer to a different * route, which this method does not check. * * @return List of potential stop_positions for this PTStop */ public List<Node> findPotentialStopPositions() { ArrayList<Node> potentialStopPositions = new ArrayList<>(); if (platform == null) { return potentialStopPositions; } // Look for a stop position within 0.002 degrees (around 100 m) of this // platform: LatLon platformCenter = platform.getBBox().getCenter(); Double ax = platformCenter.getX() - 0.002; Double bx = platformCenter.getX() + 0.002; Double ay = platformCenter.getY() - 0.002; Double by = platformCenter.getY() + 0.002; BBox platformBBox = new BBox(ax, ay, bx, by); Collection<Node> allNodes = platform.getDataSet().getNodes(); for (Node currentNode : allNodes) { if (platformBBox.bounds(currentNode.getBBox()) && currentNode.hasTag("public_transport", "stop_position")) { potentialStopPositions.add(currentNode); } } return potentialStopPositions; } /** * Checks if this stop equals to other by comparing if they have the same * stop_position or a platform * * @param other * PTStop to be compared * @return true if equal, false otherwise */ public boolean equalsStop(PTStop other) { if (other == null) { return false; } if (this.stopPosition != null && (this.stopPosition == other.getStopPosition() || this.stopPosition == other.getPlatform())) { return true; } if (this.platform != null && (this.platform == other.getPlatform() || this.platform == other.getStopPosition())) { return true; } return false; } }