Search in sources :

Example 16 with MapLine

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

the class DouglasPeuckerFilter method doFilter.

/**
 * This applies to both lines and polygons.  We are going to smooth out
 * the points in the line so that you do not get jaggies.
 *
 * @param element A map element that will be a line or a polygon.
 * @param next This is used to pass the possibly transformed element onward.
 */
public void doFilter(MapElement element, MapFilterChain next) {
    // First off we don't touch things if at the highest level of detail
    if (resolution == 24) {
        // XXX 24 is not necessarily the highest level.
        next.doFilter(element);
        return;
    }
    MapLine line = (MapLine) element;
    List<Coord> points = line.getPoints();
    // Create a new list to rewrite the points into. Don't alter the original one
    List<Coord> coords = new ArrayList<>(points.size());
    coords.addAll(points);
    // Loop runs downwards, as the list length gets modified while running
    int endIndex = coords.size() - 1;
    for (int i = endIndex - 1; i > 0; i--) {
        Coord p = coords.get(i);
        // TODO: Should consider only nodes connected to roads visible at current resolution.
        if (p.preserved()) {
            // point is "preserved", don't remove it
            douglasPeucker(coords, i, endIndex, maxErrorDistance);
            endIndex = i;
        }
    }
    // Simplify the rest
    douglasPeucker(coords, 0, endIndex, maxErrorDistance);
    if (coords.size() == points.size())
        // nothing changed, no need to copy
        next.doFilter(line);
    else {
        MapLine newline = line.copy();
        newline.setPoints(coords);
        next.doFilter(newline);
    }
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) MapLine(uk.me.parabola.mkgmap.general.MapLine) ArrayList(java.util.ArrayList)

Example 17 with MapLine

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

the class LineMergeFilter method merge.

// TODO: This routine has a side effect: it modifies some of the MapLine instances
// instead of creating copies. It seems that this has no bad effect, but it is not clean
public List<MapLine> merge(List<MapLine> lines, int res) {
    // better use LinkedList??
    linesMerged = new ArrayList<MapLine>(lines.size());
    for (MapLine line : lines) {
        if (line.getMinResolution() > res || line.getMaxResolution() < res)
            continue;
        if (line.isRoad()) {
            linesMerged.add(line);
            continue;
        }
        boolean isMerged = false;
        List<Coord> points = line.getPoints();
        Coord start = points.get(0);
        Coord end = points.get(points.size() - 1);
        // (can the end of current line connected to an existing line?)
        for (MapLine line2 : startPoints.get(end)) {
            if (line.isSimilar(line2)) {
                addPointsAtStart(line2, points);
                // both lines has to be merged and one of them dropped)
                for (MapLine line1 : endPoints.get(start)) {
                    if (line2.isSimilar(line1) && // don't make a closed loop a double loop
                    !line2.equals(line1)) {
                        mergeLines(line1, line2);
                        break;
                    }
                }
                isMerged = true;
                break;
            }
        }
        if (isMerged)
            continue;
        // (can the start of current line connected to an existing line?)
        for (MapLine line2 : endPoints.get(start)) {
            if (line.isSimilar(line2)) {
                addPointsAtEnd(line2, points);
                isMerged = true;
                break;
            }
        }
        if (isMerged)
            continue;
        // No matching, create a copy of line
        MapLine l = line.copy();
        // use better LinkedList for performance?
        List<Coord> p = new ArrayList<Coord>(line.getPoints());
        l.setPoints(p);
        addLine(l);
    }
    return linesMerged;
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) MapLine(uk.me.parabola.mkgmap.general.MapLine) ArrayList(java.util.ArrayList)

Example 18 with MapLine

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

the class LineSizeSplitterFilter method doFilter.

/**
 * Keep track of the max dimensions of a line and split when they get too
 * big.
 *
 * @param element A map element.
 * @param next This is used to pass the possibly transformed element onward.
 */
public void doFilter(MapElement element, MapFilterChain next) {
    // We do not deal with shapes.
    assert !(element instanceof MapShape) && element instanceof MapLine;
    MapLine line = (MapLine) element;
    if (line.getBounds().getMaxDimension() < maxSize) {
        next.doFilter(element);
        return;
    }
    if (line instanceof MapRoad) {
        MapRoad road = ((MapRoad) line);
        log.error("Way " + road.getRoadDef() + " has a max dimension of " + line.getBounds().getMaxDimension() + " and is about to be split (routing will be broken)");
    }
    // ensure that all single lines do not exceed the maximum size
    // use a slightly decreased max size (-10) to get better results
    // in the subdivision creation
    List<Coord> points = splitLinesToMaxSize(line.getPoints(), maxSize - 10);
    log.debug("line bbox too big, splitting");
    MapLine l = line.copy();
    List<Coord> coords = new ArrayList<Coord>();
    boolean first = true;
    /**
     * Class to keep track of the dimensions.
     */
    class Dim {

        private int minLat;

        private int minLong;

        private int maxLat;

        private int maxLong;

        Dim() {
            reset();
        }

        private void reset() {
            minLat = Integer.MAX_VALUE;
            minLong = Integer.MAX_VALUE;
            maxLat = Integer.MIN_VALUE;
            maxLong = Integer.MIN_VALUE;
        }

        private void addToBounds(Coord co) {
            int lat = co.getLatitude();
            if (lat < minLat)
                minLat = lat;
            if (lat > maxLat)
                maxLat = lat;
            int lon = co.getLongitude();
            if (lon < minLong)
                minLong = lon;
            if (lon > maxLong)
                maxLong = lon;
        }

        private int getMaxDim() {
            int dx = maxLong - minLong;
            int dy = maxLat - minLat;
            return Math.max(dx, dy);
        }
    }
    Dim dim = new Dim();
    Coord prev = null;
    // Add points while not too big and then start again with a fresh line.
    for (Coord co : points) {
        dim.addToBounds(co);
        if (dim.getMaxDim() > maxSize) {
            if (first)
                log.debug("bigness saving first part");
            else
                log.debug("bigness saving next part");
            l.setPoints(coords);
            next.doFilter(l);
            l = line.copy();
            first = false;
            dim.reset();
            coords = new ArrayList<Coord>();
            coords.add(prev);
            dim.addToBounds(prev);
            dim.addToBounds(co);
        }
        coords.add(co);
        prev = co;
    }
    assert coords.size() > 1;
    if (coords.size() > 1) {
        log.debug("bigness saving a final part");
        l.setPoints(coords);
        next.doFilter(l);
    }
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) MapLine(uk.me.parabola.mkgmap.general.MapLine) ArrayList(java.util.ArrayList) MapRoad(uk.me.parabola.mkgmap.general.MapRoad) MapShape(uk.me.parabola.mkgmap.general.MapShape)

