Ticket #16189: 0001-Introduce-almost-square-check-for-buildings.patch

File 0001-Introduce-almost-square-check-for-buildings.patch, 10.2 KB (added by marxin, 6 years ago)

Update version

  • src/org/openstreetmap/josm/data/osm/Way.java

    From dcf3f22e5a25361fb35e4c673b95457575a66ca3 Mon Sep 17 00:00:00 2001
    From: marxin <mliska@suse.cz>
    Date: Sun, 4 Mar 2018 10:25:28 +0100
    Subject: [PATCH] Introduce almost square check for buildings.
    
    ---
     src/org/openstreetmap/josm/data/osm/Way.java       | 36 ++++++++++++
     .../josm/data/validation/OsmValidator.java         |  2 +
     .../validation/tests/RightAngleBuildingTest.java   | 66 ++++++++++++++++++++++
     src/org/openstreetmap/josm/tools/Geometry.java     | 10 ++++
     .../org/openstreetmap/josm/data/osm/WayTest.java   |  1 +
     .../org/openstreetmap/josm/tools/GeometryTest.java | 36 ++++++++++++
     6 files changed, 151 insertions(+)
     create mode 100644 src/org/openstreetmap/josm/data/validation/tests/RightAngleBuildingTest.java
    
    diff --git a/src/org/openstreetmap/josm/data/osm/Way.java b/src/org/openstreetmap/josm/data/osm/Way.java
    index 8fd0cef49..f28cef9ff 100644
    a b import org.openstreetmap.josm.data.osm.visitor.OsmPrimitiveVisitor;  
    1515import org.openstreetmap.josm.data.osm.visitor.PrimitiveVisitor;
    1616import org.openstreetmap.josm.spi.preferences.Config;
    1717import org.openstreetmap.josm.tools.CopyList;
     18import org.openstreetmap.josm.tools.Geometry;
     19import org.openstreetmap.josm.tools.Logging;
    1820import org.openstreetmap.josm.tools.Pair;
    1921import org.openstreetmap.josm.tools.Utils;
    2022
    public final class Way extends OsmPrimitive implements IWay {  
    805807            n.clearCachedStyle();
    806808        }
    807809    }
     810
     811    /**
     812     * Returns angles of vertices.
     813     *
     814     * @return angles of the way
     815     * @since xxx
     816     */
     817    public List<Pair<Double, Node>> getAngles() {
     818        List<Pair<Double, Node>> angles = new ArrayList<Pair<Double, Node>>();
     819
     820        List<Node> nodes = getNodes();
     821        int count = getNodesCount();
     822
     823        for (int i = 0; i < count; i++)
     824            Logging.info(nodes.get(i).toString());
     825
     826        for (int i = 1; i < count - 1; i++)
     827        {
     828            Node n0 = nodes.get(i - 1);
     829            Node n1 = nodes.get(i);
     830            Node n2 = nodes.get(i + 1);
     831
     832            double angle = Geometry.getNormalizedAngleInDegrees(Geometry.getCornerAngle(n0.getEastNorth(), n1.getEastNorth(),
     833                    n2.getEastNorth()));
     834            angles.add(new Pair<Double, Node>(angle, n1));
     835        }
     836
     837        angles.add(new Pair<Double, Node>(Geometry.getNormalizedAngleInDegrees(Geometry.getCornerAngle(
     838                nodes.get(count - 2).getEastNorth(),
     839                nodes.get(0).getEastNorth(),
     840                nodes.get(1).getEastNorth())), nodes.get(0)));
     841
     842        return angles;
     843    }
    808844}
  • src/org/openstreetmap/josm/data/validation/OsmValidator.java

    diff --git a/src/org/openstreetmap/josm/data/validation/OsmValidator.java b/src/org/openstreetmap/josm/data/validation/OsmValidator.java
    index 30a2661fe..4cf70c621 100644
    a b import org.openstreetmap.josm.data.validation.tests.OverlappingWays;  
    5252import org.openstreetmap.josm.data.validation.tests.PowerLines;
    5353import org.openstreetmap.josm.data.validation.tests.PublicTransportRouteTest;
    5454import org.openstreetmap.josm.data.validation.tests.RelationChecker;
     55import org.openstreetmap.josm.data.validation.tests.RightAngleBuildingTest;
    5556import org.openstreetmap.josm.data.validation.tests.SelfIntersectingWay;
    5657import org.openstreetmap.josm.data.validation.tests.SimilarNamedWays;
    5758import org.openstreetmap.josm.data.validation.tests.TagChecker;
    public final class OsmValidator {  
    139140        ApiCapabilitiesTest.class, // 3400 .. 3499
    140141        LongSegment.class, // 3500 .. 3599
    141142        PublicTransportRouteTest.class, // 3600 .. 3699
     143        RightAngleBuildingTest.class, // 3700 .. 3799
    142144    };
    143145
    144146    /**
  • new file src/org/openstreetmap/josm/data/validation/tests/RightAngleBuildingTest.java

    diff --git a/src/org/openstreetmap/josm/data/validation/tests/RightAngleBuildingTest.java b/src/org/openstreetmap/josm/data/validation/tests/RightAngleBuildingTest.java
    new file mode 100644
    index 000000000..15ee55250
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.validation.tests;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
     6import org.openstreetmap.josm.data.osm.Node;
     7import org.openstreetmap.josm.data.osm.Way;
     8import org.openstreetmap.josm.data.validation.Severity;
     9import org.openstreetmap.josm.data.validation.Test;
     10import org.openstreetmap.josm.data.validation.TestError;
     11import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     12import org.openstreetmap.josm.spi.preferences.Config;
     13import org.openstreetmap.josm.tools.Pair;
     14
     15/**
     16 * Checks for buildings with angles close to right angle.
     17 *
     18 * @since xxx
     19 */
     20public class RightAngleBuildingTest extends Test {
     21
     22    /** Maximum angle difference from right angle that is considered as invalid. */
     23    protected double maxAngleDelta;
     24
     25    /** Minimum angle difference from right angle that is considered as invalid. */
     26    protected double minAngleDelta;
     27
     28    /**
     29     * Constructs a new {@code RightAngleBuildingTest} test.
     30     */
     31    public RightAngleBuildingTest() {
     32        super(tr("Almost right angle buildings"),
     33                tr("Checks for buildings that have angles close to right angle and are not orthogonalized."));
     34    }
     35
     36    @Override
     37    public void visit(Way w) {
     38        if (!w.isUsable() || !w.isClosed() || !isBuilding(w)) return;
     39
     40        for (Pair<Double, Node> pair: w.getAngles())
     41            if (!checkAngle(w, pair.a, pair.b))
     42                return;
     43    }
     44
     45    @Override
     46    public void startTest(ProgressMonitor monitor) {
     47        super.startTest(monitor);
     48        maxAngleDelta = Config.getPref().getDouble("validator.RightAngleBuilding.maximumDelta", 10.0);
     49        minAngleDelta = Config.getPref().getDouble("validator.RightAngleBuilding.minimumDelta", 0.001);
     50    }
     51
     52    private boolean checkAngle(Way w, double angle, Node n) {
     53        double difference = Math.abs(angle - 90);
     54
     55        if (difference > minAngleDelta && difference < maxAngleDelta) {
     56            errors.add(TestError.builder(this, Severity.WARNING, 3701)
     57                    .message(tr("Building with an almost square angle"))
     58                    .primitives(w)
     59                    .highlight(n)
     60                    .build());
     61            return false;
     62        }
     63
     64        return true;
     65    }
     66}
  • src/org/openstreetmap/josm/tools/Geometry.java

    diff --git a/src/org/openstreetmap/josm/tools/Geometry.java b/src/org/openstreetmap/josm/tools/Geometry.java
    index 379192e92..83e1771f5 100644
    a b public final class Geometry {  
    792792        return result;
    793793    }
    794794
     795    /** Get angles in radians and return it's value in range [0, 180].
     796    *
     797    * @param angle the angle in radians
     798    * @return normalized angle
     799    * @since xxx
     800    */
     801   public static double getNormalizedAngleInDegrees(double angle) {
     802       return Math.abs(180 * angle / Math.PI);
     803   }
     804
    795805    /**
    796806     * Compute the centroid/barycenter of nodes
    797807     * @param nodes Nodes for which the centroid is wanted
  • test/unit/org/openstreetmap/josm/data/osm/WayTest.java

    diff --git a/test/unit/org/openstreetmap/josm/data/osm/WayTest.java b/test/unit/org/openstreetmap/josm/data/osm/WayTest.java
    index e6c63c596..bcd51cddc 100644
    a b import org.junit.BeforeClass;  
    1111import org.junit.Test;
    1212import org.openstreetmap.josm.JOSMFixture;
    1313import org.openstreetmap.josm.data.coor.LatLon;
     14import org.openstreetmap.josm.tools.Geometry;
    1415
    1516/**
    1617 * Unit tests of the {@code Way} class.
  • test/unit/org/openstreetmap/josm/tools/GeometryTest.java

    diff --git a/test/unit/org/openstreetmap/josm/tools/GeometryTest.java b/test/unit/org/openstreetmap/josm/tools/GeometryTest.java
    index 1581e3cbd..d364a689b 100644
    a b  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.tools;
    33
     4import static org.junit.Assert.assertEquals;
     5
    46import java.io.FileInputStream;
    57import java.util.List;
    68
    import org.junit.Rule;  
    911import org.junit.Test;
    1012import org.openstreetmap.josm.TestUtils;
    1113import org.openstreetmap.josm.data.coor.EastNorth;
     14import org.openstreetmap.josm.data.coor.LatLon;
    1215import org.openstreetmap.josm.data.osm.DataSet;
     16import org.openstreetmap.josm.data.osm.Node;
    1317import org.openstreetmap.josm.data.osm.Relation;
    1418import org.openstreetmap.josm.data.osm.Way;
    1519import org.openstreetmap.josm.data.osm.search.SearchCompiler;
    public class GeometryTest {  
    108112            Assert.assertEquals(15093.201209424187, areaAndPerimeter.getPerimeter(), 1e-3);
    109113        }
    110114    }
     115
     116    /**
     117     * Test of {@link Geometry#getNormalizedAngleInDegrees(double) method.
     118     */
     119    @Test
     120    public void testRightAngle() {
     121        Node n1 = new Node(1);
     122        Node n2 = new Node(2);
     123        Node n3 = new Node(3);
     124        n1.setCoor(new LatLon(10.22873540462851, 6.169719398316592));
     125        n2.setCoor(new LatLon(10.229332494162811, 6.16978130985785));
     126        n3.setCoor(new LatLon(10.22924937004949, 6.17060908367496));
     127
     128        double angle = Geometry.getNormalizedAngleInDegrees(Geometry.getCornerAngle(n1.getEastNorth(),
     129                n2.getEastNorth(), n3.getEastNorth()));
     130        Assert.assertEquals(90, angle, 1e-8);
     131        angle = Geometry.getNormalizedAngleInDegrees(Geometry.getCornerAngle(n1.getEastNorth(),
     132                n2.getEastNorth(), n1.getEastNorth()));
     133        Assert.assertEquals(0, angle, 1e-8);
     134
     135        n1.setCoor(new LatLon(10.2295011, 6.1693106));
     136        n2.setCoor(new LatLon(10.2294958, 6.16930635));
     137        n3.setCoor(new LatLon(10.2294895, 6.1693039));
     138
     139        angle = Geometry.getNormalizedAngleInDegrees(Geometry.getCornerAngle(n1.getEastNorth(),
     140                n2.getEastNorth(), n3.getEastNorth()));
     141        Assert.assertEquals(162.66381817961337, angle, 1e-5);
     142
     143        angle = Geometry.getNormalizedAngleInDegrees(Geometry.getCornerAngle(n3.getEastNorth(),
     144                n2.getEastNorth(), n1.getEastNorth()));
     145        Assert.assertEquals(162.66381817961337, angle, 1e-5);
     146    }
    111147}