Exemplo n.º 1
0
    public MeshNode ConstructMeshTree()
    {
        // Create the grid
        CreateGrid();

        // Do the hierarchical clustering on the grid
        Dictionary <Vector3, MeshNode> slotClusterAssign = new Dictionary <Vector3, MeshNode>();
        int maxClusterSize = 1;

        // Assign the slotClusterAssign
        foreach (Vector3 key in slots.Keys)
        {
            slotClusterAssign.Add(key, new MeshNode(slots[key].GetMesh(), key, slots[key].GetOffset()));
        }

        // Processing queue
        Queue <List <Vector3> > clusters = new Queue <List <Vector3> >();

        // Add initial clusters to the queue
        System.Random  rand        = new System.Random();
        List <Vector3> randomOrder = new List <Vector3>(slotClusterAssign.Keys);

        randomOrder.Sort((x, y) => rand.Next(100000));
        foreach (Vector3 key in randomOrder)
        {
            List <Vector3> cluster = new List <Vector3>();
            cluster.Add(key);
            clusters.Enqueue(cluster);
        }

        while (maxClusterSize != slots.Count && clusters.Count != 0)
        {
            // Get the processing position
            foreach (Vector3 procPos in clusters.Dequeue())
            {
                // Get the node behind the key
                MeshNode procNode = slotClusterAssign[procPos];

                // Get all the positions inside the cluster (this nodes cluster)
                HashSet <Vector3> selfClusterPositions = new HashSet <Vector3>(procNode.GetPositions());

                // Find the neighboring cluster with the lowest size
                int     minClusterSize = 1000;
                Vector3 minClusterKey  = new Vector3(10000f, 10000f, 10000f);
                foreach (Vector3 n in basisvectors)
                {
                    // Get a neighbor key
                    Vector3 candidate = procPos + n;;

                    // Check if the candidate exists
                    if (!slots.ContainsKey(candidate))
                    {
                        continue;
                    }

                    // Check if the candidate is in the same cluster as current node
                    if (selfClusterPositions.Contains(candidate))
                    {
                        continue;
                    }

                    // Check the size of the cluster
                    MeshNode neigh = slotClusterAssign[candidate];
                    if (neigh.GetSize() < minClusterSize)
                    {
                        minClusterSize = neigh.GetSize();
                        minClusterKey  = candidate;
                    }
                }

                // No eligable neighbours
                if (minClusterSize == 1000)
                {
                    continue;
                }

                // Now we know the cluster we want to pair with
                // Get the node of the cluster
                MeshNode clusterNode = slotClusterAssign[minClusterKey];

                // Create a new cluster where the children are the current cluster and the neighbor cluster
                MeshNode newNode = new MeshNode(clusterNode.GetMesh(), procNode.GetMesh());
                newNode.AddChild(clusterNode);
                newNode.AddChild(procNode);

                // Get all the positions in the new cluster
                List <Vector3> clusterPositions = newNode.GetPositions();

                // Update the cluster assignment
                foreach (Vector3 position in clusterPositions)
                {
                    slotClusterAssign[position] = newNode;
                }

                // Add the cluster positions to the processing queue
                clusters.Enqueue(clusterPositions);


                // Get the cluster size
                if (newNode.GetSize() > maxClusterSize)
                {
                    maxClusterSize = newNode.GetSize();

                    // Early exit if task is already finished
                    if (maxClusterSize == slots.Count)
                    {
                        break;
                    }
                }
            }
        }

        // Return the topmost cluster
        return(slotClusterAssign[new Vector3(0f, 0f, 0f)]);
    }