/// <summary>
 /// Create a new Spring instance
 ///<param name="fi1">  the first ForceItem endpoint</param>
 /// <param name="fi2"> the second ForceItem endpoint          </param>
 ///  <param name="k">the spring tension co-efficient                             </param>
 ///  <param name="len">the spring's resting length                                               </param>
 /// </summary>
 public Spring(ForceItem fi1, ForceItem fi2, float k, float len)
 {
     item1  = fi1;
     item2  = fi2;
     coeff  = k;
     length = len;
 }
Exemple #2
0
 /// <summary>
 /// Inserts the specified force.
 /// </summary>
 /// <param name="p">The p.</param>
 /// <param name="n">The n.</param>
 /// <param name="x1">The x1.</param>
 /// <param name="y1">The y1.</param>
 /// <param name="x2">The x2.</param>
 /// <param name="y2">The y2.</param>
 private void Insert(ForceItem p, QuadTreeNode n, float x1, float y1, float x2, float y2)
 {
     // try to Insert particle p at node n in the quadtree
     // by construction, each leaf will contain either 1 or 0 particles
     if (n.hasChildren)
     {
         // n contains more than 1 particle
         InsertHelper(p, n, x1, y1, x2, y2);
     }
     else if (n.value != null)
     {
         // n contains 1 particle
         if (IsSameLocation(n.value, p))
         {
             InsertHelper(p, n, x1, y1, x2, y2);
         }
         else
         {
             ForceItem v = n.value; n.value = null;
             InsertHelper(v, n, x1, y1, x2, y2);
             InsertHelper(p, n, x1, y1, x2, y2);
         }
     }
     else
     {
         // n is empty, so is a leaf
         n.value = p;
     }
 }
Exemple #3
0
        /// <summary>
        /// Determines whether the two force are at the same location.
        /// </summary>
        /// <param name="f1">The f1.</param>
        /// <param name="f2">The f2.</param>
        /// <returns>
        ///     <c>true</c> if [is same location] [the specified f1]; otherwise, <c>false</c>.
        /// </returns>
        private static bool IsSameLocation(ForceItem f1, ForceItem f2)
        {
            float dx = Math.Abs(f1.Location[0] - f2.Location[0]);
            float dy = Math.Abs(f1.Location[1] - f2.Location[1]);

            return(dx < 0.01 && dy < 0.01);
        }
Exemple #4
0
        /// <summary>
        /// Inserts helper method.
        /// </summary>
        /// <param name="p">The p.</param>
        /// <param name="n">The n.</param>
        /// <param name="x1">The x1.</param>
        /// <param name="y1">The y1.</param>
        /// <param name="x2">The x2.</param>
        /// <param name="y2">The y2.</param>
        private void InsertHelper(ForceItem p, QuadTreeNode n, float x1, float y1, float x2, float y2)
        {
            float x = p.Location[0], y = p.Location[1];
            float splitx = (x1 + x2) / 2;
            float splity = (y1 + y2) / 2;
            int   i      = (x >= splitx ? 1 : 0) + (y >= splity ? 2 : 0);

            // create new child node, if necessary
            if (n.children[i] == null)
            {
                n.children[i] = factory.GetQuadTreeNode();
                n.hasChildren = true;
            }
            // update bounds
            if (i == 1 || i == 3)
            {
                x1 = splitx;
            }
            else
            {
                x2 = splitx;
            }
            if (i > 1)
            {
                y1 = splity;
            }
            else
            {
                y2 = splity;
            }
            // recurse
            Insert(p, n.children[i], x1, y1, x2, y2);
        }
 /// <summary>
 /// Create a new Spring instance
 ///<param name="fi1">  the first ForceItem endpoint</param>
 /// <param name="fi2"> the second ForceItem endpoint          </param>
 ///  <param name="k">the spring tension co-efficient                             </param>
 ///  <param name="len">the spring's resting length                                               </param>
 /// </summary>
 public Spring(ForceItem fi1, ForceItem fi2, float k, float len)
 {
     item1 = fi1;
     item2 = fi2;
     coeff = k;
     length = len;
 }
Exemple #6
0
 /// <summary>
 /// Checks a ForceItem to make sure its values are all valid numbers(i.e., not NaNs).
 /// </summary>
 /// <param name="item">The item to check.</param>
 /// <returns>
 ///     <c>true</c> if the specified item is valid; otherwise, <c>false</c>.
 /// </returns>
 public static bool isValid(ForceItem item)
 {
     return
         (!(float.IsNaN(item.location[0]) || float.IsNaN(item.location[1]) ||
            float.IsNaN(item.plocation[0]) || float.IsNaN(item.plocation[1]) ||
            float.IsNaN(item.velocity[0]) || float.IsNaN(item.velocity[1]) ||
            float.IsNaN(item.force[0]) || float.IsNaN(item.force[1])));
 }
