TrueClusterHistogram::TrueClusterHistogram(features::Feature *feature_,
					   DataPointCollection dps):
  feature(feature_), 
  ncenters(Parameters::getInstance()->getiParameter("clustering_means")), 
  nsegments(1), 
  patch_size(Parameters::getInstance()->getiParameter("clustering_patch_size")),
  spacing
(Parameters::getInstance()->getiParameter("clustering_spacing")),
  histogram_type(Parameters::getInstance()->
		 getiParameter("clustering_histogram_type")),
  parameters(Parameters::getUniqueClone()),
  feature_type("")
{
  
  patch_collection patches = getPatches(dps, ncenters * 100);
  KMeansClustering clustering;
  centers = clustering.cluster(patches);
}
void ColorGenerator::Generate(Vector<RGBColor> &Result, const Vec3f &Scale)
{
    const UINT ColorCount = Result.Length();
    KMeansClustering<Vec3f, Vec3fKMeansMetric> Clustering;
    
    Vector<Vec3f> AllColors(ColorCount * 25);
    const UINT AllColorsCount = AllColors.Length();
    for(UINT Index = 0; Index < AllColorsCount; Index++)
    {
        Vec3f CurColor = Vec3f(rnd(), rnd(), rnd());
        while(CurColor.x + CurColor.y + CurColor.z < 0.5f)
        {
            CurColor = Vec3f(rnd(), rnd(), rnd());
        }
        AllColors[Index] = Vec3f(CurColor.x * Scale.x, CurColor.y * Scale.y, CurColor.z * Scale.z);
    }

    Clustering.Cluster(AllColors, ColorCount, 20, false);

    for(UINT ColorIndex = 0; ColorIndex < ColorCount; ColorIndex++)
    {
        Result[ColorIndex] = RGBColor(Clustering.ClusterCenter(ColorIndex));
    }
}
void SpectralClustering::Cluster(const DenseMatrix<double> &S, UINT kMeansClusters, UINT reducedDimensionCount, Method method, Vector<UINT> &clusterIDs, SpectralClusteringCache *cache)
{
    const UINT pointCount = S.RowCount();
    
    Console::WriteLine("Spectral clustering on " + String(pointCount) + " points, " + String(kMeansClusters) + " clusters, " + String(reducedDimensionCount) + String(" dimensions"));
    
    DenseMatrix<double> L(pointCount, pointCount);
    MakeLaplacian(S, method, L);

    Vector<double> eigenvalues;
    DenseMatrix<double> eigenvectors;
    {
        if(cache != NULL && cache->eigenvalues.Length() == pointCount)
        {
            Console::WriteString("Loading eigensystem from cache...");
            eigenvalues = cache->eigenvalues;
            eigenvectors = cache->eigenvectors;
        }
        else
        {
            Clock timer;
            Console::WriteString("Solving eigensystem...");
            L.EigenSystemTNT(eigenvalues, eigenvectors);
            Console::WriteLine(String(timer.Elapsed()) + "s");
        }
        if(cache != NULL)
        {
            cache->eigenvalues = eigenvalues;
            cache->eigenvectors = eigenvectors;
        }
    }

    //
    // Note that the eigensystem is sorted in decreasing order.
    //
    const bool useLargestEigenvector = (method == RandomWalk || method == Symmetric);
    
    Vector<VecNf> points(pointCount);
    for(UINT pointIndex = 0; pointIndex < pointCount; pointIndex++)
    {
        VecNf &curPoint = points[pointIndex];
        curPoint.v.Allocate(reducedDimensionCount);
        for(UINT dimensionIndex = 0; dimensionIndex < reducedDimensionCount; dimensionIndex++)
        {
            if(useLargestEigenvector)
            {
                curPoint[dimensionIndex] = float(eigenvectors(pointIndex, pointCount - dimensionIndex - 1));
            }
            else
            {
                curPoint[dimensionIndex] = float(eigenvectors(pointIndex, dimensionIndex));
            }
            
        }
    }

    if(method == Symmetric)
    {
        for(UINT pointIndex = 0; pointIndex < pointCount; pointIndex++)
        {
            points[pointIndex] = VecNf::Normalize(points[pointIndex]);
        }
    }

    KMeansClustering<VecNf, VecNfKMeansMetric> clustering;
    clustering.Cluster(points, kMeansClusters, 100);
    
    clusterIDs.Allocate(pointCount);
    for(UINT pointIndex = 0; pointIndex < pointCount; pointIndex++)
    {
        clusterIDs[pointIndex] = clustering.QuantizeToNearestClusterIndex(points[pointIndex]);
    }
}