public static LayoutElement NewRow(IEnumerable<LayoutElement> nodes, LayoutElementType type = LayoutElementType.Row) { RectangleF dummyBounds = new RectangleF(0,0,1,1); var e = new LayoutElement(type, dummyBounds, null, nodes); // set bounds if (!nodes.IsEmpty()) { e.Text = nodes.Select(x => x.Text).Where(x => !String.IsNullOrEmpty(x)).ElementsToStringS(delim: " "); e.SetBoundsFromNodes(false); } return e; }
void DetectRowBounds(PageLayout cbi, Blob[] blobs) { if (blobs.Length == 0) { return; } if (cbi.Bounds == Rectangle.Empty) { return; } List<LayoutElement> rows = new List<LayoutElement>(); LayoutElement currentRow = null; // Attempt drawing lines between the rows. for (int y = cbi.Bounds.Top; y < cbi.Bounds.Bottom; y++) { Rectangle rowRect = new Rectangle(cbi.Bounds.Left, y, cbi.Bounds.Width, 1); var blobsInRow = blobs.Where(b => b.Rectangle.IntersectsWith(rowRect)); if (blobsInRow.FirstOrDefault() == null) { // Empty row detected. Commit current row (if any) TryAddRow(rows, currentRow); currentRow = null; } else { // Start new row if needed if (currentRow == null) { currentRow = new LayoutElement(); currentRow.Type = LayoutElementType.Row; } currentRow.Children.AddRange(blobsInRow.Select(x => LayoutElement.NewWord(cbi.PageSize, x.Rectangle))); // Advance to test the next empty space // TODO: beware of off-by-1 //y = currentRow.Bounds.Bottom - 1; } } // Add row at the end TryAddRow(rows, currentRow); FindAndRemoveHeaderAndFooter(cbi, rows); cbi.Children = rows; cbi.SetBoundsFromNodes(true); }
void TryAddRow(List<LayoutElement> rows, LayoutElement currentRow) { if (currentRow == null) { return; } currentRow.Children = currentRow.Children.Distinct().ToList(); currentRow.SetBoundsFromNodes(false); rows.Add(currentRow); }
public static LayoutElement NewWord(Size pageSize, Rectangle bounds, String text = null) { RectangleF unitBounds = GetUnitBounds(pageSize, bounds); var e = new LayoutElement(LayoutElementType.Word, unitBounds, text); return e; }
bool StartsNewColumn(LayoutElement a, LayoutElement b) { return b.UnitBounds.Bottom <= a.UnitBounds.Top && b.UnitBounds.Left > a.UnitBounds.Right; }
bool StartsNewRow(LayoutElement prev, LayoutElement cur) { // Normal case: next row // QQ: do rows ever overlap? if (prev.UnitBounds.Bottom <= cur.UnitBounds.Top) { return true; } // Special case: next column if (prev.UnitBounds.Top >= cur.UnitBounds.Bottom) { return true; } return false; }