void KMeansClustering()
    {
        print("k-means started..");

        // calculate centroid points
        int k_means = k_clusters;

        int[] k_calculations = new int[k_means];
        for (int i = 0; i < k_means; i++)
        {
            decimal f        = Decimal.Divide(i, k_means);
            float   division = (float)f;
            k_calculations[i] = Mathf.RoundToInt(colombs_nodes.Count * (division));
            print("k means calculation: " + f + " = " + i + " / " + k_means);
        }
        print("step 0, k_means = " + k_means);
        int k_num = 0;

        foreach (int num in k_calculations)
        {
            //print(k_num +" : "+num);
            k_num++;
        }

        // Assigning centroids
        GameObject[] centroids    = new GameObject[k_means];
        VisualNode[] vs_c         = new VisualNode[k_means];
        ArrayList[]  clusternodes = new ArrayList[k_means];
        for (int i = 0; i < k_means; i++)
        {
            centroids[i]          = (GameObject)colombs_nodes[k_calculations[i]];
            vs_c[i]               = centroids[i].GetComponent <VisualNode>();
            vs_c[i].distinct_node = true;
            Vector3 localScale = vs_c[i].transform.localScale;
            if (transform.localScale.x < 2)
            {
                //vs_c[i].transform.localScale = new Vector3(localScale.x * 2, localScale.y * 2, localScale.z * 2);
            }
            clusternodes[i] = new ArrayList();
            clusternodes[i].Add(vs_c[i]);
        }
        print("step 1");

        // Assigning nodes to centroids on Euclidean Distance
        foreach (GameObject g in colombs_nodes)
        {
            if (centroids.Contains(g) == false)
            {
                VisualNode n          = g.GetComponent <VisualNode>();
                float[]    dist_array = new float[k_means];
                for (int i = 0; i < dist_array.Length; i++)
                {
                    dist_array[i] = Vector3.Distance(g.transform.localPosition, centroids[i].transform.localPosition);
                }
                float smallest_dist  = dist_array.Min();
                int   smallest_index = 0;
                for (int i = 0; i < dist_array.Length; i++)
                {
                    if (dist_array[i] == smallest_dist)
                    {
                        smallest_index = i;
                    }
                }
                clusternodes[smallest_index].Add(n);
            }
        }
        print("step 2");

        // Create Cluster Objects
        GameObject[] clusterObjects = new GameObject[k_means];
        for (int i = 0; i < k_means; i++)
        {
            clusterObjects[i] = new GameObject();
            clusterObjects[i].AddComponent <ClusterBehaviour>();
            clusterObjects[i].GetComponent <ClusterBehaviour>().setArrayList(clusternodes[i]);
            clusterObjects[i].GetComponent <ClusterBehaviour>().setClusterCentre(centroids[i]);
        }
        print("step 3");

        int cluster_index = 0;

        // Go through the three centroids and generate the clusters
        foreach (GameObject cluster_object in clusterObjects)
        {
            ClusterBehaviour clu = cluster_object.GetComponent <ClusterBehaviour>();
            // return nodes of cluster c
            ArrayList cluster_array = clu.returnClusterNodes();
            // setup meshfilters for child objects
            MeshFilter[] meshFilters = new MeshFilter[clu.returnClusterNodes().Count + 1];
            // combine instance mesh array
            CombineInstance[] combine = new CombineInstance[meshFilters.Length];
            // Color of cluster
            Color col = UnityEngine.Random.ColorHSV(0.1f, 0.8f, 0.7f, 1f, 0.5f, 1f);


            // go through each child node and add to meshFilter array
            // first cluster node
            GameObject first_node = clu.gameObject;
            meshFilters[0]       = centroids[cluster_index].GetComponent <MeshFilter>();
            combine[0].mesh      = meshFilters[0].sharedMesh;
            combine[0].transform = meshFilters[0].transform.localToWorldMatrix;
            meshFilters[0].gameObject.SetActive(false);
            nodes_already_clustered.Add(first_node.GetComponent <VisualNode>());
            // add boxcollider for each node
            BoxCollider b = cluster_object.AddComponent <BoxCollider>();
            b.size      = new Vector3(0.05f, 0.05f, 0.05f);
            b.center    = clu.transform.position;
            b.isTrigger = true;

            /*
             * ArrayList edge = n.getAllocatedEdges();
             * if (edge.Count > 0) {
             *  GameObject index0 = edge[0] as GameObject;
             *  foreach (GameObject ga in edge) {
             *      LineRenderer l = ga.GetComponent<LineRenderer>();
             *      l.material.SetColor("_TintColor", new Color(col.r, col.g, col.b, 0.01f));
             *  }
             * }
             */

            int k = 1;
            foreach (VisualNode v in clu.returnClusterNodes())
            {
                if (nodes_already_clustered.Contains(v) == false)
                {
                    GameObject g = v.gameObject;

                    meshFilters[k]       = g.GetComponent <MeshFilter>();
                    combine[k].mesh      = meshFilters[k].sharedMesh;
                    combine[k].transform = meshFilters[k].transform.localToWorldMatrix;
                    meshFilters[k].gameObject.SetActive(false);
                    //nodes.Add(v);
                    nodes_already_clustered.Add(v);
                    // add boxcollider for each node
                    BoxCollider b1 = cluster_object.AddComponent <BoxCollider>();
                    b1.size      = new Vector3(0.05f, 0.05f, 0.05f);
                    b1.center    = g.transform.position;
                    b1.isTrigger = true;
                    ArrayList edge1 = v.getAllocatedEdges();
                    v.transform.parent = cluster_object.transform;
                    vs_c[cluster_index].addClusterNode(v);

                    if (edge1.Count > 0)
                    {
                        GameObject index0 = edge1[0] as GameObject;

                        foreach (GameObject ga in edge1)
                        {
                            //LineRenderer l = ga.GetComponent<LineRenderer>();
                            //l.material.SetColor("_TintColor", new Color(col.r, col.g, col.b, 0.01f));
                        }
                    }
                }
                else
                {
                }
                k++;
            }

            // set the parent of the cluster to visualization object
            cluster_object.transform.parent = this.transform;
            // set the name of the cluster
            //cluster_object.transform.name = first_node.transform.name + " cluster";

            // add meshfilter to new cluster
            cluster_object.AddComponent <MeshFilter>();
            cluster_object.AddComponent <MeshRenderer>();
            cluster_object.GetComponent <MeshFilter>().mesh = new Mesh();
            // combine all the meshes in the mesh array "combine"
            cluster_object.GetComponent <MeshFilter>().mesh.CombineMeshes(combine);
            cluster_object.GetComponent <MeshRenderer>().material = nodeMat;
            // assign random color to cluster
            cluster_object.GetComponent <MeshRenderer>().material.color = col;
            clusters.Add(clu);
            cluster_index++;
        }
        EdgeManager edgeManager = Camera.main.GetComponent <EdgeManager> ();
        ArrayList   glEdges     = edgeManager.getEdges();

        print(glEdges.Count + "glEdge count");
        for (int i = 0; i < glEdges.Count; i++)
        {
            Edge e = (Edge)glEdges[i];
            e.setColor(e.getTransformRef().parent.GetComponent <MeshRenderer>().material.color);
        }
        print("step 4 DONE");
        clusterAllNodes         = true;
        graph_layout_recognized = false;
    }
    // on interacting with button
    void OnCollisionEnter(Collision other)
    {
        if (other.gameObject.tag == "Controller")
        {
            if (d.getVisualNode().hiding() == true)
            {
                off = 1;
                gameObject.GetComponent <Image>().color = Color.black;
                print("on");
            }
            if (d.getVisualNode().hiding() == false)
            {
                off = 0;
                gameObject.GetComponent <Image>().color = Color.white;
                print("off");
            }
            // unhighlight previous node
            if (visualnode != null && d.getVisualNode() != visualnode)
            {
                visualnode.transform.parent.GetComponent <ClusterBehaviour>().ExitHighlight();
            }


            // set UI to white

            // Get cluster nodes and cluster class

            ClusterBehaviour c            = d.getVisualNode().transform.parent.GetComponent <ClusterBehaviour>();
            ArrayList        clusterNodes = c.returnClusterNodes();
            // if filtering cluster nodes
            if (off == 0)
            {
                d.getVisualNode().setHiding(true);
                foreach (VisualNode v in clusterNodes)
                {
                    if (v != d.getVisualNode())
                    {
                        graph.addIgnoreNode(v);
                    }
                }
                foreach (VisualNode v in clusterNodes)
                {
                    if (v != d.getVisualNode())
                    {
                        v.OnHideEdges();
                    }
                }
            }
            // if unfiltering cluster nodes
            if (off == 1)
            {
                d.getVisualNode().setHiding(false);
                foreach (VisualNode v in clusterNodes)
                {
                    if (v != d.getVisualNode())
                    {
                        graph.removeIgnoreNode(v);
                    }
                }
                foreach (VisualNode v in clusterNodes)
                {
                    if (v != d.getVisualNode())
                    {
                        v.UnHideEdges();
                    }
                }
            }
            off++;
            // reset back to 0 if greater than 1
            if (off > 1)
            {
                off = 0;
            }
            c.RecreateCluster();
            visualnode = d.getVisualNode();
        }
    }