Пример #1
0
        /// <summary>
        /// Create a new spring with given parameter
        /// </summary>
        /// <param name="p1">the first particle attached to the spring</param>
        /// <param name="p2">the second particle attached to the spring</param>
        public Spring(Particle p1, Particle p2)
        {
            this.p1 = p1;
            this.p2 = p2;

            restLength = 10.0;
            tension = 0.1;
            damping = 0.1;
            isDead = false;
        }
Пример #2
0
 /// <summary>
 /// Reclaims a Particle, adding it to the object pool for recycling
 /// <param name="p">the Particle to Reclaim</param>
 /// </summary>
 protected static void reclaimParticle(Particle p)
 {
     if (_ppool.Count < objectPoolLimit)
     {
         _ppool.Push(p);
     }
 }
Пример #3
0
 /// <summary>
 /// Adds a spring to the simulation
 /// </summary>
 /// <param name="p1">the first Particle attached to the spring</param>
 /// <param name="p2">the second Particle attached to the spring</param>
 /// <param name="restLength">the rest length of the spring</param>
 /// <param name="tenstion">the tension of the spring</param>
 /// <param name="damping">the damping (friction) co-efficient of the spring</param>
 /// <returns>the added spring</returns>
 public Spring AddSpring(Particle p1, Particle p2, double restLength,
     double tension, double damping)
 {
     var edge = new Spring(p1, p2)
     {
         restLength = restLength,
         tension = tension,
         damping = damping
     };
     p1.degree++;
     p2.degree++;
     Springs.Add(edge);
     return edge;
 }
Пример #4
0
        private void BuildParticles()
        {
            double maxProjectFileCount = 0;

            foreach (Project p in _projectManager.Projects)
            {
                if (p.Files > maxProjectFileCount)
                {
                    maxProjectFileCount = p.Files;
                }
            }

            Random random = new Random(DateTime.Now.Millisecond);

            Dictionary<string, Particle<NodeRenderer, LineRenderer>> particleDictionary = new Dictionary<string, Particle<NodeRenderer, LineRenderer>>();

            //create each particle
            foreach (Project p in _projectManager.Projects)
            {
                NodeRenderer renderer = new NodeRenderer(p.Name, ((p.Files / maxProjectFileCount) * MAX_RADIUS) + MIN_RADIUS);
                Particle<NodeRenderer, LineRenderer> particle =
                    new Particle<NodeRenderer, LineRenderer>(DEFAULT_MAX_MASS, DEFAULT_REPELLANT_FORCE,
                                                             _simulation.ForceDissipationFunction);
                particle.InitPosition(random.Next(RenderPanel.Width), random.Next(RenderPanel.Height));
                _simulation.AddParticle(particle, renderer);

                particleDictionary.Add(p.Name,particle);
            }

            //connect the particle dependancies
            foreach (Project p in _projectManager.Projects)
            {
                foreach (string projectName in p.Dependancies)
                {
                    //if this has any projects that are not loaded, create a defualt project to link to
                    if (!particleDictionary.ContainsKey(projectName))
                    {
                        NodeRenderer renderer = new NodeRenderer(projectName, MIN_RADIUS);
                        Particle<NodeRenderer, LineRenderer> particle =
                            new Particle<NodeRenderer, LineRenderer>(DEFAULT_MAX_MASS, DEFAULT_REPELLANT_FORCE,
                                                                     _simulation.ForceDissipationFunction);
                        particle.InitPosition(random.Next(RenderPanel.Width), random.Next(RenderPanel.Height));
                        _simulation.AddParticle(particle, renderer);

                        particleDictionary.Add(projectName, particle);
                    }

                    particleDictionary[
                        p.Name].AddConnection(particleDictionary[projectName],
                        new LineRenderer(particleDictionary[projectName].MetaData.Radius),
                        DEFAULT_SHORT_RESTING_LENGTH,
                        DEFAULT_SPRING_CONSTANT);
                }
            }
        }
Пример #5
0
 private bool isSameLocation(Particle p1, Particle p2)
 {
     return (Math.Abs(p1.x - p2.x) < _eps &&
             Math.Abs(p1.y - p2.y) < _eps);
 }
Пример #6
0
        private void insertHelper(Particle p, QuadTreeNode n, 
            double x1, double y1, double x2, double y2)
        {
            // determine split
            double sx = (x1+x2)/2;
            double sy = (y1+y2)/2;
            int c = (p.x >= sx ? 1 : 0) + (p.y >= sy ? 2 : 0);

            // update bounds
            if (c==1 || c==3) x1 = sx; else x2 = sx;
            if (c>1) y1 = sy; else y2 = sy;

            // update children
            QuadTreeNode cn;
            if (c == 0) {
                if (n.c1==null) n.c1 = QuadTreeNode.Particle();
                cn = n.c1;
            } else if (c == 1) {
                if (n.c2==null) n.c2 = QuadTreeNode.Particle();
                cn = n.c2;
            } else if (c == 2) {
                if (n.c3==null) n.c3 = QuadTreeNode.Particle();
                cn = n.c3;
            } else {
                if (n.c4==null) n.c4 = QuadTreeNode.Particle();
                cn = n.c4;
            }
            n.hasChildren = true;
            insert(p,cn,x1,y1,x2,y2);
        }
