Search in sources :

Example 1 with IntegerSortKey

use of uk.me.parabola.imgfmt.app.srt.IntegerSortKey in project mkgmap by openstreetmap.

the class NETFile method sortRoads.

/**
 * Sort the roads by name and remove duplicates.
 *
 * We want a list of roads such that every entry in the list is a different road. Since in osm
 * roads are frequently chopped into small pieces we have to remove the duplicates.
 * This doesn't have to be perfect, it needs to be useful when searching for roads.
 *
 * So we have a separate entry if the road is in a different city. This would probably be enough
 * except that associating streets with cities is not always very good in OSM. So I also create an
 * extra entry for each subdivision. Finally there a search for disconnected roads within the subdivision
 * with the same name.
 *
 * Performance note: The previous implementation was very, very slow when there were a large number
 * of roads with the same name. Although this was an unusual situation, when it happened it appears
 * that mkgmap has hung. This implementation takes a fraction of a second even for large numbers of
 * same named roads.
 *
 * @return A sorted list of road labels that identify all the different roads.
 */
private List<LabeledRoadDef> sortRoads() {
    List<SortKey<LabeledRoadDef>> sortKeys = new ArrayList<>(roads.size());
    Map<Label, byte[]> cache = new HashMap<>();
    for (RoadDef rd : roads) {
        Label[] labels = rd.getLabels();
        for (int i = 0; i < labels.length && labels[i] != null; ++i) {
            Label label = labels[i];
            if (label.getLength() == 0)
                continue;
            // Sort by name, city, region/country and subdivision number.
            LabeledRoadDef lrd = new LabeledRoadDef(label, rd);
            SortKey<LabeledRoadDef> nameKey = new IntegerSortKey<NETFile.LabeledRoadDef>(lrd, label.getOffset(), 0);
            // If there is a city add it to the sort.
            // what if we more than one?
            City city = (rd.getCities().isEmpty() ? null : rd.getCities().get(0));
            SortKey<LabeledRoadDef> cityKey;
            if (city != null) {
                int region = city.getRegionNumber();
                int country = city.getCountryNumber();
                cityKey = sort.createSortKey(null, city.getLabel(), (region & 0xffff) << 16 | (country & 0xffff), cache);
            } else {
                cityKey = sort.createSortKey(null, Label.NULL_OUT_LABEL, 0, cache);
            }
            SortKey<LabeledRoadDef> sortKey = new MultiSortKey<>(nameKey, cityKey, new IntegerSortKey<LabeledRoadDef>(null, rd.getStartSubdivNumber(), 0));
            sortKeys.add(sortKey);
        }
    }
    Collections.sort(sortKeys);
    List<LabeledRoadDef> out = new ArrayList<>(sortKeys.size());
    Label lastName = null;
    City lastCity = null;
    List<LabeledRoadDef> dupes = new ArrayList<>();
    // The duplicates are saved to the dupes list.
    for (SortKey<LabeledRoadDef> key : sortKeys) {
        LabeledRoadDef lrd = key.getObject();
        Label name = lrd.label;
        RoadDef road = lrd.roadDef;
        // what if we more than one?
        City city = (road.getCities().isEmpty() ? null : road.getCities().get(0));
        if (road.hasHouseNumbers() || !name.equals(lastName) || city != lastCity) {
            // process any previously collected duplicate road names and reset.
            addDisconnected(dupes, out);
            dupes = new ArrayList<>();
            lastName = name;
            lastCity = city;
        }
        dupes.add(lrd);
    }
    // Finish off the final set of duplicates.
    addDisconnected(dupes, out);
    sortByName(out);
    return out;
}
Also used : IntegerSortKey(uk.me.parabola.imgfmt.app.srt.IntegerSortKey) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Label(uk.me.parabola.imgfmt.app.Label) IntegerSortKey(uk.me.parabola.imgfmt.app.srt.IntegerSortKey) DoubleSortKey(uk.me.parabola.imgfmt.app.srt.DoubleSortKey) SortKey(uk.me.parabola.imgfmt.app.srt.SortKey) MultiSortKey(uk.me.parabola.imgfmt.app.srt.MultiSortKey) City(uk.me.parabola.imgfmt.app.lbl.City) MultiSortKey(uk.me.parabola.imgfmt.app.srt.MultiSortKey)

Aggregations

ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Label (uk.me.parabola.imgfmt.app.Label)1 City (uk.me.parabola.imgfmt.app.lbl.City)1 DoubleSortKey (uk.me.parabola.imgfmt.app.srt.DoubleSortKey)1 IntegerSortKey (uk.me.parabola.imgfmt.app.srt.IntegerSortKey)1 MultiSortKey (uk.me.parabola.imgfmt.app.srt.MultiSortKey)1 SortKey (uk.me.parabola.imgfmt.app.srt.SortKey)1