// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.pt_assistant.data;
import java.util.ArrayList;
import java.util.List;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
import org.openstreetmap.josm.data.osm.RelationMember;
import org.openstreetmap.josm.data.osm.Way;
/**
* Representation of PTWays, which can be of OsmPrimitiveType Way or Relation
*
* @author darya
*
*/
public class PTWay extends RelationMember {
/*
* Ways that belong to this PTWay. If the corresponding relation member is
* OsmPrimitiveType.WAY, this list size is 1. If the corresponding relation
* member is a nested relation, the list size is >= 1.
*/
private List<Way> ways = new ArrayList<>();
/**
*
* @param other
* the corresponding RelationMember
* @throws IllegalArgumentException
* if the given relation member cannot be a PTWay due to its
* OsmPrimitiveType and/or role.
*/
public PTWay(RelationMember other) throws IllegalArgumentException {
super(other);
if (other.getType().equals(OsmPrimitiveType.WAY)) {
ways.add(other.getWay());
} else if (other.getType().equals(OsmPrimitiveType.RELATION)) {
for (RelationMember rm : other.getRelation().getMembers()) {
if (rm.getType().equals(OsmPrimitiveType.WAY)) {
ways.add(rm.getWay());
} else {
throw new IllegalArgumentException(
"A route relation member of OsmPrimitiveType.RELATION can only have ways as members");
}
}
} else {
// the RelationMember other cannot be a OsmPrimitiveType.NODE
throw new IllegalArgumentException("A node cannot be used to model a public transport way");
}
}
/**
* Returns the course of this PTWay. In most cases, this list only has 1
* element. In the case of nested relations in a route, the list can have
* multiple elements.
*
* @return the course of this PTWay
*/
public List<Way> getWays() {
return this.ways;
}
/**
* Determines if this PTWay is modeled by an OsmPrimitiveType.WAY
*/
@Override
public boolean isWay() {
if (this.getType().equals(OsmPrimitiveType.WAY)) {
return true;
}
return false;
}
/**
* Determines if this PTWay is modeled by an OsmPrimitieType.RELATION (i.e.
* this is a nested relation)
*/
@Override
public boolean isRelation() {
if (this.getType().equals(OsmPrimitiveType.RELATION)) {
return true;
}
return false;
}
/**
* Returns the end nodes of this PTWay. If this PTWay is a nested relation,
* the order of the composing ways is assumed to be correct
*
* @return the end nodes of this PTWay
*/
public Node[] getEndNodes() {
Node[] endNodes = new Node[2];
if (this.isWay()) {
endNodes[0] = this.getWay().firstNode();
endNodes[1] = this.getWay().lastNode();
// TODO: if this is a roundabout
} else { // nested relation:
Way firstWay = this.getWays().get(0);
Way secondWay = this.getWays().get(1);
Way prelastWay = this.getWays().get(this.getWays().size() - 2);
Way lastWay = this.getWays().get(this.getWays().size() - 1);
if (firstWay.firstNode() == secondWay.firstNode() || firstWay.firstNode() == secondWay.lastNode()) {
endNodes[0] = firstWay.lastNode();
} else {
endNodes[0] = firstWay.firstNode();
}
if (lastWay.firstNode() == prelastWay.firstNode() || lastWay.firstNode() == prelastWay.lastNode()) {
endNodes[1] = lastWay.lastNode();
} else {
endNodes[1] = lastWay.firstNode();
}
}
return endNodes;
}
/**
* Checks if this PTWay contains an unsplit roundabout (i.e. a way that
* touches itself) among its ways
*
* @return {@code true} if this PTWay contains an unsplit roundabout
*/
public boolean containsUnsplitRoundabout() {
List<Way> ways = this.getWays();
for (Way way : ways) {
if (way.firstNode() == way.lastNode()) {
return true;
}
}
return false;
}
/**
* Checks if the first Way of this PTWay is an unsplit roundabout (i.e. a
* way that touches itself)
*
* @return {@code true} if the first Way of this PTWay is an unsplit roundabout
*/
public boolean startsWithUnsplitRoundabout() {
if (this.ways.get(0).firstNode() == this.ways.get(0).lastNode()) {
return true;
}
return false;
}
/**
* Checks if the last Way of this PTWay is an unsplit roundabout (i.e. a way
* that touches itself)
*
* @return {@code true} if the last Way of this PTWay is an unsplit roundabout
*/
public boolean endsWithUnsplitRoundabout() {
if (this.ways.get(this.ways.size() - 1).firstNode() == this.ways.get(this.ways.size() - 1).lastNode()) {
return true;
}
return false;
}
}