Exemple #7
0
 /**
  * Calculates the force vector acting on the given item.
  * @param item the ForceItem for which to compute the force
  */
 public override void GetForce(ForceItem item)
 {
     try {
         ForceHelper(item, root, xMin, yMin, xMax, yMax);
     }
     catch (StackOverflowException e) {
         // TODO: safe to remove?
         Trace.WriteLine(e.Message);
     }
 }
Exemple #8
0
        /// <summary>
        /// Add a Spring to the simulation.
        /// </summary>
        /// <param name="item1">the first endpoint of the spring</param>
        /// <param name="item2"> the second endpoint of the spring</param>
        /// <param name="coeff">the spring coefficient</param>
        /// <param name="length">the spring length</param>
        /// <returns> the Spring added to the simulation</returns>
        public Spring addSpring(ForceItem item1, ForceItem item2, float coeff, float length)
        {
            if (item1 == null || item2 == null)
            {
                throw new ArgumentException("ForceItems must be non-null");
            }
            Spring s = Spring.Factory.getSpring(item1, item2, coeff, length);

            springs.Add(s);
            return(s);
        }
Exemple #9
0
 /// <summary>
 /// Inserts an item into the quadtree.
 /// </summary>
 /// <param name="item"> the ForceItem to add.</param>
 public void Insert(ForceItem item)
 {
     // Insert item into the quadtrees
     try {
         Insert(item, root, xMin, yMin, xMax, yMax);
     }
     catch (StackOverflowException e) {
         // TODO: safe to remove?
         Trace.WriteLine(e.Message);
     }
 }
Exemple #10
0
 /// <summary>
 /// Get a Spring instance and set it to the given parameters.
 /// </summary>
 public Spring getSpring(ForceItem f1, ForceItem f2, float k, float length)
 {
     if (springs.Count > 0)
     {
         Spring s = springs[springs.Count - 1];
         springs.Remove(s);
         s.Item1  = f1;
         s.Item2  = f2;
         s.Coeff  = k;
         s.Length = length;
         return(s);
     }
     else
     {
         return(new Spring(f1, f2, k, length));
     }
 }
        /// <summary>
        /// Gets the force.
        /// </summary>
        /// <param name="s">The s.</param>
        public override void GetForce(Spring s)
        {
            ForceItem item1 = s.Item1;
            ForceItem item2 = s.Item2;
            float     length = (s.Length < 0 ? parms[SpringLength] : s.Length);
            float     x1 = item1.Location[0], y1 = item1.Location[1];
            float     x2 = item2.Location[0], y2 = item2.Location[1];
            float     dx = x2 - x1, dy = y2 - y1;
            float     r = (float)Math.Sqrt(dx * dx + dy * dy);

            if (r == 0.0)
            {
                dx = ((float)rnd.NextDouble() - 0.5f) / 50.0f;
                dy = ((float)rnd.NextDouble() - 0.5f) / 50.0f;
                r  = (float)Math.Sqrt(dx * dx + dy * dy);
            }
            float d     = r - length;
            float coeff = (s.Coeff < 0 ? parms[SpringCoeff] : s.Coeff) * d / r;

            item1.Force[0] += coeff * dx;
            item1.Force[1] += coeff * dy;
            item2.Force[0] += -coeff * dx;
            item2.Force[1] += -coeff * dy;
        }
 /// <summary>
 /// Add a ForceItem to the simulation.
 /// </summary>
 /// <param name="item"> item the ForceItem to add.</param>
 public void addItem(ForceItem item) {
   mItems.Add(item);
 }
Exemple #13
0
 /// <summary>
 /// Returns the force acting on the given item.
 /// </summary>
 /// <param name="item"></param>
 public override void GetForce(ForceItem item)
 {
     item.Force[0] -= parms[DragCoeff] * item.Velocity[0];
     item.Force[1] -= parms[DragCoeff] * item.Velocity[1];
 }
