Commit 24907935 authored by Nico Mack's avatar Nico Mack

Generalized ClusterManager class

Added possibility to specify target coordinate system to
PositionalComparator
parent ef3f2f34
......@@ -17,6 +17,8 @@
package lu.list.itis.dkd.tui.feature.cluster;
import lu.list.itis.dkd.tui.utility.Positionable;
import lu.list.itis.dkd.tui.utility.ScreenCoordinates;
import lu.list.itis.dkd.tui.utility.kdtree.KdComparator;
import lu.list.itis.dkd.tui.utility.kdtree.KdTree;
import java.util.ArrayList;
......@@ -26,16 +28,21 @@ import java.util.List;
* @author nico.mack@list.lu
* @since 2.6
* @version 1.0.0
* @param <P>
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class ClusterManager {
public class ClusterManager<P extends Positionable> {
private KdTree<Positionable> kdTree;
private double radius;
private KdComparator<P> comparator;
private List<P> constituents;
private List<P> clustered;
private KdTree<P> kdTree;
// ---------------------------------------------------------------------------
// ***************************************************************************
......@@ -47,8 +54,13 @@ public class ClusterManager {
*/
// ---------------------------------------------------------------------------
@SuppressWarnings("unchecked")
public ClusterManager(double radius) {
this.radius = radius;
this.constituents = new ArrayList<>();
this.clustered = new ArrayList<>();
this.comparator = (KdComparator<P>) new PositionableComparator();
((PositionableComparator) this.comparator).setReferenceState(ScreenCoordinates.class);
}
// ---------------------------------------------------------------------------
......@@ -57,10 +69,10 @@ public class ClusterManager {
// ***************************************************************************
// ---------------------------------------------------------------------------
private synchronized List<Clusterable> getClusterable(List<Positionable> candidates) {
private synchronized List<Clusterable> getClusterable(List<P> candidates) {
List<Clusterable> results = new ArrayList<>();
for (Positionable candidate : candidates) {
for (P candidate : candidates) {
if (Clusterable.class.isAssignableFrom(candidate.getClass())) {
results.add((Clusterable) candidate);
}
......@@ -74,24 +86,60 @@ public class ClusterManager {
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* @param positionables
*
*/
// ---------------------------------------------------------------------------
public void refresh(List<Positionable> positionables) {
kdTree = new KdTree<>(positionables, 2, new PositionableComparator());
List<Positionable> coallesced = new ArrayList<>();
List<Clusterable> clusters = new ArrayList<>();
public void clear() {
this.kdTree = null;
this.constituents.clear();
}
for (Positionable candidate : positionables) {
if ((candidate instanceof Clusterable) && coallesced.contains(candidate)) {
List<Positionable> coallescing = kdTree.findNearest(candidate, radius);
// ---------------------------------------------------------------------------
/**
* @param constituent
*/
// ---------------------------------------------------------------------------
public void addConstituent(P constituent) {
if (!this.constituents.contains(constituent)) {
this.constituents.add(constituent);
}
}
// ---------------------------------------------------------------------------
/**
* @param positionables
*/
// ---------------------------------------------------------------------------
public void refresh() {
kdTree = new KdTree<>(this.constituents, 2, this.comparator);
clustered.clear();
List<P> coallesced = new ArrayList<>();
for (P candidate : this.constituents) {
if ((candidate instanceof Clusterable) && !coallesced.contains(candidate)) {
List<P> coallescing = kdTree.findNearest(candidate, radius);
if (coallescing.size() > 1) {
List<Clusterable> clusterable = this.getClusterable(coallescing);
((Clusterable) candidate).coalesce(clusterable);
coallesced.addAll(coallescing);
clusters.add((Clusterable) candidate);
((Clusterable) candidate).coalesce(clusterable);
}
clustered.add(candidate);
}
}
}
// ---------------------------------------------------------------------------
public boolean hasClusters() {
return !this.clustered.isEmpty();
}
// ---------------------------------------------------------------------------
public List<P> getClusters() {
return this.clustered;
}
// ---------------------------------------------------------------------------
......
......@@ -16,8 +16,10 @@
*/
package lu.list.itis.dkd.tui.feature.cluster;
import lu.list.itis.dkd.tui.utility.CoordinateState;
import lu.list.itis.dkd.tui.utility.Point;
import lu.list.itis.dkd.tui.utility.Positionable;
import lu.list.itis.dkd.tui.utility.ScreenCoordinates;
import lu.list.itis.dkd.tui.utility.kdtree.KdComparator;
/**
......@@ -27,27 +29,39 @@ import lu.list.itis.dkd.tui.utility.kdtree.KdComparator;
*/
public class PositionableComparator implements KdComparator<Positionable> {
private Class<? extends CoordinateState> referenceState = ScreenCoordinates.class;
public void setReferenceState(Class<? extends CoordinateState> state) {
this.referenceState = state;
}
/** {@inheritDoc} */
@Override
public int compare(Positionable o1, Positionable o2, int axis) {
Point pos1 = o1.getPosition();
Point pos2 = o2.getPosition();
Point pos1 = o1.getPosition().clone();
Point pos2 = o2.getPosition().clone();
pos1.toCoordinates(this.referenceState);
pos2.toCoordinates(this.referenceState);
return pos1.compareTo(pos2, axis);
}
/** {@inheritDoc} */
@Override
public double getDistance(Positionable o1, Positionable o2) {
Point pos1 = o1.getPosition();
Point pos2 = o2.getPosition();
Point pos1 = o1.getPosition().clone();
Point pos2 = o2.getPosition().clone();
pos1.toCoordinates(this.referenceState);
pos2.toCoordinates(this.referenceState);
return pos1.getDistance(pos2);
}
/** {@inheritDoc} */
@Override
public double getDistance(Positionable o1, Positionable o2, int axis) {
Point pos1 = o1.getPosition();
Point pos2 = o2.getPosition();
Point pos1 = o1.getPosition().clone();
Point pos2 = o2.getPosition().clone();
pos1.toCoordinates(this.referenceState);
pos2.toCoordinates(this.referenceState);
return pos1.getDistance(pos2, axis);
}
......
......@@ -58,6 +58,7 @@ public abstract class Marker implements Positionable, Clusterable, Cloneable {
this.isClusterable = builder.isClusterable;
this.coronas = builder.coronas;
this.positions = builder.positions;
this.clustered = new ArrayList<>();
}
// ---------------------------------------------------------------------------
......@@ -67,6 +68,7 @@ public abstract class Marker implements Positionable, Clusterable, Cloneable {
this.isClusterable = original.isClusterable;
this.coronas = original.cloneCoronas();
this.positions = original.clonePositions();
this.clustered = new ArrayList<>();
}
// ---------------------------------------------------------------------------
......
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