Search in sources :

Example 6 with MapShape

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

the class MapArea method splitIntoAreas.

/**
 * Spit the polygon into areas
 *
 * @param areas The available areas to choose from.
 * @param e The map element.
 * @param used flag vector to say area has been added to.
 */
private void splitIntoAreas(MapArea[] areas, MapShape e) {
    if (areas.length == 1) {
        // this happens quite a lot
        areas[0].addShape(e);
        return;
    }
    // quick check if bbox of shape lies fully inside one of the areas
    Area shapeBounds = e.getBounds();
    // this is worked out at standard precision, along with Area.contains() and so can get
    // tricky problems as it might not really be fully within the area.
    // so: pretend the shape is a touch bigger. Will get the optimisation most of the time
    // and in the boundary cases will fall into the precise code.
    int xtra = 2;
    // notices with an debug message and then output filters probably chuck away.
    if (Math.min(shapeBounds.getWidth(), shapeBounds.getHeight()) > 8)
        // pretend shape is smaller
        xtra = -2;
    shapeBounds = new Area(shapeBounds.getMinLat() - xtra, shapeBounds.getMinLong() - xtra, shapeBounds.getMaxLat() + xtra, shapeBounds.getMaxLong() + xtra);
    for (int areaIndex = 0; areaIndex < areas.length; ++areaIndex) {
        if (areas[areaIndex].getBounds().contains(shapeBounds)) {
            areas[areaIndex].addShape(e);
            return;
        }
    }
    if (areasHashMap == null)
        areasHashMap = new Long2ObjectOpenHashMap<>();
    if (areas.length == 2) {
        // just divide along the line between the two areas
        int dividingLine = 0;
        boolean isLongitude = false;
        boolean commonLine = true;
        if (areas[0].getBounds().getMaxLat() == areas[1].getBounds().getMinLat()) {
            dividingLine = areas[0].getBounds().getMaxLat();
            isLongitude = false;
        } else if (areas[0].getBounds().getMaxLong() == areas[1].getBounds().getMinLong()) {
            dividingLine = areas[0].getBounds().getMaxLong();
            isLongitude = true;
        } else {
            commonLine = false;
            log.error("Split into 2 expects shared edge between the areas");
        }
        if (commonLine) {
            List<List<Coord>> lessList = new ArrayList<>(), moreList = new ArrayList<>();
            ShapeSplitter.splitShape(e.getPoints(), dividingLine << Coord.DELTA_SHIFT, isLongitude, lessList, moreList, areasHashMap);
            for (List<Coord> subShape : lessList) {
                MapShape s = e.copy();
                s.setPoints(subShape);
                s.setClipped(true);
                areas[0].addShape(s);
            }
            for (List<Coord> subShape : moreList) {
                MapShape s = e.copy();
                s.setPoints(subShape);
                s.setClipped(true);
                areas[1].addShape(s);
            }
            return;
        }
    }
    for (int areaIndex = 0; areaIndex < areas.length; ++areaIndex) {
        List<List<Coord>> subShapePoints = ShapeSplitter.clipToBounds(e.getPoints(), areas[areaIndex].getBounds(), areasHashMap);
        for (List<Coord> subShape : subShapePoints) {
            MapShape s = e.copy();
            s.setPoints(subShape);
            s.setClipped(true);
            areas[areaIndex].addShape(s);
        }
    }
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) Area(uk.me.parabola.imgfmt.app.Area) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) Long2ObjectOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap) MapShape(uk.me.parabola.mkgmap.general.MapShape) MapPoint(uk.me.parabola.mkgmap.general.MapPoint)

Example 7 with MapShape

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

the class MapArea method addPolygons.

/**
 * Add the polygons
 * @param src The map data.
 * @param resolution The current resolution of the layer.
 */
private void addPolygons(MapDataSource src, final int resolution) {
    MapFilterChain chain = new MapFilterChain() {

        public void doFilter(MapElement element) {
            MapShape shape = (MapShape) element;
            addShape(shape);
        }
    };
    PolygonSubdivSizeSplitterFilter filter = new PolygonSubdivSizeSplitterFilter();
    FilterConfig config = new FilterConfig();
    config.setResolution(resolution);
    config.setBounds(bounds);
    filter.init(config);
    for (MapShape s : src.getShapes()) {
        if (s.getMaxResolution() < resolution)
            continue;
        if (splitPolygonsIntoArea || this.bounds.isEmpty() || this.bounds.contains(s.getBounds()))
            // if splitPolygonsIntoArea, don't want to have other splitting as well.
            // PolygonSubdivSizeSplitterFilter is a bit drastic - filters by both size and number of points
            // so use splitPolygonsIntoArea logic for this as well. This is fine as long as there
            // aren't bits of the shape outside the initial area.
            addShape(s);
        else
            filter.doFilter(s, chain);
    }
}
Also used : PolygonSubdivSizeSplitterFilter(uk.me.parabola.mkgmap.filters.PolygonSubdivSizeSplitterFilter) MapElement(uk.me.parabola.mkgmap.general.MapElement) FilterConfig(uk.me.parabola.mkgmap.filters.FilterConfig) MapFilterChain(uk.me.parabola.mkgmap.filters.MapFilterChain) MapShape(uk.me.parabola.mkgmap.general.MapShape)

Example 8 with MapShape

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

the class MapBuilder method processShapes.

/**
 * Step through the polygons, filter, simplify if necessary, and create a map
 * shape which is then added to the map.
 *
 * Note that the location and resolution of map elements is relative to the
 * subdivision that they occur in.
 *
 * @param map	The map to add polygons to.
 * @param div	The subdivision that the polygons belong to.
 * @param shapes The polygons to be added.
 */
