use of uk.me.parabola.imgfmt.app.srt.MultiSortKey in project mkgmap by openstreetmap.
the class Mdr5 method calcMdr20SortPos.
/**
* Calculate a position when sorting by name, region, and country- This is used for MDR20.
*/
private void calcMdr20SortPos() {
List<SortKey<Mdr5Record>> sortKeys = new ArrayList<>(allCities.size());
Sort sort = getConfig().getSort();
for (Mdr5Record m : allCities) {
if (m.getName() == null)
continue;
// Sort by city name, region name, and country name .
SortKey<Mdr5Record> sortKey = sort.createSortKey(m, m.getName());
SortKey<Mdr5Record> regionKey = sort.createSortKey(null, m.getRegionName());
SortKey<Mdr5Record> countryKey = sort.createSortKey(null, m.getCountryName());
sortKey = new MultiSortKey<>(sortKey, regionKey, countryKey);
sortKeys.add(sortKey);
}
Collections.sort(sortKeys);
SortKey<Mdr5Record> lastKey = null;
int pos = 0;
for (SortKey<Mdr5Record> key : sortKeys) {
Mdr5Record c = key.getObject();
if (lastKey == null || key.compareTo(lastKey) != 0)
pos++;
c.setMdr20SortPos(pos);
lastKey = key;
}
}
use of uk.me.parabola.imgfmt.app.srt.MultiSortKey in project mkgmap by openstreetmap.
the class Mdr5 method preWriteImpl.
/**
* Called after all cities to sort and number them.
*/
public void preWriteImpl() {
localCitySize = Utils.numberToPointerSize(maxCityIndex + 1);
List<SortKey<Mdr5Record>> sortKeys = new ArrayList<>(allCities.size());
Sort sort = getConfig().getSort();
for (Mdr5Record m : allCities) {
if (m.getName() == null)
continue;
// Sort by city name, region name, country name and map index.
SortKey<Mdr5Record> sortKey = sort.createSortKey(m, m.getName());
SortKey<Mdr5Record> regionKey = sort.createSortKey(null, m.getRegionName());
SortKey<Mdr5Record> countryKey = sort.createSortKey(null, m.getCountryName(), m.getMapIndex());
sortKey = new MultiSortKey<>(sortKey, regionKey, countryKey);
sortKeys.add(sortKey);
}
Collections.sort(sortKeys);
Collator collator = getConfig().getSort().getCollator();
int count = 0;
Mdr5Record lastCity = null;
// We need a common area to save the mdr20 values, since there can be multiple
// city records with the same global city index
int[] mdr20s = new int[sortKeys.size() + 1];
int mdr20count = 0;
for (SortKey<Mdr5Record> key : sortKeys) {
Mdr5Record c = key.getObject();
c.setMdr20set(mdr20s);
if (!c.isSameByName(collator, lastCity))
mdr20count++;
c.setMdr20Index(mdr20count);
if (c.isSameByMapAndName(collator, lastCity)) {
c.setGlobalCityIndex(count);
} else {
count++;
c.setGlobalCityIndex(count);
cities.add(c);
lastCity = c;
}
}
// calculate positions for the different road indexes
calcMdr20SortPos();
calcMdr21SortPos();
calcMdr22SortPos();
}
use of uk.me.parabola.imgfmt.app.srt.MultiSortKey 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;
}
Aggregations