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

File fix-unglue-ways-cleanup-code.patch, 14.2 KB (added by cmuelle8, 3 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 {