use of uk.me.parabola.imgfmt.app.Area in project mkgmap by openstreetmap.
the class SeaGenerator method addPrecompSea.
/**
* Loads the precompiled sea tiles and adds the data to the
* element saver.
*/
private void addPrecompSea() {
log.info("Load precompiled sea tiles");
// flag if all tiles contains sea or way only
// this is important for polygon processing
boolean distinctTilesOnly = true;
List<Way> landWays = new ArrayList<Way>();
List<Way> seaWays = new ArrayList<Way>();
List<java.awt.geom.Area> seaOnlyAreas = new ArrayList<java.awt.geom.Area>();
List<java.awt.geom.Area> landOnlyAreas = new ArrayList<java.awt.geom.Area>();
// get the index with assignment key => sea/land/tilename
ZipFile zipFile = null;
PrecompData pd = precompIndex.get();
if (precompSeaDir.getName().endsWith(".zip")) {
zipFile = pd.zipFile;
}
for (String precompKey : getPrecompKeyNames()) {
String tileName = getTileName(precompKey);
if (tileName == null) {
log.error("Precompile sea tile " + precompKey + " is missing in the index. Skipping.");
continue;
}
if ("sea".equals(tileName) || "land".equals(tileName)) {
// the whole precompiled tile is filled with either land or sea
// => create a rectangle that covers the whole precompiled tile
String[] tileCoords = keySplitter.split(precompKey);
int minLat = Integer.valueOf(tileCoords[0]);
int minLon = Integer.valueOf(tileCoords[1]);
Rectangle r = new Rectangle(minLon, minLat, PRECOMP_RASTER, PRECOMP_RASTER);
if ("sea".equals(tileName)) {
seaOnlyAreas = addWithoutCreatingHoles(seaOnlyAreas, new java.awt.geom.Area(r));
} else {
landOnlyAreas = addWithoutCreatingHoles(landOnlyAreas, new java.awt.geom.Area(r));
}
} else {
distinctTilesOnly = false;
try {
InputStream is = null;
if (zipFile != null) {
ZipEntry entry = zipFile.getEntry(pd.precompZipFileInternalPath + tileName);
if (entry != null) {
is = zipFile.getInputStream(entry);
} else {
log.error("Preompiled sea tile " + tileName + " not found.");
}
} else {
File precompTile = new File(precompSeaDir, tileName);
is = new FileInputStream(precompTile);
}
if (is != null) {
Collection<Way> seaPrecompWays = loadPrecompTile(is, tileName);
if (log.isDebugEnabled())
log.debug(seaPrecompWays.size(), "precomp sea ways from", tileName, "loaded.");
for (Way w : seaPrecompWays) {
// set a new id to be sure that the precompiled ids do not
// interfere with the ids of this run
w.setFakeId();
if ("land".equals(w.getTag("natural"))) {
landWays.add(w);
} else {
seaWays.add(w);
}
}
}
} catch (FileNotFoundException exp) {
log.error("Preompiled sea tile " + tileName + " not found.");
} catch (Exception exp) {
log.error(exp);
exp.printStackTrace();
}
}
}
landWays.addAll(areaToWays(landOnlyAreas, "land"));
seaWays.addAll(areaToWays(seaOnlyAreas, "sea"));
landOnlyAreas = null;
seaOnlyAreas = null;
// check if the land tags need to be changed
if (landTag != null && ("natural".equals(landTag[0]) && "land".equals(landTag[1])) == false) {
for (Way w : landWays) {
w.deleteTag("natural");
w.addTag(landTag[0], landTag[1]);
}
}
if (generateSeaUsingMP || distinctTilesOnly) {
// also with polygons if all tiles are using either sea or land only
for (Way w : landWays) {
saver.addWay(w);
}
for (Way w : seaWays) {
w.setFullArea(seaSize);
saver.addWay(w);
}
} else {
// using polygons
Area bounds = saver.getBoundingBox();
// first add the complete bounding box as sea
Way sea = new Way(FakeIdGenerator.makeFakeId(), bounds.toCoords());
sea.addTag("natural", "sea");
sea.setFullArea(seaSize);
for (Way w : landWays) {
saver.addWay(w);
}
}
}
use of uk.me.parabola.imgfmt.app.Area in project mkgmap by openstreetmap.
the class SeaGenerator method getPrecompKeyNames.
/**
* Calculates the key names of the precompiled sea tiles for the bounding box.
* The key names are compiled of {@code lat+"_"+lon}.
* @return the key names for the bounding box
*/
private List<String> getPrecompKeyNames() {
Area bounds = saver.getBoundingBox();
List<String> precompKeys = new ArrayList<String>();
for (int lat = getPrecompTileStart(bounds.getMinLat()); lat < getPrecompTileEnd(bounds.getMaxLat()); lat += PRECOMP_RASTER) {
for (int lon = getPrecompTileStart(bounds.getMinLong()); lon < getPrecompTileEnd(bounds.getMaxLong()); lon += PRECOMP_RASTER) {
precompKeys.add(lat + "_" + lon);
}
}
return precompKeys;
}
use of uk.me.parabola.imgfmt.app.Area in project mkgmap by openstreetmap.
the class SeaGenerator method end.
/**
* All done, process the saved shoreline information and construct the polygons.
*/
public void end() {
// if it is set do not perform any other algorithm
if (precompSeaDir != null) {
addPrecompSea();
return;
}
final Area seaBounds = saver.getBoundingBox();
if (coastlineFilenames == null) {
log.info("Shorelines before join", shoreline.size());
shoreline = joinWays(shoreline);
} else {
shoreline.addAll(CoastlineFileLoader.getCoastlineLoader().getCoastlines(seaBounds));
log.info("Shorelines from extra file:", shoreline.size());
}
int closedS = 0;
int unclosedS = 0;
for (Way w : shoreline) {
if (w.hasIdenticalEndPoints()) {
closedS++;
} else {
unclosedS++;
}
}
log.info("Closed shorelines", closedS);
log.info("Unclosed shorelines", unclosedS);
// clip all shoreline segments
clipShorlineSegments(shoreline, seaBounds);
log.info("generating sea, seaBounds=", seaBounds);
int minLat = seaBounds.getMinLat();
int maxLat = seaBounds.getMaxLat();
int minLong = seaBounds.getMinLong();
int maxLong = seaBounds.getMaxLong();
Coord nw = new Coord(minLat, minLong);
Coord ne = new Coord(minLat, maxLong);
Coord sw = new Coord(maxLat, minLong);
Coord se = new Coord(maxLat, maxLong);
if (shoreline.isEmpty()) {
// no sea required
// even though there is no sea, generate a land
// polygon so that the tile's background colour will
// match the land colour on the tiles that do contain
// some sea
long landId = FakeIdGenerator.makeFakeId();
Way land = new Way(landId, seaBounds.toCoords());
land.addTag(landTag[0], landTag[1]);
// no matter if the multipolygon option is used it is
// only necessary to create a land polygon
saver.addWay(land);
// nothing more to do
return;
}
long multiId = FakeIdGenerator.makeFakeId();
Relation seaRelation = null;
if (generateSeaUsingMP) {
log.debug("Generate seabounds relation", multiId);
seaRelation = new GeneralRelation(multiId);
seaRelation.addTag("type", "multipolygon");
seaRelation.addTag("natural", "sea");
}
List<Way> islands = new ArrayList<Way>();
// handle islands (closed shoreline components) first (they're easy)
handleIslands(shoreline, seaBounds, islands);
// the remaining shoreline segments should intersect the boundary
// find the intersection points and store them in a SortedMap
NavigableMap<EdgeHit, Way> hitMap = findIntesectionPoints(shoreline, seaBounds, seaRelation);
// now construct inner ways from these segments
boolean shorelineReachesBoundary = createInnerWays(seaBounds, islands, hitMap);
if (!shorelineReachesBoundary && roadsReachBoundary) {
// try to avoid tiles being flooded by anti-lakes or other
// bogus uses of natural=coastline
generateSeaBackground = false;
}
List<Way> antiIslands = removeAntiIslands(seaRelation, islands);
if (islands.isEmpty()) {
// the tile doesn't contain any islands so we can assume
// that it's showing a land mass that contains some
// enclosed sea areas - in which case, we don't want a sea
// coloured background
generateSeaBackground = false;
}
if (generateSeaBackground) {
for (Way ai : antiIslands) {
boolean containedByLand = false;
for (Way i : islands) {
if (i.containsPointsOf(ai)) {
containedByLand = true;
break;
}
}
if (!containedByLand) {
// found an anti-island that is not contained by
// land so convert it back into an island
ai.deleteTag("natural");
ai.addTag(landTag[0], landTag[1]);
if (generateSeaUsingMP) {
// create a "inner" way for the island
assert seaRelation != null;
seaRelation.addElement("inner", ai);
}
log.warn("Converting anti-island starting at", ai.getPoints().get(0).toOSMURL(), "into an island as it is surrounded by water");
}
}
long seaId = FakeIdGenerator.makeFakeId();
Way sea = new Way(seaId);
// the sea background area must be a little bigger than all
// inner land areas. this is a workaround for a mp shortcoming:
// mp is not able to combine outer and inner if they intersect
// or have overlaying lines
// the added area will be clipped later by the style generator
sea.addPoint(new Coord(nw.getLatitude() - 1, nw.getLongitude() - 1));
sea.addPoint(new Coord(sw.getLatitude() + 1, sw.getLongitude() - 1));
sea.addPoint(new Coord(se.getLatitude() + 1, se.getLongitude() + 1));
sea.addPoint(new Coord(ne.getLatitude() - 1, ne.getLongitude() + 1));
// close shape
sea.addPoint(sea.getPoints().get(0));
sea.addTag("natural", "sea");
sea.setFullArea(seaSize);
log.info("sea: ", sea);
saver.addWay(sea);
if (generateSeaUsingMP) {
assert seaRelation != null;
seaRelation.addElement("outer", sea);
}
} else {
// background is land
// generate a land polygon so that the tile's
// background colour will match the land colour on the
// tiles that do contain some sea
long landId = FakeIdGenerator.makeFakeId();
Way land = new Way(landId, seaBounds.toCoords());
land.addTag(landTag[0], landTag[1]);
saver.addWay(land);
if (generateSeaUsingMP) {
seaRelation.addElement("inner", land);
}
}
if (generateSeaUsingMP) {
SeaPolygonRelation coastRel = saver.createSeaPolyRelation(seaRelation);
coastRel.setFloodBlocker(floodblocker);
if (floodblocker) {
coastRel.setFloodBlockerGap(fbGap);
coastRel.setFloodBlockerRatio(fbRatio);
coastRel.setFloodBlockerThreshold(fbThreshold);
coastRel.setFloodBlockerRules(fbRules.getWayRules());
coastRel.setLandTag(landTag[0], landTag[1]);
coastRel.setDebug(fbDebug);
}
saver.addRelation(coastRel);
}
shoreline = null;
}
use of uk.me.parabola.imgfmt.app.Area in project mkgmap by openstreetmap.
the class UnusedElementsRemoverHook method end.
public void end() {
long t1 = System.currentTimeMillis();
log.info("Removing unused elements");
final Area bbox = saver.getBoundingBox();
long nodes = saver.getNodes().size();
// go through all nodes
for (Node node : new ArrayList<Node>(saver.getNodes().values())) {
// nodes without tags can be removed
if (node.getTagCount() == 0) {
saver.getNodes().remove(node.getId());
continue;
}
// check if the node is within the tile bounding box
if (bbox.contains(node.getLocation()) == false) {
boolean removeNode = true;
// check if the node has no tag of the blacklist
if (nodeTagBlacklist.isEmpty() == false) {
for (String tag : nodeTagBlacklist) {
if (node.getTag(tag) != null) {
// the node contains one tag that might be interesting for the POIGeneratorHook
// do not remove it
removeNode = false;
break;
}
}
}
if (removeNode) {
saver.getNodes().remove(node.getId());
} else {
log.debug("Keep node", node, "because it contains a tag which might be required for the area-to-poi function.");
}
}
}
long tr1 = System.currentTimeMillis();
// store all way ids that are referenced by a relation
// all tags without a tag must not be removed if they are referenced by a relation
Set<Long> relationWays = new HashSet<Long>();
for (Relation rel : saver.getRelations().values()) {
for (Entry<String, Element> relEntry : rel.getElements()) {
if (relEntry.getValue() instanceof Way) {
relationWays.add(relEntry.getValue().getId());
}
}
}
log.debug("Collecting way ids from relations took", (System.currentTimeMillis() - tr1), "ms");
Rectangle bboxRect = new Rectangle(bbox.getMinLong(), bbox.getMinLat(), bbox.getWidth(), bbox.getHeight());
long relWays = 0;
long ways = saver.getWays().size();
for (Way way : new ArrayList<Way>(saver.getWays().values())) {
if (way.getPoints().isEmpty()) {
// empty way will not appear in the map => remove it
saver.getWays().remove(way.getId());
continue;
}
// a relation might be used to add tags to the way using the style file
if (way.getTagCount() == 0) {
if (relationWays.contains(way.getId())) {
relWays++;
} else {
saver.getWays().remove(way.getId());
continue;
}
}
// check if the way is completely outside the tile bounding box
boolean coordInBbox = false;
Coord prevC = null;
// It is possible that the way is larger than the bounding box and therefore
// contains the bbox completely. Especially this is true for the sea polygon
// when using --generate-sea=polygon
// So need the calc the bbox of the way
Coord firstC = way.getPoints().get(0);
int minLat = firstC.getLatitude();
int maxLat = firstC.getLatitude();
int minLong = firstC.getLongitude();
int maxLong = firstC.getLongitude();
for (Coord c : way.getPoints()) {
if (bbox.contains(c)) {
coordInBbox = true;
break;
} else if (prevC != null) {
// check if the line intersects the bounding box
if (bboxRect.intersectsLine(prevC.getLongitude(), prevC.getLatitude(), c.getLongitude(), c.getLatitude())) {
if (log.isDebugEnabled()) {
log.debug("Intersection!");
log.debug("Bbox:", bbox);
log.debug("Way coords:", prevC, c);
}
coordInBbox = true;
break;
}
}
if (minLat > c.getLatitude()) {
minLat = c.getLatitude();
} else if (maxLat < c.getLatitude()) {
maxLat = c.getLatitude();
}
if (minLong > c.getLongitude()) {
minLong = c.getLongitude();
} else if (maxLong < c.getLongitude()) {
maxLong = c.getLongitude();
}
prevC = c;
}
if (coordInBbox == false) {
// no coord of the way is within the bounding box
// check if the way possibly covers the bounding box completely
Area wayBbox = new Area(minLat, minLong, maxLat, maxLong);
if (wayBbox.intersects(saver.getBoundingBox())) {
log.debug(way, "possibly covers the bbox completely. Keep it.", way.toTagString());
} else {
saver.getWays().remove(way.getId());
}
}
}
log.info("Relation referenced ways:", relationWays.size(), "Used:", relWays);
log.info("Nodes: before:", nodes, "after:", saver.getNodes().size());
log.info("Ways: before:", ways, "after:", saver.getWays().size());
log.info("Removing unused elements took", (System.currentTimeMillis() - t1), "ms");
}
use of uk.me.parabola.imgfmt.app.Area in project mkgmap by openstreetmap.
the class HGTConverterTest method testLon0Right.
@Test
public void testLon0Right() throws Exception {
Area bbox = new Area(0, 0.1, 0.1, 0.0);
HGTConverter hgtConverter = new HGTConverter(HGT_PATH, bbox, null, DEMFile.EXTRA);
assertEquals(0, hgtConverter.getElevation(bbox.getMaxLat() * 256, bbox.getMinLong() * 256));
assertEquals(0, hgtConverter.getElevation(bbox.getMaxLat() * 256, bbox.getMaxLong() * 256));
assertEquals(0, hgtConverter.getElevation(bbox.getMinLat() * 256, bbox.getMinLong() * 256));
assertEquals(0, hgtConverter.getElevation(bbox.getMinLat() * 256, bbox.getMaxLong() * 256));
}
Aggregations