Changeset 11360 in josm


Ignore:
Timestamp:
2016-12-04T15:06:02+01:00 (8 years ago)
Author:
bastiK
Message:

fixed #10387 - efficiency for "inside(...)" function in MapCSS

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/relations/Multipolygon.java

    r11313 r11360  
    163163    }
    164164
     165    /**
     166     * Class representing a string of ways.
     167     *
     168     * The last node of one way is the first way of the next one.
     169     * The string may or may not be closed.
     170     */
    165171    public static class JoinedWay {
    166172        protected final List<Node> nodes;
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java

    r11247 r11360  
    1818import java.util.Locale;
    1919import java.util.Objects;
    20 import java.util.Set;
    2120import java.util.TreeSet;
    2221import java.util.function.Function;
     
    966965         */
    967966        public static boolean inside(Environment env, String codes) { // NO_UCD (unused code)
    968             Set<String> osmCodes = Territories.getIso3166Codes(center(env));
    969967            for (String code : codes.toUpperCase(Locale.ENGLISH).split(",")) {
    970                 if (osmCodes.contains(code.trim())) {
     968                if (Territories.isIso3166Code(code.trim(), center(env))) {
    971969                    return true;
    972970                }
  • trunk/src/org/openstreetmap/josm/tools/DefaultGeoProperty.java

    r11277 r11360  
    77import org.openstreetmap.josm.data.coor.LatLon;
    88import org.openstreetmap.josm.data.osm.BBox;
     9import org.openstreetmap.josm.data.osm.Relation;
    910import org.openstreetmap.josm.data.osm.Way;
    1011
     
    1415public class DefaultGeoProperty implements GeoProperty<Boolean> {
    1516
    16     private Area area;
     17    private final Area area;
    1718
    1819    /**
     
    2223     */
    2324    public DefaultGeoProperty(Collection<Way> ways) {
     25        Area area = null;
    2426        for (Way w : ways) {
    25             Area tmp = Geometry.getAreaLatLon(w.getNodes());
     27            Area wayArea = Geometry.getAreaLatLon(w.getNodes());
    2628            if (area == null) {
    27                 area = tmp;
     29                area = wayArea;
    2830            } else {
    29                 area.add(tmp);
     31                area.add(wayArea);
    3032            }
    3133        }
     34        this.area = area;
     35    }
     36
     37    /**
     38     * Create DefaultGeoProperty based on a multipolygon relation.
     39     *
     40     * @param multipolygon the multipolygon
     41     */
     42    public DefaultGeoProperty(Relation multipolygon) {
     43        this.area = Geometry.getAreaLatLon(multipolygon);
    3244    }
    3345
  • trunk/src/org/openstreetmap/josm/tools/Geometry.java

    r11243 r11360  
    478478    /**
    479479     * Returns the Area of a polygon, from its list of nodes.
    480      * @param polygon List of nodes forming polygon (EastNorth coordinates)
    481      * @return Area for the given list of nodes
     480     * @param polygon List of nodes forming polygon
     481     * @return Area for the given list of nodes  (EastNorth coordinates)
    482482     * @since 6841
    483483     */
     
    506506    /**
    507507     * Returns the Area of a polygon, from its list of nodes.
    508      * @param polygon List of nodes forming polygon (LatLon coordinates)
    509      * @return Area for the given list of nodes
     508     * @param polygon List of nodes forming polygon
     509     * @return Area for the given list of nodes (LatLon coordinates)
    510510     * @since 6841
    511511     */
     
    527527
    528528        return new Area(path);
     529    }
     530
     531    /**
     532     * Returns the Area of a polygon, from the multipolygon relation.
     533     * @param multipolygon the multipolygon relation
     534     * @return Area for the multipolygon (LatLon coordinates)
     535     */
     536    public static Area getAreaLatLon(Relation multipolygon) {
     537        final Multipolygon mp = Main.map == null || Main.map.mapView == null
     538                ? new Multipolygon(multipolygon)
     539                : MultipolygonCache.getInstance().get(Main.map.mapView, multipolygon);
     540        Area result = null;
     541        for (Multipolygon.PolyData pd : mp.getCombinedPolygons()) {
     542            Area area = getAreaLatLon(pd.getNodes());
     543            for (Multipolygon.PolyData pdInner : pd.getInners()) {
     544                Area areaInner = getAreaLatLon(pdInner.getNodes());
     545                area.subtract(areaInner);
     546            }
     547            if (result == null) {
     548                result = area;
     549            } else {
     550                result.add(area);
     551            }
     552        }
     553        return result;
    529554    }
    530555
  • trunk/src/org/openstreetmap/josm/tools/Territories.java

    r11266 r11360  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.tools;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
    35
    46import java.io.IOException;
     
    68import java.util.ArrayList;
    79import java.util.Collection;
    8 import java.util.HashSet;
     10import java.util.Collections;
     11import java.util.HashMap;
    912import java.util.Map;
    1013import java.util.Set;
    11 import java.util.concurrent.ConcurrentHashMap;
    1214
    1315import org.openstreetmap.josm.Main;
    14 import org.openstreetmap.josm.actions.SelectByInternalPointAction;
    1516import org.openstreetmap.josm.data.coor.LatLon;
    16 import org.openstreetmap.josm.data.osm.BBox;
    1717import org.openstreetmap.josm.data.osm.DataSet;
    1818import org.openstreetmap.josm.data.osm.OsmPrimitive;
     19import org.openstreetmap.josm.data.osm.Relation;
     20import org.openstreetmap.josm.data.osm.Way;
    1921import org.openstreetmap.josm.io.CachedFile;
    2022import org.openstreetmap.josm.io.IllegalDataException;
     
    2931    private static final String ISO3166_2 = "ISO3166-2";
    3032
    31     private static class Iso3166GeoProperty implements GeoProperty<Set<String>> {
     33    private static DataSet dataSet;
    3234
    33         @Override
    34         public Set<String> get(LatLon ll) {
    35             Set<String> result = new HashSet<>();
    36             for (OsmPrimitive surrounding :
    37                     SelectByInternalPointAction.getSurroundingObjects(dataSet, Main.getProjection().latlon2eastNorth(ll), true)) {
    38                 String iso1 = surrounding.get(ISO3166_1);
    39                 if (iso1 != null) {
    40                     result.add(iso1);
    41                 }
    42                 String iso2 = surrounding.get(ISO3166_2);
    43                 if (iso2 != null) {
    44                     result.add(iso2);
    45                 }
    46             }
    47             return result;
    48         }
    49 
    50         @Override
    51         public Set<String> get(BBox box) {
    52             return null; // TODO
    53         }
    54     }
    55 
    56     private static DataSet dataSet;
    57     private static final Map<String, OsmPrimitive> iso3166Map = new ConcurrentHashMap<>();
    58 
    59     private static volatile GeoPropertyIndex<Set<String>> iso3166Cache;
     35    private static volatile Map<String, GeoPropertyIndex<Boolean>> iso3166Cache;
    6036
    6137    private Territories() {
     
    6945     */
    7046    public static synchronized Set<String> getKnownIso3166Codes() {
    71         return iso3166Map.keySet();
     47        return iso3166Cache.keySet();
    7248    }
    7349
    7450    /**
    75      * Get the ISO3166-1 and ISO3166-2 codes for the given location.
     51     * Determine, if a point is inside a territory with the given the ISO3166-1
     52     * or ISO3166-2 code.
    7653     *
     54     * @param code the ISO3166-1 or ISO3166-2 code
    7755     * @param ll the coordinates of the point
    78      * @return the ISO3166-1 and ISO3166-2 codes for the given location
     56     * @return true, if the point is inside a territory with the given code
    7957     */
    80     public static synchronized Set<String> getIso3166Codes(LatLon ll) {
    81         return iso3166Cache.get(ll);
     58    public static synchronized boolean isIso3166Code(String code, LatLon ll) {
     59        GeoPropertyIndex<Boolean> gpi = iso3166Cache.get(code);
     60        if (gpi == null) {
     61            Main.warn(tr("Unknown territory id: {0}", code));
     62            return false;
     63        }
     64        return gpi.get(ll);
    8265    }
    8366
     
    9578     */
    9679    public static synchronized void initialize() {
    97         iso3166Cache = new GeoPropertyIndex<>(new Iso3166GeoProperty(), 24);
     80        iso3166Cache = new HashMap<>();
    9881        try (CachedFile cf = new CachedFile("resource://data/boundaries.osm");
    9982                InputStream is = cf.getInputStream()) {
     
    10386            for (OsmPrimitive osm : candidates) {
    10487                String iso1 = osm.get(ISO3166_1);
    105                 if (iso1 != null) {
    106                     iso3166Map.put(iso1, osm);
    107                 }
    10888                String iso2 = osm.get(ISO3166_2);
    109                 if (iso2 != null) {
    110                     iso3166Map.put(iso2, osm);
     89                if (iso1 != null || iso2 != null) {
     90                    GeoProperty<Boolean> gp;
     91                    if (osm instanceof Way) {
     92                        gp = new DefaultGeoProperty(Collections.singleton((Way) osm));
     93                    } else {
     94                        gp = new DefaultGeoProperty((Relation) osm);
     95                    }
     96                    GeoPropertyIndex gpi = new GeoPropertyIndex(gp, 24);
     97                    if (iso1 != null) {
     98                        iso3166Cache.put(iso1, gpi);
     99                    }
     100                    if (iso2 != null) {
     101                        iso3166Cache.put(iso2, gpi);
     102                    }
    111103                }
    112104            }
  • trunk/test/unit/org/openstreetmap/josm/tools/TerritoriesTest.java

    r11324 r11360  
    22package org.openstreetmap.josm.tools;
    33
    4 import static org.junit.Assert.assertEquals;
    54import static org.junit.Assert.assertTrue;
    6 
    7 import java.util.Set;
    85
    96import org.junit.Rule;
     
    3431
    3532    private static void check(String name, LatLon ll, String ... expectedCodes) {
    36         Set<String> codes = Territories.getIso3166Codes(ll);
    37         assertEquals(name + " -> " + codes, expectedCodes.length, codes.size());
    3833        for (String e : expectedCodes) {
    39             assertTrue(e, codes.contains(e));
     34            assertTrue(name + " " + e, Territories.isIso3166Code(e, ll));
    4035        }
    4136    }
Note: See TracChangeset for help on using the changeset viewer.