Search in sources :

Example 1 with Coord

use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.

the class StyledConverter method createRouteRestrictionsFromPOI.

/**
 * If POI changes access restrictions (e.g. bollards), create corresponding
 * route restrictions so that only allowed vehicles/pedestrians are routed
 * through this point.
 */
private void createRouteRestrictionsFromPOI() {
    Iterator<Map.Entry<Node, List<Way>>> iter = poiRestrictions.entrySet().iterator();
    while (iter.hasNext()) {
        Map.Entry<Node, List<Way>> entry = iter.next();
        Node node = entry.getKey();
        Coord p = node.getLocation();
        // list of ways that are connected to the poi
        List<Way> wayList = entry.getValue();
        byte exceptMask = AccessTagsAndBits.evalAccessTags(node);
        Map<Integer, CoordNode> otherNodeIds = new LinkedHashMap<>();
        CoordNode viaNode = null;
        boolean viaIsUnique = true;
        for (Way way : wayList) {
            CoordNode lastNode = null;
            for (Coord co : way.getPoints()) {
                // not 100% fail safe: points may have been replaced before
                if (co instanceof CoordNode == false)
                    continue;
                CoordNode cn = (CoordNode) co;
                if (p.highPrecEquals(cn)) {
                    if (viaNode == null)
                        viaNode = cn;
                    else if (viaNode != cn) {
                        log.error("Found multiple points with equal coords as CoordPOI at " + p.toOSMURL());
                        // if we ever get here we can add code to identify the exact node
                        viaIsUnique = false;
                    }
                    if (lastNode != null)
                        otherNodeIds.put(lastNode.getId(), lastNode);
                } else {
                    if (p.highPrecEquals(lastNode))
                        otherNodeIds.put(cn.getId(), cn);
                }
                lastNode = cn;
            }
        }
        if (viaNode == null) {
            log.error("Did not find CoordPOI node at " + p.toOSMURL() + " in ways " + wayList);
            continue;
        }
        if (viaIsUnique == false) {
            log.error("Found multiple points with equal coords as CoordPOI at " + p.toOSMURL());
            continue;
        }
        if (otherNodeIds.size() < 2) {
            log.info("Access restriction in POI node " + node.toBrowseURL() + " was ignored, has no effect on any connected way");
            continue;
        }
        GeneralRouteRestriction rr = new GeneralRouteRestriction("no_through", exceptMask, "CoordPOI at " + p.toOSMURL());
        rr.setViaNodes(Arrays.asList(viaNode));
        int added = collector.addRestriction(rr);
        if (added == 0) {
            log.info("Access restriction in POI node " + node.toBrowseURL() + " was ignored, has no effect on any connected way");
        } else {
            log.info("Access restriction in POI node", node.toBrowseURL(), "was translated to", added, "route restriction(s)");
        }
        if (wayList.size() > 1 && added > 2) {
            log.warn("Access restriction in POI node", node.toBrowseURL(), "affects routing on multiple ways");
        }
    }
}
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) LinkedHashMap(java.util.LinkedHashMap) Coord(uk.me.parabola.imgfmt.app.Coord) Entry(java.util.Map.Entry) GeneralRouteRestriction(uk.me.parabola.imgfmt.app.net.GeneralRouteRestriction) List(java.util.List) ArrayList(java.util.ArrayList) 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 2 with Coord

use of uk.me.parabola.imgfmt.app.Coord 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 3 with Coord

use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.

the class StyledConverter method splitWayAt.

/**
 * split a Way at the specified point and return the new Way (the
 * original Way is truncated, both ways will contain the split point)
 * @param way the way to split
 * @param index the split position.
 * @return the trailing part of the way
 */
private static Way splitWayAt(Way way, int index) {
    if (way.isViaWay()) {
        log.warn("via way of restriction is split, restriction will be ignored", way);
    }
    Way trailingWay = new Way(way.getId());
    List<Coord> wayPoints = way.getPoints();
    int numPointsInWay = wayPoints.size();
    for (int i = index; i < numPointsInWay; ++i) trailingWay.addPoint(wayPoints.get(i));
    // ensure split point becomes a node
    wayPoints.get(index).incHighwayCount();
    // copy the way's name and tags to the new way
    trailingWay.copyTags(way);
    // it's probably more efficient to remove from the end first
    for (int i = numPointsInWay - 1; i > index; --i) wayPoints.remove(i);
    return trailingWay;
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) Way(uk.me.parabola.mkgmap.reader.osm.Way) MapPoint(uk.me.parabola.mkgmap.general.MapPoint) MapExitPoint(uk.me.parabola.mkgmap.general.MapExitPoint)

Example 4 with Coord

use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.

the class StyledConverter method setBoundingBox.

/**
 * Set the bounding box for this map.  This should be set before any other
 * elements are converted if you want to use it. All elements that are added
 * are clipped to this box, new points are added as needed at the boundary.
 *
 * If a node or a way falls completely outside the boundary then it would be
 * omitted.  This would not normally happen in the way this option is typically
 * used however.
 *
 * @param bbox The bounding area, must not be null.
 */
public void setBoundingBox(Area bbox) {
    this.clipper = new AreaClipper(bbox);
    this.bbox = bbox;
    // we calculate our own bounding box, now let the collector know about it.
    collector.addToBounds(new Coord(bbox.getMinLat(), bbox.getMinLong()));
    collector.addToBounds(new Coord(bbox.getMaxLat(), bbox.getMaxLong()));
}
Also used : AreaClipper(uk.me.parabola.mkgmap.general.AreaClipper) Coord(uk.me.parabola.imgfmt.app.Coord)

Example 5 with Coord

use of uk.me.parabola.imgfmt.app.Coord 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)

Aggregations

Coord (uk.me.parabola.imgfmt.app.Coord)178 ArrayList (java.util.ArrayList)71 Way (uk.me.parabola.mkgmap.reader.osm.Way)31 MapPoint (uk.me.parabola.mkgmap.general.MapPoint)27 List (java.util.List)23 MapLine (uk.me.parabola.mkgmap.general.MapLine)16 Area (uk.me.parabola.imgfmt.app.Area)15 MapShape (uk.me.parabola.mkgmap.general.MapShape)15 CoordNode (uk.me.parabola.imgfmt.app.CoordNode)13 MapExitPoint (uk.me.parabola.mkgmap.general.MapExitPoint)13 Node (uk.me.parabola.mkgmap.reader.osm.Node)13 HashMap (java.util.HashMap)12 IdentityHashMap (java.util.IdentityHashMap)11 Test (org.junit.Test)11 MapRoad (uk.me.parabola.mkgmap.general.MapRoad)9 Long2ObjectOpenHashMap (it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap)8 Area (java.awt.geom.Area)8 HashSet (java.util.HashSet)8 IntArrayList (it.unimi.dsi.fastutil.ints.IntArrayList)5 LinkedHashMap (java.util.LinkedHashMap)5