using System; using System.Collections.Generic; using System.Linq; using System.Text; using Azimuth; using Annulus.CSG; namespace Annulus.UnitTests.CSG { public class PolygonFlattenTests : UnitTestSharp.TestFixture { public delegate void CheckEqualDelegate(object lhs, object rhs); public static void Test(PolygonPolygon.UnionStatus expectedStatus, PolygonPolygon.UnionStatus actualStatus, SimplePolygon expectedSilhouette, SimplePolygon actualSilhouette, IList expectedHoles, IList actualHoles, CheckEqualDelegate CheckEqual) { CheckEqual(expectedStatus, actualStatus); if (actualStatus != PolygonPolygon.UnionStatus.Success) { CheckEqual(null, expectedSilhouette); CheckEqual(null, expectedHoles); CheckEqual(null, actualSilhouette); CheckEqual(null, actualHoles); return; } expectedSilhouette = expectedSilhouette ?? new SimplePolygon(new List()); expectedHoles = expectedHoles ?? new List(); CheckEqual(expectedSilhouette.Vertices.Count(), actualSilhouette.Vertices.Count()); CheckEqual(expectedHoles.Count(), actualHoles.Count()); if (expectedSilhouette.Vertices.Count() == actualSilhouette.Vertices.Count()) { for (int i = 0; i < expectedSilhouette.Vertices.Count(); ++i) { CheckEqual(expectedSilhouette.Vertices[i], actualSilhouette.Vertices[i]); } } if (expectedHoles.Count() == actualHoles.Count()) { for (int i = 0; i < expectedHoles.Count(); ++i) { CheckEqual(expectedHoles[i].Vertices.Count(), actualHoles[i].Vertices.Count()); if (expectedHoles[i].Vertices.Count() != actualHoles[i].Vertices.Count()) { continue; } for (int j = 0; j < expectedHoles[i].Vertices.Count(); ++j) { CheckEqual(expectedHoles[i].Vertices[j], actualHoles[i].Vertices[j]); } } } } public void Tris() { var tris = new SimplePolygon(new Vector[] { new Vector(0,0), new Vector(1,0), new Vector(0,1), }); SimplePolygon silhouette; IList holes; var status = Annulus.CSG.PolygonPolygon.FlattenComplexPolygon(tris.Vertices, out silhouette, out holes); Test(PolygonPolygon.UnionStatus.Success, status, tris, silhouette, null, holes, CheckEqual); } public void Quad() { var tris = new SimplePolygon(new Vector[] { new Vector(-1,1), new Vector(-1,-1), new Vector(1,-1), new Vector(1,1), }); SimplePolygon silhouette; IList holes; var status = Annulus.CSG.PolygonPolygon.FlattenComplexPolygon(tris.Vertices, out silhouette, out holes); Test(PolygonPolygon.UnionStatus.Success, status, tris, silhouette, null, holes, CheckEqual); } public void WeaklySimple_Vertex() { 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 expectedSilhouette = new Vector[] { new Vector(-2, 2), new Vector(2, 2), new Vector(2, 1), new Vector(1.5, 0), new Vector(2, -1), new Vector(2, -2), new Vector(-2, -2), }; SimplePolygon silhouette; IList holes; var status = Annulus.CSG.PolygonPolygon.FlattenComplexPolygon(cave, out silhouette, out holes); Test(PolygonPolygon.UnionStatus.Success, status, new SimplePolygon(cave), silhouette, null, holes, CheckEqual); } public void WeaklySimple_Edge_Matching() { var cave = new Vector[] { new Vector(-2, 2), new Vector(2, 2), new Vector(2, 0), new Vector(1, 0), new Vector(1, 1), new Vector(-1, 1), new Vector(-1, -1), new Vector(1, -1), new Vector(1, 0), new Vector(2, 0), new Vector(2, -2), new Vector(-2, -2), }; var expectedSilhouette = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector(2, 2), new Vector(2, -2), new Vector(-2, -2), }); var expectedHole = new SimplePolygon(new Vector[] { new Vector(1, 1), new Vector(-1, 1), new Vector(-1, -1), new Vector(1, -1), }); SimplePolygon silhouette; IList holes; var status = Annulus.CSG.PolygonPolygon.FlattenComplexPolygon(cave, out silhouette, out holes); Test(PolygonPolygon.UnionStatus.Success, status, expectedSilhouette, silhouette, new SimplePolygon[] { expectedHole }, holes, CheckEqual); } public void WeaklySimple_Edge_NotMatching() { var cave = new Vector[] { new Vector(-2, 2), new Vector(2, 2), new Vector(2, 0), new Vector(1, 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.5, 0), new Vector(2, -2), new Vector(-2, -2), }; var expectedSilhouette = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector(2, 2), new Vector(2, 0), new Vector(2.5, 0), new Vector(2, -2), new Vector(-2, -2), }); var expectedHole = new SimplePolygon(new Vector[] { new Vector(1.5, 0), new Vector(1, 0), new Vector(1, 1), new Vector(-1, 1), new Vector(-1, -1), new Vector(1, -1), }); SimplePolygon silhouette; IList holes; var status = Annulus.CSG.PolygonPolygon.FlattenComplexPolygon(cave, out silhouette, out holes); Test(PolygonPolygon.UnionStatus.Success, status, expectedSilhouette, silhouette, new SimplePolygon[] { expectedHole }, holes, CheckEqual); } public void NicelySelfIntersecting() { var cave = new Vector[] { new Vector(-2, 2), new Vector(2, 2), new Vector(2, -.5), new Vector(1, -.5), new Vector(1, 1), new Vector(-1, 1), new Vector(-1, -1), new Vector(1, -1), new Vector(1.5, .5), new Vector(2.5, .5), new Vector(2, -2), new Vector(-2, -2), }; var expectedSilhouette = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector(2, 2), new Vector(2, .5), new Vector(2.5, .5), new Vector(2, -2), new Vector(-2, -2), }); var expectedHole = new SimplePolygon(new Vector[] { new Vector(7/6.0, -.5), new Vector(1, -.5), new Vector(1, 1), new Vector(-1, 1), new Vector(-1, -1), new Vector(1, -1), }); SimplePolygon silhouette; IList holes; var status = Annulus.CSG.PolygonPolygon.FlattenComplexPolygon(cave, out silhouette, out holes); Test(PolygonPolygon.UnionStatus.Success, status, expectedSilhouette, silhouette, new SimplePolygon[] { expectedHole }, holes, CheckEqual); } } }