Search in sources :

Example 6 with Coord

use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.

the class StyledConverter method setHighwayCounts.

/**
 * Increment the highway counter for each coord of each road.
 * As a result, all road junctions have a count > 1.
 */
private void setHighwayCounts() {
    log.info("Maintaining highway counters");
    long lastId = 0;
    List<Way> dupIdHighways = new ArrayList<>();
    for (ConvertedWay cw : roads) {
        if (!cw.isValid())
            continue;
        Way way = cw.getWay();
        if (way.getId() == lastId) {
            log.debug("Road with identical id:", way.getId());
            dupIdHighways.add(way);
            continue;
        }
        lastId = way.getId();
        List<Coord> points = way.getPoints();
        for (Coord p : points) {
            p.incHighwayCount();
        }
    }
    for (Way way : dupIdHighways) {
        List<Coord> points = way.getPoints();
        // increase the highway counter of the first and last point
        points.get(0).incHighwayCount();
        points.get(points.size() - 1).incHighwayCount();
        // for all other points increase the counter only if other roads are connected
        for (int i = 1; i < points.size() - 1; i++) {
            Coord p = points.get(i);
            if (p.getHighwayCount() > 1) {
                // this is a crossroads - mark that the duplicated way is also part of it
                p.incHighwayCount();
            }
        }
    }
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) ArrayList(java.util.ArrayList) Way(uk.me.parabola.mkgmap.reader.osm.Way) MapPoint(uk.me.parabola.mkgmap.general.MapPoint) MapExitPoint(uk.me.parabola.mkgmap.general.MapExitPoint)

Example 7 with Coord

use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.

the class StyledConverter method checkRoundabout.

/**
 * Check if roundabout has correct direction. Set driveOnRight or
 * driveOnLeft is not yet set.
 */
private void checkRoundabout(ConvertedWay cw) {
    if (cw.isRoundabout() == false)
        return;
    Way way = cw.getWay();
    List<Coord> points = way.getPoints();
    // check", check its direction
    if (checkRoundabouts && points.size() > 2 && !way.tagIsLikeYes("mkgmap:no-dir-check") && !way.tagIsLikeNo("mkgmap:dir-check")) {
        Coord centre = way.getCofG();
        int dir = 0;
        // check every third segment
        for (int i = 0; (i + 1) < points.size(); i += 3) {
            Coord pi = points.get(i);
            Coord pi1 = points.get(i + 1);
            // don't check segments that are very short
            if (pi.distance(centre) > 2.5 && pi.distance(pi1) > 2.5) {
                // determine bearing from segment that starts with
                // point i to centre of roundabout
                double a = pi.bearingTo(pi1);
                double b = pi.bearingTo(centre) - a;
                while (b > 180) b -= 360;
                while (b < -180) b += 360;
                // degrees consider it trustworthy
                if (b >= 15 && b < 165)
                    ++dir;
                else if (b <= -15 && b > -165)
                    --dir;
            }
        }
        if (dir == 0)
            log.info("Roundabout segment " + way.getId() + " direction unknown (see " + points.get(0).toOSMURL() + ")");
        else {
            boolean clockwise = dir > 0;
            if (points.get(0) == points.get(points.size() - 1)) {
                // roundabout is a loop
                if (driveOnLeft == true && !clockwise || driveOnLeft == false && clockwise) {
                    log.warn("Roundabout " + way.getId() + " direction is wrong - reversing it (see " + centre.toOSMURL() + ")");
                    way.reverse();
                }
            } else if (driveOnLeft == true && !clockwise || driveOnLeft == false && clockwise) {
                // roundabout is a line
                log.warn("Roundabout segment " + way.getId() + " direction looks wrong (see " + points.get(0).toOSMURL() + ")");
            }
        }
    }
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord) Way(uk.me.parabola.mkgmap.reader.osm.Way) MapPoint(uk.me.parabola.mkgmap.general.MapPoint) MapExitPoint(uk.me.parabola.mkgmap.general.MapExitPoint)

Example 8 with Coord

use of uk.me.parabola.imgfmt.app.Coord 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));
}
Also used : MapLine(uk.me.parabola.mkgmap.general.MapLine) ArrayList(java.util.ArrayList) MapRoad(uk.me.parabola.mkgmap.general.MapRoad) Way(uk.me.parabola.mkgmap.reader.osm.Way) MapPoint(uk.me.parabola.mkgmap.general.MapPoint) MapExitPoint(uk.me.parabola.mkgmap.general.MapExitPoint) Coord(uk.me.parabola.imgfmt.app.Coord) RestrictionRelation(uk.me.parabola.mkgmap.reader.osm.RestrictionRelation) CoordPOI(uk.me.parabola.mkgmap.reader.osm.CoordPOI) CoordNode(uk.me.parabola.imgfmt.app.CoordNode)

