Changeset 11003 in josm


Ignore:
Timestamp:
2016-09-15T21:39:13+02:00 (8 years ago)
Author:
simon04
Message:

fix #11975 - Evaluate extended Overpass queries bbox, geocodeArea

Location:
trunk
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/io/NameFinder.java

    r11002 r11003  
    1414import org.openstreetmap.josm.Main;
    1515import org.openstreetmap.josm.data.Bounds;
     16import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     17import org.openstreetmap.josm.data.osm.PrimitiveId;
     18import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
    1619import org.openstreetmap.josm.tools.HttpClient;
    1720import org.openstreetmap.josm.tools.OsmUrlToBounds;
     
    6770        public int zoom;
    6871        public Bounds bounds;
     72        public PrimitiveId osmId;
    6973
    7074        public Bounds getDownloadArea() {
     
    127131                            Double.parseDouble(bbox[0]), Double.parseDouble(bbox[2]),
    128132                            Double.parseDouble(bbox[1]), Double.parseDouble(bbox[3]));
     133                    final String osmId = atts.getValue("osm_id");
     134                    final String osmType = atts.getValue("osm_type");
     135                    if (osmId != null && osmType != null) {
     136                        currentResult.osmId = new SimplePrimitiveId(Long.parseLong(osmId), OsmPrimitiveType.from(osmType));
     137                    }
    129138                    data.add(currentResult);
    130139                }
  • trunk/src/org/openstreetmap/josm/io/OverpassDownloadReader.java

    r9669 r11003  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.io.IOException;
    67import java.io.InputStream;
     8import java.util.EnumMap;
     9import java.util.List;
    710import java.util.regex.Matcher;
    811import java.util.regex.Pattern;
     
    1114import javax.xml.stream.XMLStreamException;
    1215
     16import org.openstreetmap.josm.Main;
    1317import org.openstreetmap.josm.data.Bounds;
    1418import org.openstreetmap.josm.data.DataSource;
    1519import org.openstreetmap.josm.data.osm.DataSet;
     20import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     21import org.openstreetmap.josm.data.osm.PrimitiveId;
    1622import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    1723import org.openstreetmap.josm.tools.HttpClient;
     24import org.openstreetmap.josm.tools.UncheckedParseException;
    1825import org.openstreetmap.josm.tools.Utils;
    1926
     
    5158            return super.getRequestForBbox(lon1, lat1, lon2, lat2);
    5259        else {
    53             String realQuery = completeOverpassQuery(overpassQuery);
    54             return "interpreter?data=" + Utils.encodeUrl(realQuery)
    55                     + "&bbox=" + lon1 + ',' + lat1 + ',' + lon2 + ',' + lat2;
     60            final String overpassQuery = this.overpassQuery.replace("{{bbox}}", lat1 + "," + lon1 + "," + lat2 + "," + lon2);
     61            final String expandedOverpassQuery = expandExtendedQueries(overpassQuery);
     62            return "interpreter?data=" + Utils.encodeUrl(expandedOverpassQuery);
    5663        }
    5764    }
    5865
    59     private static String completeOverpassQuery(String query) {
    60         int firstColon = query.indexOf(';');
    61         if (firstColon == -1) {
    62             return "[bbox];" + query;
    63         }
    64         int bboxPos = query.indexOf("[bbox");
    65         if (bboxPos > -1 && bboxPos < firstColon) {
    66             return query;
    67         }
    68 
    69         int bracketCount = 0;
    70         int pos = 0;
    71         for (; pos < firstColon; ++pos) {
    72             if (query.charAt(pos) == '[')
    73                 ++bracketCount;
    74             else if (query.charAt(pos) == ']')
    75                 --bracketCount;
    76             else if (bracketCount == 0) {
    77                 if (!Character.isWhitespace(query.charAt(pos)))
    78                     break;
     66    /**
     67     * Evaluates some features of overpass turbo extended query syntax.
     68     * See https://wiki.openstreetmap.org/wiki/Overpass_turbo/Extended_Overpass_Turbo_Queries
     69     */
     70    static String expandExtendedQueries(String query) {
     71        final StringBuffer sb = new StringBuffer();
     72        final Matcher matcher = Pattern.compile("\\{\\{(geocodeArea):([^}]+)\\}\\}").matcher(query);
     73        while (matcher.find()) {
     74            try {
     75                switch (matcher.group(1)) {
     76                    case "geocodeArea":
     77                        matcher.appendReplacement(sb, geocodeArea(matcher.group(2)));
     78                }
     79            } catch (Exception ex) {
     80                final String msg = tr("Failed to evaluate {0}", matcher.group());
     81                Main.warn(ex, msg);
     82                matcher.appendReplacement(sb, "// " + msg + "\n");
    7983            }
    8084        }
     85        matcher.appendTail(sb);
     86        return sb.toString();
     87    }
    8188
    82         if (pos < firstColon) {
    83             // We start with a statement, not with declarations
    84             return "[bbox];" + query;
     89    private static String geocodeArea(String area) {
     90        // Offsets defined in https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#By_element_id
     91        final EnumMap<OsmPrimitiveType, Long> idOffset = new EnumMap<>(OsmPrimitiveType.class);
     92        idOffset.put(OsmPrimitiveType.NODE, 0L);
     93        idOffset.put(OsmPrimitiveType.WAY, 2400000000L);
     94        idOffset.put(OsmPrimitiveType.RELATION, 3600000000L);
     95        try {
     96            final List<NameFinder.SearchResult> results = NameFinder.queryNominatim(area);
     97            final PrimitiveId osmId = results.iterator().next().osmId;
     98            return String.format("area(%d)", osmId.getUniqueId() + idOffset.get(osmId.getType()));
     99        } catch (IOException ex) {
     100            throw new UncheckedParseException(ex);
    85101        }
    86 
    87         // We start with declarations. Add just one more declaration in this case.
    88         return "[bbox]" + query;
    89102    }
    90103
     
    150163
    151164        // add bounds if necessary (note that Overpass API does not return bounds in the response XML)
    152         if (ds != null && ds.dataSources.isEmpty()) {
     165        if (ds != null && ds.dataSources.isEmpty() && overpassQuery.contains("{{bbox}}")) {
    153166            if (crosses180th) {
    154167                Bounds bounds = new Bounds(lat1, lon1, lat2, 180.0);
  • trunk/src/org/openstreetmap/josm/tools/OverpassTurboQueryWizard.java

    r10802 r11003  
    7070                throw new UncheckedParseException();
    7171            }
    72             String query = (String) result;
    73             if (query != null) {
    74                 query = query.replace("[bbox:{{bbox}}]", "");
    75             }
    76             return query;
     72            return (String) result;
    7773        } catch (NoSuchMethodException e) {
    7874            throw new IllegalStateException(e);
  • trunk/test/unit/org/openstreetmap/josm/tools/OverpassTurboQueryWizardTest.java

    r10961 r11003  
    2828        final String query = OverpassTurboQueryWizard.getInstance().constructQuery("amenity=drinking_water");
    2929        assertEquals("" +
    30                 "[out:xml][timeout:25];\n" +
     30                "[out:xml][timeout:25][bbox:{{bbox}}];\n" +
    3131                "(\n" +
    3232                "  node[\"amenity\"=\"drinking_water\"];\n" +
Note: See TracChangeset for help on using the changeset viewer.