Search in sources :

Example 16 with Coord

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);
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord)

Example 17 with Coord

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());
    }
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) Relation(uk.me.parabola.mkgmap.reader.osm.Relation) Entry(java.util.Map.Entry) SyntaxException(uk.me.parabola.mkgmap.scan.SyntaxException) Way(uk.me.parabola.mkgmap.reader.osm.Way)

Example 18 with Coord

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;
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) ArrayList(java.util.ArrayList)

Example 19 with Coord

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;
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord)

Example 20 with Coord

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;
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

Coord (uk.me.parabola.imgfmt.app.Coord)178 ArrayList (java.util.ArrayList)71 Way (uk.me.parabola.mkgmap.reader.osm.Way)31 MapPoint (uk.me.parabola.mkgmap.general.MapPoint)27 List (java.util.List)23 MapLine (uk.me.parabola.mkgmap.general.MapLine)16 Area (uk.me.parabola.imgfmt.app.Area)15 MapShape (uk.me.parabola.mkgmap.general.MapShape)15 CoordNode (uk.me.parabola.imgfmt.app.CoordNode)13 MapExitPoint (uk.me.parabola.mkgmap.general.MapExitPoint)13 Node (uk.me.parabola.mkgmap.reader.osm.Node)13 HashMap (java.util.HashMap)12 IdentityHashMap (java.util.IdentityHashMap)11 Test (org.junit.Test)11 MapRoad (uk.me.parabola.mkgmap.general.MapRoad)9 Long2ObjectOpenHashMap (it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap)8 Area (java.awt.geom.Area)8 HashSet (java.util.HashSet)8 IntArrayList (it.unimi.dsi.fastutil.ints.IntArrayList)5 LinkedHashMap (java.util.LinkedHashMap)5