use of org.opentripplanner.routing.graph.Edge in project OpenTripPlanner by opentripplanner.
the class EdgeVertexTileRenderer method renderTile.
@Override
public void renderTile(TileRenderContext context) {
float lineWidth = (float) (1.0f + 3.0f / Math.sqrt(context.metersPerPixel));
// Grow a bit the envelope to prevent rendering glitches between tiles
Envelope bboxWithMargins = context.expandPixels(lineWidth * 2.0, lineWidth * 2.0);
Collection<Vertex> vertices = context.graph.streetIndex.getVerticesForEnvelope(bboxWithMargins);
Collection<Edge> edges = context.graph.streetIndex.getEdgesForEnvelope(bboxWithMargins);
Set<Edge> edgesSet = new HashSet<>(edges);
/*
* Some edges do not have geometry and thus do not get spatial-indexed. Add
* outgoing/incoming edges of all vertices. This is not perfect, as if the edge cross a tile
* it will not be rendered on it.
*/
for (Vertex vertex : vertices) {
edgesSet.addAll(vertex.getIncoming());
edgesSet.addAll(vertex.getOutgoing());
}
// Note: we do not use the transform inside the shapeWriter, but do it ourselves
// since it's easier for the offset to work in pixel size.
ShapeWriter shapeWriter = new ShapeWriter(new IdentityPointTransformation(), new PointShapeFactory.Point());
GeometryFactory geomFactory = new GeometryFactory();
Stroke stroke = new BasicStroke(lineWidth * 1.4f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);
Stroke halfStroke = new BasicStroke(lineWidth * 0.6f + 1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);
Stroke halfDashedStroke = new BasicStroke(lineWidth * 0.6f + 1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1.0f, new float[] { 4 * lineWidth, lineWidth }, 2 * lineWidth);
Stroke arrowStroke = new ShapeStroke(new Polygon(new int[] { 0, 0, 30 }, new int[] { 0, 20, 10 }, 3), lineWidth / 2, 5.0f * lineWidth, 2.5f * lineWidth);
BasicStroke thinStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);
Font font = new Font(Font.SANS_SERIF, Font.PLAIN, Math.round(lineWidth));
Font largeFont = new Font(Font.SANS_SERIF, Font.PLAIN, Math.round(lineWidth * 1.5f));
FontMetrics largeFontMetrics = context.graphics.getFontMetrics(largeFont);
context.graphics.setFont(largeFont);
context.graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
context.graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
BufferParameters bufParams = new BufferParameters();
bufParams.setSingleSided(true);
bufParams.setJoinStyle(BufferParameters.JOIN_BEVEL);
// Render all edges
EdgeVisualAttributes evAttrs = new EdgeVisualAttributes();
for (Edge edge : edgesSet) {
evAttrs.color = null;
evAttrs.label = null;
Geometry edgeGeom = edge.getGeometry();
boolean hasGeom = true;
if (edgeGeom == null) {
Coordinate[] coordinates = new Coordinate[] { edge.getFromVertex().getCoordinate(), edge.getToVertex().getCoordinate() };
edgeGeom = GeometryUtils.getGeometryFactory().createLineString(coordinates);
hasGeom = false;
}
boolean render = evRenderer.renderEdge(edge, evAttrs);
if (!render)
continue;
Geometry midLineGeom = context.transform.transform(edgeGeom);
OffsetCurveBuilder offsetBuilder = new OffsetCurveBuilder(new PrecisionModel(), bufParams);
Coordinate[] coords = offsetBuilder.getOffsetCurve(midLineGeom.getCoordinates(), lineWidth * 0.4);
if (coords.length < 2)
// Can happen for very small edges (<1mm)
continue;
LineString offsetLine = geomFactory.createLineString(coords);
Shape midLineShape = shapeWriter.toShape(midLineGeom);
Shape offsetShape = shapeWriter.toShape(offsetLine);
context.graphics.setStroke(hasGeom ? halfStroke : halfDashedStroke);
context.graphics.setColor(evAttrs.color);
context.graphics.draw(offsetShape);
if (lineWidth > 6.0f) {
context.graphics.setColor(Color.WHITE);
context.graphics.setStroke(arrowStroke);
context.graphics.draw(offsetShape);
}
if (lineWidth > 4.0f) {
context.graphics.setColor(Color.BLACK);
context.graphics.setStroke(thinStroke);
context.graphics.draw(midLineShape);
}
if (evAttrs.label != null && lineWidth > 8.0f) {
context.graphics.setColor(Color.BLACK);
context.graphics.setStroke(new TextStroke(" " + evAttrs.label + " ", font, false, true));
context.graphics.draw(offsetShape);
}
}
// Render all vertices
VertexVisualAttributes vvAttrs = new VertexVisualAttributes();
for (Vertex vertex : vertices) {
vvAttrs.color = null;
vvAttrs.label = null;
Point point = geomFactory.createPoint(new Coordinate(vertex.getLon(), vertex.getLat()));
boolean render = evRenderer.renderVertex(vertex, vvAttrs);
if (!render)
continue;
Point tilePoint = (Point) context.transform.transform(point);
Shape shape = shapeWriter.toShape(tilePoint);
context.graphics.setColor(vvAttrs.color);
context.graphics.setStroke(stroke);
context.graphics.draw(shape);
if (vvAttrs.label != null && lineWidth > 6.0f && context.bbox.contains(point.getCoordinate())) {
context.graphics.setColor(Color.BLACK);
int labelWidth = largeFontMetrics.stringWidth(vvAttrs.label);
/*
* Poor man's solution: stay on the tile if possible. Otherwise the renderer would
* need to expand the envelope by an unbounded amount (max label size).
*/
double x = tilePoint.getX();
if (x + labelWidth > context.tileWidth)
x -= labelWidth;
context.graphics.drawString(vvAttrs.label, (float) x, (float) tilePoint.getY());
}
}
}
use of org.opentripplanner.routing.graph.Edge in project OpenTripPlanner by opentripplanner.
the class StreetMatcher method createIndex.
STRtree createIndex() {
STRtree edgeIndex = new STRtree();
for (Vertex v : graph.getVertices()) {
for (Edge e : v.getOutgoing()) {
if (e instanceof StreetEdge) {
Envelope envelope;
Geometry geometry = e.getGeometry();
envelope = geometry.getEnvelopeInternal();
edgeIndex.insert(envelope, e);
}
}
}
log.debug("Created index");
return edgeIndex;
}
use of org.opentripplanner.routing.graph.Edge in project OpenTripPlanner by opentripplanner.
the class WFSNotePollingGraphUpdater method runPolling.
/**
* The function is run periodically by the update manager.
* The extending class should provide the getNote method. It is not implemented here
* as the requirements for different updaters can be vastly different dependent on the data source.
*/
@Override
protected void runPolling() throws IOException {
LOG.info("Run WFS polling updater with hashcode: {}", this.hashCode());
notesForEdge = HashMultimap.create();
uniqueMatchers = new HashMap<>();
FeatureIterator<SimpleFeature> features = featureSource.getFeatures(query).features();
while (features.hasNext()) {
SimpleFeature feature = features.next();
if (feature.getDefaultGeometry() == null)
continue;
Alert alert = getNote(feature);
if (alert == null)
continue;
Geometry geom = (Geometry) feature.getDefaultGeometry();
Geometry searchArea = geom.buffer(SEARCH_RADIUS_DEG);
Collection<Edge> edges = graph.streetIndex.getEdgesForEnvelope(searchArea.getEnvelopeInternal());
for (Edge edge : edges) {
if (edge instanceof StreetEdge && !searchArea.disjoint(edge.getGeometry())) {
addNote(edge, alert, NOTE_MATCHER);
}
}
}
updaterManager.execute(new WFSGraphWriter());
}
use of org.opentripplanner.routing.graph.Edge in project OpenTripPlanner by opentripplanner.
the class StreetVertexIndexServiceImpl method postSetup.
@SuppressWarnings("rawtypes")
private void postSetup() {
for (Vertex gv : graph.getVertices()) {
Vertex v = gv;
/*
* We add all edges with geometry, skipping transit, filtering them out after. We do not
* index transit edges as we do not need them and some GTFS do not have shape data, so
* long straight lines between 2 faraway stations will wreck performance on a hash grid
* spatial index.
*
* If one need to store transit edges in the index, we could improve the hash grid
* rasterizing splitting long segments.
*/
for (Edge e : gv.getOutgoing()) {
if (e instanceof PatternEdge || e instanceof SimpleTransfer)
continue;
LineString geometry = e.getGeometry();
if (geometry == null) {
continue;
}
Envelope env = geometry.getEnvelopeInternal();
if (edgeTree instanceof HashGridSpatialIndex)
((HashGridSpatialIndex) edgeTree).insert(geometry, e);
else
edgeTree.insert(env, e);
}
if (v instanceof TransitStop) {
Envelope env = new Envelope(v.getCoordinate());
transitStopTree.insert(env, v);
}
Envelope env = new Envelope(v.getCoordinate());
verticesTree.insert(env, v);
}
}
use of org.opentripplanner.routing.graph.Edge in project OpenTripPlanner by opentripplanner.
the class OtpsIndividual method getSnappedLocation.
/**
* @return The snapped location of the individual on the graph (ie a point on the nearest
* walkable/drivable street). This can be useful to output a more precise location for a
* generated grid point, as the returned location is the effective one used for
* path/time computations. Return NULL if the individual has never been evualuated (by a
* call to OtpsSPT.eval). Return the original location if the point can't be snapped
* (too far away from a street).
*/
public OtpsLatLon getSnappedLocation() {
if (cachedSample == null)
return null;
// Maybe the Sample should store the snapped location itself
for (Edge e : cachedSample.v0.getOutgoingStreetEdges()) {
if (e.getToVertex().equals(cachedSample.v1) && e.getGeometry() != null) {
LineString geom = e.getGeometry();
LengthIndexedLine liline = new LengthIndexedLine(geom);
int d = cachedSample.d0 + cachedSample.d1;
double k = d == 0 ? 0.0 : 1.0 * cachedSample.d0 / d;
double x = liline.getStartIndex() + (liline.getEndIndex() - liline.getStartIndex()) * k;
Coordinate p = liline.extractPoint(x);
return new OtpsLatLon(p.y, p.x);
}
}
return getLocation();
}
Aggregations