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

org.opentripplanner.analyst.request.IsoChroneSPTRendererRecursiveGrid Maven / Gradle / Ivy

There is a newer version: 2.6.0
Show newest version
/* This program is free software: you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public License
 as published by the Free Software Foundation, either version 3 of
 the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see . */

package org.opentripplanner.analyst.request;

import java.util.ArrayList;
import java.util.List;

import org.opentripplanner.analyst.core.IsochroneData;
import org.opentripplanner.analyst.core.Sample;
import org.opentripplanner.analyst.core.SampleSource;
import org.opentripplanner.common.geometry.RecursiveGridIsolineBuilder;
import org.opentripplanner.common.geometry.RecursiveGridIsolineBuilder.ZFunc;
import org.opentripplanner.common.geometry.SphericalDistanceLibrary;
import org.opentripplanner.routing.algorithm.AStar;
import org.opentripplanner.routing.core.RoutingRequest;
import org.opentripplanner.routing.core.State;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.graph.Vertex;
import org.opentripplanner.routing.spt.ShortestPathTree;
import org.opentripplanner.routing.vertextype.StreetVertex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vividsolutions.jts.geom.Coordinate;

/**
 * Compute isochrones out of a shortest path tree request (RecursiveGrid isoline algorithm).
 * 
 * @author laurent
 */
public class IsoChroneSPTRendererRecursiveGrid implements IsoChroneSPTRenderer {

    private static final Logger LOG = LoggerFactory
            .getLogger(IsoChroneSPTRendererRecursiveGrid.class);

    private Graph graph;
    private SampleSource sampleSource;

    public IsoChroneSPTRendererRecursiveGrid(Graph graph) {
        this.graph = graph;
        this.sampleSource = graph.getSampleFactory();
    }

    /**
     * @param isoChroneRequest
     * @param sptRequest
     * @return
     */
    @Override
    public List getIsochrones(IsoChroneRequest isoChroneRequest,
            RoutingRequest sptRequest) {

        if (sptRequest.routerId != null && !sptRequest.routerId.isEmpty())
            throw new IllegalArgumentException(
                    "TODO: SampleSource is not multi-router compatible (yet).");

        // 1. Compute the Shortest Path Tree.
        long t0 = System.currentTimeMillis();
        sptRequest.worstTime = (sptRequest.dateTime
                + (sptRequest.arriveBy ? -isoChroneRequest.maxCutoffSec : isoChroneRequest.maxCutoffSec));
        sptRequest.batch = true;
        sptRequest.setRoutingContext(graph);
        // TODO handle different path dominance conditions
        final ShortestPathTree spt = new AStar().getShortestPathTree(sptRequest);
        sptRequest.cleanup();

        // 2. Compute the set of initial points
        long t1 = System.currentTimeMillis();
        List initialPoints = computeInitialPoints(spt);

        // 3. Compute the isochrone based on the SPT.
        ZFunc timeFunc = new ZFunc() {
            @Override
            public long z(Coordinate c) {
                Sample sample = sampleSource.getSample(c.x, c.y);
                if (sample == null) {
                    return Long.MAX_VALUE;
                }
                Long z = sample.eval(spt);
                return z;
            }
        };
        // TODO Snap the center as XYZ tile grid for better sample-reuse (if using sample cache).
        Coordinate center = sptRequest.from.getCoordinate();
        double gridSizeMeters = isoChroneRequest.precisionMeters;
        double dY = Math.toDegrees(gridSizeMeters / SphericalDistanceLibrary.RADIUS_OF_EARTH_IN_M);
        double dX = dY / Math.cos(Math.toRadians(center.x));
        LOG.info("dX={}, dY={}", dX, dY);
        RecursiveGridIsolineBuilder isolineBuilder = new RecursiveGridIsolineBuilder(dX, dY,
                center, timeFunc, initialPoints);
        isolineBuilder.setDebugCrossingEdges(isoChroneRequest.includeDebugGeometry);
        isolineBuilder.setDebugSeedGrid(isoChroneRequest.includeDebugGeometry);
        List isochrones = new ArrayList();
        for (Integer cutoffSec : isoChroneRequest.cutoffSecList) {
            IsochroneData isochrone = new IsochroneData(cutoffSec,
                    isolineBuilder.computeIsoline(cutoffSec));
            if (isoChroneRequest.includeDebugGeometry)
                isochrone.debugGeometry = isolineBuilder.getDebugGeometry();
            isochrones.add(isochrone);
        }
        long t2 = System.currentTimeMillis();
        LOG.info("Computed SPT in {}msec, {} isochrones in {}msec", (int) (t1 - t0),
                isochrones.size(), (int) (t2 - t1));

        return isochrones;
    }

    /**
     * Compute a set of initial coordinates for the given SPT
     * 
     * @param spt
     * @return
     */
    private List computeInitialPoints(ShortestPathTree spt) {
        List retval = new ArrayList(spt.getVertexCount());
        for (State s : spt.getAllStates()) {
            Vertex v = s.getVertex();
            // Take only street
            if (v instanceof StreetVertex) {
                retval.add(v.getCoordinate());
            }
        }
        LOG.debug("Created {} initial points from {} vertexes.", retval.size(),
                spt.getVertexCount());
        return retval;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy