Search in sources :

Example 1 with MapRoad

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

the class StyledConverter method addRoadWithoutLoops.

private void addRoadWithoutLoops(ConvertedWay cw) {
    Way way = cw.getWay();
    List<Integer> nodeIndices = new ArrayList<>();
    List<Coord> points = way.getPoints();
    if (points.size() < 2) {
        log.warn("road has < 2 points", way.getId(), "(discarding)");
        return;
    }
    Way trailingWay = null;
    String debugWayName = way.getDebugName();
    // collect the Way's nodes and also split the way if any
    // inter-node arc length becomes excessive
    double arcLength = 0;
    // detect if it would be split by the LineSizeSplitterFilter
    class WayBBox {

        int minLat = Integer.MAX_VALUE;

        int maxLat = Integer.MIN_VALUE;

        int minLon = Integer.MAX_VALUE;

        int maxLon = Integer.MIN_VALUE;

        void addPoint(Coord co) {
            int lat = co.getLatitude();
            if (lat < minLat)
                minLat = lat;
            if (lat > maxLat)
                maxLat = lat;
            int lon = co.getLongitude();
            if (lon < minLon)
                minLon = lon;
            if (lon > maxLon)
                maxLon = lon;
        }

        boolean tooBig() {
            return LineSizeSplitterFilter.testDims(maxLat - minLat, maxLon - minLon) >= 1.0;
        }
    }
    WayBBox wayBBox = new WayBBox();
    for (int i = 0; i < points.size(); ++i) {
        Coord p = points.get(i);
        wayBBox.addPoint(p);
        // the arc length between nodes
        if ((i + 1) < points.size()) {
            Coord nextP = points.get(i + 1);
            double d = p.distance(nextP);
            for (; ; ) {
                int dlat = Math.abs(nextP.getLatitude() - p.getLatitude());
                int dlon = Math.abs(nextP.getLongitude() - p.getLongitude());
                if (d > MAX_ARC_LENGTH || Math.max(dlat, dlon) >= LineSizeSplitterFilter.MAX_SIZE) {
                    double frac = Math.min(0.5, 0.95 * (MAX_ARC_LENGTH / d));
                    nextP = p.makeBetweenPoint(nextP, frac);
                    nextP.incHighwayCount();
                    points.add(i + 1, nextP);
                    double newD = p.distance(nextP);
                    if (log.isInfoEnabled())
                        log.info("Way", debugWayName, "contains a segment that is", (int) d + "m long but I am adding a new point to reduce its length to", (int) newD + "m");
                    d = newD;
                } else
                    break;
            }
            wayBBox.addPoint(nextP);
            if ((arcLength + d) > MAX_ARC_LENGTH) {
                if (i <= 0)
                    log.error("internal error: long arc segment was not split", debugWayName);
                assert i > 0 : "long arc segment was not split";
                assert trailingWay == null : "trailingWay not null #1";
                trailingWay = splitWayAt(way, i);
                // points so the loop will now terminate
                if (log.isInfoEnabled())
                    log.info("Splitting way", debugWayName, "at", points.get(i).toOSMURL(), "to limit arc length to", (long) arcLength + "m");
            } else if (wayBBox.tooBig()) {
                if (i <= 0)
                    log.error("internal error: arc segment with big bbox not split", debugWayName);
                assert i > 0 : "arc segment with big bbox not split";
                assert trailingWay == null : "trailingWay not null #2";
                trailingWay = splitWayAt(way, i);
                // points so the loop will now terminate
                if (log.isInfoEnabled())
                    log.info("Splitting way", debugWayName, "at", points.get(i).toOSMURL(), "to limit the size of its bounding box");
            } else {
                if (p.getHighwayCount() > 1) {
                    // point is a node so zero arc length
                    arcLength = 0;
                }
                arcLength += d;
            }
        }
        if (p.getHighwayCount() > 1) {
            // this point is a node connecting highways
            CoordNode coordNode = nodeIdMap.get(p);
            if (coordNode == null) {
                // assign a node id
                coordNode = new CoordNode(p, nextNodeId++, p.getOnBoundary());
                nodeIdMap.put(p, coordNode);
            }
            if (p instanceof CoordPOI) {
                // check if this poi should be converted to a route restriction
                CoordPOI cp = (CoordPOI) p;
                if (cp.getConvertToViaInRouteRestriction()) {
                    String wayPOI = way.getTag(WAY_POI_NODE_IDS);
                    if (wayPOI != null && wayPOI.contains("[" + cp.getNode().getId() + "]")) {
                        byte nodeAccess = AccessTagsAndBits.evalAccessTags(cp.getNode());
                        if (nodeAccess != cw.getAccess()) {
                            List<Way> wayList = poiRestrictions.get(cp.getNode());
                            if (wayList == null) {
                                wayList = new ArrayList<>();
                                poiRestrictions.put(cp.getNode(), wayList);
                            }
                            wayList.add(way);
                        }
                    }
                }
            }
            // add this index to node Indexes (should not already be there)
            assert !nodeIndices.contains(i) : debugWayName + " has multiple nodes for point " + i + " new node is " + p.toOSMURL();
            nodeIndices.add(i);
            if ((i + 1) < points.size() && nodeIndices.size() == MAX_NODES_IN_WAY) {
                // limit
                assert trailingWay == null : "trailingWay not null #7";
                trailingWay = splitWayAt(way, i);
                // points so the loop will now terminate
                if (log.isInfoEnabled())
                    log.info("Splitting way", debugWayName, "at", points.get(i).toOSMURL(), "as it has at least", MAX_NODES_IN_WAY, "nodes");
            }
        }
    }
    MapLine line = new MapLine();
    elementSetup(line, cw.getGType(), way);
    line.setPoints(points);
    MapRoad road = new MapRoad(nextRoadId++, way.getId(), line);
    if (routable == false)
        road.skipAddToNOD(true);
    boolean doFlareCheck = true;
    if (cw.isRoundabout()) {
        road.setRoundabout(true);
        doFlareCheck = false;
    }
    if (way.tagIsLikeYes("mkgmap:synthesised")) {
        road.setSynthesised(true);
        doFlareCheck = false;
    }
    if (way.tagIsLikeNo("mkgmap:flare-check")) {
        doFlareCheck = false;
    } else if (way.tagIsLikeYes("mkgmap:flare-check")) {
        doFlareCheck = true;
    }
    road.doFlareCheck(doFlareCheck);
    // set road parameters
    // copy road class and road speed
    road.setRoadClass(cw.getRoadClass());
    road.setSpeed(cw.getRoadSpeed());
    if (cw.isOneway()) {
        road.setDirection(true);
        road.setOneway();
    }
    road.setAccess(cw.getAccess());
    // does the road have a carpool lane?
    if (cw.isCarpool())
        road.setCarpoolLane();
    if (cw.isThroughroute() == false)
        road.setNoThroughRouting();
    if (cw.isToll())
        road.setToll();
    // by default, ways are paved
    if (cw.isUnpaved())
        road.paved(false);
    // by default, way's are not ferry routes
    if (cw.isFerry())
        road.ferry(true);
    int numNodes = nodeIndices.size();
    if (way.isViaWay() && numNodes > 2) {
        List<RestrictionRelation> rrList = wayRelMap.get(way.getId());
        for (RestrictionRelation rr : rrList) {
            rr.updateViaWay(way, nodeIndices);
        }
    }
    if (numNodes > 0) {
        // replace Coords that are nodes with CoordNodes
        for (int i = 0; i < numNodes; ++i) {
            int n = nodeIndices.get(i);
            Coord coord = points.get(n);
            CoordNode thisCoordNode = nodeIdMap.get(coord);
            assert thisCoordNode != null : "Way " + debugWayName + " node " + i + " (point index " + n + ") at " + coord.toOSMURL() + " yields a null coord node";
            boolean boundary = coord.getOnBoundary();
            if (boundary && log.isInfoEnabled()) {
                log.info("Way", debugWayName + "'s point #" + n, "at", coord.toOSMURL(), "is a boundary node");
            }
            points.set(n, thisCoordNode);
        }
    }
    if (roadLog.isInfoEnabled()) {
        // shift the bits so that they have the correct position
        int cmpAccess = (road.getRoadDef().getTabAAccess() & 0xff) + ((road.getRoadDef().getTabAAccess() & 0xc000) >> 6);
        if (road.isDirection()) {
            cmpAccess |= 1 << 10;
        }
        String access = String.format("%11s", Integer.toBinaryString(cmpAccess)).replace(' ', '0');
        roadLog.info(String.format("%19d 0x%-2x %11s %6d %6d %6d %s", way.getId(), road.getType(), access, road.getRoadDef().getRoadClass(), road.getRoadDef().getRoadSpeed(), road.getPoints().size(), Arrays.toString(road.getLabels())));
    }
    // add the road to the housenumber generator
    // it will add the road later on to the lineAdder
    housenumberGenerator.addRoad(way, road);
    if (trailingWay != null)
        addRoadWithoutLoops(new ConvertedWay(cw, trailingWay));
}
Also used : MapLine(uk.me.parabola.mkgmap.general.MapLine) ArrayList(java.util.ArrayList) MapRoad(uk.me.parabola.mkgmap.general.MapRoad) Way(uk.me.parabola.mkgmap.reader.osm.Way) MapPoint(uk.me.parabola.mkgmap.general.MapPoint) MapExitPoint(uk.me.parabola.mkgmap.general.MapExitPoint) Coord(uk.me.parabola.imgfmt.app.Coord) RestrictionRelation(uk.me.parabola.mkgmap.reader.osm.RestrictionRelation) CoordPOI(uk.me.parabola.mkgmap.reader.osm.CoordPOI) CoordNode(uk.me.parabola.imgfmt.app.CoordNode)

