I came up with this, this afternoon, and it seems to work fairly well. It will give me an List of annots for the selection:
private List GetAnnotsFromQuads(pdftron.PDF.PDFViewWPF.Selection selection)
{
//http://www.pdftron.com/pdfnet/samplecode/PDFViewControl.xaml.cs.html
//THIS WILL CAPTURE THE WINDOWS SELECTION’S RECTS AND CONVERT THEM TO PDFtron ANNOT OBJECTS
List annotList = new List();
int quadNumber = 0;
int pageNumber = selection.GetPageNum();
double[] quads = selection.GetQuads();
int numQuads = quads.Length / 8;
if (quads.Length >= 8) //must have at least 8 points to be valid
{
Console.WriteLine("GetRectsFromQuads - numQuads: " + numQuads.ToString());
for (int i = 0; i < numQuads; i++)
{
quadNumber = i * 8;
double x1 = quads[quadNumber + 0];
double y1 = quads[quadNumber + 1];
double x2 = quads[quadNumber + 2];
double y2 = quads[quadNumber + 3];
double x3 = quads[quadNumber + 4];
double y3 = quads[quadNumber + 5];
double x4 = quads[quadNumber + 6];
double y4 = quads[quadNumber + 7];
//https://groups.google.com/forum/#!searchin/pdfnet-sdk/rect$20from$20quads/pdfnet-sdk/fP_cynRYurE/r8XczPrGOVEJ
double rectX1 = Math.Min(Math.Min(Math.Min(quads[quadNumber + 0], quads[quadNumber + 2]), quads[quadNumber + 4]), quads[quadNumber + 6]);
double rectX2 = Math.Max(Math.Max(Math.Max(quads[quadNumber + 0], quads[quadNumber + 2]), quads[quadNumber + 4]), quads[quadNumber + 6]);
double rectY1 = Math.Min(Math.Min(Math.Min(quads[quadNumber + 1], quads[quadNumber + 3]), quads[quadNumber + 5]), quads[quadNumber + 7]);
double rectY2 = Math.Max(Math.Max(Math.Max(quads[quadNumber + 1], quads[quadNumber + 3]), quads[quadNumber + 5]), quads[quadNumber + 7]);
Rect selectionRect = new Rect(rectX1, rectY1, rectX2, rectY2);
//Console.WriteLine("GetRectsFromQuads - aRect: " + rectX1.ToString() + " | " + rectY1.ToString() + " | " + rectX2.ToString() + " | " + rectY2.ToString());
ColorPt defaultColour = new ColorPt(250, 246, 5, 0.3);;
Annot highlightAnnot = CreateHighlightAnnot(_pdfDocument, selectionRect, defaultColour);
annotList.Add(highlightAnnot);
//--------------------------------------------------------------------
//DEBUG TEST - REVERSE OF PDFtron BACK TO WINDOWS SELECTION
//(this should highlight the exact same text just selected)
List<System.Windows.Shapes.Rectangle> _onScreenSelection = new List<System.Windows.Shapes.Rectangle>();
System.Windows.Controls.Canvas annotCanvas = _pdfViewer.GetCanvas();
foreach (Annot annot in annotList)
{
Rect aRect = annot.GetRect();
pdftron.SDF.Obj quadPoints = annot.GetSDFObj().PutArray(“QuadPoints”);
quadPoints.PushBackNumber(aRect.x1);
quadPoints.PushBackNumber(aRect.y2);
quadPoints.PushBackNumber(aRect.x2);
quadPoints.PushBackNumber(aRect.y2);
quadPoints.PushBackNumber(aRect.x1);
quadPoints.PushBackNumber(aRect.y1);
quadPoints.PushBackNumber(aRect.x2);
quadPoints.PushBackNumber(aRect.y1);
quadNumber = i * 8;
x1 = quads[quadNumber + 0];
y1 = quads[quadNumber + 1];
x2 = quads[quadNumber + 2];
y2 = quads[quadNumber + 3];
x3 = quads[quadNumber + 4];
y3 = quads[quadNumber + 5];
x4 = quads[quadNumber + 6];
y4 = quads[quadNumber + 7];
_pdfViewer.ConvPagePtToScreenPt(ref x1, ref y1, pageNumber);
_pdfViewer.ConvPagePtToScreenPt(ref x2, ref y2, pageNumber);
_pdfViewer.ConvPagePtToScreenPt(ref x3, ref y3, pageNumber);
_pdfViewer.ConvPagePtToScreenPt(ref x4, ref y4, pageNumber);
double left, right, top, bottom;
left = Math.Min(x1, Math.Min(x2, Math.Min(x3, x4)));
right = Math.Max(x1, Math.Max(x2, Math.Max(x3, x4)));
top = Math.Min(y1, Math.Min(y2, Math.Min(y3, y4)));
bottom = Math.Max(y1, Math.Max(y2, Math.Max(y3, y4)));
System.Windows.Rect windowsRect = new System.Windows.Rect(left, top, right - left, bottom - top);
System.Windows.Shapes.Rectangle highlight = new System.Windows.Shapes.Rectangle();
highlight.Fill = new System.Windows.Media.SolidColorBrush() { Color = System.Windows.Media.Colors.Red };
highlight.Fill.Opacity = 0.3;
highlight.Width = windowsRect.Width;
highlight.Height = windowsRect.Height;
System.Windows.Controls.Canvas.SetLeft(highlight, windowsRect.Left + _pdfViewer.GetHScrollPos());
System.Windows.Controls.Canvas.SetTop(highlight, windowsRect.Top + _pdfViewer.GetVScrollPos());
annotCanvas.Children.Add(highlight);
_onScreenSelection.Add(highlight);
}
//--------------------------------------------------------------------
}
}
Console.WriteLine("GetRectsFromQuads - TOTAL RECTS FOR HIGHLIGHT: " + annotList.Count.ToString());
return annotList;
}
//HELPERS
// Use PDFNet to generate appearance stream for highlight annotation.
public pdftron.SDF.Obj CreateHighlightAppearance(PDFDoc doc, pdftron.PDF.Rect bbox, ColorPt higlight_color)
{
ElementBuilder build = new ElementBuilder();
ElementWriter writer = new ElementWriter();
writer.Begin(doc);
// Draw background
Element element = build.CreateRect(bbox.x1 - 2, bbox.y1, bbox.x2 + 2, bbox.y2);
element.SetPathFill(true);
element.SetPathStroke(false);
GState gs = element.GetGState();
gs.SetFillColorSpace(ColorSpace.CreateDeviceRGB());
gs.SetFillColor(higlight_color);
gs.SetBlendMode(GState.BlendMode.e_bl_multiply);
writer.WriteElement(element);
pdftron.SDF.Obj stm = writer.End();
build.Dispose();
writer.Dispose();
// Set the bounding box
stm.PutRect(“BBox”, bbox.x1, bbox.y1, bbox.x2, bbox.y2);
stm.PutName(“Subtype”, “Form”);
return stm;
}
// Create Highlight Annotation.
public Annot CreateHighlightAnnot(PDFDoc doc, pdftron.PDF.Rect rect, ColorPt highlight_color)
{
Annot a = Annot.Create(doc, Annot.Type.e_Highlight, rect);
a.SetColor(highlight_color);
a.SetAppearance(CreateHighlightAppearance(doc, rect, highlight_color));
pdftron.SDF.Obj quads = a.GetSDFObj().PutArray(“QuadPoints”);
quads.PushBackNumber(rect.x1);
quads.PushBackNumber(rect.y2);
quads.PushBackNumber(rect.x2);
quads.PushBackNumber(rect.y2);
quads.PushBackNumber(rect.x1);
quads.PushBackNumber(rect.y1);
quads.PushBackNumber(rect.x2);
quads.PushBackNumber(rect.y1);
return a;
}
…so that takes care of “You can run through the array of doubles that from the quads, and for every pair, make a Rect, and add that to a new array of Rects. Sorry this isn’t done for you.”
So, in your opinion what would be the most efficient way to look for over-lapping annotations at this point ?
A “bounding box” sounds interesting, but it can’t be a “x1, y1, x2, y2” rectangle because that will potentially include words that weren’t selected (highlighted) by the user, they just happened to exist int he same overall area…
thanks,
Barry