Exemple #14
0
        /// <summary>
        /// Utility method.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="n">The n.</param>
        /// <param name="x1">The x1.</param>
        /// <param name="y1">The y1.</param>
        /// <param name="x2">The x2.</param>
        /// <param name="y2">The y2.</param>
        private void ForceHelper(ForceItem item, QuadTreeNode n, float x1, float y1, float x2, float y2)
        {
            float dx   = n.com[0] - item.Location[0];
            float dy   = n.com[1] - item.Location[1];
            float r    = (float)Math.Sqrt(dx * dx + dy * dy);
            bool  same = false;

            if (r == 0.0f)
            {
                // if items are in the exact same place, add some noise
                dx   = Convert.ToSingle((rand.NextDouble() - 0.5D) / 50.0D);
                dy   = Convert.ToSingle((rand.NextDouble() - 0.5D) / 50.0D);
                r    = (float)Math.Sqrt(dx * dx + dy * dy);
                same = true;
            }
            bool minDist = parms[MIN_DISTANCE] > 0f && r > parms[MIN_DISTANCE];

            // the Barnes-Hut approximation criteria is if the ratio of the
            // size of the quadtree box to the distance between the point and
            // the box's center of mass is beneath some threshold theta.
            if ((!n.hasChildren && n.value != item) ||
                (!same && (x2 - x1) / r < parms[BARNES_HUT_THETA]))
            {
                if (minDist)
                {
                    return;
                }
                // either only 1 particle or we meet criteria
                // for Barnes-Hut approximation, so calc force
                float v = parms[GRAVITATIONAL_CONST] * item.Mass * n.mass
                          / (r * r * r);
                item.Force[0] += v * dx;
                item.Force[1] += v * dy;
            }
            else if (n.hasChildren)
            {
                // recurse for more accurate calculation
                float splitx = (x1 + x2) / 2;
                float splity = (y1 + y2) / 2;
                for (int i = 0; i < n.children.Length; i++)
                {
                    if (n.children != null && n.children[i] != null)
                    {
                        ForceHelper(item, n.children[i],
                                    (i == 1 || i == 3 ? splitx : x1), (i > 1 ? splity : y1),
                                    (i == 1 || i == 3 ? x2 : splitx), (i > 1 ? y2 : splity));
                    }
                }
                if (minDist)
                {
                    return;
                }
                if (n.value != null && n.value != item)
                {
                    float v = parms[GRAVITATIONAL_CONST] * item.Mass * n.value.Mass
                              / (r * r * r);
                    item.Force[0] += v * dx;
                    item.Force[1] += v * dy;
                }
            }
        }
Exemple #15
0
 /// <summary>
 /// Checks a ForceItem to make sure its values are all valid numbers(i.e., not NaNs).
 /// </summary>
 /// <param name="item">The item to check.</param>
 /// <returns>
 /// 	<c>true</c> if the specified item is valid; otherwise, <c>false</c>.
 /// </returns>
 public static bool isValid(ForceItem item) {
   return
     !(float.IsNaN(item.location[0]) || float.IsNaN(item.location[1]) ||
        float.IsNaN(item.plocation[0]) || float.IsNaN(item.plocation[1]) ||
        float.IsNaN(item.velocity[0]) || float.IsNaN(item.velocity[1]) ||
        float.IsNaN(item.force[0]) || float.IsNaN(item.force[1]));
 }
Exemple #16
0
 /// <summary>
 /// Add a ForceItem to the simulation.
 /// </summary>
 /// <param name="item"> item the ForceItem to add.</param>
 public void addItem(ForceItem item)
 {
     mItems.Add(item);
 }
Exemple #17
0
 /// <summary>
 /// Remove a ForceItem to the simulation.
 /// </summary>
 /// <param name="item">Item the ForceItem to remove.</param>
 /// <returns></returns>
 public bool removeItem(ForceItem item)
 {
     return(mItems.Remove(item));
 }
 /// <summary>
 ///Returns the force acting on the given item.
 /// </summary>
 public virtual void GetForce(ForceItem item)
 {
     throw new NotImplementedException("This class does not support this operation");
 }
