Search in sources :

Example 6 with WTWD

use of org.opentripplanner.analyst.request.SampleGridRenderer.WTWD in project OpenTripPlanner by opentripplanner.

the class TNPropagatedTimesStore method makeIsochroneForVertices.

/**
 * This bypasses a bunch of TimeSurface conversion/copy steps we were going though and makes the isochrones directly.
 * This assumes that the target indexes in this router/propagatedTimesStore are vertex indexes, not pointset indexes.
 * Called three times on min/avg/max to create the three elements of a ResultEnvelope.
 */
private ResultSet makeIsochroneForVertices(int[] times) {
    final int spacing = 5;
    final int nMax = 24;
    final int cutoffMinutes = 120;
    final int offroadDistanceMeters = 250;
    SparseMatrixZSampleGrid<WTWD> grid = makeSampleGridForVertices(times, offroadDistanceMeters);
    long t0 = System.currentTimeMillis();
    DelaunayIsolineBuilder<WTWD> isolineBuilder = new DelaunayIsolineBuilder<>(grid.delaunayTriangulate(), new WTWD.IsolineMetric());
    List<IsochroneData> isoData = new ArrayList<IsochroneData>();
    for (int minutes = spacing, n = 0; minutes <= cutoffMinutes && n < nMax; minutes += spacing, n++) {
        int seconds = minutes * 60;
        WTWD z0 = new WTWD();
        z0.w = 1.0;
        z0.wTime = seconds;
        z0.d = offroadDistanceMeters;
        IsochroneData isochrone = new IsochroneData(seconds, isolineBuilder.computeIsoline(z0));
        isoData.add(isochrone);
    }
    long t1 = System.currentTimeMillis();
    ResultSet resultSet = new ResultSet();
    resultSet.isochrones = new IsochroneData[isoData.size()];
    isoData.toArray(resultSet.isochrones);
    LOG.debug("Computed {} isochrones in {} msec", isoData.size(), (int) (t1 - t0));
    return resultSet;
}
Also used : WTWD(org.opentripplanner.analyst.request.SampleGridRenderer.WTWD) DelaunayIsolineBuilder(org.opentripplanner.common.geometry.DelaunayIsolineBuilder) TIntArrayList(gnu.trove.list.array.TIntArrayList) ArrayList(java.util.ArrayList) ResultSet(org.opentripplanner.analyst.ResultSet) IsochroneData(org.opentripplanner.analyst.core.IsochroneData)

Example 7 with WTWD

use of org.opentripplanner.analyst.request.SampleGridRenderer.WTWD in project OpenTripPlanner by opentripplanner.

the class TimeGridWs method getTimeGridPng.

