/Graphics/TreapOfSegments.cs

https://bitbucket.org/kriskk/graphics · C# · 296 lines · 255 code · 19 blank · 22 comment · 60 complexity · 7df9d6b694a1b81ea93b59ca0c484d66 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using NUnit.Framework;
  5. namespace PolygonIntersections
  6. {
  7. public static class TreapOfSegments
  8. {
  9. #region OrderedInfoMethods // this methods Contract that tree is orderd like binary
  10. public static Segment Max(this ImplicitTreap<Segment> treap)
  11. {
  12. if (treap == null) return null;
  13. return treap.DigRight().Info;
  14. }
  15. public static Segment Min(this ImplicitTreap<Segment> treap)
  16. {
  17. if (treap == null) return null;
  18. return treap.DigLeft().Info;
  19. }
  20. public static ImplicitTreap<Segment> FindW(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
  21. {
  22. var compared = comp.Compare(treap.Info, item);
  23. if (compared < 0)
  24. {
  25. if (treap.Right == null) return null;
  26. return treap.Right.FindW(item, comp);
  27. }
  28. if (compared > 0)
  29. {
  30. if (treap.Left == null) return null;
  31. return treap.Left.FindW(item, comp);
  32. }
  33. // (compared == 0)
  34. if (Equals(treap.Info, item)) return treap;
  35. ImplicitTreap<Segment> check = null;
  36. if (treap.Left != null)
  37. {
  38. check = treap.Left.FindW(item, comp);
  39. if (check != null) return check;
  40. }
  41. if (treap.Right != null)
  42. {
  43. check = treap.Right.FindW(item, comp);
  44. if (check != null) return check;
  45. }
  46. return null;
  47. }
  48. public static int? Find(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
  49. {
  50. if (treap == null) return null;
  51. var compared = comp.Compare(treap.Info, item);
  52. if (compared < 0)
  53. {
  54. return treap.Right.Find(item, comp) + treap.RightPos;
  55. }
  56. if (compared > 0)
  57. {
  58. return treap.Left.Find(item, comp);
  59. }
  60. // (compared == 0)
  61. if (Equals(treap.Info, item)) return treap.CurrentPos;
  62. int? check = null;
  63. return treap.Left.Find(item, comp) ?? treap.Right.Find(item, comp) + treap.RightPos;
  64. }
  65. public static int FindNotNull(this ImplicitTreap<Segment> treap, Segment item, SegmentComparerNotNull comp)
  66. {
  67. if (treap == null) return 0;
  68. var compared = comp.Compare(treap.Info, item);
  69. if (compared < 0)
  70. {
  71. return treap.Right.FindNotNull(item, comp) + treap.RightPos;
  72. }
  73. if (compared > 0)
  74. {
  75. return treap.Left.FindNotNull(item, comp);
  76. }
  77. // (compared == 0)
  78. if (Equals(treap.Info, item)) return treap.CurrentPos;
  79. int? check = null;
  80. if (treap.Left != null && comp.Compare(treap.Left.Max(), item) == 0)
  81. return treap.Left.FindNotNull(item, comp);
  82. return treap.Right.FindNotNull(item, comp) + treap.RightPos;
  83. }
  84. // public static int? Find(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
  85. // {
  86. // int i = 0;
  87. // foreach (var segment in treap.GetAllInfos())
  88. // {
  89. // if (segment.Equals( item)) return i;
  90. // i++;
  91. // }
  92. // return null;
  93. // }
  94. public static int? FindSimilar(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
  95. {
  96. var compared = comp.Compare(treap.Info, item);
  97. if (compared < 0)
  98. {
  99. if (treap.Right == null) return null;
  100. return treap.Right.FindSimilar(item, comp) + treap.RightPos;
  101. }
  102. if (compared > 0)
  103. {
  104. if (treap.Left == null) return null;
  105. return treap.Left.FindSimilar(item, comp);
  106. }
  107. // (compared == 0)
  108. return treap.CurrentPos;
  109. }
  110. /// <summary>
  111. /// Info that is above equivalent to item infos
  112. /// </summary>
  113. public static int? GetCeilPos(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
  114. {
  115. var fCeil = GetCeilPosQ(treap, item, comp);
  116. return fCeil >= treap.Size ? null : fCeil;
  117. }
  118. private static int? GetCeilPosQ(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
  119. {
  120. if (treap == null) return null;
  121. var compared = comp.Compare(treap.Info, item);
  122. if (compared < 0) // go to Right
  123. {
  124. return treap.Right.GetCeilPosQ(item, comp) + treap.RightPos;
  125. }
  126. if (compared > 0) // go to Left
  127. {
  128. return treap.Left.GetCeilPosQ(item, comp);
  129. }
  130. // (compared == 0)
  131. return (treap.Right.GetCeilPosQ(item, comp) ?? 0) + treap.RightPos;
  132. }
  133. /// <summary>
  134. /// Least Info that is equivalent to item
  135. /// </summary>
  136. private static int? GetFloorP(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
  137. {
  138. if (treap == null) return 0;
  139. var compared = comp.Compare(treap.Info, item);
  140. if (compared < 0) // go to Right
  141. {
  142. return treap.Right.GetFloorP(item, comp) + treap.RightPos;
  143. }
  144. if (compared > 0) // go to Left
  145. {
  146. return treap.Left.GetFloorP(item, comp);
  147. }
  148. // (compared == 0)
  149. if (treap.Left != null && comp.Compare(treap.Left.Max(), item) == 0)
  150. return treap.Left.GetFloorP(item, comp);
  151. return treap.CurrentPos;
  152. }
  153. public static int GetFloorPos(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
  154. {
  155. return treap.GetFloorP(item, comp) ?? 0;
  156. }
  157. public static ImplicitTreap<Segment> Remove(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
  158. {
  159. var pos = treap.Find(item, comp);
  160. if (!pos.HasValue) return treap;
  161. return treap.Remove(pos.Value);
  162. }
  163. public static ImplicitTreap<Segment> Swap(this ImplicitTreap<Segment> treap, Segment s1, Segment s2, SegmentComparer comp)
  164. {
  165. var t1 = treap.FindW(s1, comp);
  166. var t2 = treap.FindW(s2, comp);
  167. if (t1 == null) return treap;
  168. if (t2 == null) return treap;
  169. var temp1 = new Segment(t1.Info);
  170. var temp2 = new Segment(t2.Info);
  171. t2.Info = temp1;
  172. t2.Info = temp1;
  173. t1.Info = temp2;
  174. return treap;
  175. }
  176. public static ImplicitTreap<Segment> CreateOrderedTreapFromRange(Segment[] segments, SegmentComparer comp)
  177. {
  178. var t = new ImplicitTreap<Segment>(segments[0]);
  179. var ans = t;
  180. foreach (Segment segment in segments.Skip(1))
  181. {
  182. var qt = TreapOfSegmentsTester.GetAllI(ans);
  183. var pos = ans.GetFloorPos(segment, comp);
  184. ans = ans.Add(pos, segment);
  185. ans.Recalc();
  186. qt = TreapOfSegmentsTester.GetAllI(ans);
  187. }
  188. ans.Recalc();
  189. return ans;
  190. }
  191. #endregion
  192. }
  193. [TestFixture]
  194. internal class TreapOfSegmentsTester
  195. {
  196. public static Segment[] SegsNear = new Segment[]
  197. {
  198. new Segment(0,0,6,6),
  199. new Segment(0,1,6,1),
  200. new Segment(0,2,6,4),
  201. new Segment(0,3,6,3),
  202. new Segment(0,4,6,2),
  203. new Segment(0,5,6,5),
  204. new Segment(0,6,6,0),
  205. };
  206. public static Dictionary<Segment, int> Mapper = SegsNear.ToDictionary(q => q, q => (int)q.Start.Y);
  207. public SegmentComparer Comparer = new SegmentComparer();
  208. public static object[][] NearsOrder =
  209. {
  210. new object[]
  211. {
  212. 0.5,
  213. new []{0,1,2,3,4,5,6},
  214. new []{0,1,2,3,4,5,6},
  215. new int?[]{1,2,3,4,5,6,null}
  216. },
  217. new object[]
  218. {
  219. 2,
  220. new[]{1,0,2,3,4,6,5},
  221. new[]{0,1,2,3,4,5,6},
  222. new int?[]{2,0,3,4,6,null,5}
  223. },
  224. new object[]
  225. {
  226. 1,
  227. new[]{1,0,2,3,4,6,5},
  228. new[]{1,1,2,3,4,6,6},
  229. new int?[]{2,2,3,4,6,null, null}
  230. },
  231. new object[] // awfull and not working // praying for it not to be in algorithm
  232. {
  233. 3,
  234. new[]{1,6,4,3,2,0,5},
  235. new[]{0,1,0,0,0,5,0},
  236. new int?[]{5,0,5,5,5,null,5}
  237. },
  238. };
  239. [Test]
  240. [TestCaseSource("NearsOrder")]
  241. public void NearsTest(double x, int[] finds, int[] floors, int?[] ceils)
  242. {
  243. Comparer.X = x;
  244. var t = TreapOfSegments.CreateOrderedTreapFromRange(SegsNear, Comparer);
  245. Console.Out.WriteLine(t.ToString(Mapper));
  246. Console.Out.WriteLine(GetAllI(t));
  247. for (int i = 0; i < SegsNear.Length; i++)
  248. {
  249. var segment = SegsNear[i];
  250. var foundPos = t.Find(segment, Comparer);
  251. var floorPos = t.GetFloorPos(segment, Comparer);
  252. var ceilPos = t.GetCeilPos(segment, Comparer);
  253. Console.Out.WriteLine(String.Join(" ", foundPos, t[floorPos].Start.Y, ceilPos.HasValue?t[ceilPos.Value].Start.Y:-1));
  254. Assert.That(foundPos.HasValue);
  255. Assert.That(foundPos.Value, Is.EqualTo(finds[i]));
  256. Assert.That(t[floorPos].Start.Y, Is.EqualTo(floors[i]));
  257. if (ceilPos == null)
  258. Assert.That(ceils[i] == null);
  259. else
  260. Assert.That(t[ceilPos.Value].Start.Y, Is.EqualTo(ceils[i]));
  261. }
  262. }
  263. [Test]
  264. public void SwapTest()
  265. {
  266. Comparer.X = 0.5;
  267. var t = TreapOfSegments.CreateOrderedTreapFromRange(SegsNear, Comparer);
  268. Console.Out.WriteLine(GetAllI(t));
  269. t.Swap(SegsNear[3], SegsNear[1], Comparer);
  270. Console.Out.WriteLine(GetAllI(t));
  271. }
  272. public static string GetAllI(ImplicitTreap<Segment> t)
  273. {
  274. return String.Join(" ",t.GetAllInfos().Select(i => i.Start.Y));
  275. }
  276. }
  277. }