Exemple #19
0
    /// <summary>
    /// Utility method.
    /// </summary>
    /// <param name="item">The item.</param>
    /// <param name="n">The n.</param>
    /// <param name="x1">The x1.</param>
    /// <param name="y1">The y1.</param>
    /// <param name="x2">The x2.</param>
    /// <param name="y2">The y2.</param>
    private void ForceHelper(ForceItem item, QuadTreeNode n, float x1, float y1, float x2, float y2) {
      float dx = n.com[0] - item.Location[0];
      float dy = n.com[1] - item.Location[1];
      float r = (float)Math.Sqrt(dx * dx + dy * dy);
      bool same = false;
      if (r == 0.0f) {
        // if items are in the exact same place, add some noise
        dx = Convert.ToSingle((rand.NextDouble() - 0.5D) / 50.0D);
        dy = Convert.ToSingle((rand.NextDouble() - 0.5D) / 50.0D);
        r = (float)Math.Sqrt(dx * dx + dy * dy);
        same = true;
      }
      bool minDist = parms[MIN_DISTANCE] > 0f && r > parms[MIN_DISTANCE];

      // the Barnes-Hut approximation criteria is if the ratio of the
      // size of the quadtree box to the distance between the point and
      // the box's center of mass is beneath some threshold theta.
      if ((!n.hasChildren && n.value != item) ||
           (!same && (x2 - x1) / r < parms[BARNES_HUT_THETA])) {
        if (minDist) return;
        // either only 1 particle or we meet criteria
        // for Barnes-Hut approximation, so calc force
        float v = parms[GRAVITATIONAL_CONST] * item.Mass * n.mass
                    / (r * r * r);
        item.Force[0] += v * dx;
        item.Force[1] += v * dy;
      } else if (n.hasChildren) {
        // recurse for more accurate calculation
        float splitx = (x1 + x2) / 2;
        float splity = (y1 + y2) / 2;
        for (int i = 0; i < n.children.Length; i++) {
          if (n.children != null && n.children[i] != null) {
            ForceHelper(item, n.children[i],
                (i == 1 || i == 3 ? splitx : x1), (i > 1 ? splity : y1),
                (i == 1 || i == 3 ? x2 : splitx), (i > 1 ? y2 : splity));
          }
        }
        if (minDist) return;
        if (n.value != null && n.value != item) {
          float v = parms[GRAVITATIONAL_CONST] * item.Mass * n.value.Mass
                      / (r * r * r);
          item.Force[0] += v * dx;
          item.Force[1] += v * dy;
        }
      }
    }
Exemple #20
0
 /// <summary>
 /// Add a Spring to the simulation.
 /// </summary>
 /// <param name="item1">the first endpoint of the spring</param>
 /// <param name="item2">the second endpoint of the spring</param>
 /// <returns>the Spring added to the simulation</returns>
 public Spring addSpring(ForceItem item1, ForceItem item2)
 {
     return(addSpring(item1, item2, -1.0F, -1.0F));
 }
Exemple #21
0
 /// <summary>
 /// Inserts helper method.
 /// </summary>
 /// <param name="p">The p.</param>
 /// <param name="n">The n.</param>
 /// <param name="x1">The x1.</param>
 /// <param name="y1">The y1.</param>
 /// <param name="x2">The x2.</param>
 /// <param name="y2">The y2.</param>
 private void InsertHelper(ForceItem p, QuadTreeNode n, float x1, float y1, float x2, float y2) {
   float x = p.Location[0], y = p.Location[1];
   float splitx = (x1 + x2) / 2;
   float splity = (y1 + y2) / 2;
   int i = (x >= splitx ? 1 : 0) + (y >= splity ? 2 : 0);
   // create new child node, if necessary
   if (n.children[i] == null) {
     n.children[i] = factory.GetQuadTreeNode();
     n.hasChildren = true;
   }
   // update bounds
   if (i == 1 || i == 3) x1 = splitx; else x2 = splitx;
   if (i > 1) y1 = splity; else y2 = splity;
   // recurse 
   Insert(p, n.children[i], x1, y1, x2, y2);
 }
Exemple #22
0
 /// <summary>
 /// Inserts the specified force.
 /// </summary>
 /// <param name="p">The p.</param>
 /// <param name="n">The n.</param>
 /// <param name="x1">The x1.</param>
 /// <param name="y1">The y1.</param>
 /// <param name="x2">The x2.</param>
 /// <param name="y2">The y2.</param>
 private void Insert(ForceItem p, QuadTreeNode n, float x1, float y1, float x2, float y2) {
   // try to Insert particle p at node n in the quadtree
   // by construction, each leaf will contain either 1 or 0 particles
   if (n.hasChildren) {
     // n contains more than 1 particle
     InsertHelper(p, n, x1, y1, x2, y2);
   } else if (n.value != null) {
     // n contains 1 particle
     if (IsSameLocation(n.value, p)) {
       InsertHelper(p, n, x1, y1, x2, y2);
     } else {
       ForceItem v = n.value; n.value = null;
       InsertHelper(v, n, x1, y1, x2, y2);
       InsertHelper(p, n, x1, y1, x2, y2);
     }
   } else {
     // n is empty, so is a leaf
     n.value = p;
   }
 }
