use of uk.me.parabola.imgfmt.app.CoordNode 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.CoordNode 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.imgfmt.app.CoordNode in project mkgmap by openstreetmap.
the class HousenumberRoad method buildIntervals.
public void buildIntervals() {
Collections.sort(houseNumbers, new HousenumberMatchByNumComparator());
if (log.isInfoEnabled())
log.info("Initial housenumbers for", road, "in", road.getCity(), houseNumbers);
filterRealDuplicates();
filterGroups();
if (houseNumbers.isEmpty())
return;
List<HousenumberMatch> leftNumbers = new ArrayList<HousenumberMatch>();
List<HousenumberMatch> rightNumbers = new ArrayList<HousenumberMatch>();
for (HousenumberMatch house : houseNumbers) {
if (house.getRoad() == null || house.isIgnored()) {
continue;
}
if (house.getHousenumberRoad() != this || house.getHousenumberRoad().getRoad() != house.getRoad()) {
log.error("internal error, road links are not correct", house.toBrowseURL());
}
if (house.isLeft()) {
leftNumbers.add(house);
} else {
rightNumbers.add(house);
}
}
detectGroups(leftNumbers, rightNumbers);
Collections.sort(leftNumbers, new HousenumberMatchByPosComparator());
Collections.sort(rightNumbers, new HousenumberMatchByPosComparator());
int currNodePos = 0;
int nodeIndex = 0;
int prevNumberNodeIndex = 0;
int prevNodePos = 0;
extNumbersHead = null;
ExtNumbers currNumbers = null;
for (Coord p : road.getPoints()) {
if (currNodePos == 0) {
if (road.skipAddToNOD() == false)
assert p instanceof CoordNode;
}
// An ordinary point in the road.
if (p.isNumberNode() == false) {
currNodePos++;
continue;
}
// The first time round, this is guaranteed to be a CoordNode
if (currNodePos == 0) {
nodeIndex++;
currNodePos++;
continue;
}
// Now we have a CoordNode and it is not the first one.
ExtNumbers numbers = new ExtNumbers(this);
numbers.setNodeIndex(prevNumberNodeIndex);
int leftUsed = numbers.setNumbers(leftNumbers, prevNodePos, currNodePos, true);
int rightUsed = numbers.setNumbers(rightNumbers, prevNodePos, currNodePos, false);
prevNodePos = currNodePos;
// maintain chain
numbers.prev = currNumbers;
if (currNumbers != null)
currNumbers.next = numbers;
else {
extNumbersHead = numbers;
}
currNumbers = numbers;
leftNumbers.subList(0, leftUsed).clear();
rightNumbers.subList(0, rightUsed).clear();
prevNumberNodeIndex = nodeIndex;
nodeIndex++;
currNodePos++;
}
}
use of uk.me.parabola.imgfmt.app.CoordNode in project mkgmap by openstreetmap.
the class RoadHelper method makeRoad.
public MapRoad makeRoad(MapLine l) {
assert roadId != 0;
if (log.isDebugEnabled())
log.debug("finishing road id " + roadId);
MapRoad road = new MapRoad(roadId, roadId, l);
// Set parameters.
road.setRoadClass(roadClass);
road.setSpeed(speed);
if (oneway)
road.setOneway();
if (toll)
road.setToll();
road.setAccess(mkgmapAccess);
if (numbers != null && !numbers.isEmpty()) {
convertNodesForHouseNumbers(road);
road.setNumbers(numbers);
}
List<Coord> points = road.getPoints();
for (NodeIndex ni : nodes) {
int n = ni.index;
if (log.isDebugEnabled())
log.debug("road has " + points.size() + " points");
Coord coord = points.get(n);
long id = coord.getId();
if (id == 0) {
CoordNode node = nodeCoords.get((long) ni.nodeId);
if (node == null) {
node = new CoordNode(coord, ni.nodeId, ni.boundary);
nodeCoords.put((long) ni.nodeId, node);
}
points.set(n, node);
} else if (id != ni.nodeId) {
log.warn("Inconsistant node ids");
}
}
return road;
}
use of uk.me.parabola.imgfmt.app.CoordNode in project mkgmap by openstreetmap.
the class RoadNetwork method addRoad.
public void addRoad(RoadDef roadDef, List<Coord> coordList) {
roadDefs.add(roadDef);
CoordNode lastCoord = null;
int lastIndex = 0;
double roadLength = 0;
double arcLength = 0;
int pointsHash = 0;
int npoints = coordList.size();
int numCoordNodes = 0;
boolean hasInternalNodes = false;
int numNumberNodes = 0;
BitSet nodeFlags = new BitSet();
for (int index = 0; index < npoints; index++) {
Coord co = coordList.get(index);
int id = co.getId();
if (id != 0) {
nodeFlags.set(numNumberNodes);
++numCoordNodes;
if (index > 0 && index < npoints - 1)
hasInternalNodes = true;
}
if (co.isNumberNode())
++numNumberNodes;
if (index == 0) {
if (id == 0)
roadDef.setStartsWithNode(false);
} else {
double d = co.distance(coordList.get(index - 1));
arcLength += d;
roadLength += d;
}
if (roadDef.skipAddToNOD())
continue;
pointsHash += co.hashCode();
if (id == 0)
// not a routing node
continue;
// the previous node to this one (and back again).
if (lastCoord != null) {
int lastId = lastCoord.getId();
if (log.isDebugEnabled()) {
log.debug("lastId = " + lastId + " curId = " + id);
log.debug("from " + lastCoord.toDegreeString() + " to " + co.toDegreeString());
log.debug("arclength=" + arcLength + " roadlength=" + roadLength);
}
RouteNode node1 = getOrAddNode(lastId, lastCoord);
RouteNode node2 = getOrAddNode(id, co);
if (node1 == node2)
log.error("Road " + roadDef + " contains consecutive identical nodes at " + co.toOSMURL() + " - routing will be broken");
else if (arcLength == 0)
log.warn("Road " + roadDef + " contains zero length arc at " + co.toOSMURL());
Coord forwardBearingPoint = coordList.get(lastIndex + 1);
if (lastCoord.equals(forwardBearingPoint) || forwardBearingPoint.isAddedNumberNode()) {
// useful - try some more points
for (int bi = lastIndex + 2; bi <= index; ++bi) {
Coord coTest = coordList.get(bi);
if (coTest.isAddedNumberNode() || lastCoord.equals(coTest))
continue;
forwardBearingPoint = coTest;
break;
}
}
Coord reverseBearingPoint = coordList.get(index - 1);
if (co.equals(reverseBearingPoint) || reverseBearingPoint.isAddedNumberNode()) {
// useful - try some more points
for (int bi = index - 2; bi >= lastIndex; --bi) {
Coord coTest = coordList.get(bi);
if (coTest.isAddedNumberNode() || co.equals(coTest))
continue;
reverseBearingPoint = coTest;
break;
}
}
double forwardInitialBearing = lastCoord.bearingTo(forwardBearingPoint);
double forwardDirectBearing = (co == forwardBearingPoint) ? forwardInitialBearing : lastCoord.bearingTo(co);
double reverseInitialBearing = co.bearingTo(reverseBearingPoint);
double directLength = (lastIndex + 1 == index) ? arcLength : lastCoord.distance(co);
double reverseDirectBearing = 0;
if (directLength > 0) {
// bearing on rhumb line is a constant, so we can simply revert
reverseDirectBearing = (forwardDirectBearing <= 0) ? 180 + forwardDirectBearing : -(180 - forwardDirectBearing) % 180.0;
}
// Create forward arc from node1 to node2
RouteArc arc = new RouteArc(roadDef, node1, node2, forwardInitialBearing, forwardDirectBearing, arcLength, arcLength, directLength, pointsHash);
arc.setForward();
node1.addArc(arc);
// Create the reverse arc
RouteArc reverseArc = new RouteArc(roadDef, node2, node1, reverseInitialBearing, reverseDirectBearing, arcLength, arcLength, directLength, pointsHash);
node2.addArc(reverseArc);
// link the two arcs
arc.setReverseArc(reverseArc);
reverseArc.setReverseArc(arc);
} else {
// This is the first node in the road
roadDef.setNode(getOrAddNode(id, co));
}
lastCoord = (CoordNode) co;
lastIndex = index;
arcLength = 0;
pointsHash = co.hashCode();
}
if (roadDef.hasHouseNumbers()) {
// we ignore number nodes when we have no house numbers
if (numCoordNodes < numNumberNodes)
hasInternalNodes = true;
roadDef.setNumNodes(numNumberNodes);
roadDef.setNod2BitSet(nodeFlags);
} else {
roadDef.setNumNodes(numCoordNodes);
}
if (hasInternalNodes)
roadDef.setInternalNodes(true);
roadDef.setLength(roadLength);
}
Aggregations