Subject: [PATCH] 24046
---
Index: src/org/openstreetmap/josm/data/osm/visitor/paint/relations/MultipolygonCache.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/MultipolygonCache.java b/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/MultipolygonCache.java
--- a/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/MultipolygonCache.java	(revision 19284)
+++ b/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/MultipolygonCache.java	(date 1736336212769)
@@ -3,6 +3,8 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -10,6 +12,9 @@
 
 import org.openstreetmap.josm.data.osm.DataSelectionListener;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.MultipolygonBuilder;
+import org.openstreetmap.josm.data.osm.MultipolygonBuilder.JoinedPolygon;
+import org.openstreetmap.josm.data.osm.MultipolygonBuilder.JoinedPolygonCreationException;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Relation;
@@ -34,6 +39,7 @@
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.tools.Pair;
 
 /**
  * A memory cache for {@link Multipolygon} objects.
@@ -44,6 +50,7 @@
     private static final MultipolygonCache INSTANCE = new MultipolygonCache();
 
     private final Map<DataSet, Map<Relation, Multipolygon>> cache = new ConcurrentHashMap<>(); // see ticket 11833
+    private final Map<DataSet, Map<Relation, Pair<List<JoinedPolygon>, List<JoinedPolygon>>>> wayCache = new HashMap<>();
 
     private final Collection<PolyData> selectedPolyData = new ArrayList<>();
 
@@ -102,6 +109,40 @@
         return multipolygon;
     }
 
+    /**
+     * Get joined ways for a relation
+     * @param r The relation to get the joined ways for
+     * @return The joined ways, see {@link MultipolygonBuilder#joinWays(Relation)} for details.
+     * @throws JoinedPolygonCreationException if the creation fails
+     * @since xxx
+     */
+    public Pair<List<JoinedPolygon>, List<JoinedPolygon>> getWays(Relation r) throws JoinedPolygonCreationException {
+        return getWays(r, false);
+    }
+
+    /**
+     * Get joined ways for a relation
+     * @param r The relation to get the joined ways for
+     * @param forceRefresh {@code true} if a cached calculation should not be used
+     * @return The joined ways, see {@link MultipolygonBuilder#joinWays(Relation)} for details.
+     * @throws JoinedPolygonCreationException if the creation fails
+     * @since xxx
+     */
+    public Pair<List<JoinedPolygon>, List<JoinedPolygon>> getWays(Relation r, boolean forceRefresh) throws JoinedPolygonCreationException {
+        if (r == null) {
+            return new Pair<>(Collections.emptyList(), Collections.emptyList());
+        } else if (r.getDataSet() == null) {
+            return MultipolygonBuilder.joinWays(r);
+        }
+        Map<Relation, Pair<List<JoinedPolygon>, List<JoinedPolygon>>> tMap = wayCache.computeIfAbsent(r.getDataSet(), d -> new HashMap<>());
+        if (forceRefresh || !tMap.containsKey(r)) {
+            Pair<List<JoinedPolygon>, List<JoinedPolygon>> outerInner = MultipolygonBuilder.joinWays(r);
+            tMap.put(r, outerInner);
+            return outerInner;
+        }
+        return tMap.get(r);
+    }
+
     /**
      * Clears the cache for the given dataset.
      * @param ds the data set
@@ -111,6 +152,10 @@
         if (map2 != null) {
             map2.clear();
         }
+        Map<Relation, Pair<List<JoinedPolygon>, List<JoinedPolygon>>> map3 = wayCache.remove(ds);
+        if (map3 != null) {
+            map3.clear();
+        }
     }
 
     /**
@@ -118,6 +163,7 @@
      */
     public void clear() {
         cache.clear();
+        wayCache.clear();
     }
 
     private Collection<Map<Relation, Multipolygon>> getMapsFor(DataSet ds) {
Index: 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/src/org/openstreetmap/josm/tools/Geometry.java	(revision 19284)
+++ b/src/org/openstreetmap/josm/tools/Geometry.java	(date 1736185434724)
@@ -1191,7 +1191,7 @@
                 if (polygonArea == null) {
                     polygonArea = getArea(polygon.getNodes());
                 }
-                Multipolygon mp = new Multipolygon((Relation) p);
+                Multipolygon mp = p.getDataSet() != null ? MultipolygonCache.getInstance().get((Relation) p) : new Multipolygon((Relation) p);
                 boolean inside = true;
                 // a (valid) multipolygon is inside the polygon if all outer rings are inside
                 for (PolyData outer : mp.getOuterPolygons()) {
@@ -1226,7 +1226,7 @@
 
         final Pair<List<JoinedPolygon>, List<JoinedPolygon>> outerInner;
         try {
-            outerInner = MultipolygonBuilder.joinWays(multiPolygon);
+            outerInner = MultipolygonCache.getInstance().getWays(multiPolygon);
         } catch (MultipolygonBuilder.JoinedPolygonCreationException ex) {
             Logging.trace(ex);
             Logging.debug("Invalid multipolygon " + multiPolygon);