Example 2 with MapRoad

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

the class StyleTester method formatResults.

/**
 * Print out the garmin elements that were produced by the rules.
 * @param prefix This string will be prepended to the formatted result.
 * @param lines The resulting map elements.
 */
private static List<String> formatResults(String prefix, List<MapElement> lines) {
    List<String> result = new ArrayList<>();
    int i = 0;
    for (MapElement el : lines) {
        String s;
        // So we can run against versions that do not have toString() methods
        if (el instanceof MapRoad)
            s = roadToString((MapRoad) el);
        else
            s = lineToString((MapLine) el);
        result.add(prefix + s);
    }
    return result;
}
Also used : MapElement(uk.me.parabola.mkgmap.general.MapElement) ArrayList(java.util.ArrayList) MapRoad(uk.me.parabola.mkgmap.general.MapRoad) MapPoint(uk.me.parabola.mkgmap.general.MapPoint)

Example 3 with MapRoad

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

the class ExtNumbers method getNumberList.

/**
 * Return the intervals in the format used for the writer routines
 * @return
 */
public List<Numbers> getNumberList() {
    // do we have numbers?
    boolean foundNumbers = false;
    for (ExtNumbers curr = this; curr != null; curr = curr.next) {
        if (curr.hasNumbers()) {
            foundNumbers = true;
            break;
        }
    }
    if (!foundNumbers)
        return null;
    List<Numbers> list = new ArrayList<>();
    boolean headerWasReported = false;
    for (ExtNumbers curr = this; curr != null; curr = curr.next) {
        if (curr.hasNumbers() == false)
            continue;
        list.add(curr.getNumbers());
        if (log.isInfoEnabled()) {
            if (headerWasReported == false) {
                MapRoad road = curr.getRoad();
                if (road.getStreet() == null && road.getName() == null)
                    log.info("final numbers for", road, curr.housenumberRoad.getName(), "in", road.getCity());
                else
                    log.info("final numbers for", road, "in", road.getCity());
                headerWasReported = true;
            }
            Numbers cn = curr.getNumbers();
            log.info("Left: ", cn.getLeftNumberStyle(), cn.getIndex(), "Start:", cn.getLeftStart(), "End:", cn.getLeftEnd(), "numbers " + curr.getHouses(Numbers.LEFT));
            log.info("Right:", cn.getRightNumberStyle(), cn.getIndex(), "Start:", cn.getRightStart(), "End:", cn.getRightEnd(), "numbers " + curr.getHouses(Numbers.RIGHT));
        }
    }
    return list;
}
Also used : Numbers(uk.me.parabola.imgfmt.app.net.Numbers) ArrayList(java.util.ArrayList) MapRoad(uk.me.parabola.mkgmap.general.MapRoad)

