21 package org.matsim.core.network.algorithms.intersectionSimplifier;
23 import java.io.BufferedWriter;
24 import java.io.IOException;
27 import org.apache.commons.csv.CSVFormat;
28 import org.apache.commons.csv.CSVPrinter;
29 import org.apache.logging.log4j.LogManager;
30 import org.apache.logging.log4j.Logger;
69 private final String[]
csvHeader =
new String[]{
"clusterId",
"lon",
"lat",
"numberOfActivities"};
76 this.inputPoints = nodesToCluster;
80 for (
Node node : inputPoints) {
81 if (node == null || node.getCoord() == null) {
85 if (nullCounter > 0) {
86 log.warn(
"In DJCluster: of the " + inputPoints.size() +
" points, " + nullCounter +
" were null.");
89 this.clusterList =
new ArrayList<>();
101 if (this.inputPoints.isEmpty()) {
102 log.warn(
"DJCluster.clusterInput() called, but no points to cluster.");
105 log.info(
"Clustering input points. This may take a while.");
107 int clusterIndex = 0;
108 int pointMultiplier = 1;
109 int uPointCounter = 0;
110 int cPointCounter = 0;
115 double xMin = Double.POSITIVE_INFINITY;
116 double yMin = Double.POSITIVE_INFINITY;
117 double xMax = Double.NEGATIVE_INFINITY;
118 double yMax = Double.NEGATIVE_INFINITY;
120 for (
Node node : this.inputPoints) {
121 Coord c = node.getCoord();
124 log.warn(
"Coord is null. Number of points in list: " + inputPoints.size());
126 xMin = Math.min(xMin, c.
getX());
127 yMin = Math.min(yMin, c.
getY());
128 xMax = Math.max(xMax, c.
getX());
129 yMax = Math.max(yMax, c.
getY());
139 log.info(
"Place points in QuadTree.");
141 quadTree =
new QuadTree<>(xMin - 1, yMin - 1, xMax + 1, yMax + 1);
142 List<ClusterActivity> listOfPoints =
new ArrayList<>();
143 for (
int i = 0; i < this.inputPoints.size(); i++) {
144 double x = inputPoints.get(i).getCoord().getX();
145 double y = inputPoints.get(i).getCoord().getY();
147 quadTree.
put(x, y, cp);
148 listOfPoints.add(cp);
151 log.info(
"Done placing activities.");
157 int pointCounter = 0;
158 while (pointCounter < listOfPoints.
size()) {
165 List<ClusterActivity> uN =
new ArrayList<>(neighbourhood.size());
166 List<ClusterActivity> cN =
new ArrayList<>(neighbourhood.size());
168 if (cp.getCluster() == null) {
174 if (neighbourhood.size() < minimumPoints) {
180 lostPoints.put(p.
getId(), p);
182 }
else if (!cN.isEmpty()) {
187 List<Cluster> localClusters =
new ArrayList<>();
188 Cluster smallestCluster = cN.getFirst().getCluster();
189 for (
int i = 1; i < cN.size(); i++) {
190 if (Integer.parseInt(cN.get(i).getCluster().getId().toString()) <
191 Integer.parseInt(smallestCluster.getId().toString())) {
192 smallestCluster = cN.get(i).getCluster();
194 if (!localClusters.contains(cN.get(i).getCluster())) {
195 localClusters.add(cN.get(i).getCluster());
198 for (
Cluster DigicoreCluster : localClusters) {
199 if (!DigicoreCluster.equals(smallestCluster)) {
200 List<ClusterActivity> thisClusterList = DigicoreCluster.
getPoints();
203 clusterActivity.setCluster(smallestCluster);
205 smallestCluster.getPoints().add(clusterActivity);
212 smallestCluster.getPoints().add(cp);
213 cp.setCluster(smallestCluster);
215 if (lostPoints.containsKey(cp.getId())) {
216 lostPoints.remove(cp.getId());
226 cp.setCluster(newCluster);
229 if (lostPoints.containsKey(cp.getId())) {
230 lostPoints.remove(cp.getId());
239 if (pointCounter == pointMultiplier) {
240 log.info(
" Points clustered: " + pointCounter);
241 pointMultiplier *= 4;
248 log.info(
" Points clustered: " + pointCounter +
" (Done)");
249 int sum = cPointCounter + uPointCounter;
250 log.info(
"Sum should add up: " + cPointCounter +
" (clustered) + " 251 + uPointCounter +
" (unclustered) = " + sum);
254 log.info(
"Unclustered points: ");
256 log.info(String.format(
" %.6f,%.6f", ca.getCoord().getX(), ca.getCoord().getY()));
258 log.info(
"New way of unclustered points:");
259 log.info(
" Number: " + lostPoints.size());
269 log.info(
"Building the cluster list (2 steps)");
271 Map<Cluster, List<ClusterActivity>> clusterMap =
new HashMap<>();
274 log.info(
"Step 1 of 2:");
275 log.info(
"Number of ClusterPoints to process: " + listOfPoints.
size());
278 int cpMultiplier = 1;
280 Cluster theCluster = ca.getCluster();
281 if (theCluster != null) {
282 if (!clusterMap.containsKey(theCluster)) {
283 List<ClusterActivity> newList =
new ArrayList<>();
284 clusterMap.put(theCluster, newList);
286 clusterMap.get(theCluster).add(ca);
290 if (++cpCounter == cpMultiplier) {
291 log.info(
" ClusterPoints processed: " + cpCounter +
" (" + String.format(
"%3.2f", ((
double) cpCounter / (
double) listOfPoints.size()) * 100) +
"%)");
297 log.info(
" ClusterPoints processed: " + cpCounter +
" (Done)");
301 log.info(
"Step 2 of 2:");
302 log.info(
"Number of clusters to process: " + clusterMap.keySet().size());
304 int clusterCounter = 0;
305 int clusterMultiplier = 1;
306 int clusterNumber = 0;
307 for (Map.Entry<
Cluster, List<ClusterActivity>> e : clusterMap.entrySet()) {
308 Cluster digicoreCluster = e.getKey();
309 List<ClusterActivity> listOfClusterPoints = e.getValue();
310 if (listOfClusterPoints.size() >= minimumPoints) {
314 clusterList.add(digicoreCluster);
315 }
else if (!silent) {
316 log.warn(
" ... why do we HAVE a cluster with too few points?...");
320 if (++clusterCounter == clusterMultiplier) {
321 log.info(
" Clusters processed: " + clusterCounter +
" (" + String.format(
"%3.2f", ((
double) clusterCounter / (
double) clusterMap.keySet().size()) * 100) +
"%)");
322 clusterMultiplier *= 2;
327 log.info(
" Clusters processed: " + clusterCounter +
" (Done)");
328 log.info(
"DensityCluster list built.");
355 int clusterCount = 0;
356 int clusterMultiplier = 1;
357 int totalClusters = clusterList.size();
359 log.info(
"Writing a total of " + totalClusters +
" to file.");
363 CSVPrinter printer =
new CSVPrinter(output, CSVFormat.Builder.create().setHeader(csvHeader).setDelimiter(delimiter).build())) {
364 for (
Cluster c : clusterList) {
365 c.setCenterOfGravity();
366 Coord center = c.getCenterOfGravity();
369 String.format(Locale.US,
"%.6f", center.
getX()),
370 String.format(Locale.US,
"%.6f", center.
getY()),
376 if (clusterCount == clusterMultiplier) {
377 log.info(
" Clusters written: " + clusterCount);
378 clusterMultiplier *= 2;
383 log.info(
" Clusters written: " + clusterCount +
" (Done)");
385 }
catch (IOException e) {
386 log.error(
"Could not write cluster to file.", e);
List< ClusterActivity > getPoints()
DensityCluster(List< Node > nodesToCluster, boolean silent)
void writeClustersToFile(String filename)
static BufferedWriter getBufferedWriter(URL url, Charset charset, boolean append)
final Map< Id< Coord >, ClusterActivity > lostPoints
final List< Node > inputPoints
static< T > Id< T > create(final long key, final Class< T > type)
void setDelimiter(String delimiter)
void setCenterOfGravity()
boolean put(final double x, final double y, final T value)
final String [] csvHeader
QuadTree< ClusterActivity > getClusteredPoints()
Map< Id< Coord >, ClusterActivity > getLostPoints()
void setClusterId(Id< Cluster > id)
List< Cluster > getClusterList()
Collection< T > getDisk(final double x, final double y, final double distance)
void clusterInput(double radius, int minimumPoints)
final List< Cluster > clusterList
QuadTree< ClusterActivity > quadTree