Ticket #5561: fix-unglue-ways-cleanup-code.patch

File fix-unglue-ways-cleanup-code.patch, 14.2 KB (added by cmuelle8, 13 years ago)

fix things, but please test thoroughly, before applying - let's hope that there are no regression bugs..

  • src/org/openstreetmap/josm/actions/mapmode/SelectAction.java

     
    340340    private Collection<OsmPrimitive> cycleSetup(Collection<OsmPrimitive> single, MouseEvent e) {
    341341        OsmPrimitive osm = null;
    342342
    343         if (single == null) {
    344             single = MapView.asColl(
    345                     mv.getNearestNodeOrWay(e.getPoint(), OsmPrimitive.isSelectablePredicate, false));
    346         }
     343        if (single != null && !single.isEmpty()) {
     344            osm = single.iterator().next();
    347345
    348         if (!single.isEmpty()) {
     346            Point p = e.getPoint();
    349347            boolean waitForMouseUp = Main.pref.getBoolean("mappaint.select.waits-for-mouse-up", false);
    350348            boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
    351349            boolean alt = ((e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0
    352350                    || Main.pref.getBoolean("selectaction.cycles.multiple.matches", false));
    353351
    354             Point p = e.getPoint();
    355             osm = single.iterator().next();
    356 
    357352            if (!alt) {
    358353                cycleList = MapView.asColl(osm);
     354
    359355                if (waitForMouseUp) {
    360                     // find a selected nearest node or way, not the true nearest..
     356                    // prefer a selected nearest node or way, if possible
    361357                    osm = mv.getNearestNodeOrWay(p, OsmPrimitive.isSelectablePredicate, true);
    362358                }
    363359            } else {
     
    367363                    cycleList = new LinkedList<OsmPrimitive>(mv.getNearestWays(p, OsmPrimitive.isSelectablePredicate));
    368364                }
    369365
    370                 if (!waitForMouseUp && cycleList.size()>1) {
     366                if (cycleList.size()>1) {
    371367                    cyclePrims = false;
    372368
    373369                    OsmPrimitive old = osm;
     
    379375                        }
    380376                    }
    381377
    382                     // for cycle groups of 2, we can toggle to the true nearest
    383                     // primitive on mouse presses, if it is not selected and if ctrl is not used
    384                     // else, if rotation is possible, defer sel change to mouse release
    385                     if (cycleList.size()==2) {
    386                         if (!(old.equals(osm) || ctrl)) {
     378                    // special case:  for cycle groups of 2, we can toggle to the
     379                    // true nearest primitive on mousePressed right away
     380                    if (cycleList.size()==2 && !waitForMouseUp) {
     381                        if (!(osm.equals(old) || osm.isNew() || ctrl)) {
    387382                            cyclePrims = false;
    388383                            osm = old;
    389                         }
     384                        } // else defer toggling to mouseRelease time in those cases:
     385                        /*
     386                         * osm == old        -- the true nearest node is the selected one
     387                         * osm is a new node -- do not break unglue ways in ALT mode
     388                         * ctrl is pressed   -- ctrl generally works on mouseReleased
     389                         */
    390390                    }
    391391                }
    392392            }
  • src/org/openstreetmap/josm/gui/SelectionManager.java

     
    273273        Point center = new Point(r.x+r.width/2, r.y+r.height/2);
    274274
    275275        if (clicked) {
    276             OsmPrimitive osm = nc.getNearestNodeOrWay(center, OsmPrimitive.isSelectablePredicate);
     276            OsmPrimitive osm = nc.getNearestNodeOrWay(center, OsmPrimitive.isSelectablePredicate, false);
    277277            if (osm != null) {
    278278                selection.add(osm);
    279279            }
  • src/org/openstreetmap/josm/gui/NavigatableComponent.java

     
    559559    }
    560560
    561561    /**
    562      * The *result* depends on the current map selection state.
     562     * The *result* depends on the current map selection state IF use_selected is true.
    563563     *
    564564     * If more than one node within node.snap-distance pixels is found,
    565      * the nearest node selected is returned.
     565     * the nearest node selected is returned IF use_selected is true.
    566566     *
    567      * If no such node is found, the nearest new/id=0 node within
    568      * about the same distance as the true nearest node is returned.
     567     * Else the nearest new/id=0 node within about the same distance
     568     * as the true nearest node is returned.
    569569     *
    570570     * If no such node is found either, the true nearest
    571571     * node to p is returned.
    572572     *
    573      * Finally, if a node is not found at all, return null.
     573     * Finally, if a node is not found at all, null is returned.
    574574     *
    575575     * @return A node within snap-distance to point p,
    576576     *      that is chosen by the algorithm described.
     
    579579     * @param predicate this parameter imposes a condition on the returned object, e.g.
    580580     *        give the nearest node that is tagged.
    581581     */
    582     public final Node getNearestNode(Point p, Predicate<OsmPrimitive> predicate) {
     582    public final Node getNearestNode(Point p, Predicate<OsmPrimitive> predicate, boolean use_selected) {
    583583        Node n = null;
    584584
    585585        Map<Double, List<Node>> nlists = getNearestNodesImpl(p, predicate);
     
    602602            }
    603603
    604604            // take nearest selected, nearest new or true nearest node to p, in that order
    605             n = (ntsel != null) ? ntsel : ((ntnew != null) ? ntnew
    606                     : nlists.values().iterator().next().get(0));
     605            n = (ntsel != null && use_selected) ? ntsel
     606                    : ((ntnew != null) ? ntnew
     607                            : nlists.values().iterator().next().get(0));
    607608        }
    608609
    609610        return n;
    610611    }
    611612
     613    /**
     614     * Convenience method to {@link #getNearestNode(Point, Predicate, boolean)}.
     615     *
     616     * @return The nearest node to point p.
     617     */
     618    public final Node getNearestNode(Point p, Predicate<OsmPrimitive> predicate) {
     619        return getNearestNode(p, predicate, true);
     620    }
     621
    612622    @Deprecated
    613623    public final Node getNearestNode(Point p) {
    614624        return getNearestNode(p, OsmPrimitive.isUsablePredicate);
     
    730740    }
    731741
    732742    /**
    733      * The *result* depends on the current map selection state.
     743     * The *result* depends on the current map selection state IF use_selected is true.
    734744     *
    735745     * @return The nearest way segment to point p,
    736      *      prefer a nearest, selected way segment, if found.
     746     *      and, depending on use_selected, prefers a selected way segment, if found.
    737747     * @see #getNearestWaySegments(Point, Collection, Predicate)
    738748     *
    739749     * @param p the point for which to search the nearest segment.
    740750     * @param predicate the returned object has to fulfill certain properties.
     751     * @param use_selected whether selected way segments should be preferred.
    741752     */
    742     public final WaySegment getNearestWaySegment(Point p, Predicate<OsmPrimitive> predicate) {
     753    public final WaySegment getNearestWaySegment(Point p, Predicate<OsmPrimitive> predicate, boolean use_selected) {
    743754        WaySegment wayseg = null, ntsel = null;
    744755
    745756        for (List<WaySegment> wslist : getNearestWaySegmentsImpl(p, predicate).values()) {
     
    756767            }
    757768        }
    758769
    759         return (ntsel != null) ? ntsel : wayseg;
     770        return (ntsel != null && use_selected) ? ntsel : wayseg;
     771    }
     772
     773    /**
     774     * Convenience method to {@link #getNearestWaySegment(Point, Predicate, boolean)}.
     775     *
     776     * @return The nearest way segment to point p.
     777     */
     778    public final WaySegment getNearestWaySegment(Point p, Predicate<OsmPrimitive> predicate) {
     779        return getNearestWaySegment(p, predicate, true);
    760780    }
    761781
    762782    /**
     
    882902
    883903    /**
    884904     * This is used as a helper routine to {@link #getNearestNodeOrWay(Point, Predicate, boolean)}
     905     * It decides, whether to yield the node to be tested or look for further (way) candidates.
    885906     *
    886      * @return true, if the node fulfills certain properties wrt p and use_sel
     907     * @return true, if the node fulfills the properties of the function body
    887908     *
    888909     * @param osm node to check
    889910     * @param p point clicked
    890      * @param use_sel whether to prefer a selected node
     911     * @param use_selected whether to prefer selected nodes
    891912     */
    892913    private boolean isPrecedenceNode(Node osm, Point p, boolean use_selected) {
    893914        boolean ret = false;
     
    929950     * @param use_selected whether to prefer primitives that are currently selected.
    930951     */
    931952    public final OsmPrimitive getNearestNodeOrWay(Point p, Predicate<OsmPrimitive> predicate, boolean use_selected) {
    932         OsmPrimitive osm = null;
     953        OsmPrimitive osm = getNearestNode(p, predicate, use_selected);
    933954        WaySegment ws = null;
    934955
    935         // find a nearest, selected primitive
    936         if (use_selected) {
    937             osm = getNearestNode(p, predicate);
    938             use_selected = isPrecedenceNode((Node)osm, p, use_selected);
     956        if (!isPrecedenceNode((Node)osm, p, use_selected)) {
     957            ws = getNearestWaySegment(p, predicate, use_selected);
    939958
    940             if (!use_selected) {
    941                 ws = getNearestWaySegment(p, predicate);
    942                 if (ws != null) {
    943                     if (ws.way.isSelected() || osm == null) {
    944                         // either no nearest nodes found or none were selected
    945                         use_selected = true;
    946                         osm = ws.way;
    947                     } // else { unselected node and wayseg found, do the stuff below }
     959            if (ws != null) {
     960                if ((ws.way.isSelected() && use_selected) || osm == null) {
     961                    // either (no _selected_ nearest node found, if desired) or no nearest node was found
     962                    osm = ws.way;
    948963                } else {
    949                     // no nearest wayseg found, osm is null or the nearest node
    950                     use_selected = true;
    951                 }
    952             }
    953         }
     964                    int maxWaySegLenSq = 3*PROP_SNAP_DISTANCE.get();
     965                    maxWaySegLenSq *= maxWaySegLenSq;
    954966
    955         // no nearest, selected primitive was found or caller does not care about current selection
    956         if (!use_selected) {
    957             if (osm == null) {
    958                 // get the true nearest node (if unselected found before, reuse it)
    959                 for (List<Node> nlist : getNearestNodesImpl(p, predicate).values()) {
    960                     osm = nlist.get(0);
    961                     break;
    962                 }
    963             }
     967                    Point2D wp1 = getPoint2D(ws.way.getNode(ws.lowerIndex));
     968                    Point2D wp2 = getPoint2D(ws.way.getNode(ws.lowerIndex+1));
    964969
    965             // there is no nearest node OR it does not fulfill criteria to simply be chosen
    966             if (osm == null || !isPrecedenceNode((Node)osm, p, use_selected)) {
    967                 if (ws == null) {
    968                     // get the true nearest wayseg (if unselected found before, reuse it)
    969                     for (WaySegment wseg : getNearestWaySegments(p, predicate)) {
    970                         ws = wseg;
    971                         break;
    972                     }
    973                 }
    974                 if (ws != null) {
    975                     if (osm == null) {
    976                         // a nearest node was not found
     970                    // is wayseg shorter than maxWaySegLenSq and
     971                    // is p closer to the middle of wayseg  than  to the nearest node?
     972                    if (wp1.distanceSq(wp2) < maxWaySegLenSq &&
     973                            p.distanceSq(project(0.5, wp1, wp2)) < p.distanceSq(getPoint2D((Node)osm))) {
    977974                        osm = ws.way;
    978                     } else {
    979                         int maxWaySegLenSq = 3*PROP_SNAP_DISTANCE.get();
    980                         maxWaySegLenSq *= maxWaySegLenSq;
    981 
    982                         Point2D wp1 = getPoint2D(ws.way.getNode(ws.lowerIndex));
    983                         Point2D wp2 = getPoint2D(ws.way.getNode(ws.lowerIndex+1));
    984 
    985                         // is wayseg shorter than maxWaySegLenSq and
    986                         // is p closer to the middle of wayseg than to the nearest node?
    987                         if (wp1.distanceSq(wp2) < maxWaySegLenSq &&
    988                                 p.distanceSq(project(0.5, wp1, wp2)) < p.distanceSq(getPoint2D((Node)osm))) {
    989                             osm = ws.way;
    990                         }
    991975                    }
    992976                }
    993977            }
     
    996980        return osm;
    997981    }
    998982
    999     /**
    1000      * Convenience method to {@link #getNearestNodeOrWay(Point, Predicate, boolean)}.
    1001      *
    1002      * @return The nearest primitive to point p.
    1003      */
    1004     public final OsmPrimitive getNearestNodeOrWay(Point p, Predicate<OsmPrimitive> predicate) {
    1005         return getNearestNodeOrWay(p, predicate, false);
    1006     }
    1007 
    1008983    @Deprecated
    1009984    public final OsmPrimitive getNearest(Point p, Predicate<OsmPrimitive> predicate) {
    1010985        return getNearestNodeOrWay(p, predicate, false);
  • src/org/openstreetmap/josm/gui/MapStatus.java

     
    299299         * @param ms
    300300         */
    301301        private final void statusBarElementUpdate(MouseState ms) {
    302             final OsmPrimitive osmNearest = mv.getNearestNodeOrWay(ms.mousePos, OsmPrimitive.isUsablePredicate);
     302            final OsmPrimitive osmNearest = mv.getNearestNodeOrWay(ms.mousePos, OsmPrimitive.isUsablePredicate, false);
    303303            if (osmNearest != null) {
    304304                nameText.setText(osmNearest.getDisplayName(DefaultNameFormatter.getInstance()));
    305305            } else {