/Graphics/TreapOfSegments.cs
https://bitbucket.org/kriskk/graphics · C# · 296 lines · 255 code · 19 blank · 22 comment · 60 complexity · 7df9d6b694a1b81ea93b59ca0c484d66 MD5 · raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using NUnit.Framework;
-
- namespace PolygonIntersections
- {
- public static class TreapOfSegments
- {
- #region OrderedInfoMethods // this methods Contract that tree is orderd like binary
- public static Segment Max(this ImplicitTreap<Segment> treap)
- {
- if (treap == null) return null;
- return treap.DigRight().Info;
- }
- public static Segment Min(this ImplicitTreap<Segment> treap)
- {
- if (treap == null) return null;
- return treap.DigLeft().Info;
- }
-
- public static ImplicitTreap<Segment> FindW(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
- {
- var compared = comp.Compare(treap.Info, item);
- if (compared < 0)
- {
- if (treap.Right == null) return null;
- return treap.Right.FindW(item, comp);
- }
- if (compared > 0)
- {
- if (treap.Left == null) return null;
- return treap.Left.FindW(item, comp);
- }
- // (compared == 0)
- if (Equals(treap.Info, item)) return treap;
- ImplicitTreap<Segment> check = null;
- if (treap.Left != null)
- {
- check = treap.Left.FindW(item, comp);
- if (check != null) return check;
- }
- if (treap.Right != null)
- {
- check = treap.Right.FindW(item, comp);
- if (check != null) return check;
- }
- return null;
- }
-
- public static int? Find(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
- {
- if (treap == null) return null;
- var compared = comp.Compare(treap.Info, item);
- if (compared < 0)
- {
- return treap.Right.Find(item, comp) + treap.RightPos;
- }
- if (compared > 0)
- {
- return treap.Left.Find(item, comp);
- }
- // (compared == 0)
- if (Equals(treap.Info, item)) return treap.CurrentPos;
- int? check = null;
- return treap.Left.Find(item, comp) ?? treap.Right.Find(item, comp) + treap.RightPos;
- }
- public static int FindNotNull(this ImplicitTreap<Segment> treap, Segment item, SegmentComparerNotNull comp)
- {
- if (treap == null) return 0;
- var compared = comp.Compare(treap.Info, item);
- if (compared < 0)
- {
- return treap.Right.FindNotNull(item, comp) + treap.RightPos;
- }
- if (compared > 0)
- {
- return treap.Left.FindNotNull(item, comp);
- }
- // (compared == 0)
- if (Equals(treap.Info, item)) return treap.CurrentPos;
- int? check = null;
- if (treap.Left != null && comp.Compare(treap.Left.Max(), item) == 0)
- return treap.Left.FindNotNull(item, comp);
- return treap.Right.FindNotNull(item, comp) + treap.RightPos;
- }
-
- // public static int? Find(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
- // {
- // int i = 0;
- // foreach (var segment in treap.GetAllInfos())
- // {
- // if (segment.Equals( item)) return i;
- // i++;
- // }
- // return null;
- // }
- public static int? FindSimilar(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
- {
- var compared = comp.Compare(treap.Info, item);
- if (compared < 0)
- {
- if (treap.Right == null) return null;
- return treap.Right.FindSimilar(item, comp) + treap.RightPos;
- }
- if (compared > 0)
- {
- if (treap.Left == null) return null;
- return treap.Left.FindSimilar(item, comp);
- }
- // (compared == 0)
- return treap.CurrentPos;
- }
-
- /// <summary>
- /// Info that is above equivalent to item infos
- /// </summary>
- public static int? GetCeilPos(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
- {
- var fCeil = GetCeilPosQ(treap, item, comp);
- return fCeil >= treap.Size ? null : fCeil;
- }
- private static int? GetCeilPosQ(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
- {
- if (treap == null) return null;
- var compared = comp.Compare(treap.Info, item);
- if (compared < 0) // go to Right
- {
- return treap.Right.GetCeilPosQ(item, comp) + treap.RightPos;
- }
- if (compared > 0) // go to Left
- {
- return treap.Left.GetCeilPosQ(item, comp);
- }
- // (compared == 0)
- return (treap.Right.GetCeilPosQ(item, comp) ?? 0) + treap.RightPos;
- }
- /// <summary>
- /// Least Info that is equivalent to item
- /// </summary>
- private static int? GetFloorP(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
- {
- if (treap == null) return 0;
- var compared = comp.Compare(treap.Info, item);
- if (compared < 0) // go to Right
- {
- return treap.Right.GetFloorP(item, comp) + treap.RightPos;
- }
- if (compared > 0) // go to Left
- {
- return treap.Left.GetFloorP(item, comp);
- }
- // (compared == 0)
- if (treap.Left != null && comp.Compare(treap.Left.Max(), item) == 0)
- return treap.Left.GetFloorP(item, comp);
- return treap.CurrentPos;
- }
-
- public static int GetFloorPos(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
- {
- return treap.GetFloorP(item, comp) ?? 0;
- }
-
- public static ImplicitTreap<Segment> Remove(this ImplicitTreap<Segment> treap, Segment item, SegmentComparer comp)
- {
- var pos = treap.Find(item, comp);
- if (!pos.HasValue) return treap;
- return treap.Remove(pos.Value);
-
- }
- public static ImplicitTreap<Segment> Swap(this ImplicitTreap<Segment> treap, Segment s1, Segment s2, SegmentComparer comp)
- {
- var t1 = treap.FindW(s1, comp);
- var t2 = treap.FindW(s2, comp);
- if (t1 == null) return treap;
- if (t2 == null) return treap;
- var temp1 = new Segment(t1.Info);
- var temp2 = new Segment(t2.Info);
- t2.Info = temp1;
- t2.Info = temp1;
- t1.Info = temp2;
- return treap;
-
- }
-
- public static ImplicitTreap<Segment> CreateOrderedTreapFromRange(Segment[] segments, SegmentComparer comp)
- {
- var t = new ImplicitTreap<Segment>(segments[0]);
- var ans = t;
- foreach (Segment segment in segments.Skip(1))
- {
- var qt = TreapOfSegmentsTester.GetAllI(ans);
- var pos = ans.GetFloorPos(segment, comp);
- ans = ans.Add(pos, segment);
- ans.Recalc();
- qt = TreapOfSegmentsTester.GetAllI(ans);
- }
- ans.Recalc();
- return ans;
- }
-
- #endregion
-
- }
-
- [TestFixture]
- internal class TreapOfSegmentsTester
- {
- public static Segment[] SegsNear = new Segment[]
- {
- new Segment(0,0,6,6),
- new Segment(0,1,6,1),
- new Segment(0,2,6,4),
- new Segment(0,3,6,3),
- new Segment(0,4,6,2),
- new Segment(0,5,6,5),
- new Segment(0,6,6,0),
- };
-
- public static Dictionary<Segment, int> Mapper = SegsNear.ToDictionary(q => q, q => (int)q.Start.Y);
- public SegmentComparer Comparer = new SegmentComparer();
-
- public static object[][] NearsOrder =
- {
- new object[]
- {
- 0.5,
- new []{0,1,2,3,4,5,6},
- new []{0,1,2,3,4,5,6},
- new int?[]{1,2,3,4,5,6,null}
- },
- new object[]
- {
- 2,
- new[]{1,0,2,3,4,6,5},
- new[]{0,1,2,3,4,5,6},
- new int?[]{2,0,3,4,6,null,5}
- },
- new object[]
- {
- 1,
- new[]{1,0,2,3,4,6,5},
- new[]{1,1,2,3,4,6,6},
- new int?[]{2,2,3,4,6,null, null}
- },
- new object[] // awfull and not working // praying for it not to be in algorithm
- {
- 3,
- new[]{1,6,4,3,2,0,5},
- new[]{0,1,0,0,0,5,0},
- new int?[]{5,0,5,5,5,null,5}
- },
- };
-
- [Test]
- [TestCaseSource("NearsOrder")]
- public void NearsTest(double x, int[] finds, int[] floors, int?[] ceils)
- {
- Comparer.X = x;
- var t = TreapOfSegments.CreateOrderedTreapFromRange(SegsNear, Comparer);
- Console.Out.WriteLine(t.ToString(Mapper));
- Console.Out.WriteLine(GetAllI(t));
- for (int i = 0; i < SegsNear.Length; i++)
- {
- var segment = SegsNear[i];
- var foundPos = t.Find(segment, Comparer);
- var floorPos = t.GetFloorPos(segment, Comparer);
- var ceilPos = t.GetCeilPos(segment, Comparer);
- Console.Out.WriteLine(String.Join(" ", foundPos, t[floorPos].Start.Y, ceilPos.HasValue?t[ceilPos.Value].Start.Y:-1));
- Assert.That(foundPos.HasValue);
- Assert.That(foundPos.Value, Is.EqualTo(finds[i]));
- Assert.That(t[floorPos].Start.Y, Is.EqualTo(floors[i]));
- if (ceilPos == null)
- Assert.That(ceils[i] == null);
- else
- Assert.That(t[ceilPos.Value].Start.Y, Is.EqualTo(ceils[i]));
-
- }
- }
-
- [Test]
- public void SwapTest()
- {
- Comparer.X = 0.5;
- var t = TreapOfSegments.CreateOrderedTreapFromRange(SegsNear, Comparer);
- Console.Out.WriteLine(GetAllI(t));
- t.Swap(SegsNear[3], SegsNear[1], Comparer);
- Console.Out.WriteLine(GetAllI(t));
- }
-
- public static string GetAllI(ImplicitTreap<Segment> t)
- {
- return String.Join(" ",t.GetAllInfos().Select(i => i.Start.Y));
- }
- }
- }