MergeRectanglesTests.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. namespace Terminal.Gui.DrawingTests;
  2. public class MergeRectanglesTests
  3. {
  4. [Fact]
  5. public void MergeRectangles_ComplexAdjacentRectangles_NoOverlap ()
  6. {
  7. /*
  8. INPUT: Complex arrangement of four adjacent rectangles forming a hollow square ring.
  9. Top-left origin (0,0), x→, y↓:
  10. x=0 1 2 3 4
  11. y=0 A A A
  12. y=1 B C
  13. y=2 B C
  14. y=3 B C
  15. y=4 D D D
  16. Rectangles (width × height):
  17. A: (1,0,3,1) // top edge
  18. B: (0,1,1,3) // left edge
  19. C: (4,1,1,3) // right edge
  20. D: (1,4,3,1) // bottom edge
  21. They only touch corners or edges, with no overlapping areas.
  22. The expected result is exactly these four rectangles, unmerged.
  23. */
  24. List<Rectangle> rectangles = new ()
  25. {
  26. new (1, 0, 3, 1), // A
  27. new (0, 1, 1, 3), // B
  28. new (4, 1, 1, 3), // C
  29. new (1, 4, 3, 1) // D
  30. };
  31. List<Rectangle> merged = Region.MergeRectangles (rectangles, false);
  32. // Because there's no overlapping area, the method shouldn't merge any of them.
  33. Assert.Equal (4, merged.Count);
  34. Assert.Contains (new (1, 0, 3, 1), merged);
  35. Assert.Contains (new (0, 1, 1, 3), merged);
  36. Assert.Contains (new (4, 1, 1, 3), merged);
  37. Assert.Contains (new (1, 4, 3, 1), merged);
  38. }
  39. [Fact]
  40. public void MergeRectangles_ComplexContainedRectangles_AllMergeIntoBoundingRect ()
  41. {
  42. /*
  43. INPUT: (top-left origin, x→, y↓):
  44. x=0 1 2 3 4 5
  45. y=0 A A A A A A
  46. y=1 A . . . . A
  47. y=2 A . B B . A
  48. y=3 A . B B . A
  49. y=4 A . . . C C
  50. y=5 A A A A C C
  51. Where:
  52. A = (0,0,6,6) // Large bounding rectangle
  53. B = (2,2,2,2) // Fully contained inside A
  54. C = (4,4,2,2) // Also fully contained inside A
  55. */
  56. List<Rectangle> rectangles = new ()
  57. {
  58. new (0, 0, 6, 6), // A
  59. new (2, 2, 2, 2), // B inside A
  60. new (4, 4, 2, 2) // C inside A
  61. };
  62. List<Rectangle> merged = Region.MergeRectangles (rectangles, minimize: false);
  63. /*
  64. OUTPUT: The expected result should be a minimal set of non-overlapping rectangles
  65. that cover the same area as the input rectangles.
  66. x=0 1 2 3 4 5
  67. y=0 a a b b c c
  68. y=1 a a b b c c
  69. y=2 a a b b c c
  70. y=3 a a b b c c
  71. y=4 a a b b c c
  72. y=5 a a b b c c
  73. */
  74. Assert.Equal (3, merged.Count);
  75. Assert.Contains (new (0, 0, 2, 6), merged); // a
  76. Assert.Contains (new (2, 0, 2, 6), merged); // b
  77. Assert.Contains (new (4, 0, 2, 6), merged); // c
  78. }
  79. [Fact]
  80. public void MergeRectangles_ComplexOverlap_ReturnsMergedRectangles ()
  81. {
  82. /*
  83. INPUT: Visual diagram treating (0,0) as top-left, x increasing to the right, y increasing downward:
  84. x=0 1 2 3 4 5 6 ...
  85. y=0 A A
  86. y=1 A B B
  87. y=2 B B
  88. y=3 C C
  89. y=4 C D D
  90. y=5 D D
  91. A overlaps B slightly; C overlaps D slightly. The union of A & B forms one rectangle,
  92. and the union of C & D forms another.
  93. */
  94. List<Rectangle> rectangles = new ()
  95. {
  96. // A
  97. new (0, 0, 2, 2),
  98. // B
  99. new (1, 1, 2, 2),
  100. // C
  101. new (3, 3, 2, 2),
  102. // D
  103. new (4, 4, 2, 2)
  104. };
  105. List<Rectangle> merged = Region.MergeRectangles (rectangles, false);
  106. /*
  107. OUTPUT: Merged fragments (top-left origin, x→, y↓).
  108. Lowercase letters a..f show the six sub-rectangles:
  109. x=0 1 2 3 4 5
  110. y=0 a b
  111. y=1 a b c
  112. y=2 b c
  113. y=3 d e
  114. y=4 d e f
  115. y=5 e f
  116. */
  117. Assert.Equal (6, merged.Count);
  118. Assert.Contains (new (0, 0, 1, 2), merged); // a
  119. Assert.Contains (new (1, 0, 1, 3), merged); // b
  120. Assert.Contains (new (2, 1, 1, 2), merged); // c
  121. Assert.Contains (new (3, 3, 1, 2), merged); // d
  122. Assert.Contains (new (4, 3, 1, 3), merged); // e
  123. Assert.Contains (new (5, 4, 1, 2), merged); // f
  124. }
  125. [Fact]
  126. public void MergeRectangles_NoOverlap_ReturnsSameRectangles ()
  127. {
  128. List<Rectangle> rectangles = new ()
  129. {
  130. new (0, 0, 10, 10),
  131. new (20, 20, 10, 10),
  132. new (40, 40, 10, 10)
  133. };
  134. List<Rectangle> result = Region.MergeRectangles (rectangles, false);
  135. Assert.Equal (3, result.Count);
  136. Assert.Contains (new (0, 0, 10, 10), result);
  137. Assert.Contains (new (20, 20, 10, 10), result);
  138. Assert.Contains (new (40, 40, 10, 10), result);
  139. }
  140. [Fact]
  141. public void MergeRectangles_EmptyRectangles_ReturnsEmptyList ()
  142. {
  143. // Arrange: Create list of empty rectangles
  144. var emptyRectangles = new List<Rectangle> { new (0, 0, 0, 0), new (0, 0, 0, 0) };
  145. // Act: Call MergeRectangles with granular output
  146. var result = Region.MergeRectangles (emptyRectangles, minimize: false);
  147. // Assert: Result is empty
  148. Assert.Empty (result);
  149. }
  150. }