Example #1
0
        /// <summary>
        /// Get the minimum distance between two clusters
        /// </summary>
        /// <param name="a">Cluster A</param>
        /// <param name="b">Cluster B</param>
        /// <returns>Minimum straight-line distance between the two clusters of points</returns>
        public static double GetMinDistance(Cluster a, Cluster b)
        {
            // Compute all distances
            List<double> distances = new List<double>();
            foreach (Point3D pointA in a.points)
            {
                foreach (Point3D pointB in b.points)
                {
                    distances.Add(pointA.DistanceTo(pointB));
                }
            }

            return distances.Min();
        }
        private void WorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
        {
            // Prepare the output file path
            string outputPath = Path.GetDirectoryName(this.InputFile);
            string outputName = Path.GetFileNameWithoutExtension(this.InputFile) + ".cluster";
            string outputFile = Path.Combine(outputPath, outputName);

            // Load the points
            List<Point3D> rawPoints = LoadPointsFromFile(this.InputFile);

            // Collapse the points to the central Z
            var pointZValues = from x in rawPoints select x.Z;
            double centralZ = (pointZValues.Max() + pointZValues.Min())/2.0;
            List<Point3D> freePoints = (from x in rawPoints select new Point3D(x.X, x.Y, centralZ)).ToList();

            // Begin the clustering!
            List<Cluster> clusters = (from x in freePoints select new Cluster(x)).ToList();

            bool action = true;
            int iteration = 0;
            int merges = 0;

            double toleranceInMeters = this.Tolerance/100.0;

            while (action)
            {
                action = false;

                // Iterate through all of the clusters, checking each one against all of the other clusters to see
                // if any valid merges can be made.
                for (int i = 0; i < clusters.Count; i++)
                {
                    // We start with an empty list of valid merges.  As we go through the clusters will we check each one for
                    // clusters that are below the minimum tolerance distance and add them to the list of valid merges.  When
                    // we have finished going through the clusters we will see if there are any valid merges, and if there are
                    // we will perform the merges and construct a new list of clusters, beginning the process again.
                    List<int> validMerges = new List<int>();
                    for (int j = 0; j < clusters.Count; j++)
                    {
                        if (i == j)
                            continue;
                        if (Cluster.GetMinDistance(clusters[i], clusters[j]) < toleranceInMeters)
                        {
                            validMerges.Add(j);
                        }
                    }

                    // If there are valid merges we must now perform them.
                    if (validMerges.Any())
                    {
                        merges += validMerges.Count;
                        validMerges.Add(i);

                        var clustersToMerge = from x in validMerges select clusters[x];
                        Cluster merged = new Cluster(clustersToMerge);

                        // Construct the new list of clusters without any of the ones that were merged

                        List<Cluster> newClusterList = new List<Cluster> {merged};

                        // Now add every cluster after i
                        for (int j = i; j < clusters.Count; j++)
                        {
                            if (!validMerges.Contains(j))
                                newClusterList.Add(clusters[j]);
                        }

                        // Now add every cluster before i, which presumably has no merges
                        for (int j = 0; j < i; j++)
                        {
                            if (!validMerges.Contains(j))
                                newClusterList.Add(clusters[j]);
                        }

                        clusters = newClusterList;
                        action = true;
                        break;
                    }
                }

                // Count the total points
                int totalPoints = 0;
                foreach (var cluster in clusters)
                {
                    totalPoints += cluster.Count;
                }

                iteration++;
                string updateText = string.Format("Clusters: {0}, Merges: {1}, Total Points: {3}, Iteration {2}", clusters.Count, merges, iteration, totalPoints);
                WorkerOnProgressChanged(sender, new ProgressChangedEventArgs(0, updateText));

            }

            File.WriteAllText(outputFile, JsonConvert.SerializeObject(clusters, Formatting.Indented));
        }
Example #3
0
 /// <summary>
 /// Create a cluster from the merge of two clusters
 /// </summary>
 /// <param name="a"></param>
 /// <param name="b"></param>
 public Cluster(Cluster a, Cluster b)
 {
     this.points = new List<Point3D>();
     this.points.AddRange(a.points);
     this.points.AddRange(b.points);
 }