private TestCase SetupTripleArcTestCase(BreakpointNode leftBP, BreakpointNode rightBP, ArcNode leftArc,
			ArcNode middleArc, ArcNode rightArc, ArcNode expectedResult, Vector newSitePos)
        {
            leftArc.Parent = leftBP;
            middleArc.Parent = rightBP;
            rightArc.Parent = rightBP;
            leftBP.LeftChild = leftArc;
            leftBP.RightChild = rightBP;
            rightBP.Parent = leftBP;
            rightBP.LeftChild = middleArc;
            rightBP.RightChild = rightArc;
            return new TestCase
            {
                RootNode = leftBP,
                ExpectedResult = expectedResult,
                NewSitePosition = newSitePos
            };
        }
        public void FindsCorrectArcNode()
        {
            // First object is root node, second object is expected result arc node.
            var tests = new List<TestCase>();

            // A single arc.
            {
                var singleArc = new ArcNode(new Site(new Vector(0, 1)));
                tests.Add(new TestCase
                {
                    RootNode = singleArc,
                    ExpectedResult = singleArc,
                    NewSitePosition = new Vector(0, 0)
                });
            }
            // Simple tree with three arcs.
            {
                /*
                var leftArc = new ArcNode(new Site(new Vector(0, 10)));
                var middleArc = new ArcNode(new Site(new Vector(5, 2)));
                var rightArc = new ArcNode(leftArc.DefiningSite);
                var leftBP = new BreakpointNode(leftArc.DefiningSite, middleArc.DefiningSite, null, true);
                var rightBP = new BreakpointNode(leftArc.DefiningSite, middleArc.DefiningSite, null, false);
                tests.Add(SetupTripleArcTestCase(
                    leftBP, rightBP, leftArc, middleArc, rightArc,
                    leftArc, new Vector(-5, 0)));
                tests.Add(SetupTripleArcTestCase(
                    leftBP, rightBP, leftArc, middleArc, rightArc,
                    middleArc, new Vector(5, 0)));
                tests.Add(SetupTripleArcTestCase(
                    leftBP, rightBP, leftArc, middleArc, rightArc,
                    rightArc, new Vector(500, 0)));
                 */
            }
            // Three arc tree with sites vertically aligned.
            {
                // Breakpoints are at +- 7.01...
                var leftArc = new ArcNode(new Site(new Vector(0, 10)));
                var middleArc = new ArcNode(new Site(new Vector(0, 5)));
                var rightArc = new ArcNode(leftArc.DefiningSite);
                var leftBP = new BreakpointNode(leftArc.DefiningSite, middleArc.DefiningSite, null, true);
                var rightBP = new BreakpointNode(leftArc.DefiningSite, middleArc.DefiningSite, null, false);
                tests.Add(SetupTripleArcTestCase(
                    leftBP, rightBP, leftArc, middleArc, rightArc,
                    leftArc, new Vector(-250, 0)));
                tests.Add(SetupTripleArcTestCase(
                    leftBP, rightBP, leftArc, middleArc, rightArc,
                    middleArc, new Vector(-1, 0)));
                tests.Add(SetupTripleArcTestCase(
                    leftBP, rightBP, leftArc, middleArc, rightArc,
                    middleArc, new Vector(0, 0)));
                tests.Add(SetupTripleArcTestCase(
                    leftBP, rightBP, leftArc, middleArc, rightArc,
                    middleArc, new Vector(1, 0)));
                tests.Add(SetupTripleArcTestCase(
                    leftBP, rightBP, leftArc, middleArc, rightArc,
                    rightArc, new Vector(250, 0)));
            }

            foreach (var test in tests)
                Assert.That(Helpers.FindArcSplitByNewSite(test.NewSitePosition, test.RootNode), Is.EqualTo(test.ExpectedResult));
        }
Ejemplo n.º 3
0
        private void HandleSiteEvent(SiteEvent ev, State state)
        {
            // If the beach line data structure is empty, initialize
            // it with the arc created by the new site into it and return.
            if (state.BeachLine == null)
            {
                state.BeachLine = new ArcNode(ev.Site);
                return;
            }

            // Find the arc split by the new site.
            var splitArcNode = Helpers.FindArcSplitByNewSite(ev.Site.Position, state.BeachLine);

            // If the arc being split has a circle event, it is a false alarm,
            // so delete it from the event queue.
            if (splitArcNode.DisappearanceEvent != null)
                state.EventQueue.Remove(splitArcNode.DisappearanceEvent.Index);

            // The following pieces of the final Voronoi diagram are created
            // during a site event:
            //	- The Face defined by the new site.
            //	- Both HalfEdges of the edge that will be traced out by the
            //	two new breakpoints.
            var newFace = new Face {UserData = ev.Site.UserData};
            var halfEdgeFacingOldSite = new HalfEdge();
            var halfEdgeFacingNewSite = new HalfEdge();
            state.Faces.Add(ev.Site, newFace);
            state.HalfEdges.Add(halfEdgeFacingOldSite);
            state.HalfEdges.Add(halfEdgeFacingNewSite);

            // Link all the diagram pieces together that can be linked at this time.
            halfEdgeFacingOldSite.Interior = state.Faces[splitArcNode.DefiningSite];
            halfEdgeFacingNewSite.Interior = newFace;
            halfEdgeFacingOldSite.Twin = halfEdgeFacingNewSite;
            halfEdgeFacingNewSite.Twin = halfEdgeFacingOldSite;

            // During a site event, an existing arc is split into two
            // new arcs with an additional arc in the middle. We reflect
            // this change in beach line status tree data structure by
            // replacing the split arc node with a new subtree with five
            // nodes total: two for the two new breakpoints, and three
            // for the three new arcs on the beach line.
            var leftBP = new BreakpointNode(ev.Site, splitArcNode.DefiningSite, halfEdgeFacingOldSite, true);
            var rightBP = new BreakpointNode(ev.Site, splitArcNode.DefiningSite, halfEdgeFacingNewSite, false);
            var leftArc = new ArcNode(splitArcNode.DefiningSite);
            var middleArc = new ArcNode(ev.Site);
            var rightArc = new ArcNode(splitArcNode.DefiningSite);

            // Set up new subtree.
            leftBP.LeftChild = leftArc;
            leftBP.RightChild = rightBP;
            rightBP.LeftChild = middleArc;
            rightBP.RightChild = rightArc;
            rightBP.Parent = leftBP;
            leftArc.Parent = leftBP;
            middleArc.Parent = rightBP;
            rightArc.Parent = rightBP;

            // Graft new subtree into existing beach line status tree data structure.
            // First check for the special case where the split arc node was the
            // root element of the tree (aka the only element).
            if (splitArcNode.Parent == null)
            {
                if (state.BeachLine != splitArcNode)
                    throw new SanityCheckFailedException(
                        "The splitArcNode's parent was null, but it was not the root of the beach line status tree data structure.");
                state.BeachLine = leftBP;
            }
            // Otherwise, graft into existing tree. Here is where
            // we would perform rebalancing operations on the tree.
            else
            {
                if (splitArcNode.Parent.LeftChild == splitArcNode)
                {
                    splitArcNode.Parent.LeftChild = leftBP;
                    leftBP.Parent = splitArcNode.Parent;
                }
                else
                {
                    splitArcNode.Parent.RightChild = leftBP;
                    leftBP.Parent = splitArcNode.Parent;
                }
            }
        }