public SymImage addItem(int[,] imageMatrix)
        {
            //Check if image matrix size is correct
            if (imageMatrix.GetLength(0) != matrixSize || imageMatrix.GetLength(0) != matrixSize)
            {
                throw new ArgumentException("The image matrix must be " + matrixSize + "x" + matrixSize + ".");
            }

            //Create a new SymImage
            SymImage symImage = new SymImage(imageMatrix, generateID());

            //Calculate distance to all other items in the list
            foreach (SymImage sImg in symImages)
            {
                symDistances.Add(new SymImageDistance(symImage, sImg));
            }

            //Add item to symImages list. It is added after distance calculations are done, so it is note compared to itself.
            symImages.Add(symImage);

            //Perform hierarchy analysis
            createHierarchy();

            //Return the new SymImage
            return(symImage);
        }
        public void removeItem(SymImage symImage)
        {
            //Remove from symDistances list
            symDistances.RemoveAll(p => p.symImageA == symImage || p.symImageB == symImage);

            //Remove from symImages list
            symImages.Remove(symImage);
        }
        public void createHierarchy()
        {
            //Create copy of original data
            List <SymImage>         clusters         = symImages.ToList();
            List <SymImageDistance> clusterDistances = symDistances.ToList();

            //Merge all pairs and until list is empty
            int AutoStop = 10;

            while (clusterDistances.Count > 0)
            {
                AutoStop--;
                if (AutoStop == 0)
                {
                    AutoStop = 0;
                }

                //Sort the distance list
                clusterDistances = clusterDistances.OrderBy(p => p.Distance).ToList();

                //Get first distance entry, since it is the nearest pair.
                SymImageDistance distEntry = clusterDistances[0];

                //Remove all items referencing these two items.
                clusters.Remove(distEntry.symImageA);
                clusters.Remove(distEntry.symImageB);
                clusterDistances.RemoveAll(p => p.symImageA == distEntry.symImageA || p.symImageA == distEntry.symImageB);
                clusterDistances.RemoveAll(p => p.symImageB == distEntry.symImageA || p.symImageB == distEntry.symImageB);

                //Create a new cluster from the distEntry items
                SymImage newCluster = new SymImage(new List <SymImage>()
                {
                    distEntry.symImageA, distEntry.symImageB
                }, generateID());


                //Calculate distance to all existing clusters
                foreach (SymImage cluster in clusters)
                {
                    clusterDistances.Add(new SymImageDistance(newCluster, cluster));
                }


                //Add new cluster to list
                clusters.Add(newCluster);
            }

            //Save results
            clusterHierarchy = clusters.ToList();
        }
            //Constructors
            public SymImageDistance(SymImage symImage1, SymImage symImage2)
            {
                //Compare IDs and put lower ID in position A
                if (symImage1.ID < symImage2.ID)
                {
                    a = symImage1;
                    b = symImage2;
                }
                else
                {
                    b = symImage1;
                    a = symImage2;
                }

                //Calculate distance and save
                distance = a.distanceFrom(b);
            }
            //Methods - Public
            public int distanceFrom(SymImage symImageB)
            {
                //Result variable
                int distance = 0;

                //Cycle through every X pixel of image A
                for (int aX = 0; aX < matrixSize; aX++)
                {
                    //Cycle through every Y pixel of image A
                    for (int aY = 0; aY < matrixSize; aY++)
                    {
                        //Check if pixel A is white. Skip these
                        if (this.ImageMatrix[aX, aY] == 0)
                        {
                            continue;
                        }

                        //Cycle through every X pixel of image B
                        for (int bX = 0; bX < matrixSize; bX++)
                        {
                            //Cycle through every Y pixel of image B
                            for (int bY = 0; bY < matrixSize; bY++)
                            {
                                //Check if pixel B is white. Skip these
                                if (symImageB.ImageMatrix[bX, bY] == 0)
                                {
                                    continue;
                                }

                                //Calculate difference between coordinates
                                distance += Convert.ToInt32(Math.Sqrt(Math.Pow(aX - bX, 2) + Math.Pow(aY - bY, 2)));
                            }
                        }
                    }
                }

                //Normalized the distance by dividing by number of black pixels
                distance = distance / ((this.numBlackPixels + symImageB.numBlackPixels) / 2);

                return(distance);
            }