Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.opentripplanner.api.resource;
import java.io.ByteArrayOutputStream;
import java.util.Date;
import java.util.Locale;
import javax.ws.rs.*;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Response;
import org.apache.commons.codec.binary.Base64;
import org.opentripplanner.analyst.request.SampleGridRenderer.WTWD;
import org.opentripplanner.analyst.request.SampleGridRequest;
import org.opentripplanner.api.common.RoutingResource;
import org.opentripplanner.common.geometry.ZSampleGrid;
import org.opentripplanner.common.geometry.ZSampleGrid.ZSamplePoint;
import org.opentripplanner.common.model.GenericLocation;
import org.opentripplanner.routing.core.RoutingRequest;
import org.opentripplanner.standalone.Router;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ar.com.hjg.pngj.ImageInfo;
import ar.com.hjg.pngj.ImageLineHelper;
import ar.com.hjg.pngj.ImageLineInt;
import ar.com.hjg.pngj.PngWriter;
import ar.com.hjg.pngj.chunks.PngChunkTEXT;
import ar.com.hjg.pngj.chunks.PngChunkTextVar;
/**
* A Jersey web service resource class that returns a grid with time for a set of points.
*
* Example of request:
*
*
* http://localhost:8080/otp/routers/bordeaux/timegrid?fromPlace=47.059,-0.880&date=2013/10/01&time=12:00:00&maxWalkDistance=1000&maxTimeSec=3600&mode=WALK,TRANSIT
*
*
* @author laurent
*/
@Path("/routers/{routerId}/timegrid")
public class TimeGridWs extends RoutingResource {
public enum DataChannel {
TIME, /* Clock time */
BOARDINGS, /* Number of boardings */
WALK_DISTANCE, /* Total walk distance */
}
@SuppressWarnings("unused")
private static final Logger LOG = LoggerFactory.getLogger(TimeGridWs.class);
@QueryParam("maxTimeSec")
private Integer maxTimeSec;
@QueryParam("precisionMeters")
@DefaultValue("200")
private Integer precisionMeters;
@QueryParam("offRoadDistanceMeters")
@DefaultValue("150")
private Integer offRoadDistanceMeters;
@QueryParam("coordinateOrigin")
private String coordinateOrigin;
@QueryParam("zDataType")
@DefaultValue("TIME")
private DataChannel zDataType;
private static final String OTPA_GRID_CORNER = "OTPA-Grid-Corner";
private static final String OTPA_GRID_CELL_SIZE = "OTPA-Grid-Cell-Size";
private static final String OTPA_OFFROAD_DIST = "OTPA-OffRoad-Dist";
@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 sampleGrid = router.sampleGridRenderer.getSampleGrid(tgRequest, sptRequest);
int cols = sampleGrid.getXMax() - sampleGrid.getXMin() + 1;
int rows = sampleGrid.getYMax() - sampleGrid.getYMin() + 1;
int channels = 4; // Hard-coded to RGBA
// 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:
unit = 1.0; // 1:1sec, max 18h
break;
case BOARDINGS:
unit = 1000.0; // 1:0.001 boarding, max 65.5
break;
case WALK_DISTANCE:
unit = 10.0; // 1:0.1m, max 6.55km
break;
default:
throw new IllegalArgumentException("Unsupported Z DataType.");
}
for (ZSamplePoint 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)
iz = 65534; // Clamp
}
// 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;
rgba[row][offset + 0] = (iz & 0xFF); // z low 8 bits
rgba[row][offset + 1] = (iz >> 8); // z high 8 bits
rgba[row][offset + 2] = id; // d
/*
* 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();
}
}