/** * Get polygons covering the components of the graph. The largest component (in terms of number of * nodes) will not overlap any other components (it will have holes); the others may overlap each * other. * * @param modes * @return */ @Secured({"ROLE_USER"}) @GET @Path("/polygons") @Produces({MediaType.APPLICATION_JSON}) public GraphComponentPolygons getComponentPolygons( @DefaultValue("TRANSIT,WALK") @QueryParam("modes") TraverseModeSet modes, @QueryParam(RequestInf.DATE) String date, @QueryParam(RequestInf.TIME) String time, @DefaultValue("") @QueryParam(RequestInf.BANNED_ROUTES) String bannedRoutes) { TraverseOptions options = new TraverseOptions(modes); options.bannedRoutes = new HashSet<RouteSpec>(); if (bannedRoutes.length() > 0) { for (String element : bannedRoutes.split(",")) { String[] routeSpec = element.split("_", 2); if (routeSpec.length != 2) { throw new IllegalArgumentException("AgencyId or routeId not set in bannedRoutes list"); } options.bannedRoutes.add(new RouteSpec(routeSpec[0], routeSpec[1])); } } long dateTime = DateUtils.toDate(date, time).getTime(); if (cachedPolygons == null || dateTime != cachedDateTime || !options.equals(cachedOptions)) { cachedOptions = options; cachedDateTime = dateTime; Graph graph = graphService.getGraph(); if (graphService.getCalendarService() != null) { options.setCalendarService(graphService.getCalendarService()); } options.setServiceDays(dateTime, graph.getAgencyIds()); cachedPolygons = AnalysisUtils.getComponentPolygons(graph, options, dateTime); } GraphComponentPolygons out = new GraphComponentPolygons(); out.components = new ArrayList<GraphComponent>(); for (Geometry geometry : cachedPolygons) { GraphComponent component = new GraphComponent(); component.polygon = geometry; out.components.add(component); } return out; }
/** * Cache ServiceDay objects representing which services are running yesterday, today, and tomorrow * relative to the search time. This information is very heavily used (at every transit boarding) * and Date operations were identified as a performance bottleneck. Must be called after the * TraverseOptions already has a CalendarService set. */ public void setServiceDays() { final long SEC_IN_DAY = 60 * 60 * 24; final long time = opt.getSecondsSinceEpoch(); this.serviceDays = new ArrayList<ServiceDay>(3); if (calendarService == null && graph.getCalendarService() != null && (opt.getModes() == null || opt.getModes().contains(TraverseMode.TRANSIT))) { LOG.warn("RoutingContext has no CalendarService. Transit will never be boarded."); return; } // This should be a valid way to find yesterday and tomorrow, // since DST changes more than one hour after midnight in US/EU. // But is this true everywhere? for (String agency : graph.getAgencyIds()) { addIfNotExists( this.serviceDays, new ServiceDay(graph, time - SEC_IN_DAY, calendarService, agency)); addIfNotExists(this.serviceDays, new ServiceDay(graph, time, calendarService, agency)); addIfNotExists( this.serviceDays, new ServiceDay(graph, time + SEC_IN_DAY, calendarService, agency)); } }