Search in sources :

Example 16 with MapShape

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

the class ShapeMergeFilter method mergeSimilar.

/**
 * Merge similar shapes.
 * @param similar list of similar shapes
 * @param mergedShapes list to which the shapes are added
 */
private void mergeSimilar(List<MapShape> similar, List<MapShape> mergedShapes) {
    if (similar.size() == 1) {
        mergedShapes.addAll(similar);
        return;
    }
    List<ShapeHelper> list = new ArrayList<>();
    MapShape s1 = similar.get(0);
    for (MapShape ms : similar) {
        ShapeHelper sh = new ShapeHelper(ms.getPoints());
        sh.id = ms.getOsmid();
        list.add(sh);
    }
    tryMerge(s1, list);
    for (ShapeHelper sh : list) {
        MapShape newShape = s1.copy();
        assert sh.getPoints().get(0) == sh.getPoints().get(sh.getPoints().size() - 1);
        if (sh.id == 0) {
            // this shape is the result of a merge
            List<Coord> optimizedPoints = WrongAngleFixer.fixAnglesInShape(sh.getPoints());
            if (optimizedPoints.isEmpty())
                continue;
            newShape.setPoints(optimizedPoints);
            newShape.setOsmid(FakeIdGenerator.makeFakeId());
        } else {
            newShape.setPoints(sh.getPoints());
            newShape.setOsmid(sh.id);
        }
        mergedShapes.add(newShape);
    }
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) ArrayList(java.util.ArrayList) IntArrayList(it.unimi.dsi.fastutil.ints.IntArrayList) MapShape(uk.me.parabola.mkgmap.general.MapShape)

Example 17 with MapShape

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

the class ShapeMergeFilter method merge.

/**
 * Merge shapes that are similar and have identical points.
 * @param shapes list of shapes
 * @return list of merged shapes (might be identical to original list)
 */
public List<MapShape> merge(List<MapShape> shapes) {
    if (shapes.size() <= 1)
        return shapes;
    List<MapShape> mergedShapes = new ArrayList<>();
    List<MapShape> usableShapes = new ArrayList<>();
    for (MapShape shape : shapes) {
        if (shape.getMinResolution() > resolution || shape.getMaxResolution() < resolution)
            continue;
        if (shape.getPoints().get(0) != shape.getPoints().get(shape.getPoints().size() - 1)) {
            // should not happen here
            log.error("shape is not closed with identical points", shape.getOsmid(), shape.getPoints().get(0).toOSMURL());
            mergedShapes.add(shape);
            continue;
        }
        usableShapes.add(shape);
    }
    if (usableShapes.size() < 2) {
        mergedShapes.addAll(usableShapes);
        return mergedShapes;
    }
    Comparator<MapShape> comparator = new MapShapeComparator();
    usableShapes.sort(comparator);
    int p1 = 0;
    MapShape s1 = usableShapes.get(0);
    for (int i = 1; i < usableShapes.size(); i++) {
        if (comparator.compare(s1, usableShapes.get(i)) == 0)
            continue;
        mergeSimilar(usableShapes.subList(p1, i), mergedShapes);
        s1 = usableShapes.get(i);
        p1 = i;
    }
    if (p1 < usableShapes.size())
        mergeSimilar(usableShapes.subList(p1, usableShapes.size()), mergedShapes);
    return mergedShapes;
}
Also used : ArrayList(java.util.ArrayList) IntArrayList(it.unimi.dsi.fastutil.ints.IntArrayList) MapShape(uk.me.parabola.mkgmap.general.MapShape)

Example 18 with MapShape

use of uk.me.parabola.mkgmap.general.MapShape 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 MapShape

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

the class ShapeMergeFilterTest method testVariants.

/**
 * Test all variants regarding clockwise/ccw direction and positions of the points
 * in the list and the order of shapes.
 * @param list1
 * @param list2
 */
