Search in sources :

Example 1 with CoordPOI

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

the class StyledConverter method filterCoordPOI.

/**
 * Make sure that only CoordPOI which affect routing will be treated as
 * nodes in the following routines.
 */
private void filterCoordPOI() {
    if (!linkPOIsToWays)
        return;
    log.info("translating CoordPOI");
    for (ConvertedWay cw : roads) {
        if (!cw.isValid())
            continue;
        Way way = cw.getWay();
        if ("true".equals(way.getTag("mkgmap:way-has-pois"))) {
            String wayPOI = "";
            List<Coord> points = way.getPoints();
            int numPoints = points.size();
            for (int i = 0; i < numPoints; i++) {
                Coord p = points.get(i);
                if (p instanceof CoordPOI) {
                    CoordPOI cp = (CoordPOI) p;
                    Node node = cp.getNode();
                    boolean usedInThisWay = false;
                    byte wayAccess = cw.getAccess();
                    if (node.getTag("mkgmap:road-class") != null || node.getTag("mkgmap:road-speed") != null) {
                        if (wayAccess != AccessTagsAndBits.FOOT)
                            usedInThisWay = true;
                    }
                    byte nodeAccess = AccessTagsAndBits.evalAccessTags(node);
                    if (nodeAccess != (byte) 0xff) {
                        // barriers etc.
                        if ((wayAccess & nodeAccess) != wayAccess) {
                            // node is more restrictive
                            if (p.getHighwayCount() >= 2 || (i != 0 && i != numPoints - 1)) {
                                usedInThisWay = true;
                                cp.setConvertToViaInRouteRestriction(true);
                            } else {
                                log.info("POI node", node.getId(), "with access restriction is ignored, it is not connected to other routable ways");
                            }
                        } else
                            log.info("Access restriction in POI node", node.toBrowseURL(), "was ignored for way", way.toBrowseURL());
                    }
                    if (usedInThisWay) {
                        cp.setUsed(true);
                        wayPOI += "[" + node.getId() + "]";
                    }
                }
            }
            if (wayPOI.isEmpty()) {
                way.deleteTag("mkgmap:way-has-pois");
                log.info("ignoring CoordPOI(s) for way", way.toBrowseURL(), "because routing is not affected.");
            } else {
                way.addTag(WAY_POI_NODE_IDS, wayPOI);
            }
        }
    }
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) CoordPOI(uk.me.parabola.mkgmap.reader.osm.CoordPOI) Node(uk.me.parabola.mkgmap.reader.osm.Node) CoordNode(uk.me.parabola.imgfmt.app.CoordNode) Way(uk.me.parabola.mkgmap.reader.osm.Way) MapPoint(uk.me.parabola.mkgmap.general.MapPoint) MapExitPoint(uk.me.parabola.mkgmap.general.MapExitPoint)

Example 2 with CoordPOI

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

the class StyledConverter method addRoad.

/**
 * Add a way to the road network. May call itself recursively and
 * might truncate the way if splitting is required.
 * @param way the way
 * @param gt the type assigned by the style
 */
