Ignore:
Timestamp:
2010-10-13T19:05:12+02:00 (14 years ago)
Author:
guggis
Message:

Fixed #5522 - Plug-in turn restriction is adding the wrong part of a splitted "to"-way to the relation
Changed the expression "OSM way", "OSM node", and "OSM relation" to "way", "node", and "relation" respectively. Translators should follow up and fix the translations in Launchpad.

Location:
applications/editors/josm/plugins/turnrestrictions/src/org/openstreetmap/josm/plugins/turnrestrictions
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/turnrestrictions/src/org/openstreetmap/josm/plugins/turnrestrictions/TurnRestrictionBuilder.java

    r23571 r23593  
    11package org.openstreetmap.josm.plugins.turnrestrictions;
     2
     3import static org.openstreetmap.josm.plugins.turnrestrictions.TurnRestrictionBuilder.determineWayJoinOrientation;
     4import static org.openstreetmap.josm.plugins.turnrestrictions.TurnRestrictionBuilder.isEndNode;
     5import static org.openstreetmap.josm.plugins.turnrestrictions.TurnRestrictionBuilder.isStartNode;
    26
    37import java.util.ArrayList;
     
    59import java.util.HashSet;
    610import java.util.List;
     11import java.util.Set;
    712
    813import org.openstreetmap.josm.data.osm.Node;
     
    1217import org.openstreetmap.josm.data.osm.Way;
    1318import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     19import org.openstreetmap.josm.plugins.turnrestrictions.editor.TurnRestrictionLegRole;
    1420import org.openstreetmap.josm.plugins.turnrestrictions.editor.TurnRestrictionType;
    1521import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    2228 */
    2329public class TurnRestrictionBuilder {
     30       
     31        /**
     32         * Replies the angle phi in the polar coordinates (r,phi) representing the first
     33         * segment of the way {@code w}, where w is moved such that the start node of {@code w} is
     34         * in the origin (0,0).
     35         * 
     36         * @param w the way.  Must not be null. At least two nodes required.
     37         * @return phi in the polar coordinates
     38         * @throws IllegalArgumentException thrown if w is null
     39         * @throws IllegalArgumentException thrown if w is too short (at least two nodes required)
     40         */
     41    static public double phi(Way w) throws IllegalArgumentException{
     42        return phi(w, false /* not inverse */);
     43    }
     44   
     45    /**
     46     * <p>Replies the angle phi in the polar coordinates (r,phi) representing the first
     47         * segment of the way {@code w}, where w is moved such that the start node of {@code w} is
     48         * in the origin (0,0).</p>
     49         *
     50         * <p>If {@code doInvert} is true, computes phi for the way in reversed direction.</p>
     51         *
     52         * @param w the way.  Must not be null. At least two nodes required.
     53         * @param doInvert if true, computes phi for the reversed way
     54         * @return phi in the polar coordinates
     55         * @throws IllegalArgumentException thrown if w is null
     56         * @throws IllegalArgumentException thrown if w is too short (at least two nodes required)
     57     */
     58    static public double phi(Way w, boolean doInvert) throws IllegalArgumentException {
     59        CheckParameterUtil.ensureParameterNotNull(w, "w");
     60        if (w.getNodesCount() < 2) {
     61                throw new IllegalArgumentException("can't compute phi for way with less than 2 nodes");
     62        }
     63        List<Node> nodes = w.getNodes();
     64        if (doInvert) Collections.reverse(nodes);
     65        Node n0 = nodes.get(0);
     66        Node n1 = nodes.get(1);
     67       
     68        double x = n1.getCoor().getX() - n0.getCoor().getX();
     69        double y = n1.getCoor().getY() - n0.getCoor().getY();
     70        return Math.atan2(y, x);       
     71    }   
     72
     73    /**
     74     * Replies the unique common node of two ways, or null, if either no
     75     * such node or multiple common nodes exist.
     76     *
     77     * @param w1 the first way
     78     * @param w2 the second way
     79     * @return the common node or null, if w1 is null, or if w2 is null or if
     80     * w1 and w2 don't share exactly one node
     81     */
     82    static public Node getUniqueCommonNode(Way w1, Way w2) throws IllegalArgumentException{
     83        Set<Node> w1Nodes = new HashSet<Node>(w1.getNodes());
     84        w1Nodes.retainAll(w2.getNodes());
     85        if (w1Nodes.size() != 1) return null;
     86        return w1Nodes.iterator().next();
     87    }   
     88       
     89    /**
     90     * Replies true, if {@code n} is the start node of the way {@code w}.
     91     *
     92     * @param w the way. Must not be null.
     93     * @param n the node. Must not be null.
     94     * @return true, if {@code n} is the start node of the way {@code w}.
     95     */
     96    static public boolean isStartNode(Way w, Node n) {
     97        if (w.getNodesCount() == 0) return false;
     98        return w.getNode(0).equals(n);
     99    }
     100       
     101    /**
     102     * Replies true, if {@code n} is the end node of the way {@code w}.
     103     *
     104     * @param w the way. Must not be null.
     105     * @param n the node. Must not be null.
     106     * @return true, if {@code n} is the end node of the way {@code w}.
     107     */
     108    static public boolean isEndNode(Way w, Node n){
     109        if (w.getNodesCount() == 0) return false;
     110        return w.getNode(w.getNodesCount()-1).equals(n);
     111    }
     112   
     113    /**
     114     * Replies true, if {@code n} is a node in the way {@code w} but {@code n}
     115     * is neither the start nor the end node.
     116     *
     117     * @param w the way
     118     * @param n the node
     119     * @return true if {@code n} is an "inner" node
     120     */
     121    static public boolean isInnerNode(Way w, Node n){
     122        if (!w.getNodes().contains(n)) return false;
     123        if (isStartNode(w, n)) return false;
     124        if (isEndNode(w, n)) return false;
     125        return true;           
     126    }
     127   
     128    /**
     129     * <p>Replies the angle at which way {@code from} and {@code to} are connected
     130     * at exactly one common node.</p>
     131     *
     132     * <p>If the result is positive, the way {@code from} bends to the right, if it
     133     * is negative, the {@code to} bends to the left.</p>
     134     *
     135     * <p>The two ways must not be null and they must be connected at exactly one
     136     * common node. They must <strong>not intersect</code> at this node.</p>.
     137     *
     138     * @param from the from way
     139     * @param to the to way
     140     * @return the intersection angle
     141     * @throws IllegalArgumentException thrown if the two nodes don't have exactly one common
     142     * node at which they are connected
     143     *
     144     */
     145    static public double interesectionAngle(Way from, Way to) throws IllegalArgumentException {
     146            Node via = getUniqueCommonNode(from, to);
     147            if (via == null)
     148                throw new IllegalArgumentException("the two ways must share exactly one common node"); // no I18n required
     149            if (!isStartNode(from, via) && ! isEndNode(from, via))
     150                throw new IllegalArgumentException("via node must be start or end node of from-way"); // no I18n required
     151            if (!isStartNode(to, via) && ! isEndNode(to, via))
     152                throw new IllegalArgumentException("via node must be start or end node of to-way"); // no I18n required
     153            double phi1 = phi(from, isStartNode(from, via));
     154            double phi2 = phi(to, isEndNode(to, via));         
     155                return phi1 - phi2;
     156    }   
     157       
     158    static public enum RelativeWayJoinOrientation {
     159        LEFT,
     160        RIGHT
     161    }
     162    /**
     163     * <p>Determines the orientation in which two ways {@code from} and {@code to}
     164     * are connected, with respect to the direction of the way {@code from}.</p>
     165     *
     166     * <p>The following preconditions must be met:
     167     *   <ul>
     168     *     <li>{@code from} and {@code to} must not be null</li>
     169     *     <li>they must have exactly one common node <em>n</em> </li>
     170     *     <li><em>n</em> must occur exactly once in {@code from} and {@code to}, i.e. the
     171     *     two ways must not be closed at <em>n</em></li>
     172     *     <li><em>n</em> must be the start or the end node of both ways </li>
     173     *   </ul>
     174     * </p>
     175     *
     176     * <p>Here's a typical configuration:</p>
     177     * <pre>
     178     *          to1             to2
     179     *      -------------> o -------------->
     180     *                     ^
     181     *                     | from
     182     *                     |
     183     * </pre>
     184     *
     185     * <p>Replies null, if the preconditions aren't met and the method fails to
     186     *  determine the join orientation.</p>
     187     *
     188     * @param from the "from"-way
     189     * @param to the "to"-way
     190     * @return the join orientation or null, if the method fails to compute the
     191     * join orientation
     192     */
     193    public static RelativeWayJoinOrientation determineWayJoinOrientation(Way from, Way to){
     194        Node via = getUniqueCommonNode(from, to);
     195        if (via == null) return null;
     196        if (!isConnectingNode(from, to, via)) return null;
     197        // if either w1 or w2 are closed at the via node, we can't determine automatically
     198        // whether the connection at "via" is a "left turn" or a "right turn"
     199        if (isClosedAt(from, via)) return null;
     200        if (isClosedAt(to, via)) return null;
     201       
     202        double phi = interesectionAngle(from, to);     
     203        if (phi >=0 && phi <= Math.PI) {
     204                return RelativeWayJoinOrientation.RIGHT;
     205        } else {
     206                return RelativeWayJoinOrientation.LEFT;
     207        }
     208    }
     209   
     210    /**
     211     * <p>Selects either of the two ways resulting from the split of a way
     212     * in the role {@link TurnRestrictionLegRole#TO TO}.</p>
     213     *
     214     * <p>This methods operates on three ways for which the following
     215     * preconditions must be met:
     216     * <ul>
     217     *   <li>{@code t1} and {@code t2} are connected at a common node <em>n</em></li>
     218     *   <li>{@code from} is also connected to the node <em>n</em>. <em>n</em> occurs
     219     *   exactly once in {@code from} and is either the start or the end node of {@code from}.</li>
     220     * </ul>
     221     * </p>
     222     *
     223     * <p>Here's a typical configuration:</p>
     224     * <pre>
     225     *          to1             to2
     226     *      -------------> o -------------->
     227     *                     ^
     228     *                     | from
     229     *                     |
     230     * </pre>
     231     *
     232     * <p>Depending on {@code restrictionType}, this method either returns {@code to1}
     233     * or {@code to2}. If {@code restrictionType} indicates that our context is a
     234     * "left turn", {@code to1} is replied. If our context is a "right turn", {@code to2}
     235     * is returned.</p>
     236     *
     237     * <p>Replies null, if the expected preconditions aren't met or if we can't infer
     238     * from {@code restrictionType} whether our context is a "left turn" or a "right turn".</p>
     239     *
     240     * @param from the from-way
     241     * @param to1 the first part of the split to-way
     242     * @param to2 the second part of the split to-way
     243     * @param restrictionType the restriction type
     244     * @return either {@code to1}, {@code to2}, or {@code null}.
     245     */
     246    static public Way selectToWayAfterSplit(Way from, Way to1, Way to2, TurnRestrictionType restrictionType){
     247        if (restrictionType == null) return null;
     248        Node cn1 = TurnRestrictionBuilder.getUniqueCommonNode(from, to1);
     249        if (cn1 == null) return null;
     250        Node cn2 = TurnRestrictionBuilder.getUniqueCommonNode(from, to2);
     251        if (cn2 == null) return null;
     252        if (cn1 != cn2) return null;           
     253       
     254        if (! isStartNode(from, cn1) && ! isEndNode(from, cn1)) {
     255                /*
     256                 * the now split to-way still *interesects* the from-way. We
     257                 * can't adjust the split decisions.
     258                 */
     259                return null;
     260        }
     261       
     262        RelativeWayJoinOrientation o1 = determineWayJoinOrientation(from, to1);
     263        RelativeWayJoinOrientation o2 = determineWayJoinOrientation(from, to2);
     264       
     265        switch(restrictionType){
     266        case NO_LEFT_TURN:
     267        case ONLY_LEFT_TURN:
     268                if (RelativeWayJoinOrientation.LEFT.equals(o1)) return to1;
     269                else if (RelativeWayJoinOrientation.LEFT.equals(o2)) return to2;
     270                else return null;
     271               
     272        case NO_RIGHT_TURN:
     273        case ONLY_RIGHT_TURN:
     274                if (RelativeWayJoinOrientation.RIGHT.equals(o1)) return to1;
     275                else if (RelativeWayJoinOrientation.RIGHT.equals(o2)) return to2;
     276                else return null;
     277               
     278        default:
     279                 /*
     280                  * For restriction types like NO_U_TURN, NO_STRAIGHT_ON, etc. we
     281                  * can select a "left" or "right" way after splitting.
     282                  */
     283                return null;
     284        }
     285    }
    24286   
    25287    public TurnRestrictionBuilder(){
     
    74336
    75337    /**
    76      * Replies the unique common node of two ways, or null, if either no
    77      * such node or multiple common nodes exist.
    78      *
    79      * @param w1 the first way
    80      * @param w2 the second way
    81      * @return the common node
    82      */
    83     protected Node getUniqueCommonNode(Way w1, Way w2){
    84         List<Node> w1Nodes = w1.getNodes();
    85         w1Nodes.retainAll(w2.getNodes());
    86         if (w1Nodes.size() != 1) return null;
    87         return w1Nodes.get(0);
    88     }   
    89    
    90     /**
    91      * Replies true, if {@code n} is the start node of the way {@code w}.
    92      *
    93      * @param w the way
    94      * @param n the node
    95      * @return true, if {@code n} is the start node of the way {@code w}.
    96      */
    97     protected boolean isStartNode(Way w, Node n) {
    98         if (w.getNodesCount() == 0) return false;
    99         return w.getNode(0).equals(n);
    100     }
    101    
    102    
    103     /**
    104      * Replies true, if {@code n} is the end node of the way {@code w}.
    105      *
    106      * @param w the way
    107      * @param n the node
    108      * @return true, if {@code n} is the end node of the way {@code w}.
    109      */
    110     protected boolean isEndNode(Way w, Node n){
    111         if (w.getNodesCount() == 0) return false;
    112         return w.getNode(w.getNodesCount()-1).equals(n);
    113     }
    114    
    115     /**
    116338     * <p>Replies true, if the ways {@code w1} and {@code w2} are connected
    117339     * at the node {@code n}.</p>
     
    125347     * @return
    126348     */
    127     protected boolean isConnectingNode(Way w1, Way w2, Node n){
     349    public static boolean isConnectingNode(Way w1, Way w2, Node n){
    128350        if (isStartNode(w1, n)) {
    129351                return isStartNode(w2, n)  | isEndNode(w2, n);
     
    141363     * @return true, if the way {@code w} is closed at the node {@code n}.
    142364     */
    143     protected boolean isClosedAt(Way w, Node n){
     365    public static boolean isClosedAt(Way w, Node n){
    144366        List<Node> nodes = w.getNodes();
    145367        nodes.retainAll(Collections.singletonList(n));
    146368        return nodes.size() >= 2;
    147369    }
    148    
    149     protected double phi(Way w) {
    150         return phi(w, false /* not inverse */);
    151     }
    152    
    153     protected double phi(Way w, boolean doInvert) {
    154         double x1 = w.getNode(0).getCoor().getX();
    155         double y1 = w.getNode(0).getCoor().getY();
    156         double x2 = w.getNode(w.getNodesCount()-1).getCoor().getX();
    157         double y2 = w.getNode(w.getNodesCount()-1).getCoor().getY();
    158         if (doInvert){
    159                 double t = x1; x1 = x2; x2 = t;
    160                 t = y1; y1 = y2; y2 = t;
    161         }
    162         x2-=x1;
    163         y2-=y1;
    164         return phi(x2,y2);     
    165     }
    166    
    167     protected double phi(double x, double y) {
    168         return Math.atan2(y, x);
    169     }   
    170    
    171     /**
    172      * <p>Determines the standard turn restriction between from way {@code w1} to
    173      * way {@code w2}.</p>
    174      *
    175      * <p>Replies {@link TurnRestrictionType#NO_LEFT_TURN no_left_turn} or
    176      * {@link TurnRestrictionType#NO_RIGHT_TURN no_right_turn}, if applicable. Or
    177      * null, if neither of these restrictions is applicable, for instance because
    178      * the passed in via node {@code via} isn't a node where the two ways are
    179      * connected.</p>
    180      *
    181      * @param w1 the "from"-way
    182      * @param w2 the "to"-way
    183      * @param via the via node
    184      * @return an applicable turn restriction, or null, if no turn restriction is
    185      * applicable
    186      */
    187     protected String determineRestriction(Way w1, Way w2, Node via){
    188         if (via == null) return null;
    189         if (!isConnectingNode(w1, w2, via)) return null;
    190         // if either w1 or w2 are closed at the via node, we can't determine automatically
    191         // whether the connection at "via" is a "left turn" or a "right turn"
    192         if (isClosedAt(w1, via)) return null;
    193         if (isClosedAt(w2, via)) return null;
    194        
    195         double phi1 = 0, phi2 = 0;
    196         if (isEndNode(w1, via)){
    197                 if (isStartNode(w2, via)) {
    198                         phi1 = phi(w1);
    199                         phi2 = phi(w2);
    200                 } else if (isEndNode(w2, via)){
    201                         phi1 = phi(w1);
    202                         phi2 = phi(w2, true /* reverse it */);
    203                 } else {
    204                         assert false: "Unexpected state: via node is expected to be a start or and end node";
    205                 }                       
    206         } else if (isStartNode(w1,via)) {
    207                 if (isStartNode(w2, via)) {
    208                         phi1 = phi(w1, true /* reverse it */);
    209                         phi2 = phi(w2);
    210                 } else if (isEndNode(w2, via)){
    211                         phi1 = phi(w1, true /* reverse it */);
    212                         phi2 = phi(w2, true /* reverse it */);
    213                 } else {
    214                         assert false: "Unexpected state: via node is expected to be a start or and end node";
    215                 }           
    216         } else {
    217                 assert false: "Unexpected state: via node is expected to be a start or and end node of w1";             
    218         }
    219        
    220         double phi = phi1-phi2;
    221         if (phi >=0 && phi <= Math.PI) {
    222                 // looks like a right turn 
    223                 return TurnRestrictionType.NO_RIGHT_TURN.getTagValue();
    224         } else {
    225                 // looks like a left turn
    226                 return TurnRestrictionType.NO_LEFT_TURN.getTagValue();
    227         }
    228     }
    229    
     370   
    230371    protected Relation initTurnRestrictionFromTwoWays(List<OsmPrimitive> primitives) {
    231372        Way w1 = null;
     
    273414        if (via != null){
    274415                tr.addMember(new RelationMember("via", via));
    275                 String restriction = determineRestriction(w1, w2, via);
    276                 if (restriction != null){
    277                         tr.put("restriction", restriction);
     416                RelativeWayJoinOrientation orientation = determineWayJoinOrientation(w1, w2);
     417                if (orientation != null){
     418                        switch(orientation){
     419                        case LEFT:
     420                                tr.put("restriction", TurnRestrictionType.NO_LEFT_TURN.getTagValue());
     421                                break;
     422                        case RIGHT:
     423                                tr.put("restriction", TurnRestrictionType.NO_RIGHT_TURN.getTagValue());
     424                                break;                                 
     425                        }
    278426                }
    279427        }
  • applications/editors/josm/plugins/turnrestrictions/src/org/openstreetmap/josm/plugins/turnrestrictions/qa/IdenticalTurnRestrictionLegsError.java

    r23192 r23593  
    2727    @Override
    2828    public String getText() {       
    29         return tr("This turn restriction uses the OSM way <span class=\"object-name\">{0}</span> with role <tt>from</tt> <strong>and</strong> with role <tt>to</tt>. "
     29        return tr("This turn restriction uses the way <span class=\"object-name\">{0}</span> with role <tt>from</tt> <strong>and</strong> with role <tt>to</tt>. "
    3030                + "In a turn restriction, the way with role <tt>from</tt> should be different from the way with role <tt>to</tt>, though.",
    3131                leg.getDisplayName(DefaultNameFormatter.getInstance())
  • applications/editors/josm/plugins/turnrestrictions/src/org/openstreetmap/josm/plugins/turnrestrictions/qa/IssuesModel.java

    r23571 r23593  
    11package org.openstreetmap.josm.plugins.turnrestrictions.qa;
     2
     3import static org.openstreetmap.josm.plugins.turnrestrictions.TurnRestrictionBuilder.isInnerNode;
    24
    35import java.util.ArrayList;
    46import java.util.Collections;
    5 import java.util.HashSet;
    67import java.util.List;
    78import java.util.Observable;
     
    1415import org.openstreetmap.josm.gui.tagging.TagEditorModel;
    1516import org.openstreetmap.josm.gui.tagging.TagModel;
     17import org.openstreetmap.josm.plugins.turnrestrictions.TurnRestrictionBuilder;
    1618import org.openstreetmap.josm.plugins.turnrestrictions.editor.ExceptValueModel;
    1719import org.openstreetmap.josm.plugins.turnrestrictions.editor.NavigationControler;
     
    190192    }
    191193   
    192     protected Node getNodeAtIntersection(Way from, Way to){
    193         Set<Node> fromNodes = new HashSet<Node>(from.getNodes());
    194         fromNodes.retainAll(to.getNodes());
    195         if (fromNodes.size() == 1){
    196             return fromNodes.iterator().next();
    197         } else {
    198             return null;
    199         }
    200     }
    201    
    202194    /**
    203195     * Checks the 'via' members in the turn restriction
     
    215207        Way from = (Way)fromLegs.iterator().next();
    216208        Way to = (Way)toLegs.iterator().next();
    217         Node intersect = getNodeAtIntersection(from, to);
     209        Node intersect = TurnRestrictionBuilder.getUniqueCommonNode(from, to);       
    218210        if (intersect != null){
    219211            if (!editorModel.getVias().contains(intersect)) {
    220212                issues.add(new IntersectionMissingAsViaError(this, from, to, intersect));
    221213            }
    222             // 'from' intersects with 'to' - should be split 
    223             if (from.getNode(0) != intersect && from.getNode(from.getNodesCount()-1) != intersect){
    224                 issues.add(new TurnRestrictionLegSplitRequiredError(this, TurnRestrictionLegRole.FROM, from, to, intersect));
    225             }
    226             // 'to' intersects with 'from' - should be split
    227             if (to.getNode(0) != intersect && to.getNode(to.getNodesCount()-1) != intersect){
    228                 issues.add(new TurnRestrictionLegSplitRequiredError(this, TurnRestrictionLegRole.TO, from, to, intersect));
    229             }                 
     214                if (isInnerNode(from, intersect) && isInnerNode(to, intersect)) {
     215                        issues.add(new TurnRestrictionLegSplitRequiredError(this, from, to));
     216                } else if (isInnerNode(from, intersect) && ! isInnerNode(to, intersect)) {
     217                        issues.add(new TurnRestrictionLegSplitRequiredError(this, TurnRestrictionLegRole.FROM, from, to, intersect));
     218                } else if (!isInnerNode(from, intersect) && isInnerNode(to, intersect)) {
     219                        issues.add(new TurnRestrictionLegSplitRequiredError(this, TurnRestrictionLegRole.TO, from, to, intersect));
     220                }
    230221        } else {
    231222                if (editorModel.getVias().isEmpty() && ! from.equals(to)){
  • applications/editors/josm/plugins/turnrestrictions/src/org/openstreetmap/josm/plugins/turnrestrictions/qa/MissingTurnRestrictionLegError.java

    r23192 r23593  
    3434        switch(role){
    3535        case FROM:
    36             msg = tr("An OSM way with role <tt>from</tt> is required in a turn restriction.");
     36            msg = tr("A way with role <tt>from</tt> is required in a turn restriction.");
    3737            break;
    3838        case TO:
    39             msg = tr("An OSM way with role <tt>to</tt> is required in a turn restriction.");
     39            msg = tr("A way with role <tt>to</tt> is required in a turn restriction.");
    4040            break;
    4141        }
    42         msg += " " + tr("Please go to the Basic editor and manually choose an OSM way.");
     42        msg += " " + tr("Please go to the Basic editor and manually choose a way.");
    4343        return msg;
    4444    }
     
    4949            switch(role){
    5050            case FROM:
    51                 putValue(SHORT_DESCRIPTION, tr("Add an OSM way with role ''from''"));
     51                putValue(SHORT_DESCRIPTION, tr("Add a way with role ''from''"));
    5252                break;
    5353            case TO:
    54                 putValue(SHORT_DESCRIPTION, tr("Add an OSM way with role ''to''"));
     54                putValue(SHORT_DESCRIPTION, tr("Add a way with role ''to''"));
    5555                break;             
    5656            }           
  • applications/editors/josm/plugins/turnrestrictions/src/org/openstreetmap/josm/plugins/turnrestrictions/qa/TurnRestrictionLegSplitRequiredError.java

    r23192 r23593  
    44
    55import java.awt.event.ActionEvent;
     6import java.util.Arrays;
    67import java.util.Collections;
     8import java.util.logging.Logger;
    79
    810import javax.swing.AbstractAction;
     
    1517import org.openstreetmap.josm.data.osm.Way;
    1618import org.openstreetmap.josm.gui.DefaultNameFormatter;
     19import org.openstreetmap.josm.plugins.turnrestrictions.TurnRestrictionBuilder;
    1720import org.openstreetmap.josm.plugins.turnrestrictions.editor.TurnRestrictionLegRole;
     21import org.openstreetmap.josm.plugins.turnrestrictions.editor.TurnRestrictionType;
     22import org.openstreetmap.josm.tools.CheckParameterUtil;
    1823
    1924/**
     
    2328 */
    2429public class TurnRestrictionLegSplitRequiredError extends Issue{
     30        static private final Logger logger = Logger.getLogger(TurnRestrictionLegSplitRequiredError.class.getName());
     31       
    2532    private TurnRestrictionLegRole role;
    2633    private Way from;
    2734    private Way to;
    28     private Node interesect;
     35    private Node intersect;
     36   
     37    /**
     38     * <p>Creates the issue for a pair of ways {@code from} and {@code to} which interesect
     39     * at node {@code intersect}.</p>
     40     *
     41     * @param parent the parent model
     42     * @param from the way with role "from"
     43     * @param to the way with role "to"
     44     * @param intersect the intersection node
     45     */
     46    public TurnRestrictionLegSplitRequiredError(IssuesModel parent, Way from, Way to){
     47        super(parent, Severity.ERROR);
     48        CheckParameterUtil.ensureParameterNotNull(from, "from");
     49        CheckParameterUtil.ensureParameterNotNull(to, "to");
     50       
     51        intersect= TurnRestrictionBuilder.getUniqueCommonNode(from, to);
     52        if (intersect == null)
     53                throw new IllegalArgumentException("exactly one intersecting node required");
     54       
     55        this.from = from;
     56        this.to = to;
     57        this.role = null;
     58        actions.add(new SplitAction());
     59    }
    2960
    3061    /**
     
    3566     * @param from the way with role 'from'
    3667     * @param to the way with role 'to'
    37      * @param interesect the node at the intersection
     68     * @param intersect the node at the intersection
    3869     */
    3970    public TurnRestrictionLegSplitRequiredError(IssuesModel parent, TurnRestrictionLegRole role, Way from, Way to, Node intersect) {
     
    4273        this.from = from;
    4374        this.to = to;
    44         this.interesect = intersect;
     75        this.intersect = intersect;
    4576        actions.add(new SplitAction());
    4677    }
     
    4980    public String getText() {
    5081        String msg = null;
     82        if (role == null){
     83                /*
     84                 * from and to intersect at a common node. Both have to be split.
     85                 */
     86                return tr("The way <span class=\"object-name\">{0}</span> with role <tt>from</tt> and the "
     87                                + "way <span class=\"object-name\">{1}</span> with role <tt>to</tt> intersect "                         
     88                                + "at node <span class=\"object-name\">{2}</span>. "
     89                                + "<p> "
     90                                + "Both ways should be split at the intersecting node.",
     91                    from.getDisplayName(DefaultNameFormatter.getInstance()),
     92                    to.getDisplayName(DefaultNameFormatter.getInstance()),
     93                    intersect.getDisplayName(DefaultNameFormatter.getInstance())
     94                );
     95        }
    5196        switch(role){
    5297        case FROM:
    53             msg = tr("The OSM way <span class=\"object-name\">{0}</span> with role <tt>{1}</tt> should be split "
     98                /*
     99                 * "to" joins "from" at a common node. Only from has to be split
     100                 */
     101            msg = tr("The way <span class=\"object-name\">{0}</span> with role <tt>{1}</tt> should be split "
    54102                + "at node <span class=\"object-name\">{2}</span> where it connects to way <span class=\"object-name\">{3}</span>.",
    55103                from.getDisplayName(DefaultNameFormatter.getInstance()),
    56104                role.getOsmRole(),
    57                 interesect.getDisplayName(DefaultNameFormatter.getInstance()),
     105                intersect.getDisplayName(DefaultNameFormatter.getInstance()),
    58106                to.getDisplayName(DefaultNameFormatter.getInstance())
    59107            );
    60108            break;
    61109        case TO:
    62             msg = tr("The OSM way <span class=\"object-name\">{0}</span> with role <tt>{1}</tt> should be split "
     110                /*
     111                 * "from" joins "to" at a common node. Only to has to be split
     112                 */
     113            msg = tr("The way <span class=\"object-name\">{0}</span> with role <tt>{1}</tt> should be split "
    63114                    + "at node <span class=\"object-name\">{2}</span> where it connects to way <span class=\"object-name\">{3}</span>.",
    64115                    to.getDisplayName(DefaultNameFormatter.getInstance()),
    65116                    role.getOsmRole(),
    66                     interesect.getDisplayName(DefaultNameFormatter.getInstance()),
     117                    intersect.getDisplayName(DefaultNameFormatter.getInstance()),
    67118                    from.getDisplayName(DefaultNameFormatter.getInstance())
    68119                );
     
    75126        public SplitAction() {
    76127            putValue(NAME, tr("Split now"));
    77             putValue(SHORT_DESCRIPTION, tr("Splits the way"));
     128            putValue(SHORT_DESCRIPTION, tr("Split the ways"));
    78129        }
     130       
    79131        public void actionPerformed(ActionEvent e) {
    80             Way way = null;
    81             switch(role){
    82             case FROM: way = from; break;
    83             case TO: way = to; break;
     132
     133                SplitWayResult result = null;
     134            if (role == null || role.equals(TurnRestrictionLegRole.FROM)){
     135                  result = SplitWayAction.split(
     136                          parent.getEditorModel().getLayer(),
     137                          from,
     138                          Collections.singletonList(intersect),
     139                          Collections.<OsmPrimitive>emptyList()
     140                  );
     141                  if (result != null){
     142                      Main.main.undoRedo.add(result.getCommand());
     143                  }
    84144            }
    85             SplitWayResult result = SplitWayAction.split(
    86                     parent.getEditorModel().getLayer(),
    87                     way,
    88                     Collections.singletonList(interesect),
    89                     Collections.<OsmPrimitive>emptyList()
    90             );
    91             if (result != null){
    92                 Main.main.undoRedo.add(result.getCommand());
    93             }
     145           
     146            if (role == null || role.equals(TurnRestrictionLegRole.TO)) {
     147                result = SplitWayAction.split(
     148                        parent.getEditorModel().getLayer(),
     149                        to,
     150                        Collections.singletonList(intersect),
     151                        Collections.<OsmPrimitive>emptyList()
     152                );
     153                if (result != null){
     154                    Main.main.undoRedo.add(result.getCommand());
     155                }
     156                if (result == null) return;
     157                        TurnRestrictionType restrictionType = TurnRestrictionType.fromTagValue(getIssuesModel().getEditorModel().getRestrictionTagValue());
     158                    if (restrictionType == null) return;
     159                    Way adjustedTo = TurnRestrictionBuilder.selectToWayAfterSplit(
     160                                 from,
     161                                 result.getOriginalWay(),
     162                                 result.getNewWays().get(0),
     163                                 restrictionType
     164                    );
     165       
     166                    if (adjustedTo == null) return;
     167                    getIssuesModel().getEditorModel().setTurnRestrictionLeg(
     168                                 TurnRestrictionLegRole.TO,
     169                                 adjustedTo
     170                    );       
     171                    getIssuesModel().getEditorModel().getLayer().data.setSelected(
     172                                 Arrays.asList(from, adjustedTo)
     173                     );
     174            } else {
     175                    getIssuesModel().getEditorModel().getLayer().data.setSelected(
     176                                 Arrays.asList(from, to)
     177                     );                 
     178            }           
    94179        }
    95180    }
  • applications/editors/josm/plugins/turnrestrictions/src/org/openstreetmap/josm/plugins/turnrestrictions/qa/WrongTurnRestrictionLegTypeError.java

    r23192 r23593  
    4343        case NODE:
    4444            msg = tr(
    45                 "This turn restriction uses the OSM node <span class=\"object-name\">{0}</span> as member with role <tt>{1}</tt>.",
     45                "This turn restriction uses the node <span class=\"object-name\">{0}</span> as member with role <tt>{1}</tt>.",
    4646                leg.getDisplayName(DefaultNameFormatter.getInstance()),
    4747                role.toString()
     
    4949            break;
    5050        case RELATION:
    51             msg = tr("This turn restriction uses the OSM relation <span class=\"object-name\">{0}</span> as member with role <tt>{1}</tt>.",
     51            msg = tr("This turn restriction uses the relation <span class=\"object-name\">{0}</span> as member with role <tt>{1}</tt>.",
    5252                    leg.getDisplayName(DefaultNameFormatter.getInstance()),
    5353                    role.toString()
     
    5555            break;         
    5656        }
    57         return msg + " " + tr("An OSM way is required instead.");
     57        return msg + " " + tr("A way is required instead.");
    5858    }
    5959
     
    7979        public FixInEditorAction() {
    8080            putValue(NAME, tr("Fix in editor"));
    81             putValue(SHORT_DESCRIPTION, tr("Change to the Basic Editor and select an OSM way"));
     81            putValue(SHORT_DESCRIPTION, tr("Change to the Basic Editor and select a way"));
    8282        }
    8383        public void actionPerformed(ActionEvent e) {
Note: See TracChangeset for help on using the changeset viewer.