Ignore:
Timestamp:
2016-07-24T04:46:09+02:00 (8 years ago)
Author:
darya
Message:

stop-by-stop test added

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  
    55
    66import org.openstreetmap.josm.data.coor.LatLon;
     7import org.openstreetmap.josm.data.osm.Node;
    78import org.openstreetmap.josm.data.osm.Relation;
    89import org.openstreetmap.josm.data.osm.RelationMember;
     
    181182                return this.failedMembers;
    182183        }
     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        }
    183192
    184193        /**
     
    218227                return null;
    219228        }
     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
    220390}
  • applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTRouteSegment.java

    r32299 r32707  
    2727        }
    2828       
     29        public PTRouteSegment(PTStop firstStop, PTStop lastStop) {
     30                this.firstStop = firstStop;
     31                this.lastStop = lastStop;
     32                this.ptways = new ArrayList<>();
     33        }
     34       
    2935        public List<PTWay> getPTWays() {
    3036                return this.ptways;
  • applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/data/PTWay.java

    r32522 r32707  
    44import java.util.List;
    55
     6import org.openstreetmap.josm.data.osm.Node;
    67import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    78import org.openstreetmap.josm.data.osm.RelationMember;
     
    6364                return this.ways;
    6465        }
    65        
    6666
    6767        /**
     
    7474                return false;
    7575        }
    76        
     76
    7777        /**
    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)
    7980         */
    8081        public boolean isRelation() {
     
    8485                return false;
    8586        }
    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        }
    87120
    88121}
  • applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/utils/StopToWayAssigner.java

    r32656 r32707  
    44import java.util.Collection;
    55import java.util.HashMap;
     6import java.util.HashSet;
    67import java.util.List;
    78import java.util.Set;
     
    3031
    3132        /* contains assigned stops */
    32         private static HashMap<PTStop, PTWay> stopToWay = new HashMap<>();
     33        public static HashMap<PTStop, List<Way>> stopToWay = new HashMap<>();
    3334
    3435        /*
     
    3637         * created
    3738         */
    38         private List<PTWay> ptways;
     39        private HashSet<Way> ways;
     40
     41        /* route relation for which this StopToWayAssigner was created */
    3942
    4043        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                }
    4248        }
    4349
     
    4854         * @return
    4955         */
    50         public PTWay get(PTStop stop) {
     56        public Way get(PTStop stop) {
    5157
    5258                // 1) Search if this stop has already been assigned:
    5359                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                        }
    5566                }
    5667
    5768                // 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
    6376
    6477                // 3) Search if the stop has a stop_area:
     
    7588                                for (RelationMember rm : parentRelation.getMembers()) {
    7689                                        if (rm.getMember().hasTag("public_transport", "stop_position")) {
    77                                                 PTWay rmPtway = this.findPtwayForNode(rm.getNode());
    78                                                 if (rmPtway != null) {
    79                                                         stopToWay.put(stop, rmPtway);
    80                                                         return rmPtway;
     90                                                Way rmWay = this.findWayForNode(rm.getNode());
     91                                                if (rmWay != null) {
     92                                                        addAssignedWayToMap(stop, rmWay);
     93                                                        return rmWay;
    8194                                                }
    8295                                        }
     
    89102                while (searchRadius < 0.005) {
    90103
    91                         PTWay foundWay = this.findNearestWayInRadius(stop.getPlatform(), searchRadius);
     104                        Way foundWay = this.findNearestWayInRadius(stop.getPlatform(), searchRadius);
    92105                        if (foundWay != null) {
    93                                 stopToWay.put(stop, foundWay);
     106                                addAssignedWayToMap(stop, foundWay);
    94107                                return foundWay;
    95108                        }
     
    97110                        foundWay = this.findNearestWayInRadius(stop.getStopPosition(), searchRadius);
    98111                        if (foundWay != null) {
    99                                 stopToWay.put(stop, foundWay);
     112                                addAssignedWayToMap(stop, foundWay);
    100113                                return foundWay;
    101114                        }
     
    113126         * @return
    114127         */
    115         private PTWay findPtwayForNode(Node stopPosition) {
     128        private Way findWayForNode(Node stopPosition) {
    116129
    117130                if (stopPosition == null) {
     
    124137                        if (referredPrimitive.getType().equals(OsmPrimitiveType.WAY)) {
    125138                                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;
    130141                                }
    131142                        }
     
    144155         * @return
    145156         */
    146         private PTWay findNearestWayInRadius(OsmPrimitive platform, double searchRadius) {
     157        private Way findNearestWayInRadius(OsmPrimitive platform, double searchRadius) {
    147158
    148159                if (platform == null) {
     
    157168                BBox platformBBox = new BBox(ax, ay, bx, by);
    158169
    159                 List<Way> potentialWays = new ArrayList<>();
     170                Set<Way> potentialWays = new HashSet<>();
    160171
    161172                Collection<Node> allNodes = platform.getDataSet().getNodes();
     
    166177                                        if (referrer.getType().equals(OsmPrimitiveType.WAY)) {
    167178                                                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);
    172181                                                }
    173182                                        }
     
    176185                        }
    177186                }
    178                
     187
    179188                Node platformNode = null;
    180189                if (platform.getType().equals(OsmPrimitiveType.NODE)) {
     
    185194                Way nearestWay = null;
    186195                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);
    189198                        if (distance < minDistance) {
    190199                                minDistance = distance;
     
    193202                }
    194203
    195                 for (PTWay ptway: this.ptways) {
    196                         if (ptway.getWays().contains(nearestWay)) {
    197                                 return ptway;
    198                         }
    199                 }
    200                
    201                 return null;
     204                return nearestWay;
    202205        }
    203206
    204207        /**
    205208         * Calculates the minimum distance between a node and a way
     209         *
    206210         * @param node
    207211         * @param way
    208212         * @return
    209213         */
    210         private double calculateMinDistance(Node node, Way way) {
     214        private double calculateMinDistanceToSegment(Node node, Way way) {
    211215
    212216                double minDistance = Double.MAX_VALUE;
    213217
    214218                List<Pair<Node, Node>> waySegments = way.getNodePairs(false);
     219
    215220                for (Pair<Node, Node> waySegment : waySegments) {
    216221                        if (waySegment.a != node && waySegment.b != node) {
    217                                 double distanceToLine = this.calculateDistance(node, waySegment);
     222                                double distanceToLine = this.calculateDistanceToSegment(node, waySegment);
    218223                                if (distanceToLine < minDistance) {
    219224                                        minDistance = distanceToLine;
     
    227232
    228233        /**
    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
    231268         *
    232269         * @param node
     
    234271         * @return
    235272         */
    236         private double calculateDistance(Node node, Pair<Node, Node> segment) {
     273        private double calculateDistanceToLine(Node node, Pair<Node, Node> segment) {
    237274
    238275                /*
     
    257294
    258295        /**
     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        /**
    259341         * May be needed if the correspondence between stops and ways has changed
    260342         * significantly
  • applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/PTAssistantValidatorTest.java

    r32650 r32707  
    1515import org.openstreetmap.josm.data.osm.Node;
    1616import org.openstreetmap.josm.data.osm.Relation;
     17import org.openstreetmap.josm.data.osm.Way;
    1718import org.openstreetmap.josm.data.validation.Severity;
    1819import org.openstreetmap.josm.data.validation.Test;
     
    2021import org.openstreetmap.josm.plugins.pt_assistant.actions.FixTask;
    2122import org.openstreetmap.josm.plugins.pt_assistant.actions.IncompleteMembersDownloadThread;
     23import org.openstreetmap.josm.plugins.pt_assistant.data.PTRouteDataManager;
     24import org.openstreetmap.josm.plugins.pt_assistant.data.PTRouteSegment;
     25import org.openstreetmap.josm.plugins.pt_assistant.data.PTStop;
     26import org.openstreetmap.josm.plugins.pt_assistant.data.PTWay;
    2227import org.openstreetmap.josm.plugins.pt_assistant.gui.IncompleteMembersDownloadDialog;
    2328import org.openstreetmap.josm.plugins.pt_assistant.gui.PTAssistantLayer;
    2429import org.openstreetmap.josm.plugins.pt_assistant.gui.ProceedDialog;
    2530import org.openstreetmap.josm.plugins.pt_assistant.utils.RouteUtils;
     31import org.openstreetmap.josm.plugins.pt_assistant.utils.StopToWayAssigner;
    2632
    2733public class PTAssistantValidatorTest extends Test {
     
    3642        public static final int ERROR_CODE_SOLITARY_STOP_POSITION = 3751;
    3743        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
    3847
    3948        private PTAssistantLayer layer;
     
    280289                if (!routeChecker.getHasGap()) {
    281290                        // Variant 1
    282                         // TODO: add the segments of this route to the list correct route
    283                         // segments
     291//                      storeCorrectRouteSegments(r);
     292
    284293                }
    285294
     
    302311                segmentChecker.performFirstStopTest();
    303312                segmentChecker.performLastStopTest();
    304 
    305                 // TODO: perform segment test
     313                segmentChecker.performStopByStopTest();
     314
    306315                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                }
    308337        }
    309338
     
    340369                }
    341370
    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) {
    343373                        commands.add(NodeChecker.fixError(testError));
    344374                }
  • applications/editors/josm/plugins/pt_assistant/src/org/openstreetmap/josm/plugins/pt_assistant/validation/SegmentChecker.java

    r32567 r32707  
    66import java.util.List;
    77
     8import org.openstreetmap.josm.command.Command;
     9import org.openstreetmap.josm.data.coor.LatLon;
    810import org.openstreetmap.josm.data.osm.Node;
    911import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    3032
    3133        /* PTRouteSegments that have been validated and are correct */
    32         @SuppressWarnings("unused")
    3334        private static List<PTRouteSegment> correctSegments = new ArrayList<PTRouteSegment>();
    3435
     
    3738
    3839        /* Assigns PTStops to nearest PTWays and stores that correspondence */
    39         @SuppressWarnings("unused")
    4040        private StopToWayAssigner assigner;
    4141
     42        /*
     43         * Stores reference that shows in which direction the segment checker is
     44         * moving
     45         */
     46        private Node firstNodeOfRouteSegmentInDirectionOfTravel;
     47
    4248        public SegmentChecker(Relation relation, Test test) {
    4349
     
    4551
    4652                this.manager = new PTRouteDataManager(relation);
    47                
    48                 for (RelationMember rm: manager.getFailedMembers()) {
     53
     54                for (RelationMember rm : manager.getFailedMembers()) {
    4955                        List<Relation> primitives = new ArrayList<>(1);
    5056                        primitives.add(relation);
     
    5662                }
    5763
    58 
    59                
    6064                this.assigner = new StopToWayAssigner(manager.getPTWays());
    6165
     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);
    6287        }
    6388
     
    153178        }
    154179
    155         @SuppressWarnings("unused")
    156         private void performSegmentTest() {
    157                 // TODO
    158         }
    159 
    160180        /**
    161181         * Checks if the given node belongs to the ways of this route.
     
    192212        }
    193213
     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
    194445}
Note: See TracChangeset for help on using the changeset viewer.