Example 4 with MapRoad

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

the class HousenumberGenerator method identifyServiceRoads.

/**
 * process option --x-name-service-roads=n
 * The program identifies unnamed roads which are only connected to one
 * road with a name or to multiple roads with the same name. The process is
 * repeated n times. If n > 1 the program will also use unnamed roads which
 * are connected to unnamed roads if those are connected to named roads.
 * Higher values for n mean deeper search, but reasonable values are
 * probably between 1 and 5.
 *
 * These roads are then used for house number processing like the named
 * ones. If house numbers are assigned to these roads, they are named so
 * that address search will find them.
 */
private void identifyServiceRoads() {
    Int2ObjectOpenHashMap<String> roadNamesByNodeIds = new Int2ObjectOpenHashMap<>();
    HashMap<MapRoad, List<Coord>> coordNodesUnnamedRoads = new HashMap<>();
    HashSet<Integer> unclearNodeIds = new HashSet<>();
    long t1 = System.currentTimeMillis();
    List<MapRoad> unnamedRoads = new ArrayList<>();
    for (MapRoad road : allRoads) {
        if (road.isSkipHousenumberProcessing())
            continue;
        if (road.getStreet() == null) {
            // the road probably has a ref. We assume these are not service roads.
            if (road.getName() == null) {
                unnamedRoads.add(road);
                List<Coord> nodes = new ArrayList<>();
                for (Coord co : road.getPoints()) {
                    if (co.getId() != 0)
                        nodes.add(co);
                }
                coordNodesUnnamedRoads.put(road, nodes);
            }
        } else {
            identifyNodes(road.getPoints(), road.getStreet(), roadNamesByNodeIds, unclearNodeIds);
        }
    }
    int numUnnamedRoads = unnamedRoads.size();
    long t2 = System.currentTimeMillis();
    if (log.isDebugEnabled())
        log.debug("identifyServiceRoad step 1 took", (t2 - t1), "ms, found", roadNamesByNodeIds.size(), "nodes to check and", numUnnamedRoads, "unnamed roads");
    long t3 = System.currentTimeMillis();
    int named = 0;
    for (int pass = 1; pass <= nameSearchDepth; pass++) {
        int unnamed = 0;
        List<MapRoad> namedRoads = new ArrayList<>();
        for (int j = 0; j < unnamedRoads.size(); j++) {
            MapRoad road = unnamedRoads.get(j);
            if (road == null)
                continue;
            unnamed++;
            List<Coord> coordNodes = coordNodesUnnamedRoads.get(road);
            String name = null;
            for (Coord co : coordNodes) {
                if (unclearNodeIds.contains(co.getId())) {
                    name = null;
                    // don't process again
                    unnamedRoads.set(j, null);
                    break;
                }
                String possibleName = roadNamesByNodeIds.get(co.getId());
                if (possibleName == null)
                    continue;
                if (name == null)
                    name = possibleName;
                else if (name.equals(possibleName) == false) {
                    name = null;
                    // don't process again
                    unnamedRoads.set(j, null);
                    break;
                }
            }
            if (name != null) {
                named++;
                road.setStreet(name);
                namedRoads.add(road);
                // don't process again
                unnamedRoads.set(j, null);
            }
        }
        for (MapRoad road : namedRoads) {
            road.setNamedByHousenumberProcessing(true);
            String name = road.getStreet();
            if (log.isDebugEnabled())
                log.debug("pass", pass, "using unnamed road for housenumber processing,id=", road.getRoadDef().getId(), ":", name);
            List<Coord> coordNodes = coordNodesUnnamedRoads.get(road);
            identifyNodes(coordNodes, name, roadNamesByNodeIds, unclearNodeIds);
        }
        if (namedRoads.isEmpty())
            break;
        if (log.isDebugEnabled())
            log.debug("pass", pass, unnamed, named);
    }
    long t4 = System.currentTimeMillis();
    if (log.isDebugEnabled()) {
        log.debug("indentifyServiceRoad step 2 took", (t4 - t3), "ms, found a name for", named, "of", numUnnamedRoads, "roads");
    }
    return;
}
Also used : Int2ObjectOpenHashMap(it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap) 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) MapRoad(uk.me.parabola.mkgmap.general.MapRoad) Coord(uk.me.parabola.imgfmt.app.Coord) LongArrayList(it.unimi.dsi.fastutil.longs.LongArrayList) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 5 with MapRoad

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

