Dear users, Please note that, from Monday, August 16, 2019, RSA keys shorter than 2048bit will no longer be accepted for security reasons. Please update your keys as needed before this date. If you need assistance with regard to this process, please contact sia@list.lu

Thank you for your understanding.

Commit 060595ad authored by Nico Mack's avatar Nico Mack

Refactoring of API

parent 64c24630
...@@ -42,8 +42,9 @@ public class ClusterManager<P extends Positionable> { ...@@ -42,8 +42,9 @@ public class ClusterManager<P extends Positionable> {
private double radius; private double radius;
private KdComparator<P> comparator; private KdComparator<P> comparator;
private List<P> constituents; private List<P> nodes;
private List<P> clustered; private List<P> clusteredNodes;
private boolean clustersFormed;
private KdTree<P> kdTree; private KdTree<P> kdTree;
...@@ -66,8 +67,9 @@ public class ClusterManager<P extends Positionable> { ...@@ -66,8 +67,9 @@ public class ClusterManager<P extends Positionable> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public ClusterManager(double radius) { public ClusterManager(double radius) {
this.radius = radius; this.radius = radius;
this.constituents = new ArrayList<>(); this.clustersFormed = false;
this.clustered = new ArrayList<>(); this.nodes = new ArrayList<>();
this.clusteredNodes = new ArrayList<>();
this.comparator = (KdComparator<P>) new PositionableComparator(); this.comparator = (KdComparator<P>) new PositionableComparator();
((PositionableComparator) this.comparator).setReferenceState(ScreenCoordinates.class); ((PositionableComparator) this.comparator).setReferenceState(ScreenCoordinates.class);
} }
...@@ -84,44 +86,50 @@ public class ClusterManager<P extends Positionable> { ...@@ -84,44 +86,50 @@ public class ClusterManager<P extends Positionable> {
// Iterate over all candidates. // Iterate over all candidates.
for (P candidate : candidates) { for (P candidate : candidates) {
// Check whether candidate is indeed clusterable and has not already been // Check whether candidate is indeed clusterable.
// coalesced into a cluster.
if ((candidate instanceof Clusterable) && !coalesced.contains(candidate)) { if ((candidate instanceof Clusterable) && ((Clusterable) candidate).isClusterable()) {
// Try to find items within a specific radius. // Next check whether node has not already been coalesced into a cluster.
List<P> coalescing = kdTree.findNearest(candidate, radius); if (!coalesced.contains(candidate)) {
// If there were items within that zone, than the candidate will be // Try to find items within a specific radius.
// a cluster, representing the matching items.
boolean isClustered = (!coalescing.isEmpty()); List<P> coalescing = kdTree.findNearest(candidate, radius);
// However, since we don't rebuild the kdTree for performance reasons // If there were items within that zone, than the candidate will be
// on each iteration, the tree will always hold to the totality of // a cluster, representing the matching items.
// available items. We thus have to remove previously coalesced items
// in order to find out whether we're in the presence of a new cluster
// or not.
coalescing.removeAll(coalesced); boolean isClustered = (!coalescing.isEmpty());
clusterDetected |= (!coalescing.isEmpty());
// Add remaining coalescing items to list of already coalesced items // However, since we don't rebuild the kdTree for performance reasons
// and make sure none of them remains in the retained list. // on each iteration, the tree will always hold to the totality of
// available items. We thus have to remove previously coalesced items
// in order to find out whether we're in the presence of a new cluster
// or not.
if (isClustered) { coalescing.removeAll(coalesced);
coalesced.addAll(coalescing); clusterDetected |= (!coalescing.isEmpty());
retained.removeAll(coalescing);
} // Add remaining coalescing items to list of already coalesced items
// and make sure none of them remains in the retained list.
// Last but not least, set the candidates' clustered flag and add if (isClustered) {
// it to the list of retained items. coalesced.addAll(coalescing);
retained.removeAll(coalescing);
}
((Clusterable) candidate).setClustered(isClustered); // Last but not least, set the candidates' clustered flag and add
if (!retained.contains(candidate)) { // it to the list of retained items.
retained.add(candidate);
((Clusterable) candidate).setClustered(isClustered);
if (!retained.contains(candidate)) {
retained.add(candidate);
}
} }
} else {
retained.add(candidate);
} }
} }
return clusterDetected; return clusterDetected;
...@@ -133,34 +141,51 @@ public class ClusterManager<P extends Positionable> { ...@@ -133,34 +141,51 @@ public class ClusterManager<P extends Positionable> {
// *************************************************************************** // ***************************************************************************
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** /**
* * Clears internal state of this instance. Previously added constituents are no longer known to this
* instance.
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
public void clear() { public void clear() {
this.kdTree = null; this.kdTree = null;
this.constituents.clear(); this.nodes.clear();
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** /**
* @param constituent * sets the list of nodes this cluster manager is aware off. Previously added or set nodes will be
* discarded.
*
* @param newNodes
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
public void addConstituent(P constituent) { public void setNodes(List<P> newNodes) {
if (!this.constituents.contains(constituent)) { this.nodes.clear();
this.constituents.add(constituent); this.nodes.addAll(newNodes);
}
// ---------------------------------------------------------------------------
/**
* Adds the specified node to the list of nodes this instance is aware of.
*
* @param node
*/
// ---------------------------------------------------------------------------
public void addNode(P node) {
if (!this.nodes.contains(node)) {
this.nodes.add(node);
} }
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
public void setup() { public void setup() {
if (!this.constituents.isEmpty()) { if (!this.nodes.isEmpty()) {
kdTree = new KdTree<>(this.constituents, 2, this.comparator); kdTree = new KdTree<>(this.nodes, 2, this.comparator);
} else { } else {
LOGGER.info("No clusterable items available! Clustering is disabled!"); LOGGER.info("No clusterable items available! Clustering is disabled!"); //$NON-NLS-1$
} }
} }
...@@ -175,36 +200,41 @@ public class ClusterManager<P extends Positionable> { ...@@ -175,36 +200,41 @@ public class ClusterManager<P extends Positionable> {
if (kdTree == null) if (kdTree == null)
return; return;
this.clustersFormed = false;
List<P> retained = new ArrayList<>(); List<P> retained = new ArrayList<>();
List<P> coalesced = new ArrayList<>(); List<P> coalesced = new ArrayList<>();
List<P> candidates = new ArrayList<>(this.constituents); List<P> candidates = new ArrayList<>(this.nodes);
boolean clusterDetected; boolean clusterDetected;
int iterations = 0; int iterations = 0;
do { do {
clusterDetected = this.cluster(candidates, retained, coalesced); clusterDetected = this.cluster(candidates, retained, coalesced);
clustersFormed |= clusterDetected;
candidates.clear(); candidates.clear();
candidates.addAll(retained); candidates.addAll(retained);
iterations++; iterations++;
} while (clusterDetected); } while (clusterDetected);
synchronized (clustered) { synchronized (clusteredNodes) {
clustered.clear(); clusteredNodes.clear();
clustered.addAll(retained); clusteredNodes.addAll(retained);
LOGGER.info("Clustering completed in {} iteration(s)! {} Marker(s) remaining!", iterations, clustered.size()); //$NON-NLS-1$ if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Clustering completed in {} iteration(s)! {} Marker(s) remaining!", iterations, clusteredNodes.size()); //$NON-NLS-1$
}
} }
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
public boolean hasClusters() { public boolean haveClustersFormed() {
return !this.clustered.isEmpty(); return this.clustersFormed;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
public synchronized List<P> getClusters() { public synchronized List<P> getClusteredNodes() {
return new ArrayList<>(this.clustered); return new ArrayList<>(this.clusteredNodes);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment