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.getInstance().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);