if(logger.isVerbose()) {
logger.verbose("knnJoin...");
}
DataStore<KNNList<D>> knns = knnJoin.run(database, relation);
FiniteProgress progress = logger.isVerbose() ? new FiniteProgress("DeLiClu", relation.size(), logger) : null;
final int size = relation.size();
ClusterOrderResult<D> clusterOrder = new ClusterOrderResult<D>("DeLiClu Clustering", "deliclu-clustering");
heap = new UpdatableHeap<SpatialObjectPair>();
// add start object to cluster order and (root, root) to priority queue
DBID startID = getStartObject(relation);
clusterOrder.add(startID, null, distFunction.getDistanceFactory().infiniteDistance());
int numHandled = 1;
index.setHandled(startID, relation.get(startID));
SpatialDirectoryEntry rootEntry = (SpatialDirectoryEntry) index.getRootEntry();
SpatialObjectPair spatialObjectPair = new SpatialObjectPair(distFunction.getDistanceFactory().nullDistance(), rootEntry, rootEntry, true);
heap.add(spatialObjectPair);
while(numHandled < size) {
if(heap.isEmpty()) {
throw new AbortException("DeLiClu heap was empty when it shouldn't have been.");
}
SpatialObjectPair dataPair = heap.poll();
// pair of nodes
if(dataPair.isExpandable) {
expandNodes(index, distFunction, dataPair, knns);
}
// pair of objects
else {
// set handled
LeafEntry e1 = (LeafEntry) dataPair.entry1;
LeafEntry e2 = (LeafEntry) dataPair.entry2;
final DBID e1id = e1.getDBID();
List<TreeIndexPathComponent<DeLiCluEntry>> path = index.setHandled(e1id, relation.get(e1id));
if(path == null) {
throw new RuntimeException("snh: parent(" + e1id + ") = null!!!");
}
// add to cluster order
clusterOrder.add(e1id, e2.getDBID(), dataPair.distance);
numHandled++;
// reinsert expanded leafs
reinsertExpanded(distFunction, index, path, knns);
if(progress != null) {
progress.setProcessed(numHandled, logger);
}
}
}
if(progress != null) {
progress.ensureCompleted(logger);
}
return clusterOrder;
}