Ignore:
Timestamp:
2015-05-01T21:33:01+02:00 (5 years ago)
Author:
Balaitous
Message:

fix #7421 - Circle created from way heads always clockwise

  • If 3 nodes closed way is selected, keep way direction when creating circle;
  • Otherwise use left- and right-hand traffic database (r7193) to determine way direction;
  • Add a Geometry.isClockwise(List<Node>) method;
  • Fix some sonar issue
  • Add test case
File:
1 edited

Legend:

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

    r8285 r8303  
    1010import java.util.Arrays;
    1111import java.util.Collection;
     12import java.util.Collections;
    1213import java.util.Comparator;
    1314import java.util.LinkedList;
     
    2829import org.openstreetmap.josm.gui.Notification;
    2930import org.openstreetmap.josm.tools.Geometry;
     31import org.openstreetmap.josm.tools.RightAndLefthandTraffic;
    3032import org.openstreetmap.josm.tools.Shortcut;
    3133
     
    115117        @Override
    116118        public int compare(PolarNode pc1, PolarNode pc2) {
    117             if(pc1.a < pc2.a)
    118                 return -1;
    119             else if(pc1.a == pc2.a)
    120                 return 0;
    121             else
    122                 return 1;
     119            return Double.compare(pc1.a, pc2.a);
    123120        }
    124121    }
     
    137134
    138135        Collection<OsmPrimitive> sel = getCurrentDataSet().getSelected();
    139         List<Node> nodes = new LinkedList<>();
     136        List<Node> nodes = OsmPrimitive.getFilteredList(sel, Node.class);
     137        List<Way> ways = OsmPrimitive.getFilteredList(sel, Way.class);
     138
    140139        Way existingWay = null;
    141 
    142         for (OsmPrimitive osm : sel)
    143             if (osm instanceof Node) {
    144                 nodes.add((Node)osm);
    145             }
    146140
    147141        // special case if no single nodes are selected and exactly one way is:
    148142        // then use the way's nodes
    149         if (nodes.isEmpty() && (sel.size() == 1)) {
    150             for (OsmPrimitive osm : sel)
    151                 if (osm instanceof Way) {
    152                     existingWay = ((Way)osm);
    153                     for (Node n : ((Way)osm).getNodes())
    154                     {
    155                         if(!nodes.contains(n)) {
    156                             nodes.add(n);
    157                         }
    158                     }
     143        if (nodes.isEmpty() && (ways.size() == 1)) {
     144            existingWay = ways.get(0);
     145            for (Node n : existingWay.getNodes()) {
     146                if(!nodes.contains(n)) {
     147                    nodes.add(n);
    159148                }
     149            }
    160150        }
    161151
     
    210200
    211201        // build a way for the circle
    212         List<Node> wayToAdd = new ArrayList<>();
     202        List<Node> nodesToAdd = new ArrayList<>();
    213203        for(int i = 0; i < nodes.size(); i++) {
    214             wayToAdd.add(angles[i].node);
     204            nodesToAdd.add(angles[i].node);
    215205            double delta = angles[(i+1) % nodes.size()].a - angles[i].a;
    216206            if(delta < 0)
     
    226216                }
    227217                Node n = new Node(ll);
    228                 wayToAdd.add(n);
     218                nodesToAdd.add(n);
    229219                cmds.add(new AddCommand(n));
    230220            }
    231221        }
    232         wayToAdd.add(wayToAdd.get(0)); // close the circle
     222        nodesToAdd.add(nodesToAdd.get(0)); // close the circle
     223        if (existingWay != null && existingWay.getNodesCount() >= 3) {
     224            nodesToAdd = orderNodesByWay(nodesToAdd, existingWay);
     225        } else {
     226            nodesToAdd = orderNodesByTrafficHand(nodesToAdd);
     227        }
    233228        if (existingWay == null) {
    234229            Way newWay = new Way();
    235             newWay.setNodes(wayToAdd);
     230            newWay.setNodes(nodesToAdd);
    236231            cmds.add(new AddCommand(newWay));
    237232        } else {
    238233            Way newWay = new Way(existingWay);
    239             newWay.setNodes(wayToAdd);
     234            newWay.setNodes(nodesToAdd);
    240235            cmds.add(new ChangeCommand(existingWay, newWay));
    241236        }
     
    243238        Main.main.undoRedo.add(new SequenceCommand(tr("Create Circle"), cmds));
    244239        Main.map.repaint();
     240    }
     241
     242    /**
     243     * Order nodes according to left/right hand traffic.
     244     * @param nodes Nodes list to be ordered.
     245     * @return Modified nodes list ordered according hand traffic.
     246     */
     247    private List<Node> orderNodesByTrafficHand(List<Node> nodes) {
     248        boolean rightHandTraffic = true;
     249        for (Node n: nodes) {
     250            if (!RightAndLefthandTraffic.isRightHandTraffic(n.getCoor())) {
     251                rightHandTraffic = false;
     252                break;
     253            }
     254        }
     255        if (rightHandTraffic == Geometry.isClockwise(nodes)) {
     256            Collections.reverse(nodes);
     257        }
     258        return nodes;
     259    }
     260
     261    /**
     262     * Order nodes according to way direction.
     263     * @param nodes Nodes list to be ordered.
     264     * @param way Way used to determine direction.
     265     * @return Modified nodes list with same direction as way.
     266     */
     267    private List<Node> orderNodesByWay(List<Node> nodes, Way way) {
     268        List<Node> wayNodes = way.getNodes();
     269        if (!way.isClosed()) {
     270            wayNodes.add(wayNodes.get(0));
     271        }
     272        if (Geometry.isClockwise(wayNodes) != Geometry.isClockwise(nodes)) {
     273            Collections.reverse(nodes);
     274        }
     275        return nodes;
    245276    }
    246277
Note: See TracChangeset for help on using the changeset viewer.