/// <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);
            }
            public static void GetLinks(out LinkBrain2D[] brainLinks, out LinkIO[] ioLinks, Item2D[] brains, Item2D[] io, IOLinkupPriority ioLinkupPriority = IOLinkupPriority.ShortestDistFirst, double brainLinkResistanceMult = 10)
            {
                if (brains == null || brains.Length == 0)
                {
                    brainLinks = null;
                    ioLinks = null;
                    return;
                }
                else if (brains.Length == 1)
                {
                    brainLinks = null;
                    ioLinks = Enumerable.Range(0, io.Length).Select(o => new LinkIO(0, o, brains, io)).ToArray();
                    return;
                }

                // Link brains:brains
                SortedList<Tuple<int, int>, double> allBrainLinks;
                Worker2D_Voronoi.BrainLinks(out allBrainLinks, out brainLinks, brains);

                // Link brains:io
                ioLinks = IOLinks(brains, io, allBrainLinks, ioLinkupPriority, brainLinkResistanceMult);
            }
            public static void GetLinks(out LinkBrain2D[] brainLinks, out LinkIO[] ioLinks, Item2D[] brains, Item2D[] io)
            {
                if (brains == null || brains.Length == 0)
                {
                    brainLinks = null;
                    ioLinks = null;
                    return;
                }
                else if (brains.Length == 1)
                {
                    brainLinks = null;
                    ioLinks = Enumerable.Range(0, io.Length).Select(o => new LinkIO(0, o, brains, io)).ToArray();
                    return;
                }

                // Link brains:brains
                SortedList<Tuple<int, int>, double> allBrainLinks;
                BrainLinks(out allBrainLinks, out brainLinks, brains);

                // Link brains:io
                ioLinks = IOLinks(brains, io, allBrainLinks);
            }