コード例 #1
0
        private static void PlaceLabels(MapSegment segment)
        {
            Console.WriteLine("==== " + segment.name + " ====");

            int num_prefs = Constants.tower_preference_positions.Length;

            // My Linear Algebra library is apparently quite slow, so if you cache these, then it makes a
            // massive increase to the program's speed, particularly in the Simulated Annealing stage.
            Rect2 [] influenced_region = new Rect2 [segment.towers.Count];
            Rect2 [] point_rects       = new Rect2 [segment.towers.Count];
            Rect2 [,] label_pref_rects          = new Rect2 [segment.towers.Count, num_prefs];
            Vector2 [,] label_pref_rect_centres = new Vector2 [segment.towers.Count, num_prefs];

            #region Populate caches
            for (int i = 0; i < segment.towers.Count; i++)
            {
                segment.towers [i].ComputeLabelSize();

                for (int j = 0; j < num_prefs; j++)
                {
                    label_pref_rects [i, j]        = segment.towers [i].GetLabelRectByPreference(j);
                    label_pref_rect_centres [i, j] = label_pref_rects [i, j].centre;
                }

                influenced_region [i] = segment.towers [i].affected_region;
                point_rects [i]       = Rect2.FromCentreAndSize(segment.towers [i].map_position, Vector2.one * Constants.point_radius_outer * 2);

                if (influenced_region [i].w >= Chunk.chunk_size.x)
                {
                    Console.WriteLine("!!! CHUNK SIZE NOT WIDE ENOUGH !!! : " + segment.towers [i].name);
                }

                if (influenced_region [i].h >= Chunk.chunk_size.y)
                {
                    Console.WriteLine("!!! CHUNK SIZE NOT TALL ENOUGH !!! : " + segment.towers [i].name);
                }
            }
            #endregion

            /* Note that this list/relation is symmetric; if (a, b) is in the list then so is (b, a).
             * This way, in order to check every combination symmetrically, only one iteration over the list
             * is required with no code duplication.
             */
            List <(Tower, Tower)> close_tower_pairs = new List <(Tower, Tower)> ();

            #region Generate a list of close tower pairs to speed up comparisons
            int    p          = 0;
            int    q          = 0;
            int    r          = 0;
            int [] ref_counts = new int [segment.towers.Count];

            foreach (Chunk chunk in segment.chunks)
            {
                foreach (Tower tower_2 in chunk.towers_to_compare)
                {
                    foreach (Tower tower_1 in chunk.towers)
                    {
                        if (tower_1 == tower_2)
                        {
                            continue;
                        }

                        p++;

                        if (Rect2.Overlaps(
                                influenced_region [tower_1.index],
                                influenced_region [tower_2.index]
                                ))
                        {
                            q++;

                            close_tower_pairs.Add((tower_1, tower_2));

                            ref_counts [tower_1.index]++;

                            if (tower_1.index < tower_2.index)
                            {
                                r++;
                            }
                        }
                    }
                }
            }
            #endregion

            Console.WriteLine(" >> " + p + " comparisons normally.");
            Console.WriteLine(" >> " + q + " comparisons with reductions (" + r + " unique comparisons).");

            Console.WriteLine(" >> " + ref_counts.Where(x => x == 0).Count() + " towers will be completely ignored.");

            int [,] label_pref_orders = new int [segment.towers.Count, num_prefs];

            #region Decide on the order of preference for label positions
            float [,] label_pref_weights = new float [segment.towers.Count, num_prefs];

            foreach (Chunk chunk in segment.chunks)
            {
                foreach (Tower tower_2 in chunk.towers_to_compare)
                {
                    foreach (Tower tower_1 in chunk.towers)
                    {
                        if (tower_1.index == tower_2.index)
                        {
                            continue;
                        }

                        if (Vector2.SquareDistanceBetween(tower_1.map_position, tower_2.map_position) > 900)
                        {
                            continue;
                        }

                        for (int i = 0; i < num_prefs; i++)
                        {
                            float d = label_pref_rects [tower_1.index, i].ClosestDistanceTo(tower_2.map_position);

                            float dx = label_pref_rect_centres [tower_1.index, i].x - tower_2.map_position.x;
                            float dy = label_pref_rect_centres [tower_1.index, i].y - tower_2.map_position.y;

                            label_pref_weights [tower_1.index, i] += 1f / (dx * dx + dy * dy + 0.01f);
                        }
                    }
                }
            }

            // Sort weights
            for (int i = 0; i < segment.towers.Count; i++)
            {
                List <(int, float)> indices_in_order = Enumerable.Range(0, num_prefs).Select(x => (x, label_pref_weights [i, x])).ToList();