Search in sources :

Example 6 with CityInfo

use of uk.me.parabola.mkgmap.general.CityInfo in project mkgmap by openstreetmap.

the class HousenumberGenerator method markSimpleDuplicates.

private static void markSimpleDuplicates(String streetName, List<HousenumberMatch> housesNearCluster) {
    List<HousenumberMatch> sortedHouses = new ArrayList<>(housesNearCluster);
    Collections.sort(sortedHouses, new HousenumberMatchByNumComparator());
    int n = sortedHouses.size();
    for (int i = 1; i < n; i++) {
        HousenumberMatch house1 = sortedHouses.get(i - 1);
        if (house1.isIgnored())
            continue;
        HousenumberMatch house2 = sortedHouses.get(i);
        if (house2.isIgnored())
            continue;
        if (house1.getHousenumber() != house2.getHousenumber())
            continue;
        if (house1.getRoad() == house2.getRoad()) {
            if (house1.isFarDuplicate())
                house2.setFarDuplicate(true);
            // handled later
            continue;
        }
        // we have two equal house numbers in different roads
        // check if they should be treated alike
        boolean markFarDup = false;
        double dist = house1.getLocation().distance(house2.getLocation());
        if (dist > MAX_DISTANCE_SAME_NUM)
            markFarDup = true;
        else {
            CityInfo city1 = house1.getCityInfo();
            CityInfo city2 = house2.getCityInfo();
            if (city1 != null && city1.equals(city2) == false) {
                markFarDup = true;
            }
        }
        if (markFarDup) {
            if (log.isDebugEnabled())
                log.debug("keeping duplicate numbers assigned to different roads in cluster ", streetName, house1, house2);
            house1.setFarDuplicate(true);
            house2.setFarDuplicate(true);
            continue;
        }
        boolean ignore2nd = false;
        if (dist < 30) {
            ignore2nd = true;
        } else {
            Coord c1s = house1.getRoad().getPoints().get(house1.getSegment());
            Coord c1e = house1.getRoad().getPoints().get(house1.getSegment() + 1);
            Coord c2s = house2.getRoad().getPoints().get(house2.getSegment());
            Coord c2e = house2.getRoad().getPoints().get(house2.getSegment() + 1);
            if (c1s == c2s || c1s == c2e || c1e == c2s || c1e == c2e) {
                // roads are directly connected
                ignore2nd = true;
            }
        }
        if (ignore2nd) {
            house2.setIgnored(true);
            if (log.isDebugEnabled()) {
                if (house1.getSign().equals(house2.getSign()))
                    log.debug("duplicate number is ignored", streetName, house2.getSign(), house2.toBrowseURL());
                else
                    log.info("using", streetName, house1.getSign(), "in favor of", house2.getSign(), "as target for address search");
            }
        } else {
            if (log.isDebugEnabled())
                log.debug("keeping duplicate numbers assigned to different roads in cluster ", streetName, house1, house2);
            house1.setFarDuplicate(true);
            house2.setFarDuplicate(true);
        }
    }
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) CityInfo(uk.me.parabola.mkgmap.general.CityInfo) LongArrayList(it.unimi.dsi.fastutil.longs.LongArrayList) ArrayList(java.util.ArrayList)

Example 7 with CityInfo

use of uk.me.parabola.mkgmap.general.CityInfo 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 8 with CityInfo

use of uk.me.parabola.mkgmap.general.CityInfo 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)

Example 9 with CityInfo

use of uk.me.parabola.mkgmap.general.CityInfo in project mkgmap by openstreetmap.

the class HousenumberGenerator method parseElement.

