use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class RoadMerger method mergeRoads.
/**
* Merges {@code road2} into {@code road1}. This means that
* only the way id and the tags of {@code road1} is kept.
* For the tag it should not matter because all tags used after the
* RoadMerger are compared to be the same.
*
* @param road1 first road (will keep the merged road)
* @param road2 second road
*/
private void mergeRoads(ConvertedWay road1, ConvertedWay road2) {
// Removes the second line,
// Merges the points in the first one
List<Coord> points1 = road1.getWay().getPoints();
List<Coord> points2 = road2.getWay().getPoints();
Coord mergePoint = points2.get(0);
Coord endPoint = points2.get(points2.size() - 1);
startPoints.removeMapping(mergePoint, road2);
endPoints.removeMapping(endPoint, road2);
endPoints.removeMapping(mergePoint, road1);
points1.addAll(points2.subList(1, points2.size()));
endPoints.add(endPoint, road1);
// merge the POI info
String wayPOI2 = road2.getWay().getTag(StyledConverter.WAY_POI_NODE_IDS);
if (wayPOI2 != null) {
String WayPOI1 = road1.getWay().getTag(StyledConverter.WAY_POI_NODE_IDS);
if (wayPOI2.equals(WayPOI1) == false) {
if (WayPOI1 == null)
WayPOI1 = "";
// store combination of both ways. This might contain
// duplicates, but that is not a problem.
road1.getWay().addTag(StyledConverter.WAY_POI_NODE_IDS, WayPOI1 + wayPOI2);
}
}
// // the mergePoint is now used by one highway less
mergePoint.decHighwayCount();
// road2 is removed - it must not be part of a restriction
assert (restrictions.get(endPoint).contains(road2.getWay().getId()) == false);
}
use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class LengthFunction method calcLength.
private double calcLength(Element el) {
if (el instanceof Way) {
Way w = (Way) el;
double length = 0;
Coord prevC = null;
for (Coord c : w.getPoints()) {
if (prevC != null) {
length += prevC.distance(c);
}
prevC = c;
}
return length;
} else if (el instanceof Relation) {
Relation rel = (Relation) el;
double length = 0;
for (Entry<String, Element> relElem : rel.getElements()) {
if (relElem.getValue() instanceof Way || relElem.getValue() instanceof Relation) {
if (rel == relElem.getValue()) {
// avoid recursive call
log.error("Relation " + rel.getId() + " contains itself as element. This is not supported.");
} else {
length += calcLength(relElem.getValue());
}
}
}
return length;
} else {
throw new SyntaxException("length() cannot calculate elements of type " + el.getClass().getName());
}
}
use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class ExtNumbers method rasterLineNearPoint3.
/**
* Use Bresemham algorithm to get the Garmin points which are close to the line
* described by c1 and c2 and the point p.
* @param c1
* @param c2
* @param p
* @return the list of points
*/
public static List<Coord> rasterLineNearPoint3(Coord c1, Coord c2, double maxDistToLine) {
int x0 = c1.getLongitude();
int y0 = c1.getLatitude();
int x1 = c2.getLongitude();
int y1 = c2.getLatitude();
Coord c1Dspl = c1.getDisplayedCoord();
Coord c2Dspl = c2.getDisplayedCoord();
int x = x0, y = y0;
int dx = Math.abs(x1 - x), sx = x < x1 ? 1 : -1;
int dy = -Math.abs(y1 - y), sy = y < y1 ? 1 : -1;
int err = dx + dy, e2;
/* error value e_xy */
List<Coord> rendered = new ArrayList<>();
for (; ; ) {
/* loop */
Coord t = new Coord(y, x);
double distLine = t.distToLineSegment(c1Dspl, c2Dspl);
if (distLine <= maxDistToLine)
rendered.add(t);
if (x == x1 && y == y1)
break;
e2 = 2 * err;
if (e2 > dy) {
err += dy;
x += sx;
}
/* e_xy+e_x > 0 */
if (e2 < dx) {
err += dx;
y += sy;
}
/* e_xy+e_y < 0 */
}
return rendered;
}
use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class ExtNumbers method rasterLineNearPoint.
/**
* Use Bresenham algorithm to get the Garmin points which are close to the line
* described by c1 and c2 and the point p.
* @param c1
* @param c2
* @param p
* @return point with smallest perpendicular distance to line
*/
public static Coord rasterLineNearPoint(Coord c1, Coord c2, Coord p, boolean includeEndPoints) {
int x0 = c1.getLongitude();
int y0 = c1.getLatitude();
int x1 = c2.getLongitude();
int y1 = c2.getLatitude();
Coord c1Dspl = c1.getDisplayedCoord();
Coord c2Dspl = c2.getDisplayedCoord();
int x = x0, y = y0;
int dx = Math.abs(x1 - x), sx = x < x1 ? 1 : -1;
int dy = -Math.abs(y1 - y), sy = y < y1 ? 1 : -1;
int err = dx + dy, e2;
/* error value e_xy */
double minDistLine = Double.MAX_VALUE;
double minDistTarget = Double.MAX_VALUE;
int bestX = Integer.MAX_VALUE, bestY = Integer.MAX_VALUE;
for (; ; ) {
/* loop */
if (!includeEndPoints && x == x1 && y == y1)
break;
if (Math.abs(y - p.getLatitude()) <= 1 || Math.abs(x - p.getLongitude()) <= 1) {
Coord t = new Coord(y, x);
double distToTarget = t.distance(p);
if (includeEndPoints || x != x0 || y != y0) {
if (distToTarget < 10) {
double distLine = t.distToLineSegment(c1Dspl, c2Dspl);
if (distLine < minDistLine || distLine == minDistLine && distToTarget < minDistTarget || distLine < 0.2 && distToTarget < minDistTarget) {
bestX = x;
bestY = y;
minDistLine = distLine;
minDistTarget = distToTarget;
}
}
}
}
if (x == x1 && y == y1)
break;
e2 = 2 * err;
if (e2 > dy) {
err += dy;
x += sx;
}
/* e_xy+e_x > 0 */
if (e2 < dx) {
err += dx;
y += sy;
}
/* e_xy+e_y < 0 */
}
if (minDistLine == Double.MAX_VALUE)
return null;
Coord best = new Coord(bestY, bestX);
return best;
}
use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.
the class ExtNumbers method dupNode.
/**
* Duplicate a node in the road. This creates a zero-length segment.
* We can add house numbers to this segment and the position in the
* address search will be the same for all of them.
* @param fraction a value below 0.5 means duplicate the start node, others
* duplicate the end node
* @return the new chain with two segments
*/
private ExtNumbers dupNode(double fraction, int reason) {
log.info("duplicating number node in road", getRoad(), getNumbers(), getHouses(Numbers.LEFT), getHouses(Numbers.RIGHT));
boolean atStart = (fraction <= 0.5);
// add a copy of an existing node
int index = (atStart) ? startInRoad : endInRoad;
int splitSegment = (atStart) ? startInRoad + 1 : endInRoad;
Coord closePoint = getRoad().getPoints().get(index);
Coord toAdd = new Coord(closePoint);
toAdd.setOnBoundary(closePoint.getOnBoundary());
toAdd.incHighwayCount();
// we have to make sure that the road starts and ends with a CoordNode!
this.endInRoad = addAsNumberNode(splitSegment, toAdd);
// distribute the houses to the new intervals
List<ArrayList<HousenumberMatch>> leftTargets = Arrays.asList(new ArrayList<HousenumberMatch>(), new ArrayList<HousenumberMatch>());
List<ArrayList<HousenumberMatch>> rightTargets = Arrays.asList(new ArrayList<HousenumberMatch>(), new ArrayList<HousenumberMatch>());
int target;
if (reason == SR_SPLIT_ROAD_END || reason == SR_OPT_LEN) {
for (int side = 0; side < 2; side++) {
boolean left = side == 0;
List<ArrayList<HousenumberMatch>> targets = left ? leftTargets : rightTargets;
for (HousenumberMatch house : getHouses(left)) {
if (house.getSegmentFrac() < fraction)
target = 0;
else if (house.getSegmentFrac() > fraction)
target = 1;
else
target = (atStart) ? 0 : 1;
targets.get(target).add(house);
}
}
} else if (getHouses(Numbers.LEFT).size() > 1 || getHouses(Numbers.RIGHT).size() > 1) {
int start, end;
for (int side = 0; side < 2; side++) {
boolean left = side == 0;
if (getHouses(left).isEmpty())
continue;
start = getNumbers().getStart(left);
end = getNumbers().getEnd(left);
List<ArrayList<HousenumberMatch>> targets = left ? leftTargets : rightTargets;
if (start != end) {
int midNum = (start + end) / 2;
for (HousenumberMatch house : getHouses(left)) {
if (house.getHousenumber() < midNum)
target = 0;
else if (house.getHousenumber() > midNum)
target = 1;
else
target = (atStart) ? 0 : 1;
targets.get(target).add(house);
}
} else if (multipleZipOrCity(left) == false) {
if (atStart)
targets.get(1).addAll(getHouses(left));
else
targets.get(0).addAll(getHouses(left));
} else {
int mid = getHouses(left).size() / 2;
targets.get(0).addAll(getHouses(left).subList(0, mid));
targets.get(1).addAll(getHouses(left).subList(mid, getHouses(left).size()));
}
}
} else {
log.error("internal error, don't know how to split", this);
}
assert splitSegment != startInRoad && splitSegment != endInRoad;
// make sure that the numbers are assigned to the wanted segment
setSegment(startInRoad, leftTargets.get(0));
setSegment(startInRoad, rightTargets.get(0));
setSegment(splitSegment, leftTargets.get(1));
setSegment(splitSegment, rightTargets.get(1));
// don't use split() here, the numbers in this may not be properly
// sorted and we don't want to sort them
ExtNumbers en1 = divide();
ExtNumbers en2 = en1.next;
en1.setNumbers(leftTargets.get(0), startInRoad, splitSegment, true);
en1.setNumbers(rightTargets.get(0), startInRoad, splitSegment, false);
en2.setNumbers(leftTargets.get(1), splitSegment, endInRoad, true);
en2.setNumbers(rightTargets.get(1), splitSegment, endInRoad, false);
log.info("zero length interval added in street", getRoad(), getNumbers(), "==>", en1.getNumbers(), "+", en2.getNumbers());
if (atStart && !en1.hasNumbers() || !atStart && !en2.hasNumbers()) {
log.error("internal error, zero length interval has no numbers in road", getRoad());
}
return en1;
}
Aggregations