Пример #7
0
        // -- Helpers ---------------------------------------------------------
        private void insert(Particle p, QuadTreeNode n,
            double x1, double y1, double x2, double y2)
        {
            // ignore particles with NaN coordinates
            if (double.IsNaN(p.x) || double.IsNaN(p.y)) return;

            // try to insert Particle p at Particle 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.p != null ) {
                // n contains 1 Particle
                if ( isSameLocation(n.p, p) ) {
                    // recurse
                    insertHelper(p,n,x1,y1,x2,y2);
                } else {
                    // divide
                    Particle v = n.p; n.p = null;
                    insertHelper(v,n,x1,y1,x2,y2);
                    insertHelper(p,n,x1,y1,x2,y2);
                }
            } else {
                // n is empty, add p as leaf
                n.p = p;
            }
        }
Пример #8
0
        private void forces(Particle p, QuadTreeNode n,
            double x1, double y1, double x2, double y2)
        {
            Random rnd = new Random();
            double f = 0;
            double dx = n.cx - p.x;
            double dy = n.cy - p.y;
            double dd = Math.Sqrt(dx*dx + dy*dy);
            bool max = _max > 0 && dd > _max;
            if (dd == 0)
            { // add direction when needed
                dx = _eps * (0.5 - rnd.NextDouble());
                dy = _eps * (0.5 - rnd.NextDouble());
            }

            // 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.p != p) || ((x2-x1)/dd < _t) )
            {
                if ( max ) return;
                // either only 1 Particle or we meet criteria
                // for Barnes-Hut approximation, so calc force
                dd = dd<_min ? _min : dd;
                f = _g * p.mass * n.mass / (dd * dd * dd);
                p.fx += f*dx; p.fy += f*dy;
            }
            else if ( n.hasChildren )
            {
                // recurse for more accurate calculation
                double sx = (x1+x2)/2;
                double sy = (y1+y2)/2;

                if (n.c1 != null) forces(p, n.c1, x1, y1, sx, sy);
                if (n.c2 != null) forces(p, n.c2, sx, y1, x2, sy);
                if (n.c3 != null) forces(p, n.c3, x1, sy, sx, y2);
                if (n.c4 != null) forces(p, n.c4, sx, sy, x2, y2);

                if ( max ) return;
                if ( n.p != null && n.p != p ) {
                    dd = dd<_min ? _min : dd;
                    f = _g * p.mass * n.p.mass / (dd*dd*dd);
                    p.fx += f*dx; p.fy += f*dy;
                }
            }
        }
Пример #9
0
        /// <summary>
        /// 多角形のエッジを追加する
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="style"></param>
        /// <returns></returns>
        Spring AddPolygonEdge(Particle p1, Particle p2, string style)
        {
            var spring = sim.AddSpring(p1, p2, 100, 0.1, 0.1);

            var group = new TransformGroup();
            var scale = new ScaleTransform();
            var rotate = new RotateTransform();
            var translate = new TranslateTransform();
            group.Children.Add(scale);
            group.Children.Add(rotate);
            group.Children.Add(translate);

            p1.PropertyChanged += (s, e) =>
            {
                var dx = p2.x - p1.x;
                var dy = p2.y - p1.y;
                var d = Math.Sqrt(dx * dx + dy * dy);
                var angle = Math.Atan2(dy, dx) / Math.PI * 180;

                scale.ScaleX = d / 100.0;
                rotate.Angle = angle;
                translate.X = p1.x;
                translate.Y = p1.y;
            };
            p2.PropertyChanged += (s, e) =>
            {
                var dx = p2.x - p1.x;
                var dy = p2.y - p1.y;
                var d = Math.Sqrt(dx * dx + dy * dy);
                var angle = Math.Atan2(dy, dx) / Math.PI * 180;

                scale.ScaleX = d / 100;
                rotate.Angle = angle;
                translate.X = p1.x;
                translate.Y = p1.y;
            };

            Polygon poly = new Polygon()
            {
                Points = new PointCollection(){
                    new Point(0,1),
                    new Point(100,0),
                    new Point(0,-1)
                },
                RenderTransform = group,
                Style = Resources[style] as Style
            };

            LayoutRoot.Children.Insert(0, poly);

            return spring;
        }
Пример #10
0
        /// <summary>
        /// 線のエッジを追加する
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <returns></returns>
        Spring AddLineEdge(Particle p1, Particle p2)
        {
            var s = sim.AddSpring(p1, p2, 10, 0.1, 0.1);

            Line line = new Line()
            {
                Fill = new SolidColorBrush(Colors.Brown),
                Stroke = new SolidColorBrush(Colors.Brown),
            };
            line.SetBinding(Line.X1Property, new Binding("x") { Source = p1, Mode = BindingMode.TwoWay });
            line.SetBinding(Line.Y1Property, new Binding("y") { Source = p1, Mode = BindingMode.TwoWay });
            line.SetBinding(Line.X2Property, new Binding("x") { Source = p2, Mode = BindingMode.TwoWay });
            line.SetBinding(Line.Y2Property, new Binding("y") { Source = p2, Mode = BindingMode.TwoWay });

            LayoutRoot.Children.Insert(0, line);
            return s;
        }