Esempio n. 1
0
        /// <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;
            }
        }
Esempio n. 2
0
        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
        }
Esempio n. 4
0
        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));
            }
        }
Esempio n. 5
0
        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);
        }
Esempio n. 7
0
        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
        }
Esempio n. 9
0
        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;
        }
Esempio n. 10
0
        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);*/
        }
Esempio n. 11
0
 /// <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;
 }
Esempio n. 12
0
        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
        }
Esempio n. 14
0
        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;
            }
        }
Esempio n. 15
0
        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);
            }
        }
Esempio n. 16
0
        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;
        }