private void addRoad(ConvertedWay cw) {
    Way way = cw.getWay();
    if (way.getPoints().size() < 2) {
        log.warn("road has < 2 points", way.getId(), "(discarding)");
        return;
    }
    checkRoundabout(cw);
    // process any Coords that have a POI associated with them
    // metres
    final double stubSegmentLength = 25;
    String wayPOI = way.getTag(WAY_POI_NODE_IDS);
    if (wayPOI != null) {
        List<Coord> points = way.getPoints();
        // or a barrier
        for (int i = 0; i < points.size(); ++i) {
            Coord p = points.get(i);
            if (p instanceof CoordPOI && ((CoordPOI) p).isUsed()) {
                CoordPOI cp = (CoordPOI) p;
                Node node = cp.getNode();
                if (wayPOI.contains("[" + node.getId() + "]")) {
                    log.debug("POI", node.getId(), "changes way", way.getId());
                    // are converted to RouteRestrictions
                    if (p.getHighwayCount() < 2 && cp.getConvertToViaInRouteRestriction() && (i != 0 && i != points.size() - 1))
                        p.incHighwayCount();
                    String roadClass = node.getTag("mkgmap:road-class");
                    String roadSpeed = node.getTag("mkgmap:road-speed");
                    if (roadClass != null || roadSpeed != null) {
                        // find good split point after POI
                        Coord splitPoint;
                        double segmentLength = 0;
                        int splitPos = i + 1;
                        while (splitPos + 1 < points.size()) {
                            splitPoint = points.get(splitPos);
                            segmentLength += splitPoint.distance(points.get(splitPos - 1));
                            if (splitPoint.getHighwayCount() > 1 || segmentLength > stubSegmentLength - 5)
                                break;
                            splitPos++;
                        }
                        if (segmentLength > stubSegmentLength + 10) {
                            // insert a new point after the POI to
                            // make a short stub segment
                            splitPoint = points.get(splitPos);
                            Coord prev = points.get(splitPos - 1);
                            double dist = splitPoint.distance(prev);
                            double neededLength = stubSegmentLength - (segmentLength - dist);
                            splitPoint = prev.makeBetweenPoint(splitPoint, neededLength / dist);
                            double newDist = splitPoint.distance(prev);
                            segmentLength += newDist - dist;
                            splitPoint.incHighwayCount();
                            points.add(splitPos, splitPoint);
                        }
                        if ((splitPos + 1) < points.size() && way.isViaWay() == false && safeToSplitWay(points, splitPos, i, points.size() - 1)) {
                            Way tail = splitWayAt(way, splitPos);
                            // recursively process tail of way
                            addRoad(new ConvertedWay(cw, tail));
                        }
                        boolean classChanged = cw.recalcRoadClass(node);
                        if (classChanged && log.isInfoEnabled()) {
                            log.info("POI changing road class of", way.toBrowseURL(), "to", cw.getRoadClass(), "at", points.get(0).toOSMURL());
                        }
                        boolean speedChanged = cw.recalcRoadSpeed(node);
                        if (speedChanged && log.isInfoEnabled()) {
                            log.info("POI changing road speed of", way.toBrowseURL(), "to", cw.getRoadSpeed(), "at", points.get(0).toOSMURL());
                        }
                    }
                }
            }
            // the affected region
            if (i + 1 < points.size() && points.get(i + 1) instanceof CoordPOI) {
                CoordPOI cp = (CoordPOI) points.get(i + 1);
                Node node = cp.getNode();
                if (cp.isUsed() && wayPOI.contains("[" + node.getId() + "]")) {
                    if (node.getTag("mkgmap:road-class") != null || node.getTag("mkgmap:road-speed") != null) {
                        // find good split point before POI
                        double segmentLength = 0;
                        int splitPos = i;
                        Coord splitPoint;
                        while (splitPos >= 0) {
                            splitPoint = points.get(splitPos);
                            segmentLength += splitPoint.distance(points.get(splitPos + 1));
                            if (splitPoint.getHighwayCount() >= 2 || segmentLength > stubSegmentLength - 5)
                                break;
                            --splitPos;
                        }
                        if (segmentLength > stubSegmentLength + 10) {
                            // insert a new point before the POI to
                            // make a short stub segment
                            splitPoint = points.get(splitPos);
                            Coord prev = points.get(splitPos + 1);
                            double dist = splitPoint.distance(prev);
                            double neededLength = stubSegmentLength - (segmentLength - dist);
                            splitPoint = prev.makeBetweenPoint(splitPoint, neededLength / dist);
                            segmentLength += splitPoint.distance(prev) - dist;
                            splitPoint.incHighwayCount();
                            splitPos++;
                            points.add(splitPos, splitPoint);
                        }
                        if (splitPos > 0 && safeToSplitWay(points, splitPos, 0, points.size() - 1)) {
                            Way tail = splitWayAt(way, splitPos);
                            // recursively process tail of way
                            addRoad(new ConvertedWay(cw, tail));
                        }
                    }
                }
            }
        }
    }
    // if there is a bounding box, clip the way with it
    List<Way> clippedWays = null;
    if (bbox != null) {
        List<List<Coord>> lineSegs = LineClipper.clip(bbox, way.getPoints());
        if (lineSegs != null) {
            if (lineSegs.isEmpty()) {
                removeRestrictionsWithWay(Level.WARNING, way, "ends on tile boundary, restriction is ignored");
            }
            clippedWays = new ArrayList<>();
            for (List<Coord> lco : lineSegs) {
                Way nWay = new Way(way.getId());
                nWay.copyTags(way);
                for (Coord co : lco) {
                    nWay.addPoint(co);
                    if (co.getOnBoundary()) {
                        // this point lies on a boundary
                        // make sure it becomes a node
                        co.incHighwayCount();
                    }
                }
                clippedWays.add(nWay);
            }
        }
    }
    if (clippedWays != null) {
        for (Way clippedWay : clippedWays) {
            addRoadAfterSplittingLoops(new ConvertedWay(cw, clippedWay));
        }
    } else {
        // no bounding box or way was not clipped
        addRoadAfterSplittingLoops(cw);
    }
}
Also used : Node(uk.me.parabola.mkgmap.reader.osm.Node) CoordNode(uk.me.parabola.imgfmt.app.CoordNode) 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) CoordPOI(uk.me.parabola.mkgmap.reader.osm.CoordPOI) List(java.util.List) ArrayList(java.util.ArrayList)

Example 3 with CoordPOI

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

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

the class WrongAngleFixer method getReplacement.

