/// <summary>
    ///     Only for internal testing purposes. Three nodes a-b-c, after the process the distances should be 10 between them.
    /// </summary>
        public static void TestMajorizationSmall() {
            // small 4-star to test the majorization
            var positions = new List<Point>(4);

            positions.Add(new Point(0, 0));
            positions.Add(new Point(-2, -1));
            positions.Add(new Point(1, 2));


            //for first node on 0/0 create forces to push the other away
            var nodeVotings = new List<NodeVoting>(8);


            var votesNode1 = new List<Vote>();
            var votesNodeLeft = new List<Vote>();
            var votesNodeRight = new List<Vote>();

            votesNodeLeft.Add(new Vote(0, 10, 1/Math.Pow(10, 2))); // force from middle node to left node
            votesNodeRight.Add(new Vote(0, 10, 1/Math.Pow(10, 2))); // force from middle node to right node

            votesNode1.Add(new Vote(1, 10, 1/Math.Pow(10, 2)));
            votesNode1.Add(new Vote(2, 10, 1/Math.Pow(10, 2)));

            var blockNode1 = new List<VoteBlock>();
            blockNode1.Add(new VoteBlock(votesNode1, 1));

            var blockNodeLeft = new List<VoteBlock>();
            blockNodeLeft.Add(new VoteBlock(votesNodeLeft, 1));

            var blockNodeRight = new List<VoteBlock>();
            blockNodeRight.Add(new VoteBlock(votesNodeRight, 1));


            nodeVotings.Add(new NodeVoting(0, blockNode1));
            nodeVotings.Add(new NodeVoting(1, blockNodeLeft));
            nodeVotings.Add(new NodeVoting(2, blockNodeRight));


            var majorization = new StressMajorization();
            majorization.Positions = positions;
            majorization.NodeVotings = nodeVotings;

            for (int i = 0; i < 20; i++) {
                List<Point> result = majorization.IterateSingleLocalizedMethod();

                foreach (Point point in result) {
                    Console.WriteLine("ResultPoint: {0}", point.ToString());
                }

                Console.WriteLine("Distance To Left: {0}", (result[0] - result[1]).Length);
                Console.WriteLine("Distance To Right: {0}", (result[0] - result[2]).Length);

                Console.WriteLine("----------------------------------------");
            }
        }
예제 #2
0
        /// <summary>
        ///     Only for internal testing purposes. Three nodes a-b-c, after the process the distances should be 10 between them.
        /// </summary>
        public static void TestMajorizationSmall()
        {
            // small 4-star to test the majorization
            var positions = new List <Point>(4);

            positions.Add(new Point(0, 0));
            positions.Add(new Point(-2, -1));
            positions.Add(new Point(1, 2));


            //for first node on 0/0 create forces to push the other away
            var nodeVotings = new List <NodeVoting>(8);


            var votesNode1     = new List <Vote>();
            var votesNodeLeft  = new List <Vote>();
            var votesNodeRight = new List <Vote>();

            votesNodeLeft.Add(new Vote(0, 10, 1 / Math.Pow(10, 2)));  // force from middle node to left node
            votesNodeRight.Add(new Vote(0, 10, 1 / Math.Pow(10, 2))); // force from middle node to right node

            votesNode1.Add(new Vote(1, 10, 1 / Math.Pow(10, 2)));
            votesNode1.Add(new Vote(2, 10, 1 / Math.Pow(10, 2)));

            var blockNode1 = new List <VoteBlock>();

            blockNode1.Add(new VoteBlock(votesNode1, 1));

            var blockNodeLeft = new List <VoteBlock>();

            blockNodeLeft.Add(new VoteBlock(votesNodeLeft, 1));

            var blockNodeRight = new List <VoteBlock>();

            blockNodeRight.Add(new VoteBlock(votesNodeRight, 1));


            nodeVotings.Add(new NodeVoting(0, blockNode1));
            nodeVotings.Add(new NodeVoting(1, blockNodeLeft));
            nodeVotings.Add(new NodeVoting(2, blockNodeRight));


            var majorization = new StressMajorization();

            majorization.Positions   = positions;
            majorization.NodeVotings = nodeVotings;

            for (int i = 0; i < 20; i++)
            {
                List <Point> result = majorization.IterateSingleLocalizedMethod();

                foreach (Point point in result)
                {
                    Console.WriteLine("ResultPoint: {0}", point.ToString());
                }

                Console.WriteLine("Distance To Left: {0}", (result[0] - result[1]).Length);
                Console.WriteLine("Distance To Right: {0}", (result[0] - result[2]).Length);

                Console.WriteLine("----------------------------------------");
            }
        }
        /// <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
        }
         static void AddStressFromProximityEdges(StressMajorization stressSolver,
                                                        List<Tuple<int, int, double, double>> proximityEdgesWithDistance) {
            //set to check whether we already added forces between two nodes
            var nodePairs = new HashSet<Tuple<int, int>>();

            // set the corresponding forces/votings
            foreach (var tuple in proximityEdgesWithDistance) {
                int nodeId1 = tuple.Item1;
                int nodeId2 = tuple.Item2;
                if (nodeId1 > nodeId2) {
                    nodeId1 = tuple.Item2;
                    nodeId2 = tuple.Item1;
                }
                var tup = new Tuple<int, int>(nodeId1, nodeId2);
                if (nodePairs.Contains(tup))
                    continue;
                nodePairs.Add(tup);

                double distance = tuple.Item3;
                double weight = 1/(distance*distance);
                var voteFromNode1 = new Vote(nodeId1, distance, weight); // vote from node1 for node2
                var voteFromNode2 = new Vote(nodeId2, distance, weight); // vote from node2 for node1

                if (tuple.Item4 <= 1) {
                    //nodes do not overlap
                    // add the votings, which represent forces, to the corresponding block.
                    stressSolver.NodeVotings[nodeId2].VotingBlocks[0].Votings.Add(voteFromNode1);
                    // add vote of node1 to list of node2
                    stressSolver.NodeVotings[nodeId1].VotingBlocks[0].Votings.Add(voteFromNode2);
                }
                else {
                    //edges where nodes do overlap
                    // add the votings, which represent forces, to the corresponding block.
                    stressSolver.NodeVotings[nodeId2].VotingBlocks[1].Votings.Add(voteFromNode1);
                    // add vote of node1 to list of node2
                    stressSolver.NodeVotings[nodeId1].VotingBlocks[1].Votings.Add(voteFromNode2);
                    // add vote of node2 to list of node1
                }
            }
        }
        /// <summary>
        ///     Inits some structures.
        /// </summary>
        protected virtual void InitWithGraph() {
            if (StressSolver != null) {
                //possibly call destructor to free memory...
            }

            if (_nodes == null || _nodes.Length == 0) return;

            if (StressSolver == null) {
                StressSolver = new StressMajorization();
                if (Settings != null)
                    StressSolver.Settings = Settings.StressSettings;
            }
        }
        /// <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);
            }
        }