Using PDFNetJS, how can I find what geometrical endpoints are near a given mouse click?

110 views
Skip to first unread message

Aaron

unread,
Dec 2, 2015, 1:18:52 PM12/2/15
to PDFTron WebViewer
Q:

I'm creating a measurement tool with PDFNetJS.  I'd like to take a mouse click and find the geometrical "endpoints" close to that mouse click --- such as the endpoints of a line.  How can I do so with PDFNetJS?

A:

The following code sample shows how to find the distance between points in a path and the location where the user clicked.  From there you can prune out points below some threshold, or find the N closest endpoints:


(function() {
/* tslint:disable */
    $
(document).on('documentLoaded', function() {
       
var docCore = readerControl.docViewer.getDocument();
       
PDFNet.initialize().then(function(){

           
// Handling mouse clicks
            readerControl
.docViewer.el.mousedown(function(evt){
               
// running custom PDFNetJS script
                docCore
.getPDFDoc().then(function(pdfDoc){
                    runCustomScript
(pdfDoc, evt);
               
});
           
});
       
});
   
});

   
function* MatrixMult(mtrx, x, y){
        x_res
= x*mtrx.m_a + y*mtrx.m_c + mtrx.m_h;
        y_res
= x*mtrx.m_b + y*mtrx.m_d + mtrx.m_v;
       
return {"x":x_res,"y":y_res};
   
}

   
function distance(pagePoint1, pagePoint2) {
       
var x_dist = pagePoint1.x - pagePoint2.x;
       
var y_dist = pagePoint1.y - pagePoint2.y;
       
return Math.sqrt(x_dist * x_dist + y_dist * y_dist);
   
}

   
function* ProcessElements(reader, page, mouse_pdfCoord) {
       
// page_rot_mtx = page default matrix
       
var page_rot_mtx = yield page.getDefaultMatrix();
       
for (var element = yield reader.next(); element !== null; element = yield reader.next()) // Read page contents
       
{  
           
// ctm = current transformation matrix
           
var ctm = yield element.getCTM();
           
// Concatenated matrix
            page_rot_mtx
.concat(ctm.m_a, ctm.m_b, ctm.m_c, ctm.m_d, ctm.m_h, ctm.m_v);
           
var elemType = yield element.getType();
           
switch (elemType)
           
{
               
case PDFNet.Element.Type.e_path: // Process path data...
                   
{
                       
// Here we extract our path information
                       
var pathinfo = yield element.getPathData();
                       
var opr = new Uint8Array(pathinfo.operators);
                       
var point = new Float64Array(pathinfo.points);
                       
// Process each path
                       
var point_index = 0;
                       
for (var opr_index = 0; opr_index < opr.length; ++opr_index)
                       
{
                           
switch (opr[opr_index])
                           
{
                           
case PDFNet.Element.PathSegmentType.e_moveto:
                               
// code to handle move segments
                               
var x1 = point[point_index]; ++point_index;
                               
var y1 = point[point_index]; ++point_index;
                               
var pagePoint = yield * MatrixMult(page_rot_mtx, x1, y1);
                                console
.log("MoveTo Segment Page Point: (" + pagePoint.x + ", " + pagePoint.y + ")");
                                console
.log("  Distance from mouse click: " + distance(mouse_pdfCoord, pagePoint));
                               
break;
                           
case PDFNet.Element.PathSegmentType.e_lineto:
                               
// code to handle line segments
                               
var x1 = point[point_index]; ++point_index;
                               
var y1 = point[point_index]; ++point_index;
                               
var pagePoint = yield * MatrixMult(page_rot_mtx, x1, y1);
                                console
.log("Line Segment Page Point: (" + pagePoint.x + ", " + pagePoint.y + ")");
                                console
.log("  Distance from mouse click: " + distance(mouse_pdfCoord, pagePoint));
                               
break;
                           
case PDFNet.Element.PathSegmentType.e_cubicto:
                               
// code to handle cubic segments
                                x3
= point[point_index]; ++point_index;
                                y3
= point[point_index]; ++point_index;
                               
var pagePoint = yield * MatrixMult(page_rot_mtx, x3, y3);
                                console
.log("Cubic Segment Page Point: (" + pagePoint.x + ", " + pagePoint.y + ")");
                                console
.log("  Distance from mouse click: " + distance(mouse_pdfCoord, pagePoint));
                               
break;
                           
case PDFNet.Element.PathSegmentType.e_rect:
                               
// code to handle rect segments
                                x1
= point[point_index]; ++point_index;
                                y1
= point[point_index]; ++point_index;
                               
var w = point[point_index]; ++point_index;
                               
var h = point[point_index]; ++point_index;
                                x2
= x1 + w;
                                y2
= y1;
                                x3
= x2;
                                y3
= y1 + h;
                               
var x4 = x1;
                               
var y4 = y3;
                               
var pagePoint1 = yield * MatrixMult(page_rot_mtx, x1, y1);
                               
var pagePoint2 = yield * MatrixMult(page_rot_mtx, x2, y2);
                               
var pagePoint3 = yield * MatrixMult(page_rot_mtx, x3, y3);
                               
var pagePoint4 = yield * MatrixMult(page_rot_mtx, x4, y4);
                                console
.log("Rect Segment Page Points: ("+pagePoint1.x+", "+pagePoint1.y+")" + " ("+pagePoint2.x+", "+pagePoint2.y+")" + " ("+pagePoint3.x+", "+pagePoint3.y+")" + " ("+pagePoint4.x+", "+pagePoint4.y+")");
                                console
.log("  Distance from mouse click: " + distance(mouse_pdfCoord, pagePoint1));
                                console
.log("  Distance from mouse click: " + distance(mouse_pdfCoord, pagePoint2));
                                console
.log("  Distance from mouse click: " + distance(mouse_pdfCoord, pagePoint3));
                                console
.log("  Distance from mouse click: " + distance(mouse_pdfCoord, pagePoint4));
                               
break;
                           
case PDFNet.Element.PathSegmentType.e_closepath:
                               
//console.log(" Close Path");
                               
break;
                           
default:
                               
break;
                           
}
                       
}
                   
}
                   
break;
               
case PDFNet.Element.Type.e_form: // Process form XObjects
                   
{
                        reader
.formBegin();
                       
yield * ProcessElements(reader, page);
                        reader
.end();
                   
}
                   
break;
               
default:                
           
}
       
}
   
}

   
var runCustomScript = function(pdfDoc, evt)
   
{
       
function continueIteration(asyncVal) {
           
var result = iterator.next(asyncVal)
           
if (!result.done) {
               
var promise = result.value;
                promise
.then(continueIteration);
           
}
       
}

       
function* main()
       
{
           
var ret = 0;
           
try
           
{
               
var islocked = false;
               
var doc = pdfDoc;
               
yield PDFNet.beginOperation();
                doc
.lock();
                islocked
= true;
                doc
.initSecurityHandler();
               
// Add in custom script info here
                console
.log("MouseClick X: " + evt.pageX + ", " + "MouseClick Y: " + evt.pageY);

               
// convert from screen coordinates to PDF page coordinates
               
var documentViewer = readerControl.docViewer;
               
var docCore = documentViewer.getDocument();
               
var displayModeManager = documentViewer.getDisplayModeManager();
               
var displayMode = displayModeManager.getDisplayMode();
               
// Get scrolling offsets
               
var scrollContainer = $("#DocumentViewer");
               
var viewportTop = scrollContainer.scrollTop();
               
var viewportLeft = scrollContainer.scrollLeft();
                console
.log("ScrollingTop offset: " + viewportTop, "ScrollingLeft offset: " + viewportLeft);

               
// windowCoord = mouseclick object with scrolling offsets
               
var windowCoord = {x:(evt.pageX + viewportLeft), y:(evt.pageY + viewportTop)};
               
var viewerPageCoord = displayMode.windowToPage(windowCoord, pageIndex);
                console
.log("ViewerCoord X: " + viewerPageCoord.x + ", " + "ViewerCoord Y: " + viewerPageCoord.y);
               
var pdfCoord = docCore.getPDFCoordinates(pageIndex, viewerPageCoord.x, viewerPageCoord.y);
                console
.log("PDFCoord X: " + pdfCoord.x + ", " + "PDFCoord Y: " + pdfCoord.y);

               
var page_reader = yield PDFNet.ElementReader.create();
               
var pageNum = 1;
               
var itr = yield doc.getPageIterator(pageNum);
               
// output the page coordinates of every LineTo segment on every page
               
for (itr; yield itr.hasNext(); itr.next())
               
{
                   
var curritr = yield itr.current();
                   
var currPage = yield doc.getPage(pageNum);
                    page_reader
.beginOnPage(curritr);
                   
yield * ProcessElements(page_reader, currPage, pdfCoord);
                    page_reader
.end();
                    pageNum
++;
               
}
                console
.log("Finished outputting all path segments");
           
}
           
catch(err)
           
{
                console
.log(err.stack)
                ret
= 1;
           
}
           
finally
           
{
               
if (islocked){
                    doc
.unlock();
               
}
           
}
       
}

       
// start the generator
       
var iterator = main();
        iterator
.next().value.then(continueIteration);
   
}


})();
//# sourceURL=config.js



Reply all
Reply to author
Forward
0 new messages