the class HousenumberGenerator method findClosestRoadSegment.

/**
 * Fill/overwrite the fields in house which depend on the assigned road.
 */
public static void findClosestRoadSegment(HousenumberMatch house, MapRoad r, int firstSeg, int stopSeg) {
    Coord cx = house.getLocation();
    double oldDist = house.getDistance();
    MapRoad oldRoad = house.getRoad();
    house.setRoad(null);
    house.setDistance(Double.POSITIVE_INFINITY);
    boolean foundGroupLink = false;
    int end = Math.min(r.getPoints().size(), stopSeg + 1);
    for (int node = firstSeg; node + 1 < end; node++) {
        Coord c1 = r.getPoints().get(node);
        Coord c2 = r.getPoints().get(node + 1);
        double frac = getFrac(c1, c2, cx);
        double dist = distanceToSegment(c1, c2, cx, frac);
        if (house.getGroup() != null && house.getGroup().linkNode == c1) {
            if (c1.highPrecEquals(c2) == false) {
                log.debug("block doesn't have zero length segment! Road:", r, house);
            }
            foundGroupLink = true;
            house.setDistance(dist);
            house.setSegmentFrac(frac);
            house.setRoad(r);
            house.setSegment(node);
            break;
        } else if (dist < house.getDistance()) {
            house.setDistance(dist);
            house.setSegmentFrac(frac);
            house.setRoad(r);
            house.setSegment(node);
        }
    }
    if (house.getGroup() != null && house.getGroup().linkNode != null && foundGroupLink == false) {
        log.debug(r, house, "has a group but the link was not found, should only happen after split of zero-length-segment");
    }
    if (oldRoad == r) {
        if (house.getDistance() > MAX_DISTANCE_TO_ROAD + 2.5 && oldDist <= MAX_DISTANCE_TO_ROAD) {
            log.warn("line distorted? Road segment was moved by more than", String.format("%.2f m", 2.5), ", from address", r, house.getSign());
        }
    }
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) MapRoad(uk.me.parabola.mkgmap.general.MapRoad)

Aggregations

MapRoad (uk.me.parabola.mkgmap.general.MapRoad)16 ArrayList (java.util.ArrayList)11 Coord (uk.me.parabola.imgfmt.app.Coord)9 MapLine (uk.me.parabola.mkgmap.general.MapLine)6 MapPoint (uk.me.parabola.mkgmap.general.MapPoint)5 LongArrayList (it.unimi.dsi.fastutil.longs.LongArrayList)4 MapShape (uk.me.parabola.mkgmap.general.MapShape)4 Int2ObjectOpenHashMap (it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap)3 HashMap (java.util.HashMap)3 HashSet (java.util.HashSet)3 LinkedHashSet (java.util.LinkedHashSet)3 Numbers (uk.me.parabola.imgfmt.app.net.Numbers)3 CityInfo (uk.me.parabola.mkgmap.general.CityInfo)3 Int2IntOpenHashMap (it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap)2 Long2ObjectOpenHashMap (it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 List (java.util.List)2 CoordNode (uk.me.parabola.imgfmt.app.CoordNode)2 MapExitPoint (uk.me.parabola.mkgmap.general.MapExitPoint)2 MultiHashMap (uk.me.parabola.util.MultiHashMap)2