/// <summary> /// This finds brains that are really close together, and turns them into sets (the rest of the brains become 1 item sets) /// </summary> internal static Set2D[] IOLinks_PreMergeBrains(Item2D[] brains, SortedList<Tuple<int, int>, double> links) { if (!IOPREMERGE_SHOULD) { return Enumerable.Range(0, brains.Length).Select(o => new Set2D(o, brains)).ToArray(); } // Get the AABB of the brains, and use the diagonal as the size var aabb = Math2D.GetAABB(brains.Select(o => o.Position)); double maxDistance = (aabb.Item2 - aabb.Item1).Length; // Figure out the max distance allowed for a merge double threshold = maxDistance * IOPREMERGE_DISTANCE; // Find links that should be merged var closePairs = links. Where(o => o.Value <= threshold). OrderBy(o => o.Value). ToArray(); if (closePairs.Length == 0) { return Enumerable.Range(0, brains.Length).Select(o => new Set2D(o, brains)).ToArray(); } // Combine any close pairs that share a point (turn pairs into triples) List<List<int>> sets = IOLinks_PreMergeBrains_Sets(closePairs); // Build the final list return IOLinks_PreMergeBrains_Centers(sets, brains, links); }
/// <summary> /// Link brains to each other (delaunay graph, then prune thin triangles) /// </summary> internal static void BrainLinks(out SortedList<Tuple<int, int>, double> all, out LinkBrain2D[] pruned, Item2D[] brains) { if (brains.Length < 2) { throw new ArgumentException("This method requires at least two brains: " + brains.Length.ToString()); } else if (brains.Length == 2) { all = GetLengths(new[] { Tuple.Create(0, 1) }, brains); pruned = all.Keys.Select(o => new LinkBrain2D(o.Item1, o.Item2, brains)).ToArray(); return; } TriangleIndexed[] triangles = Math2D.GetDelaunayTriangulation(brains.Select(o => o.Position).ToArray(), brains.Select(o => o.Position.ToPoint3D()).ToArray()); all = GetLengths(TriangleIndexed.GetUniqueLines(triangles), brains); // Prune links that don't make sense pruned = PruneBrainLinks(triangles, all, brains); }