Example 9 with Coord

use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.

the class WrongAngleFixer method removeWrongAngles.

/**
 * Find wrong angles caused by rounding to map units. Try to fix them by
 * moving, removing or merging points.
 * @param roads list with routable ways or null, if lines should be optimized
 * @param lines list with non-routable ways
 * @param modifiedRoads map of modified routable ways (modified by this routine)
 * @param deletedRoads set of ids of deleted routable ways (modified by this routine)
 * @param restrictions Map with restriction relations. The restriction relations may be modified by this routine
 */
private void removeWrongAngles(List<ConvertedWay> roads, List<ConvertedWay> lines, HashMap<Long, ConvertedWay> modifiedRoads, HashSet<Long> deletedRoads, List<RestrictionRelation> restrictions) {
    // replacements maps those nodes that have been replaced to
    // the node that replaces them
    Map<Coord, Coord> replacements = new IdentityHashMap<>();
    final HashSet<Coord> changedPlaces = new HashSet<>();
    int numNodesMerged = 0;
    HashSet<Way> waysWithBearingErrors = new HashSet<>();
    HashSet<Long> waysThatMapToOnePoint = new HashSet<>();
    Way lastWay = null;
    List<ConvertedWay> convertedWays = (roads != null) ? roads : lines;
    boolean anotherPassRequired = true;
    for (pass = 1; pass < 20; pass++) {
        if (!anotherPassRequired && !extraPass)
            break;
        anotherPassRequired = false;
        log.info("Removing wrong angles - PASS", pass);
        writeOSM(((mode == MODE_LINES) ? "lines" : "roads") + "_pass_" + pass, convertedWays);
        // Step 1: detect points which are parts of line segments with wrong bearings
        lastWay = null;
        for (ConvertedWay cw : convertedWays) {
            if (!cw.isValid() || cw.isOverlay())
                continue;
            Way way = cw.getWay();
            if (way.equals(lastWay))
                continue;
            if (pass != 1 && waysWithBearingErrors.contains(way) == false)
                continue;
            lastWay = way;
            List<Coord> points = way.getPoints();
            // scan through the way's points looking for line segments with big
            // bearing errors
            Coord prev = null;
            if (points.get(0) == points.get(points.size() - 1) && points.size() >= 2)
                prev = points.get(points.size() - 2);
            boolean hasNonEqualPoints = false;
            for (int i = 0; i < points.size(); ++i) {
                Coord p = points.get(i);
                if (pass == 1)
                    p.setRemove(false);
                p = getReplacement(p, way, replacements);
                if (i == 0 || i == points.size() - 1) {
                    p.setEndOfWay(true);
                }
                if (prev != null) {
                    if (pass == 1 && p.equals(prev) == false)
                        hasNonEqualPoints = true;
                    double err = calcBearingError(p, prev);
                    if (err >= MAX_BEARING_ERROR) {
                        // bearing error is big
                        p.setPartOfBadAngle(true);
                        prev.setPartOfBadAngle(true);
                    }
                }
                prev = p;
            }
            if (pass == 1 && hasNonEqualPoints == false) {
                waysThatMapToOnePoint.add(way.getId());
                log.info("all points of way", way.toBrowseURL(), "are rounded to equal map units");
            }
        }
        // Step 2: collect the line segments that are connected to critical points
        IdentityHashMap<Coord, CenterOfAngle> centerMap = new IdentityHashMap<>();
        // needed for ordered processing
        List<CenterOfAngle> centers = new ArrayList<>();
        Map<Coord, Set<Way>> overlaps = new HashMap<>();
        lastWay = null;
        for (ConvertedWay cw : convertedWays) {
            if (!cw.isValid() || cw.isOverlay())
                continue;
            Way way = cw.getWay();
            if (way.equals(lastWay))
                continue;
            if (pass != 1 && waysWithBearingErrors.contains(way) == false)
                continue;
            lastWay = way;
            boolean wayHasSpecialPoints = false;
            List<Coord> points = way.getPoints();
            // scan through the way's points looking for line segments with big
            // bearing errors
            Coord prev = null;
            if (points.get(0) == points.get(points.size() - 1) && points.size() >= 2)
                prev = points.get(points.size() - 2);
            for (int i = 0; i < points.size(); ++i) {
                Coord p = points.get(i);
                if (prev != null) {
                    if (p == prev) {
                        points.remove(i);
                        --i;
                        if (mode == MODE_ROADS)
                            modifiedRoads.put(way.getId(), cw);
                        continue;
                    }
                    if (p.isPartOfBadAngle() || prev.isPartOfBadAngle()) {
                        wayHasSpecialPoints = true;
                        // save both points with their neighbour
                        Coord p1 = prev;
                        Coord p2 = p;
                        CenterOfAngle coa1 = getOrCreateCenter(p, way, centerMap, centers, overlaps);
                        CenterOfAngle coa2 = getOrCreateCenter(prev, way, centerMap, centers, overlaps);
                        coa1.addNeighbour(coa2);
                        coa2.addNeighbour(coa1);
                        if (points.size() == 2) {
                            // way has only two points, don't merge them
                            coa1.addBadMergeCandidate(coa2);
                        }
                        if (mode == MODE_ROADS) {
                            if (p1.getHighwayCount() >= 2 && p2.getHighwayCount() >= 2) {
                                if (cw.isRoundabout()) {
                                    // avoid to merge exits of roundabouts
                                    coa1.addBadMergeCandidate(coa2);
                                }
                            }
                        }
                    }
                }
                prev = p;
            }
            if (pass == 1 && wayHasSpecialPoints)
                waysWithBearingErrors.add(way);
        }
        markOverlaps(overlaps, centers);
        overlaps.clear();
        // Step 3: Update list of ways with bearing errors or points next to them
        lastWay = null;
        for (ConvertedWay cw : convertedWays) {
            if (!cw.isValid() || cw.isOverlay())
                continue;
            Way way = cw.getWay();
            if (way.equals(lastWay))
                continue;
            lastWay = way;
            if (waysWithBearingErrors.contains(way))
                continue;
            List<Coord> points = way.getPoints();
            // bearing errors
            for (Coord p : points) {
                if (p.getHighwayCount() < 2)
                    continue;
                if (centerMap.containsKey(p)) {
                    waysWithBearingErrors.add(way);
                    break;
                }
            }
        }
        log.info("pass " + pass + ": analysing " + centers.size() + " points with bearing problems.");
        // Return to GC
        centerMap = null;
        // Step 4: try to correct the errors
        List<CenterOfAngle> checkAgainList = null;
        boolean tryMerge = false;
        while (true) {
            checkAgainList = new ArrayList<>();
            for (CenterOfAngle coa : centers) {
                // reset flag for next pass
                coa.center.setPartOfBadAngle(false);
                if (coa.getCurrentLocation(replacements) == null)
                    // removed center
                    continue;
                if (coa.isOK(replacements) == false) {
                    boolean changed = coa.tryChange(replacements, tryMerge);
                    if (changed) {
                        if (DEBUG_PATH != null)
                            changedPlaces.add(coa.center);
                        continue;
                    }
                    checkAgainList.add(coa);
                }
            }
            if (tryMerge)
                // leave when 2nd pass finished
                break;
            tryMerge = true;
            centers = checkAgainList;
        }
        // Step 5: apply the calculated corrections to the ways
        lastWay = null;
        boolean lastWayModified = false;
        ConvertedWay lastConvertedWay = null;
        for (ConvertedWay cw : convertedWays) {
            if (!cw.isValid() || cw.isOverlay())
                continue;
            Way way = cw.getWay();
            if (waysWithBearingErrors.contains(way) == false)
                continue;
            List<Coord> points = way.getPoints();
            if (way.equals(lastWay)) {
                if (lastWayModified) {
                    points.clear();
                    points.addAll(lastWay.getPoints());
                    if (cw.isReversed() != lastConvertedWay.isReversed())
                        Collections.reverse(points);
                }
                continue;
            }
            lastWay = way;
            lastConvertedWay = cw;
            lastWayModified = false;
            // loop backwards because we may delete points
            for (int i = points.size() - 1; i >= 0; i--) {
                Coord p = points.get(i);
                if (p.isToRemove()) {
                    points.remove(i);
                    anotherPassRequired = true;
                    lastWayModified = true;
                    if (i > 0 && i < points.size()) {
                        // special case: handle micro loop
                        if (points.get(i - 1) == points.get(i))
                            points.remove(i);
                    }
                    continue;
                }
                // check if this point is to be replaced because
                // it was previously moved
                Coord replacement = getReplacement(p, way, replacements);
                if (p == replacement)
                    continue;
                if (p.isViaNodeOfRestriction()) {
                    // make sure that we find the restriction with the new coord instance
                    replacement.setViaNodeOfRestriction(true);
                    p.setViaNodeOfRestriction(false);
                }
                p = replacement;
                // replace point in way
                points.set(i, p);
                if (p.getHighwayCount() >= 2)
                    numNodesMerged++;
                lastWayModified = true;
                if (i + 1 < points.size() && points.get(i + 1) == p) {
                    points.remove(i);
                    anotherPassRequired = true;
                }
                if (i - 1 >= 0 && points.get(i - 1) == p) {
                    points.remove(i);
                    anotherPassRequired = true;
                }
            }
            if (lastWayModified && mode == MODE_ROADS) {
                modifiedRoads.put(way.getId(), cw);
            }
        }
        if (extraPass) {
            anotherPassRequired = false;
            break;
        } else {
            if (!anotherPassRequired) {
                // check if we have centres on different ways that overlap
                for (CenterOfAngle coa : centers) {
                    if (coa.forceChange) {
                        anotherPassRequired = true;
                        extraPass = true;
                        break;
                    }
                }
            }
        }
    }
    // finish: remove remaining duplicate points
    int numWaysDeleted = 0;
    lastWay = null;
    boolean lastWayModified = false;
    ConvertedWay lastConvertedWay = null;
    for (ConvertedWay cw : convertedWays) {
        if (cw.isOverlay())
            continue;
        Way way = cw.getWay();
        List<Coord> points = way.getPoints();
        if (points.size() < 2) {
            if (log.isInfoEnabled())
                log.info("  Way " + way.getTag("name") + " (" + way.toBrowseURL() + ") has less than 2 points - deleting it");
            if (mode == MODE_LINES && waysThatMapToOnePoint.contains(way.getId()) == false)
                log.warn("non-routable way ", way.getId(), "was removed");
            if (mode == MODE_ROADS)
                deletedRoads.add(way.getId());
            ++numWaysDeleted;
            continue;
        }
        if (way.equals(lastWay)) {
            if (lastWayModified) {
                points.clear();
                points.addAll(lastWay.getPoints());
                if (cw.isReversed() != lastConvertedWay.isReversed())
                    Collections.reverse(points);
            }
            continue;
        }
        lastWay = way;
        lastConvertedWay = cw;
        lastWayModified = false;
        Coord prev = points.get(points.size() - 1);
        // loop backwards because we may delete points
        for (int i = points.size() - 2; i >= 0; i--) {
            Coord p = points.get(i);
            if (p == prev) {
                points.remove(i);
                lastWayModified = true;
            }
            // if (p.equals(prev) && (p.getHighwayCount() < 2 || prev.getHighwayCount() < 2)){
            // // not an error, but should not happen
            // log.warn("way " + way.getId() + " still has consecutive equal points at " + p.toOSMURL());
            // }
            prev = p;
        }
    }
    if (mode == MODE_ROADS) {
        // points in roads
        for (ConvertedWay cw : lines) {
            if (!cw.isValid() || cw.isOverlay())
                continue;
            Way way = cw.getWay();
            List<Coord> points = way.getPoints();
            int n = points.size();
            boolean hasReplacedPoints = false;
            for (int i = 0; i < n; i++) {
                Coord p = points.get(i);
                if (p.isReplaced()) {
                    hasReplacedPoints = true;
                    points.set(i, getReplacement(p, null, replacements));
                }
            }
            if (hasReplacedPoints && DEBUG_PATH != null) {
                GpxCreator.createGpx(Utils.joinPath(DEBUG_PATH, way.getId() + "_mod_non_routable"), points);
            }
        }
        for (RestrictionRelation rr : restrictions) {
            for (Coord p : rr.getViaCoords()) {
                Coord replacement = getReplacement(p, null, replacements);
                if (p != replacement) {
                    rr.replaceViaCoord(p, replacement);
                }
            }
        }
    }
    if (DEBUG_PATH != null) {
        GpxCreator.createGpx(Utils.joinPath(DEBUG_PATH, (mode == MODE_ROADS ? "roads_" : "lines_") + "solved_badAngles"), bbox.toCoords(), new ArrayList<>(changedPlaces));
    }
    if (anotherPassRequired)
        log.error("Removing wrong angles - didn't finish in " + pass + " passes, giving up!");
    else
        log.info("Removing wrong angles - finished in", pass, "passes (", numNodesMerged, "nodes merged,", numWaysDeleted, "ways deleted)");
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) Long2ObjectOpenHashMap(it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap) IdentityHashMap(java.util.IdentityHashMap) ArrayList(java.util.ArrayList) Way(uk.me.parabola.mkgmap.reader.osm.Way) Coord(uk.me.parabola.imgfmt.app.Coord) RestrictionRelation(uk.me.parabola.mkgmap.reader.osm.RestrictionRelation) HashSet(java.util.HashSet)

Example 10 with Coord

use of uk.me.parabola.imgfmt.app.Coord in project mkgmap by openstreetmap.

the class WrongAngleFixer method calcMaxErrorDistance.

/**
 * Calculate the rounding error tolerance for a given point.
 * The latitude error may be max higher. Maybe this should be
 * @param p0
 * @return
 */
private static double calcMaxErrorDistance(Coord p0) {
    Coord test = new Coord(p0.getLatitude(), p0.getLongitude() + 1);
    double lonErr = p0.getDisplayedCoord().distance(test) / 2;
    return lonErr;
}
Also used : Coord(uk.me.parabola.imgfmt.app.Coord)

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