Esempio n. 1
0
        public FDLEdge(FDLNode source, FDLNode target, Vector ideal)
            : base(source, target)
        {
            this.ideal = ideal;

            InvalidateEdge();
        }
        /// <summary>
        /// Initializes this force-directed layout. Assumes that graph has some
        /// reasonable initial node positions.
        /// </summary>
        /// <param name="graph">The graph to layout.</param>
        /// <param name="start_node">The node to start layout from.</param>
        public ForceDirectedLayout(IReadOnlyGraph<FDLNode, FDLEdge> graph, FDLNode start_node)
        {
            if (graph == null)
                throw new ArgumentNullException("graph");
            if (start_node == null)
                throw new ArgumentNullException("start_node");
            if (!graph.ContainsNode(start_node))
                throw new ArgumentException("start_node must be in this graph");

            //initialize nodes array to only the reachable nodes
            ArrayList n = new ArrayList(graph.NodeCount);
            Algorithms.Algorithms.BreadthFirstSearch(graph, start_node, null, delegate(FDLNode node){
                n.Add(node);
            });
            nodes = new FDLNode[n.Count];
            n.CopyTo(nodes);

            new_positions = new MutablePoint[nodes.Length];
            accels = new double[nodes.Length];

            //summarize constraints
            HashSet<FDLEdge> h = new HashSet<FDLEdge>();
            for (int i = 0; i < nodes.Length; i++)
            {
                foreach (FDLEdge edge in nodes[i].OutEdges)
                {
                    DefaultEdge reverse = edge.Target.GetEdgeTo(edge.Source);
                    if(h.Contains(edge) || (reverse != null && h.Contains(reverse)))
                        continue;
                    h.Add(edge);
                }
            }
            constraints = new FDLEdge[h.Count];
            h.CopyTo(constraints);
        }
Esempio n. 3
0
 /// <summary>
 /// Create a new FDLEdge leading from the source to the target.
 /// </summary>
 /// <param name="source"></param>
 /// <param name="target"></param>
 public FDLEdge(FDLNode source, FDLNode target)
     : this(source, target, Point.Delta(source.Position, target.Position))
 {
 }
        private static Vector NodeNodeForce(FDLNode node1, FDLNode node2)
        {
            // distance squared for a small perf improvement
            double distance_s = NodeDistanceSquared(node1, node2);

            // composite function, must be continuous
            if (distance_s >= 4.0 * K_SQUARED)
            {
                return Vector.ZERO_VECTOR;
            }
            else if (distance_s > K_SQUARED)
            {
                double distance = Math.Sqrt(distance_s);
                double repulsion = Math.Min(-1.0 * distance / K + 2.0, K);
                double angle = NodeAngle(node2, node1);
                return Vector.FromPolar(repulsion, angle);
            }
            else if (distance_s > 0)
            {
                double repulsion = Math.Min(K_SQUARED / distance_s, K);
                double angle = NodeAngle(node2, node1);
                return Vector.FromPolar(repulsion, angle);
            }
            else
            {
                return Vector.ZERO_VECTOR;
            }
        }
        private static double NodeDistanceSquared(FDLNode node1, FDLNode node2)
        {
            Point v1 = node1.Position;
            Point v2 = node2.Position;

            double dx = v1.X - v2.X;
            double dy = v1.Y - v2.Y;

            return dx * dx + dy * dy;
        }
        private static double NodeAngle(FDLNode from, FDLNode to)
        {
            FDLEdge e = from.GetEdgeTo(to) as FDLEdge;
            if (e != null)
                return e.Angle;

            return Vector.CalcAngle(from.Position, to.Position);
        }