private HousenumberElem parseElement(Element el, String sign) {
    String city = el.getTag(cityTagKey);
    String region = el.getTag(regionTagKey);
    String country = el.getTag(countryTagKey);
    CityInfo ci = getCityInfos(city, region, country);
    HousenumberElem house = new HousenumberElem(el, ci);
    if (house.getLocation() == null) {
        // there has been a report that indicates match.getLocation() == null
        // could not reproduce so far but catching it here with some additional
        // information. (WanMil)
        log.error("OSM element seems to have no point.");
        log.error("Element: " + el.toBrowseURL() + " " + el);
        log.error("Please report on the mkgmap mailing list.");
        log.error("Continue creating the map. This should be possible without a problem.");
        return null;
    }
    house.setSign(sign);
    Integer hn = parseHousenumber(sign);
    if (hn == null) {
        if (log.isDebugEnabled())
            log.debug("No housenumber (", el.toBrowseURL(), "): ", sign);
        return null;
    }
    if (hn < 0 || hn > 1_000_000) {
        log.warn("Number looks wrong, is ignored", house.getSign(), hn, "element", el.toBrowseURL());
        return null;
    }
    house.setHousenumber(hn);
    house.setStreet(getStreetname(el));
    house.setPlace(el.getTag(addrPlaceTagKey));
    String zipStr = el.getTag(postalCodeTagKey);
    ZipCodeInfo zip = getZipInfos(zipStr);
    house.setZipCode(zip);
    return house;
}
Also used : CityInfo(uk.me.parabola.mkgmap.general.CityInfo) ZipCodeInfo(uk.me.parabola.mkgmap.general.ZipCodeInfo)

Example 10 with CityInfo

use of uk.me.parabola.mkgmap.general.CityInfo in project mkgmap by openstreetmap.

the class CityZipWriter method compile.

public boolean compile(List<Numbers> numbers) {
    try {
        // left and right entry in zip or city table
        // current num
        int[] indexes = { defaultIndex, defaultIndex };
        // previous num
        int[] refIndexes = { defaultIndex, defaultIndex };
        int lastEncodedNodeIndex = -1;
        boolean needsWrite = false;
        for (Numbers num : numbers) {
            for (int side = 0; side < 2; side++) {
                indexes[side] = defaultIndex;
                boolean left = (side == 0);
                switch(type) {
                    case "zip":
                        ZipCodeInfo zipInfo = num.getZipCodeInfo(left);
                        if (zipInfo != null) {
                            if (zipInfo.getImgZip() != null) {
                                indexes[side] = zipInfo.getImgZip().getIndex();
                            }
                        }
                        break;
                    case "city":
                        CityInfo cityInfo = num.getCityInfo(left);
                        if (cityInfo != null) {
                            if (cityInfo.getImgCity() != null) {
                                indexes[side] = cityInfo.getImgCity().getIndex();
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
            if (indexes[0] == refIndexes[0] && indexes[1] == refIndexes[1])
                continue;
            needsWrite = true;
            if (num.getIndex() > 0) {
                int range = num.getIndex() - 1;
                if (lastEncodedNodeIndex > 0)
                    range -= lastEncodedNodeIndex;
                encode(range, refIndexes);
            }
            refIndexes[0] = indexes[0];
            refIndexes[1] = indexes[1];
            lastEncodedNodeIndex = num.getIndex();
        }
        if (needsWrite) {
            int lastIndexWithNumbers = numbers.get(numbers.size() - 1).getIndex();
            int range = lastIndexWithNumbers - lastEncodedNodeIndex;
            encode(range, indexes);
        } else {
            // probably not needed
            buf.reset();
        }
    } catch (Abandon e) {
        return false;
    }
    return true;
}
Also used : CityInfo(uk.me.parabola.mkgmap.general.CityInfo) ZipCodeInfo(uk.me.parabola.mkgmap.general.ZipCodeInfo)

Aggregations

CityInfo (uk.me.parabola.mkgmap.general.CityInfo)12 ZipCodeInfo (uk.me.parabola.mkgmap.general.ZipCodeInfo)6 ArrayList (java.util.ArrayList)5 LongArrayList (it.unimi.dsi.fastutil.longs.LongArrayList)4 Int2IntOpenHashMap (it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap)3 Coord (uk.me.parabola.imgfmt.app.Coord)3 MapRoad (uk.me.parabola.mkgmap.general.MapRoad)3 Int2ObjectOpenHashMap (it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap)2 Long2ObjectOpenHashMap (it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 LinkedHashMap (java.util.LinkedHashMap)2 LinkedHashSet (java.util.LinkedHashSet)2 Numbers (uk.me.parabola.imgfmt.app.net.Numbers)2 MultiHashMap (uk.me.parabola.util.MultiHashMap)2 List (java.util.List)1 TreeMap (java.util.TreeMap)1 City (uk.me.parabola.imgfmt.app.lbl.City)1 LBLFile (uk.me.parabola.imgfmt.app.lbl.LBLFile)1 Zip (uk.me.parabola.imgfmt.app.lbl.Zip)1