use of uk.me.parabola.util.MultiHashMap in project mkgmap by openstreetmap.
the class BoundaryUtil method mergePostalCodes.
/**
* Merges boundaries with the same postal code.
* @param boundaries a list of boundaries
* @return the boundary list with postal code areas merged
*/
private static List<Boundary> mergePostalCodes(List<Boundary> boundaries) {
List<Boundary> mergedList = new ArrayList<>(boundaries.size());
MultiHashMap<String, Boundary> equalPostalCodes = new MultiHashMap<>();
for (Boundary boundary : boundaries) {
String postalCode = getPostalCode(boundary.getTags());
if (postalCode == null) {
// no postal code boundary
mergedList.add(boundary);
} else {
// postal code boundary => merge it later
equalPostalCodes.add(postalCode, boundary);
}
}
for (Entry<String, List<Boundary>> postCodeBoundary : equalPostalCodes.entrySet()) {
if (postCodeBoundary.getValue().size() == 1) {
// nothing to merge
mergedList.addAll(postCodeBoundary.getValue());
continue;
}
// there are more than 2 boundaries with the same post code
// => merge them
Area newPostCodeArea = new Area();
for (Boundary b : postCodeBoundary.getValue()) {
newPostCodeArea.add(b.getArea());
// remove the post code tags from the original boundary
if (b.getTags().get("postal_code") != null) {
b.getTags().remove("postal_code");
} else if ("postal_code".equals(b.getTags().get("boundary"))) {
b.getTags().remove("boundary");
b.getTags().remove("name");
}
// check if the boundary contains other boundary information
if (isAdministrativeBoundary(b)) {
mergedList.add(b);
} else {
log.info("Boundary", b.getId(), b.getTags(), "contains no more boundary tags. Skipping it.");
}
}
Tags postalCodeTags = new Tags();
postalCodeTags.put("postal_code", postCodeBoundary.getKey());
Boundary postalCodeBoundary = new Boundary(newPostCodeArea, postalCodeTags, "p" + postCodeBoundary.getKey());
log.info("Merged", postCodeBoundary.getValue().size(), "postal code boundaries for postal code", postCodeBoundary.getKey());
mergedList.add(postalCodeBoundary);
}
return mergedList;
}
use of uk.me.parabola.util.MultiHashMap in project mkgmap by openstreetmap.
the class HousenumberGenerator method useAddrPlaceTag.
private void useAddrPlaceTag(List<HousenumberRoad> hnrList) {
HashMap<CityInfo, MultiHashMap<String, HousenumberMatch>> cityPlaceHouseMap = new LinkedHashMap<>();
for (int i = 0; i < houseElems.size(); i++) {
HousenumberElem house = houseElems.get(i);
if (house.getRoad() == null)
continue;
if (house.getPlace() == null)
continue;
if (house instanceof HousenumberMatch) {
HousenumberMatch hm = (HousenumberMatch) house;
if (hm.getHousenumberRoad() == null)
continue;
} else
continue;
MultiHashMap<String, HousenumberMatch> subMap = cityPlaceHouseMap.get(house.getCityInfo());
if (subMap == null) {
subMap = new MultiHashMap<>();
cityPlaceHouseMap.put(house.getCityInfo(), subMap);
}
subMap.add(house.getPlace(), (HousenumberMatch) house);
}
log.info("analysing", cityPlaceHouseMap.size(), "cities with addr:place=* houses");
for (Entry<CityInfo, MultiHashMap<String, HousenumberMatch>> topEntry : cityPlaceHouseMap.entrySet()) {
CityInfo cityInfo = topEntry.getKey();
List<String> placeNames = new ArrayList<>(topEntry.getValue().keySet());
Collections.sort(placeNames);
for (String placeName : placeNames) {
List<HousenumberMatch> placeHouses = topEntry.getValue().get(placeName);
HashSet<HousenumberRoad> roads = new LinkedHashSet<>();
Int2IntOpenHashMap usedNumbers = new Int2IntOpenHashMap();
HashMap<String, Integer> usedSigns = new HashMap<>();
int dupSigns = 0;
int dupNumbers = 0;
int housesWithStreet = 0;
int housesWithMatchingStreet = 0;
int roadsWithNames = 0;
int unnamedCloseRoads = 0;
for (HousenumberMatch house : placeHouses) {
if (house.getStreet() != null) {
++housesWithStreet;
if (house.getStreet().equalsIgnoreCase(house.getRoad().getStreet())) {
++housesWithMatchingStreet;
}
} else {
if (house.getRoad().getStreet() == null)
++unnamedCloseRoads;
}
boolean added = roads.add(house.getHousenumberRoad());
if (added && house.getRoad().getStreet() != null)
++roadsWithNames;
int oldCount = usedNumbers.put(house.getHousenumber(), 1);
if (oldCount != 0) {
usedNumbers.put(house.getHousenumber(), oldCount + 1);
++dupNumbers;
}
Integer oldSignCount = usedSigns.put(house.getSign(), 1);
if (oldSignCount != null) {
usedSigns.put(house.getSign(), oldSignCount + 1);
++dupSigns;
}
}
if (log.isDebugEnabled()) {
log.debug("place", placeName, "in city", cityInfo, ":", "houses:", placeHouses.size(), ",duplicate numbers/signs:", dupNumbers + "/" + dupSigns, ",roads (named/unnamed):", roads.size(), "(" + roadsWithNames + "/" + (roads.size() - roadsWithNames) + ")", ",houses without addr:street:", placeHouses.size() - housesWithStreet, ",street = name of closest road:", housesWithMatchingStreet, ",houses without addr:street near named road:", unnamedCloseRoads);
}
if ((float) dupSigns / placeHouses.size() < 0.25) {
if (log.isDebugEnabled())
log.debug("will not use gaps in intervals for roads in", placeName);
for (HousenumberRoad hnr : roads) {
hnr.setRemoveGaps(true);
}
}
if (placeHouses.size() > housesWithStreet) {
// XXX: threshold value?
LongArrayList ids = new LongArrayList();
for (HousenumberRoad hnr : roads) {
ids.add(hnr.getRoad().getRoadDef().getId());
hnr.addPlaceName(placeName);
}
if (log.isDebugEnabled())
log.debug("detected", placeName, "as potential address name for roads", ids);
} else {
if (log.isDebugEnabled())
log.debug("will ignore addr:place for address search in", placeName, "in city", cityInfo);
}
}
}
}
use of uk.me.parabola.util.MultiHashMap in project mkgmap by openstreetmap.
the class HousenumberGenerator method generate.
/**
* @param adder
* @param naxNodeId the highest nodeId used before
*/
public void generate(LineAdder adder, int naxNodeId) {
if (numbersEnabled) {
MultiHashMap<MapRoad, HousenumberMatch> initialHousesForRoads = findClosestRoadsToHouse();
identifyServiceRoads();
handleInterpolationWays(initialHousesForRoads);
List<HousenumberRoad> hnrList = createHousenumberRoads(initialHousesForRoads);
initialHousesForRoads = null;
log.info("found", hnrList.size(), "road candidates for address search");
useAddrPlaceTag(hnrList);
Map<MapRoad, HousenumberRoad> road2HousenumberRoadMap = new HashMap<>();
for (HousenumberRoad hnr : hnrList) {
road2HousenumberRoadMap.put(hnr.getRoad(), hnr);
}
Int2ObjectOpenHashMap<HashSet<MapRoad>> nodeId2RoadLists = new Int2ObjectOpenHashMap<>();
for (MapRoad road : allRoads) {
for (Coord co : road.getPoints()) {
if (co.getId() == 0)
continue;
HashSet<MapRoad> connectedRoads = nodeId2RoadLists.get(co.getId());
if (connectedRoads == null) {
connectedRoads = new HashSet<>();
nodeId2RoadLists.put(co.getId(), connectedRoads);
}
connectedRoads.add(road);
}
}
List<HousenumberRoad> addedRoads = new ArrayList<>();
Iterator<HousenumberRoad> iter = hnrList.iterator();
while (iter.hasNext()) {
HousenumberRoad hnr = iter.next();
List<HousenumberMatch> lostHouses = hnr.checkStreetName(road2HousenumberRoadMap, nodeId2RoadLists);
for (HousenumberMatch house : lostHouses) {
MapRoad r = house.getRoad();
if (r != null) {
HousenumberRoad hnr2 = road2HousenumberRoadMap.get(r);
if (hnr2 == null) {
CityInfo ci = getCityInfos(r.getCity(), r.getRegion(), r.getCountry());
hnr2 = new HousenumberRoad(r, ci, Arrays.asList(house));
if (r.getZip() != null)
hnr2.setZipCodeInfo(getZipInfos(r.getZip()));
road2HousenumberRoadMap.put(r, hnr2);
addedRoads.add(hnr2);
} else {
hnr2.addHouse(house);
}
}
}
if (hnr.getName() == null) {
iter.remove();
for (HousenumberMatch house : hnr.getHouses()) {
log.warn("found no plausible road name for address", house.toBrowseURL(), ", closest road id:", house.getRoad());
}
}
}
hnrList.addAll(addedRoads);
// TODO: interpolate addr:interpolation houses
removeDupsGroupedByCityAndName(hnrList);
// group by street name and city
TreeMap<String, TreeMap<CityInfo, List<HousenumberRoad>>> streetnameCityRoadMap = new TreeMap<>();
for (HousenumberRoad hnr : hnrList) {
TreeMap<CityInfo, List<HousenumberRoad>> cluster = streetnameCityRoadMap.get(hnr.getName());
if (cluster == null) {
cluster = new TreeMap<>();
streetnameCityRoadMap.put(hnr.getName(), cluster);
}
List<HousenumberRoad> roadsInCluster = cluster.get(hnr.getRoadCityInfo());
if (roadsInCluster == null) {
roadsInCluster = new ArrayList<>();
cluster.put(hnr.getRoadCityInfo(), roadsInCluster);
}
roadsInCluster.add(hnr);
}
for (Entry<String, TreeMap<CityInfo, List<HousenumberRoad>>> streetNameEntry : streetnameCityRoadMap.entrySet()) {
String streetName = streetNameEntry.getKey();
for (Entry<CityInfo, List<HousenumberRoad>> clusterEntry : streetNameEntry.getValue().entrySet()) {
useInterpolationInfo(streetName, clusterEntry.getValue(), road2HousenumberRoadMap);
}
for (Entry<CityInfo, List<HousenumberRoad>> clusterEntry : streetNameEntry.getValue().entrySet()) {
List<HousenumberRoad> roadsInCluster = clusterEntry.getValue();
if (log.isDebugEnabled()) {
log.debug("processing road(s) with name", streetName, "in", clusterEntry.getKey());
}
for (HousenumberRoad hnr : roadsInCluster) {
hnr.buildIntervals();
}
boolean optimized = false;
for (int loop = 0; loop < 10; loop++) {
for (HousenumberRoad hnr : roadsInCluster) {
hnr.checkIntervals();
}
checkWrongRoadAssignmments(roadsInCluster);
boolean changed = hasChanges(roadsInCluster);
if (!optimized && !changed) {
for (HousenumberRoad hnr : roadsInCluster) {
hnr.improveSearchResults();
}
changed = hasChanges(roadsInCluster);
optimized = true;
}
if (!changed)
break;
}
for (HousenumberRoad hnr : roadsInCluster) {
hnr.setNumbers();
}
}
}
}
if (log.isInfoEnabled()) {
for (HousenumberElem house : houseElems) {
if (house.getRoad() == null) {
if (house.getStreet() != null)
log.info("found no plausible road for house number element", house.toBrowseURL(), house.getStreet(), house.getSign());
else
log.info("found no plausible road for house number element", house.toBrowseURL());
}
}
}
for (MapRoad r : allRoads) {
if (log.isDebugEnabled()) {
List<Numbers> finalNumbers = r.getRoadDef().getNumbersList();
if (finalNumbers != null) {
log.info("id:" + r.getRoadDef().getId(), ", final numbers,", r, "in", r.getCity());
for (Numbers cn : finalNumbers) {
if (cn.isEmpty())
continue;
log.info("id:" + r.getRoadDef().getId(), ", Left: ", cn.getLeftNumberStyle(), cn.getIndex(), "Start:", cn.getLeftStart(), "End:", cn.getLeftEnd());
log.info("id:" + r.getRoadDef().getId(), ", Right:", cn.getRightNumberStyle(), cn.getIndex(), "Start:", cn.getRightStart(), "End:", cn.getRightEnd());
}
}
}
adder.add(r);
}
}
Aggregations