@Secured({"ROLE_USER"}) @GET @Path("/annotations") @Produces({MediaType.APPLICATION_JSON}) public Object getAnnotations() { Graph graph = graphService.getGraph(); List<GraphBuilderAnnotation> builderAnnotations = graph.getBuilderAnnotations(); List<Annotation> out = new ArrayList<Annotation>(); for (GraphBuilderAnnotation annotation : builderAnnotations) { Annotation outAnnotation = new Annotation(); out.add(outAnnotation); outAnnotation.annotation = annotation.getVariety().name(); Collection<Object> referencedObjects = annotation.getReferencedObjects(); for (Object object : referencedObjects) { AnnotationObject annotationObj = new AnnotationObject(); applyObjectToAnnotation(graph, annotationObj, object); outAnnotation.addObject(annotationObj); } } Annotations annotations = new Annotations(); annotations.annotations = out; return annotations; }
/** * The safest bike lane should have a safety weight no lower than the time weight of a flat * street. This method divides the safety lengths by the length ratio of the safest street, * ensuring this property. * * @param graph */ private void applyBikeSafetyFactor(Graph graph) { _log.info( GraphBuilderAnnotation.register( graph, Variety.GRAPHWIDE, "Multiplying all bike safety values by " + (1 / bestBikeSafety))); HashSet<Edge> seenEdges = new HashSet<Edge>(); for (Vertex vertex : graph.getVertices()) { for (Edge e : vertex.getOutgoing()) { if (!(e instanceof PlainStreetEdge)) { continue; } PlainStreetEdge pse = (PlainStreetEdge) e; if (!seenEdges.contains(e)) { seenEdges.add(e); pse.setBicycleSafetyEffectiveLength( pse.getBicycleSafetyEffectiveLength() / bestBikeSafety); } } for (Edge e : vertex.getIncoming()) { if (!(e instanceof PlainStreetEdge)) { continue; } PlainStreetEdge pse = (PlainStreetEdge) e; if (!seenEdges.contains(e)) { seenEdges.add(e); pse.setBicycleSafetyEffectiveLength( pse.getBicycleSafetyEffectiveLength() / bestBikeSafety); } } } }
/** * Handle oneway streets, cycleways, and whatnot. See http://wiki.openstreetmap.org/wiki/Bicycle * for various scenarios, along with * http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing#Oneway. * * @param end * @param start */ private P2<PlainStreetEdge> getEdgesForStreet( IntersectionVertex start, IntersectionVertex end, OSMWay way, long startNode, StreetTraversalPermission permissions, LineString geometry) { // get geometry length in meters, irritatingly. Coordinate[] coordinates = geometry.getCoordinates(); double d = 0; for (int i = 1; i < coordinates.length; ++i) { d += DistanceLibrary.distance(coordinates[i - 1], coordinates[i]); } LineString backGeometry = (LineString) geometry.reverse(); Map<String, String> tags = way.getTags(); if (permissions == StreetTraversalPermission.NONE) return new P2<PlainStreetEdge>(null, null); PlainStreetEdge street = null, backStreet = null; /* * pedestrian rules: everything is two-way (assuming pedestrians are allowed at all) * bicycle rules: default: permissions; * * cycleway=dismount means walk your bike -- the engine will automatically try walking * bikes any time it is forbidden to ride them, so the only thing to do here is to * remove bike permissions * * oneway=... sets permissions for cars and bikes oneway:bicycle overwrites these * permissions for bikes only * * now, cycleway=opposite_lane, opposite, opposite_track can allow once oneway has been * set by oneway:bicycle, but should give a warning if it conflicts with oneway:bicycle * * bicycle:backward=yes works like oneway:bicycle=no bicycle:backwards=no works like * oneway:bicycle=yes */ String foot = way.getTag("foot"); if ("yes".equals(foot) || "designated".equals(foot)) { permissions = permissions.add(StreetTraversalPermission.PEDESTRIAN); } if (OSMWithTags.isFalse(foot)) { permissions = permissions.remove(StreetTraversalPermission.PEDESTRIAN); } boolean forceBikes = false; String bicycle = way.getTag("bicycle"); if ("yes".equals(bicycle) || "designated".equals(bicycle)) { permissions = permissions.add(StreetTraversalPermission.BICYCLE); forceBikes = true; } if (way.isTag("cycleway", "dismount") || "dismount".equals(bicycle)) { permissions = permissions.remove(StreetTraversalPermission.BICYCLE); if (forceBikes) { _log.warn( GraphBuilderAnnotation.register(graph, Variety.CONFLICTING_BIKE_TAGS, way.getId())); } } StreetTraversalPermission permissionsFront = permissions; StreetTraversalPermission permissionsBack = permissions; if (way.isTagTrue("oneway") || "roundabout".equals(tags.get("junction"))) { permissionsBack = permissionsBack.remove(StreetTraversalPermission.BICYCLE_AND_CAR); } if (way.isTag("oneway", "-1")) { permissionsFront = permissionsFront.remove(StreetTraversalPermission.BICYCLE_AND_CAR); } String oneWayBicycle = way.getTag("oneway:bicycle"); if (OSMWithTags.isTrue(oneWayBicycle) || way.isTagFalse("bicycle:backwards")) { permissionsBack = permissionsBack.remove(StreetTraversalPermission.BICYCLE); } if ("-1".equals(oneWayBicycle)) { permissionsFront = permissionsFront.remove(StreetTraversalPermission.BICYCLE); } if (OSMWithTags.isFalse(oneWayBicycle) || way.isTagTrue("bicycle:backwards")) { if (permissions.allows(StreetTraversalPermission.BICYCLE)) { permissionsFront = permissionsFront.add(StreetTraversalPermission.BICYCLE); permissionsBack = permissionsBack.add(StreetTraversalPermission.BICYCLE); } } // any cycleway which is opposite* allows contraflow biking String cycleway = way.getTag("cycleway"); String cyclewayLeft = way.getTag("cycleway:left"); String cyclewayRight = way.getTag("cycleway:right"); if ((cycleway != null && cycleway.startsWith("opposite")) || (cyclewayLeft != null && cyclewayLeft.startsWith("opposite")) || (cyclewayRight != null && cyclewayRight.startsWith("opposite"))) { permissionsBack = permissionsBack.add(StreetTraversalPermission.BICYCLE); } String access = way.getTag("access"); boolean noThruTraffic = "destination".equals(access) || "private".equals(access) || "customers".equals(access) || "delivery".equals(access) || "forestry".equals(access) || "agricultural".equals(access); if (permissionsFront != StreetTraversalPermission.NONE) { street = getEdgeForStreet(start, end, way, startNode, d, permissionsFront, geometry, false); street.setNoThruTraffic(noThruTraffic); } if (permissionsBack != StreetTraversalPermission.NONE) { backStreet = getEdgeForStreet(end, start, way, startNode, d, permissionsBack, backGeometry, true); backStreet.setNoThruTraffic(noThruTraffic); } /* mark edges that are on roundabouts */ if ("roundabout".equals(tags.get("junction"))) { if (street != null) street.setRoundabout(true); if (backStreet != null) backStreet.setRoundabout(true); } return new P2<PlainStreetEdge>(street, backStreet); }
/** * Handle turn restrictions * * @param relation */ private void processRestriction(OSMRelation relation) { long from = -1, to = -1, via = -1; for (OSMRelationMember member : relation.getMembers()) { String role = member.getRole(); if (role.equals("from")) { from = member.getRef(); } else if (role.equals("to")) { to = member.getRef(); } else if (role.equals("via")) { via = member.getRef(); } } if (from == -1 || to == -1 || via == -1) { _log.warn( GraphBuilderAnnotation.register(graph, Variety.TURN_RESTRICTION_BAD, relation.getId())); return; } Set<TraverseMode> modes = EnumSet.of(TraverseMode.BICYCLE, TraverseMode.CAR); String exceptModes = relation.getTag("except"); if (exceptModes != null) { for (String m : exceptModes.split(";")) { if (m.equals("motorcar")) { modes.remove(TraverseMode.CAR); } else if (m.equals("bicycle")) { modes.remove(TraverseMode.BICYCLE); _log.warn( GraphBuilderAnnotation.register( graph, Variety.TURN_RESTRICTION_EXCEPTION, via, from)); } } } modes = TraverseMode.internSet(modes); TurnRestrictionTag tag; if (relation.isTag("restriction", "no_right_turn")) { tag = new TurnRestrictionTag(via, TurnRestrictionType.NO_TURN); } else if (relation.isTag("restriction", "no_left_turn")) { tag = new TurnRestrictionTag(via, TurnRestrictionType.NO_TURN); } else if (relation.isTag("restriction", "no_straight_on")) { tag = new TurnRestrictionTag(via, TurnRestrictionType.NO_TURN); } else if (relation.isTag("restriction", "no_u_turn")) { tag = new TurnRestrictionTag(via, TurnRestrictionType.NO_TURN); } else if (relation.isTag("restriction", "only_straight_on")) { tag = new TurnRestrictionTag(via, TurnRestrictionType.ONLY_TURN); } else if (relation.isTag("restriction", "only_right_turn")) { tag = new TurnRestrictionTag(via, TurnRestrictionType.ONLY_TURN); } else if (relation.isTag("restriction", "only_left_turn")) { tag = new TurnRestrictionTag(via, TurnRestrictionType.ONLY_TURN); } else { _log.warn( GraphBuilderAnnotation.register( graph, Variety.TURN_RESTRICTION_UNKNOWN, relation.getTag("restriction"))); return; } TurnRestriction restriction = new TurnRestriction(); restriction.type = tag.type; restriction.modes = modes; turnRestrictionsByTag.put(tag, restriction); MapUtils.addToMapList(turnRestrictionsByFromWay, from, tag); MapUtils.addToMapList(turnRestrictionsByToWay, to, tag); }
public static String register(Graph graph, Variety variety, Object... refs) { GraphBuilderAnnotation gba = new GraphBuilderAnnotation(variety, refs); graph.addBuilderAnnotation(gba); LOG.trace("Registering {}", gba); return gba.getMessage() + " (annotation registered)"; }