Esempio n. 1
0
 /// <summary>
 ///     Clears the votings for a given node representative, but leaves the index references.
 /// </summary>
 /// <param name="nodeVoting"></param>
 void ClearVoting(NodeVoting nodeVoting)
 {
     foreach (VoteBlock block in nodeVoting.VotingBlocks)
     {
         block.Votings.Clear();
     }
 }
Esempio n. 2
0
        /// <summary>
        ///     Local optimization for a given node, as described in Graph Drawing by Stress Majorization by Gansner et. al. (Sect. 2.3).
        /// </summary>
        /// <param name="nodeVoting"></param>
        /// <returns></returns>
        Point LocalizedOptimization(NodeVoting nodeVoting)
        {
            Point  currentPosition = Positions[nodeVoting.VotedNodeIndex];
            double nextX           = 0;
            double nextY           = 0;
            double sumWeights      = 0;

            // if there is not voting vlock, the position of this node will not change
            if (nodeVoting.VotingBlocks == null || nodeVoting.VotingBlocks.Count == 0)
            {
                return(currentPosition);
            }

            foreach (VoteBlock votingBlock in nodeVoting.VotingBlocks)
            {
                double blockWeight = votingBlock.BlockWeight;
                foreach (Vote vote in votingBlock.Votings)
                {
                    Point voterPos = Positions[vote.VoterIndex];

                    double votingDistance = vote.Distance;
                    double diffX          = currentPosition.X - voterPos.X;
                    double diffY          = currentPosition.Y - voterPos.Y;
                    double euclidDistance = Math.Sqrt(diffX * diffX + diffY * diffY);
                    double weight         = blockWeight * vote.Weight;

                    double voteX = voterPos.X + votingDistance * diffX / euclidDistance;
                    nextX += voteX * weight;
                    double voteY = voterPos.Y + votingDistance * diffY / euclidDistance;
                    nextY += voteY * weight;

                    sumWeights += weight;
                }
            }

            if (sumWeights == 0)
            {
                // there was no single voting, just return the current position
                return(currentPosition);
            }
            return(new Point(nextX / sumWeights, nextY / sumWeights));
        }
