use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class StyledConverter method createRouteRestrictionsFromPOI.
/**
* If POI changes access restrictions (e.g. bollards), create corresponding
* route restrictions so that only allowed vehicles/pedestrians are routed
* through this point.
*/
private void createRouteRestrictionsFromPOI() {
Iterator<Map.Entry<Node, List<Way>>> iter = poiRestrictions.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Node, List<Way>> entry = iter.next();
Node node = entry.getKey();
Coord p = node.getLocation();
// list of ways that are connected to the poi
List<Way> wayList = entry.getValue();
byte exceptMask = AccessTagsAndBits.evalAccessTags(node);
Map<Integer, CoordNode> otherNodeIds = new LinkedHashMap<>();
CoordNode viaNode = null;
boolean viaIsUnique = true;
for (Way way : wayList) {
CoordNode lastNode = null;
for (Coord co : way.getPoints()) {
// not 100% fail safe: points may have been replaced before
if (co instanceof CoordNode == false)
continue;
CoordNode cn = (CoordNode) co;
if (p.highPrecEquals(cn)) {
if (viaNode == null)
viaNode = cn;
else if (viaNode != cn) {
log.error("Found multiple points with equal coords as CoordPOI at " + p.toOSMURL());
// if we ever get here we can add code to identify the exact node
viaIsUnique = false;
}
if (lastNode != null)
otherNodeIds.put(lastNode.getId(), lastNode);
} else {
if (p.highPrecEquals(lastNode))
otherNodeIds.put(cn.getId(), cn);
}
lastNode = cn;
}
}
if (viaNode == null) {
log.error("Did not find CoordPOI node at " + p.toOSMURL() + " in ways " + wayList);
continue;
}
if (viaIsUnique == false) {
log.error("Found multiple points with equal coords as CoordPOI at " + p.toOSMURL());
continue;
}
if (otherNodeIds.size() < 2) {
log.info("Access restriction in POI node " + node.toBrowseURL() + " was ignored, has no effect on any connected way");
continue;
}
GeneralRouteRestriction rr = new GeneralRouteRestriction("no_through", exceptMask, "CoordPOI at " + p.toOSMURL());
rr.setViaNodes(Arrays.asList(viaNode));
int added = collector.addRestriction(rr);
if (added == 0) {
log.info("Access restriction in POI node " + node.toBrowseURL() + " was ignored, has no effect on any connected way");
} else {
log.info("Access restriction in POI node", node.toBrowseURL(), "was translated to", added, "route restriction(s)");
}
if (wayList.size() > 1 && added > 2) {
log.warn("Access restriction in POI node", node.toBrowseURL(), "affects routing on multiple ways");
}
}
}
use of uk.me.parabola.imgfmt.app.Coord 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.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class StyledConverter method splitWayAt.
/**
* split a Way at the specified point and return the new Way (the
* original Way is truncated, both ways will contain the split point)
* @param way the way to split
* @param index the split position.
* @return the trailing part of the way
*/
private static Way splitWayAt(Way way, int index) {
if (way.isViaWay()) {
log.warn("via way of restriction is split, restriction will be ignored", way);
}
Way trailingWay = new Way(way.getId());
List<Coord> wayPoints = way.getPoints();
int numPointsInWay = wayPoints.size();
for (int i = index; i < numPointsInWay; ++i) trailingWay.addPoint(wayPoints.get(i));
// ensure split point becomes a node
wayPoints.get(index).incHighwayCount();
// copy the way's name and tags to the new way
trailingWay.copyTags(way);
// it's probably more efficient to remove from the end first
for (int i = numPointsInWay - 1; i > index; --i) wayPoints.remove(i);
return trailingWay;
}
use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class StyledConverter method setBoundingBox.
/**
* Set the bounding box for this map. This should be set before any other
* elements are converted if you want to use it. All elements that are added
* are clipped to this box, new points are added as needed at the boundary.
*
* If a node or a way falls completely outside the boundary then it would be
* omitted. This would not normally happen in the way this option is typically
* used however.
*
* @param bbox The bounding area, must not be null.
*/
public void setBoundingBox(Area bbox) {
this.clipper = new AreaClipper(bbox);
this.bbox = bbox;
// we calculate our own bounding box, now let the collector know about it.
collector.addToBounds(new Coord(bbox.getMinLat(), bbox.getMinLong()));
collector.addToBounds(new Coord(bbox.getMaxLat(), bbox.getMaxLong()));
}
use of uk.me.parabola.imgfmt.app.Coord 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);
}
}
Aggregations