Search in sources :

Example 1 with RestrictionRelation

use of uk.me.parabola.mkgmap.reader.osm.RestrictionRelation 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 RestrictionRelation

use of uk.me.parabola.mkgmap.reader.osm.RestrictionRelation in project mkgmap by openstreetmap.

the class WrongAngleFixer method removeWrongAngles.

/**
 * Find wrong angles caused by rounding to map units. Try to fix them by
 * moving, removing or merging points.
 * @param roads list with routable ways or null, if lines should be optimized
 * @param lines list with non-routable ways
 * @param modifiedRoads map of modified routable ways (modified by this routine)
 * @param deletedRoads set of ids of deleted routable ways (modified by this routine)
 * @param restrictions Map with restriction relations. The restriction relations may be modified by this routine
 */
private void removeWrongAngles(List<ConvertedWay> roads, List<ConvertedWay> lines, HashMap<Long, ConvertedWay> modifiedRoads, HashSet<Long> deletedRoads, List<RestrictionRelation> restrictions) {
    // replacements maps those nodes that have been replaced to
    // the node that replaces them
    Map<Coord, Coord> replacements = new IdentityHashMap<>();
    final HashSet<Coord> changedPlaces = new HashSet<>();
    int numNodesMerged = 0;
    HashSet<Way> waysWithBearingErrors = new HashSet<>();
    HashSet<Long> waysThatMapToOnePoint = new HashSet<>();
    Way lastWay = null;
    List<ConvertedWay> convertedWays = (roads != null) ? roads : lines;
    boolean anotherPassRequired = true;
    for (pass = 1; pass < 20; pass++) {
        if (!anotherPassRequired && !extraPass)
            break;
        anotherPassRequired = false;
        log.info("Removing wrong angles - PASS", pass);
        writeOSM(((mode == MODE_LINES) ? "lines" : "roads") + "_pass_" + pass, convertedWays);
        // Step 1: detect points which are parts of line segments with wrong bearings
        lastWay = null;
        for (ConvertedWay cw : convertedWays) {
            if (!cw.isValid() || cw.isOverlay())
                continue;
            Way way = cw.getWay();
            if (way.equals(lastWay))
                continue;
            if (pass != 1 && waysWithBearingErrors.contains(way) == false)
                continue;
            lastWay = way;
            List<Coord> points = way.getPoints();
            // scan through the way's points looking for line segments with big
            // bearing errors
            Coord prev = null;
            if (points.get(0) == points.get(points.size() - 1) && points.size() >= 2)
                prev = points.get(points.size() - 2);
            boolean hasNonEqualPoints = false;
            for (int i = 0; i < points.size(); ++i) {
                Coord p = points.get(i);
                if (pass == 1)
                    p.setRemove(false);
                p = getReplacement(p, way, replacements);
                if (i == 0 || i == points.size() - 1) {
                    p.setEndOfWay(true);
                }
                if (prev != null) {
                    if (pass == 1 && p.equals(prev) == false)
                        hasNonEqualPoints = true;
                    double err = calcBearingError(p, prev);
                    if (err >= MAX_BEARING_ERROR) {
                        // bearing error is big
                        p.setPartOfBadAngle(true);
                        prev.setPartOfBadAngle(true);
                    }
                }
                prev = p;
            }
            if (pass == 1 && hasNonEqualPoints == false) {
                waysThatMapToOnePoint.add(way.getId());
                log.info("all points of way", way.toBrowseURL(), "are rounded to equal map units");
            }
        }
        // Step 2: collect the line segments that are connected to critical points
        IdentityHashMap<Coord, CenterOfAngle> centerMap = new IdentityHashMap<>();
        // needed for ordered processing
        List<CenterOfAngle> centers = new ArrayList<>();
        Map<Coord, Set<Way>> overlaps = new HashMap<>();
        lastWay = null;
        for (ConvertedWay cw : convertedWays) {
            if (!cw.isValid() || cw.isOverlay())
                continue;
            Way way = cw.getWay();
            if (way.equals(lastWay))
                continue;
            if (pass != 1 && waysWithBearingErrors.contains(way) == false)
                continue;
            lastWay = way;
            boolean wayHasSpecialPoints = false;
            List<Coord> points = way.getPoints();
            // scan through the way's points looking for line segments with big
            // bearing errors
            Coord prev = null;
            if (points.get(0) == points.get(points.size() - 1) && points.size() >= 2)
                prev = points.get(points.size() - 2);
            for (int i = 0; i < points.size(); ++i) {
                Coord p = points.get(i);
                if (prev != null) {
                    if (p == prev) {
                        points.remove(i);
                        --i;
                        if (mode == MODE_ROADS)
                            modifiedRoads.put(way.getId(), cw);
                        continue;
                    }
                    if (p.isPartOfBadAngle() || prev.isPartOfBadAngle()) {
                        wayHasSpecialPoints = true;
                        // save both points with their neighbour
                        Coord p1 = prev;
                        Coord p2 = p;
                        CenterOfAngle coa1 = getOrCreateCenter(p, way, centerMap, centers, overlaps);
                        CenterOfAngle coa2 = getOrCreateCenter(prev, way, centerMap, centers, overlaps);
                        coa1.addNeighbour(coa2);
                        coa2.addNeighbour(coa1);
                        if (points.size() == 2) {
                            // way has only two points, don't merge them
                            coa1.addBadMergeCandidate(coa2);
                        }
                        if (mode == MODE_ROADS) {
                            if (p1.getHighwayCount() >= 2 && p2.getHighwayCount() >= 2) {
                                if (cw.isRoundabout()) {
                                    // avoid to merge exits of roundabouts
                                    coa1.addBadMergeCandidate(coa2);
                                }
                            }
                        }
                    }
                }
                prev = p;
            }
            if (pass == 1 && wayHasSpecialPoints)
                waysWithBearingErrors.add(way);
        }
        markOverlaps(overlaps, centers);
        overlaps.clear();
        // Step 3: Update list of ways with bearing errors or points next to them
        lastWay = null;
        for (ConvertedWay cw : convertedWays) {
            if (!cw.isValid() || cw.isOverlay())
                continue;
            Way way = cw.getWay();
            if (way.equals(lastWay))
                continue;
            lastWay = way;
            if (waysWithBearingErrors.contains(way))
                continue;
            List<Coord> points = way.getPoints();
            // bearing errors
            for (Coord p : points) {
                if (p.getHighwayCount() < 2)
                    continue;
                if (centerMap.containsKey(p)) {
                    waysWithBearingErrors.add(way);
                    break;
                }
            }
        }
        log.info("pass " + pass + ": analysing " + centers.size() + " points with bearing problems.");
        // Return to GC
        centerMap = null;
        // Step 4: try to correct the errors
        List<CenterOfAngle> checkAgainList = null;
        boolean tryMerge = false;
        while (true) {
            checkAgainList = new ArrayList<>();
            for (CenterOfAngle coa : centers) {
                // reset flag for next pass
                coa.center.setPartOfBadAngle(false);
                if (coa.getCurrentLocation(replacements) == null)
                    // removed center
                    continue;
                if (coa.isOK(replacements) == false) {
                    boolean changed = coa.tryChange(replacements, tryMerge);
                    if (changed) {
                        if (DEBUG_PATH != null)
                            changedPlaces.add(coa.center);
                        continue;
                    }
                    checkAgainList.add(coa);
                }
            }
            if (tryMerge)
                // leave when 2nd pass finished
                break;
            tryMerge = true;
            centers = checkAgainList;
        }
        // Step 5: apply the calculated corrections to the ways
        lastWay = null;
        boolean lastWayModified = false;
        ConvertedWay lastConvertedWay = null;
        for (ConvertedWay cw : convertedWays) {
            if (!cw.isValid() || cw.isOverlay())
                continue;
            Way way = cw.getWay();
            if (waysWithBearingErrors.contains(way) == false)
                continue;
            List<Coord> points = way.getPoints();
            if (way.equals(lastWay)) {
                if (lastWayModified) {
                    points.clear();
                    points.addAll(lastWay.getPoints());
                    if (cw.isReversed() != lastConvertedWay.isReversed())
                        Collections.reverse(points);
                }
                continue;
            }
            lastWay = way;
            lastConvertedWay = cw;
            lastWayModified = false;
            // loop backwards because we may delete points
            for (int i = points.size() - 1; i >= 0; i--) {
                Coord p = points.get(i);
                if (p.isToRemove()) {
                    points.remove(i);
                    anotherPassRequired = true;
                    lastWayModified = true;
                    if (i > 0 && i < points.size()) {
                        // special case: handle micro loop
                        if (points.get(i - 1) == points.get(i))
                            points.remove(i);
                    }
                    continue;
                }
                // check if this point is to be replaced because
                // it was previously moved
                Coord replacement = getReplacement(p, way, replacements);
                if (p == replacement)
                    continue;
                if (p.isViaNodeOfRestriction()) {
                    // make sure that we find the restriction with the new coord instance
                    replacement.setViaNodeOfRestriction(true);
                    p.setViaNodeOfRestriction(false);
                }
                p = replacement;
                // replace point in way
                points.set(i, p);
                if (p.getHighwayCount() >= 2)
                    numNodesMerged++;
                lastWayModified = true;
                if (i + 1 < points.size() && points.get(i + 1) == p) {
                    points.remove(i);
                    anotherPassRequired = true;
                }
                if (i - 1 >= 0 && points.get(i - 1) == p) {
                    points.remove(i);
                    anotherPassRequired = true;
                }
            }
            if (lastWayModified && mode == MODE_ROADS) {
                modifiedRoads.put(way.getId(), cw);
            }
        }
        if (extraPass) {
            anotherPassRequired = false;
            break;
        } else {
            if (!anotherPassRequired) {
                // check if we have centres on different ways that overlap
                for (CenterOfAngle coa : centers) {
                    if (coa.forceChange) {
                        anotherPassRequired = true;
                        extraPass = true;
                        break;
                    }
                }
            }
        }
    }
    // finish: remove remaining duplicate points
    int numWaysDeleted = 0;
    lastWay = null;
    boolean lastWayModified = false;
    ConvertedWay lastConvertedWay = null;
    for (ConvertedWay cw : convertedWays) {
        if (cw.isOverlay())
            continue;
        Way way = cw.getWay();
        List<Coord> points = way.getPoints();
        if (points.size() < 2) {
            if (log.isInfoEnabled())
                log.info("  Way " + way.getTag("name") + " (" + way.toBrowseURL() + ") has less than 2 points - deleting it");
            if (mode == MODE_LINES && waysThatMapToOnePoint.contains(way.getId()) == false)
                log.warn("non-routable way ", way.getId(), "was removed");
            if (mode == MODE_ROADS)
                deletedRoads.add(way.getId());
            ++numWaysDeleted;
            continue;
        }
        if (way.equals(lastWay)) {
            if (lastWayModified) {
                points.clear();
                points.addAll(lastWay.getPoints());
                if (cw.isReversed() != lastConvertedWay.isReversed())
                    Collections.reverse(points);
            }
            continue;
        }
        lastWay = way;
        lastConvertedWay = cw;
        lastWayModified = false;
        Coord prev = points.get(points.size() - 1);
        // loop backwards because we may delete points
        for (int i = points.size() - 2; i >= 0; i--) {
            Coord p = points.get(i);
            if (p == prev) {
                points.remove(i);
                lastWayModified = true;
            }
            // if (p.equals(prev) && (p.getHighwayCount() < 2 || prev.getHighwayCount() < 2)){
            // // not an error, but should not happen
            // log.warn("way " + way.getId() + " still has consecutive equal points at " + p.toOSMURL());
            // }
            prev = p;
        }
    }
    if (mode == MODE_ROADS) {
        // points in roads
        for (ConvertedWay cw : lines) {
            if (!cw.isValid() || cw.isOverlay())
                continue;
            Way way = cw.getWay();
            List<Coord> points = way.getPoints();
            int n = points.size();
            boolean hasReplacedPoints = false;
            for (int i = 0; i < n; i++) {
                Coord p = points.get(i);
                if (p.isReplaced()) {
                    hasReplacedPoints = true;
                    points.set(i, getReplacement(p, null, replacements));
                }
            }
            if (hasReplacedPoints && DEBUG_PATH != null) {
                GpxCreator.createGpx(Utils.joinPath(DEBUG_PATH, way.getId() + "_mod_non_routable"), points);
            }
        }
        for (RestrictionRelation rr : restrictions) {
            for (Coord p : rr.getViaCoords()) {
                Coord replacement = getReplacement(p, null, replacements);
                if (p != replacement) {
                    rr.replaceViaCoord(p, replacement);
                }
            }
        }
    }
    if (DEBUG_PATH != null) {
        GpxCreator.createGpx(Utils.joinPath(DEBUG_PATH, (mode == MODE_ROADS ? "roads_" : "lines_") + "solved_badAngles"), bbox.toCoords(), new ArrayList<>(changedPlaces));
    }
    if (anotherPassRequired)
        log.error("Removing wrong angles - didn't finish in " + pass + " passes, giving up!");
    else
        log.info("Removing wrong angles - finished in", pass, "passes (", numNodesMerged, "nodes merged,", numWaysDeleted, "ways deleted)");
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) Long2ObjectOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap) IdentityHashMap(java.util.IdentityHashMap) ArrayList(java.util.ArrayList) Way(uk.me.parabola.mkgmap.reader.osm.Way) Coord(uk.me.parabola.imgfmt.app.Coord) RestrictionRelation(uk.me.parabola.mkgmap.reader.osm.RestrictionRelation) HashSet(java.util.HashSet)

