use of uk.me.parabola.mkgmap.general.MapRoad 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.general.MapRoad in project mkgmap by openstreetmap.
the class StyleTester method formatResults.
/**
* Print out the garmin elements that were produced by the rules.
* @param prefix This string will be prepended to the formatted result.
* @param lines The resulting map elements.
*/
private static List<String> formatResults(String prefix, List<MapElement> lines) {
List<String> result = new ArrayList<>();
int i = 0;
for (MapElement el : lines) {
String s;
// So we can run against versions that do not have toString() methods
if (el instanceof MapRoad)
s = roadToString((MapRoad) el);
else
s = lineToString((MapLine) el);
result.add(prefix + s);
}
return result;
}
use of uk.me.parabola.mkgmap.general.MapRoad in project mkgmap by openstreetmap.
the class ExtNumbers method getNumberList.
/**
* Return the intervals in the format used for the writer routines
* @return
*/
public List<Numbers> getNumberList() {
// do we have numbers?
boolean foundNumbers = false;
for (ExtNumbers curr = this; curr != null; curr = curr.next) {
if (curr.hasNumbers()) {
foundNumbers = true;
break;
}
}
if (!foundNumbers)
return null;
List<Numbers> list = new ArrayList<>();
boolean headerWasReported = false;
for (ExtNumbers curr = this; curr != null; curr = curr.next) {
if (curr.hasNumbers() == false)
continue;
list.add(curr.getNumbers());
if (log.isInfoEnabled()) {
if (headerWasReported == false) {
MapRoad road = curr.getRoad();
if (road.getStreet() == null && road.getName() == null)
log.info("final numbers for", road, curr.housenumberRoad.getName(), "in", road.getCity());
else
log.info("final numbers for", road, "in", road.getCity());
headerWasReported = true;
}
Numbers cn = curr.getNumbers();
log.info("Left: ", cn.getLeftNumberStyle(), cn.getIndex(), "Start:", cn.getLeftStart(), "End:", cn.getLeftEnd(), "numbers " + curr.getHouses(Numbers.LEFT));
log.info("Right:", cn.getRightNumberStyle(), cn.getIndex(), "Start:", cn.getRightStart(), "End:", cn.getRightEnd(), "numbers " + curr.getHouses(Numbers.RIGHT));
}
}
return list;
}
use of uk.me.parabola.mkgmap.general.MapRoad in project mkgmap by openstreetmap.
the class HousenumberGenerator method identifyServiceRoads.
/**
* process option --x-name-service-roads=n
* The program identifies unnamed roads which are only connected to one
* road with a name or to multiple roads with the same name. The process is
* repeated n times. If n > 1 the program will also use unnamed roads which
* are connected to unnamed roads if those are connected to named roads.
* Higher values for n mean deeper search, but reasonable values are
* probably between 1 and 5.
*
* These roads are then used for house number processing like the named
* ones. If house numbers are assigned to these roads, they are named so
* that address search will find them.
*/
private void identifyServiceRoads() {
Int2ObjectOpenHashMap<String> roadNamesByNodeIds = new Int2ObjectOpenHashMap<>();
HashMap<MapRoad, List<Coord>> coordNodesUnnamedRoads = new HashMap<>();
HashSet<Integer> unclearNodeIds = new HashSet<>();
long t1 = System.currentTimeMillis();
List<MapRoad> unnamedRoads = new ArrayList<>();
for (MapRoad road : allRoads) {
if (road.isSkipHousenumberProcessing())
continue;
if (road.getStreet() == null) {
// the road probably has a ref. We assume these are not service roads.
if (road.getName() == null) {
unnamedRoads.add(road);
List<Coord> nodes = new ArrayList<>();
for (Coord co : road.getPoints()) {
if (co.getId() != 0)
nodes.add(co);
}
coordNodesUnnamedRoads.put(road, nodes);
}
} else {
identifyNodes(road.getPoints(), road.getStreet(), roadNamesByNodeIds, unclearNodeIds);
}
}
int numUnnamedRoads = unnamedRoads.size();
long t2 = System.currentTimeMillis();
if (log.isDebugEnabled())
log.debug("identifyServiceRoad step 1 took", (t2 - t1), "ms, found", roadNamesByNodeIds.size(), "nodes to check and", numUnnamedRoads, "unnamed roads");
long t3 = System.currentTimeMillis();
int named = 0;
for (int pass = 1; pass <= nameSearchDepth; pass++) {
int unnamed = 0;
List<MapRoad> namedRoads = new ArrayList<>();
for (int j = 0; j < unnamedRoads.size(); j++) {
MapRoad road = unnamedRoads.get(j);
if (road == null)
continue;
unnamed++;
List<Coord> coordNodes = coordNodesUnnamedRoads.get(road);
String name = null;
for (Coord co : coordNodes) {
if (unclearNodeIds.contains(co.getId())) {
name = null;
// don't process again
unnamedRoads.set(j, null);
break;
}
String possibleName = roadNamesByNodeIds.get(co.getId());
if (possibleName == null)
continue;
if (name == null)
name = possibleName;
else if (name.equals(possibleName) == false) {
name = null;
// don't process again
unnamedRoads.set(j, null);
break;
}
}
if (name != null) {
named++;
road.setStreet(name);
namedRoads.add(road);
// don't process again
unnamedRoads.set(j, null);
}
}
for (MapRoad road : namedRoads) {
road.setNamedByHousenumberProcessing(true);
String name = road.getStreet();
if (log.isDebugEnabled())
log.debug("pass", pass, "using unnamed road for housenumber processing,id=", road.getRoadDef().getId(), ":", name);
List<Coord> coordNodes = coordNodesUnnamedRoads.get(road);
identifyNodes(coordNodes, name, roadNamesByNodeIds, unclearNodeIds);
}
if (namedRoads.isEmpty())
break;
if (log.isDebugEnabled())
log.debug("pass", pass, unnamed, named);
}
long t4 = System.currentTimeMillis();
if (log.isDebugEnabled()) {
log.debug("indentifyServiceRoad step 2 took", (t4 - t3), "ms, found a name for", named, "of", numUnnamedRoads, "roads");
}
return;
}
use of uk.me.parabola.mkgmap.general.MapRoad in project mkgmap by openstreetmap.
the class HousenumberGenerator method findClosestRoadSegment.
/**
* Fill/overwrite the fields in house which depend on the assigned road.
*/
public static void findClosestRoadSegment(HousenumberMatch house, MapRoad r, int firstSeg, int stopSeg) {
Coord cx = house.getLocation();
double oldDist = house.getDistance();
MapRoad oldRoad = house.getRoad();
house.setRoad(null);
house.setDistance(Double.POSITIVE_INFINITY);
boolean foundGroupLink = false;
int end = Math.min(r.getPoints().size(), stopSeg + 1);
for (int node = firstSeg; node + 1 < end; node++) {
Coord c1 = r.getPoints().get(node);
Coord c2 = r.getPoints().get(node + 1);
double frac = getFrac(c1, c2, cx);
double dist = distanceToSegment(c1, c2, cx, frac);
if (house.getGroup() != null && house.getGroup().linkNode == c1) {
if (c1.highPrecEquals(c2) == false) {
log.debug("block doesn't have zero length segment! Road:", r, house);
}
foundGroupLink = true;
house.setDistance(dist);
house.setSegmentFrac(frac);
house.setRoad(r);
house.setSegment(node);
break;
} else if (dist < house.getDistance()) {
house.setDistance(dist);
house.setSegmentFrac(frac);
house.setRoad(r);
house.setSegment(node);
}
}
if (house.getGroup() != null && house.getGroup().linkNode != null && foundGroupLink == false) {
log.debug(r, house, "has a group but the link was not found, should only happen after split of zero-length-segment");
}
if (oldRoad == r) {
if (house.getDistance() > MAX_DISTANCE_TO_ROAD + 2.5 && oldDist <= MAX_DISTANCE_TO_ROAD) {
log.warn("line distorted? Road segment was moved by more than", String.format("%.2f m", 2.5), ", from address", r, house.getSign());
}
}
}
Aggregations