public Dictionary<float, HLine> Split(List<float> Xs) { #region conditions // Xs can be empty, in which case this function returns the original line in the dict. foreach(float x in Xs) { Debug.Assert(x > Left && x < Right); } if(Xs.Count > 1) { for(int i = 1; i < Xs.Count; ++i) { Debug.Assert(Xs[i - 1] < Xs[i]); } } #endregion conditions; Dictionary<float, HLine> lines = new Dictionary<float, HLine>(); List<float> allXs = new List<float>(); allXs.Add(Left); allXs.AddRange(Xs); allXs.Add(Right); for(int i = 1; i < allXs.Count; ++i) { HLine line = new HLine(allXs[i - 1], allXs[i], Y); lines.Add(line.Left, line); } return lines; }
/// <summary> /// Creates a TopEdge by inverting the bottomEdge /// </summary> public TopEdge(BottomEdge bottomEdge) : base() { foreach (HLine line in bottomEdge.Lines) { HLine fLine = new HLine(line.Left, line.Right, -line.Y); Lines.Add(fLine); } }
public Dictionary<float, HLine> Split(float x) { Debug.Assert(Left < x && Right > x); Dictionary<float, HLine> linesDict = new Dictionary<float, HLine>(); HLine line1 = new HLine(Left, x, Y); HLine line2 = new HLine(x, Right, Y); linesDict.Add(line1.Left, line1); linesDict.Add(line2.Left, line2); return linesDict; }
public Dictionary <double, HLine> Split(double x) { M.Assert(Left <x && Right> x); Dictionary <double, HLine> linesDict = new Dictionary <double, HLine>(); HLine line1 = new HLine(Left, x, Y); HLine line2 = new HLine(x, Right, Y); linesDict.Add(line1.Left, line1); linesDict.Add(line2.Left, line2); return(linesDict); }
public Dictionary <float, HLine> Split(float x) { Debug.Assert(Left <x && Right> x); Dictionary <float, HLine> linesDict = new Dictionary <float, HLine>(); HLine line1 = new HLine(Left, x, Y); HLine line2 = new HLine(x, Right, Y); linesDict.Add(line1.Left, line1); linesDict.Add(line2.Left, line2); return(linesDict); }
/// <summary> /// The HLines from this edge, with the HLines at the beginning and end of the newLine split into two. /// The dictionary's key is the left edge of each HLine. /// </summary> private Dictionary <double, HLine> SplitEdge(HLine newLine, double leftY, double rightY) { M.Assert(Lines.Count > 0); Dictionary <double, HLine> splitEdge = new Dictionary <double, HLine>(); foreach (HLine hline in Lines) { if (hline.Left < newLine.Left && hline.Right > newLine.Left && leftY > newLine.Y) { Dictionary <double, HLine> splitLines1 = hline.Split(newLine.Left); Dictionary <double, HLine> splitLines2 = new Dictionary <double, HLine>(); foreach (double x in splitLines1.Keys) { HLine line = splitLines1[x]; if (line.Left < newLine.Right && line.Right > newLine.Right && line.Y > newLine.Y) { splitLines2 = line.Split(newLine.Right); } } foreach (double x in splitLines1.Keys) { if (!splitLines2.ContainsKey(x)) { splitEdge.Add(splitLines1[x].Left, splitLines1[x]); } } foreach (double x in splitLines2.Keys) { splitEdge.Add(splitLines2[x].Left, splitLines2[x]); } } else if (hline.Left < newLine.Right && hline.Right > newLine.Right && rightY > newLine.Y) { Dictionary <double, HLine> splitLines = hline.Split(newLine.Right); foreach (double x in splitLines.Keys) { splitEdge.Add(splitLines[x].Left, splitLines[x]); } } else { splitEdge.Add(hline.Left, hline); } } return(splitEdge); }
public void AddLineToUpperEdge(HLine newLine) { M.Assert(newLine.Y != double.MaxValue); if (Lines.Count == 0) { Lines.Add(newLine); } else { double leftY = this.YatX(newLine.Left); double rightY = this.YatX(newLine.Right); Dictionary <double, HLine> splitEdge = SplitEdge(newLine, leftY, rightY); List <double> splitXsOnNewLine = SplitXsOnNewLine(newLine); Dictionary <double, HLine> splitNewLine = newLine.Split(splitXsOnNewLine); // if List <HLine> newLines = new List <HLine>(); double currentX = splitEdge[0].Left; foreach (double x in splitEdge.Keys) { if (splitNewLine.ContainsKey(x)) { if (newLine.Y < splitEdge[x].Y) { newLines.Add(splitNewLine[x]); currentX = splitNewLine[x].Right; } else { newLines.Add(splitEdge[x]); currentX = splitEdge[x].Right; } } else if (splitEdge[x].Left == currentX) { newLines.Add(splitEdge[x]); currentX = splitEdge[x].Right; } } for (int i = 1; i < newLines.Count; ++i) { M.Assert(newLines[i - 1].Right == newLines[i].Left); } Lines = null; Lines = newLines; } }
/// <summary> /// If the hLine lies below any line in this bottom edge, /// then this bottom edge is adjusted accordingly. /// </summary> public override void Add(HLine hLine) { if (Lines.Count == 0) { Lines.Add(hLine); } else { TopEdge flippedEdge = FlipVertically(); HLine flippedLine = new HLine(hLine.Left, hLine.Right, -hLine.Y); flippedEdge.AddLineToUpperEdge(flippedLine); Lines = flippedEdge.FlippedLines; } }
/// <summary> /// The x-coordinates on the newLine which intersect the verticals between the top Lines /// (The edge considered as a continuous, joined up line). /// This does NOT include the end points of the newLine. /// </summary> private List <double> SplitXsOnNewLine(HLine newLine) { List <double> splitXs = new List <double>(); for (int i = 1; i < Lines.Count; ++i) { HLine leftEdgeLine = Lines[i - 1]; HLine rightEdgeLine = Lines[i]; M.Assert(leftEdgeLine.Right == rightEdgeLine.Left); if (leftEdgeLine.Right > newLine.Left && leftEdgeLine.Right < newLine.Right) { if ((leftEdgeLine.Y >= newLine.Y && rightEdgeLine.Y <= newLine.Y) || (leftEdgeLine.Y <= newLine.Y && rightEdgeLine.Y >= newLine.Y)) { splitXs.Add(leftEdgeLine.Right); } } } return(splitXs); }
/// <summary> /// returns the y-coordinate of this BottomEdge at X. /// If X greater than or equal to the leftX of an HLine, and less than the rightX of the same HLine, /// then the returned value is HLine.Y. /// Else If X is equal to the rightX of an Hline and there is another Hline to the right, /// { /// if isTopEdge is true, then the returned value is the higher (=smaller) of the two Ys, /// else the returned value is the lower (=greater) of the two Ys /// } /// </summary> protected double YatX(double X, bool isTopEdge) { double y = double.MaxValue; for (int i = 0; i < this.Lines.Count; ++i) { HLine hLine = this.Lines[i]; if (hLine.Left <= X && hLine.Right > X) { y = hLine.Y; break; } else if (hLine.Right == X) { if (i < this.Lines.Count - 1) { HLine nextHLine = this.Lines[i + 1]; if (isTopEdge) { y = nextHLine.Y < hLine.Y ? nextHLine.Y : hLine.Y; } else { y = nextHLine.Y > hLine.Y ? nextHLine.Y : hLine.Y; } break; } else { y = hLine.Y; break; } } } M.Assert(y != double.MaxValue); return(y); }
/// <summary> /// returns the y-coordinate of this BottomEdge at X. /// If X greater than or equal to the leftX of an HLine, and less than the rightX of the same HLine, /// then the returned value is HLine.Y. /// Else If X is equal to the rightX of an Hline and there is another Hline to the right, /// { /// if isTopEdge is true, then the returned value is the higher (=smaller) of the two Ys, /// else the returned value is the lower (=greater) of the two Ys /// } /// </summary> protected float YatX(float X, bool isTopEdge) { float y = float.MaxValue; for (int i = 0; i < this.Lines.Count; ++i) { HLine hLine = this.Lines[i]; if (hLine.Left <= X && hLine.Right > X) { y = hLine.Y; break; } else if (hLine.Right == X) { if (i < this.Lines.Count - 1) { HLine nextHLine = this.Lines[i + 1]; if (isTopEdge) { y = nextHLine.Y < hLine.Y ? nextHLine.Y : hLine.Y; } else { y = nextHLine.Y > hLine.Y ? nextHLine.Y : hLine.Y; } break; } else { y = hLine.Y; break; } } } Debug.Assert(y != float.MaxValue); return(y); }
/// <summary> /// If the bottom edge of the metrics object lies below any line in this bottom edge, /// then this bottom edge is adjusted accordingly. /// </summary> public override void Add(Metrics metrics) { HLine line = new HLine(metrics.Left, metrics.Right, metrics.Bottom); Add(line); }
/// <summary> /// Adds the hLine to the edge line. /// </summary> /// <param name="hLine"></param> public abstract void Add(HLine hLine);
/// <summary> /// Creates a TopEdge by inverting the bottomEdge /// </summary> public TopEdge(BottomEdge bottomEdge) : base() { foreach(HLine line in bottomEdge.Lines) { HLine fLine = new HLine(line.Left, line.Right, -line.Y); Lines.Add(fLine); } }
/// <summary> /// If the top edge of the metrics object lies above any line in this top edge, /// then this top edge is adjusted accordingly. /// </summary> public override void Add(Metrics metrics) { HLine hLine = new HLine(metrics.Left, metrics.Right, metrics.Top); AddLineToUpperEdge(hLine); }
/// <summary> /// If the line lies above any line in this top edge, /// then this top edge is adjusted accordingly. /// </summary> public override void Add(HLine hLine) { AddLineToUpperEdge(hLine); }
public void AddLineToUpperEdge(HLine newLine) { Debug.Assert(newLine.Y != float.MaxValue); if(Lines.Count == 0) { Lines.Add(newLine); } else { float leftY = this.YatX(newLine.Left); float rightY = this.YatX(newLine.Right); Dictionary<float, HLine> splitEdge = SplitEdge(newLine, leftY, rightY); List<float> splitXsOnNewLine = SplitXsOnNewLine(newLine); Dictionary<float, HLine> splitNewLine = newLine.Split(splitXsOnNewLine); // if List<HLine> newLines = new List<HLine>(); float currentX = splitEdge[0].Left; foreach(float x in splitEdge.Keys) { if(splitNewLine.ContainsKey(x)) { if(newLine.Y < splitEdge[x].Y) { newLines.Add(splitNewLine[x]); currentX = splitNewLine[x].Right; } else { newLines.Add(splitEdge[x]); currentX = splitEdge[x].Right; } } else if(splitEdge[x].Left == currentX) { newLines.Add(splitEdge[x]); currentX = splitEdge[x].Right; } } for(int i = 1; i < newLines.Count; ++i) { Debug.Assert(newLines[i - 1].Right == newLines[i].Left); } Lines = null; Lines = newLines; } }
/// <summary> /// If the hLine lies below any line in this bottom edge, /// then this bottom edge is adjusted accordingly. /// </summary> public override void Add(HLine hLine) { if(Lines.Count == 0) { Lines.Add(hLine); } else { TopEdge flippedEdge = FlipVertically(); HLine flippedLine = new HLine(hLine.Left, hLine.Right, -hLine.Y); flippedEdge.AddLineToUpperEdge(flippedLine); Lines = flippedEdge.FlippedLines; } }
/// <summary> /// The HLines from this edge, with the HLines at the beginning and end of the newLine split into two. /// The dictionary's key is the left edge of each HLine. /// </summary> private Dictionary<float, HLine> SplitEdge(HLine newLine, float leftY, float rightY) { Debug.Assert(Lines.Count > 0); Dictionary<float, HLine> splitEdge = new Dictionary<float, HLine>(); foreach(HLine hline in Lines) { if(hline.Left < newLine.Left && hline.Right > newLine.Left && leftY > newLine.Y) { Dictionary<float, HLine> splitLines1 = hline.Split(newLine.Left); Dictionary<float, HLine> splitLines2 = new Dictionary<float, HLine>(); foreach(float x in splitLines1.Keys) { HLine line = splitLines1[x]; if(line.Left < newLine.Right && line.Right > newLine.Right && line.Y > newLine.Y) { splitLines2 = line.Split(newLine.Right); } } foreach(float x in splitLines1.Keys) { if(!splitLines2.ContainsKey(x)) splitEdge.Add(splitLines1[x].Left, splitLines1[x]); } foreach(float x in splitLines2.Keys) { splitEdge.Add(splitLines2[x].Left, splitLines2[x]); } } else if(hline.Left < newLine.Right && hline.Right > newLine.Right && rightY > newLine.Y) { Dictionary<float, HLine> splitLines = hline.Split(newLine.Right); foreach(float x in splitLines.Keys) { splitEdge.Add(splitLines[x].Left, splitLines[x]); } } else { splitEdge.Add(hline.Left, hline); } } return splitEdge; }
/// <summary> /// The x-coordinates on the newLine which intersect the verticals between the top Lines /// (The edge considered as a continuous, joined up line). /// This does NOT include the end points of the newLine. /// </summary> private List<float> SplitXsOnNewLine(HLine newLine) { List<float> splitXs = new List<float>(); for(int i = 1; i < Lines.Count; ++i) { HLine leftEdgeLine = Lines[i - 1]; HLine rightEdgeLine = Lines[i]; Debug.Assert(leftEdgeLine.Right == rightEdgeLine.Left); if(leftEdgeLine.Right > newLine.Left && leftEdgeLine.Right < newLine.Right) { if((leftEdgeLine.Y >= newLine.Y && rightEdgeLine.Y <= newLine.Y) || (leftEdgeLine.Y <= newLine.Y && rightEdgeLine.Y >= newLine.Y)) { splitXs.Add(leftEdgeLine.Right); } } } return splitXs; }