private void floodFillSimilarClusters( int unitpos, int[] clusterassoc, double[][] lkvalues, int[][] neighbors, int startunitpos) { // check if already associated to other cluster (end of recursion) if (clusterassoc[unitpos] != unitpos && clusterassoc[unitpos] != startunitpos) return; Vector<Integer> joinedunits = new Vector<Integer>(); // check neighbors (starts with index 1) for join candidates for (int i = 1; i < neighbors[unitpos].length; i++) { if (neighbors[unitpos][i] != -1 && // on the som clusterassoc[neighbors[unitpos][i]] != startunitpos && // not already in cluster clusterassoc[neighbors[unitpos][i]] == neighbors[unitpos][i]) { // not part of any other cluster // join two units iff summed up vector differs below threshold from both original vectors double[] cosNormA = Vec.cosineNormalize(Vec.cloneVector(lkvalues[unitpos])); double[] cosNormB = Vec.cosineNormalize(Vec.cloneVector(lkvalues[neighbors[unitpos][i]])); double[] sumAB = Vec.add(lkvalues[unitpos], lkvalues[neighbors[unitpos][i]]); double[] cosNormAB = Vec.cosineNormalize(Vec.cloneVector(sumAB)); if (Vec.euclDist(cosNormA, cosNormAB) < 0.6 && Vec.euclDist(cosNormB, cosNormAB) < 0.6) { // similar units -> join clusterassoc[neighbors[unitpos][i]] = startunitpos; // write new vector to all associated for (int k = 0; k < clusterassoc.length; k++) { if (clusterassoc[k] == startunitpos) { lkvalues[k] = sumAB; } } // Vec.copyTo(lkvalues[unitpos], sumAB); // Vec.copyTo(lkvalues[neighbors[unitpos][i]], sumAB); // add to list for recursion joinedunits.addElement(new Integer(neighbors[unitpos][i])); } } } // recursion over joined units Iterator<Integer> iit = joinedunits.iterator(); while (iit.hasNext()) { floodFillSimilarClusters( iit.next().intValue(), clusterassoc, lkvalues, neighbors, startunitpos); } }