Example 3 with RestrictionRelation

use of uk.me.parabola.mkgmap.reader.osm.RestrictionRelation in project mkgmap by openstreetmap.

the class RoadMerger method workoutRestrictionRelations.

/**
 * We must not merge roads at via points of restriction relations
 * if the way is referenced in the restriction.
 * @param restrictionRels
 */
private void workoutRestrictionRelations(List<RestrictionRelation> restrictionRels) {
    for (RestrictionRelation rel : restrictionRels) {
        Set<Long> restrictionWayIds = rel.getWayIds();
        for (Coord via : rel.getViaCoords()) {
            HashSet<ConvertedWay> roadAtVia = new HashSet<>();
            roadAtVia.addAll(startPoints.get(via));
            roadAtVia.addAll(endPoints.get(via));
            for (ConvertedWay r : roadAtVia) {
                long wayId = r.getWay().getId();
                if (restrictionWayIds.contains(wayId))
                    restrictions.add(via, wayId);
            }
        }
    }
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) RestrictionRelation(uk.me.parabola.mkgmap.reader.osm.RestrictionRelation) HashSet(java.util.HashSet)

Example 4 with RestrictionRelation

use of uk.me.parabola.mkgmap.reader.osm.RestrictionRelation in project mkgmap by openstreetmap.

