DisjointRectSet.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/Vector.h>
  9. #include <LibGfx/Point.h>
  10. #include <LibGfx/Rect.h>
  11. namespace Gfx {
  12. template<typename T>
  13. class DisjointRectSet {
  14. public:
  15. DisjointRectSet(DisjointRectSet const&) = delete;
  16. DisjointRectSet& operator=(DisjointRectSet const&) = delete;
  17. DisjointRectSet() = default;
  18. ~DisjointRectSet() = default;
  19. DisjointRectSet(Rect<T> const& rect)
  20. {
  21. m_rects.append(rect);
  22. }
  23. DisjointRectSet(DisjointRectSet&&) = default;
  24. DisjointRectSet& operator=(DisjointRectSet&&) = default;
  25. DisjointRectSet clone() const
  26. {
  27. DisjointRectSet rects;
  28. rects.m_rects = m_rects;
  29. return rects;
  30. }
  31. void move_by(T dx, T dy)
  32. {
  33. for (auto& r : m_rects)
  34. r.translate_by(dx, dy);
  35. }
  36. void move_by(Point<T> const& delta)
  37. {
  38. move_by(delta.x(), delta.y());
  39. }
  40. void add(Rect<T> const& rect)
  41. {
  42. if (add_no_shatter(rect) && m_rects.size() > 1)
  43. shatter();
  44. }
  45. template<typename Container>
  46. void add_many(Container const& rects)
  47. {
  48. bool added = false;
  49. for (auto const& rect : rects) {
  50. if (add_no_shatter(rect))
  51. added = true;
  52. }
  53. if (added && m_rects.size() > 1)
  54. shatter();
  55. }
  56. void add(DisjointRectSet const& rect_set)
  57. {
  58. if (this == &rect_set)
  59. return;
  60. if (m_rects.is_empty()) {
  61. m_rects = rect_set.m_rects;
  62. } else {
  63. add_many(rect_set.rects());
  64. }
  65. }
  66. DisjointRectSet shatter(Rect<T> const& hammer) const
  67. {
  68. if (hammer.is_empty())
  69. return clone();
  70. DisjointRectSet shards;
  71. for (auto& rect : m_rects) {
  72. for (auto& shard : rect.shatter(hammer))
  73. shards.add_no_shatter(shard);
  74. }
  75. // Since there should be no overlaps, we don't need to call shatter()
  76. return shards;
  77. }
  78. DisjointRectSet shatter(DisjointRectSet const& hammer) const
  79. {
  80. if (this == &hammer)
  81. return {};
  82. if (hammer.is_empty() || !intersects(hammer))
  83. return clone();
  84. // TODO: This could use some optimization
  85. DisjointRectSet shards = shatter(hammer.m_rects[0]);
  86. auto rects_count = hammer.m_rects.size();
  87. for (size_t i = 1; i < rects_count && !shards.is_empty(); i++) {
  88. if (hammer.m_rects[i].intersects(shards.m_rects)) {
  89. auto shattered = shards.shatter(hammer.m_rects[i]);
  90. shards = move(shattered);
  91. }
  92. }
  93. // Since there should be no overlaps, we don't need to call shatter()
  94. return shards;
  95. }
  96. bool contains(Rect<T> const& rect) const
  97. {
  98. if (is_empty() || rect.is_empty())
  99. return false;
  100. // TODO: This could use some optimization
  101. DisjointRectSet remainder(rect);
  102. for (auto& r : m_rects) {
  103. auto shards = remainder.shatter(r);
  104. if (shards.is_empty())
  105. return true;
  106. remainder = move(shards);
  107. }
  108. return false;
  109. }
  110. bool intersects(Rect<T> const& rect) const
  111. {
  112. for (auto& r : m_rects) {
  113. if (r.intersects(rect))
  114. return true;
  115. }
  116. return false;
  117. }
  118. bool intersects(DisjointRectSet const& rects) const
  119. {
  120. if (this == &rects)
  121. return true;
  122. for (auto& r : m_rects) {
  123. for (auto& r2 : rects.m_rects) {
  124. if (r.intersects(r2))
  125. return true;
  126. }
  127. }
  128. return false;
  129. }
  130. DisjointRectSet intersected(Rect<T> const& rect) const
  131. {
  132. DisjointRectSet intersected_rects;
  133. intersected_rects.m_rects.ensure_capacity(m_rects.capacity());
  134. for (auto& r : m_rects) {
  135. auto intersected_rect = r.intersected(rect);
  136. if (!intersected_rect.is_empty())
  137. intersected_rects.m_rects.append(intersected_rect);
  138. }
  139. // Since there should be no overlaps, we don't need to call shatter()
  140. return intersected_rects;
  141. }
  142. DisjointRectSet intersected(DisjointRectSet const& rects) const
  143. {
  144. if (&rects == this)
  145. return clone();
  146. if (is_empty() || rects.is_empty())
  147. return {};
  148. DisjointRectSet intersected_rects;
  149. intersected_rects.m_rects.ensure_capacity(m_rects.capacity());
  150. for (auto& r : m_rects) {
  151. for (auto& r2 : rects.m_rects) {
  152. auto intersected_rect = r.intersected(r2);
  153. if (!intersected_rect.is_empty())
  154. intersected_rects.m_rects.append(intersected_rect);
  155. }
  156. }
  157. // Since there should be no overlaps, we don't need to call shatter()
  158. return intersected_rects;
  159. }
  160. template<typename Function>
  161. IterationDecision for_each_intersected(Rect<T> const& rect, Function f) const
  162. {
  163. if (is_empty() || rect.is_empty())
  164. return IterationDecision::Continue;
  165. for (auto& r : m_rects) {
  166. auto intersected_rect = r.intersected(rect);
  167. if (intersected_rect.is_empty())
  168. continue;
  169. IterationDecision decision = f(intersected_rect);
  170. if (decision != IterationDecision::Continue)
  171. return decision;
  172. }
  173. return IterationDecision::Continue;
  174. }
  175. template<typename Function>
  176. IterationDecision for_each_intersected(DisjointRectSet const& rects, Function f) const
  177. {
  178. if (is_empty() || rects.is_empty())
  179. return IterationDecision::Continue;
  180. if (this == &rects) {
  181. for (auto& r : m_rects) {
  182. IterationDecision decision = f(r);
  183. if (decision != IterationDecision::Continue)
  184. return decision;
  185. }
  186. } else {
  187. for (auto& r : m_rects) {
  188. for (auto& r2 : rects.m_rects) {
  189. auto intersected_rect = r.intersected(r2);
  190. if (intersected_rect.is_empty())
  191. continue;
  192. IterationDecision decision = f(intersected_rect);
  193. if (decision != IterationDecision::Continue)
  194. return decision;
  195. }
  196. }
  197. }
  198. return IterationDecision::Continue;
  199. }
  200. bool is_empty() const { return m_rects.is_empty(); }
  201. size_t size() const { return m_rects.size(); }
  202. void clear() { m_rects.clear(); }
  203. void clear_with_capacity() { m_rects.clear_with_capacity(); }
  204. Vector<Rect<T>, 32> const& rects() const { return m_rects; }
  205. Vector<Rect<T>, 32> take_rects() { return move(m_rects); }
  206. void translate_by(T dx, T dy)
  207. {
  208. for (auto& rect : m_rects)
  209. rect.translate_by(dx, dy);
  210. }
  211. void translate_by(Point<T> const& delta)
  212. {
  213. for (auto& rect : m_rects)
  214. rect.translate_by(delta);
  215. }
  216. private:
  217. bool add_no_shatter(Rect<T> const& new_rect)
  218. {
  219. if (new_rect.is_empty())
  220. return false;
  221. for (auto& rect : m_rects) {
  222. if (rect.contains(new_rect))
  223. return false;
  224. }
  225. m_rects.append(new_rect);
  226. return true;
  227. }
  228. void shatter()
  229. {
  230. Vector<Rect<T>, 32> output;
  231. output.ensure_capacity(m_rects.size());
  232. bool pass_had_intersections = false;
  233. do {
  234. pass_had_intersections = false;
  235. output.clear_with_capacity();
  236. for (size_t i = 0; i < m_rects.size(); ++i) {
  237. auto& r1 = m_rects[i];
  238. for (size_t j = 0; j < m_rects.size(); ++j) {
  239. if (i == j)
  240. continue;
  241. auto& r2 = m_rects[j];
  242. if (!r1.intersects(r2))
  243. continue;
  244. pass_had_intersections = true;
  245. auto pieces = r1.shatter(r2);
  246. for (auto& piece : pieces)
  247. output.append(piece);
  248. m_rects.remove(i);
  249. for (; i < m_rects.size(); ++i)
  250. output.append(m_rects[i]);
  251. goto next_pass;
  252. }
  253. output.append(r1);
  254. }
  255. next_pass:
  256. swap(output, m_rects);
  257. } while (pass_had_intersections);
  258. }
  259. Vector<Rect<T>, 32> m_rects;
  260. };
  261. }