/// <summary> /// Removes node overlap occurring in the input graph /// </summary> /// <param name="graph">GraphMapData</param> public static void FSAOverlapRemoval(GraphMapData graph) { ICollection <NodeMapData> nodes = graph.GetNodes(); IDictionary <string, Rect> rectangles = new Dictionary <string, Rect>(nodes.Count); foreach (NodeMapData node in nodes) { Point location = new Point(node.Position.X, node.Position.Y); Rect rect = new Rect(location, node.Dimension); rectangles[node.Id] = rect; } OverlapRemovalParameters overlapRemovalParameters = new OverlapRemovalParameters() { HorizontalGap = 0F, VerticalGap = 0F }; FSAAlgorithm <string> overlapRemoval = new FSAAlgorithm <string>(rectangles, overlapRemovalParameters); overlapRemoval.Compute(); foreach (NodeMapData node in nodes) { Rect rect = overlapRemoval.Rectangles[node.Id]; Point pos = new Point(rect.X, rect.Y); node.Position = pos; } }
private object RemoveOverlaps2() { OverlapRemovalParameters params2 = new OverlapRemovalParameters(); params2.HorizontalGap = 40; params2.VerticalGap = 40; var vertexRectangles = new Dictionary <string, Rectangle>(); for (int i = 0; i < vertexLabels.Length; ++i) { var vertex = vertexPositions[vertexLabels[i]]; var border = vertexBorders[vertexLabels[i]]; var rect = new Rectangle(); rect.Width = border.Right - border.Left; rect.Height = border.Bottom - border.Top; vertexRectangles.Add(vertexLabels[i], rect); } FSAAlgorithm <string> algo2; algo2 = new FSAAlgorithm <string>(null, params2); algo2.Compute(); return(null); }
public void Constructor() { Constructor_Test <double, OverlapRemovalParameters, FSAAlgorithm <double, OverlapRemovalParameters> >( (rectangles, parameters) => new FSAAlgorithm <double, OverlapRemovalParameters>(rectangles, parameters)); var rects = new Dictionary <double, Rect>(); var param = new OverlapRemovalParameters(); var algorithm = new FSAAlgorithm <double>(rects, param); AssertAlgorithmProperties(algorithm, rects, param); #region Local function void AssertAlgorithmProperties <TObject>( FSAAlgorithm <TObject> algo, IDictionary <TObject, Rect> r, IOverlapRemovalParameters p) { AssertAlgorithmState(algo); Assert.AreSame(r, algo.Rectangles); Assert.AreSame(p, algo.Parameters); Assert.AreSame(p, algo.GetParameters()); } #endregion }
private void VerifyAxisResults(uint rep, ConstraintGenerator generator, OverlapRemovalParameters olapParameters, ref bool succeeded) { var axisName = generator.IsHorizontal ? "X" : "Y"; var solver = generator.IsHorizontal ? this.SolverX : this.SolverY; var solution = generator.IsHorizontal ? this.SolutionX : this.SolutionY; if (TestGlobals.VerboseLevel >= 3) { this.WriteLine(" {0} Nodes after solving Constraints:", axisName); foreach (Variable var in solver.Variables) { var node = (OverlapRemovalNode)var.UserData; Console.Write(" {0}", node); const string Format = " - L/R T/B {0:F5}/{1:F5} {2:F5}/{3:F5}"; if (generator.IsHorizontal) { // X is Perpendicular here this.WriteLine(Format, node.OpenP, node.CloseP, node.Open, node.Close); } else { // Y is Perpendicular here this.WriteLine(Format, node.Open, node.Close, node.OpenP, node.CloseP); } } } // We should never see unsatisfiable constraints since we created them ourselves. if (0 != solution.NumberOfUnsatisfiableConstraints) { succeeded = false; this.WriteLine(" *** Error! {0} unsatisfiable {1} constraints found ***", solution.NumberOfUnsatisfiableConstraints, axisName); if ((TestGlobals.VerboseLevel >= 2) && (0 == rep)) { foreach (Constraint cst in solver.Constraints.Where(cst => cst.IsUnsatisfiable)) { this.WriteLine(" {0}", cst); } } // endif VerboseLevel } // endif unsatisfiable constraints bool violationSeen = false; foreach (Constraint cst in solver.Constraints) { if (!this.VerifyConstraint(olapParameters.SolverParameters, cst, generator.IsHorizontal, ref violationSeen)) { succeeded = false; } } if (solution.ExecutionLimitExceeded) { this.WriteLine(GetCutoffString(solution)); } }
private void RunFSA(CancellationToken cancellationToken) { OverlapRemovalParameters parameters = new OverlapRemovalParameters { HorizontalGap = 20, VerticalGap = 30 }; var oneWayFSA = new FSAAlgorithm <ElementVertex>(Rectangles, parameters); oneWayFSA.Compute(cancellationToken); Rectangles = oneWayFSA.Rectangles; }
public void Parameter_Throws() { var parameters = new OverlapRemovalParameters(); Assert.Throws <ArgumentOutOfRangeException>(() => parameters.VerticalGap = -1); Assert.Throws <ArgumentOutOfRangeException>(() => parameters.HorizontalGap = -1); var oneWayFSAParameters = new OneWayFSAParameters(); Assert.Throws <ArgumentOutOfRangeException>(() => oneWayFSAParameters.VerticalGap = -1); Assert.Throws <ArgumentOutOfRangeException>(() => oneWayFSAParameters.HorizontalGap = -1); }
public DependencyGraphLayout() { LayoutAlgorithmFactory = new CCLayoutAlgorithmFactory <DisplayNode, DisplayEdge, _IDisplayGraph?>(); OverlapRemovalParameters = new OverlapRemovalParameters() { HorizontalGap = 10, VerticalGap = 10 }; OverlapRemovalAlgorithmType = "FSA"; AsyncCompute = true; AnimationLength = TimeSpan.FromMilliseconds(200); HighlightAlgorithmType = "Simple"; }
public void Constructor_Throws() { var rectangles = new Dictionary <double, Rect>(); var parameters = new OverlapRemovalParameters(); // ReSharper disable ObjectCreationAsStatement // ReSharper disable AssignNullToNotNullAttribute Assert.Throws <ArgumentNullException>(() => new FSAAlgorithm <double>(null, parameters)); Assert.Throws <ArgumentNullException>(() => new FSAAlgorithm <double>(rectangles, null)); Assert.Throws <ArgumentNullException>(() => new FSAAlgorithm <double>(null, null)); // ReSharper restore AssignNullToNotNullAttribute // ReSharper restore ObjectCreationAsStatement }
public static void ShowGraphCircular(GraphLayout layout, IBidirectionalGraph <object, IEdge <object> > graph, int horizontalGap = 25, int verticalGap = 10) { var overlapParameters = new OverlapRemovalParameters(); overlapParameters.HorizontalGap = horizontalGap; overlapParameters.VerticalGap = verticalGap; layout.OverlapRemovalParameters = overlapParameters; layout.OverlapRemovalAlgorithmType = "FSA"; layout.OverlapRemovalConstraint = AlgorithmConstraints.Must; layout.LayoutMode = LayoutMode.Simple; layout.LayoutAlgorithmType = "Circular"; layout.Graph = graph; }
void tst_but_gen_Click(object sender, RoutedEventArgs e) { var graph = GenerateTestGraph(); var logic = new LogicCoreExample { Graph = graph }; logic.EnableParallelEdges = false; logic.ParallelEdgeDistance = 15; tst_Area.ShowAllEdgesArrows(false); tst_Area.LogicCore = logic; var layParams = new LinLogLayoutParameters { IterationCount = 100 }; logic.DefaultLayoutAlgorithm = LayoutAlgorithmTypeEnum.Tree; logic.DefaultLayoutAlgorithmParams = layParams; var overlapParams = new OverlapRemovalParameters { HorizontalGap = 100, VerticalGap = 100 }; logic.DefaultOverlapRemovalAlgorithm = OverlapRemovalAlgorithmTypeEnum.FSA; logic.DefaultOverlapRemovalAlgorithmParams = overlapParams; IExternalEdgeRouting <DataVertex, DataEdge> erParams = null; //logic.ExternalEdgeRoutingAlgorithm = tst_Area.GenerateGraph(graph, true); //tst_Area.VertexList[v1].Visibility = System.Windows.Visibility.Collapsed; //tst_Area.VertexList[v2].Visibility = System.Windows.Visibility.Collapsed; //tst_Area.VertexList[v3].Visibility = System.Windows.Visibility.Collapsed; //tst_Area.VertexList[v4].SetPosition(new Point(0, 0)); tst_Area.ShowAllEdgesLabels(); tst_Area.AlignAllEdgesLabels(); tst_zoomctrl.ZoomToFill(); /* var img = new BitmapImage(new Uri(@"pack://application:,,,/ShowcaseExample;component/Images/birdy.png", UriKind.Absolute)) { CacheOption = BitmapCacheOption.OnLoad }; * GraphAreaBase.SetX(img, -100); * GraphAreaBase.SetY(img, -100); * var image = new Image() { Source = img, Width = 100, Height = 100 }; * var border = new Border() { BorderBrush = Brushes.Black, BorderThickness = new Thickness(2), Background = Brushes.Black, Width = 100, Height = 100 }; * image.Visibility = System.Windows.Visibility.Visible; * border.Visibility = System.Windows.Visibility.Visible; * tst_Area.InsertCustomChildControl(0, image); * tst_Area.InsertCustomChildControl(0, border);*/ }
/// <summary> /// Creates a new instance of <see cref="PointedTreeGraphLayout"/>. /// </summary> public PointedTreeGraphLayout() { HighlightAlgorithmType = "Simple"; LayoutAlgorithmType = "Tree"; OverlapRemovalAlgorithmType = "FSA"; OverlapRemovalConstraint = AlgorithmConstraints.Must; OverlapRemovalParameters = new OverlapRemovalParameters { HorizontalGap = 10, VerticalGap = 10 }; LayoutParameters = new SimpleTreeLayoutParameters { VertexGap = 10, Direction = LayoutDirection.TopToBottom, SpanningTreeGeneration = SpanningTreeGeneration.DFS }; AnimationLength = new TimeSpan(0); IsAnimationEnabled = false; }
public void Compute([NotNull] OverlapRemovalParameters parameters) { Dictionary <int, Rect> rectangles = GetRectangles(); Dictionary <int, Rect> initialRectangles = rectangles.ToDictionary( pair => pair.Key, pair => new Rect(pair.Value.Location, pair.Value.Size)); var algorithm = new FSAAlgorithm <int>(rectangles, parameters); algorithm.Compute(); foreach (KeyValuePair <int, Rect> pair in algorithm.Rectangles) { Rect initialRectangle = initialRectangles[pair.Key]; // Size must not change Assert.AreEqual(initialRectangle.Size, pair.Value.Size); // Fulfill minimum spacing AssertNoOverlap(Distinct(algorithm.Rectangles.Values)); foreach (KeyValuePair <int, Rect> innerPair in algorithm.Rectangles.Where(p => pair.Key != p.Key)) { if (NearEqual(pair.Value, innerPair.Value)) { continue; } if (Math.Abs(pair.Value.Location.X - innerPair.Value.Location.X) >= parameters.HorizontalGap) { continue; } if (Math.Abs(pair.Value.Location.Y - innerPair.Value.Location.Y) >= parameters.VerticalGap) { continue; } Assert.Fail("Minimum spacing not fulfilled."); } } }
public void Clone() { var parameters = new OverlapRemovalParameters(); var clonedParameters = (OverlapRemovalParameters)parameters.Clone(); AssertAreEqual(parameters, clonedParameters); parameters = new OverlapRemovalParameters { HorizontalGap = 25, VerticalGap = 50 }; clonedParameters = (OverlapRemovalParameters)parameters.Clone(); AssertAreEqual(parameters, clonedParameters); var oneWayFSAParameters = new OneWayFSAParameters(); var clonedOneWayFSAParameters = (OneWayFSAParameters)oneWayFSAParameters.Clone(); AssertOneWayParamsAreEqual(oneWayFSAParameters, clonedOneWayFSAParameters); oneWayFSAParameters = new OneWayFSAParameters { HorizontalGap = 25, VerticalGap = 50 }; clonedOneWayFSAParameters = (OneWayFSAParameters)oneWayFSAParameters.Clone(); AssertOneWayParamsAreEqual(oneWayFSAParameters, clonedOneWayFSAParameters); #region Local function void AssertAreEqual(IOverlapRemovalParameters p1, IOverlapRemovalParameters p2) { Assert.AreEqual(p1.HorizontalGap, p2.HorizontalGap); Assert.AreEqual(p1.VerticalGap, p2.VerticalGap); } void AssertOneWayParamsAreEqual(OneWayFSAParameters p1, OneWayFSAParameters p2) { AssertAreEqual(p1, p2); Assert.AreEqual(p1.Way, p2.Way); } #endregion }
private void AddNodesAndSolve(ConstraintGenerator generator, IEnumerable <VariableDef> iterVariableDefs, OverlapRemovalParameters olapParameters, IEnumerable <ConstraintDef> iterConstraintDefs, ref bool succeeded) { var axisName = generator.IsHorizontal ? "X" : "Y"; var solver = generator.IsHorizontal ? this.SolverX : this.SolverY; foreach (VariableDef varDef in iterVariableDefs) { // Create the variable in its initial cluster. OverlapRemovalCluster olapClusParent = generator.DefaultClusterHierarchy; if (varDef.ParentClusters.Count > 0) { olapClusParent = varDef.ParentClusters[0].Cluster; } OverlapRemovalNode newNode; if (generator.IsHorizontal) { newNode = generator.AddNode(olapClusParent, varDef.IdString, varDef.DesiredPosX, varDef.DesiredPosY, varDef.SizeX, varDef.SizeY, varDef.WeightX); varDef.VariableX = new OlapTestNode(newNode); } else { newNode = generator.AddNode(olapClusParent, varDef.IdString, varDef.DesiredPosY, varDef.VariableX.ActualPos, varDef.SizeY, varDef.SizeX, varDef.WeightY); varDef.VariableY = new OlapTestNode(newNode); } // Add it to its other clusters. for (int ii = 1; ii < varDef.ParentClusters.Count; ++ii) { olapClusParent = varDef.ParentClusters[ii].Cluster; generator.AddNodeToCluster(olapClusParent, newNode); } } generator.Generate(solver, olapParameters); if (TestGlobals.VerboseLevel >= 3) { this.WriteLine(" {0} Constraints:", axisName); foreach (Constraint cst in solver.Constraints.OrderBy(cst => cst)) { this.WriteLine(" {0} {1} g {2:F5}", cst.Left.UserData, cst.Right.UserData, cst.Gap); } } if (null != iterConstraintDefs) { // TODO: Compare expected to actual constraints generated in solver } var solution = generator.Solve(solver, olapParameters, false /* doGenerate */); if (!this.VerifySolutionMembers(solution, /*iterNeighborDefs:*/ null)) { succeeded = false; } if (generator.IsHorizontal) { this.SolutionX = solution; } else { this.SolutionY = solution; } }
private void CreateSolversAndGetSolutions(Stopwatch sw, IEnumerable <ClusterDef> iterClusterDefs, IEnumerable <VariableDef> iterVariableDefs, IEnumerable <ConstraintDef> iterConstraintDefsX, IEnumerable <ConstraintDef> iterConstraintDefsY, ref bool succeeded) { var olapParameters = new OverlapRemovalParameters(this.SolverParameters) { AllowDeferToVertical = this.AllowDeferToVertical }; for (uint rep = 0; rep < TestGlobals.TestReps; ++rep) { sw.Start(); // Load the Horizontal ProjectionSolver and ConstraintGenerator with variables. // We must Solve the X coordinates before generating the Y ones, so that the // Y generation, whose scan line uses X coordinates, uses the updated values. var generatorX = new ConstraintGenerator(true /* fIsHorizontal */, this.MinPaddingX, this.MinPaddingY); this.SolverX = new Solver(); // First create the X Clusters. if (null != iterClusterDefs) { foreach (ClusterDef clusDef in iterClusterDefs) { clusDef.ComputeInitialBorders(); // called for H only; does both H and V clusDef.CreateCluster(generatorX); } } this.AddNodesAndSolve(generatorX, iterVariableDefs, olapParameters, iterConstraintDefsX, ref succeeded); sw.Stop(); this.VerifyAxisResults(rep, generatorX, olapParameters, ref succeeded); sw.Start(); // Load the Vertical ProjectionSolver and ConstraintGenerator with variables. // This uses the X coordinate determined by the above solution for the perpendicular. var generatorY = new ConstraintGenerator(false /* fIsHorizontal */, this.MinPaddingY, this.MinPaddingX); this.SolverY = new Solver(); // First create the Y Clusters. if (null != iterClusterDefs) { // Clear out the ConGenX Clusters first, then create them in ConGenY. foreach (ClusterDef clusDef in iterClusterDefs) { if (!clusDef.PostX()) { succeeded = false; } } foreach (ClusterDef clusDef in iterClusterDefs) { clusDef.CreateCluster(generatorY); } } this.AddNodesAndSolve(generatorY, iterVariableDefs, olapParameters, iterConstraintDefsY, ref succeeded); sw.Stop(); if (null != iterClusterDefs) { foreach (ClusterDef clusDef in iterClusterDefs) { if (!clusDef.PostY()) { succeeded = false; } } } this.VerifyAxisResults(rep, generatorY, olapParameters, ref succeeded); } }
public void StandardFactory() { var rectangles = new Dictionary <int, Rect>(); var context = new TestOverlapRemovalContext(rectangles); var factory = new StandardOverlapRemovalAlgorithmFactory <int>(); CollectionAssert.AreEqual(new[] { "FSA", "OneWayFSA" }, factory.AlgorithmTypes); Assert.IsNull( factory.CreateAlgorithm( string.Empty, context, new OverlapRemovalParameters())); Assert.IsInstanceOf <FSAAlgorithm <int> >( factory.CreateAlgorithm( "FSA", context, new OverlapRemovalParameters())); Assert.IsInstanceOf <OneWayFSAAlgorithm <int> >( factory.CreateAlgorithm( "OneWayFSA", context, new OneWayFSAParameters())); var fsaParameters = new OverlapRemovalParameters(); IOverlapRemovalParameters createdParameters = factory.CreateParameters(string.Empty, fsaParameters); Assert.IsNull(createdParameters); createdParameters = factory.CreateParameters("fsa", fsaParameters); Assert.IsNull(createdParameters); createdParameters = factory.CreateParameters("FSA", fsaParameters); Assert.IsInstanceOf <OverlapRemovalParameters>(createdParameters); Assert.AreNotSame(fsaParameters, createdParameters); createdParameters = factory.CreateParameters("FSA", null); Assert.IsInstanceOf <OverlapRemovalParameters>(createdParameters); Assert.AreNotSame(fsaParameters, createdParameters); var oneWayFSAParameters = new OneWayFSAParameters(); createdParameters = factory.CreateParameters("OneWayFSA", oneWayFSAParameters); Assert.IsInstanceOf <OneWayFSAParameters>(createdParameters); Assert.AreNotSame(oneWayFSAParameters, createdParameters); createdParameters = factory.CreateParameters("OneWayFSA", null); Assert.IsInstanceOf <OneWayFSAParameters>(createdParameters); Assert.AreNotSame(oneWayFSAParameters, createdParameters); createdParameters = factory.CreateParameters("OneWayFSA", fsaParameters); Assert.IsInstanceOf <OneWayFSAParameters>(createdParameters); Assert.AreNotSame(fsaParameters, createdParameters); Assert.AreNotSame(oneWayFSAParameters, createdParameters); Assert.IsFalse(factory.IsValidAlgorithm(null)); Assert.IsFalse(factory.IsValidAlgorithm(string.Empty)); Assert.IsTrue(factory.IsValidAlgorithm("FSA")); Assert.IsTrue(factory.IsValidAlgorithm("OneWayFSA")); Assert.IsFalse(factory.IsValidAlgorithm("fsa")); var algorithm1 = new FSAAlgorithm <int, OverlapRemovalParameters>(rectangles, new OverlapRemovalParameters()); Assert.IsEmpty(factory.GetAlgorithmType(algorithm1)); var algorithm2 = new FSAAlgorithm <int>(rectangles, new OverlapRemovalParameters()); Assert.AreEqual("FSA", factory.GetAlgorithmType(algorithm2)); var algorithm3 = new OneWayFSAAlgorithm <int>(rectangles, new OneWayFSAParameters()); Assert.AreEqual("OneWayFSA", factory.GetAlgorithmType(algorithm3)); }
public void ParameterRaise() { string expectedPropertyName = null; var parameters = new OverlapRemovalParameters(); parameters.PropertyChanged += (sender, args) => { // ReSharper disable AccessToModifiedClosure if (expectedPropertyName is null) { Assert.Fail("Must not raise."); } else { Assert.AreEqual(expectedPropertyName, args.PropertyName); } // ReSharper restore AccessToModifiedClosure }; expectedPropertyName = nameof(OverlapRemovalParameters.VerticalGap); parameters.VerticalGap = 42; expectedPropertyName = null; parameters.VerticalGap = 42; expectedPropertyName = nameof(OverlapRemovalParameters.HorizontalGap); parameters.HorizontalGap = 72; expectedPropertyName = null; parameters.HorizontalGap = 72; var oneWayFSAParameters = new OneWayFSAParameters(); oneWayFSAParameters.PropertyChanged += (sender, args) => { // ReSharper disable AccessToModifiedClosure if (expectedPropertyName is null) { Assert.Fail("Must not raise."); } else { Assert.AreEqual(expectedPropertyName, args.PropertyName); } // ReSharper restore AccessToModifiedClosure }; expectedPropertyName = nameof(OverlapRemovalParameters.VerticalGap); oneWayFSAParameters.VerticalGap = 42; expectedPropertyName = null; oneWayFSAParameters.VerticalGap = 42; expectedPropertyName = nameof(OverlapRemovalParameters.HorizontalGap); oneWayFSAParameters.HorizontalGap = 72; expectedPropertyName = null; oneWayFSAParameters.HorizontalGap = 72; expectedPropertyName = nameof(OneWayFSAParameters.Way); oneWayFSAParameters.Way = OneWayFSAWay.Vertical; expectedPropertyName = null; oneWayFSAParameters.Way = OneWayFSAWay.Vertical; expectedPropertyName = nameof(OneWayFSAParameters.Way); oneWayFSAParameters.Way = OneWayFSAWay.Horizontal; }