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);
}
}
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;
}
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);
}
}
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;
}
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);
}
Aggregations