Changeset 19272 in josm


Ignore:
Timestamp:
2024-12-19T22:13:29+01:00 (13 hours ago)
Author:
taylor.smock
Message:

See #24046: Reduce cost of Geometry#filterInsidePolygon when a primitive is a relation

This was done by checking that the bounds of the polygon contain the bounds of
the multipolygon ring before creating an area from the multipolygon ring.

If the polygon does not contain the bounds of the ring, then at least part
of the ring is outside the polygon, and thus is not inside the polygon.

Measurements using validators at (57.5183581,-75.0512982),(57.2181217,-73.9434821):

  • CPU: -87%
  • Memory: -62%

Please note that the test area is still very expensive in
Geometry#filterInsideMultipolygon (note the Multipolygon).

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/tools/Geometry.java

    r18990 r19272  
    705705        inter.intersect(a2);
    706706
     707        // Note: Area has an equals method that takes Area; it does _not_ override the Object.equals method.
    707708        if (inter.isEmpty() || !checkIntersection(inter, eps)) {
    708709            return new Pair<>(PolygonIntersection.OUTSIDE, inter);
     
    11961197                for (PolyData outer : mp.getOuterPolygons()) {
    11971198                    if (!outer.isClosed()
     1199                            || !polygonArea.getBounds2D().contains(outer.getBounds())
    11981200                            || PolygonIntersection.FIRST_INSIDE_SECOND != polygonIntersection(getArea(outer.getNodes()),
    11991201                                    polygonArea)) {
  • trunk/test/unit/org/openstreetmap/josm/tools/GeometryTest.java

    r18675 r19272  
    22package org.openstreetmap.josm.tools;
    33
     4import static org.junit.jupiter.api.Assertions.assertAll;
    45import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
    56import static org.junit.jupiter.api.Assertions.assertEquals;
     
    1516import java.util.ArrayList;
    1617import java.util.Arrays;
     18import java.util.Collection;
    1719import java.util.Collections;
    1820import java.util.List;
     
    2931import org.openstreetmap.josm.data.coor.LatLon;
    3032import org.openstreetmap.josm.data.osm.DataSet;
     33import org.openstreetmap.josm.data.osm.IPrimitive;
    3134import org.openstreetmap.josm.data.osm.Node;
    3235import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    574577    }
    575578
     579    @Test
     580    void testFilterInsidePolygon() {
     581        final Way polygon = TestUtils.newWay("", new Node(new LatLon(39.0673254, -108.5610777)),
     582                new Node(new LatLon(39.0672673, -108.561012)),
     583                new Node(new LatLon(39.0673414, -108.5609747)));
     584        polygon.addNode(polygon.firstNode());
     585        final Node out1 = new Node(new LatLon(39.0673259, -108.5610835));
     586        final Node out2 = new Node(new LatLon(39.067263, -108.5610113));
     587        final Node out3 = new Node(new LatLon(39.0673434, -108.5609708));
     588        final Node out4 = new Node(new LatLon(39.067336, -108.5610312));
     589        final Node out5 = new Node(new LatLon(39.0672963, -108.5610448));
     590        final Node in1 = new Node(new LatLon(39.0672965, -108.5610446));
     591        final Node in2 = new Node(new LatLon(39.0673009, -108.5609964));
     592        final Node in3 = new Node(new LatLon(39.0673315, -108.5610294));
     593        int i = 1;
     594        for (final Node node : Arrays.asList(out1, out2, out3, out4, out5)) {
     595            node.put("name", "out" + i++);
     596        }
     597        i = 1;
     598        for (final Node node : Arrays.asList(in1, in2, in3)) {
     599            node.put("name", "in" + i++);
     600        }
     601        // Not closed, ignored
     602        final Way win1 = TestUtils.newWay("name=win1", in1, in2, in3);
     603        final Way win2 = TestUtils.newWay("name=win2", in1, in2, in3, in1);
     604        final Way wout1 = TestUtils.newWay("name=wout1", out1, out2, out3, out1);
     605        final Relation rin1 = TestUtils.newRelation("type=multipolygon name=rin1", new RelationMember("outer", win2));
     606        // Ignored, not multipolygon
     607        final Relation rin2 = TestUtils.newRelation("name=rin2", new RelationMember("outer", win2));
     608        // Ignored, sole outer is not closed
     609        final Relation rin3 = TestUtils.newRelation("type=multipolygon name=rin3", new RelationMember("outer", win1));
     610        final Relation rout1 = TestUtils.newRelation("type=multipolygon name=rout1", new RelationMember("outer", wout1));
     611        final Collection<IPrimitive> result = Geometry.filterInsidePolygon(Arrays.asList(out1, out2, out3, out4, out5, in1, in2, in3,
     612                win1, win2, wout1, rin1, rin2, rin3, rout1), polygon);
     613        assertAll(() -> assertTrue(result.contains(in1)),
     614                () -> assertTrue(result.contains(in2)),
     615                () -> assertTrue(result.contains(in3)),
     616                () -> assertTrue(result.contains(win2)),
     617                () -> assertTrue(result.contains(rin1)));
     618        assertEquals(5, result.size(), () -> {
     619            final List<IPrimitive> notExpected = new ArrayList<>(result);
     620            notExpected.removeAll(Arrays.asList(in1, in2, in3, win2, rin1));
     621            return notExpected.stream().map(p -> p.get("name")).collect(Collectors.joining("\n"));
     622        });
     623    }
     624
    576625    /**
    577626     * A non-regression test for an issue found during the investigation of #22684 (see comment:3 by GerdP)
Note: See TracChangeset for help on using the changeset viewer.