allow oriented bounding box for TextBlock

This commit is contained in:
BobLd
2020-05-23 19:45:51 +01:00
committed by Eliot Jones
parent 5b0b0a6db3
commit 43a68693ba

View File

@@ -64,16 +64,245 @@
TextLines = lines;
Text = string.Join(" ", lines.Select(x => x.Text));
var minX = lines.Min(x => x.BoundingBox.Left);
var minY = lines.Min(x => x.BoundingBox.Bottom);
var maxX = lines.Max(x => x.BoundingBox.Right);
var maxY = lines.Max(x => x.BoundingBox.Top);
BoundingBox = new PdfRectangle(minX, minY, maxX, maxY);
if (lines.Count == 1)
{
BoundingBox = lines[0].BoundingBox;
Text = lines[0].Text;
TextOrientation = lines[0].TextOrientation;
}
else
{
var tempTextOrientation = lines[0].TextOrientation;
if (tempTextOrientation != TextOrientation.Other)
{
foreach (var letter in lines)
{
if (letter.TextOrientation != tempTextOrientation)
{
tempTextOrientation = TextOrientation.Other;
break;
}
}
}
switch (tempTextOrientation)
{
case TextOrientation.Horizontal:
BoundingBox = GetBoundingBoxH(lines);
break;
case TextOrientation.Rotate180:
BoundingBox = GetBoundingBox180(lines);
break;
case TextOrientation.Rotate90:
BoundingBox = GetBoundingBox90(lines);
break;
case TextOrientation.Rotate270:
BoundingBox = GetBoundingBox270(lines);
break;
case TextOrientation.Other:
default:
BoundingBox = GetBoundingBoxOther(lines);
break;
}
Text = string.Join(separator, lines.Select(x => x.Text));
TextOrientation = tempTextOrientation;
}
}
#region Bounding box
private PdfRectangle GetBoundingBoxH(IReadOnlyList<TextLine> lines)
{
var blX = double.MaxValue;
var trX = double.MinValue;
var blY = double.MaxValue;
var trY = double.MinValue;
for (var i = 0; i < lines.Count; i++)
{
var line = lines[i];
if (line.BoundingBox.BottomLeft.X < blX)
{
blX = line.BoundingBox.BottomLeft.X;
}
if (line.BoundingBox.BottomLeft.Y < blY)
{
blY = line.BoundingBox.BottomLeft.Y;
}
var right = line.BoundingBox.BottomLeft.X + line.BoundingBox.Width;
if (right > trX)
{
trX = right;
}
if (line.BoundingBox.TopLeft.Y > trY)
{
trY = line.BoundingBox.TopLeft.Y;
}
}
return new PdfRectangle(blX, blY, trX, trY);
}
private PdfRectangle GetBoundingBox180(IReadOnlyList<TextLine> lines)
{
var blX = double.MinValue;
var blY = double.MinValue;
var trX = double.MaxValue;
var trY = double.MaxValue;
for (var i = 0; i < lines.Count; i++)
{
var line = lines[i];
if (line.BoundingBox.BottomLeft.X > blX)
{
blX = line.BoundingBox.BottomLeft.X;
}
if (line.BoundingBox.BottomLeft.Y > blY)
{
blY = line.BoundingBox.BottomLeft.Y;
}
var right = line.BoundingBox.BottomLeft.X - line.BoundingBox.Width;
if (right < trX)
{
trX = right;
}
if (line.BoundingBox.TopRight.Y < trY)
{
trY = line.BoundingBox.TopRight.Y;
}
}
return new PdfRectangle(blX, blY, trX, trY);
}
private PdfRectangle GetBoundingBox90(IReadOnlyList<TextLine> lines)
{
var b = double.MaxValue;
var r = double.MaxValue;
var t = double.MinValue;
var l = double.MinValue;
for (var i = 0; i < lines.Count; i++)
{
var line = lines[i];
if (line.BoundingBox.BottomLeft.X < b)
{
b = line.BoundingBox.BottomLeft.X;
}
if (line.BoundingBox.BottomRight.Y < r)
{
r = line.BoundingBox.BottomRight.Y;
}
var right = line.BoundingBox.BottomLeft.X + line.BoundingBox.Height;
if (right > t)
{
t = right;
}
if (line.BoundingBox.BottomLeft.Y > l)
{
l = line.BoundingBox.BottomLeft.Y;
}
}
return new PdfRectangle(new PdfPoint(b, l), new PdfPoint(t, l),
new PdfPoint(t, r), new PdfPoint(b, r));
}
private PdfRectangle GetBoundingBox270(IReadOnlyList<TextLine> lines)
{
var t = double.MaxValue;
var b = double.MinValue;
var l = double.MaxValue;
var r = double.MinValue;
for (var i = 0; i < lines.Count; i++)
{
var line = lines[i];
if (line.BoundingBox.BottomLeft.X > b)
{
b = line.BoundingBox.BottomLeft.X;
}
if (line.BoundingBox.BottomLeft.Y < l)
{
l = line.BoundingBox.BottomLeft.Y;
}
var right = line.BoundingBox.BottomLeft.X - line.BoundingBox.Height;
if (right < t)
{
t = right;
}
if (line.BoundingBox.BottomRight.Y > r)
{
r = line.BoundingBox.BottomRight.Y;
}
}
return new PdfRectangle(new PdfPoint(b, l), new PdfPoint(t, l),
new PdfPoint(t, r), new PdfPoint(b, r));
}
private PdfRectangle GetBoundingBoxOther(IReadOnlyList<TextLine> lines)
{
var points = lines.SelectMany(l => new[]
{
l.BoundingBox.BottomLeft,
l.BoundingBox.BottomRight,
l.BoundingBox.TopLeft,
l.BoundingBox.TopRight
});
// Candidates bounding boxes
var obb = Geometry.GeometryExtensions.MinimumAreaRectangle(points);
var obb1 = new PdfRectangle(obb.BottomRight, obb.BottomLeft, obb.TopLeft, obb.TopRight);
var obb2 = new PdfRectangle(obb.TopRight, obb.BottomRight, obb.BottomLeft, obb.TopLeft);
var obb3 = new PdfRectangle(obb.TopLeft, obb.TopRight, obb.BottomRight, obb.BottomLeft);
// Find the orientation of the OBB, using the baseline angle
// Assumes line order is correct
var lastLine = lines[lines.Count - 1];
var baseLineAngle = Distances.BoundAngle180(Distances.Angle(lastLine.BoundingBox.BottomLeft, lastLine.BoundingBox.BottomRight));
double deltaAngle = Math.Abs(Distances.BoundAngle180(obb.Rotation - baseLineAngle));
double deltaAngle1 = Math.Abs(Distances.BoundAngle180(obb1.Rotation - baseLineAngle));
if (deltaAngle1 < deltaAngle)
{
deltaAngle = deltaAngle1;
obb = obb1;
}
double deltaAngle2 = Math.Abs(Distances.BoundAngle180(obb2.Rotation - baseLineAngle));
if (deltaAngle2 < deltaAngle)
{
deltaAngle = deltaAngle2;
obb = obb2;
}
double deltaAngle3 = Math.Abs(Distances.BoundAngle180(obb3.Rotation - baseLineAngle));
if (deltaAngle3 < deltaAngle)
{
obb = obb3;
}
return obb;
}
#endregion
/// <summary>
/// Sets the <see cref="TextBlock"/>'s reading order.