the class StyledConverter method end.

public void end() {
    pointMap.clear();
    style.reportStats();
    driveOnLeft = calcDrivingSide();
    setHighwayCounts();
    findUnconnectedRoads();
    rotateClosedWaysToFirstNode();
    filterCoordPOI();
    WrongAngleFixer wrongAngleFixer = new WrongAngleFixer(bbox);
    wrongAngleFixer.optimizeWays(roads, lines, modifiedRoads, deletedRoads, restrictions);
    // make sure that copies of modified roads have equal points
    for (ConvertedWay line : lines) {
        if (!line.isValid())
            continue;
        Way way = line.getWay();
        if (deletedRoads.contains(way.getId())) {
            line.getPoints().clear();
            continue;
        }
        if (!line.isOverlay())
            continue;
        ConvertedWay modWay = modifiedRoads.get(way.getId());
        if (modWay != null) {
            List<Coord> points = line.getPoints();
            points.clear();
            points.addAll(modWay.getPoints());
            if (modWay.isReversed() != line.isReversed())
                Collections.reverse(points);
        }
    }
    for (Long wayId : deletedRoads) {
        if (wayRelMap.containsKey(wayId)) {
            // may happen e.g. when very short way is leading to nowhere
            log.warn("Way that is used in valid restriction relation was removed, id:", wayId);
        }
    }
    deletedRoads = null;
    modifiedRoads = null;
    mergeRoads();
    resetHighwayCounts();
    setHighwayCounts();
    for (ConvertedWay cw : lines) {
        if (cw.isValid())
            addLine(cw.getWay(), cw.getGType());
    }
    lines = null;
    if (roadLog.isInfoEnabled()) {
        roadLog.info("Flags: oneway,no-emergency, no-delivery, no-throughroute, no-truck, no-bike, no-foot, carpool, no-taxi, no-bus, no-car");
        roadLog.info(String.format("%19s %4s %11s %6s %6s %6s %s", "Road-OSM-Id", "Type", "Flags", "Class", "Speed", "Points", "Labels"));
    }
    // add the roads after the other lines
    for (ConvertedWay cw : roads) {
        if (cw.isValid())
            addRoad(cw);
    }
    housenumberGenerator.generate(lineAdder, nextNodeId);
    housenumberGenerator = null;
    if (routable)
        createRouteRestrictionsFromPOI();
    poiRestrictions = null;
    if (routable) {
        for (RestrictionRelation rr : restrictions) {
            rr.addRestriction(collector, nodeIdMap);
        }
    }
    roads = null;
    if (routable) {
        for (Relation relation : throughRouteRelations) {
            Node node = null;
            Way w1 = null;
            Way w2 = null;
            for (Map.Entry<String, Element> member : relation.getElements()) {
                if (member.getValue() instanceof Node) {
                    if (node == null)
                        node = (Node) member.getValue();
                    else
                        log.warn("Through route relation", relation.toBrowseURL(), "has more than 1 node");
                } else if (member.getValue() instanceof Way) {
                    Way w = (Way) member.getValue();
                    if (w1 == null)
                        w1 = w;
                    else if (w2 == null)
                        w2 = w;
                    else
                        log.warn("Through route relation", relation.toBrowseURL(), "has more than 2 ways");
                }
            }
            CoordNode coordNode = null;
            if (node == null)
                log.warn("Through route relation", relation.toBrowseURL(), "is missing the junction node");
            else {
                Coord junctionPoint = node.getLocation();
                if (bbox != null && !bbox.contains(junctionPoint)) {
                    // junction is outside of the tile - ignore it
                    continue;
                }
                coordNode = nodeIdMap.get(junctionPoint);
                if (coordNode == null)
                    log.warn("Through route relation", relation.toBrowseURL(), "junction node at", junctionPoint.toOSMURL(), "is not a routing node");
            }
            if (w1 == null || w2 == null)
                log.warn("Through route relation", relation.toBrowseURL(), "should reference 2 ways that meet at the junction node");
            if (coordNode != null && w1 != null && w2 != null)
                collector.addThroughRoute(coordNode.getId(), w1.getId(), w2.getId());
        }
    }
    // return memory to GC
    nodeIdMap = null;
    throughRouteRelations.clear();
    restrictions.clear();
}
Also used : Node(uk.me.parabola.mkgmap.reader.osm.Node) CoordNode(uk.me.parabola.imgfmt.app.CoordNode) MapElement(uk.me.parabola.mkgmap.general.MapElement) Element(uk.me.parabola.mkgmap.reader.osm.Element) Way(uk.me.parabola.mkgmap.reader.osm.Way) Coord(uk.me.parabola.imgfmt.app.Coord) RestrictionRelation(uk.me.parabola.mkgmap.reader.osm.RestrictionRelation) Relation(uk.me.parabola.mkgmap.reader.osm.Relation) RestrictionRelation(uk.me.parabola.mkgmap.reader.osm.RestrictionRelation) CoordNode(uk.me.parabola.imgfmt.app.CoordNode) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) MultiHashMap(uk.me.parabola.util.MultiHashMap)

