use of uk.me.parabola.imgfmt.app.Coord 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;
}
use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class MapBuilder method preserveHorizontalAndVerticalLines.
/**
* Preserve shape points which a) lie on the shape boundary or
* b) which appear multiple times in the shape (excluding the start
* point which should always be identical to the end point).
* The preserved points are kept treated specially in the
* Line-Simplification-Filters, this should avoid artifacts like
* white triangles in the sea for lower resolutions.
* @param res the current resolution
* @param shapes list of shapes
*/
private static void preserveHorizontalAndVerticalLines(int res, List<MapShape> shapes) {
if (res == 24)
return;
for (MapShape shape : shapes) {
if (shape.getMinResolution() > res)
continue;
int minLat = shape.getBounds().getMinLat();
int maxLat = shape.getBounds().getMaxLat();
int minLon = shape.getBounds().getMinLong();
int maxLon = shape.getBounds().getMaxLong();
List<Coord> points = shape.getPoints();
int n = shape.getPoints().size();
IdentityHashMap<Coord, Coord> coords = new IdentityHashMap<>(n);
Coord first = points.get(0);
Coord prev = first;
Coord last = first;
for (int i = 1; i < points.size(); ++i) {
last = points.get(i);
// to connect holes
if (coords.get(last) == null) {
coords.put(last, last);
} else {
if (!last.preserved()) {
last.preserved(true);
}
}
// on the bbox of the shape.
if (last.getLatitude() == prev.getLatitude() && (last.getLatitude() == minLat || last.getLatitude() == maxLat) || last.getLongitude() == prev.getLongitude() && (last.getLongitude() == minLon || last.getLongitude() == maxLon)) {
last.preserved(true);
prev.preserved(true);
}
prev = last;
}
}
}
use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class OverviewBuilder method readShapes.
/**
* Read the polygons from the .img file and add them to the overview map.
* We read from the least detailed level (apart from the empty one).
*
* @param mapReader Map reader on the detailed .img file.
*/
private void readShapes(MapReader mapReader) {
Zoom[] levels = mapReader.getLevels();
for (int l = 1; l < levels.length; l++) {
int min = levels[l].getLevel();
int res = levels[l].getResolution();
List<Polygon> list = mapReader.shapesForLevel(min, MapReader.WITH_EXT_TYPE_DATA);
for (Polygon shape : list) {
if (log.isDebugEnabled())
log.debug("got polygon", shape);
if (shape.getType() == 0x4b) {
hasBackground = true;
}
MapShape ms = new MapShape();
List<Coord> points = shape.getPoints();
if (log.isDebugEnabled())
log.debug("polygon point list", points);
if (points.size() < 3)
continue;
ms.setType(shape.getType());
if (shape.getLabel() != null)
ms.setName(shape.getLabel().getText());
ms.setMaxResolution(res);
ms.setMinResolution(res);
ms.setPoints(points);
overviewSource.addShape(ms);
}
}
}
use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class PredictFilterPoints method predictedMaxNumPoints.
public static int predictedMaxNumPoints(List<Coord> points, int resolution, boolean checkPreserved) {
// see RemoveObsoletePointsFilter, RoundCoordsFilter, ... for comments on preserved and resolution
// %%% checkPreserved = config.getLevel() == 0 && config.isRoutable() && line.isRoad()){
// final int shift = 30 - resolution; // NB getting highPrec
// final int half = 1 << (shift - 1); // 0.5 shifted
// final int mask = ~((1 << shift) - 1); // to remove fraction bits
// best use same info as filters
final int shift = 24 - resolution;
int half;
int mask;
if (shift == 0) {
half = 0;
mask = ~0;
} else {
// 0.5 shifted
half = 1 << (shift - 1);
// to remove fraction bits
mask = ~((1 << shift) - 1);
}
int numPoints = 0;
int lastLat = 0, lastLon = 0;
for (Coord p : points) {
// final int lat = (p.getHighPrecLat() + half) & mask;
// final int lon = (p.getHighPrecLon() + half) & mask;
final int lat = (p.getLatitude() + half) & mask;
final int lon = (p.getLongitude() + half) & mask;
if (numPoints == 0)
// always have one/first point
numPoints = 1;
else {
if (lat != lastLat || lon != lastLon || (checkPreserved && (p instanceof CoordNode || p.preserved())))
++numPoints;
}
lastLat = lat;
lastLon = lon;
}
// true shapes will have >3 points, lines >1
return numPoints;
}
use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class RemoveObsoletePointsFilter method doFilter.
/**
* @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;
List<Coord> points = line.getPoints();
int numPoints = points.size();
if (numPoints <= 1) {
return;
}
int requiredPoints = (line instanceof MapShape) ? 4 : 2;
List<Coord> newPoints = new ArrayList<Coord>(numPoints);
while (true) {
boolean removedSpike = false;
numPoints = points.size();
Coord lastP = points.get(0);
newPoints.add(lastP);
for (int i = 1; i < numPoints; i++) {
Coord newP = points.get(i);
int last = newPoints.size() - 1;
lastP = newPoints.get(last);
if (lastP.equals(newP)) {
// coordinates to the last point or is preserved
if (checkPreserved && line.isRoad()) {
if (newP.preserved() == false)
continue;
else if (lastP.preserved() == false) {
// replace last
newPoints.set(last, newP);
}
} else
continue;
}
if (newPoints.size() > 1) {
switch(Utils.isStraight(newPoints.get(last - 1), lastP, newP)) {
case Utils.STRICTLY_STRAIGHT:
if (checkPreserved && lastP.preserved() && line.isRoad()) {
// keep it
} else {
log.debug("found three consecutive points on strictly straight line");
newPoints.set(last, newP);
continue;
}
break;
case Utils.STRAIGHT_SPIKE:
if (line instanceof MapShape) {
log.debug("removing spike");
newPoints.remove(last);
removedSpike = true;
if (newPoints.get(last - 1).equals(newP))
continue;
}
break;
default:
break;
}
}
newPoints.add(newP);
}
if (!removedSpike || newPoints.size() < requiredPoints)
break;
points = newPoints;
newPoints = new ArrayList<Coord>(points.size());
}
if (line instanceof MapShape) {
// in a shape are identical.
while (newPoints.size() > 3) {
int nPoints = newPoints.size();
switch(Utils.isStraight(newPoints.get(newPoints.size() - 2), newPoints.get(0), newPoints.get(1))) {
case Utils.STRAIGHT_SPIKE:
newPoints.remove(0);
newPoints.set(newPoints.size() - 1, newPoints.get(0));
if (newPoints.get(newPoints.size() - 2).equals(newPoints.get(newPoints.size() - 1)))
newPoints.remove(newPoints.size() - 1);
break;
case Utils.STRICTLY_STRAIGHT:
newPoints.remove(newPoints.size() - 1);
newPoints.set(0, newPoints.get(newPoints.size() - 1));
break;
}
if (nPoints == newPoints.size())
break;
}
}
if (newPoints.size() != line.getPoints().size()) {
if (line instanceof MapShape && newPoints.size() <= 3 || newPoints.size() <= 1)
return;
MapLine newLine = line.copy();
newLine.setPoints(newPoints);
next.doFilter(newLine);
} else {
// no need to create new object
next.doFilter(line);
}
}
Aggregations