public static void ConvexBasic(IPolygonSubtractor sub) { // Basic corner clips (produces an 'L' shape) DTPolygon clip0 = Translate(square, V(-1, -1)); // bottom left DTPolygon clip1 = Translate(square, V(1, -1)); // bottom right DTPolygon clip2 = Translate(square, V(1, 1)); // top right DTPolygon clip3 = Translate(square, V(-1, 1)); // top left // Basic edge clips (produces a 'C' shape) DTPolygon clip4 = Translate(narrowRect, V(0, -1)); // bottom DTPolygon clip5 = Translate(shortRect, V(1, 0)); // right DTPolygon clip6 = Translate(narrowRect, V(0, 1)); // top DTPolygon clip7 = Translate(shortRect, V(-1, 0)); // left // Diamond clip (produces 4 triangles) DTPolygon clip8 = P(V(0, -1.5f), V(1.5f, 0), V(0, 1.5f), V(-1.5f, 0)); // start with bottom vertex // Basic corner clips (produces an 'L' shape) List <DTPolygon> expected0 = L(P(V(0, 0), V(0, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0))); List <DTPolygon> expected1 = L(P(V(-1, -1), V(0, -1), V(0, 0), V(1, 0), V(1, 1), V(-1, 1))); List <DTPolygon> expected2 = L(P(V(-1, -1), V(1, -1), V(1, 0), V(0, 0), V(0, 1), V(-1, 1))); List <DTPolygon> expected3 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 1), V(0, 0), V(-1, 0))); // Basic edge clips (produces a 'C' shape) List <DTPolygon> expected4 = L(P(V(-1, -1), V(-0.5f, -1), V(-0.5f, 0), V(0.5f, 0), V(0.5f, -1), V(1, -1), V(1, 1), V(-1, 1))); List <DTPolygon> expected5 = L(P(V(-1, -1), V(1, -1), V(1, -0.5f), V(0, -0.5f), V(0, 0.5f), V(1, 0.5f), V(1, 1), V(-1, 1))); List <DTPolygon> expected6 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0.5f, 1), V(0.5f, 0), V(-0.5f, 0), V(-0.5f, 1), V(-1, 1))); List <DTPolygon> expected7 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0.5f), V(0, 0.5f), V(0, -0.5f), V(-1, -0.5f))); // Diamond clip (produces 4 triangles) List <DTPolygon> expected8 = L( P(V(-1, -0.5f), V(-1, -1), V(-0.5f, -1)), P(V(0.5f, -1), V(1, -1), V(1, -0.5f)), P(V(1, 0.5f), V(1, 1), V(0.5f, 1)), P(V(-0.5f, 1), V(-1, 1), V(-1, 0.5f)) ); // Complete removal List <DTPolygon> empty = new List <DTPolygon>(); VerifyPolygons(sub.Subtract(square, clip0), expected0); VerifyPolygons(sub.Subtract(square, clip1), expected1); VerifyPolygons(sub.Subtract(square, clip2), expected2); VerifyPolygons(sub.Subtract(square, clip3), expected3); VerifyPolygons(sub.Subtract(square, clip4), expected4); VerifyPolygons(sub.Subtract(square, clip5), expected5); VerifyPolygons(sub.Subtract(square, clip6), expected6); VerifyPolygons(sub.Subtract(square, clip7), expected7); VerifyPolygons(sub.Subtract(square, clip8), expected8); // Complete removal VerifyPolygons(sub.Subtract(smallSquare, square), empty); }
public static void ConvexCasesProducingHoles(IPolygonSubtractor sub) { // Diamond hole in center DTPolygon clip0 = smallDiamond; // Diamond holes touching edge DTPolygon clip1 = Translate(smallDiamond, V(0, -0.5f)); // bottom DTPolygon clip2 = Translate(smallDiamond, V(0.5f, 0)); // right DTPolygon clip3 = Translate(smallDiamond, V(0, 0.5f)); // top DTPolygon clip4 = Translate(smallDiamond, V(-0.5f, 0)); // left // Exact diamond clip (produces 4 triangles) DTPolygon clip5 = diamond; // Diamond hole in center List <DTPolygon> expected0 = L(new DTPolygon( square.Contour, L(smallDiamond.Contour.AsEnumerable().Reverse().ToList()) )); // Diamond holes touching edge List <DTPolygon> expected1 = L(P(V(-1, -1), V(0, -1), V(-0.5f, -0.5f), V(0, 0), V(0.5f, -0.5f), V(0, -1), V(1, -1), V(1, 1), V(-1, 1))); List <DTPolygon> expected1Hole = L(new DTPolygon( square.Contour, L(clip1.Contour.AsEnumerable().Reverse().ToList()) )); List <DTPolygon> expected2 = L(P(V(-1, -1), V(1, -1), V(1, 0), V(0.5f, -0.5f), V(0, 0), V(0.5f, 0.5f), V(1, 0), V(1, 1), V(-1, 1))); List <DTPolygon> expected2Hole = L(new DTPolygon( square.Contour, L(clip2.Contour.AsEnumerable().Reverse().ToList()) )); List <DTPolygon> expected3 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 1), V(0.5f, 0.5f), V(0, 0), V(-0.5f, 0.5f), V(0, 1), V(-1, 1))); List <DTPolygon> expected3Hole = L(new DTPolygon( square.Contour, L(clip3.Contour.AsEnumerable().Reverse().ToList()) )); List <DTPolygon> expected4 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0), V(-0.5f, 0.5f), V(0, 0), V(-0.5f, -0.5f), V(-1, 0))); List <DTPolygon> expected4Hole = L(new DTPolygon( square.Contour, L(clip4.Contour.AsEnumerable().Reverse().ToList()) )); // Exact diamond clip (produces 4 triangles) List <DTPolygon> expected5 = L( P(V(-1, 0), V(-1, -1), V(0, -1)), P(V(0, -1), V(1, -1), V(1, 0)), P(V(1, 0), V(1, 1), V(0, 1)), P(V(0, 1), V(-1, 1), V(-1, 0)) ); List <DTPolygon> expected5Hole = L(new DTPolygon( square.Contour, L(clip5.Contour.AsEnumerable().Reverse().ToList()) )); List <DTPolygon> expected5Single0 = L(P(V(-1, -1), V(0, -1), V(-1, 0), V(0, 1), V(1, 0), V(0, -1), V(1, -1), V(1, 1), V(-1, 1))); List <DTPolygon> expected5Single1 = L(P(V(-1, -1), V(1, -1), V(1, 0), V(0, -1), V(-1, 0), V(0, 1), V(1, 0), V(1, 1), V(-1, 1))); List <DTPolygon> expected5Single2 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 1), V(1, 0), V(0, -1), V(-1, 0), V(0, 1), V(-1, 1))); List <DTPolygon> expected5Single3 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0), V(0, 1), V(1, 0), V(0, -1), V(-1, 0))); VerifyPolygons(sub.Subtract(square, clip0), expected0); VerifyPolygons(sub.Subtract(square, clip1), expected1, expected1Hole); VerifyPolygons(sub.Subtract(square, clip2), expected2, expected2Hole); VerifyPolygons(sub.Subtract(square, clip3), expected3, expected3Hole); VerifyPolygons(sub.Subtract(square, clip4), expected4, expected4Hole); VerifyPolygons(sub.Subtract(square, clip5), expected5, expected5Hole, expected5Single0, expected5Single1, expected5Single2, expected5Single3); }
public static void ConvexDegenerateNoIntersection(IPolygonSubtractor sub) { // Half-overlapping edges DTPolygon clip0 = Translate(diamond, V(0.5f, -1.5f)); // bottom right edge shared, Q shifted down-left DTPolygon clip1 = Translate(diamond, V(1.5f, -0.5f)); // bottom right edge shared, Q shifted up-right DTPolygon clip2 = Translate(diamond, V(1.5f, 0.5f)); // top right edge shared, Q shifted down-right DTPolygon clip3 = Translate(diamond, V(0.5f, 1.5f)); // top right edge shared, Q shifted up-left DTPolygon clip4 = Translate(diamond, V(-0.5f, 1.5f)); // top left edge shared, Q shifted up-right DTPolygon clip5 = Translate(diamond, V(-1.5f, 0.5f)); // top left edge shared, Q shifted down-left DTPolygon clip6 = Translate(diamond, V(-1.5f, -0.5f)); // bottom left edge shared, Q shifted up-left DTPolygon clip7 = Translate(diamond, V(-0.5f, -1.5f)); // bottom left edge shared, Q shifted down-right // P edge completely inside Q edge DTPolygon clip8 = Translate(diamond, V(0.75f, -0.75f)); // bottom right edge inside Q edge DTPolygon clip9 = Translate(diamond, V(0.75f, 0.75f)); // top right edge inside Q edge DTPolygon clip10 = Translate(diamond, V(-0.75f, 0.75f)); // top left edge inside Q edge DTPolygon clip11 = Translate(diamond, V(-0.75f, -0.75f)); // bottom left edge inside Q edge // P edge completely contains Q edge DTPolygon clip12 = Translate(smallDiamond, V(0.75f, -0.75f)); // bottom right edge contains Q edge DTPolygon clip13 = Translate(smallDiamond, V(0.75f, 0.75f)); // top right edge contains Q edge DTPolygon clip14 = Translate(smallDiamond, V(-0.75f, 0.75f)); // top left edge contains Q edge DTPolygon clip15 = Translate(smallDiamond, V(-0.75f, -0.75f)); // bottom left edge contains Q edge // P edge and Q edge are the same DTPolygon clip16 = Translate(diamond, V(1, -1)); // bottom right edge same DTPolygon clip17 = Translate(diamond, V(1, 1)); // top right edge same DTPolygon clip18 = Translate(diamond, V(-1, 1)); // top left edge same DTPolygon clip19 = Translate(diamond, V(-1, -1)); // bottom left edge same // Single shared vertex (octagon) DTPolygon clip20 = Translate(octagon, V(-2, -2)); // octagon, bottom left vertex same DTPolygon clip21 = Translate(octagon, V(2, -2)); // octagon, bottom right vertex same DTPolygon clip22 = Translate(octagon, V(2, 2)); // octagon, top left vertex same DTPolygon clip23 = Translate(octagon, V(-2, 2)); // octagon, top right vertex same // Single shared vertex (diamond) DTPolygon clip24 = Translate(diamond, V(-1, -2)); // diamond top, square bottom left vertex same DTPolygon clip25 = Translate(diamond, V(1, -2)); // diamond top, square bottom right vertex same DTPolygon clip26 = Translate(diamond, V(-1, 2)); // diamond bottom, square top left vertex same DTPolygon clip27 = Translate(diamond, V(1, 2)); // diamond bottom, square top right vertex same // Q single vertex inside P edge DTPolygon clip28 = Translate(square, V(1.5f, -1.5f)); // bottom right edge contains Q vertex DTPolygon clip29 = Translate(square, V(1.5f, 1.5f)); // top right edge contains Q vertex DTPolygon clip30 = Translate(square, V(-1.5f, 1.5f)); // top left edge contains Q vertex DTPolygon clip31 = Translate(square, V(-1.5f, -1.5f)); // bottom left edge contains Q vertex // P single vertex inside Q edge DTPolygon clip32 = Translate(diamond, V(-1.5f, -1.5f)); // bottom left vertex in Q edge DTPolygon clip33 = Translate(diamond, V(1.5f, -1.5f)); // bottom right vertex in Q edge DTPolygon clip34 = Translate(diamond, V(1.5f, 1.5f)); // top right vertex in Q edge DTPolygon clip35 = Translate(diamond, V(-1.5f, 1.5f)); // top left vertex in Q edge List <DTPolygon> expectedSquare = L(square); List <DTPolygon> expectedDiamond = L(diamond); List <DTPolygon> expectedSmallDiamond = L(smallDiamond); List <DTPolygon> expectedOctagon = L(octagon); VerifyPolygons(sub.Subtract(diamond, clip0), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip1), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip2), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip3), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip4), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip5), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip6), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip7), expectedDiamond); VerifyPolygons(sub.Subtract(smallDiamond, clip8), expectedSmallDiamond); VerifyPolygons(sub.Subtract(smallDiamond, clip9), expectedSmallDiamond); VerifyPolygons(sub.Subtract(smallDiamond, clip10), expectedSmallDiamond); VerifyPolygons(sub.Subtract(smallDiamond, clip11), expectedSmallDiamond); VerifyPolygons(sub.Subtract(diamond, clip12), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip13), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip14), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip15), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip16), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip17), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip18), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip19), expectedDiamond); VerifyPolygons(sub.Subtract(octagon, clip20), expectedOctagon); VerifyPolygons(sub.Subtract(octagon, clip21), expectedOctagon); VerifyPolygons(sub.Subtract(octagon, clip22), expectedOctagon); VerifyPolygons(sub.Subtract(octagon, clip23), expectedOctagon); VerifyPolygons(sub.Subtract(octagon, clip24), expectedOctagon); VerifyPolygons(sub.Subtract(octagon, clip25), expectedOctagon); VerifyPolygons(sub.Subtract(octagon, clip26), expectedOctagon); VerifyPolygons(sub.Subtract(octagon, clip27), expectedOctagon); VerifyPolygons(sub.Subtract(diamond, clip28), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip29), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip30), expectedDiamond); VerifyPolygons(sub.Subtract(diamond, clip31), expectedDiamond); VerifyPolygons(sub.Subtract(octagon, clip32), expectedOctagon); VerifyPolygons(sub.Subtract(octagon, clip33), expectedOctagon); VerifyPolygons(sub.Subtract(octagon, clip34), expectedOctagon); VerifyPolygons(sub.Subtract(octagon, clip35), expectedOctagon); }
public static void ConvexDegenerateIntersection(IPolygonSubtractor sub) { // Shared corners (produces an 'L' shape) DTPolygon clip0 = Translate(smallSquare, V(-0.5f, -0.5f)); // bottom left DTPolygon clip1 = Translate(smallSquare, V(0.5f, -0.5f)); // bottom right DTPolygon clip2 = Translate(smallSquare, V(0.5f, 0.5f)); // top right DTPolygon clip3 = Translate(smallSquare, V(-0.5f, 0.5f)); // top left // Q edge inside P edge (produces a 'C' shape) DTPolygon clip4 = Translate(smallSquare, V(0, -0.5f)); // bottom DTPolygon clip5 = Translate(smallSquare, V(0.5f, 0)); // right DTPolygon clip6 = Translate(smallSquare, V(0, 0.5f)); // top DTPolygon clip7 = Translate(smallSquare, V(-0.5f, 0)); // left // Half same DTPolygon clip8 = Translate(shortRect, V(0, -0.5f)); // bottom half DTPolygon clip9 = Translate(narrowRect, V(0.5f, 0)); // right half DTPolygon clip10 = Translate(shortRect, V(0, 0.5f)); // top half DTPolygon clip11 = Translate(narrowRect, V(-0.5f, 0)); // left half // Diamond on corners DTPolygon clip12 = Translate(diamond, V(-1, -1)); // bottom left DTPolygon clip13 = Translate(diamond, V(1, -1)); // bottom right DTPolygon clip14 = Translate(diamond, V(1, 1)); // top right DTPolygon clip15 = Translate(diamond, V(-1, 1)); // top left // Diamond on edges DTPolygon clip16 = Translate(diamond, V(0, -1)); // bottom DTPolygon clip17 = Translate(diamond, V(1, 0)); // right DTPolygon clip18 = Translate(diamond, V(0, 1)); // top DTPolygon clip19 = Translate(diamond, V(-1, 0)); // left // Basic corner clips (produces an 'L' shape) List <DTPolygon> expected0 = L(P(V(0, 0), V(0, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0))); List <DTPolygon> expected1 = L(P(V(-1, -1), V(0, -1), V(0, 0), V(1, 0), V(1, 1), V(-1, 1))); List <DTPolygon> expected2 = L(P(V(-1, -1), V(1, -1), V(1, 0), V(0, 0), V(0, 1), V(-1, 1))); List <DTPolygon> expected3 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 1), V(0, 0), V(-1, 0))); // Basic edge clips (produces a 'C' shape) List <DTPolygon> expected4 = L(P(V(-1, -1), V(-0.5f, -1), V(-0.5f, 0), V(0.5f, 0), V(0.5f, -1), V(1, -1), V(1, 1), V(-1, 1))); List <DTPolygon> expected5 = L(P(V(-1, -1), V(1, -1), V(1, -0.5f), V(0, -0.5f), V(0, 0.5f), V(1, 0.5f), V(1, 1), V(-1, 1))); List <DTPolygon> expected6 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0.5f, 1), V(0.5f, 0), V(-0.5f, 0), V(-0.5f, 1), V(-1, 1))); List <DTPolygon> expected7 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0.5f), V(0, 0.5f), V(0, -0.5f), V(-1, -0.5f))); // Half same List <DTPolygon> expected8 = L(P(V(-1, 0), V(1, 0), V(1, 1), V(-1, 1))); List <DTPolygon> expected9 = L(P(V(-1, -1), V(0, -1), V(0, 1), V(-1, 1))); List <DTPolygon> expected10 = L(P(V(-1, -1), V(1, -1), V(1, 0), V(-1, 0))); List <DTPolygon> expected11 = L(P(V(0, -1), V(1, -1), V(1, 1), V(0, 1))); // Diamond on corners List <DTPolygon> expected12 = L(P(V(0, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0))); List <DTPolygon> expected13 = L(P(V(-1, -1), V(0, -1), V(1, 0), V(1, 1), V(-1, 1))); List <DTPolygon> expected14 = L(P(V(-1, -1), V(1, -1), V(1, 0), V(0, 1), V(-1, 1))); List <DTPolygon> expected15 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 1), V(-1, 0))); // Diamond on edges List <DTPolygon> expected16 = L(P(V(-1, -1), V(0, 0), V(1, -1), V(1, 1), V(-1, 1))); List <DTPolygon> expected17 = L(P(V(-1, -1), V(1, -1), V(0, 0), V(1, 1), V(-1, 1))); List <DTPolygon> expected18 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 0), V(-1, 1))); List <DTPolygon> expected19 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(-1, 1), V(0, 0))); // Complete removal List <DTPolygon> empty = new List <DTPolygon>(); // Complete removal VerifyPolygons(sub.Subtract(square, square), empty); VerifyPolygons(sub.Subtract(square, clip0), expected0); VerifyPolygons(sub.Subtract(square, clip1), expected1); VerifyPolygons(sub.Subtract(square, clip2), expected2); VerifyPolygons(sub.Subtract(square, clip3), expected3); VerifyPolygons(sub.Subtract(square, clip4), expected4); VerifyPolygons(sub.Subtract(square, clip5), expected5); VerifyPolygons(sub.Subtract(square, clip6), expected6); VerifyPolygons(sub.Subtract(square, clip7), expected7); VerifyPolygons(sub.Subtract(square, clip8), expected8); VerifyPolygons(sub.Subtract(square, clip9), expected9); VerifyPolygons(sub.Subtract(square, clip10), expected10); VerifyPolygons(sub.Subtract(square, clip11), expected11); VerifyPolygons(sub.Subtract(square, clip12), expected12); VerifyPolygons(sub.Subtract(square, clip13), expected13); VerifyPolygons(sub.Subtract(square, clip14), expected14); VerifyPolygons(sub.Subtract(square, clip15), expected15); VerifyPolygons(sub.Subtract(square, clip16), expected16); VerifyPolygons(sub.Subtract(square, clip17), expected17); VerifyPolygons(sub.Subtract(square, clip18), expected18); VerifyPolygons(sub.Subtract(square, clip19), expected19); }