void testVariants(String msg, List<Coord> list1, List<Coord> list2, int expectedNumShapes, int expectedNumPoints) {
    MapShape s1 = new MapShape(1);
    MapShape s2 = new MapShape(2);
    s1.setMinResolution(22);
    s2.setMinResolution(22);
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < list1.size(); j++) {
            List<Coord> points1 = new ArrayList<>(list1);
            if ((i & 1) != 0)
                Collections.reverse(points1);
            points1.remove(points1.size() - 1);
            Collections.rotate(points1, j);
            points1.add(points1.get(0));
            s1.setPoints(points1);
            for (int k = 0; k < list2.size(); k++) {
                List<Coord> points2 = new ArrayList<>(list2);
                if ((i & 2) != 0)
                    Collections.reverse(points2);
                points2.remove(points2.size() - 1);
                Collections.rotate(points2, k);
                points2.add(points2.get(0));
                s2.setPoints(points2);
                for (int l = 0; l < 2; l++) {
                    String testId = msg + " i=" + i + ",j=" + j + ",k=" + k + ",l=" + l;
                    if (l == 0)
                        testOneVariant(testId, s1, s2, expectedNumShapes, expectedNumPoints);
                    else
                        testOneVariant(testId, s2, s1, expectedNumShapes, expectedNumPoints);
                }
            }
        }
    }
    return;
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) ArrayList(java.util.ArrayList) MapShape(uk.me.parabola.mkgmap.general.MapShape)

Example 20 with MapShape

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

the class StyledConverter method addShape.

private void addShape(Way way, GType gt) {
    // 
    if (!way.hasIdenticalEndPoints() && way.hasEqualEndPoints())
        log.error("shape is not closed with identical points " + way.getId());
    if (!way.hasIdenticalEndPoints())
        return;
    // TODO: split self intersecting polygons?
    final MapShape shape = new MapShape(way.getId());
    elementSetup(shape, gt, way);
    shape.setPoints(way.getPoints());
    long areaVal = 0;
    String tagStringVal = way.getTag(drawLevelTagKey);
    if (tagStringVal != null) {
        try {
            areaVal = Integer.parseInt(tagStringVal);
            if (areaVal < 1 || areaVal > 100) {
                log.error("mkgmap:drawLevel must be in range 1..100, not", areaVal);
                areaVal = 0;
            } else if (areaVal <= 50)
                // 1 => MAX_VALUE-1, 50 => MAX_VALUE-50
                areaVal = Long.MAX_VALUE - areaVal;
            else
                // 51 => 50, 100 => 1
                areaVal = 101 - areaVal;
        } catch (NumberFormatException e) {
            log.error("mkgmap:drawLevel invalid integer:", tagStringVal);
        }
    }
    if (areaVal == 0)
        areaVal = way.getFullArea();
    shape.setFullArea(areaVal);
    clipper.clipShape(shape, collector);
}
Also used : MapShape(uk.me.parabola.mkgmap.general.MapShape)

Aggregations

MapShape (uk.me.parabola.mkgmap.general.MapShape)27 Coord (uk.me.parabola.imgfmt.app.Coord)15 MapPoint (uk.me.parabola.mkgmap.general.MapPoint)14 ArrayList (java.util.ArrayList)11 MapLine (uk.me.parabola.mkgmap.general.MapLine)10 Point (uk.me.parabola.imgfmt.app.trergn.Point)5 Area (uk.me.parabola.imgfmt.app.Area)4 MapRoad (uk.me.parabola.mkgmap.general.MapRoad)4 MapExitPoint (uk.me.parabola.mkgmap.general.MapExitPoint)3 IntArrayList (it.unimi.dsi.fastutil.ints.IntArrayList)2 Long2ObjectOpenHashMap (it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap)2 List (java.util.List)2 FilterConfig (uk.me.parabola.mkgmap.filters.FilterConfig)2 IdentityHashMap (java.util.IdentityHashMap)1 GeneralRouteRestriction (uk.me.parabola.imgfmt.app.net.GeneralRouteRestriction)1 Polygon (uk.me.parabola.imgfmt.app.trergn.Polygon)1 Subdivision (uk.me.parabola.imgfmt.app.trergn.Subdivision)1 Zoom (uk.me.parabola.imgfmt.app.trergn.Zoom)1 DouglasPeuckerFilter (uk.me.parabola.mkgmap.filters.DouglasPeuckerFilter)1 LinePreparerFilter (uk.me.parabola.mkgmap.filters.LinePreparerFilter)1