using System; using Annulus.CSG; using Azimuth; namespace Annulus.UnitTests.CSG { public class BoundaryIntervalsTests : UnitTestSharp.TestFixture { public static BoundaryStretch Piece(int piece) { return new BoundaryStretch { Piece = piece, OwnSite = piece }; } public static BoundaryStretch Fan(int piece) { return new BoundaryStretch { IsFan = true, Piece = piece, OwnSite = -1 - piece }; } // One cut per stretch, in order, where the interval after cut `i` has the across label `across[i]`. public static BoundaryCut[] Cuts(params int[] across) { BoundaryCut[] returnMe = new BoundaryCut[across.Length]; for (int i = 0; i < across.Length; ++i) { returnMe[i] = new BoundaryCut { Stretch = i, AcrossBefore = across[(i + across.Length - 1) % across.Length], AcrossAfter = across[i], }; } return returnMe; } public class BuildTests : UnitTestSharp.TestFixture { public void Square_HasTwoIntervalsPerSideSplitAtItsMiddle() { BoundaryLabelling labelling = new BoundaryLabelling(BoundaryLabellingTests.Rectangle(1, 1)); CheckEqual(8, labelling.Intervals.Length); CheckEqual(0, labelling.Intervals[0].Own); CheckEqual(3, labelling.Intervals[0].Across); CheckEqual(0, labelling.Intervals[1].Own); CheckEqual(1, labelling.Intervals[1].Across); CheckEqual(1, labelling.Intervals[2].Own); CheckEqual(0, labelling.Intervals[2].Across); } public void EveryIntervalStartsAtItsOwnCutAndStretch() { BoundaryLabelling labelling = new BoundaryLabelling(BoundaryLabellingTests.LShape()); for (int i = 0; i < labelling.Intervals.Length; ++i) { CheckEqual(i, labelling.Intervals[i].StartCut); CheckEqual(labelling.Cuts[i].Stretch, labelling.Intervals[i].Stretch); } } public void LShapeJointAcrossTheFloor_ResolvesToThePieceNextToItsNeighbour() { BoundaryLabelling labelling = new BoundaryLabelling(BoundaryLabellingTests.LShape()); CheckEqual(0, labelling.Intervals[1].Own); CheckEqual(2, labelling.Intervals[1].Across); } public void LShapeFan_ResolvesToTheEndingPieceWhereItMatchesThePreviousInterval() { BoundaryLabelling labelling = new BoundaryLabelling(BoundaryLabellingTests.LShape()); CheckEqual(2, labelling.Intervals[8].Own); CheckEqual(0, labelling.Intervals[8].Across); } public void LShapeFan_ResolvesToTheNextPieceWhereItMatchesTheNextInterval() { BoundaryLabelling labelling = new BoundaryLabelling(BoundaryLabellingTests.LShape()); CheckEqual(3, labelling.Intervals[9].Own); CheckEqual(5, labelling.Intervals[9].Across); } public void JointMatchingNeitherNeighbour_ResolvesToTheEarlierPiece() { BoundaryStretch[] stretches = { Piece(0), Piece(1), Piece(2), Piece(3) }; BoundaryInterval[] intervals = BoundaryIntervals.Build(Cuts(-2, 3, 3, 3), stretches); CheckEqual(0, intervals[0].Own); CheckEqual(1, intervals[0].Across); } public void JointMatchingThePreviousNeighbour_ResolvesToThePieceThatMatches() { BoundaryStretch[] stretches = { Piece(0), Piece(0), Piece(1), Piece(2), Piece(3) }; BoundaryInterval[] intervals = BoundaryIntervals.Build(Cuts(2, -2, 3, 3, 3), stretches); CheckEqual(0, intervals[1].Own); CheckEqual(2, intervals[1].Across); } public void JointMatchingTheNextNeighbour_ResolvesToThePieceThatMatches() { BoundaryStretch[] stretches = { Piece(0), Piece(0), Piece(0), Piece(2), Piece(3) }; BoundaryInterval[] intervals = BoundaryIntervals.Build(Cuts(3, -2, 2, 3, 3), stretches); CheckEqual(0, intervals[1].Own); CheckEqual(2, intervals[1].Across); } public void FanAcrossAnotherJoint_ResolvesBothToTheirPiecesThatMatchANeighbour() { BoundaryStretch[] stretches = { Piece(0), Piece(1), Piece(2), Fan(2), Piece(3) }; BoundaryInterval[] intervals = BoundaryIntervals.Build(Cuts(3, 3, 0, -2, 2), stretches); CheckEqual(3, intervals[3].Own); CheckEqual(2, intervals[3].Across); } public void JointAfterTheLastPiece_ResolvesToPieceZeroWhereItMatchesTheFirstInterval() { BoundaryStretch[] stretches = { Piece(0), Piece(1), Piece(2), Fan(2) }; BoundaryInterval[] intervals = BoundaryIntervals.Build(Cuts(1, 2, 0, 1), stretches); CheckEqual(0, intervals[3].Own); CheckEqual(1, intervals[3].Across); } public void IntervalsWithoutJoints_AreLeftAsLabelled() { BoundaryStretch[] stretches = { Piece(0), Piece(1), Piece(2) }; BoundaryInterval[] intervals = BoundaryIntervals.Build(Cuts(2, 0, 1), stretches); CheckEqual(1, intervals[1].Own); CheckEqual(0, intervals[1].Across); } public void CutsWithDisagreeingLabels_Throw() { BoundaryCut[] cuts = new BoundaryCut[] { new BoundaryCut { Stretch = 0, AcrossBefore = 1, AcrossAfter = 2 }, new BoundaryCut { Stretch = 0, AcrossBefore = 3, AcrossAfter = 1 }, }; CheckThrow(typeof(InvalidOperationException)); BoundaryIntervals.Build(cuts, new BoundaryStretch[] { Piece(0) }); } } } }