/* * Licensed to GraphHopper GmbH under one or more contributor * license agreements. See the NOTICE file distributed with this work for * additional information regarding copyright ownership. * * GraphHopper GmbH licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.graphhopper; import com.graphhopper.util.InstructionList; import com.graphhopper.util.PointList; import com.graphhopper.util.shapes.BBox; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * This class holds the data like points and instructions of a Path. * <p> * * @author Peter Karich */ public class PathWrapper { private final List<Throwable> errors = new ArrayList<Throwable>(4); private List<String> description; private double distance; private double ascend; private double descend; private double routeWeight; private long time; private String debugInfo = ""; private InstructionList instructions; private PointList waypointList = PointList.EMPTY; private PointList pointList = PointList.EMPTY; private int numChanges; private long firstPtLegDeparture; private final List<Trip.Leg> legs = new ArrayList<>(); private BigDecimal fare; /** * @return the description of this route alternative to make it meaningful for the user e.g. it * displays one or two main roads of the route. */ public List<String> getDescription() { if (description == null) return Collections.emptyList(); return description; } public PathWrapper setDescription(List<String> names) { this.description = names; return this; } public PathWrapper addDebugInfo(String debugInfo) { if (debugInfo == null) throw new IllegalStateException("Debug information has to be none null"); if (!this.debugInfo.isEmpty()) this.debugInfo += ";"; this.debugInfo += debugInfo; return this; } public String getDebugInfo() { return debugInfo; } /** * This method returns all points on the path. Keep in mind that calculating the distance from * these points might yield different results compared to getDistance as points could have been * simplified on import or after querying. */ public PointList getPoints() { check("getPoints"); return pointList; } public PathWrapper setPoints(PointList points) { if (pointList != PointList.EMPTY) throw new IllegalStateException("Cannot call setPoint twice"); pointList = points; return this; } /** * This method returns the input points snapped to the road network. */ public PointList getWaypoints() { check("getWaypoints"); return waypointList; } /** * This method initializes this path with the snapped input points. */ public void setWaypoints(PointList wpList) { if (waypointList != PointList.EMPTY) throw new IllegalStateException("Cannot call setWaypoints twice"); this.waypointList = wpList; } /** * This method returns the distance of the path. Always prefer this method over * getPoints().calcDistance * <p> * * @return distance in meter */ public double getDistance() { check("getDistance"); return distance; } public PathWrapper setDistance(double distance) { this.distance = distance; return this; } /** * This method returns the total elevation change (going upwards) in meter. * <p> * * @return ascend in meter */ public double getAscend() { return ascend; } public PathWrapper setAscend(double ascend) { if (ascend < 0 || Double.isNaN(ascend)) throw new IllegalStateException("ascend has to be positive but was " + ascend); this.ascend = ascend; return this; } /** * This method returns the total elevation change (going downwards) in meter. * <p> * * @return decline in meter */ public double getDescend() { return descend; } public PathWrapper setDescend(double descend) { if (descend < 0 || Double.isNaN(descend)) throw new IllegalStateException("descend has to be positive but was " + descend); this.descend = descend; return this; } /** * @return time in millis */ public long getTime() { check("getTimes"); return time; } public PathWrapper setTime(long timeInMillis) { this.time = timeInMillis; return this; } /** * This method returns a double value which is better than the time for comparison of routes but * only if you know what you are doing, e.g. only to compare routes gained with the same query * parameters like vehicle. */ public double getRouteWeight() { check("getRouteWeight"); return routeWeight; } public PathWrapper setRouteWeight(double weight) { this.routeWeight = weight; return this; } /** * Calculates the bounding box of this route response */ public BBox calcRouteBBox(BBox _fallback) { check("calcRouteBBox"); BBox bounds = BBox.createInverse(_fallback.hasElevation()); int len = pointList.getSize(); if (len == 0) return _fallback; for (int i = 0; i < len; i++) { double lat = pointList.getLatitude(i); double lon = pointList.getLongitude(i); if (bounds.hasElevation()) { double ele = pointList.getEle(i); bounds.update(lat, lon, ele); } else { bounds.update(lat, lon); } } return bounds; } @Override public String toString() { String str = "nodes:" + pointList.getSize() + "; " + pointList.toString(); if (instructions != null && !instructions.isEmpty()) str += ", " + instructions.toString(); if (hasErrors()) str += ", " + errors.toString(); return str; } public InstructionList getInstructions() { check("getInstructions"); if (instructions == null) throw new IllegalArgumentException("To access instructions you need to enable creation before routing"); return instructions; } public void setInstructions(InstructionList instructions) { this.instructions = instructions; } private void check(String method) { if (hasErrors()) { throw new RuntimeException("You cannot call " + method + " if response contains errors. Check this with ghResponse.hasErrors(). " + "Errors are: " + getErrors()); } } /** * @return true if this alternative response contains one or more errors */ public boolean hasErrors() { return !errors.isEmpty(); } public List<Throwable> getErrors() { return errors; } public PathWrapper addError(Throwable error) { errors.add(error); return this; } public PathWrapper addErrors(List<Throwable> errors) { this.errors.addAll(errors); return this; } public void setNumChanges(int numChanges) { this.numChanges = numChanges; } public int getNumChanges() { return numChanges; } public void setFirstPtLegDeparture(long firstPtLegDeparture) { this.firstPtLegDeparture = firstPtLegDeparture; } public List<Trip.Leg> getLegs() { return legs; } public void setFare(BigDecimal fare) { this.fare = fare; } public BigDecimal getFare() { return fare; } }