Ignore:
Timestamp:
2007-09-04T10:21:49+02:00 (19 years ago)
Author:
imi
Message:
  • removed MinML2 dependency (use javax.xml)
  • fixed reorder action (thanks Robert)
  • added backup files before saving (thanks Dave)
  • added search for last modifying user (thanks Dave)
  • fixed import of plugin list and added author field (thanks Shaun)
File:
1 edited

Legend:

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

    r301 r319  
    1 // License: GPL. Copyright 2007 by Immanuel Scholz and others
     1//License: GPL. Copyright 2007 by Immanuel Scholz and others
    22package org.openstreetmap.josm.actions;
    33
     
    1010import java.util.Iterator;
    1111import java.util.LinkedList;
     12import java.util.HashMap;
    1213
    1314import javax.swing.JOptionPane;
     
    2728        public ReorderAction() {
    2829                super(tr("Reorder Segments"), "reorder", tr("Try to reorder segments of a way so that they are in a line. May try to flip segments around to match a line."), KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK, true);
    29     }
    30        
     30        }
     31
    3132        /**
    3233         * This method first sorts all the segments in a way, then makes sure that all
     
    3839                        if (osm instanceof Way)
    3940                                ways.add((Way)osm);
    40                
     41
    4142                if (ways.size() < 1) {
    4243                        JOptionPane.showMessageDialog(Main.parent, tr("Please select at least one way."));
    4344                        return;
    4445                }
    45                
     46
    4647                if (ways.size() > 1) {
    4748                        int answer = JOptionPane.showConfirmDialog(Main.parent,
    48                                 trn(null, "You selected more than one way. Reorder the segments of {0} ways?", ways.size(), ways.size()),
    49                                 tr("Reorder segments"), JOptionPane.OK_CANCEL_OPTION);
     49                                        trn(null, "You selected more than one way. Reorder the segments of {0} ways?", ways.size(), ways.size()),
     50                                        tr("Reorder segments"), JOptionPane.OK_CANCEL_OPTION);
    5051                        if (answer != JOptionPane.OK_OPTION)
    5152                                return;
     
    7576         * the segments are facing the same direction as the first one.
    7677         * @param way The way to reorder
    77     * @return The command needed to reorder the way
    78     */
    79     public static Command reorderWay(Way way) {
    80             final LinkedList<Segment> sel = new LinkedList<Segment>(sortSegments(new LinkedList<Segment>(way.segments), false));       
    81 
    82             Collection<Command> c = new LinkedList<Command>();
    83 
    84             boolean direction = false;
    85             // work out the "average" direction of the way, we use this to direct the rest of the segments
    86             int dirCounter = 0;
    87             for(int i = 0; i < sel.size() - 1; i++)
    88             {
    89                 Segment firstSegment = sel.get(i);
    90                 Segment secondSegment = sel.get(i+1);
    91                 if ( firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to ) // direction = true when 'from' is the first node in the Way
    92                         dirCounter++;
    93                 else
    94                         dirCounter--;
    95             }
    96             if ( dirCounter <= 0 )
    97                 direction = false;
    98             else
    99                 direction = true;
    100            
    101             Node lastNode = null;
    102 
    103             // we need to calculate what the first node in the way is, we work from there
    104             Segment firstSegment = sel.getFirst();
    105             Segment secondSegment = sel.get(1);
    106             if (firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to)
    107                 lastNode = firstSegment.from;
    108             else
    109                 lastNode = firstSegment.to;
    110            
    111             // go through each segment and flip them if required
    112             for (Segment s : sel) {
    113                 Segment snew = new Segment(s);
    114                 boolean segDirection = s.from == lastNode;
    115                 // segDirection = true when the 'from' node occurs before the 'to' node in the Way
    116                 if (direction != segDirection)
    117                 {                       
    118                         // reverse the segment's direction
    119                         Node n = snew.from;
    120                         snew.from = snew.to;
    121                         snew.to = n;
    122                         c.add(new ChangeCommand(s, snew));
    123                 }       
    124                
    125                 if (direction) // if its facing forwards,
    126                         lastNode = snew.to; // our next node is the 'to' one
    127                 else
    128                         lastNode = snew.from; // otherwise its the 'from' one
    129             }
    130 
    131             LinkedList<Segment> segments = new LinkedList<Segment>();
    132            
    133             // Now we recreate the segment list, in the correct order of the direction
    134             for (Segment s : sel)
    135                 if (!direction)
    136                         segments.addFirst(s);
    137                 else
    138                         segments.addLast(s);
    139                
    140             // Check if the new segment list is actually different from the old one
    141             // before we go and add a change command for it
    142             for(int i = 0; i < segments.size(); i++)
    143                 if (way.segments.get(i) != segments.get(i))
    144                 {
    145                         Way newWay = new Way(way);
    146                         newWay.segments.clear();
    147                         newWay.segments.addAll(segments);
    148                         c.add(new ChangeCommand(way, newWay));
    149                         break;
    150                 }
    151            
    152             // Check we've got some change commands before we add a sequence command
     78        * @return The command needed to reorder the way
     79        */
     80        public static Command reorderWay(Way way) {
     81                final LinkedList<Segment> sel = new LinkedList<Segment>(sortSegments(new LinkedList<Segment>(way.segments), false));   
     82
     83                Collection<Command> c = new LinkedList<Command>();
     84
     85                boolean direction = false;
     86                // work out the "average" direction of the way, we use this to direct the rest of the segments
     87                int dirCounter = 0;
     88                for(int i = 0; i < sel.size() - 1; i++)
     89                {
     90                        Segment firstSegment = sel.get(i);
     91                        Segment secondSegment = sel.get(i+1);
     92                        if ( firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to ) // direction = true when 'from' is the first node in the Way
     93                                dirCounter++;
     94                        else
     95                                dirCounter--;
     96                }
     97                if ( dirCounter <= 0 )
     98                        direction = false;
     99                else
     100                        direction = true;
     101
     102                Node lastNode = null;
     103
     104                // we need to calculate what the first node in the way is, we work from there
     105                Segment firstSegment = sel.getFirst();
     106                Segment secondSegment = sel.get(1);
     107                if (firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to)
     108                        lastNode = firstSegment.from;
     109                else
     110                        lastNode = firstSegment.to;
     111
     112                // go through each segment and flip them if required
     113                for (Segment s : sel) {
     114                        Segment snew = new Segment(s);
     115                        boolean segDirection = s.from == lastNode;
     116                        // segDirection = true when the 'from' node occurs before the 'to' node in the Way
     117                        if (direction != segDirection)
     118                        {                       
     119                                // reverse the segment's direction
     120                                Node n = snew.from;
     121                                snew.from = snew.to;
     122                                snew.to = n;
     123                                c.add(new ChangeCommand(s, snew));
     124                        }       
     125
     126                        if (direction) // if its facing forwards,
     127                                lastNode = snew.to; // our next node is the 'to' one
     128                        else
     129                                lastNode = snew.from; // otherwise its the 'from' one
     130                }
     131
     132                LinkedList<Segment> segments = new LinkedList<Segment>();
     133
     134                // Now we recreate the segment list, in the correct order of the direction
     135                for (Segment s : sel)
     136                        if (!direction)
     137                                segments.addFirst(s);
     138                        else
     139                                segments.addLast(s);
     140
     141                // Check if the new segment list is actually different from the old one
     142                // before we go and add a change command for it
     143                for(int i = 0; i < segments.size(); i++)
     144                        if (way.segments.get(i) != segments.get(i))
     145                        {
     146                                Way newWay = new Way(way);
     147                                newWay.segments.clear();
     148                                newWay.segments.addAll(segments);
     149                                c.add(new ChangeCommand(way, newWay));
     150                                break;
     151                        }
     152
     153                // Check we've got some change commands before we add a sequence command
    153154                if (c.size() != 0) {
    154155                        NameVisitor v = new NameVisitor();
     
    157158                }
    158159                return null;
    159     }
     160        }
    160161
    161162        /**
     
    168169         */
    169170        public static LinkedList<Segment> sortSegments(LinkedList<Segment> segments, boolean strict) {
    170                
     171
    171172                LinkedList<Segment> sortedSegments = new LinkedList<Segment>();
    172                
     173
    173174                while (!segments.isEmpty()) {
    174175                        LinkedList<Segment> pivotList = new LinkedList<Segment>();
    175                         pivotList.add(segments.getFirst());
    176                         segments.removeFirst();
     176                        pivotList.add(firstSegment(segments));
     177                        segments.remove(pivotList.getLast());
    177178                        boolean found;
    178179                        do {
    179180                                found = false;
     181                                //try working forwards first
    180182                                for (Iterator<Segment> it = segments.iterator(); it.hasNext();) {
    181183                                        Segment ls = it.next();
    182184                                        if (ls.incomplete)
    183185                                                continue; // incomplete segments are never added to a new way
    184                                         if (ls.from == pivotList.getLast().to || (!strict && (ls.to == pivotList.getLast().to || ls.from == pivotList.getLast().from || ls.to == pivotList.getLast().from))) {
     186                                        if (ls.from == pivotList.getLast().to) {
    185187                                                pivotList.addLast(ls);
    186188                                                it.remove();
    187189                                                found = true;
    188                                         } else if (ls.to == pivotList.getFirst().from || (!strict && (ls.from == pivotList.getFirst().from || ls.to == pivotList.getFirst().to || ls.from == pivotList.getFirst().to))) {
    189                                                 pivotList.addFirst(ls);
    190                                                 it.remove();
    191                                                 found = true;
     190                                        }
     191                                }
     192                                if(!found){
     193                                        for (Iterator<Segment> it = segments.iterator(); it.hasNext();) {
     194                                                Segment ls = it.next();
     195                                                if (ls.incomplete)
     196                                                        continue; // incomplete segments are never added to a new way
     197                                                if (ls.from == pivotList.getLast().to || (!strict && (ls.to == pivotList.getLast().to || ls.from == pivotList.getLast().from || ls.to == pivotList.getLast().from))) {
     198                                                        pivotList.addLast(ls);
     199                                                        it.remove();
     200                                                        found = true;
     201                                                } else if (ls.to == pivotList.getFirst().from || (!strict && (ls.from == pivotList.getFirst().from || ls.to == pivotList.getFirst().to || ls.from == pivotList.getFirst().to))) {
     202                                                        pivotList.addFirst(ls);
     203                                                        it.remove();
     204                                                        found = true;
     205                                                }
    192206                                        }
    193207                                }
     
    195209                        sortedSegments.addAll(pivotList);
    196210                }
    197             return sortedSegments;
    198         }
     211                return sortedSegments;
     212        }
     213
     214        /**
     215         * This method searches for a good segment to start a reorder from.
     216         * In most cases this will be a segment with a start node that occurs only
     217         * once in the way. In cases with loops, this could be any odd number. If no nodes
     218         * are referenced an odd number of times, then any segment is a good start point.
     219         */
     220        public static Segment firstSegment(Collection<Segment> segments) {
     221                HashMap<Node, Integer> refCount = new HashMap<Node, Integer>(segments.size()*2);
     222                //loop through all segments and count up how many times each node is referenced
     223                for (Segment seg : segments) {
     224                        if (!refCount.containsKey(seg.from))
     225                                refCount.put(seg.from, 0);
     226                        refCount.put(seg.from,refCount.get(seg.from)+1);
     227
     228                        if (!refCount.containsKey(seg.to))
     229                                refCount.put(seg.to, 0);
     230                        refCount.put(seg.to,refCount.get(seg.to)+1);
     231                }
     232
     233                //now look for start nodes that are referenced only once
     234                for (Segment seg : segments)
     235                        if (refCount.get(seg.from) == 1)
     236                                return seg;
     237                //now look for start nodes that are referenced only (2n+1)
     238                for (Segment seg : segments)
     239                        if (refCount.get(seg.from) % 2 == 1)
     240                                return seg;
     241                //now look for end nodes that are referenced only once
     242                for (Segment seg : segments)
     243                        if (refCount.get(seg.to) == 1)
     244                                return seg;
     245                //now look for end nodes that are referenced only (2n+1)
     246                for (Segment seg : segments)
     247                        if (refCount.get(seg.to) % 2 == 1)
     248                                return seg;
     249
     250                return segments.iterator().next();
     251        }   
    199252}
Note: See TracChangeset for help on using the changeset viewer.