@GET
@Produces({ "image/png" })
public Response getTimeGridPng(@QueryParam("base64") @DefaultValue("false") boolean base64) throws Exception {
    /* Fetch the Router for this request using server and routerId fields from superclass. */
    Router router = otpServer.getRouter(routerId);
    if (precisionMeters < 10)
        throw new IllegalArgumentException("Too small precisionMeters: " + precisionMeters);
    if (offRoadDistanceMeters < 10)
        throw new IllegalArgumentException("Too small offRoadDistanceMeters: " + offRoadDistanceMeters);
    // Build the request
    RoutingRequest sptRequest = buildRequest();
    SampleGridRequest tgRequest = new SampleGridRequest();
    tgRequest.maxTimeSec = maxTimeSec;
    tgRequest.precisionMeters = precisionMeters;
    tgRequest.offRoadDistanceMeters = offRoadDistanceMeters;
    if (coordinateOrigin != null)
        tgRequest.coordinateOrigin = new GenericLocation(null, coordinateOrigin).getCoordinate();
    // Get a sample grid
    ZSampleGrid<WTWD> sampleGrid = router.sampleGridRenderer.getSampleGrid(tgRequest, sptRequest);
    int cols = sampleGrid.getXMax() - sampleGrid.getXMin() + 1;
    int rows = sampleGrid.getYMax() - sampleGrid.getYMin() + 1;
    // Hard-coded to RGBA
    int channels = 4;
    // We force to 8 bits channel depth, some clients won't support more than 8
    // (namely, HTML5 canvas...)
    ImageInfo imgInfo = new ImageInfo(cols, rows, 8, true, false, false);
    /**
     * TODO: PNGJ allow for progressive (ie line-by-line) writing. Thus we could theorically
     * prevent having to allocate a bit pixel array in the first place, but we would need a
     * line-by-line iterator on the sample grid, which is currently not the case.
     */
    int[][] rgba = new int[rows][cols * channels];
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PngWriter pw = new PngWriter(baos, imgInfo);
    pw.getMetadata().setText(PngChunkTextVar.KEY_Software, "OTPA");
    pw.getMetadata().setText(PngChunkTextVar.KEY_Creation_Time, new Date().toString());
    pw.getMetadata().setText(PngChunkTextVar.KEY_Description, "Sample grid bitmap");
    String gridCornerStr = String.format(Locale.US, "%.8f,%.8f", sampleGrid.getCenter().y + sampleGrid.getYMin() * sampleGrid.getCellSize().y, sampleGrid.getCenter().x + sampleGrid.getXMin() * sampleGrid.getCellSize().x);
    String gridCellSzStr = String.format(Locale.US, "%.12f,%.12f", sampleGrid.getCellSize().y, sampleGrid.getCellSize().x);
    String offRoadDistStr = String.format(Locale.US, "%d", offRoadDistanceMeters);
    PngChunkTEXT gridCornerChunk = new PngChunkTEXT(imgInfo);
    gridCornerChunk.setKeyVal(OTPA_GRID_CORNER, gridCornerStr);
    pw.getChunksList().queue(gridCornerChunk);
    PngChunkTEXT gridCellSzChunk = new PngChunkTEXT(imgInfo);
    gridCellSzChunk.setKeyVal(OTPA_GRID_CELL_SIZE, gridCellSzStr);
    pw.getChunksList().queue(gridCellSzChunk);
    PngChunkTEXT offRoadDistChunk = new PngChunkTEXT(imgInfo);
    offRoadDistChunk.setKeyVal(OTPA_OFFROAD_DIST, offRoadDistStr);
    pw.getChunksList().queue(offRoadDistChunk);
    double unit;
    switch(zDataType) {
        case TIME:
            // 1:1sec, max 18h
            unit = 1.0;
            break;
        case BOARDINGS:
            // 1:0.001 boarding, max 65.5
            unit = 1000.0;
            break;
        case WALK_DISTANCE:
            // 1:0.1m, max 6.55km
            unit = 10.0;
            break;
        default:
            throw new IllegalArgumentException("Unsupported Z DataType.");
    }
    for (ZSamplePoint<WTWD> p : sampleGrid) {
        WTWD z = p.getZ();
        int row = p.getY() - sampleGrid.getYMin();
        int col = p.getX() - sampleGrid.getXMin();
        double zz;
        switch(zDataType) {
            case TIME:
                zz = z.wTime / z.w;
                break;
            case BOARDINGS:
                zz = z.wBoardings / z.w;
                break;
            case WALK_DISTANCE:
                zz = z.wWalkDist / z.w;
                break;
            default:
                throw new IllegalArgumentException("Unsupported Z DataType.");
        }
        int iz;
        if (Double.isInfinite(zz)) {
            iz = 65535;
        } else {
            iz = ImageLineHelper.clampTo_0_65535((int) Math.round(zz * unit));
            if (iz == 65535)
                // Clamp
                iz = 65534;
        }
        // d is expressed as a percentage of grid size, max 255%.
        // Sometimes d will be bigger than 2.55 x grid size,
        // but this should not be too much important as we are off-bounds.
        int id = ImageLineHelper.clampTo_0_255((int) Math.round(z.d / precisionMeters * 100));
        int offset = col * channels;
        // z low 8 bits
        rgba[row][offset + 0] = (iz & 0xFF);
        // z high 8 bits
        rgba[row][offset + 1] = (iz >> 8);
        // d
        rgba[row][offset + 2] = id;
        /*
             * Keep the alpha channel at 255, otherwise the RGB channel will be downsampled on some
             * rendering clients (namely, JS canvas).
             */
        rgba[row][offset + 3] = 255;
    }
    for (int row = 0; row < rgba.length; row++) {
        ImageLineInt iline = new ImageLineInt(imgInfo, rgba[row]);
        pw.writeRow(iline, row);
    }
    pw.end();
    // Disallow caching on client side
    CacheControl cc = new CacheControl();
    cc.setNoCache(true);
    // Also put the meta-data in the HTML header (easier to read from JS)
    byte[] data = baos.toByteArray();
    if (base64) {
        data = Base64.encodeBase64(data);
    }
    return Response.ok().cacheControl(cc).entity(data).header(OTPA_GRID_CORNER, gridCornerStr).header(OTPA_GRID_CELL_SIZE, gridCellSzStr).header(OTPA_OFFROAD_DIST, offRoadDistStr).build();
}
Also used : PngChunkTEXT(ar.com.hjg.pngj.chunks.PngChunkTEXT) WTWD(org.opentripplanner.analyst.request.SampleGridRenderer.WTWD) SampleGridRequest(org.opentripplanner.analyst.request.SampleGridRequest) Router(org.opentripplanner.standalone.Router) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ZSamplePoint(org.opentripplanner.common.geometry.ZSampleGrid.ZSamplePoint) Date(java.util.Date) PngWriter(ar.com.hjg.pngj.PngWriter) GenericLocation(org.opentripplanner.common.model.GenericLocation) RoutingRequest(org.opentripplanner.routing.core.RoutingRequest) CacheControl(javax.ws.rs.core.CacheControl) ImageInfo(ar.com.hjg.pngj.ImageInfo) ImageLineInt(ar.com.hjg.pngj.ImageLineInt)

