Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/PTAssistantPlugin.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/PTAssistantPlugin.java	(revision 33431)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/PTAssistantPlugin.java	(revision 33432)
@@ -21,4 +21,5 @@
 import org.openstreetmap.josm.plugins.pt_assistant.actions.EditHighlightedRelationsAction;
 import org.openstreetmap.josm.plugins.pt_assistant.actions.RepeatLastFixAction;
+import org.openstreetmap.josm.plugins.pt_assistant.actions.SortPTStopsAction;
 import org.openstreetmap.josm.plugins.pt_assistant.actions.SplitRoundaboutAction;
 import org.openstreetmap.josm.plugins.pt_assistant.data.PTRouteSegment;
@@ -66,4 +67,5 @@
         editHighlightedRelationsMenu = MainMenu.add(Main.main.menu.toolsMenu, editHighlightedRelationsAction);
         MainMenu.add(Main.main.menu.toolsMenu, new SplitRoundaboutAction());
+        MainMenu.add(Main.main.menu.toolsMenu, new SortPTStopsAction());
     }
 
Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/actions/SortPTStopsAction.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/actions/SortPTStopsAction.java	(revision 33432)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/actions/SortPTStopsAction.java	(revision 33432)
@@ -0,0 +1,124 @@
+// License: GPL. For details, see LICENSE file.
+
+package org.openstreetmap.josm.plugins.pt_assistant.actions;
+
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.RelationMember;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.gui.dialogs.relation.sort.RelationSorter;
+import org.openstreetmap.josm.plugins.pt_assistant.data.PTStop;
+import org.openstreetmap.josm.plugins.pt_assistant.utils.RouteUtils;
+import org.openstreetmap.josm.plugins.pt_assistant.utils.StopToWayAssigner;
+import org.openstreetmap.josm.tools.Utils;
+
+public class SortPTStopsAction extends JosmAction {
+
+    private static final long serialVersionUID = 1714879296430852530L;
+    private static final String ACTION_NAME = "Sort PT Stops";
+
+    /**
+     * Creates a new SortPTStopsAction
+     */
+    public SortPTStopsAction() {
+        super(ACTION_NAME, "icons/sortptstops", ACTION_NAME, null, true);
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+
+        Relation rel = (Relation) getLayerManager().getEditDataSet().getSelected().iterator().next();
+        List<RelationMember> members = rel.getMembers();
+
+        for (int i = 0; i < members.size(); i++) {
+            rel.removeMember(0);
+        }
+
+        members = new RelationSorter().sortMembers(members);
+
+        List<RelationMember> stops = new ArrayList<>();
+        List<RelationMember> wayMembers = new ArrayList<>();
+        List<Way> ways = new ArrayList<>();
+        for (int i = 0; i < members.size(); i++) {
+            RelationMember rm = members.get(i);
+            String role = rm.getRole();
+            if (role != null && (role.startsWith("platform") || role.startsWith("stop")))
+                stops.add(rm);
+            else {
+                wayMembers.add(rm);
+                if (rm.getType() == OsmPrimitiveType.WAY)
+                    ways.add(rm.getWay());
+            }
+        }
+
+        Map<String, PTStop> stopsByName = new HashMap<>();
+        stops.forEach(rm -> {
+            String name = getStopName(rm.getMember());
+            if (name != null) {
+                if (!stopsByName.containsKey(name))
+                    stopsByName.put(name, new PTStop(rm));
+                else
+                    stopsByName.get(name).addStopElement(rm);
+            }
+        });
+
+        StopToWayAssigner assigner = new StopToWayAssigner(ways);
+        List<PTStop> ptstops = new ArrayList<>(stopsByName.values());
+        Map<Way, List<PTStop>> wayStop = new HashMap<>();
+        ptstops.forEach(stop -> {
+            Way way = assigner.get(stop);
+            if (!wayStop.containsKey(way))
+                wayStop.put(way, new ArrayList<PTStop>());
+            wayStop.get(way).add(stop);
+        });
+
+        wayMembers.forEach(wm -> {
+            if (wm.getType() != OsmPrimitiveType.WAY)
+                return;
+            List<PTStop> stps = wayStop.get(wm.getWay());
+            if (stps == null)
+                return;
+            stps.forEach(stop -> {
+                if (stop != null) {
+                    if (stop.getStopPositionRM() != null)
+                        rel.addMember(stop.getStopPositionRM());
+                    if (stop.getPlatformRM() != null)
+                        rel.addMember(stop.getPlatformRM());
+                }
+            });
+        });
+
+        wayMembers.forEach(rel::addMember);
+    }
+
+    private static String getStopName(OsmPrimitive p) {
+        for (Relation ref : Utils.filteredCollection(p.getReferrers(), Relation.class)) {
+            if (ref.hasTag("type", "public_transport") && ref.hasTag("public_transport", "stop_area") && ref.getName() != null) {
+                return ref.getName();
+            }
+        }
+        return p.getName();
+    }
+
+    @Override
+    protected void updateEnabledState(
+            Collection<? extends OsmPrimitive> selection) {
+        setEnabled(false);
+        if (selection == null || selection.size() != 1)
+            return;
+        OsmPrimitive selected = selection.iterator().next();
+        if (selected.getType() == OsmPrimitiveType.RELATION &&
+                RouteUtils.isPTRoute((Relation) selected)) {
+            setEnabled(true);
+        }
+    }
+}
Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTStop.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTStop.java	(revision 33431)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTStop.java	(revision 33432)
@@ -27,4 +27,8 @@
     private OsmPrimitive platform = null;
 
