GraphHopper.com | Forum | GitHub | Maps | Blog

Original time of road in map matching


#1

After map matching and get the json
output, I found that the time of every road is compressed but not the original travel time. Could somebody tell me how to get the original time of every road. Thans a lot.


#2

This is actually a feature request: https://github.com/graphhopper/map-matching/issues/23 and the time information will be estimates until then


#3

Hi @karussell, hi @gourdeighth,

For now, before this feature comes, I do the following to map the snapped GPX entries to the route:
I create a list of the snapped GPX entries to reduce overall time complexity. Assuming the GPX entries are already time ordered (which is the case at the current master state), the mapping is then done in O(n):

    MatchResult mr = mapMatching.doWork(inputGPXEntries);

    // Create a list of successive snapped GPX entries (assume already time-ordered)
    LinkedList<GPXExtension> snappedGpxList = new LinkedList<>();
    mr.getEdgeMatches().forEach(m -> snappedGpxList.addAll(m.getGpxExtensions()));

    List<GPXEntry> route = new ArrayList<>();
    //  Sixth decimal place is worth up to 0.11m, see https://gis.stackexchange.com/a/8674
    final double snapEpsilon = 0.000001;

    // Loop through the merged path (contains GPX snapped and map locations)
    mr.getMergedPath().calcPoints().forEach(p -> {
        boolean isSnapped = false;

        // Check if current point has one or more snapped points
        ListIterator<GPXExtension> iter = snappedGpxList.listIterator();
        while (iter.hasNext()) {
            GPXExtension next = iter.next();
            GHPoint3D snapped = next.getQueryResult().getSnappedPoint();
            if (compareDouble(p.getLat(), snapped.getLat(), snapEpsilon)
                    && compareDouble(p.getLon(), snapped.getLon(), snapEpsilon)) {
                // Take time of snapped GPX entry
                route.add(new GPXEntry(p, next.getEntry().getTime()));
                isSnapped = true;
                iter.remove();
            } else {
                break;
            }
        }

        // No match found, take point with time 0
        if (!isSnapped) {
            route.add(new GPXEntry(p, 0));
        }
    });

For me this works quite well. One could additionally check if the list is empty at the end and do some additional handling in that case.
Feedback is welcome.