Example 8 with WTWD

use of org.opentripplanner.analyst.request.SampleGridRenderer.WTWD in project OpenTripPlanner by opentripplanner.

the class SurfaceResource method getIsochronesAccumulative.

/**
 * Use Laurent's accumulative grid sampler. Cutoffs in minutes.
 * The grid and Delaunay triangulation are cached, so subsequent requests are very fast.
 *
 * @param spacing the number of minutes between isochrones
 * @return a list of evenly-spaced isochrones up to the timesurface's cutoff point
 */
public static List<IsochroneData> getIsochronesAccumulative(TimeSurface surf, int spacing, int nMax) {
    long t0 = System.currentTimeMillis();
    if (surf.sampleGrid == null) {
        // The sample grid was not built from the SPT; make a minimal one including only time from the vertices in this timesurface
        surf.makeSampleGridWithoutSPT();
    }
    DelaunayIsolineBuilder<WTWD> isolineBuilder = new DelaunayIsolineBuilder<WTWD>(surf.sampleGrid.delaunayTriangulate(), new WTWD.IsolineMetric());
    List<IsochroneData> isochrones = new ArrayList<IsochroneData>();
    for (int minutes = spacing, n = 0; minutes <= surf.cutoffMinutes && n < nMax; minutes += spacing, n++) {
        int seconds = minutes * 60;
        WTWD z0 = new WTWD();
        z0.w = 1.0;
        z0.wTime = seconds;
        // meters. TODO set dynamically / properly, make sure it matches grid cell size?
        z0.d = 300;
        IsochroneData isochrone = new IsochroneData(seconds, isolineBuilder.computeIsoline(z0));
        isochrones.add(isochrone);
    }
    long t1 = System.currentTimeMillis();
    LOG.debug("Computed {} isochrones in {} msec", isochrones.size(), (int) (t1 - t0));
    return isochrones;
}
Also used : WTWD(org.opentripplanner.analyst.request.SampleGridRenderer.WTWD) DelaunayIsolineBuilder(org.opentripplanner.common.geometry.DelaunayIsolineBuilder) ArrayList(java.util.ArrayList) IsochroneData(org.opentripplanner.analyst.core.IsochroneData)

Example 9 with WTWD

use of org.opentripplanner.analyst.request.SampleGridRenderer.WTWD in project OpenTripPlanner by opentripplanner.

the class TimeSurface method makeSampleGridWithoutSPT.

/**
 * Create the SampleGrid from whatever values are already in the TimeSurface, rather than looking at the SPT.
 * This is not really ideal since it includes only intersection nodes, and no points along the road segments.
 */
public void makeSampleGridWithoutSPT() {
    long t0 = System.currentTimeMillis();
    // Todo: set dynamically and make sure this matches isoline builder params
    final double gridSizeMeters = 300;
    // Off-road max distance MUST be APPROX EQUALS to the grid precision
    // TODO: Loosen this restriction (by adding more closing sample).
    // Change the 0.8 magic factor here with caution.
    // offroad walk distance roughly grid size
    final double D0 = 0.8 * gridSizeMeters;
    // off-road walk speed in m/sec
    final double V0 = 1.00;
    Coordinate coordinateOrigin = new Coordinate();
    final double cosLat = FastMath.cos(toRadians(coordinateOrigin.y));
    double dY = Math.toDegrees(gridSizeMeters / SphericalDistanceLibrary.RADIUS_OF_EARTH_IN_M);
    double dX = dY / cosLat;
    sampleGrid = new SparseMatrixZSampleGrid<WTWD>(16, this.times.size(), dX, dY, coordinateOrigin);
    AccumulativeGridSampler.AccumulativeMetric<WTWD> metric = new SampleGridRenderer.WTWDAccumulativeMetric(cosLat, D0, V0, gridSizeMeters);
    AccumulativeGridSampler<WTWD> sampler = new AccumulativeGridSampler<WTWD>(sampleGrid, metric);
    // TODO propagation along street geometries could happen at this stage, rather than when the SPT is still available.
    for (TObjectIntIterator<Vertex> iter = times.iterator(); iter.hasNext(); ) {
        iter.advance();
        Vertex vertex = iter.key();
        int time = iter.value();
        WTWD z = new WTWD();
        z.w = 1.0;
        z.d = 0.0;
        z.wTime = time;
        // unused
        z.wBoardings = 0;
        // unused
        z.wWalkDist = 0;
        sampler.addSamplingPoint(vertex.getCoordinate(), z, V0);
    }
    sampler.close();
    long t1 = System.currentTimeMillis();
    LOG.info("Made scalar SampleGrid from TimeSurface in {} msec.", (int) (t1 - t0));
}
Also used : Vertex(org.opentripplanner.routing.graph.Vertex) StreetVertex(org.opentripplanner.routing.vertextype.StreetVertex) WTWD(org.opentripplanner.analyst.request.SampleGridRenderer.WTWD) Coordinate(com.vividsolutions.jts.geom.Coordinate) AccumulativeGridSampler(org.opentripplanner.common.geometry.AccumulativeGridSampler)