+    private RelationMember stopPositionRM = null;
+
+    private RelationMember platformRM = null;
+
     /* the name of this stop */
     private String name = "";
@@ -50,5 +54,5 @@
             this.stopPosition = other.getNode();
             this.name = stopPosition.get("name");
-
+            setStopPositionRM(other);
             // } else if (other.getRole().equals("platform") ||
             // other.getRole().equals("platform_entry_only")
@@ -60,4 +64,5 @@
             this.platform = other.getMember();
             this.name = platform.get("name");
+            setPlatformRM(other);
 
         } else {
@@ -78,5 +83,5 @@
      *         already has an attribute with that role.
      */
-    protected boolean addStopElement(RelationMember member) {
+    public boolean addStopElement(RelationMember member) {
 
         // each element is only allowed once per stop
@@ -88,4 +93,5 @@
             if (member.getType().equals(OsmPrimitiveType.NODE) && stopPosition == null) {
                 this.stopPosition = member.getNode();
+                stopPositionRM = member;
                 return true;
             }
@@ -102,4 +108,5 @@
             if (platform == null) {
                 platform = member.getMember();
+                platformRM = member;
                 return true;
             }
@@ -211,3 +218,19 @@
     }
 
+    public RelationMember getPlatformRM() {
+        return platformRM;
+    }
+
+    public void setPlatformRM(RelationMember platformRM) {
+        this.platformRM = platformRM;
+    }
+
+    public RelationMember getStopPositionRM() {
+        return stopPositionRM;
+    }
+
+    public void setStopPositionRM(RelationMember stopPositionRM) {
+        this.stopPositionRM = stopPositionRM;
+    }
+
 }
Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/utils/RouteUtils.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/utils/RouteUtils.java	(revision 33431)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/utils/RouteUtils.java	(revision 33432)
@@ -19,5 +19,5 @@
 public final class RouteUtils {
 
-    private static final String ptVersionTag = "public_transport:version";
+    private static final String PT_VERSION_TAG = "public_transport:version";
     private RouteUtils() {
         // private constructor for util classes
@@ -39,5 +39,5 @@
         }
 
-        if (!r.hasTag(ptVersionTag, "2")) {
+        if (!r.hasTag(PT_VERSION_TAG, "2")) {
             return false;
         }
@@ -52,9 +52,9 @@
         }
 
-        if (r.get(ptVersionTag) == null) {
+        if (r.get(PT_VERSION_TAG) == null) {
             return true;
         }
 
-        return r.hasTag(ptVersionTag, "1");
+        return r.hasTag(PT_VERSION_TAG, "1");
     }
 
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 33431)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/utils/StopToWayAssigner.java	(revision 33432)
@@ -7,4 +7,5 @@
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
@@ -32,5 +33,5 @@
 
     /* contains assigned stops */
-    public static HashMap<PTStop, List<Way>> stopToWay = new HashMap<>();
+    public static Map<PTStop, List<Way>> stopToWay = new HashMap<>();
 
     /*
@@ -39,6 +40,4 @@
      */
     private HashSet<Way> ways;
-
-    /* route relation for which this StopToWayAssigner was created */
 
     public StopToWayAssigner(List<PTWay> ptways) {
@@ -47,4 +46,9 @@
             ways.addAll(ptway.getWays());
         }
+    }
+
+    public StopToWayAssigner(Collection<Way> ways) {
+        this.ways = new HashSet<>();
+        this.ways.addAll(ways);
     }
 
Index: /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/RouteChecker.java
===================================================================
--- /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/RouteChecker.java	(revision 33431)
+++ /applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/RouteChecker.java	(revision 33432)
@@ -82,4 +82,8 @@
             }
         }
+    }
+
+    public boolean hasGaps(List<RelationMember> waysToCheck) {
+        return countGaps(waysToCheck) > 0;
     }
 
