All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.graphhopper.api.GoogleMatrixSyncRequester Maven / Gradle / Ivy

There is a newer version: 0.8.2.1
Show newest version
package com.graphhopper.api;

import com.graphhopper.util.Helper;
import com.graphhopper.util.shapes.GHPoint;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import org.json.JSONArray;
import org.json.JSONObject;

/**
 *
 * @author Peter Karich
 */
public class GoogleMatrixSyncRequester extends GHMatrixAbstractRequester {

    private final Set ignoreSet = new HashSet(10);

    public GoogleMatrixSyncRequester() {
        super();
    }

    public GoogleMatrixSyncRequester(String serviceUrl) {
        super(serviceUrl);

        ignoreSet.add("mode");
        ignoreSet.add("key");
        ignoreSet.add("units");
        ignoreSet.add("destinations");
        ignoreSet.add("origins");
        ignoreSet.add("mode");
    }

    @Override
    public MatrixResponse route(GHMRequest ghRequest, String key) {
        String pointsStr;

        pointsStr = createGoogleQuery(ghRequest.getFromPoints(), "origins");
        pointsStr += "&" + createGoogleQuery(ghRequest.getToPoints(), "destinations");

        List outArraysList = new ArrayList<>(ghRequest.getOutArrays());
        if (outArraysList.isEmpty()) {
            // different default as google does not support weights
            outArraysList.add("distances");
            outArraysList.add("times");
        }

        // do not do the mapping here!
        // bicycling -> bike, car -> car, walking -> foot
        //
        // allow per request service URLs
        String tmpServiceURL = ghRequest.getHints().get("service_url", serviceUrl);
        String url = tmpServiceURL;
        if (!url.contains("?")) {
            url += "?";
        }
        url += pointsStr + "&mode=" + ghRequest.getVehicle();

        if (!Helper.isEmpty(key)) {
            url += "&key=" + key;
        }

        for (Entry entry : ghRequest.getHints().toMap().entrySet()) {
            if (ignoreSet.contains(entry.getKey())) {
                continue;
            }

            url += "&" + entry.getKey() + "=" + encode(entry.getValue());
        }

        boolean withTimes = outArraysList.contains("times");
        boolean withDistances = outArraysList.contains("distances");
        boolean withWeights = outArraysList.contains("weights");
        if (withWeights) {
            throw new UnsupportedOperationException("Google Matrix API does not include weights");
        }

        MatrixResponse matrixResponse = new MatrixResponse(
                ghRequest.getFromPoints().size(),
                ghRequest.getToPoints().size(), withTimes, withDistances, false);

        try {
            String str = getJson(url);
            JSONObject getResponseJson = null;
            try {
                getResponseJson = new JSONObject(str);
            } catch (Exception ex) {
                throw new RuntimeException("Cannot parse json " + str + " from " + url);
            }

            fillResponseFromGoogleJson(matrixResponse, getResponseJson);

        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }

        return matrixResponse;
    }

    private String createGoogleQuery(List list, String pointName) {
        String pointsStr = "";
        for (GHPoint p : list) {
            if (!pointsStr.isEmpty()) {
                pointsStr += "|";
            }

            pointsStr += encode(p.lat + "," + p.lon);
        }
        return pointName + "=" + pointsStr;
    }

    public String encode(String str) {
        try {
            return URLEncoder.encode(str, "UTF-8");
        } catch (Exception ex) {
            return str;
        }
    }

    private void fillResponseFromGoogleJson(MatrixResponse matrixResponse, JSONObject responseJson) {
        JSONArray rows = responseJson.getJSONArray("rows");
        int fromCount = rows.length();

        for (int fromIndex = 0; fromIndex < fromCount; fromIndex++) {
            JSONObject elementsObj = rows.getJSONObject(fromIndex);
            JSONArray elements = elementsObj.getJSONArray("elements");
            int toCount = elements.length();
            long[] times = new long[toCount];
            int[] distances = new int[toCount];

            for (int toIndex = 0; toIndex < toCount; toIndex++) {
                JSONObject element = elements.getJSONObject(toIndex);

                if ("OK".equals(element.getString("status"))) {

                    JSONObject distance = element.getJSONObject("distance");
                    JSONObject duration = element.getJSONObject("duration");

                    times[toIndex] = duration.getInt("value") * 1000;
                    distances[toIndex] = (int) Math.round(distance.getInt("value"));
                } else {
                    matrixResponse.addError(new IllegalArgumentException("Cannot find route " + fromIndex + "->" + toIndex));
                }
            }

            matrixResponse.setTimeRow(fromIndex, times);
            matrixResponse.setDistanceRow(fromIndex, distances);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy