private static int MakeNewEqTree(BundleTree tree, IList <Segment> slist, int sIdx, Segment[] contS, ISpatiallyComparable sweepEvent) { // TODO: Refactor this horrible method! Bundle currB = null; int nc = 0; int ic = 0; while (nc < 2 && contS[nc] != null) { ++nc; } int iss = sIdx; while (sIdx < slist.Count && slist[sIdx].CompareTo(sweepEvent) <= 0) { ++sIdx; } if (ic >= nc && iss >= sIdx) { return(sIdx); } Segment currS = ic < nc && (iss >= sIdx || contS[ic].CompareTo(slist[iss]) <= 0) ? contS[ic++] : slist[iss++]; bool currBIsRed = currS.IsRed ^ true; do { if (currBIsRed == currS.IsRed) { Debug.Assert(currB != null); currB.insertSegAtTop(currS); } else { currBIsRed = currS.IsRed; currB = new Bundle(currBIsRed, null, currB, currS); tree.InsertBAtTop(currB); } currS.useStart = false; if (ic < nc || iss < sIdx) { if (ic < nc && (iss >= sIdx || contS[ic].CompareTo(slist[iss]) <= 0)) { currS = contS[ic++]; } else { currS = slist[iss++]; } } else { return(sIdx); } }while(true); }
public void Merge(BundleTree rhs, bool mergeUp) { if (rhs == null) { return; } if (rhs.IsEmpty) { return; } if (IsEmpty) { bTree = rhs.bTree; top = rhs.top; bottom = rhs.bottom; } else if (mergeUp) { if (top.IsRed) { bTree.Merge(top, rhs.bTree); } else { bTree.Merge(top.PurpleDown, rhs.bTree); } top.PurpleUp = rhs.bottom; rhs.bottom.PurpleDown = top; if (top.IsRed == rhs.bottom.IsRed) { GroupBundles(top, true); } top = rhs.top; } else { if (rhs.top.IsRed) { rhs.bTree.Merge(rhs.top, bTree); } else { rhs.bTree.Merge(rhs.top.PurpleDown, bTree); } bTree = rhs.bTree; rhs.top.PurpleUp = bottom; bottom.PurpleDown = rhs.top; if (rhs.top.IsRed == bottom.IsRed) { GroupBundles(rhs.top, true); } bottom = rhs.bottom; } }
private static void SwapMerge(Bundle lower, Bundle upper, BundleTree rBundleTree) { lower.RemovePurpleL(); RecordIntersections(lower, upper); lower.AddAbovePurpleL(upper); if (lower.IsRed == lower.PurpleUp.IsRed) { rBundleTree.GroupBundles(lower, true); } if (upper.IsRed == upper.PurpleDown.IsRed) { rBundleTree.GroupBundles(upper, false); } }
private static void FindContSegs(BundleTree oldEqTree, Segment[] contSegs, FPoint sweepEvent) { int i = 0; contSegs[0] = null; contSegs[1] = null; for (Bundle bptr = oldEqTree.Top; bptr != null; bptr = bptr.PurpleDown) { for (Segment sptr = bptr.Top; sptr != null; sptr = sptr.Down) { if (sptr.EndsAfter(sweepEvent)) { contSegs[i++] = sptr.BreakSeg(sweepEvent); } } } }
private BundleTree InitSentinels() { BundleTree rBundleTree = new BundleTree(); double lx = (redMinMax[0] >= blueMinMax[0] ? blueMinMax[0] : redMinMax[0]) - 1.0D; double ly = (redMinMax[2] >= blueMinMax[2] ? blueMinMax[2] : redMinMax[2]) - 1.0D; double ux = (redMinMax[1] <= blueMinMax[1] ? blueMinMax[1] : redMinMax[1]) + 1.0D; double uy = (redMinMax[3] <= blueMinMax[3] ? blueMinMax[3] : redMinMax[3]) + 1.0D; Segment[] boundary = { new Segment(new FPoint(lx, ly - 1.0D), new FPoint(ux, ly - 1.0D), true), new Segment(new FPoint(lx, ly), new FPoint(ux, ly), false), new Segment(new FPoint(lx, uy), new FPoint(ux, uy), false), new Segment(new FPoint(lx, uy + 1.0D), new FPoint(ux, uy + 1.0D), true) }; MakeNewEqTree(rBundleTree, boundary, 0, new Segment[1], new FPoint(ux + 1.0D, uy + 1.0D)); return(rBundleTree); }
private static void RecordEndIntersections(BundleTree oldEqTree, BundleTree newEqTree) { int intCount = -1; SingleLL intptr = null; Segment prev = null; for (Bundle bptr = oldEqTree.Top; bptr != null; bptr = bptr.PurpleDown) { for (Segment sptr = bptr.Top; sptr != null; sptr = sptr.Down) { intCount++; if (intptr == null) { intptr = new SingleLL(sptr, null); intptr.next = intptr; } else { intptr.next = new SingleLL(sptr, intptr.next); intptr = intptr.next; } } } for (Bundle bptr = newEqTree.Bottom; bptr != null; bptr = bptr.PurpleUp) { for (Segment sptr = bptr.Bottom; sptr != null; sptr = sptr.Up) { intCount++; if (intptr == null) { intptr = new SingleLL(sptr, null); intptr.next = intptr; } else { intptr.next = new SingleLL(sptr, intptr.next); intptr = intptr.next; } } } if (intCount <= 0) { return; } Debug.Assert(intptr != null); intptr = intptr.next; for (Bundle bptr = oldEqTree.Top; bptr != null; bptr = bptr.PurpleDown) { for (Segment sptr = bptr.Top; sptr != null; sptr = sptr.Down) { sptr.AddEndIntersections(intptr, intCount); if (prev != null && prev.IsSameSeg(sptr)) { prev.AddLIntersection(sptr); sptr.AddLIntersection(prev); } intptr = intptr.next; prev = sptr; } } for (Bundle bptr = newEqTree.Bottom; bptr != null; bptr = bptr.PurpleUp) { for (Segment sptr = bptr.Bottom; sptr != null; sptr = sptr.Up) { sptr.AddStartIntersections(intptr, intCount); intptr = intptr.next; } } }
private void CalcIntersections() { Debug.Assert(mergedSegments != null); Segment[] contSegs = new Segment[2]; ClearIntersections(); IEnumerable <FPoint> eventList = CreateEventList(mergedSegments); BundleTree rBundleTree = InitSentinels(); int imerge = 0; foreach (FPoint sweepEvent in eventList) { Bundle bClose = rBundleTree.FindSmBAbove(sweepEvent); Bundle bRedTeq = bClose.PurpleDown.PurpleDown; if (bRedTeq.PurpleDown != null) { for (bRedTeq = rBundleTree.separateEq(bRedTeq, sweepEvent, true, false); Witnessed(bRedTeq.PurpleDown, bRedTeq, sweepEvent); SwapMerge(bRedTeq.PurpleDown, bRedTeq, rBundleTree)) { } rBundleTree.separateEq(bRedTeq.PurpleDown, sweepEvent, true, true); if (Witnessed(bRedTeq.PurpleDown, bRedTeq, sweepEvent)) { SwapMerge(bRedTeq.PurpleDown, bRedTeq, rBundleTree); } if (bRedTeq.PurpleUp.IsRed) { bClose = bRedTeq.PurpleUp; } if (bClose.PurpleUp != null) { for (; Witnessed(bClose, bClose.PurpleUp, sweepEvent); SwapMerge(bClose, bClose.PurpleUp, rBundleTree)) { } rBundleTree.separateEq(bClose.PurpleUp, sweepEvent, true, false); if (Witnessed(bClose, bClose.PurpleUp, sweepEvent)) { SwapMerge(bClose, bClose.PurpleUp, rBundleTree); } } if (bRedTeq.PurpleUp.IsRed) { rBundleTree.GroupBundles(bRedTeq, true); } for (bRedTeq = rBundleTree.separateEq(bRedTeq, sweepEvent, false, false); Witnessed(bRedTeq.PurpleDown, bRedTeq, sweepEvent); SwapMerge(bRedTeq.PurpleDown, bRedTeq, rBundleTree)) { } rBundleTree.separateEq(bRedTeq.PurpleDown, sweepEvent, false, true); if (Witnessed(bRedTeq.PurpleDown, bRedTeq, sweepEvent)) { SwapMerge(bRedTeq.PurpleDown, bRedTeq, rBundleTree); } if (bRedTeq.PurpleUp.IsRed) { rBundleTree.GroupBundles(bRedTeq, true); } } bClose = rBundleTree.FindLgBBelow(sweepEvent); Bundle bRedBeq = bClose.PurpleUp.PurpleUp; if (bRedBeq.PurpleUp != null) { for (bRedBeq = rBundleTree.separateEq(bRedBeq, sweepEvent, false, true); Witnessed(bRedBeq, bRedBeq.PurpleUp, sweepEvent); SwapMerge(bRedBeq, bRedBeq.PurpleUp, rBundleTree)) { } rBundleTree.separateEq(bRedBeq.PurpleUp, sweepEvent, false, false); if (Witnessed(bRedBeq, bRedBeq.PurpleUp, sweepEvent)) { SwapMerge(bRedBeq, bRedBeq.PurpleUp, rBundleTree); } if (bRedBeq.PurpleDown.IsRed) { bClose = bRedBeq.PurpleDown; } if (bClose.PurpleDown != null) { for (; Witnessed(bClose.PurpleDown, bClose, sweepEvent); SwapMerge(bClose.PurpleDown, bClose, rBundleTree)) { } rBundleTree.separateEq(bClose.PurpleDown, sweepEvent, false, true); if (Witnessed(bClose.PurpleDown, bClose, sweepEvent)) { SwapMerge(bClose.PurpleDown, bClose, rBundleTree); } } if (bRedBeq.PurpleDown.IsRed) { rBundleTree.GroupBundles(bRedBeq, false); } for (bRedBeq = rBundleTree.separateEq(bRedBeq, sweepEvent, true, true); Witnessed(bRedBeq, bRedBeq.PurpleUp, sweepEvent); SwapMerge(bRedBeq, bRedBeq.PurpleUp, rBundleTree)) { } rBundleTree.separateEq(bRedBeq.PurpleUp, sweepEvent, true, false); if (Witnessed(bRedBeq, bRedBeq.PurpleUp, sweepEvent)) { SwapMerge(bRedBeq, bRedBeq.PurpleUp, rBundleTree); } if (bRedBeq.PurpleDown.IsRed) { rBundleTree.GroupBundles(bRedBeq, false); } } BundleTree plusTree = rBundleTree.Split(sweepEvent, true); BundleTree minusTree = rBundleTree; BundleTree oldEqTree = minusTree.Split(sweepEvent, false); FindContSegs(oldEqTree, contSegs, sweepEvent); rBundleTree = new BundleTree(); imerge = MakeNewEqTree(rBundleTree, mergedSegments, imerge, contSegs, sweepEvent); RecordEndIntersections(oldEqTree, rBundleTree); rBundleTree.Merge(plusTree, true); rBundleTree.Merge(minusTree, false); } }
public BundleTree Split(ISpatiallyComparable splitPos, bool keep) { BundleTree upperPart = null; Segment splitSeg; Bundle splitB; if (keep) { splitB = FindSmBAbove(splitPos); if (splitB.PurpleDown != null && splitB.PurpleDown.CompareTo(splitPos) > 0) { splitB = splitB.PurpleDown; } if (splitB.PurpleDown != null) { splitB = splitB.PurpleDown; bool found = splitB.TryFindSmallestSegmentAbove(splitPos, out splitSeg); Debug.Assert(found == (splitSeg != null)); } else { upperPart = new BundleTree(bTree, top, bottom); bTree = null; top = bottom = null; return(upperPart); } } else { splitB = FindLgBBelow(splitPos); if (splitB.PurpleUp != null && splitB.PurpleUp.CompareTo(splitPos) < 0) { splitB = splitB.PurpleUp; } if (splitB.PurpleUp != null) { bool found = splitB.PurpleUp.TryFindLargestSegmentBelow(splitPos, out splitSeg); if (found) { splitB = splitB.PurpleUp; } } else { return(new BundleTree()); } } if (splitSeg != null) { splitB.Split(splitSeg, keep ^ true); PlainInsert(splitB.PurpleUp); } SplayTree <ISpatiallyComparable> s = splitB.IsRed ? bTree.SplitAt(splitB, true) : bTree.SplitAt(splitB.PurpleDown, true); upperPart = new BundleTree(s, top, splitB.PurpleUp); top = splitB; top.PurpleUp = upperPart.bottom.PurpleDown = null; return(upperPart); }