예제 #1
0
  public GraphIndex(Graph graph) {
    LOG.info("Indexing graph...");

    for (String feedId : graph.getFeedIds()) {
      for (Agency agency : graph.getAgencies(feedId)) {
        Map<String, Agency> agencyForId = agenciesForFeedId.getOrDefault(feedId, new HashMap<>());
        agencyForId.put(agency.getId(), agency);
        this.agenciesForFeedId.put(feedId, agencyForId);
      }
    }

    Collection<Edge> edges = graph.getEdges();
    /* We will keep a separate set of all vertices in case some have the same label.
     * Maybe we should just guarantee unique labels. */
    Set<Vertex> vertices = Sets.newHashSet();
    for (Edge edge : edges) {
      vertices.add(edge.getFromVertex());
      vertices.add(edge.getToVertex());
      if (edge instanceof TablePatternEdge) {
        TablePatternEdge patternEdge = (TablePatternEdge) edge;
        TripPattern pattern = patternEdge.getPattern();
        patternForId.put(pattern.code, pattern);
      }
    }
    for (Vertex vertex : vertices) {
      vertexForId.put(vertex.getLabel(), vertex);
      if (vertex instanceof TransitStop) {
        TransitStop transitStop = (TransitStop) vertex;
        Stop stop = transitStop.getStop();
        stopForId.put(stop.getId(), stop);
        stopVertexForStop.put(stop, transitStop);
        stopsForParentStation.put(stop.getParentStation(), stop);
      }
    }
    for (TransitStop stopVertex : stopVertexForStop.values()) {
      Envelope envelope = new Envelope(stopVertex.getCoordinate());
      stopSpatialIndex.insert(envelope, stopVertex);
    }
    for (TripPattern pattern : patternForId.values()) {
      patternsForFeedId.put(pattern.getFeedId(), pattern);
      patternsForRoute.put(pattern.route, pattern);

      for (Trip trip : pattern.getTrips()) {
        patternForTrip.put(trip, pattern);
        tripForId.put(trip.getId(), trip);
      }
      for (Stop stop : pattern.getStops()) {
        patternsForStop.put(stop, pattern);
      }
    }
    for (Route route : patternsForRoute.asMap().keySet()) {
      routeForId.put(route.getId(), route);
    }

    // Copy these two service indexes from the graph until we have better ones.
    calendarService = graph.getCalendarService();
    serviceCodes = graph.serviceCodes;
    this.graph = graph;
    LOG.info("Done indexing graph.");
  }
예제 #2
0
 /**
  * Stop clustering is slow to perform and only used in profile routing for the moment. Therefore
  * it is not done automatically, and any method requiring stop clusters should call this method to
  * ensure that the necessary indexes are lazy-initialized.
  */
 public synchronized void clusterStopsAsNeeded() {
   if (stopClusterSpatialIndex == null) {
     clusterStops();
     LOG.info("Creating a spatial index for stop clusters.");
     stopClusterSpatialIndex = new HashGridSpatialIndex<StopCluster>();
     for (StopCluster cluster : stopClusterForId.values()) {
       Envelope envelope = new Envelope(new Coordinate(cluster.lon, cluster.lat));
       stopClusterSpatialIndex.insert(envelope, cluster);
     }
   }
 }
예제 #3
0
 /**
  * Find transfer candidates for profile routing. TODO replace with an on-street search using the
  * existing profile router functions.
  */
 public Map<StopCluster, Double> findNearbyStopClusters(StopCluster sc, double radius) {
   Map<StopCluster, Double> ret = Maps.newHashMap();
   Envelope env = new Envelope(new Coordinate(sc.lon, sc.lat));
   env.expandBy(
       SphericalDistanceLibrary.metersToLonDegrees(radius, sc.lat),
       SphericalDistanceLibrary.metersToDegrees(radius));
   for (StopCluster cluster : stopClusterSpatialIndex.query(env)) {
     // TODO this should account for area-like nature of clusters. Use size of bounding boxes.
     double distance = SphericalDistanceLibrary.distance(sc.lat, sc.lon, cluster.lat, cluster.lon);
     if (distance < radius) ret.put(cluster, distance);
   }
   return ret;
 }
예제 #4
0
 /**
  * FIXME OBA parentStation field is a string, not an AgencyAndId, so it has no agency/feed scope
  * But the DC regional graph has no parent stations pre-defined, so no use dealing with them for
  * now. However Trimet stops have "landmark" or Transit Center parent stations, so we don't use
  * the parent stop field.
  *
  * <p>Ideally in the future stop clusters will replicate and/or share implementation with GTFS
  * parent stations.
  *
  * <p>We can't use a similarity comparison, we need exact matches. This is because many street
  * names differ by only one letter or number, e.g. 34th and 35th or Avenue A and Avenue B.
  * Therefore normalizing the names before the comparison is essential. The agency must provide
  * either parent station information or a well thought out stop naming scheme to cluster stops --
  * no guessing is reasonable without that information.
  */
 public void clusterStops() {
   int psIdx = 0; // unique index for next parent stop
   LOG.info("Clustering stops by geographic proximity and name...");
   // Each stop without a cluster will greedily claim other stops without clusters.
   for (Stop s0 : stopForId.values()) {
     if (stopClusterForStop.containsKey(s0))
       continue; // skip stops that have already been claimed by a cluster
     String s0normalizedName = StopNameNormalizer.normalize(s0.getName());
     StopCluster cluster = new StopCluster(String.format("C%03d", psIdx++), s0normalizedName);
     // LOG.info("stop {}", s0normalizedName);
     // No need to explicitly add s0 to the cluster. It will be found in the spatial index query
     // below.
     Envelope env = new Envelope(new Coordinate(s0.getLon(), s0.getLat()));
     env.expandBy(
         SphericalDistanceLibrary.metersToLonDegrees(CLUSTER_RADIUS, s0.getLat()),
         SphericalDistanceLibrary.metersToDegrees(CLUSTER_RADIUS));
     for (TransitStop ts1 : stopSpatialIndex.query(env)) {
       Stop s1 = ts1.getStop();
       double geoDistance =
           SphericalDistanceLibrary.fastDistance(
               s0.getLat(), s0.getLon(), s1.getLat(), s1.getLon());
       if (geoDistance < CLUSTER_RADIUS) {
         String s1normalizedName = StopNameNormalizer.normalize(s1.getName());
         // LOG.info("   --> {}", s1normalizedName);
         // LOG.info("       geodist {} stringdist {}", geoDistance, stringDistance);
         if (s1normalizedName.equals(s0normalizedName)) {
           // Create a bidirectional relationship between the stop and its cluster
           cluster.children.add(s1);
           stopClusterForStop.put(s1, cluster);
         }
       }
     }
     cluster.computeCenter();
     stopClusterForId.put(cluster.id, cluster);
   }
   //        LOG.info("Done clustering stops.");
   //        for (StopCluster cluster : stopClusterForId.values()) {
   //            LOG.info("{} at {} {}", cluster.name, cluster.lat, cluster.lon);
   //            for (Stop stop : cluster.children) {
   //                LOG.info("   {}", stop.getName());
   //            }
   //        }
 }