Example 10 with WTWD

use of org.opentripplanner.analyst.request.SampleGridRenderer.WTWD in project OpenTripPlanner by opentripplanner.

the class PropagatedTimesStore method makeIsochroneForVertices.

/**
 * This bypasses a bunch of TimeSurface conversion/copy steps we were going though and makes the isochrones directly.
 * This assumes that the target indexes in this router/propagatedTimesStore are vertex indexes, not pointset indexes.
 * Called three times on min/avg/max to create the three elements of a ResultEnvelope.
 */
private ResultSet makeIsochroneForVertices(int[] times) {
    final int spacing = 5;
    final int nMax = 24;
    final int cutoffMinutes = 120;
    final double gridSize = IsochroneGenerator.GRID_SIZE_METERS;
    final double offroadDistanceMeters = gridSize * IsochroneGenerator.WALK_DISTANCE_GRID_SIZE_RATIO;
    SparseMatrixZSampleGrid<WTWD> grid = makeSampleGridForVertices(times, gridSize);
    long t0 = System.currentTimeMillis();
    DelaunayIsolineBuilder<WTWD> isolineBuilder = new DelaunayIsolineBuilder<>(grid.delaunayTriangulate(), new WTWD.IsolineMetric());
    List<IsochroneData> isoData = new ArrayList<IsochroneData>();
    for (int minutes = spacing, n = 0; minutes <= cutoffMinutes && n < nMax; minutes += spacing, n++) {
        int seconds = minutes * 60;
        WTWD z0 = new WTWD();
        z0.w = 1.0;
        z0.wTime = seconds;
        z0.d = offroadDistanceMeters;
        IsochroneData isochrone = new IsochroneData(seconds, isolineBuilder.computeIsoline(z0));
        isoData.add(isochrone);
    }
    long t1 = System.currentTimeMillis();
    ResultSet resultSet = new ResultSet();
    resultSet.isochrones = new IsochroneData[isoData.size()];
    isoData.toArray(resultSet.isochrones);
    LOG.debug("Computed {} isochrones in {} msec", isoData.size(), (int) (t1 - t0));
    return resultSet;
}
Also used : WTWD(org.opentripplanner.analyst.request.SampleGridRenderer.WTWD) DelaunayIsolineBuilder(org.opentripplanner.common.geometry.DelaunayIsolineBuilder) TIntArrayList(gnu.trove.list.array.TIntArrayList) ArrayList(java.util.ArrayList) ResultSet(org.opentripplanner.analyst.ResultSet) IsochroneData(org.opentripplanner.analyst.core.IsochroneData)

Aggregations

WTWD (org.opentripplanner.analyst.request.SampleGridRenderer.WTWD)11 Coordinate (com.vividsolutions.jts.geom.Coordinate)5 ArrayList (java.util.ArrayList)5 IsochroneData (org.opentripplanner.analyst.core.IsochroneData)5 DelaunayIsolineBuilder (org.opentripplanner.common.geometry.DelaunayIsolineBuilder)5 AccumulativeGridSampler (org.opentripplanner.common.geometry.AccumulativeGridSampler)4 Vertex (org.opentripplanner.routing.graph.Vertex)3 TIntArrayList (gnu.trove.list.array.TIntArrayList)2 ResultSet (org.opentripplanner.analyst.ResultSet)2 WTWDAccumulativeMetric (org.opentripplanner.analyst.request.SampleGridRenderer.WTWDAccumulativeMetric)2 ImageInfo (ar.com.hjg.pngj.ImageInfo)1 ImageLineInt (ar.com.hjg.pngj.ImageLineInt)1 PngWriter (ar.com.hjg.pngj.PngWriter)1 PngChunkTEXT (ar.com.hjg.pngj.chunks.PngChunkTEXT)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 Date (java.util.Date)1 CacheControl (javax.ws.rs.core.CacheControl)1 SampleGridRenderer (org.opentripplanner.analyst.request.SampleGridRenderer)1 SampleGridRequest (org.opentripplanner.analyst.request.SampleGridRequest)1 ZMetric (org.opentripplanner.common.geometry.IsolineBuilder.ZMetric)1