Search in sources :

Example 1 with MultiHashMap

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;
}
Also used : Area(java.awt.geom.Area) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) MultiHashMap(uk.me.parabola.util.MultiHashMap) Tags(uk.me.parabola.mkgmap.reader.osm.Tags)

Example 2 with MultiHashMap

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);
            }
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) CityInfo(uk.me.parabola.mkgmap.general.CityInfo) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Long2ObjectOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap) Int2ObjectOpenHashMap(it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap) Int2IntOpenHashMap(it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap) MultiHashMap(uk.me.parabola.util.MultiHashMap) LongArrayList(it.unimi.dsi.fastutil.longs.LongArrayList) LongArrayList(it.unimi.dsi.fastutil.longs.LongArrayList) ArrayList(java.util.ArrayList) MultiHashMap(uk.me.parabola.util.MultiHashMap) Int2IntOpenHashMap(it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap) LinkedHashMap(java.util.LinkedHashMap)

Example 3 with MultiHashMap

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);
    }
}
Also used : CityInfo(uk.me.parabola.mkgmap.general.CityInfo) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Long2ObjectOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap) Int2ObjectOpenHashMap(it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap) Int2IntOpenHashMap(it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap) MultiHashMap(uk.me.parabola.util.MultiHashMap) LongArrayList(it.unimi.dsi.fastutil.longs.LongArrayList) ArrayList(java.util.ArrayList) Numbers(uk.me.parabola.imgfmt.app.net.Numbers) LongArrayList(it.unimi.dsi.fastutil.longs.LongArrayList) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Int2ObjectOpenHashMap(it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap) MapRoad(uk.me.parabola.mkgmap.general.MapRoad) TreeMap(java.util.TreeMap) Coord(uk.me.parabola.imgfmt.app.Coord)

Aggregations

ArrayList (java.util.ArrayList)3 MultiHashMap (uk.me.parabola.util.MultiHashMap)3 Int2IntOpenHashMap (it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap)2 Int2ObjectOpenHashMap (it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap)2 Long2ObjectOpenHashMap (it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap)2 LongArrayList (it.unimi.dsi.fastutil.longs.LongArrayList)2 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 LinkedHashSet (java.util.LinkedHashSet)2 List (java.util.List)2 CityInfo (uk.me.parabola.mkgmap.general.CityInfo)2 Area (java.awt.geom.Area)1 HashSet (java.util.HashSet)1 TreeMap (java.util.TreeMap)1 Coord (uk.me.parabola.imgfmt.app.Coord)1 Numbers (uk.me.parabola.imgfmt.app.net.Numbers)1 MapRoad (uk.me.parabola.mkgmap.general.MapRoad)1 Tags (uk.me.parabola.mkgmap.reader.osm.Tags)1