Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTRouteDataManager.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTRouteDataManager.java	(revision 32706)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTRouteDataManager.java	(revision 32707)
@@ -5,4 +5,5 @@
 
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
@@ -181,4 +182,12 @@
 		return this.failedMembers;
 	}
+	
+	/**
+	 * Returns the route relation for which this manager was created:
+	 * @return
+	 */
+	public Relation getRelation() {
+		return this.relation;
+	}
 
 	/**
@@ -218,3 +227,164 @@
 		return null;
 	}
+
+	/**
+	 * Returns all PTWays of this route that contain the given way.
+	 * 
+	 * @param way
+	 * @return
+	 */
+	public List<PTWay> findPTWaysThatContain(Way way) {
+
+		List<PTWay> ptwaysThatContain = new ArrayList<>();
+		for (PTWay ptway : ptways) {
+			if (ptway.getWays().contains(way)) {
+				ptwaysThatContain.add(ptway);
+			}
+		}
+		return ptwaysThatContain;
+	}
+
+	/**
+	 * Returns all PTWays of this route that contain the given node as their
+	 * first or last node.
+	 * 
+	 * @return
+	 */
+	public List<PTWay> findPTWaysThatContainAsEndNode(Node node) {
+
+		List<PTWay> ptwaysThatContain = new ArrayList<>();
+		for (PTWay ptway : ptways) {
+			List<Way> ways = ptway.getWays();
+			if (ways.get(0).firstNode() == node || ways.get(0).lastNode() == node
+					|| ways.get(ways.size() - 1).firstNode() == node || ways.get(ways.size() - 1).lastNode() == node) {
+				ptwaysThatContain.add(ptway);
+			}
+		}
+		return ptwaysThatContain;
+
+	}
+
+	/**
+	 * Checks if at most one PTWay of this route refers to the given node
+	 * 
+	 * @param node
+	 * @return
+	 */
+	public boolean isDeadendNode(Node node) {
+
+		List<PTWay> referringPtways = this.findPTWaysThatContainAsEndNode(node);
+		if (referringPtways.size() <= 1) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Returns the PTWay which comes directly after the given ptway according to
+	 * the existing route member sorting
+	 * 
+	 * @param ptway
+	 * @return
+	 */
+	public PTWay getNextPTWay(PTWay ptway) {
+
+		for (int i = 0; i < ptways.size() - 1; i++) {
+			if (ptways.get(i) == ptway) {
+				return ptways.get(i + 1);
+			}
+		}
+		return null;
+
+	}
+
+	/**
+	 * Returns the PTWay which comes directly before the given ptway according
+	 * to the existing route member sorting
+	 * 
+	 * @param ptway
+	 * @return
+	 */
+	public PTWay getPreviousPTWay(PTWay ptway) {
+
+		for (int i = 1; i < ptways.size(); i++) {
+			if (ptways.get(i) == ptway) {
+				return ptways.get(i - 1);
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns a sequence of PTWays that are between the start way and the end
+	 * way. The resulting list includes the start and end PTWays.
+	 * 
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public List<PTWay> getPTWaysBetween(Way start, Way end) {
+		
+		List<Integer> potentialStartIndices = new ArrayList<>();
+		List<Integer> potentialEndIndices = new ArrayList<>();
+		
+		for (int i = 0; i < ptways.size(); i++) {
+			if (ptways.get(i).getWays().contains(start)) {
+				potentialStartIndices.add(i);
+			}
+			if (ptways.get(i).getWays().contains(end)) {
+				potentialEndIndices.add(i);
+			}
+		}
+		
+		List<int[]> pairList = new ArrayList<>();
+		for (Integer potentialStartIndex: potentialStartIndices) {
+			for (Integer potentialEndIndex: potentialEndIndices) {
+				if (potentialStartIndex <= potentialEndIndex) {
+					int[] pair = {potentialStartIndex, potentialEndIndex};
+					pairList.add(pair);
+				}
+			}
+		}
+		
+		int minDifference = Integer.MAX_VALUE;
+		int[] mostSuitablePair = {0, 0};
+		for (int[] pair: pairList) {
+			int diff = pair[1] - pair[0];
+			if (diff < minDifference) {
+				minDifference = diff;
+				mostSuitablePair = pair;
+			}
+		}
+		
+		List<PTWay> result = new ArrayList<>();
+		for (int i = mostSuitablePair[0]; i <= mostSuitablePair[1]; i++) {
+			result.add(ptways.get(i));
+		}
+		return result;
+	}
+	
+	/**
+	 * Returns the common Node of two PTWays or null if there is no common Node
+	 * @param way1
+	 * @param way2
+	 * @return
+	 */
+	public Node getCommonNode(PTWay way1, PTWay way2) {
+		
+		List<Way> wayList1 = way1.getWays();
+		List<Way> wayList2 = way2.getWays();
+		
+		for (int i = 0; i < wayList1.size(); i++) {
+			for (int j = 0; j < wayList2.size(); j++) {
+				if (wayList1.get(i).firstNode() == wayList2.get(j).firstNode() || wayList1.get(i).firstNode() == wayList2.get(j).lastNode()) {
+					return wayList1.get(i).firstNode();
+				}
+				if (wayList1.get(i).lastNode() == wayList2.get(j).firstNode() || wayList1.get(i).lastNode() == wayList2.get(j).lastNode()) {
+					return wayList1.get(i).lastNode();
+				}
+			}
+		}
+		return null;
+	}
+
 }
Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTRouteSegment.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTRouteSegment.java	(revision 32706)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTRouteSegment.java	(revision 32707)
@@ -27,4 +27,10 @@
 	}
 	
+	public PTRouteSegment(PTStop firstStop, PTStop lastStop) {
+		this.firstStop = firstStop;
+		this.lastStop = lastStop;
+		this.ptways = new ArrayList<>();
+	}
+	
 	public List<PTWay> getPTWays() {
 		return this.ptways;
Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTWay.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTWay.java	(revision 32706)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTWay.java	(revision 32707)
@@ -4,4 +4,5 @@
 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;
@@ -63,5 +64,4 @@
 		return this.ways;
 	}
-	
 
 	/**
@@ -74,7 +74,8 @@
 		return false;
 	}
-	
+
 	/**
-	 * Determines if this PTWay is modeled by an OsmPrimitieType.RELATION (i.e. this is a nested relation)
+	 * Determines if this PTWay is modeled by an OsmPrimitieType.RELATION (i.e.
+	 * this is a nested relation)
 	 */
 	public boolean isRelation() {
@@ -84,5 +85,37 @@
 		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
+	 */
+	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;
+	}
 
 }
Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/utils/StopToWayAssigner.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/utils/StopToWayAssigner.java	(revision 32706)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/utils/StopToWayAssigner.java	(revision 32707)
@@ -4,4 +4,5 @@
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -30,5 +31,5 @@
 
 	/* contains assigned stops */
-	private static HashMap<PTStop, PTWay> stopToWay = new HashMap<>();
+	public static HashMap<PTStop, List<Way>> stopToWay = new HashMap<>();
 
 	/*
@@ -36,8 +37,13 @@
 	 * created
 	 */
-	private List<PTWay> ptways;
+	private HashSet<Way> ways;
+
+	/* route relation for which this StopToWayAssigner was created */
 
 	public StopToWayAssigner(List<PTWay> ptways) {
-		this.ptways = ptways;
+		ways = new HashSet<Way>();
+		for (PTWay ptway: ptways) {
+			ways.addAll(ptway.getWays());
+		}
 	}
 
@@ -48,17 +54,24 @@
 	 * @return
 	 */
-	public PTWay get(PTStop stop) {
+	public Way get(PTStop stop) {
 
 		// 1) Search if this stop has already been assigned:
 		if (stopToWay.containsKey(stop)) {
-			return stopToWay.get(stop);
+			List<Way> assignedWays = stopToWay.get(stop);
+			for (Way assignedWay: assignedWays) {
+				if (this.ways.contains(assignedWay)) {
+					return assignedWay;
+				}
+			}
 		}
 
 		// 2) Search if the stop has a stop position:
-		PTWay ptwayOfStopPosition = findPtwayForNode(stop.getStopPosition());
-		if (ptwayOfStopPosition != null) {
-			stopToWay.put(stop, ptwayOfStopPosition);
-			return ptwayOfStopPosition;
-		}
+		Way wayOfStopPosition = findWayForNode(stop.getStopPosition());
+		if (wayOfStopPosition != null) {
+			addAssignedWayToMap(stop, wayOfStopPosition);
+			return wayOfStopPosition;
+		}
+
+		// TODO: search if a stop position is in the vicinity of a platform
 
 		// 3) Search if the stop has a stop_area:
@@ -75,8 +88,8 @@
 				for (RelationMember rm : parentRelation.getMembers()) {
 					if (rm.getMember().hasTag("public_transport", "stop_position")) {
-						PTWay rmPtway = this.findPtwayForNode(rm.getNode());
-						if (rmPtway != null) {
-							stopToWay.put(stop, rmPtway);
-							return rmPtway;
+						Way rmWay = this.findWayForNode(rm.getNode());
+						if (rmWay != null) {
+							addAssignedWayToMap(stop, rmWay);
+							return rmWay;
 						}
 					}
@@ -89,7 +102,7 @@
 		while (searchRadius < 0.005) {
 
-			PTWay foundWay = this.findNearestWayInRadius(stop.getPlatform(), searchRadius);
+			Way foundWay = this.findNearestWayInRadius(stop.getPlatform(), searchRadius);
 			if (foundWay != null) {
-				stopToWay.put(stop, foundWay);
+				addAssignedWayToMap(stop, foundWay);
 				return foundWay;
 			}
@@ -97,5 +110,5 @@
 			foundWay = this.findNearestWayInRadius(stop.getStopPosition(), searchRadius);
 			if (foundWay != null) {
-				stopToWay.put(stop, foundWay);
+				addAssignedWayToMap(stop, foundWay);
 				return foundWay;
 			}
@@ -113,5 +126,5 @@
 	 * @return
 	 */
-	private PTWay findPtwayForNode(Node stopPosition) {
+	private Way findWayForNode(Node stopPosition) {
 
 		if (stopPosition == null) {
@@ -124,8 +137,6 @@
 			if (referredPrimitive.getType().equals(OsmPrimitiveType.WAY)) {
 				Way referredWay = (Way) referredPrimitive;
-				for (PTWay ptway : ptways) {
-					if (ptway.getWays().contains(referredWay)) {
-						return ptway;
-					}
+				if (this.ways.contains(referredWay)) {
+					return referredWay;
 				}
 			}
@@ -144,5 +155,5 @@
 	 * @return
 	 */
-	private PTWay findNearestWayInRadius(OsmPrimitive platform, double searchRadius) {
+	private Way findNearestWayInRadius(OsmPrimitive platform, double searchRadius) {
 
 		if (platform == null) {
@@ -157,5 +168,5 @@
 		BBox platformBBox = new BBox(ax, ay, bx, by);
 
-		List<Way> potentialWays = new ArrayList<>();
+		Set<Way> potentialWays = new HashSet<>();
 
 		Collection<Node> allNodes = platform.getDataSet().getNodes();
@@ -166,8 +177,6 @@
 					if (referrer.getType().equals(OsmPrimitiveType.WAY)) {
 						Way referrerWay = (Way) referrer;
-						for (PTWay ptway : this.ptways) {
-							if (ptway.getWays().contains(referrerWay)) {
-								potentialWays.add(referrerWay);
-							}
+						if (this.ways.contains(referrerWay)) {
+							potentialWays.add(referrerWay);
 						}
 					}
@@ -176,5 +185,5 @@
 			}
 		}
-		
+
 		Node platformNode = null;
 		if (platform.getType().equals(OsmPrimitiveType.NODE)) {
@@ -185,6 +194,6 @@
 		Way nearestWay = null;
 		Double minDistance = Double.MAX_VALUE;
-		for (Way potentialWay: potentialWays) {
-			double distance = this.calculateMinDistance(platformNode, potentialWay);
+		for (Way potentialWay : potentialWays) {
+			double distance = this.calculateMinDistanceToSegment(platformNode, potentialWay);
 			if (distance < minDistance) {
 				minDistance = distance;
@@ -193,27 +202,23 @@
 		}
 
-		for (PTWay ptway: this.ptways) {
-			if (ptway.getWays().contains(nearestWay)) {
-				return ptway;
-			}
-		}
-		
-		return null;
+		return nearestWay;
 	}
 
 	/**
 	 * Calculates the minimum distance between a node and a way
+	 * 
 	 * @param node
 	 * @param way
 	 * @return
 	 */
-	private double calculateMinDistance(Node node, Way way) {
+	private double calculateMinDistanceToSegment(Node node, Way way) {
 
 		double minDistance = Double.MAX_VALUE;
 
 		List<Pair<Node, Node>> waySegments = way.getNodePairs(false);
+
 		for (Pair<Node, Node> waySegment : waySegments) {
 			if (waySegment.a != node && waySegment.b != node) {
-				double distanceToLine = this.calculateDistance(node, waySegment);
+				double distanceToLine = this.calculateDistanceToSegment(node, waySegment);
 				if (distanceToLine < minDistance) {
 					minDistance = distanceToLine;
@@ -227,6 +232,38 @@
 
 	/**
-	 * // * Calculates the distance from point to segment using formulas for
-	 * triangle area.
+	 * Calculates the distance from point to segment and differentiates between
+	 * acute, right and obtuse triangles. If a triangle is acute or right, the
+	 * distance to segment is calculated as distance from point to line. If the
+	 * triangle is obtuse, the distance is calculated as the distance to the
+	 * nearest vertex of the segment.
+	 * 
+	 * @param node
+	 * @param segment
+	 * @return
+	 */
+	private double calculateDistanceToSegment(Node node, Pair<Node, Node> segment) {
+
+		if (node == segment.a || node == segment.b) {
+			return 0.0;
+		}
+
+		double lengthA = node.getCoor().distance(segment.a.getCoor());
+		double lengthB = node.getCoor().distance(segment.b.getCoor());
+		double lengthC = segment.a.getCoor().distance(segment.b.getCoor());
+
+		if (isObtuse(lengthC, lengthB, lengthA)) {
+			return lengthB;
+		}
+
+		if (isObtuse(lengthA, lengthC, lengthB)) {
+			return lengthA;
+		}
+
+		return calculateDistanceToLine(node, segment);
+	}
+
+	/**
+	 * Calculates the distance from point to line using formulas for triangle
+	 * area. Does not differentiate between acute, right and obtuse triangles
 	 * 
 	 * @param node
@@ -234,5 +271,5 @@
 	 * @return
 	 */
-	private double calculateDistance(Node node, Pair<Node, Node> segment) {
+	private double calculateDistanceToLine(Node node, Pair<Node, Node> segment) {
 
 		/*
@@ -257,4 +294,49 @@
 
 	/**
+	 * Checks if the angle opposite of the edge c is obtuse. Uses the cosine
+	 * theorem
+	 * 
+	 * @param lengthA
+	 * @param lengthB
+	 * @param lengthC
+	 *            the triangle edge which is testes
+	 * @return true if the angle opposite of te edge c is obtuse
+	 */
+	private boolean isObtuse(double lengthA, double lengthB, double lengthC) {
+
+		/*-
+		 * Law of cosines:
+		 * c^2 = a^2 + b^2 - 2abcos
+		 * if c^2 = a^2 + b^2, it is a right triangle
+		 * if c^2 < a^2 + b^2, it is an acute triangle
+		 * if c^2 > a^2 + b^2, it is an obtuse triangle
+		 */
+
+		if (lengthC * lengthC > lengthA * lengthA + lengthB * lengthB) {
+			return true;
+		}
+
+		return false;
+	}
+
+	/**
+	 * Adds the given way to the map of assigned ways. Assumes that the given
+	 * way is not contained in the map.
+	 * 
+	 * @param stop
+	 * @param way
+	 */
+	private void addAssignedWayToMap(PTStop stop, Way way) {
+		if (stopToWay.containsKey(stop)) {
+			List<Way> assignedWays = stopToWay.get(stop);
+			assignedWays.add(way);
+		} else {
+			List<Way> assignedWays = new ArrayList<Way>();
+			assignedWays.add(way);
+			stopToWay.put(stop, assignedWays);
+		}
+	}
+
+	/**
 	 * May be needed if the correspondence between stops and ways has changed
 	 * significantly
Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/PTAssistantValidatorTest.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/PTAssistantValidatorTest.java	(revision 32706)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/PTAssistantValidatorTest.java	(revision 32707)
@@ -15,4 +15,5 @@
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.validation.Severity;
 import org.openstreetmap.josm.data.validation.Test;
@@ -20,8 +21,13 @@
 import org.openstreetmap.josm.plugins.pt_assistant.actions.FixTask;
 import org.openstreetmap.josm.plugins.pt_assistant.actions.IncompleteMembersDownloadThread;
+import org.openstreetmap.josm.plugins.pt_assistant.data.PTRouteDataManager;
+import org.openstreetmap.josm.plugins.pt_assistant.data.PTRouteSegment;
+import org.openstreetmap.josm.plugins.pt_assistant.data.PTStop;
+import org.openstreetmap.josm.plugins.pt_assistant.data.PTWay;
 import org.openstreetmap.josm.plugins.pt_assistant.gui.IncompleteMembersDownloadDialog;
 import org.openstreetmap.josm.plugins.pt_assistant.gui.PTAssistantLayer;
 import org.openstreetmap.josm.plugins.pt_assistant.gui.ProceedDialog;
 import org.openstreetmap.josm.plugins.pt_assistant.utils.RouteUtils;
+import org.openstreetmap.josm.plugins.pt_assistant.utils.StopToWayAssigner;
 
 public class PTAssistantValidatorTest extends Test {
@@ -36,4 +42,7 @@
 	public static final int ERROR_CODE_SOLITARY_STOP_POSITION = 3751;
 	public static final int ERROR_CODE_PLATFORM_PART_OF_HIGHWAY = 3752;
+	public static final int ERROR_CODE_STOP_NOT_SERVED = 3753;
+	public static final int ERROR_CODE_STOP_BY_STOP = 3754;
+
 
 	private PTAssistantLayer layer;
@@ -280,6 +289,6 @@
 		if (!routeChecker.getHasGap()) {
 			// Variant 1
-			// TODO: add the segments of this route to the list correct route
-			// segments
+//			storeCorrectRouteSegments(r);
+
 		}
 
@@ -302,8 +311,28 @@
 		segmentChecker.performFirstStopTest();
 		segmentChecker.performLastStopTest();
-
-		// TODO: perform segment test
+		segmentChecker.performStopByStopTest();
+
 		this.errors.addAll(segmentChecker.getErrors());
-		// performDummyTest(r);
+	}
+
+	/**
+	 * Creates the PTRouteSegments of a route that has been found correct and stores them in the list of correct route segments
+	 * @param r route relation
+	 */
+	@SuppressWarnings("unused")
+	private void storeCorrectRouteSegments(Relation r) {
+		PTRouteDataManager manager = new PTRouteDataManager(r);
+		StopToWayAssigner assigner = new StopToWayAssigner(manager.getPTWays());
+		if (manager.getPTStops().size() > 1) {
+			for (int i = 1; i < manager.getPTStops().size(); i++) {
+				PTStop segmentStartStop = manager.getPTStops().get(i-1);
+				PTStop segmentEndStop = manager.getPTStops().get(i);
+				Way segmentStartWay = assigner.get(segmentStartStop);
+				Way segmentEndWay = assigner.get(segmentEndStop);
+				List<PTWay> waysBetweenStops = manager.getPTWaysBetween(segmentStartWay, segmentEndWay);
+				PTRouteSegment routeSegment = new PTRouteSegment(segmentStartStop, segmentEndStop, waysBetweenStops);
+				SegmentChecker.addCorrectSegment(routeSegment);
+			}
+		}
 	}
 
@@ -340,5 +369,6 @@
 		}
 
-		if (testError.getCode() == ERROR_CODE_SOLITARY_STOP_POSITION || testError.getCode() == ERROR_CODE_PLATFORM_PART_OF_HIGHWAY) {
+		if (testError.getCode() == ERROR_CODE_SOLITARY_STOP_POSITION
+				|| testError.getCode() == ERROR_CODE_PLATFORM_PART_OF_HIGHWAY) {
 			commands.add(NodeChecker.fixError(testError));
 		}
Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/SegmentChecker.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/SegmentChecker.java	(revision 32706)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/SegmentChecker.java	(revision 32707)
@@ -6,4 +6,6 @@
 import java.util.List;
 
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -30,5 +32,4 @@
 
 	/* PTRouteSegments that have been validated and are correct */
-	@SuppressWarnings("unused")
 	private static List<PTRouteSegment> correctSegments = new ArrayList<PTRouteSegment>();
 
@@ -37,7 +38,12 @@
 
 	/* Assigns PTStops to nearest PTWays and stores that correspondence */
-	@SuppressWarnings("unused")
 	private StopToWayAssigner assigner;
 
+	/*
+	 * Stores reference that shows in which direction the segment checker is
+	 * moving
+	 */
+	private Node firstNodeOfRouteSegmentInDirectionOfTravel;
+
 	public SegmentChecker(Relation relation, Test test) {
 
@@ -45,6 +51,6 @@
 
 		this.manager = new PTRouteDataManager(relation);
-		
-		for (RelationMember rm: manager.getFailedMembers()) {
+
+		for (RelationMember rm : manager.getFailedMembers()) {
 			List<Relation> primitives = new ArrayList<>(1);
 			primitives.add(relation);
@@ -56,8 +62,27 @@
 		}
 
-
-		
 		this.assigner = new StopToWayAssigner(manager.getPTWays());
 
+	}
+
+	/**
+	 * Returns the number of route segments that have been already successfully
+	 * verified
+	 * 
+	 * @return
+	 */
+	public static int getCorrectSegmentCount() {
+		return correctSegments.size();
+	}
+
+	/**
+	 * Adds the given correct segment to the list of correct segments without
+	 * checking its correctness
+	 * 
+	 * @param segment
+	 *            to add to the list of correct segments
+	 */
+	public static void addCorrectSegment(PTRouteSegment segment) {
+		correctSegments.add(segment);
 	}
 
@@ -153,9 +178,4 @@
 	}
 
-	@SuppressWarnings("unused")
-	private void performSegmentTest() {
-		// TODO
-	}
-
 	/**
 	 * Checks if the given node belongs to the ways of this route.
@@ -192,3 +212,234 @@
 	}
 
+	public void performStopByStopTest() {
+
+		if (manager.getPTStopCount() < 2) {
+			return;
+		}
+
+		// Check each route segment:
+		for (int i = 1; i < manager.getPTStopCount(); i++) {
+
+			PTStop startStop = manager.getPTStops().get(i - 1);
+			PTStop endStop = manager.getPTStops().get(i);
+
+			Way startWay = assigner.get(startStop);
+			Way endWay = assigner.get(endStop);
+			if (startWay == null) {
+				this.firstNodeOfRouteSegmentInDirectionOfTravel = null;
+				continue;
+			}
+			if (endWay == null) {
+				this.firstNodeOfRouteSegmentInDirectionOfTravel = null;
+				continue;
+			}
+			// FIXME: throw error if cannot find the corresponding way (which
+			// means that the stop is too far away from way)
+			List<PTWay> segmentWays = manager.getPTWaysBetween(startWay, endWay);
+
+			if (this.firstNodeOfRouteSegmentInDirectionOfTravel == null) {
+				// if we are at the beginning of the route or after a gap /
+				// error:
+
+				this.firstNodeOfRouteSegmentInDirectionOfTravel = findFirstNodeOfRouteSegmentInDirectionOfTravel(
+						segmentWays.get(0));
+				if (this.firstNodeOfRouteSegmentInDirectionOfTravel == null) {
+					// TODO: throw error
+					continue;
+				}
+			}
+
+			boolean sortingCorrect = existingWaySortingIsCorrect(segmentWays.get(0),
+					this.firstNodeOfRouteSegmentInDirectionOfTravel, segmentWays.get(segmentWays.size() - 1));
+			if (sortingCorrect) {
+				PTRouteSegment routeSegment = new PTRouteSegment(startStop, endStop, segmentWays);
+				correctSegments.add(routeSegment);
+			}
+		}
+
+	}
+
+	private Node findFirstNodeOfRouteSegmentInDirectionOfTravel(PTWay startWay) {
+
+		// 1) at first check if one of the first or last node of the first ptway
+		// is a deadend node:
+		Node[] startWayEndnodes = startWay.getEndNodes();
+		if (isDeadendNode(startWayEndnodes[0])) {
+			return startWayEndnodes[0];
+		}
+		if (isDeadendNode(startWayEndnodes[1])) {
+			return startWayEndnodes[1];
+		}
+
+		// 2) failing that, check which node this startWay shares with the
+		// following way:
+		PTWay nextWay = manager.getNextPTWay(startWay);
+		if (nextWay == null) {
+			return null;
+		}
+		Node[] nextWayEndnodes = nextWay.getEndNodes();
+		if (startWayEndnodes[0] == nextWayEndnodes[0] || startWayEndnodes[0] == nextWayEndnodes[1]) {
+			return startWayEndnodes[1];
+		}
+		if (startWayEndnodes[1] == nextWayEndnodes[0] || startWayEndnodes[1] == nextWayEndnodes[1]) {
+			return startWayEndnodes[0];
+		}
+
+		return null;
+
+	}
+
+	private boolean isDeadendNode(Node node) {
+		int count = 0;
+		for (PTWay ptway : manager.getPTWays()) {
+			List<Way> ways = ptway.getWays();
+			for (Way way : ways) {
+				if (way.firstNode() == node || way.lastNode() == node) {
+					count++;
+				}
+			}
+		}
+		return count == 1;
+	}
+
+	/**
+	 * Finds the deadend node closest to the given node represented by its
+	 * coordinates
+	 * 
+	 * @param coord
+	 *            coordinates of the givenn node
+	 * @param deadendNodes
+	 * @return the closest deadend node
+	 */
+	@SuppressWarnings("unused")
+	private Node findClosestDeadendNode(LatLon coord, List<Node> deadendNodes) {
+
+		Node closestDeadendNode = null;
+		double minSqDistance = Double.MAX_VALUE;
+		for (Node deadendNode : deadendNodes) {
+			double distanceSq = coord.distanceSq(deadendNode.getCoor());
+			if (distanceSq < minSqDistance) {
+				minSqDistance = distanceSq;
+				closestDeadendNode = deadendNode;
+			}
+		}
+		return closestDeadendNode;
+
+	}
+
+	private boolean existingWaySortingIsCorrect(PTWay start, Node startWayPreviousNodeInDirectionOfTravel, PTWay end) {
+
+		if (start == end) {
+			// if both PTStops are on the same PTWay
+			return true;
+		}
+
+		PTWay current = start;
+
+		while (!current.equals(end)) {
+			// "equals" is used here instead of "==" because when the same way
+			// is passed multiple times by the bus, the algorithm should stop no
+			// matter which of the geometrically equal PTWays it finds
+
+			// find the next node in direction of travel (which is part of the
+			// PTWay start):
+			firstNodeOfRouteSegmentInDirectionOfTravel = getOppositeEndNode(current,
+					firstNodeOfRouteSegmentInDirectionOfTravel);
+
+			List<PTWay> nextWaysInDirectionOfTravel = this.findNextPTWaysInDirectionOfTravel(current,
+					firstNodeOfRouteSegmentInDirectionOfTravel);
+	
+			PTWay nextPTWayAccortingToExistingSorting = manager.getNextPTWay(current);
+			if (!nextWaysInDirectionOfTravel.contains(nextPTWayAccortingToExistingSorting)) {
+				List<Relation> primitives = new ArrayList<>(1);
+				primitives.add(relation);
+				List<OsmPrimitive> highlighted = new ArrayList<>();
+
+				highlighted.addAll(current.getWays());
+				highlighted.add(firstNodeOfRouteSegmentInDirectionOfTravel);
+
+				TestError e = new TestError(this.test, Severity.WARNING, tr("PT: Problem in the route segment"),
+						PTAssistantValidatorTest.ERROR_CODE_STOP_BY_STOP, primitives, highlighted);
+				this.errors.add(e);
+				this.firstNodeOfRouteSegmentInDirectionOfTravel = null;
+				return false;
+			}
+
+			current = nextPTWayAccortingToExistingSorting;
+
+		}
+
+		return true;
+	}
+
+	private Node getOppositeEndNode(Way way, Node node) {
+
+		if (node == way.firstNode()) {
+			return way.lastNode();
+		}
+
+		if (node == way.lastNode()) {
+			return way.firstNode();
+		}
+
+		return null;
+	}
+
+	private Node getOppositeEndNode(PTWay ptway, Node node) {
+		if (ptway.isWay()) {
+			return getOppositeEndNode(ptway.getWays().get(0), node);
+		}
+
+		Way firstWay = ptway.getWays().get(0);
+		Way lastWay = ptway.getWays().get(ptway.getWays().size() - 1);
+		Node oppositeNode = node;
+		if (firstWay.firstNode() == node || firstWay.lastNode() == node) {
+			for (int i = 0; i < ptway.getWays().size(); i++) {
+				oppositeNode = getOppositeEndNode(ptway.getWays().get(i), oppositeNode);
+			}
+			return oppositeNode;
+		} else if (lastWay.firstNode() == node || lastWay.lastNode() == node) {
+			for (int i = ptway.getWays().size() - 1; i >= 0; i--) {
+				oppositeNode = getOppositeEndNode(ptway.getWays().get(i), oppositeNode);
+			}
+			return oppositeNode;
+		}
+
+		return null;
+
+	}
+
+	/**
+	 * 
+	 * @param way
+	 * @param nodeInDirectionOfTravel
+	 * @return
+	 */
+	private List<PTWay> findNextPTWaysInDirectionOfTravel(PTWay currentWay, Node nextNodeInDirectionOfTravel) {
+
+		List<PTWay> nextPtways = new ArrayList<>();
+
+		List<PTWay> ptways = manager.getPTWays();
+
+		for (PTWay ptway : ptways) {
+
+			if (ptway != currentWay) {
+				Node[] endNodes = ptway.getEndNodes();
+				if (endNodes[0] == nextNodeInDirectionOfTravel || endNodes[1] == nextNodeInDirectionOfTravel) {
+					nextPtways.add(ptway);
+				}
+			}
+		}
+
+		return nextPtways;
+
+	}
+
+	protected static Command fixError(TestError testError) {
+
+		// FIXME
+
+		return null;
+	}
+
 }
Index: /applications/editors/josm/plugins/pt_assistant/test/unit/org/openstreetmap/josm/plugins/pt_assistant/AbstractTest.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/test/unit/org/openstreetmap/josm/plugins/pt_assistant/AbstractTest.java	(revision 32706)
+++ /applications/editors/josm/plugins/pt_assistant/test/unit/org/openstreetmap/josm/plugins/pt_assistant/AbstractTest.java	(revision 32707)
@@ -46,4 +46,6 @@
  
  public static final String PATH_TO_SOLITARY_STOP_POSITION = "test/data/solitary-stop-position.osm";
+ 
+ public static final String PATH_TO_SEGMENT_TEST = "test/data/segment-test.osm";
 
   /**
Index: /applications/editors/josm/plugins/pt_assistant/test/unit/org/openstreetmap/josm/plugins/pt_assistant/data/StopToWayAssignerTest.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/test/unit/org/openstreetmap/josm/plugins/pt_assistant/data/StopToWayAssignerTest.java	(revision 32706)
+++ /applications/editors/josm/plugins/pt_assistant/test/unit/org/openstreetmap/josm/plugins/pt_assistant/data/StopToWayAssignerTest.java	(revision 32707)
@@ -34,24 +34,22 @@
 		// test with a [correct] stop_position:
 		PTStop ptstop1 = manager.getPTStop(447358573l);
-		PTWay ptway1 = assigner.get(ptstop1);
-		Way way1 = ptway1.getWays().get(0);
+//		PTWay ptway1 = assigner.get(ptstop1);
+//		Way way1 = ptway1.getWays().get(0);
+		Way way1 = assigner.get(ptstop1);
 		assertEquals(way1.getId(), 26956744l);
 		
 		// test with a [wrong] stop_position:
 		PTStop ptstop2 = manager.getPTStop(427562058l);
-		PTWay ptway2 = assigner.get(ptstop2);
-		Way way2 = ptway2.getWays().get(0);
+		Way way2 = assigner.get(ptstop2);
 		assertEquals(way2.getId(), 46349880l);
 		
 		// test with a stop_area:
 		PTStop ptstop3 = manager.getPTStop(2987217064l);
-		PTWay ptway3 = assigner.get(ptstop3);
-		Way way3 = ptway3.getWays().get(0);
+		Way way3 = assigner.get(ptstop3);
 		assertEquals(way3.getId(), 7045925l);
 		
 		// test with a platform without a stop_area:
 		PTStop ptstop4 = manager.getPTStop(3327206909l);
-		PTWay ptway4 = assigner.get(ptstop4);
-		Way way4 = ptway4.getWays().get(0);
+		Way way4 = assigner.get(ptstop4);
 		assertEquals(way4.getId(), 120277227l);
 		
