Changeset 4344 in josm


Ignore:
Timestamp:
2011-08-26T22:26:37+02:00 (13 years ago)
Author:
stoecker
Message:

fix #5257 - patch by simon04 - fix way order validator checks

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

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/validation/tests/WronglyOrderedWays.java

    r3674 r4344  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import java.util.ArrayList;
    7 import java.util.List;
     6import java.util.Collections;
    87
    9 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    108import org.openstreetmap.josm.data.osm.Way;
    119import org.openstreetmap.josm.data.validation.Severity;
    1210import org.openstreetmap.josm.data.validation.Test;
    1311import org.openstreetmap.josm.data.validation.TestError;
    14 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     12import org.openstreetmap.josm.tools.Geometry;
    1513
    1614/**
     
    2220
    2321    protected static int WRONGLY_ORDERED_COAST = 1001;
    24     protected static int WRONGLY_ORDERED_WATER = 1002;
     22    //protected static int WRONGLY_ORDERED_WATER = 1002;
    2523    protected static int WRONGLY_ORDERED_LAND  = 1003;
    2624
     
    3432
    3533    @Override
    36     public void startTest(ProgressMonitor monitor) {
    37         super.startTest(monitor);
    38     }
     34    public void visit(Way w) {
    3935
    40     @Override
    41     public void endTest() {
    42         super.endTest();
    43     }
    44 
    45     @Override
    46     public void visit(Way w) {
    47         String errortype = "";
    48         int type;
    49 
    50         if (!w.isUsable())
    51             return;
    52         if (w.getNodesCount() <= 0)
     36        if (!w.isUsable() || !w.isClosed())
    5337            return;
    5438
    5539        String natural = w.get("natural");
    56         if (natural == null)
     40        if (natural == null) {
    5741            return;
     42        } else if ("coastline".equals(natural) && Geometry.isClockwise(w)) {
     43            reportError(w, tr("Reversed coastline: land not on left side"), WRONGLY_ORDERED_COAST);
     44        /*} else if ("water".equals(natural) && !Geometry.isClockwise(w)) {
     45            reportError(w, tr("Reversed water: land not on left side"), WRONGLY_ORDERED_WATER);*/
     46        } else if ("land".equals(natural) && Geometry.isClockwise(w)) {
     47            reportError(w, tr("Reversed land: land not on left side"), WRONGLY_ORDERED_LAND);
     48        } else {
     49            return;
     50        }
    5851
    59         if (natural.equals("coastline")) {
    60             errortype = tr("Reversed coastline: land not on left side");
    61             type= WRONGLY_ORDERED_COAST;
    62         } else if (natural.equals("water")) {
    63             errortype = tr("Reversed water: land not on left side");
    64             type= WRONGLY_ORDERED_WATER;
    65         } else if (natural.equals("land")) {
    66             errortype = tr("Reversed land: land not on left side");
    67             type= WRONGLY_ORDERED_LAND;
    68         } else
    69             return;
     52    }
    7053
    71         /**
    72          * Test the directionality of the way
    73          *
    74          * Assuming a closed non-looping way, compute twice the area
    75          * of the polygon using the formula 2*a = sum (Xn * Yn+1 - Xn+1 * Yn)
    76          * If the area is negative the way is ordered in a clockwise direction
    77          *
    78          */
    79         if (w.getNode(0) == w.getNode(w.getNodesCount()-1)) {
    80             double area2 = 0;
    81 
    82             for (int node = 1; node < w.getNodesCount(); node++) {
    83                 area2 += (w.getNode(node-1).getCoor().lon() * w.getNode(node).getCoor().lat()
    84                 - w.getNode(node).getCoor().lon() * w.getNode(node-1).getCoor().lat());
    85             }
    86 
    87             if (((natural.equals("coastline") || natural.equals("land")) && area2 < 0.)
    88                     || (natural.equals("water") && area2 > 0.)) {
    89                 List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
    90                 primitives.add(w);
    91                 errors.add( new TestError(this, Severity.OTHER, errortype, type, primitives) );
    92             }
    93         }
     54    private void reportError(Way w, String msg, int type) {
     55        errors.add(new TestError(this, Severity.OTHER, msg, type, Collections.singletonList(w)));
    9456    }
    9557}
  • trunk/src/org/openstreetmap/josm/tools/Geometry.java

    r4134 r4344  
    1515import org.openstreetmap.josm.command.Command;
    1616import org.openstreetmap.josm.data.coor.EastNorth;
     17import org.openstreetmap.josm.data.coor.LatLon;
    1718import org.openstreetmap.josm.data.osm.BBox;
    1819import org.openstreetmap.josm.data.osm.Node;
     
    221222     */
    222223    public static boolean angleIsClockwise(Node commonNode, Node firstNode, Node secondNode) {
    223         double dy1 = (firstNode.getEastNorth().getY() - commonNode.getEastNorth().getY());
    224         double dy2 = (secondNode.getEastNorth().getY() - commonNode.getEastNorth().getY());
    225         double dx1 = (firstNode.getEastNorth().getX() - commonNode.getEastNorth().getX());
    226         double dx2 = (secondNode.getEastNorth().getX() - commonNode.getEastNorth().getX());
    227 
    228         return dy1 * dx2 - dx1 * dy2 > 0;
     224        return angleIsClockwise(commonNode.getEastNorth(), firstNode.getEastNorth(), secondNode.getEastNorth());
    229225    }
    230226
     
    527523    }
    528524
    529 
     525    /**
     526     * Determines whether a way is oriented clockwise.
     527     *
     528     * Internals: Assuming a closed non-looping way, compute twice the area
     529     * of the polygon using the formula {@code 2 * area = sum (X[n] * Y[n+1] - X[n+1] * Y[n])}.
     530     * If the area is negative the way is ordered in a clockwise direction.
     531     *
     532     * @param w the way to be checked.
     533     * @return true if and only if way is oriented clockwise.
     534     * @throws IllegalArgumentException if way is not closed (see {@see Way#isClosed}).
     535     * @see http://paulbourke.net/geometry/polyarea/
     536     */
     537    public static boolean isClockwise(Way w) {
     538        if (!w.isClosed()) {
     539            throw new IllegalArgumentException("Way must be closed to check orientation.");
     540        }
     541
     542        double area2 = 0.;
     543        int nodesCount = w.getNodesCount();
     544
     545        for (int node = 1; node <= /*sic! consider last-first as well*/ nodesCount; node++) {
     546            LatLon coorPrev = w.getNode(node - 1).getCoor();
     547            LatLon coorCurr = w.getNode(node % nodesCount).getCoor();
     548            area2 += coorPrev.lon() * coorCurr.lat();
     549            area2 -= coorCurr.lon() * coorPrev.lat();
     550        }
     551        return area2 < 0;
     552    }
    530553}
Note: See TracChangeset for help on using the changeset viewer.