using System; using System.Collections.Generic; using System.Linq; using System.Text; using Azimuth; namespace Annulus.UnitTests { class PolygonUtilitiesTests : UnitTestSharp.TestFixture { public void CyclicIncrement_Normal() { int val = 5; val = Polygon.Utilities.CyclicIncrement(val, 10); CheckEqual(6, val); } public void CyclicIncrement_Wrap() { int val = 9; val = Polygon.Utilities.CyclicIncrement(val, 10); CheckEqual(0, val); } public void CyclicDecrement_Normal() { int val = 5; val = Polygon.Utilities.CyclicDecrement(val, 10); CheckEqual(4, val); } public void CyclicDecrement_Wrap() { int val = 0; val = Polygon.Utilities.CyclicDecrement(val, 10); CheckEqual(9, val); } public class SimplifyPolygonTests : UnitTestSharp.TestFixture { public void NoDuplicates() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(0, 1), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(vertexList.Count(), newList.Count()); for (int i = 0; i < vertexList.Count(); ++i) { CheckEqual(vertexList[i], newList[i]); } } public void MidListDuplicate() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(1, 0), new Vector(0, 1), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(3, newList.Count()); CheckEqual(vertexList[0], newList[0]); CheckEqual(vertexList[1], newList[1]); CheckEqual(vertexList[3], newList[2]); } public void StartListDuplicate() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(0, 1), new Vector(0, 0), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(vertexList.Count() - 1, newList.Count()); CheckEqual(vertexList[0], newList[0]); CheckEqual(vertexList[1], newList[1]); CheckEqual(vertexList[2], newList[2]); } public void AllDuplicates() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(0, 0), new Vector(0, 0), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(0, newList.Count()); } public void OnlyOne() { IList vertexList = new Vector[] { new Vector(0, 0), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(0, newList.Count()); } public void NoRedundancies() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(0, 1), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(3, newList.Count()); for (int i = 0; i < newList.Count(); ++i) { CheckEqual(vertexList[i], newList[i]); } } public void MidListRedundancies() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(0.5, 0), new Vector(0.75, 0), new Vector(1, 0), new Vector(0, 1), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(3, newList.Count()); CheckEqual(vertexList[0], newList[0]); CheckEqual(vertexList[3], newList[1]); CheckEqual(vertexList[4], newList[2]); } public void ZeroAreaEar() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(0, 1), new Vector(0.75, 0), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(vertexList.Count() - 1, newList.Count()); for (int i = 0; i < newList.Count(); ++i) { CheckEqual(vertexList[i+1], newList[i]); }; } public void EndOfListRedundancy() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(0, 1), new Vector(-2, 0), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(vertexList.Count() - 1, newList.Count()); CheckEqual(vertexList[1], newList[0]); CheckEqual(vertexList[2], newList[1]); CheckEqual(vertexList[3], newList[2]); } public void FakeRedundancies() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(0.25, 1), new Vector(0.5, 0), new Vector(0, 1), new Vector(0.75, 0), new Vector(1, 0), new Vector(0, 1), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(7, newList.Count()); for (int i = 0; i < vertexList.Count(); ++i) { CheckEqual(vertexList[i], newList[i]); }; } public void MultipleEars() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(0, 1), new Vector(0.5, 0), new Vector(-0.75, 0), new Vector(0.75, 0), new Vector(0.25, 0), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(3, newList.Count()); CheckEqual(vertexList[1], newList[0]); CheckEqual(vertexList[2], newList[1]); CheckEqual(vertexList[3], newList[2]); } public void ColinearTriangle() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(-1, 0), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(0, newList.Count()); } public void ColinearPolygon() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(-1, 0), new Vector(2, 0), new Vector(3, 0), new Vector(-2, 0), new Vector(0, 0), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(0, newList.Count()); } public void ColinearPolygon_DuplicatedMaxExtents() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(-1, 0), new Vector(2, 0), new Vector(3, 0), new Vector(3, 0), new Vector(3, 0), new Vector(-2, 0), new Vector(-2, 0), new Vector(-2, 0), new Vector(0, 0), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(0, newList.Count()); } public void WindAndUnwind() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(0, 1), new Vector(0, 0), new Vector(0, 1), new Vector(1, 0), }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(0, newList.Count()); } public void Empty() { IList vertexList = new Vector[] { }; var newList = Polygon.Utilities.SimplifyPolygon(vertexList); CheckEqual(0, newList.Count()); } } public class ForEachEdgePairTests : UnitTestSharp.TestFixture { public void Basic() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), new Vector(0, 1), }; int runCount = 0; var edgeList = new List(vertexList.Count()); Polygon.Utilities.ForEachAdjacentEdgePair(vertexList, delegate(Vector trailingEdge, Vector leadingEdge, int middleVertex) { ++runCount; edgeList.Add(leadingEdge); }); CheckEqual(vertexList.Count(), runCount); CheckEqual(vertexList.Count(), edgeList.Count()); CheckEqual(new Vector(1, 0), edgeList[0]); CheckEqual(new Vector(-1, 1), edgeList[1]); CheckEqual(new Vector(0, -1), edgeList[2]); } public void NotEnoughElements() { IList vertexList = new Vector[] { new Vector(0, 0), new Vector(1, 0), }; int runCount = 0; Polygon.Utilities.ForEachAdjacentEdgePair(vertexList, delegate(Vector trailingEdge, Vector leadingEdge, int middleVertex) { ++runCount; }); CheckEqual(0, runCount); } } public class SignedAreaTests : UnitTestSharp.TestFixture { public void CW_UnitTris() { var verts = new List() { new Vector(0,0), new Vector(1,0), new Vector(0,1), }; CheckEqual(-0.5, Polygon.Utilities.SignedArea(verts)); } public void CW_UnitSquare() { var verts = new List() { new Vector(0,0), new Vector(1,0), new Vector(1,1), new Vector(0,1), }; CheckEqual(-1, Polygon.Utilities.SignedArea(verts)); } public void CCW_Square() { var verts = new List() { new Vector(0,1), new Vector(1,1), new Vector(1,0), new Vector(0,0), }; CheckEqual(1, Polygon.Utilities.SignedArea(verts)); } } public class IsPointInsideTests : UnitTestSharp.TestFixture { static IList box = new Vector[] { new Vector(-1, -1), new Vector(-1, 1), new Vector(1, 1), new Vector(1, -1), }; public void Basic() { var point = new Vector(0, 0); Check(Polygon.Utilities.IsPointInside(box, point)); } public void NotInside() { var point = new Vector(110, 10); CheckFalse(Polygon.Utilities.IsPointInside(box, point)); } public void OnEdge() { var point = new Vector(1, 0); CheckFalse(Polygon.Utilities.IsPointInside(box, point)); } public void OnPoint() { var point = new Vector(1, 1); CheckFalse(Polygon.Utilities.IsPointInside(box, point)); } IList cave = new Vector[] { new Vector(-2, 2), new Vector(2, 2), new Vector(2, 1), new Vector(1.5, 0), new Vector(1, 1), new Vector(-1, 1), new Vector(-1, -1), new Vector(1, -1), new Vector(1.5, 0), new Vector(2, -1), new Vector(2, -2), new Vector(-2, -2), }; public void InPit() { var point = new Vector(0, 0); CheckFalse(Polygon.Utilities.IsPointInside(cave, point)); } public void InsideShape_Cave() { var point = new Vector(-1.5, 1.5); Check(Polygon.Utilities.IsPointInside(cave, point)); } public void Degenerate() { var degenerate = new Vector[] { new Vector(2, 1), new Vector(1, 2), }; var point = new Vector(0, 0); CheckFalse(Polygon.Utilities.IsPointInside(degenerate, point)); } Vector[] diamond = new Vector[] { new Vector( 0, 1), new Vector( 1, 0), new Vector( 0,-1), new Vector(-1, 0), }; public void Diamond_Inside() { CheckTrue(Polygon.Utilities.IsPointInside(diamond, Vector.Zero)); } public void Diamond_OnEdge() { CheckFalse(Polygon.Utilities.IsPointInside(diamond, new Vector(0.5, 0.5))); } public void Diamond_Outside() { var diamond = new Vector[] { new Vector( 0, 1), new Vector( 1, 0), new Vector( 0,-1), new Vector(-1, 0), }; CheckFalse(Polygon.Utilities.IsPointInside(diamond, new Vector(10, 0))); } } public class CalculateAABBTests : UnitTestSharp.TestFixture { public void Basic() { var box = new Vector[] { new Vector(-1,-1), new Vector(1,-1), new Vector(1,1), new Vector(-1,1), }; var aabb = Polygon.Utilities.CalculateAABB(box); var expected = new AABB(new Vector(-1, -1), new Vector(1, 1)); CheckEqual(expected, aabb); } public void Degenerate_Two() { var box = new Vector[] { new Vector(-1,-1), new Vector(1,-1), }; var aabb = Polygon.Utilities.CalculateAABB(box); var expected = new AABB(new Vector(-1, -1), new Vector(1, -1)); CheckEqual(expected, aabb); } public void Degenerate_One() { var box = new Vector[] { new Vector(-1,-1), }; var aabb = Polygon.Utilities.CalculateAABB(box); var expected = new AABB(new Vector(-1, -1), new Vector(-1, -1)); CheckEqual(expected, aabb); } public void Degenerate_Zero() { var box = new Vector[] { }; var aabb = Polygon.Utilities.CalculateAABB(box); Check(Scalar.IsNaN(aabb.Min.X)); Check(Scalar.IsNaN(aabb.Min.Y)); Check(Scalar.IsNaN(aabb.Max.X)); Check(Scalar.IsNaN(aabb.Max.Y)); } public void Concave() { var cave = new Vector[] { new Vector(-2, 2), new Vector(2, 2), new Vector(2, 1), new Vector(1.5, 0), new Vector(1, 1), new Vector(-1, 1), new Vector(-1, -1), new Vector(1, -1), new Vector(1.5, 0), new Vector(2, -1), new Vector(2, -2), new Vector(-2, -2), }; var aabb = Polygon.Utilities.CalculateAABB(cave); var expected = new AABB(new Vector(-2, -2), new Vector(2, 2)); CheckEqual(expected, aabb); } } public class CalculatePerimeterTests : UnitTestSharp.TestFixture { public void ZeroEdges() { CheckEqual(0, Polygon.Utilities.CalculatePerimeter(new Vector[] { })); } public void ZeroLength() { CheckEqual(0, Polygon.Utilities.CalculatePerimeter(new Vector[] { new Vector(0, 0) })); } public void Basic() { var perimeter = Polygon.Utilities.CalculatePerimeter(new Vector[] { new Vector(1, 0), new Vector(0, 1), new Vector(-1, 0), new Vector(0, -1), }); CheckEqual(4, perimeter); } public void Basic_ReverseWinding() { var perimeter = Polygon.Utilities.CalculatePerimeter(new Vector[] { new Vector(0, 1), new Vector(1, 0), new Vector(0,-1), new Vector(-1, 0), }); CheckEqual(4, perimeter); } } } }