use of uk.me.parabola.mkgmap.reader.osm.CoordPOI in project mkgmap by openstreetmap.
the class StyledConverter method filterCoordPOI.
/**
* Make sure that only CoordPOI which affect routing will be treated as
* nodes in the following routines.
*/
private void filterCoordPOI() {
if (!linkPOIsToWays)
return;
log.info("translating CoordPOI");
for (ConvertedWay cw : roads) {
if (!cw.isValid())
continue;
Way way = cw.getWay();
if ("true".equals(way.getTag("mkgmap:way-has-pois"))) {
String wayPOI = "";
List<Coord> points = way.getPoints();
int numPoints = points.size();
for (int i = 0; i < numPoints; i++) {
Coord p = points.get(i);
if (p instanceof CoordPOI) {
CoordPOI cp = (CoordPOI) p;
Node node = cp.getNode();
boolean usedInThisWay = false;
byte wayAccess = cw.getAccess();
if (node.getTag("mkgmap:road-class") != null || node.getTag("mkgmap:road-speed") != null) {
if (wayAccess != AccessTagsAndBits.FOOT)
usedInThisWay = true;
}
byte nodeAccess = AccessTagsAndBits.evalAccessTags(node);
if (nodeAccess != (byte) 0xff) {
// barriers etc.
if ((wayAccess & nodeAccess) != wayAccess) {
// node is more restrictive
if (p.getHighwayCount() >= 2 || (i != 0 && i != numPoints - 1)) {
usedInThisWay = true;
cp.setConvertToViaInRouteRestriction(true);
} else {
log.info("POI node", node.getId(), "with access restriction is ignored, it is not connected to other routable ways");
}
} else
log.info("Access restriction in POI node", node.toBrowseURL(), "was ignored for way", way.toBrowseURL());
}
if (usedInThisWay) {
cp.setUsed(true);
wayPOI += "[" + node.getId() + "]";
}
}
}
if (wayPOI.isEmpty()) {
way.deleteTag("mkgmap:way-has-pois");
log.info("ignoring CoordPOI(s) for way", way.toBrowseURL(), "because routing is not affected.");
} else {
way.addTag(WAY_POI_NODE_IDS, wayPOI);
}
}
}
}
use of uk.me.parabola.mkgmap.reader.osm.CoordPOI in project mkgmap by openstreetmap.
the class StyledConverter method addRoad.
/**
* Add a way to the road network. May call itself recursively and
* might truncate the way if splitting is required.
* @param way the way
* @param gt the type assigned by the style
*/
private void addRoad(ConvertedWay cw) {
Way way = cw.getWay();
if (way.getPoints().size() < 2) {
log.warn("road has < 2 points", way.getId(), "(discarding)");
return;
}
checkRoundabout(cw);
// process any Coords that have a POI associated with them
// metres
final double stubSegmentLength = 25;
String wayPOI = way.getTag(WAY_POI_NODE_IDS);
if (wayPOI != null) {
List<Coord> points = way.getPoints();
// or a barrier
for (int i = 0; i < points.size(); ++i) {
Coord p = points.get(i);
if (p instanceof CoordPOI && ((CoordPOI) p).isUsed()) {
CoordPOI cp = (CoordPOI) p;
Node node = cp.getNode();
if (wayPOI.contains("[" + node.getId() + "]")) {
log.debug("POI", node.getId(), "changes way", way.getId());
// are converted to RouteRestrictions
if (p.getHighwayCount() < 2 && cp.getConvertToViaInRouteRestriction() && (i != 0 && i != points.size() - 1))
p.incHighwayCount();
String roadClass = node.getTag("mkgmap:road-class");
String roadSpeed = node.getTag("mkgmap:road-speed");
if (roadClass != null || roadSpeed != null) {
// find good split point after POI
Coord splitPoint;
double segmentLength = 0;
int splitPos = i + 1;
while (splitPos + 1 < points.size()) {
splitPoint = points.get(splitPos);
segmentLength += splitPoint.distance(points.get(splitPos - 1));
if (splitPoint.getHighwayCount() > 1 || segmentLength > stubSegmentLength - 5)
break;
splitPos++;
}
if (segmentLength > stubSegmentLength + 10) {
// insert a new point after the POI to
// make a short stub segment
splitPoint = points.get(splitPos);
Coord prev = points.get(splitPos - 1);
double dist = splitPoint.distance(prev);
double neededLength = stubSegmentLength - (segmentLength - dist);
splitPoint = prev.makeBetweenPoint(splitPoint, neededLength / dist);
double newDist = splitPoint.distance(prev);
segmentLength += newDist - dist;
splitPoint.incHighwayCount();
points.add(splitPos, splitPoint);
}
if ((splitPos + 1) < points.size() && way.isViaWay() == false && safeToSplitWay(points, splitPos, i, points.size() - 1)) {
Way tail = splitWayAt(way, splitPos);
// recursively process tail of way
addRoad(new ConvertedWay(cw, tail));
}
boolean classChanged = cw.recalcRoadClass(node);
if (classChanged && log.isInfoEnabled()) {
log.info("POI changing road class of", way.toBrowseURL(), "to", cw.getRoadClass(), "at", points.get(0).toOSMURL());
}
boolean speedChanged = cw.recalcRoadSpeed(node);
if (speedChanged && log.isInfoEnabled()) {
log.info("POI changing road speed of", way.toBrowseURL(), "to", cw.getRoadSpeed(), "at", points.get(0).toOSMURL());
}
}
}
}
// the affected region
if (i + 1 < points.size() && points.get(i + 1) instanceof CoordPOI) {
CoordPOI cp = (CoordPOI) points.get(i + 1);
Node node = cp.getNode();
if (cp.isUsed() && wayPOI.contains("[" + node.getId() + "]")) {
if (node.getTag("mkgmap:road-class") != null || node.getTag("mkgmap:road-speed") != null) {
// find good split point before POI
double segmentLength = 0;
int splitPos = i;
Coord splitPoint;
while (splitPos >= 0) {
splitPoint = points.get(splitPos);
segmentLength += splitPoint.distance(points.get(splitPos + 1));
if (splitPoint.getHighwayCount() >= 2 || segmentLength > stubSegmentLength - 5)
break;
--splitPos;
}
if (segmentLength > stubSegmentLength + 10) {
// insert a new point before the POI to
// make a short stub segment
splitPoint = points.get(splitPos);
Coord prev = points.get(splitPos + 1);
double dist = splitPoint.distance(prev);
double neededLength = stubSegmentLength - (segmentLength - dist);
splitPoint = prev.makeBetweenPoint(splitPoint, neededLength / dist);
segmentLength += splitPoint.distance(prev) - dist;
splitPoint.incHighwayCount();
splitPos++;
points.add(splitPos, splitPoint);
}
if (splitPos > 0 && safeToSplitWay(points, splitPos, 0, points.size() - 1)) {
Way tail = splitWayAt(way, splitPos);
// recursively process tail of way
addRoad(new ConvertedWay(cw, tail));
}
}
}
}
}
}
// if there is a bounding box, clip the way with it
List<Way> clippedWays = null;
if (bbox != null) {
List<List<Coord>> lineSegs = LineClipper.clip(bbox, way.getPoints());
if (lineSegs != null) {
if (lineSegs.isEmpty()) {
removeRestrictionsWithWay(Level.WARNING, way, "ends on tile boundary, restriction is ignored");
}
clippedWays = new ArrayList<>();
for (List<Coord> lco : lineSegs) {
Way nWay = new Way(way.getId());
nWay.copyTags(way);
for (Coord co : lco) {
nWay.addPoint(co);
if (co.getOnBoundary()) {
// this point lies on a boundary
// make sure it becomes a node
co.incHighwayCount();
}
}
clippedWays.add(nWay);
}
}
}
if (clippedWays != null) {
for (Way clippedWay : clippedWays) {
addRoadAfterSplittingLoops(new ConvertedWay(cw, clippedWay));
}
} else {
// no bounding box or way was not clipped
addRoadAfterSplittingLoops(cw);
}
}
use of uk.me.parabola.mkgmap.reader.osm.CoordPOI in project mkgmap by openstreetmap.
the class StyledConverter method addRoadWithoutLoops.
private void addRoadWithoutLoops(ConvertedWay cw) {
Way way = cw.getWay();
List<Integer> nodeIndices = new ArrayList<>();
List<Coord> points = way.getPoints();
if (points.size() < 2) {
log.warn("road has < 2 points", way.getId(), "(discarding)");
return;
}
Way trailingWay = null;
String debugWayName = way.getDebugName();
// collect the Way's nodes and also split the way if any
// inter-node arc length becomes excessive
double arcLength = 0;
// detect if it would be split by the LineSizeSplitterFilter
class WayBBox {
int minLat = Integer.MAX_VALUE;
int maxLat = Integer.MIN_VALUE;
int minLon = Integer.MAX_VALUE;
int maxLon = Integer.MIN_VALUE;
void addPoint(Coord co) {
int lat = co.getLatitude();
if (lat < minLat)
minLat = lat;
if (lat > maxLat)
maxLat = lat;
int lon = co.getLongitude();
if (lon < minLon)
minLon = lon;
if (lon > maxLon)
maxLon = lon;
}
boolean tooBig() {
return LineSizeSplitterFilter.testDims(maxLat - minLat, maxLon - minLon) >= 1.0;
}
}
WayBBox wayBBox = new WayBBox();
for (int i = 0; i < points.size(); ++i) {
Coord p = points.get(i);
wayBBox.addPoint(p);
// the arc length between nodes
if ((i + 1) < points.size()) {
Coord nextP = points.get(i + 1);
double d = p.distance(nextP);
for (; ; ) {
int dlat = Math.abs(nextP.getLatitude() - p.getLatitude());
int dlon = Math.abs(nextP.getLongitude() - p.getLongitude());
if (d > MAX_ARC_LENGTH || Math.max(dlat, dlon) >= LineSizeSplitterFilter.MAX_SIZE) {
double frac = Math.min(0.5, 0.95 * (MAX_ARC_LENGTH / d));
nextP = p.makeBetweenPoint(nextP, frac);
nextP.incHighwayCount();
points.add(i + 1, nextP);
double newD = p.distance(nextP);
if (log.isInfoEnabled())
log.info("Way", debugWayName, "contains a segment that is", (int) d + "m long but I am adding a new point to reduce its length to", (int) newD + "m");
d = newD;
} else
break;
}
wayBBox.addPoint(nextP);
if ((arcLength + d) > MAX_ARC_LENGTH) {
if (i <= 0)
log.error("internal error: long arc segment was not split", debugWayName);
assert i > 0 : "long arc segment was not split";
assert trailingWay == null : "trailingWay not null #1";
trailingWay = splitWayAt(way, i);
// points so the loop will now terminate
if (log.isInfoEnabled())
log.info("Splitting way", debugWayName, "at", points.get(i).toOSMURL(), "to limit arc length to", (long) arcLength + "m");
} else if (wayBBox.tooBig()) {
if (i <= 0)
log.error("internal error: arc segment with big bbox not split", debugWayName);
assert i > 0 : "arc segment with big bbox not split";
assert trailingWay == null : "trailingWay not null #2";
trailingWay = splitWayAt(way, i);
// points so the loop will now terminate
if (log.isInfoEnabled())
log.info("Splitting way", debugWayName, "at", points.get(i).toOSMURL(), "to limit the size of its bounding box");
} else {
if (p.getHighwayCount() > 1) {
// point is a node so zero arc length
arcLength = 0;
}
arcLength += d;
}
}
if (p.getHighwayCount() > 1) {
// this point is a node connecting highways
CoordNode coordNode = nodeIdMap.get(p);
if (coordNode == null) {
// assign a node id
coordNode = new CoordNode(p, nextNodeId++, p.getOnBoundary());
nodeIdMap.put(p, coordNode);
}
if (p instanceof CoordPOI) {
// check if this poi should be converted to a route restriction
CoordPOI cp = (CoordPOI) p;
if (cp.getConvertToViaInRouteRestriction()) {
String wayPOI = way.getTag(WAY_POI_NODE_IDS);
if (wayPOI != null && wayPOI.contains("[" + cp.getNode().getId() + "]")) {
byte nodeAccess = AccessTagsAndBits.evalAccessTags(cp.getNode());
if (nodeAccess != cw.getAccess()) {
List<Way> wayList = poiRestrictions.get(cp.getNode());
if (wayList == null) {
wayList = new ArrayList<>();
poiRestrictions.put(cp.getNode(), wayList);
}
wayList.add(way);
}
}
}
}
// add this index to node Indexes (should not already be there)
assert !nodeIndices.contains(i) : debugWayName + " has multiple nodes for point " + i + " new node is " + p.toOSMURL();
nodeIndices.add(i);
if ((i + 1) < points.size() && nodeIndices.size() == MAX_NODES_IN_WAY) {
// limit
assert trailingWay == null : "trailingWay not null #7";
trailingWay = splitWayAt(way, i);
// points so the loop will now terminate
if (log.isInfoEnabled())
log.info("Splitting way", debugWayName, "at", points.get(i).toOSMURL(), "as it has at least", MAX_NODES_IN_WAY, "nodes");
}
}
}
MapLine line = new MapLine();
elementSetup(line, cw.getGType(), way);
line.setPoints(points);
MapRoad road = new MapRoad(nextRoadId++, way.getId(), line);
if (routable == false)
road.skipAddToNOD(true);
boolean doFlareCheck = true;
if (cw.isRoundabout()) {
road.setRoundabout(true);
doFlareCheck = false;
}
if (way.tagIsLikeYes("mkgmap:synthesised")) {
road.setSynthesised(true);
doFlareCheck = false;
}
if (way.tagIsLikeNo("mkgmap:flare-check")) {
doFlareCheck = false;
} else if (way.tagIsLikeYes("mkgmap:flare-check")) {
doFlareCheck = true;
}
road.doFlareCheck(doFlareCheck);
// set road parameters
// copy road class and road speed
road.setRoadClass(cw.getRoadClass());
road.setSpeed(cw.getRoadSpeed());
if (cw.isOneway()) {
road.setDirection(true);
road.setOneway();
}
road.setAccess(cw.getAccess());
// does the road have a carpool lane?
if (cw.isCarpool())
road.setCarpoolLane();
if (cw.isThroughroute() == false)
road.setNoThroughRouting();
if (cw.isToll())
road.setToll();
// by default, ways are paved
if (cw.isUnpaved())
road.paved(false);
// by default, way's are not ferry routes
if (cw.isFerry())
road.ferry(true);
int numNodes = nodeIndices.size();
if (way.isViaWay() && numNodes > 2) {
List<RestrictionRelation> rrList = wayRelMap.get(way.getId());
for (RestrictionRelation rr : rrList) {
rr.updateViaWay(way, nodeIndices);
}
}
if (numNodes > 0) {
// replace Coords that are nodes with CoordNodes
for (int i = 0; i < numNodes; ++i) {
int n = nodeIndices.get(i);
Coord coord = points.get(n);
CoordNode thisCoordNode = nodeIdMap.get(coord);
assert thisCoordNode != null : "Way " + debugWayName + " node " + i + " (point index " + n + ") at " + coord.toOSMURL() + " yields a null coord node";
boolean boundary = coord.getOnBoundary();
if (boundary && log.isInfoEnabled()) {
log.info("Way", debugWayName + "'s point #" + n, "at", coord.toOSMURL(), "is a boundary node");
}
points.set(n, thisCoordNode);
}
}
if (roadLog.isInfoEnabled()) {
// shift the bits so that they have the correct position
int cmpAccess = (road.getRoadDef().getTabAAccess() & 0xff) + ((road.getRoadDef().getTabAAccess() & 0xc000) >> 6);
if (road.isDirection()) {
cmpAccess |= 1 << 10;
}
String access = String.format("%11s", Integer.toBinaryString(cmpAccess)).replace(' ', '0');
roadLog.info(String.format("%19d 0x%-2x %11s %6d %6d %6d %s", way.getId(), road.getType(), access, road.getRoadDef().getRoadClass(), road.getRoadDef().getRoadSpeed(), road.getPoints().size(), Arrays.toString(road.getLabels())));
}
// add the road to the housenumber generator
// it will add the road later on to the lineAdder
housenumberGenerator.addRoad(way, road);
if (trailingWay != null)
addRoadWithoutLoops(new ConvertedWay(cw, trailingWay));
}
use of uk.me.parabola.mkgmap.reader.osm.CoordPOI in project mkgmap by openstreetmap.
the class WrongAngleFixer method getReplacement.
/**
* Common code to handle replacements of points in ways. Checks for special
* cases regarding CoordPOI.
*
* @param p point to replace
* @param way way that contains p
* @param replacements the Map containing the replaced points
* @return the replacement
*/
private static Coord getReplacement(Coord p, Way way, Map<Coord, Coord> replacements) {
// it was previously merged into another point
if (p.isReplaced()) {
Coord replacement = null;
Coord r = p;
while ((r = replacements.get(r)) != null) {
replacement = r;
}
if (replacement != null) {
if (p instanceof CoordPOI) {
CoordPOI cp = (CoordPOI) p;
Node node = cp.getNode();
if (cp.isUsed() && way != null && way.getId() != 0) {
String wayPOI = way.getTag(StyledConverter.WAY_POI_NODE_IDS);
if (wayPOI != null && wayPOI.contains("[" + node.getId() + "]")) {
if (replacement instanceof CoordPOI) {
Node rNode = ((CoordPOI) replacement).getNode();
if (rNode.getId() != node.getId()) {
if (wayPOI.contains("[" + rNode.getId() + "]")) {
log.warn("CoordPOI", node.getId(), "replaced by CoordPOI", rNode.getId(), "in way", way.toBrowseURL());
} else
log.warn("CoordPOI", node.getId(), "replaced by ignored CoordPOI", rNode.getId(), "in way", way.toBrowseURL());
}
} else
log.warn("CoordPOI", node.getId(), "replaced by simple coord in way", way.toBrowseURL());
}
}
}
return replacement;
}
log.error("replacement not found for point " + p.toOSMURL());
}
return p;
}
use of uk.me.parabola.mkgmap.reader.osm.CoordPOI in project mkgmap by openstreetmap.
the class WrongAngleFixer method replaceCoord.
private static void replaceCoord(Coord toRepl, Coord replacement, Map<Coord, Coord> replacements) {
assert toRepl != replacement;
if (toRepl.getOnBoundary()) {
if (replacement.equals(toRepl) == false) {
log.error("boundary node is replaced by node with non-equal coordinates at", toRepl.toOSMURL());
assert false : "boundary node is replaced";
}
replacement.setOnBoundary(true);
}
toRepl.setReplaced(true);
if (toRepl instanceof CoordPOI) {
CoordPOI cp = (CoordPOI) toRepl;
if (cp.isUsed()) {
replacement = new CoordPOI(replacement);
((CoordPOI) replacement).setNode(cp.getNode());
((CoordPOI) replacement).setUsed(true);
((CoordPOI) replacement).setConvertToViaInRouteRestriction(cp.getConvertToViaInRouteRestriction());
if (replacement.highPrecEquals(cp.getNode().getLocation()) == false) {
log.error("CoordPOI node is replaced with non-equal coordinates at", toRepl.toOSMURL());
}
}
}
if (toRepl.isViaNodeOfRestriction())
replacement.setViaNodeOfRestriction(true);
replacements.put(toRepl, replacement);
while (toRepl.getHighwayCount() > replacement.getHighwayCount()) replacement.incHighwayCount();
if (toRepl.isEndOfWay()) {
replacement.setEndOfWay(true);
}
}
Aggregations