Exemple #23
0
 /// <summary>
 /// Add a Spring to the simulation.
 /// </summary>
 /// <param name="item1">the first endpoint of the spring</param>
 /// <param name="item2">the second endpoint of the spring</param>
 /// <param name="length">the spring length</param>
 /// <returns>the Spring added to the simulation</returns>
 public Spring addSpring(ForceItem item1, ForceItem item2, float length)
 {
     return(addSpring(item1, item2, -1.0F, length));
 }
Exemple #24
0
 /// <summary>
 /// Returns the force acting on the given item.
 /// </summary>
 /// <param name="item"></param>
 public override void GetForce(ForceItem item) {
   item.Force[0] -= parms[DragCoeff] * item.Velocity[0];
   item.Force[1] -= parms[DragCoeff] * item.Velocity[1];
 }
 /// <summary>
 /// Get a Spring instance and set it to the given parameters.
 /// </summary>
 public Spring getSpring(ForceItem f1, ForceItem f2, float k, float length)
 {
     if (springs.Count > 0)
     {
         Spring s = springs[springs.Count - 1];
         springs.Remove(s);
         s.Item1 = f1;
         s.Item2 = f2;
         s.Coeff = k;
         s.Length = length;
         return s;
     }
     else
     {
         return new Spring(f1, f2, k, length);
     }
 }
Exemple #26
0
 /// <summary>
 /// Inserts an item into the quadtree.
 /// </summary>
 /// <param name="item"> the ForceItem to add.</param>
 public void Insert(ForceItem item) {
   // Insert item into the quadtrees
   try {
     Insert(item, root, xMin, yMin, xMax, yMax);
   }
   catch (StackOverflowException e) {
     // TODO: safe to remove?
     Trace.WriteLine(e.Message);
   }
 }
 /// <summary>
 /// Remove a ForceItem to the simulation.
 /// </summary>
 /// <param name="item">Item the ForceItem to remove.</param>
 /// <returns></returns>
 public bool removeItem(ForceItem item) {
   return mItems.Remove(item);
 }
Exemple #28
0
 /// <summary>
 /// Determines whether the two force are at the same location.
 /// </summary>
 /// <param name="f1">The f1.</param>
 /// <param name="f2">The f2.</param>
 /// <returns>
 /// 	<c>true</c> if [is same location] [the specified f1]; otherwise, <c>false</c>.
 /// </returns>
 private static bool IsSameLocation(ForceItem f1, ForceItem f2) {
   float dx = Math.Abs(f1.Location[0] - f2.Location[0]);
   float dy = Math.Abs(f1.Location[1] - f2.Location[1]);
   return (dx < 0.01 && dy < 0.01);
 }
 /// <summary>
 /// Add a Spring to the simulation.
 /// </summary>
 /// <param name="item1">the first endpoint of the spring</param>
 /// <param name="item2">the second endpoint of the spring</param>
 /// <returns>the Spring added to the simulation</returns>
 public Spring addSpring(ForceItem item1, ForceItem item2) {
   return addSpring(item1, item2, -1.0F, -1.0F);
 }
Exemple #30
0
 /**
  * Calculates the force vector acting on the given item.
  * @param item the ForceItem for which to compute the force
  */
 public override void GetForce(ForceItem item) {
   try {
     ForceHelper(item, root, xMin, yMin, xMax, yMax);
   }
   catch (StackOverflowException e) {
     // TODO: safe to remove?
     Trace.WriteLine(e.Message);
   }
 }
 /// <summary>
 /// Add a Spring to the simulation.
 /// </summary>
 /// <param name="item1">the first endpoint of the spring</param>
 /// <param name="item2">the second endpoint of the spring</param>
 /// <param name="length">the spring length</param>
 /// <returns>the Spring added to the simulation</returns>
 public Spring addSpring(ForceItem item1, ForceItem item2, float length) {
   return addSpring(item1, item2, -1.0F, length);
 }
 /// <summary>
 ///Returns the force acting on the given item.
 /// </summary>
 public virtual void GetForce(ForceItem item)
 {
     throw new NotImplementedException("This class does not support this operation");
 }
 /// <summary>
 /// Add a Spring to the simulation.
 /// </summary>
 /// <param name="item1">the first endpoint of the spring</param>
 /// <param name="item2"> the second endpoint of the spring</param>
 /// <param name="coeff">the spring coefficient</param>
 /// <param name="length">the spring length</param>
 /// <returns> the Spring added to the simulation</returns>
 public Spring addSpring(ForceItem item1, ForceItem item2, float coeff, float length) {
   if (item1 == null || item2 == null)
     throw new ArgumentException("ForceItems must be non-null");
   Spring s = Spring.Factory.getSpring(item1, item2, coeff, length);
   springs.Add(s);
   return s;
 }