예제 #1
0
        private void match_best_fit(IEnumerable <Vector2> nodes, NodeTargets best_fit)
        {
            foreach (Vector2 node in nodes)
            {
                if (best_fit.ContainsKey(node))
                {
                    foreach (CardinalDirections dir in new List <CardinalDirections> {
                        CardinalDirections.Down,
                        CardinalDirections.Left,
                        CardinalDirections.Right,
                        CardinalDirections.Up
                    })
                    {
                        // If there's anything in this direction
                        if (best_fit[node].ContainsKey(dir))
                        {
                            Vector2            dest    = best_fit[node][dir].Item1;
                            CardinalDirections opp_dir =
                                (CardinalDirections)(CardinalDirections.All - dir);
                            // If the destination also points back to this node
                            if (best_fit.ContainsKey(dest) &&
                                best_fit[dest].ContainsKey(opp_dir) &&
                                best_fit[dest][opp_dir].Item1 == node)
                            {
                                add_destination(node, dest, dir);

                                best_fit[node].Remove(dir);
                                best_fit[dest].Remove(opp_dir);
                            }
                        }
                    }
                }
            }
        }
예제 #2
0
        private void match_unpaired_best_fit(NodeTargets best_fit)
        {
            var ordered_best_pairs = best_fit.SelectMany(x => x.Value
                                                         .Select(y => new Tuple <Vector2, CardinalDirections, Vector2, float>(x.Key, y.Key, y.Value.Item1, y.Value.Item2)))
                                     .OrderBy(x => x.Item4)
                                     .ToList();

            foreach (var pair in ordered_best_pairs)
            {
                Vector2            node    = pair.Item1;
                CardinalDirections dir     = pair.Item2;
                Vector2            dest    = pair.Item3;
                CardinalDirections opp_dir = (CardinalDirections)(CardinalDirections.All - dir);
                // If the route is possible
                if (!Map[node].ContainsKey(dir) && !Map[dest].ContainsKey(opp_dir))
                {
                    add_destination(node, dest, dir);

                    best_fit[node].Remove(dir);
                    if (best_fit.ContainsKey(dest))
                    {
                        best_fit[dest].Remove(opp_dir);
                    }
                }
            }
        }
예제 #3
0
        /// <param name="nodes">Set of nodes to test</param>
        /// <param name="max_angle">Maximum angle off a cardinal direction to look for neighbors</param>
        /// <param name="angle_factor">Factor used to sort neighbors. The higher the factor, the higher the preference for neighbors with a lower angle.</param>
        /// <param name="true_best_fit">Pre-calculated set of best fits, to remove neighbors that are too far off base</param>
        private NodeTargets find_best_fit(
            IEnumerable <Vector2> nodes,
            float max_angle,
            float angle_factor,
            NodeTargets true_best_fit = null)
        {
            var result = nodes.ToDictionary(node => node, node =>
            {
                var map = new Dictionary <CardinalDirections, Tuple <Vector2, float> >();
                foreach (CardinalDirections dir in new List <CardinalDirections> {
                    CardinalDirections.Down,
                    CardinalDirections.Left,
                    CardinalDirections.Right,
                    CardinalDirections.Up
                })
                {
                    var destinations = possible_nodes(node, dir, max_angle);
                    // Remove nodes that are further away than the true best fit and also further in tangential directions
                    if (true_best_fit != null)
                    {
                        destinations = destinations.Where(dest =>
                        {
                            if (!true_best_fit[node].ContainsKey(dir))
                            {
                                return(true);
                            }
                            // If the distance to the target is more than four times the distance to the best target
                            if (distance(node, dest, vertical_direction(dir)) >
                                distance(true_best_fit[node][dir].Item1, node,
                                         vertical_direction(dir)) * 4 * 4)
                            {
                                return(false);
                            }
                            return(valid_tangent(node, dest, true_best_fit[node][dir].Item1, dir));
                        });
                    }
                    if (destinations.Any())
                    {
                        Vector2 best_dest = destinations
                                            .OrderBy(dest => destination_fitness(node, dest, dir, max_angle, angle_factor))
                                            .First();
                        float fitness = destination_fitness(node, best_dest, dir, max_angle, angle_factor);
                        map[dir]      = new Tuple <Vector2, float>(best_dest, fitness);
                    }
                }
                return(map);
            });

            return(result
                   .Where(x => x.Value.Any())
                   .ToDictionary(p => p.Key, p => p.Value));
        }
예제 #4
0
        private void add_neighbor_tangets(NodeTargets neighbor_tangents)
        {
            var neighbors = neighbor_tangents
                            .Where(x => x.Value.Any())
                            .ToDictionary(p => p.Key, p => p.Value);

            foreach (var pair in neighbors)
            {
                foreach (var tangent in pair.Value)
                {
                    Map[pair.Key][tangent.Key] = tangent.Value.Item1;
                }
            }
        }