private void processShapes(Map map, Subdivision div, List<MapShape> shapes) {
    // Signal that we are beginning to draw the shapes.
    div.startShapes();
    int res = div.getResolution();
    FilterConfig config = new FilterConfig();
    config.setResolution(res);
    config.setLevel(div.getZoom().getLevel());
    config.setRoutable(doRoads);
    if (mergeShapes) {
        ShapeMergeFilter shapeMergeFilter = new ShapeMergeFilter(res, orderByDecreasingArea);
        List<MapShape> mergedShapes = shapeMergeFilter.merge(shapes);
        shapes = mergedShapes;
    }
    if (orderByDecreasingArea && shapes.size() > 1) {
        // sort so that the shape with the largest area is processed first
        Collections.sort(shapes, new Comparator<MapShape>() {

            public int compare(MapShape s1, MapShape s2) {
                return Long.compare(Math.abs(s2.getFullArea()), Math.abs(s1.getFullArea()));
            }
        });
    }
    preserveHorizontalAndVerticalLines(res, shapes);
    LayerFilterChain filters = new LayerFilterChain(config);
    filters.addFilter(new PolygonSplitterFilter());
    if (enableLineCleanFilters && (res < 24)) {
        filters.addFilter(new RoundCoordsFilter());
        int sizefilterVal = getMinSizePolygonForResolution(res);
        if (sizefilterVal > 0)
            filters.addFilter(new SizeFilter(sizefilterVal));
        // Is there an similar algorithm for polygons?
        if (reducePointErrorPolygon > 0)
            filters.addFilter(new DouglasPeuckerFilter(reducePointErrorPolygon));
    }
    filters.addFilter(new RemoveObsoletePointsFilter());
    filters.addFilter(new RemoveEmpty());
    filters.addFilter(new LinePreparerFilter(div));
    filters.addFilter(new ShapeAddFilter(div, map));
    for (MapShape shape : shapes) {
        if (shape.getMinResolution() > res)
            continue;
        filters.startFilter(shape);
    }
}
Also used : PolygonSplitterFilter(uk.me.parabola.mkgmap.filters.PolygonSplitterFilter) DouglasPeuckerFilter(uk.me.parabola.mkgmap.filters.DouglasPeuckerFilter) SizeFilter(uk.me.parabola.mkgmap.filters.SizeFilter) LinePreparerFilter(uk.me.parabola.mkgmap.filters.LinePreparerFilter) MapPoint(uk.me.parabola.mkgmap.general.MapPoint) MapExitPoint(uk.me.parabola.mkgmap.general.MapExitPoint) Point(uk.me.parabola.imgfmt.app.trergn.Point) RoundCoordsFilter(uk.me.parabola.mkgmap.filters.RoundCoordsFilter) RemoveEmpty(uk.me.parabola.mkgmap.filters.RemoveEmpty) ShapeMergeFilter(uk.me.parabola.mkgmap.filters.ShapeMergeFilter) RemoveObsoletePointsFilter(uk.me.parabola.mkgmap.filters.RemoveObsoletePointsFilter) FilterConfig(uk.me.parabola.mkgmap.filters.FilterConfig) MapShape(uk.me.parabola.mkgmap.general.MapShape)

Example 9 with MapShape

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

the class MapBuilder method prepShapesForMerge.

/**
 * for the overview map:
 * Make sure that all {@link Coord} instances are
 * identical when they are equal.
 * @param shapes the list of shapes
 */
private static void prepShapesForMerge(List<MapShape> shapes) {
    Long2ObjectOpenHashMap<Coord> coordMap = new Long2ObjectOpenHashMap<>();
    for (MapShape s : shapes) {
        List<Coord> points = s.getPoints();
        int n = points.size();
        for (int i = 0; i < n; i++) {
            Coord co = points.get(i);
            Coord repl = coordMap.get(Utils.coord2Long(co));
            if (repl == null)
                coordMap.put(Utils.coord2Long(co), co);
            else
                points.set(i, repl);
        }
    }
    return;
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) Long2ObjectOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap) MapShape(uk.me.parabola.mkgmap.general.MapShape) MapPoint(uk.me.parabola.mkgmap.general.MapPoint) MapExitPoint(uk.me.parabola.mkgmap.general.MapExitPoint) Point(uk.me.parabola.imgfmt.app.trergn.Point)

Example 10 with MapShape

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

the class MapBuilder method makeSubdivision.

/**
 * Make an individual subdivision for the map.  To do this we need a link
 * to its parent and the zoom level that we are working at.
 *
 * @param map	The map to add this subdivision into.
 * @param parent The parent division.
 * @param ma	 The area of the map that we are fitting into this division.
 * @param z	  The zoom level.
 * @return The new subdivsion.
 */
private Subdivision makeSubdivision(Map map, Subdivision parent, MapArea ma, Zoom z) {
    List<MapPoint> points = ma.getPoints();
    List<MapLine> lines = ma.getLines();
    List<MapShape> shapes = ma.getShapes();
    Subdivision div = map.createSubdivision(parent, ma.getFullBounds(), z);
    if (ma.hasPoints())
        div.setHasPoints(true);
    if (ma.hasIndPoints())
        div.setHasIndPoints(true);
    if (ma.hasLines())
        div.setHasPolylines(true);
    if (ma.hasShapes())
        div.setHasPolygons(true);
    div.startDivision();
    processPoints(map, div, points);
    processLines(map, div, lines);
    processShapes(map, div, shapes);
    div.endDivision();
    return div;
}
Also used : MapLine(uk.me.parabola.mkgmap.general.MapLine) MapPoint(uk.me.parabola.mkgmap.general.MapPoint) Subdivision(uk.me.parabola.imgfmt.app.trergn.Subdivision) 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