Beispiel #1
0
        private static Tuple<int, double>[][] ItemItemResistance(LinkItem[] items, double linkResistanceMult)
        {
            // Get the AABB, and use the diagonal as the size
            var aabb = Math3D.GetAABB(items.Select(o => o.Position));
            double maxDistance = (aabb.Item2 - aabb.Item1).Length;

            // Get links between the items and distances of each link
            var links2 = UtilityCore.GetPairs(items.Length).
                Select(o =>
                {
                    double distance = (items[o.Item1].Position - items[o.Item2].Position).Length;
                    double resistance = (distance / maxDistance) * linkResistanceMult;

                    return Tuple.Create(o.Item2, o.Item1, resistance);
                }).
                ToArray();

            Tuple<int, double>[][] retVal = new Tuple<int, double>[items.Length][];

            for (int cntr = 0; cntr < items.Length; cntr++)
            {
                // Store all links for this item
                retVal[cntr] = links2.
                    Where(o => o.Item1 == cntr || o.Item2 == cntr).       // find links between this item and another
                    Select(o => Tuple.Create(o.Item1 == cntr ? o.Item2 : o.Item1, o.Item3)).     // store the link to the other item and the resistance
                    OrderBy(o => o.Item2).
                    ToArray();
            }

            return retVal;
        }
Beispiel #2
0
        /// <summary>
        /// This links closest items together
        /// </summary>
        private static Tuple<int, int>[] Link12_Closest(LinkItem[] items1, LinkItem[] items2)
        {
            var retVal = new Tuple<int, int>[items2.Length];

            for (int cntr = 0; cntr < items2.Length; cntr++)
            {
                int closest = items1.
                    Select((o, i) => new { Index = i, Position = o.Position, DistSqr = (o.Position - items2[cntr].Position).LengthSquared }).
                    OrderBy(o => o.DistSqr).
                    First().
                    Index;

                retVal[cntr] = Tuple.Create(closest, cntr);
            }

            return retVal;
        }
Beispiel #3
0
        private static Tuple<int, int>[] Link12_Extra(Tuple<int, int>[] initial, LinkItem[] items1, LinkItem[] items2, DistributeDistances distances, ItemLinker_ExtraArgs extraArgs)
        {
            Random rand = StaticRandom.GetRandomForThread();

            int wholePercent = extraArgs.Percent.ToInt_Floor();

            List<int> addOrder = new List<int>();

            if (extraArgs.BySize)
            {
                double totalSize = items2.Sum(o => o.Size);
                double maxSize = extraArgs.Percent * totalSize;
                double usedSize = 0;

                if (extraArgs.EvenlyDistribute)
                {
                    #region by size, evenly distribute

                    // Add some complete passes if over 100% percent
                    for (int cntr = 0; cntr < wholePercent; cntr++)
                    {
                        addOrder.AddRange(UtilityCore.RandomRange(0, items2.Length));
                    }

                    usedSize = wholePercent * totalSize;

                    #endregion
                }

                #region by size, distribute the rest

                //NOTE: Building this list by size so that larger items have a higher chance of being chosen
                var bySize = items2.
                    Select((o, i) => Tuple.Create(i, o.Size / totalSize)).
                    OrderByDescending(o => o.Item2).
                    ToArray();

                // Keep selecting items unti the extra size is consumed (or if no more can be added)
                while (true)
                {
                    bool foundOne = false;

                    for (int cntr = 0; cntr < 1000; cntr++)     // this is an infinite loop detector
                    {
                        int attemptIndex = UtilityCore.GetIndexIntoList(rand.NextDouble(), bySize);     // get the index into the list that the rand percent represents
                        attemptIndex = bySize[attemptIndex].Item1;      // get the index into items2

                        if (items2[attemptIndex].Size + usedSize <= maxSize)
                        {
                            foundOne = true;
                            usedSize += items2[attemptIndex].Size;
                            addOrder.Add(attemptIndex);
                            break;
                        }
                    }

                    if (!foundOne)
                    {
                        // No more will fit
                        break;
                    }
                }

                #endregion
            }
            else
            {
                if (extraArgs.EvenlyDistribute)
                {
                    #region ignore size, evenly distribute

                    // Add some complete passes if over 100% percent
                    for (int cntr = 0; cntr < wholePercent; cntr++)
                    {
                        addOrder.AddRange(UtilityCore.RandomRange(0, items2.Length));
                    }

                    // Add some items based on the portion of percent that is less than 100%
                    int remainder = (items2.Length * (extraArgs.Percent - wholePercent)).
                        ToInt_Round();

                    addOrder.AddRange(UtilityCore.RandomRange(0, items2.Length, remainder));

                    #endregion
                }
                else
                {
                    #region ignore size, randomly distribute

                    int totalCount = (items2.Length * extraArgs.Percent).
                        ToInt_Round();

                    //NOTE: UtilityCore.RandomRange stops when the list is exhausted, and makes sure not to have dupes.  That's not what is wanted
                    //here.  Just randomly pick X times
                    addOrder.AddRange(Enumerable.Range(0, totalCount).Select(o => rand.Next(items2.Length)));

                    #endregion
                }
            }

            return AddLinks(items1, items2, distances, addOrder, initial);
        }
Beispiel #4
0
        private static void GetItemDelaunay(out SortedList<Tuple<int, int>, double> segments, out TriangleIndexed[] triangles, LinkItem[] items)
        {
            Tuple<int, int>[] links = null;

            if (items.Length < 2)
            {
                links = new Tuple<int, int>[0];
                triangles = new TriangleIndexed[0];
            }
            else if (items.Length == 2)
            {
                links = new[] { Tuple.Create(0, 1) };
                triangles = new TriangleIndexed[0];
            }
            else if (items.Length == 3)
            {
                links = new[] 
                    {
                        Tuple.Create(0, 1),
                        Tuple.Create(0, 2),
                        Tuple.Create(1, 2),
                    };

                triangles = new[] { new TriangleIndexed(0, 1, 2, items.Select(o => o.Position).ToArray()) };
            }
            else
            {
                Tetrahedron[] tetras = Math3D.GetDelaunay(items.Select(o => o.Position).ToArray());
                links = Tetrahedron.GetUniqueLines(tetras);
                triangles = Tetrahedron.GetUniqueTriangles(tetras);
            }

            segments = GetLengths(links, items);
        }