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); } } } } } }
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); } } } }
/// <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)); }
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; } } }