Ticket #24046: 24046.1.patch

File 24046.1.patch, 14.2 KB (added by taylor.smock, 12 months ago)

Cache stored in test

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

    Subject: [PATCH] 24046
    ---
    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/src/org/openstreetmap/josm/data/osm/MultipolygonBuilder.java b/src/org/openstreetmap/josm/data/osm/MultipolygonBuilder.java
    a b  
    154154     * @throws JoinedPolygonCreationException if the creation fails.
    155155     */
    156156    public static Pair<List<JoinedPolygon>, List<JoinedPolygon>> joinWays(Relation multipolygon) {
     157        return joinWays(null, multipolygon);
     158    }
     159
     160    /**
     161     * Joins the given {@code multipolygon} to a pair of outer and inner multipolygon rings.
     162     *
     163     * @param multipolygon the multipolygon to join.
     164     * @return a pair of outer and inner multipolygon rings.
     165     * @throws JoinedPolygonCreationException if the creation fails.
     166     * @since xxx
     167     */
     168    public static Pair<List<JoinedPolygon>, List<JoinedPolygon>> joinWays(
     169            Map<IRelation<?>, Pair<List<JoinedPolygon>, List<JoinedPolygon>>> cache, Relation multipolygon) {
     170        if (cache != null) {
     171            return cache.computeIfAbsent(multipolygon, MultipolygonBuilder::joinWaysActual);
     172        }
     173        return joinWaysActual(multipolygon);
     174    }
     175
     176    /**
     177     * Perform the actual join ways calculation
     178     *
     179     * @param multipolygon the multipolygon to join.
     180     * @return a pair of outer and inner multipolygon rings.
     181     * @throws JoinedPolygonCreationException if the creation fails.
     182     */
     183    private static Pair<List<JoinedPolygon>, List<JoinedPolygon>> joinWaysActual(IRelation<?> multipolygon) {
    157184        CheckParameterUtil.ensureThat(multipolygon.isMultipolygon(), "multipolygon.isMultipolygon");
    158         final Map<String, Set<Way>> members = multipolygon.getMembers().stream()
    159                 .filter(RelationMember::isWay)
    160                 .collect(Collectors.groupingBy(RelationMember::getRole, Collectors.mapping(RelationMember::getWay, Collectors.toSet())));
     185        CheckParameterUtil.ensureThat(multipolygon instanceof Relation,
     186                "This method currently only supports Relation objects due to potential breakage");
     187        final Map<String, Set<Way>> members = ((Relation) multipolygon).getMembers().stream()
     188                .filter(IRelationMember::isWay)
     189                .collect(Collectors.groupingBy(IRelationMember::getRole, Collectors.mapping(RelationMember::getWay, Collectors.toSet())));
    161190        final List<JoinedPolygon> outerRings = joinWays(members.getOrDefault("outer", Collections.emptySet()));
    162191        final List<JoinedPolygon> innerRings = joinWays(members.getOrDefault("inner", Collections.emptySet()));
    163192        return Pair.create(outerRings, innerRings);
  • src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java b/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
    a b  
    2424import java.util.stream.Stream;
    2525
    2626import org.openstreetmap.josm.data.osm.IPrimitive;
     27import org.openstreetmap.josm.data.osm.IRelation;
     28import org.openstreetmap.josm.data.osm.MultipolygonBuilder.JoinedPolygon;
    2729import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2830import org.openstreetmap.josm.data.preferences.BooleanProperty;
    2931import org.openstreetmap.josm.data.preferences.CachingProperty;
     
    4951import org.openstreetmap.josm.tools.I18n;
    5052import org.openstreetmap.josm.tools.Logging;
    5153import org.openstreetmap.josm.tools.MultiMap;
     54import org.openstreetmap.josm.tools.Pair;
    5255import org.openstreetmap.josm.tools.Stopwatch;
    5356import org.openstreetmap.josm.tools.Utils;
    5457
     
    6063    private MapCSSStyleIndex indexData;
    6164    private final Map<MapCSSRule, MapCSSTagCheckerAndRule> ruleToCheckMap = new HashMap<>();
    6265    private static final Map<IPrimitive, Area> mpAreaCache = new HashMap<>();
     66    private static final Map<IRelation<?>, Pair<List<JoinedPolygon>, List<JoinedPolygon>>> mpJoinedAreaCache = new HashMap<>();
    6367    private static final Set<IPrimitive> toMatchForSurrounding = new HashSet<>();
    6468    static final boolean ALL_TESTS = true;
    6569    static final boolean ONLY_SELECTED_TESTS = false;
     
    163167
    164168        final Environment env = new Environment(p, new MultiCascade(), Environment.DEFAULT_LAYER, null);
    165169        env.mpAreaCache = mpAreaCache;
     170        env.mpJoinedAreaCache = mpJoinedAreaCache;
    166171        env.toMatchForSurrounding = toMatchForSurrounding;
    167172
    168173        Iterator<MapCSSRule> candidates = indexData.getRuleCandidates(p);
     
    221226        final List<TestError> r = new ArrayList<>();
    222227        final Environment env = new Environment(p, new MultiCascade(), Environment.DEFAULT_LAYER, null);
    223228        env.mpAreaCache = mpAreaCache;
     229        env.mpJoinedAreaCache = mpJoinedAreaCache;
    224230        env.toMatchForSurrounding = toMatchForSurrounding;
    225231        for (Set<MapCSSTagCheckerRule> schecks : checksCol) {
    226232            for (MapCSSTagCheckerRule check : schecks) {
     
    376382        // always clear the cache to make sure that we catch changes in geometry
    377383        mpAreaCache.clear();
    378384        ruleToCheckMap.clear();
     385        mpJoinedAreaCache.clear();
    379386        toMatchForSurrounding.clear();
    380387        super.endTest();
    381388    }
     
    396403        }
    397404
    398405        mpAreaCache.clear();
     406        mpJoinedAreaCache.clear();
    399407        toMatchForSurrounding.clear();
    400408
    401409        Set<OsmPrimitive> surrounding = new HashSet<>();
  • src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
    a b  
    490490            public void visit(IRelation<?> r) {
    491491                if (r instanceof Relation && r.isMultipolygon() && r.getBBox().bounds(e.osm.getBBox())
    492492                        && left.matches(new Environment(r).withParent(e.osm))
    493                         && !Geometry.filterInsideMultipolygon(Collections.singletonList(e.osm), (Relation) r).isEmpty()) {
     493                        && !Geometry.filterInsideMultipolygon(Collections.singletonList(e.osm), (Relation) r, e.mpJoinedAreaCache).isEmpty()) {
    494494                    addToChildren(e, r);
    495495                }
    496496            }
  • src/org/openstreetmap/josm/gui/mappaint/Environment.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/src/org/openstreetmap/josm/gui/mappaint/Environment.java b/src/org/openstreetmap/josm/gui/mappaint/Environment.java
    a b  
    88import java.util.Set;
    99
    1010import org.openstreetmap.josm.data.osm.IPrimitive;
     11import org.openstreetmap.josm.data.osm.IRelation;
     12import org.openstreetmap.josm.data.osm.MultipolygonBuilder;
    1113import org.openstreetmap.josm.data.osm.Relation;
    1214import org.openstreetmap.josm.data.osm.Way;
    1315import org.openstreetmap.josm.data.osm.WaySegment;
     
    1517import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
    1618import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector;
    1719import org.openstreetmap.josm.tools.CheckParameterUtil;
     20import org.openstreetmap.josm.tools.Pair;
    1821
    1922/**
    2023 * Environment is a data object to provide access to various "global" parameters.
     
    9093     * Cache for multipolygon areas, can be null, used with CrossingFinder
    9194     */
    9295    public Map<IPrimitive, Area> mpAreaCache;
     96    /**
     97     * Cache for multipolygon areas as calculated by {@link MultipolygonBuilder#joinWays(Relation)}, can be {@code null}
     98     */
     99    public Map<IRelation<?>, Pair<List<MultipolygonBuilder.JoinedPolygon>, List<MultipolygonBuilder.JoinedPolygon>>> mpJoinedAreaCache;
    93100
    94101    /**
    95102     * Can be null, may contain primitives when surrounding objects of the primitives are tested
     
    162169        this.intersections = other.intersections;
    163170        this.crossingWaysMap = other.crossingWaysMap;
    164171        this.mpAreaCache = other.mpAreaCache;
     172        this.mpJoinedAreaCache = other.mpJoinedAreaCache;
    165173        this.toMatchForSurrounding = other.toMatchForSurrounding;
    166174        this.selector = selector;
    167175    }
  • src/org/openstreetmap/josm/tools/Geometry.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/src/org/openstreetmap/josm/tools/Geometry.java b/src/org/openstreetmap/josm/tools/Geometry.java
    a b  
    1717import java.util.Iterator;
    1818import java.util.LinkedHashSet;
    1919import java.util.List;
     20import java.util.Map;
    2021import java.util.Set;
    2122import java.util.TreeSet;
    2223import java.util.function.Predicate;
     
    3233import org.openstreetmap.josm.data.osm.DataSet;
    3334import org.openstreetmap.josm.data.osm.INode;
    3435import org.openstreetmap.josm.data.osm.IPrimitive;
     36import org.openstreetmap.josm.data.osm.IRelation;
    3537import org.openstreetmap.josm.data.osm.IWay;
    3638import org.openstreetmap.josm.data.osm.MultipolygonBuilder;
    3739import org.openstreetmap.josm.data.osm.MultipolygonBuilder.JoinedPolygon;
     
    11911193                if (polygonArea == null) {
    11921194                    polygonArea = getArea(polygon.getNodes());
    11931195                }
    1194                 Multipolygon mp = new Multipolygon((Relation) p);
     1196                Multipolygon mp = p.getDataSet() != null ? MultipolygonCache.getInstance().get((Relation) p) : new Multipolygon((Relation) p);
    11951197                boolean inside = true;
    11961198                // a (valid) multipolygon is inside the polygon if all outer rings are inside
    11971199                for (PolyData outer : mp.getOuterPolygons()) {
     
    12201222     * @since 15069
    12211223     */
    12221224    public static List<IPrimitive> filterInsideMultipolygon(Collection<IPrimitive> primitives, Relation multiPolygon) {
     1225        return filterInsideMultipolygon(primitives, multiPolygon, null);
     1226    }
     1227
     1228    /**
     1229     * Find all primitives in the given collection which are inside the given multipolygon. Members of the multipolygon are
     1230     * ignored. Unclosed ways and multipolygon relations with unclosed outer rings are ignored.
     1231     * @param primitives the primitives
     1232     * @param multiPolygon the multipolygon relation
     1233     * @param cache The cache to avoid calculating joined inner/outer ways multiple times (see {@link MultipolygonBuilder#joinWays(Relation)})
     1234     * @return a new list containing the found primitives, empty if multipolygon is invalid or nothing was found.
     1235     * @since xxx
     1236     */
     1237    public static List<IPrimitive> filterInsideMultipolygon(Collection<IPrimitive> primitives, Relation multiPolygon,
     1238                                                            Map<IRelation<?>, Pair<List<JoinedPolygon>, List<JoinedPolygon>>> cache) {
    12231239        List<IPrimitive> res = new ArrayList<>();
    12241240        if (primitives.isEmpty())
    12251241            return res;
    12261242
    12271243        final Pair<List<JoinedPolygon>, List<JoinedPolygon>> outerInner;
    12281244        try {
    1229             outerInner = MultipolygonBuilder.joinWays(multiPolygon);
     1245            outerInner = MultipolygonBuilder.joinWays(cache, multiPolygon);
    12301246        } catch (MultipolygonBuilder.JoinedPolygonCreationException ex) {
    12311247            Logging.trace(ex);
    12321248            Logging.debug("Invalid multipolygon " + multiPolygon);
  • test/unit/org/openstreetmap/josm/tools/GeometryTest.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/test/unit/org/openstreetmap/josm/tools/GeometryTest.java b/test/unit/org/openstreetmap/josm/tools/GeometryTest.java
    a b  
    367367        mp2.addMember(new RelationMember("inner", inner));
    368368        mp2.put("type", "multipolygon");
    369369        assertFalse(Geometry.isPolygonInsideMultiPolygon(w1.getNodes(), mp2, null));
    370         assertFalse(Geometry.filterInsideMultipolygon(Collections.singletonList(w1), mp2).contains(w1));
     370        assertFalse(Geometry.filterInsideMultipolygon(Collections.singletonList(w1), mp2, null).contains(w1));
    371371
    372372        node4.setCoor(new LatLon(1.006, 0.99));
    373373        // now w1 is inside
    374374        assertTrue(Geometry.isPolygonInsideMultiPolygon(w1.getNodes(), mp2, null));
    375         assertTrue(Geometry.filterInsideMultipolygon(Collections.singletonList(w1), mp2).contains(w1));
    376         assertTrue(Geometry.filterInsideMultipolygon(Collections.singletonList(mp1), mp2).contains(mp1));
    377         assertTrue(Geometry.filterInsideMultipolygon(Arrays.asList(w1, mp1), mp2).contains(w1));
    378         assertTrue(Geometry.filterInsideMultipolygon(Arrays.asList(w1, mp1), mp2).contains(mp1));
     375        assertTrue(Geometry.filterInsideMultipolygon(Collections.singletonList(w1), mp2, null).contains(w1));
     376        assertTrue(Geometry.filterInsideMultipolygon(Collections.singletonList(mp1), mp2, null).contains(mp1));
     377        assertTrue(Geometry.filterInsideMultipolygon(Arrays.asList(w1, mp1), mp2, null).contains(w1));
     378        assertTrue(Geometry.filterInsideMultipolygon(Arrays.asList(w1, mp1), mp2, null).contains(mp1));
    379379    }
    380380
    381381    /**