Пример #1
0
        /// <summary>
        /// A class that generates colors for clusters.
        /// </summary>
        /// <param name="cs">A clustering.</param>
        /// <param name="degreeStart">The lowest allowable hue, in degrees.</param>
        /// <param name="degreeEnd">The highest allowable hue, in degrees.</param>
        /// <param name="offset">Shift, in degrees.  E.g., if degreeStart = 0 and
        /// degreeEnd = 360 and offset = 45, the effective degreeStart is 45 mod 360 and
        /// the effective degreeEnd is 405 mod 360.</param>
        public ClusterColorer(Clustering cs, double degreeStart, double degreeEnd, double offset)
        {
            // sort clusters so that repainting on subsequent
            // runs produces a stable coloring
            var cSorted = cs.OrderBy(c => c.OrderBy(a => new Tuple <int, int>(a.X, a.Y)).ToArray()[0]).ToArray();

            // init address-to-cluster lookup
            // address-to-cluster lookup
            var cdict = new Dictionary <AST.Address, HashSet <AST.Address> >();

            foreach (Cluster c in cSorted)
            {
                foreach (AST.Address addr in c)
                {
                    cdict.Add(addr, c);
                }
            }

            // init cluster neighbor map
            var cNeighbors = new Dictionary <HashSet <AST.Address>, HashSet <HashSet <AST.Address> > >();

            foreach (Cluster c in cSorted)
            {
                cNeighbors.Add(c, new HashSet <Cluster>());
                var neighbors = AdjacentCells(c);
                foreach (Cluster c2 in cSorted)
                {
                    // append if c is adjacent to c2
                    if (neighbors.Intersect(c2).Count() > 0)
                    {
                        cNeighbors[c].Add(c2);
                    }
                }
            }

            // rank clusters by their degree
            Cluster[] csSorted2 = cSorted.OrderByDescending(c => cNeighbors[c].Count).ToArray();

            // greedily assign colors by degree, largest first;
            // aka Welsh-Powell heuristic

            // init angle generator
            var angles = new AngleGenerator(degreeStart, degreeEnd);

            foreach (Cluster c in csSorted2)
            {
                // get neighbor colors
                var ns   = cNeighbors[c].ToArray();
                var nscs = new HashSet <Color>();
                foreach (Cluster n in ns)
                {
                    if (assignedColors.ContainsKey(n))
                    {
                        nscs.Add(assignedColors[n]);
                    }
                }

                // color getter
                Func <Color> colorf = () =>
                                      HSLtoColor(
                    new HSL(
                        mod(
                            angles.NextAngle() + offset,
                            degreeEnd - degreeStart
                            ),
                        SATURATION,
                        LUMINOSITY
                        )
                    );

                // get initial color
                var color = colorf();
                while (nscs.Contains(color))
                {
                    // get next color
                    color = colorf();
                }

                // save color
                assignedColors[c] = color;
            }
        }
Пример #2
0
        /// <summary>
        /// A class that generates colors for clusters.
        /// </summary>
        /// <param name="clustering">A clustering.</param>
        /// <param name="degreeStart">The lowest allowable hue, in degrees.</param>
        /// <param name="degreeEnd">The highest allowable hue, in degrees.</param>
        /// <param name="offset">Shift, in degrees.  E.g., if degreeStart = 0 and
        /// degreeEnd = 360 and offset = 45, the effective degreeStart is 45 mod 360 and
        /// the effective degreeEnd is 405 mod 360.</param>
        /// <param name="ih">An InvertedHistogram so that coloring is fingerprint-sensitive.</param>
        public ClusterColorer(Clustering clustering, double degreeStart, double degreeEnd, double offset, ROInvertedHistogram ih, Graph g)
        {
            // merge clusters by fingerprint
            var x      = MergeClustersByFingerprint(clustering, ih);
            var cs     = x.Item1;
            var ccdict = x.Item2;

            // get neighbors
            var neighbors = Neighbors(cs);

            // rank clusters by their degree and break ties using fingerprint (if given fingerprints)
            // also sort clusters so that repainting on subsequent
            // runs produces a stable coloring
            //Cluster[] csSorted =
            //    cs.OrderByDescending(c => neighbors[c].Count)
            //      .ThenBy(c => ih[c.First()].Item3.ToString()).ToArray();
            // size of biggest cluster
            var maxsz    = cs.Select(c => c.Count).Max();
            var csSorted = cs.OrderBy(hs =>
            {
                var first = hs.First();
                if (!g.isFormula(first))
                {
                    return(0);
                }
                else
                {
                    return(maxsz - hs.Count);
                }
            }).ThenBy(c => ih[c.First()].Item3.ToString()).ToArray();

            // greedily assign colors by degree, largest first;
            // aka Welsh-Powell heuristic

            // init angle generator
            var angles = new AngleGenerator(degreeStart, degreeEnd);

            // color getter
            Func <Color> colorf = () =>
                                  HSLtoColor(
                new HSL(
                    mod(
                        angles.NextAngle() + offset,
                        degreeEnd - degreeStart
                        ),
                    SATURATION,
                    LUMINOSITY
                    )
                );

            foreach (Cluster c in csSorted)
            {
                // get neighbor colors
                var ns   = neighbors[c].ToArray();
                var nscs = new HashSet <Color>();
                foreach (Cluster n in ns)
                {
                    if (assignedColors.ContainsKey(n))
                    {
                        nscs.Add(assignedColors[n]);
                    }
                }

                // get initial color
                var color = colorf();
                while (nscs.Contains(color))
                {
                    // if we've already chosen this one, get next color
                    color = colorf();
                }

                // save this color for each _original_ cluster in c
                foreach (Cluster corig in ccdict[c])
                {
                    assignedColors[corig] = color;
                }
            }
        }