Changeset 3230 in josm for trunk/src


Ignore:
Timestamp:
2010-05-11T08:41:44+02:00 (14 years ago)
Author:
stoecker
Message:

fix #4995 - improve area joinging reliability

Location:
trunk/src/org/openstreetmap/josm/actions
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/CombineWayAction.java

    r3170 r3230  
    103103    }
    104104
    105     public void combineWays(Collection<Way> ways) {
     105    public Way combineWays(Collection<Way> ways) {
    106106
    107107        // prepare and clean the list of ways to combine
    108108        //
    109109        if (ways == null || ways.isEmpty())
    110             return;
     110            return null;
    111111        ways.remove(null); // just in case -  remove all null ways from the collection
    112112        ways = new HashSet<Way>(ways); // remove duplicates
     
    119119        if (path == null) {
    120120            warnCombiningImpossible();
    121             return;
     121            return null;
    122122        }
    123123        // check whether any ways have been reversed in the process
     
    142142        }
    143143        if ((reversedWays != null) && !reversedWays.isEmpty()) {
    144             if (!confirmChangeDirectionOfWays()) return;
     144            if (!confirmChangeDirectionOfWays()) return null;
    145145            // filter out ways that have no direction-dependent tags
    146146            unreversedWays = ReverseWayTagCorrector.irreversibleWays(unreversedWays);
     
    167167                    }
    168168                    catch(UserCancelException ex) {
    169                         return;
     169                        return null;
    170170                    }
    171171                }
     
    207207            dialog.setVisible(true);
    208208            if (dialog.isCancelled())
    209                 return;
     209                return null;
    210210        }
    211211
     
    218218        cmds.add(new DeleteCommand(deletedWays));
    219219        final SequenceCommand sequenceCommand = new SequenceCommand(tr("Combine {0} ways", ways.size()), cmds);
    220 
    221         // update gui
    222         final Way selectedWay = targetWay;
    223         Runnable guiTask = new Runnable() {
    224             public void run() {
    225                 Main.main.undoRedo.add(sequenceCommand);
    226                 getCurrentDataSet().setSelected(selectedWay);
    227             }
    228         };
    229         if (SwingUtilities.isEventDispatchThread()) {
    230             guiTask.run();
    231         } else {
    232             SwingUtilities.invokeLater(guiTask);
    233         }
     220        Main.main.undoRedo.add(sequenceCommand);
     221
     222        return targetWay;
    234223    }
    235224
     
    248237            return;
    249238        }
    250         combineWays(selectedWays);
     239        // combine and update gui
     240        final Way selectedWay = combineWays(selectedWays);
     241        if(selectedWay != null)
     242        {
     243            Runnable guiTask = new Runnable() {
     244                public void run() {
     245                    getCurrentDataSet().setSelected(selectedWay);
     246                }
     247            };
     248            if (SwingUtilities.isEventDispatchThread()) {
     249                guiTask.run();
     250            } else {
     251                SwingUtilities.invokeLater(guiTask);
     252            }
     253        }
    251254    }
    252255
  • trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java

    r3083 r3230  
    184184        boolean hadChanges = false;
    185185        if(!same) {
     186            int i = 0;
    186187            if(checkForTagConflicts(a, b)) return true; // User aborted, so don't warn again
    187             hadChanges = joinAreas(a, a);
    188             hadChanges = joinAreas(b, b) || hadChanges;
     188            if(joinAreas(a, a))
     189                ++i;
     190            if(joinAreas(b, b))
     191                ++i;
     192            hadChanges = i > 0;
     193            cmdsCount = i;
    189194        }
    190195
     
    212217
    213218        // Fix Multipolygons if there are any
    214         Collection<Way> newInnerWays = fixMultigons(innerWays, outerWay);
     219        Collection<Way> newInnerWays = fixMultipolygons(innerWays, outerWay, same);
    215220
    216221        // Delete the remaining inner ways
     
    251256
    252257        // FIXME: This is mostly copied and pasted from CombineWayAction.java and one day should be moved into tools
     258        // We have TagCollection handling for that now - use it here as well
    253259        Map<String, Set<String>> props = new TreeMap<String, Set<String>>();
    254260        for (Way w : ways) {
     
    274280                if("created_by".equals(e.getKey()))
    275281                {
    276                     ax.put("created_by", "JOSM");
    277                     bx.put("created_by", "JOSM");
     282                    ax.remove("created_by");
     283                    bx.remove("created_by");
    278284                } else {
    279285                    JComboBox c = new JComboBox(e.getValue().toArray());
     
    409415     */
    410416    private void addNodesToWay(Way a, ArrayList<NodeToSegs> nodes) {
     417        if(nodes.size() == 0)
     418            return;
    411419        Way ax=new Way(a);
    412420        Collections.sort(nodes);
     
    640648            a = b;
    641649        }
    642         Main.main.getCurrentDataSet().setSelected(ways);
    643         // TODO: It might be possible that a confirmation dialog is presented even after reversing (for
    644         // "strange" ways). If the user cancels this, makeCommitsOneAction will wrongly consume a previous
    645         // action. Make CombineWayAction either silent or expose its combining capabilities.
    646         new CombineWayAction().actionPerformed(null);
    647         cmdsCount++;
    648         return (Way)(Main.main.getCurrentDataSet().getSelectedWays().toArray())[0];
     650        if((a = new CombineWayAction().combineWays(ways)) != null)
     651            cmdsCount++;
     652        return a;
    649653    }
    650654
     
    656660     * @return ArrayList<Way> The List of newly created inner ways
    657661     */
    658     private ArrayList<Way> fixMultigons(Collection<Way> uninterestingWays, Way outerWay) {
     662    private ArrayList<Way> fixMultipolygons(Collection<Way> uninterestingWays, Way outerWay, boolean selfintersect) {
    659663        Collection<Node> innerNodes = getNodesFromWays(uninterestingWays);
    660664        Collection<Node> outerNodes = outerWay.getNodes();
     
    672676            for(Node n : w.getNodes()) {
    673677                if(outerNodes.contains(n)) {
    674                     continue wayIterator;
    675                 }
    676                 if(!hasInnerNodes && innerNodes.contains(n)) {
     678                    if(!selfintersect) // allow outer point for self intersection
     679                        continue wayIterator;
     680                }
     681                else if(!hasInnerNodes && innerNodes.contains(n)) {
    677682                    hasInnerNodes = true;
    678683                }
     
    686691        // This removes unnecessary ways that might have been added.
    687692        removeAlmostAlikeWays(possibleWays);
    688         removePartlyUnconnectedWays(possibleWays);
    689 
    690         // Join all ways that have one start/ending node in common
    691         Way joined = null;
    692         outerIterator: do {
    693             joined = null;
    694             for(Way w1 : possibleWays) {
    695                 if(w1.isClosed()) {
    696                     if(!wayIsCollapsed(w1)) {
    697                         uninterestingWays.remove(w1);
    698                         newInnerWays.add(w1);
     693
     694        // loop twice
     695        // in k == 0 prefer ways which allow no Y-joining (i.e. which have only 1 solution)
     696        for(int k = 0; k < 2; ++k)
     697        {
     698            // Join all ways that have one start/ending node in common
     699            Way joined = null;
     700            outerIterator: do {
     701                removePartlyUnconnectedWays(possibleWays);
     702                joined = null;
     703                for(Way w1 : possibleWays) {
     704                    if(w1.isClosed()) {
     705                        if(!wayIsCollapsed(w1)) {
     706                            uninterestingWays.remove(w1);
     707                            newInnerWays.add(w1);
     708                        }
     709                        joined = w1;
     710                        possibleWays.remove(w1);
     711                        continue outerIterator;
    699712                    }
    700                     joined = w1;
    701                     possibleWays.remove(w1);
    702                     continue outerIterator;
    703                 }
    704                 for(Way w2 : possibleWays) {
    705                     // w2 cannot be closed, otherwise it would have been removed above
    706                     if(!waysCanBeCombined(w1, w2)) {
    707                         continue;
     713                    ArrayList<Way> secondary = new ArrayList<Way>();
     714                    for(Way w2 : possibleWays) {
     715                        int i = 0;
     716                        // w2 cannot be closed, otherwise it would have been removed above
     717                        if(w1.equals(w2))
     718                            continue;
     719                        if(w2.isFirstLastNode(w1.firstNode()))
     720                            ++i;
     721                        if(w2.isFirstLastNode(w1.lastNode()))
     722                            ++i;
     723                        if(i == 2) // this way closes w1 - take it!
     724                        {
     725                            if(secondary.size() > 0)
     726                                secondary.clear();
     727                            secondary.add(w2);
     728                            break;
     729                        }
     730                        else if(i > 0)
     731                            secondary.add(w2);
    708732                    }
    709 
    710                     ArrayList<Way> joinThem = new ArrayList<Way>();
    711                     joinThem.add(w1);
    712                     joinThem.add(w2);
    713                     uninterestingWays.removeAll(joinThem);
    714                     possibleWays.removeAll(joinThem);
    715 
    716                     // Although we joined the ways, we cannot simply assume that they are closed
    717                     joined = joinWays(joinThem);
    718                     uninterestingWays.add(joined);
    719                     possibleWays.add(joined);
    720                     continue outerIterator;
    721                 }
    722             }
    723         } while(joined != null);
     733                    if(k == 0 ? secondary.size() == 1 : secondary.size() > 0)
     734                    {
     735                        ArrayList<Way> joinThem = new ArrayList<Way>();
     736                        joinThem.add(w1);
     737                        joinThem.add(secondary.get(0));
     738                        // Although we joined the ways, we cannot simply assume that they are closed
     739                        if((joined = joinWays(joinThem)) != null)
     740                        {
     741                            uninterestingWays.removeAll(joinThem);
     742                            possibleWays.removeAll(joinThem);
     743
     744                            List<Node> nodes = joined.getNodes();
     745                            // check if we added too much
     746                            /*for(int i = 1; i < nodes.size()-2; ++i)
     747                            {
     748                                if(nodes.get(i) == nodes.get(nodes.size()-1))
     749                                    System.out.println("Joining of ways produced unexpecteded result\n");
     750                            }*/
     751                            uninterestingWays.add(joined);
     752                            possibleWays.add(joined);
     753                            continue outerIterator;
     754                        }
     755                    }
     756                }
     757            } while(joined != null);
     758        }
    724759        return newInnerWays;
    725760    }
     
    795830            if(count == 2) return true;
    796831        }
    797         return false;
    798     }
    799 
    800     /**
    801      * Checks if two ways share one starting/ending node
    802      * @param Way first way
    803      * @param Way second way
    804      * @return boolean Wheter the ways share a starting/ending node or not
    805      */
    806     private boolean waysCanBeCombined(Way w1, Way w2) {
    807         if(w1.equals(w2)) return false;
    808 
    809         if(w1.getNode(0).equals(w2.getNode(0))) return true;
    810         if(w1.getNode(0).equals(w2.getNode(w2.getNodesCount()-1))) return true;
    811 
    812         if(w1.getNode(w1.getNodesCount()-1).equals(w2.getNode(0))) return true;
    813         if(w1.getNode(w1.getNodesCount()-1).equals(w2.getNode(w2.getNodesCount()-1))) return true;
    814 
    815832        return false;
    816833    }
Note: See TracChangeset for help on using the changeset viewer.