Пример #1
0
        private void CollideBodies(BarnesHutTree tree, float maxRadius)
        {
            var collisions = new Dictionary <Body, HashSet <Body> >();

            foreach (Body a in _bodies)
            {
                Vector2     origin      = new Vector2(a.Position.X - 2 * maxRadius, a.Position.Y - 2 * maxRadius);
                Rectangle   range       = new Rectangle(origin, 4 * maxRadius, 4 * maxRadius);
                List <Body> closeBodies = tree.Query(range);

                foreach (Body b in closeBodies)
                {
                    if (a == b)
                    {
                        continue;
                    }

                    float distance = Vector2.Distance(a.Position, b.Position);

                    if (distance < (a.Radius + b.Radius))
                    {
                        // If there is A, there must not be B inside of it.
                        if (collisions.ContainsKey(a) && collisions.GetValueOrDefault(a).Contains(b) == false)
                        {
                            collisions.GetValueOrDefault(a).Add(b);
                        }
                        // Either there is no B, or if there is, there must not be A inside of B.
                        else if (collisions.ContainsKey(b) == false || (collisions.ContainsKey(b) && collisions.GetValueOrDefault(b).Contains(a) == false))
                        {
                            collisions.Add(a, new HashSet <Body>()
                            {
                                b
                            });
                        }
                    }
                }
            }

            foreach (var collision in collisions)
            {
                ComputeCollision(collision.Key, collision.Value);

                foreach (Body body in collision.Value)
                {
                    _bodies.Remove(body);
                }
            }
        }
Пример #2
0
        private List <Vector2> ComputeForces(BarnesHutTree tree)
        {
            var forces = new List <Vector2>();

            foreach (Body a in _bodies)
            {
                var forcesOnBody = Vector2.Zero;
                List <VirtualBody> virtualBodies = tree.Query(a, Theta);

                foreach (VirtualBody b in virtualBodies)
                {
                    float distance = Vector2.Distance(a.Position, b.Position);
                    float force    = GravitationalConstant * ((a.Mass * b.Mass) / (float)Math.Pow(distance, 2));

                    // if (distance < float.Epsilon)
                    // {
                    //  Console.WriteLine("d {0} f {1} a {2} b {3}", distance, force, a, b);
                    //  throw new Exception("Epsylon");
                    // }

                    // if (float.IsNaN(force))
                    // {
                    //  Console.WriteLine("d {0} f {1} a {2} b {3}", distance, force, a, b);
                    //  throw new Exception("NaN");
                    // }

                    float angle = (float)Math.Atan2(b.Position.Y - a.Position.Y, b.Position.X - a.Position.X);
                    forcesOnBody.X += (float)Math.Cos(angle) * force;
                    forcesOnBody.Y += (float)Math.Sin(angle) * force;
                }

                forces.Add(forcesOnBody);
            }

            return(forces);
        }