use of uk.me.parabola.mkgmap.general.MapLine in project mkgmap by openstreetmap.
the class PolishMapDataSource method endSection.
/**
* At the end of a section, we add what ever element that we have been
* building to the map.
*/
private void endSection() {
switch(section) {
case S_IMG_ID:
break;
case S_POINT:
if (extraAttributes != null && point.hasExtendedType())
point.setExtTypeAttributes(makeExtTypeAttributes());
mapper.addToBounds(point.getLocation());
mapper.addPoint(point);
break;
case S_POLYLINE:
if (points != null) {
if (roadHelper.isRoad()) {
polyline.setPoints(points);
mapper.addRoad(roadHelper.makeRoad(polyline));
} else {
if (extraAttributes != null && polyline.hasExtendedType())
polyline.setExtTypeAttributes(makeExtTypeAttributes());
final int maxPointsInLine = LineSplitterFilter.MAX_POINTS_IN_LINE;
if (points.size() > maxPointsInLine) {
List<Coord> segPoints = new ArrayList<>(maxPointsInLine);
for (Coord p : points) {
segPoints.add(p);
if (segPoints.size() == maxPointsInLine) {
MapLine seg = polyline.copy();
seg.setPoints(segPoints);
mapper.addLine(seg);
segPoints = new ArrayList<>(maxPointsInLine);
segPoints.add(p);
}
}
if (!segPoints.isEmpty()) {
polyline.setPoints(segPoints);
mapper.addLine(polyline);
}
} else {
polyline.setPoints(points);
mapper.addLine(polyline);
}
}
}
break;
case S_POLYGON:
if (points != null) {
if (points.get(0) != points.get(points.size() - 1)) {
// not closed, close it
points.add(points.get(0));
}
shape.setPoints(points);
if (extraAttributes != null && shape.hasExtendedType())
shape.setExtTypeAttributes(makeExtTypeAttributes());
mapper.addShape(shape);
}
break;
case S_RESTRICTION:
restrictionHelper.addRestriction(restriction);
break;
case 0:
// ignored section
break;
default:
log.warn("unexpected default in switch", section);
break;
}
// Clear the section state.
section = 0;
endLevel = 0;
points = null;
}
use of uk.me.parabola.mkgmap.general.MapLine in project mkgmap by openstreetmap.
the class AllElements method drawLines.
private void drawLines(MapCollector mapper, double slat, double slon, boolean hasBackground) {
double lat = slat + 0.004;
double lon = slon + 0.002;
int type = 0;
for (int x = 0; x < MAX_LINE_TYPE_X; x++) {
for (int y = 0; y < MAX_LINE_TYPE_Y; y++) {
MapLine line = new MapLine();
line.setMinResolution(10);
if (!hasBackground)
line.setName(GType.formatType(type));
double baseLat = lat + y * ELEMENT_SPACING;
double baseLong = lon + x * ELEMENT_SPACING;
List<Coord> coords = new ArrayList<Coord>();
Coord co = new Coord(baseLat, baseLong);
coords.add(co);
mapper.addToBounds(co);
if (configProps.containsKey("verbose"))
System.out.println("Generated line " + GType.formatType(type) + " at " + co.toDegreeString());
co = new Coord(baseLat + ELEMENT_SIZE, baseLong + ELEMENT_SIZE);
coords.add(co);
mapper.addToBounds(co);
co = new Coord(baseLat + ELEMENT_SIZE, baseLong + ELEMENT_SIZE + ELEMENT_SIZE / 2);
coords.add(co);
mapper.addToBounds(co);
line.setType(type);
line.setPoints(coords);
mapper.addLine(line);
type++;
}
}
}
use of uk.me.parabola.mkgmap.general.MapLine in project mkgmap by openstreetmap.
the class StyledConverterTest method makeConverter.
private StyledConverter makeConverter(String name) throws FileNotFoundException {
Style style = new StyleImpl(LOC, name);
MapCollector coll = new MapCollector() {
public void addToBounds(Coord p) {
}
// could save points in the same way as lines to test them
public void addPoint(MapPoint point) {
}
public void addLine(MapLine line) {
// Save line so that it can be examined in the tests.
assertNotNull("points are not null", line.getPoints());
lines.add(line);
}
public void addShape(MapShape shape) {
}
public void addRoad(MapRoad road) {
lines.add(road);
}
public int addRestriction(GeneralRouteRestriction grr) {
return 0;
}
public void addThroughRoute(int junctionNodeId, long roadIdA, long roadIdB) {
}
};
return new StyledConverter(style, coll, new EnhancedProperties());
}
use of uk.me.parabola.mkgmap.general.MapLine in project mkgmap by openstreetmap.
the class MapArea method canAddSize.
/**
* Will element fit nicely?
* Limit to WANTED_MAX_AREA_SIZE which is smaller than MAX_XT_xxx_SIZE
* so don't need to check down to the last detail
*
* @param el The element. Assume want to display it at this resolution
* @param kind What kind of element this is: KIND_POINT/LINE/SHAPE.
*/
private boolean canAddSize(MapElement el, int kind) {
int numPoints;
int numElements;
int sumSize = 0;
for (int s : sizes) sumSize += s;
switch(kind) {
case POINT_KIND:
if (getNumPoints() >= MapSplitter.MAX_NUM_POINTS)
return false;
// Points are predictably less than 10 bytes.
if ((sumSize + 9) > MapSplitter.WANTED_MAX_AREA_SIZE)
return false;
break;
case LINE_KIND:
// Estimate the size taken by lines and shapes as a constant plus
// a factor based on the number of points.
numPoints = PredictFilterPoints.predictedMaxNumPoints(((MapLine) el).getPoints(), areaResolution, // assume MapBuilder.doRoads is true. subDiv.getZoom().getLevel() == 0 is maximum resolution
((MapLine) el).isRoad() && areaResolution == MAX_RESOLUTION);
if (numPoints <= 1 && !((MapLine) el).isRoad())
break;
numElements = 1 + ((numPoints - 1) / LineSplitterFilter.MAX_POINTS_IN_LINE);
if (getNumLines() + numElements > MapSplitter.MAX_NUM_LINES)
return false;
// very pessimistic, typically less than 2 bytes are needed for one point
if ((sumSize + numElements * 11 + numPoints * 4) > MapSplitter.WANTED_MAX_AREA_SIZE)
return false;
break;
case SHAPE_KIND:
// Estimate the size taken by lines and shapes as a constant plus
// a factor based on the number of points.
numPoints = PredictFilterPoints.predictedMaxNumPoints(((MapShape) el).getPoints(), areaResolution, false);
if (numPoints <= 3)
break;
numElements = 1 + ((numPoints - 1) / PolygonSplitterFilter.MAX_POINT_IN_ELEMENT);
// very pessimistic, typically less than 2 bytes are needed for one point
if ((sumSize + numElements * 11 + numPoints * 4) > MapSplitter.WANTED_MAX_AREA_SIZE)
return false;
break;
}
return true;
}
use of uk.me.parabola.mkgmap.general.MapLine in project mkgmap by openstreetmap.
the class MapArea method split.
/**
* Split this area into several pieces. All the map elements are reallocated
* to the appropriate subarea. Usually this instance would now be thrown
* away and the new sub areas used instead.
* <p>
* This code is dealing with a lot of factors that govern the splitting, eg:
* splitPolygonsIntoArea,
* tooSmallToDivide,
* item.minResolution vs. areaResolution,
* number/size of items and the limits of a subDivision,
* items that exceed maximum subDivision on their own,
* items that extend up to 50% outside the current area,
* items bigger than this.
*
* @param nx The number of pieces in the x (longitude) direction.
* @param ny The number of pieces in the y direction.
* @param bounds the bounding box that is used to create the areas.
* @param tooSmallToDivide the area is small and data overflows; split into overflow areas
*
* @return An array of the new MapArea's or null if can't split.
*/
public MapArea[] split(int nx, int ny, Area bounds, boolean tooSmallToDivide) {
int resolutionShift = MAX_RESOLUTION - areaResolution;
Area[] areas = bounds.split(nx, ny, resolutionShift);
if (areas == null) {
// Failed to split!
if (log.isDebugEnabled()) {
// see what is here
for (MapLine e : this.lines) if (e.getMinResolution() <= areaResolution)
log.debug("line. locn=", e.getPoints().get(0).toOSMURL(), " type=", uk.me.parabola.mkgmap.reader.osm.GType.formatType(e.getType()), " name=", e.getName(), " min=", e.getMinResolution(), " max=", e.getMaxResolution());
for (MapShape e : this.shapes) if (e.getMinResolution() <= areaResolution)
log.debug("shape. locn=", e.getPoints().get(0).toOSMURL(), " type=", uk.me.parabola.mkgmap.reader.osm.GType.formatType(e.getType()), " name=", e.getName(), " min=", e.getMinResolution(), " max=", e.getMaxResolution(), " full=", e.getFullArea(), " calc=", uk.me.parabola.mkgmap.filters.ShapeMergeFilter.calcAreaSizeTestVal(e.getPoints()));
// the main culprits are lots of bits of sea and coastline in an overview map (res 12)
}
return null;
}
MapArea[] mapAreas = new MapArea[nx * ny];
log.info("Splitting area " + bounds + " into " + nx + "x" + ny + " pieces at resolution " + areaResolution, tooSmallToDivide);
List<MapArea> addedAreas = new ArrayList<>();
for (int i = 0; i < mapAreas.length; i++) {
mapAreas[i] = new MapArea(areas[i], areaResolution, splitPolygonsIntoArea);
if (log.isDebugEnabled())
log.debug("area before", mapAreas[i].getBounds());
}
int xbaseHp = areas[0].getMinLong() << Coord.DELTA_SHIFT;
int ybaseHp = areas[0].getMinLat() << Coord.DELTA_SHIFT;
int dxHp = areas[0].getWidth() << Coord.DELTA_SHIFT;
int dyHp = areas[0].getHeight() << Coord.DELTA_SHIFT;
// Some of the work done by PolygonSubdivSizeSplitterFilter now done here
final int maxSize = Math.min((1 << 24) - 1, Math.max(MapSplitter.MAX_DIVISION_SIZE << (MAX_RESOLUTION - areaResolution), 0x8000));
/**
* These constants control when an item (shape unless splitPolygonsIntoArea or line) is shifted into its own MapArea/SubDivision.
* Generally, an item is allowed into the MapArea chosen by centre provided it is no bigger than the MapArea.
* This means that there could be big items near the edges of the MapArea that stick out by almost half, so must
* ensure that this doesn't cause the mapArea to exceed subDivision size limits.
* When the MapArea get small, we don't want to shift lots if items into their own areas;
* The *2 of LARGE_OBJECT_DIM is to keep to the same behaviour as earlier versions.
*/
final int maxWidth = Math.max(Math.min(areas[0].getWidth(), maxSize / 2), LARGE_OBJECT_DIM * 2);
final int maxHeight = Math.max(Math.min(areas[0].getHeight(), maxSize / 2), LARGE_OBJECT_DIM * 2);
// and don't have a good tooSmallToDivide strategy when not splitPolygonsIntoArea.
if (tooSmallToDivide) {
distShapesIntoNewAreas(addedAreas, mapAreas[0]);
} else {
for (MapShape e : this.shapes) {
Area shapeBounds = e.getBounds();
if (splitPolygonsIntoArea || shapeBounds.getMaxDimension() > maxSize) {
splitIntoAreas(mapAreas, e);
continue;
}
int areaIndex = pickArea(mapAreas, e, xbaseHp, ybaseHp, nx, ny, dxHp, dyHp);
if ((shapeBounds.getHeight() > maxHeight || shapeBounds.getWidth() > maxWidth) && !areas[areaIndex].contains(shapeBounds)) {
// use splitIntoAreas to deal with overflow
MapArea largeObjectArea = new MapArea(shapeBounds, areaResolution, true);
largeObjectArea.addShape(e);
addedAreas.add(largeObjectArea);
continue;
}
mapAreas[areaIndex].addShape(e);
}
}
if (tooSmallToDivide) {
distPointsIntoNewAreas(addedAreas, mapAreas[0]);
} else {
for (MapPoint p : this.points) {
int areaIndex = pickArea(mapAreas, p, xbaseHp, ybaseHp, nx, ny, dxHp, dyHp);
mapAreas[areaIndex].addPoint(p);
}
}
if (tooSmallToDivide) {
distLinesIntoNewAreas(addedAreas, mapAreas[0]);
} else {
for (MapLine l : this.lines) {
// Drop any zero sized lines.
if (l instanceof MapRoad == false && l.getRect().height <= 0 && l.getRect().width <= 0)
continue;
Area lineBounds = l.getBounds();
int areaIndex = pickArea(mapAreas, l, xbaseHp, ybaseHp, nx, ny, dxHp, dyHp);
if ((lineBounds.getHeight() > maxHeight || lineBounds.getWidth() > maxWidth) && !areas[areaIndex].contains(lineBounds)) {
MapArea largeObjectArea = new MapArea(lineBounds, areaResolution, false);
largeObjectArea.addLine(l);
addedAreas.add(largeObjectArea);
continue;
}
mapAreas[areaIndex].addLine(l);
}
}
if (!addedAreas.isEmpty()) {
// combine list and array
int pos = mapAreas.length;
mapAreas = Arrays.copyOf(mapAreas, mapAreas.length + addedAreas.size());
for (MapArea ma : addedAreas) {
if (// distShapesIntoNewAreas etc didn't know how big it was going to be
ma.getBounds() == null)
// so set to bounds of all elements
ma.setBounds(ma.getFullBounds());
mapAreas[pos++] = ma;
}
}
return mapAreas;
}
Aggregations