Esempio n. 3
0
        /// <summary>
        ///     Iterates only once.
        /// </summary>
        /// <returns></returns>
        public List <Point> IterateSingleLocalizedMethod()
        {
            List <Point> newPositions;

            if (Settings.UpdateMethod == UpdateMethod.Serial)
            {
                newPositions = Positions;
            }
            else
            {
                newPositions = new List <Point>(Positions.Count);
            }

            // For each node compute the new position by averaging over all votes.
            for (int i = 0; i < NodeVotings.Count; i++)
            {
                NodeVoting nodeVoting = NodeVotings[i];
                int        votedIndex = nodeVoting.VotedNodeIndex;
                Point      newPos     = LocalizedOptimization(nodeVoting);
                if (Settings.UpdateMethod == UpdateMethod.Serial)
                {
                    newPositions[votedIndex] = newPos;
                }
                else
                {
                    newPositions.Add(newPos);
                }
            }

            if (Settings.UpdateMethod == UpdateMethod.Parallel)
            {
                for (int i = 0; i < NodeVotings.Count; i++)
                {
                    NodeVoting nodeVoting = NodeVotings[i];
                    int        index      = nodeVoting.VotedNodeIndex;
                    Positions[index] = newPositions[i];
                }
            }

            return(newPositions);
        }
 /// <summary>
 ///     Clears the votings for a given node representative, but leaves the index references.
 /// </summary>
 /// <param name="nodeVoting"></param>
  void ClearVoting(NodeVoting nodeVoting) {
     foreach (VoteBlock block in nodeVoting.VotingBlocks) {
         block.Votings.Clear();
     }
 }
        /// <summary>
        ///     Local optimization for a given node, as described in Graph Drawing by Stress Majorization by Gansner et. al. (Sect. 2.3).
        /// </summary>
        /// <param name="nodeVoting"></param>
        /// <returns></returns>
         Point LocalizedOptimization(NodeVoting nodeVoting) {
            Point currentPosition = Positions[nodeVoting.VotedNodeIndex];
            double nextX = 0;
            double nextY = 0;
            double sumWeights = 0;

            // if there is not voting vlock, the position of this node will not change
            if (nodeVoting.VotingBlocks == null || nodeVoting.VotingBlocks.Count == 0) {
                return currentPosition;
            }

            foreach (VoteBlock votingBlock in nodeVoting.VotingBlocks) {
                double blockWeight = votingBlock.BlockWeight;
                foreach (Vote vote in votingBlock.Votings) {
                    Point voterPos = Positions[vote.VoterIndex];

                    double votingDistance = vote.Distance;
                    double diffX = currentPosition.X - voterPos.X;
                    double diffY = currentPosition.Y - voterPos.Y;
                    double euclidDistance = Math.Sqrt(diffX*diffX + diffY*diffY);
                    double weight = blockWeight*vote.Weight;

                    double voteX = voterPos.X + votingDistance*diffX/euclidDistance;
                    nextX += voteX*weight;
                    double voteY = voterPos.Y + votingDistance*diffY/euclidDistance;
                    nextY += voteY*weight;

                    sumWeights += weight;
                }
            }

            if (sumWeights == 0) {
                // there was no single voting, just return the current position
                return currentPosition;
            }
            return new Point(nextX/sumWeights, nextY/sumWeights);
        }
        /// <summary>
        /// Example on how to use Stress Majorization with a small graph and Localized method.
        /// </summary>
        public static void RunStressMajorizationExample()
        {
            //create a star graph where three nodes are connected to the center
            GeometryGraph graph = new GeometryGraph();

            graph.Nodes.Add(new Node());
            graph.Nodes.Add(new Node());
            graph.Nodes.Add(new Node());
            graph.Nodes.Add(new Node());

            //set initial positions, e.g., random
            graph.Nodes[0].BoundaryCurve = CurveFactory.CreateRectangle(20, 10, new Point(5, 5));
            graph.Nodes[1].BoundaryCurve = CurveFactory.CreateRectangle(20, 10, new Point(7, 10));
            graph.Nodes[2].BoundaryCurve = CurveFactory.CreateRectangle(20, 10, new Point(7, 2));
            graph.Nodes[3].BoundaryCurve = CurveFactory.CreateRectangle(20, 10, new Point(35, 1));

            graph.Edges.Add(new Edge(graph.Nodes[0], graph.Nodes[1]));
            graph.Edges.Add(new Edge(graph.Nodes[0], graph.Nodes[2]));
            graph.Edges.Add(new Edge(graph.Nodes[0], graph.Nodes[3]));

            //array with desired distances between the nodes for every edge
            double[] idealEdgeLength = new double[graph.Edges.Count];
            for (int i = 0; i < graph.Edges.Count; i++)
            {
                idealEdgeLength[i] = 100; //all edges should have this euclidean length
            }


            //create stress majorization class and set the desired distances on the edges
            StressMajorization majorizer = new StressMajorization();


            majorizer.Positions   = new List <Point>(graph.Nodes.Select(v => v.Center));
            majorizer.NodeVotings = new List <NodeVoting>(graph.Nodes.Count);

            // initialize for every node an empty block
            for (int i = 0; i < graph.Nodes.Count; i++)
            {
                var nodeVote = new NodeVoting(i); //by default there is already a block with weighting 1
                //optional: add second block with different type of edges, e.g., with stronger weight
                //var secondBlock = new VoteBlock(new List<Vote>(), 100);
                //nodeVote.VotingBlocks.Add(secondBlock);
                //var block2=nodeVote.VotingBlocks[1]; //block could be accessed like this in a later stage

                majorizer.NodeVotings.Add(nodeVote);
            }


            // for every edge set the desired distances by setting votings among the two end nodes.
            Dictionary <Node, int> posDict = new Dictionary <Node, int>();

            for (int i = 0; i < graph.Nodes.Count; i++)
            {
                posDict[graph.Nodes[i]] = i;
            }

            var edges = graph.Edges.ToArray();

            for (int i = 0; i < graph.Edges.Count; i++)
            {
                var edge    = edges[i];
                int nodeId1 = posDict[edge.Source];
                int nodeId2 = posDict[edge.Target];

                double idealDistance = idealEdgeLength[i];
                double weight        = 1 / (idealDistance * idealDistance);
                var    voteFromNode1 = new Vote(nodeId1, idealDistance, weight); // vote from node1 for node2
                var    voteFromNode2 = new Vote(nodeId2, idealDistance, weight); // vote from node2 for node1

                // add vote of node1 to list of node2 (in first voting block)
                majorizer.NodeVotings[nodeId2].VotingBlocks[0].Votings.Add(voteFromNode1);
                // add vote of node2 to list of node1 (in first voting block)
                majorizer.NodeVotings[nodeId1].VotingBlocks[0].Votings.Add(voteFromNode2);
            }

            //used localized method to reduce stress
            majorizer.Settings = new StressMajorizationSettings();
            majorizer.Settings.SolvingMethod = SolvingMethod.Localized;

            List <Point> result = majorizer.IterateAll();

            for (int i = 0; i < result.Count; i++)
            {
                graph.Nodes[i].Center = result[i];
            }
#if DEBUG && !SHARPKIT
            LayoutAlgorithmSettings.ShowGraph(graph);
#endif
        }
        /// <summary>
        /// Example on how to use Stress Majorization with a small graph and Localized method.
        /// </summary>
        public static void RunStressMajorizationExample() {

            //create a star graph where three nodes are connected to the center
            GeometryGraph graph = new GeometryGraph();
            graph.Nodes.Add(new Node());
            graph.Nodes.Add(new Node());
            graph.Nodes.Add(new Node());
            graph.Nodes.Add(new Node());

            //set initial positions, e.g., random
            graph.Nodes[0].BoundaryCurve = CurveFactory.CreateRectangle(20, 10, new Point(5, 5));
            graph.Nodes[1].BoundaryCurve = CurveFactory.CreateRectangle(20, 10, new Point(7, 10));
            graph.Nodes[2].BoundaryCurve = CurveFactory.CreateRectangle(20, 10, new Point(7, 2));
            graph.Nodes[3].BoundaryCurve = CurveFactory.CreateRectangle(20, 10, new Point(35, 1));

            graph.Edges.Add(new Edge(graph.Nodes[0], graph.Nodes[1]));
            graph.Edges.Add(new Edge(graph.Nodes[0], graph.Nodes[2]));
            graph.Edges.Add(new Edge(graph.Nodes[0], graph.Nodes[3]));

            //array with desired distances between the nodes for every edge
            double[] idealEdgeLength=new double[graph.Edges.Count];
            for (int i = 0; i < graph.Edges.Count; i++) {
                idealEdgeLength[i] = 100; //all edges should have this euclidean length
            }


            //create stress majorization class and set the desired distances on the edges
            StressMajorization majorizer = new StressMajorization();


            majorizer.Positions = new List<Point>(graph.Nodes.Select(v=>v.Center));
            majorizer.NodeVotings = new List<NodeVoting>(graph.Nodes.Count);

            // initialize for every node an empty block
            for (int i = 0; i < graph.Nodes.Count; i++) {
                var nodeVote = new NodeVoting(i); //by default there is already a block with weighting 1
                //optional: add second block with different type of edges, e.g., with stronger weight
                //var secondBlock = new VoteBlock(new List<Vote>(), 100);
                //nodeVote.VotingBlocks.Add(secondBlock);
                //var block2=nodeVote.VotingBlocks[1]; //block could be accessed like this in a later stage
                
                majorizer.NodeVotings.Add(nodeVote);
            }


            // for every edge set the desired distances by setting votings among the two end nodes.
            Dictionary<Node,int> posDict=new Dictionary<Node, int>();
            for (int i = 0; i < graph.Nodes.Count; i++) {
                posDict[graph.Nodes[i]] = i;
            }

            var edges = graph.Edges.ToArray();
            for (int i=0; i<graph.Edges.Count;i++) {
                var edge = edges[i];
                int nodeId1 = posDict[edge.Source];
                int nodeId2 = posDict[edge.Target];

                double idealDistance = idealEdgeLength[i];
                double weight = 1 / (idealDistance * idealDistance);
                var voteFromNode1 = new Vote(nodeId1, idealDistance, weight); // vote from node1 for node2
                var voteFromNode2 = new Vote(nodeId2, idealDistance, weight); // vote from node2 for node1
                
                // add vote of node1 to list of node2 (in first voting block)
                majorizer.NodeVotings[nodeId2].VotingBlocks[0].Votings.Add(voteFromNode1);
                // add vote of node2 to list of node1 (in first voting block)
                majorizer.NodeVotings[nodeId1].VotingBlocks[0].Votings.Add(voteFromNode2);
               

            }

            //used localized method to reduce stress
            majorizer.Settings=new StressMajorizationSettings();
            majorizer.Settings.SolvingMethod=SolvingMethod.Localized;

            List<Point> result = majorizer.IterateAll();

            for (int i = 0; i < result.Count; i++) {
                graph.Nodes[i].Center = result[i];
            }
#if DEBUG && !SILVERLIGHT && !SHARPKIT
            LayoutAlgorithmSettings.ShowGraph(graph);
#endif
        }
        /// <summary>
        ///     Inits the datastructures, later forces can be defined on the nodes.
        /// </summary>
        /// <param name="majorizer"></param>
        /// <param name="nodes"></param>
        /// <param name="nodePositions"></param>
         static void InitStressWithGraph(StressMajorization majorizer, Node[] nodes, Point[] nodePositions) {
            majorizer.Positions = new List<Point>(nodePositions);
            majorizer.NodeVotings = new List<NodeVoting>(nodes.Length);

            for (int i = 0; i < nodes.Length; i++) {
                var nodeVote = new NodeVoting(i);
                //add second block for separate weighting of the overlap distances
                var voteBlock = new VoteBlock(new List<Vote>(), 100);
//                nodeVote.VotingBlocks[0].BlockWeight = 0;
                nodeVote.VotingBlocks.Add(voteBlock);
                majorizer.NodeVotings.Add(nodeVote);
            }
        }