Example 5 with RestrictionRelation

use of uk.me.parabola.mkgmap.reader.osm.RestrictionRelation in project mkgmap by openstreetmap.

the class StyledConverter method removeRestrictionsWithWay.

/**
 * Remove all restriction relations that are invalid if the way will not appear
 * in the NOD file.
 * @param logLevel
 * @param way the way that was removed
 * @param reason explanation for the removal
 */
private void removeRestrictionsWithWay(Level logLevel, Way way, String reason) {
    List<RestrictionRelation> rrList = wayRelMap.get(way.getId());
    for (RestrictionRelation rr : rrList) {
        if (rr.isValidWithoutWay(way.getId()) == false) {
            if (log.isLoggable(logLevel)) {
                log.log(logLevel, "restriction", rr.toBrowseURL(), " is ignored because referenced way", way.toBrowseURL(), reason);
            }
            rr.setInvalid();
            restrictions.remove(rr);
        }
    }
}
Also used : RestrictionRelation(uk.me.parabola.mkgmap.reader.osm.RestrictionRelation)

Aggregations

RestrictionRelation (uk.me.parabola.mkgmap.reader.osm.RestrictionRelation)5 Coord (uk.me.parabola.imgfmt.app.Coord)4 Way (uk.me.parabola.mkgmap.reader.osm.Way)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 IdentityHashMap (java.util.IdentityHashMap)2 CoordNode (uk.me.parabola.imgfmt.app.CoordNode)2 Long2ObjectOpenHashMap (it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 Set (java.util.Set)1 MapElement (uk.me.parabola.mkgmap.general.MapElement)1 MapExitPoint (uk.me.parabola.mkgmap.general.MapExitPoint)1 MapLine (uk.me.parabola.mkgmap.general.MapLine)1 MapPoint (uk.me.parabola.mkgmap.general.MapPoint)1 MapRoad (uk.me.parabola.mkgmap.general.MapRoad)1 CoordPOI (uk.me.parabola.mkgmap.reader.osm.CoordPOI)1 Element (uk.me.parabola.mkgmap.reader.osm.Element)1 Node (uk.me.parabola.mkgmap.reader.osm.Node)1