/// <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> /// 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); } }