/**
 * Common code to handle replacements of points in ways. Checks for special
 * cases regarding CoordPOI.
 *
 * @param p point to replace
 * @param way way that contains p
 * @param replacements the Map containing the replaced points
 * @return the replacement
 */
private static Coord getReplacement(Coord p, Way way, Map<Coord, Coord> replacements) {
    // it was previously merged into another point
    if (p.isReplaced()) {
        Coord replacement = null;
        Coord r = p;
        while ((r = replacements.get(r)) != null) {
            replacement = r;
        }
        if (replacement != null) {
            if (p instanceof CoordPOI) {
                CoordPOI cp = (CoordPOI) p;
                Node node = cp.getNode();
                if (cp.isUsed() && way != null && way.getId() != 0) {
                    String wayPOI = way.getTag(StyledConverter.WAY_POI_NODE_IDS);
                    if (wayPOI != null && wayPOI.contains("[" + node.getId() + "]")) {
                        if (replacement instanceof CoordPOI) {
                            Node rNode = ((CoordPOI) replacement).getNode();
                            if (rNode.getId() != node.getId()) {
                                if (wayPOI.contains("[" + rNode.getId() + "]")) {
                                    log.warn("CoordPOI", node.getId(), "replaced by CoordPOI", rNode.getId(), "in way", way.toBrowseURL());
                                } else
                                    log.warn("CoordPOI", node.getId(), "replaced by ignored CoordPOI", rNode.getId(), "in way", way.toBrowseURL());
                            }
                        } else
                            log.warn("CoordPOI", node.getId(), "replaced by simple coord in way", way.toBrowseURL());
                    }
                }
            }
            return replacement;
        }
        log.error("replacement not found for point " + p.toOSMURL());
    }
    return p;
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) CoordPOI(uk.me.parabola.mkgmap.reader.osm.CoordPOI) Node(uk.me.parabola.mkgmap.reader.osm.Node)

Example 5 with CoordPOI

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

the class WrongAngleFixer method replaceCoord.

private static void replaceCoord(Coord toRepl, Coord replacement, Map<Coord, Coord> replacements) {
    assert toRepl != replacement;
    if (toRepl.getOnBoundary()) {
        if (replacement.equals(toRepl) == false) {
            log.error("boundary node is replaced by node with non-equal coordinates at", toRepl.toOSMURL());
            assert false : "boundary node is replaced";
        }
        replacement.setOnBoundary(true);
    }
    toRepl.setReplaced(true);
    if (toRepl instanceof CoordPOI) {
        CoordPOI cp = (CoordPOI) toRepl;
        if (cp.isUsed()) {
            replacement = new CoordPOI(replacement);
            ((CoordPOI) replacement).setNode(cp.getNode());
            ((CoordPOI) replacement).setUsed(true);
            ((CoordPOI) replacement).setConvertToViaInRouteRestriction(cp.getConvertToViaInRouteRestriction());
            if (replacement.highPrecEquals(cp.getNode().getLocation()) == false) {
                log.error("CoordPOI node is replaced with non-equal coordinates at", toRepl.toOSMURL());
            }
        }
    }
    if (toRepl.isViaNodeOfRestriction())
        replacement.setViaNodeOfRestriction(true);
    replacements.put(toRepl, replacement);
    while (toRepl.getHighwayCount() > replacement.getHighwayCount()) replacement.incHighwayCount();
    if (toRepl.isEndOfWay()) {
        replacement.setEndOfWay(true);
    }
}
Also used : CoordPOI(uk.me.parabola.mkgmap.reader.osm.CoordPOI)

Aggregations

CoordPOI (uk.me.parabola.mkgmap.reader.osm.CoordPOI)6 Coord (uk.me.parabola.imgfmt.app.Coord)5 Way (uk.me.parabola.mkgmap.reader.osm.Way)4 CoordNode (uk.me.parabola.imgfmt.app.CoordNode)3 MapExitPoint (uk.me.parabola.mkgmap.general.MapExitPoint)3 MapPoint (uk.me.parabola.mkgmap.general.MapPoint)3 Node (uk.me.parabola.mkgmap.reader.osm.Node)3 ArrayList (java.util.ArrayList)2 File (java.io.File)1 IOException (java.io.IOException)1 HashMap (java.util.HashMap)1 IdentityHashMap (java.util.IdentityHashMap)1 List (java.util.List)1 Map (java.util.Map)1 Area (uk.me.parabola.imgfmt.app.Area)1 MapLine (uk.me.parabola.mkgmap.general.MapLine)1 MapRoad (uk.me.parabola.mkgmap.general.MapRoad)1 ConvertedWay (uk.me.parabola.mkgmap.osmstyle.ConvertedWay)1 RestrictionRelation (uk.me.parabola.mkgmap.reader.osm.RestrictionRelation)1 O5mMapWriter (uk.me.parabola.splitter.O5mMapWriter)1