Example 19 with MapLine

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

the class SizeFilter method doFilter.

/**
 * This applies to both lines and polygons.
 * Elements too small for current resolution will be dropped.
 *
 * @param element A map element that will be a line or a polygon.
 * @param next This is used to pass the possibly transformed element onward.
 */
public void doFilter(MapElement element, MapFilterChain next) {
    MapLine line = (MapLine) element;
    if ((line.isSkipSizeFilter() || (checkRouting && line.isRoad())) == false) {
        if (line.getBounds().getMaxDimension() < minSize) {
            return;
        }
    }
    next.doFilter(line);
}
Also used : MapLine(uk.me.parabola.mkgmap.general.MapLine)

Example 20 with MapLine

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

the class SmoothingFilter method doFilter.

/**
 * This applies to both lines and polygons.  We are going to smooth out
 * the points in the line so that you do not get jaggies.  We are assuming
 * that there is not an excess of points at the highest resolution.
 *
 * <ol>
 * <li>If there is just one point, the drop it.
 * <li>Ff the element is too small altogether, then drop it.
 * <li>If there are just two points the pass it on unchanged.  This is
 * probably a pretty common case.
 * <li>The first point goes in unchanged.
 * <li>Average points in groups so that they exceed the step size
 * at the shifted resolution.
 * </ol>
 *
 * @param element A map element that will be a line or a polygon.
 * @param next This is used to pass the possibly transformed element onward.
 */
public void doFilter(MapElement element, MapFilterChain next) {
    MapLine line = (MapLine) element;
    // First off we don't touch things if at the highest level of detail
    if (shift == 0) {
        next.doFilter(element);
        return;
    }
    // If the line is not very long then just let it through.  This is done
    // mainly for the background polygons.
    List<Coord> points = line.getPoints();
    int n = points.size();
    if (n <= 5) {
        next.doFilter(element);
        return;
    }
    // Create a new list to rewrite the points into.
    List<Coord> coords = new ArrayList<Coord>(n);
    // Get the step size, we want to place a point every time the
    // average exceeds this size.
    int stepsize = MIN_SPACING << shift;
    // Always add the first point
    Coord last = points.get(0);
    coords.add(last);
    // Average the rest
    Average av = new Average(last, stepsize);
    for (int i = 1; i < n; i++) {
        Coord co = points.get(i);
        av.add(co);
        if (av.isMoreThanStep()) {
            Coord nco = av.getAverageCoord();
            coords.add(nco);
            if (av.pointCounter() > 1)
                i--;
            last = nco;
            av.reset(last);
        }
    }
    Coord end = points.get(n - 1);
    if (!last.equals(end))
        coords.add(end);
    MapLine newline = line.copy();
    newline.setPoints(coords);
    next.doFilter(newline);
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) MapLine(uk.me.parabola.mkgmap.general.MapLine) ArrayList(java.util.ArrayList)

Aggregations

MapLine (uk.me.parabola.mkgmap.general.MapLine)29 Coord (uk.me.parabola.imgfmt.app.Coord)16 MapPoint (uk.me.parabola.mkgmap.general.MapPoint)15 ArrayList (java.util.ArrayList)12 MapShape (uk.me.parabola.mkgmap.general.MapShape)10 MapRoad (uk.me.parabola.mkgmap.general.MapRoad)6 MapExitPoint (uk.me.parabola.mkgmap.general.MapExitPoint)4 Point (uk.me.parabola.imgfmt.app.trergn.Point)3 CoordNode (uk.me.parabola.imgfmt.app.CoordNode)2 FilterConfig (uk.me.parabola.mkgmap.filters.FilterConfig)2 Area (uk.me.parabola.imgfmt.app.Area)1 City (uk.me.parabola.imgfmt.app.lbl.City)1 LBLFile (uk.me.parabola.imgfmt.app.lbl.LBLFile)1 Zip (uk.me.parabola.imgfmt.app.lbl.Zip)1 GeneralRouteRestriction (uk.me.parabola.imgfmt.app.net.GeneralRouteRestriction)1 Numbers (uk.me.parabola.imgfmt.app.net.Numbers)1 ExtTypeAttributes (uk.me.parabola.imgfmt.app.trergn.ExtTypeAttributes)1 Polyline (uk.me.parabola.imgfmt.app.trergn.Polyline)1 Subdivision (uk.me.parabola.imgfmt.app.trergn.Subdivision)1 Zoom (uk.me.parabola.imgfmt.app.trergn.Zoom)1